Add TypedArray C API (#2165)
New API functions added: - jerry_value_is_typedarray - jerry_create_typedarray - jerry_create_typedarray_for_arraybuffer_sz - jerry_create_typedarray_for_arraybuffer - jerry_get_typedarray_type - jerry_get_typedarray_length - jerry_get_typedarray_buffer JerryScript-DCO-1.0-Signed-off-by: Peter Gal pgal.u-szeged@partner.samsung.com
This commit is contained in:
@@ -296,6 +296,26 @@ typedef jerry_value_t (*jerry_vm_exec_stop_callback_t) (void *user_p);
|
||||
- [jerry_set_vm_exec_stop_callback](#jerry_set_vm_exec_stop_callback)
|
||||
|
||||
|
||||
## jerry_typedarray_type_t
|
||||
|
||||
Enum which describes the TypedArray types.
|
||||
Possible values:
|
||||
|
||||
- JERRY_TYPEDARRAY_UINT8 - represents the Uint8Array TypedArray
|
||||
- JERRY_TYPEDARRAY_UINT8CLAMPED - represents the Uint8ClampedArray TypedArray
|
||||
- JERRY_TYPEDARRAY_INT8 - represents the Int8Array TypedArray
|
||||
- JERRY_TYPEDARRAY_UINT16 - represents the Uint16Array TypedArray
|
||||
- JERRY_TYPEDARRAY_INT16 - represents the Int16Array TypedArray
|
||||
- JERRY_TYPEDARRAY_UINT32 - represents the Uint32Array TypedArray
|
||||
- JERRY_TYPEDARRAY_INT32 - represents the Int32Array TypedArray
|
||||
- JERRY_TYPEDARRAY_FLOAT32 - represents the Float32Array TypedArray
|
||||
- JERRY_TYPEDARRAY_FLOAT64 - represents the Float64Array TypedArray
|
||||
- JERRY_TYPEDARRAY_INVALID - represents an invalid TypedArray
|
||||
|
||||
API functions can return the `JERRY_TYPEDARRAY_INVALID` value if the
|
||||
TypedArray support is not in the engine.
|
||||
|
||||
|
||||
# General engine functions
|
||||
|
||||
## jerry_init
|
||||
@@ -1347,6 +1367,45 @@ jerry_value_is_string (const jerry_value_t value)
|
||||
- [jerry_release_value](#jerry_release_value)
|
||||
|
||||
|
||||
## jerry_value_is_typedarray
|
||||
|
||||
**Summary**
|
||||
|
||||
Checks whether the given `jerry_value_t` is a TypedArray object or not.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
bool
|
||||
jerry_value_is_typedarray (const jerry_value_t value)
|
||||
```
|
||||
|
||||
- `value` - object to check
|
||||
- return value
|
||||
- true, if the given `jerry_value_t` is a TypedArray object.
|
||||
- false, otherwise
|
||||
|
||||
**Example**
|
||||
|
||||
```c
|
||||
{
|
||||
jerry_value_t value;
|
||||
... // create or acquire value
|
||||
|
||||
if (jerry_value_is_typedarray (value))
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
jerry_release_value (value);
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_create_typedarray](#jerry_create_typedarray)
|
||||
|
||||
|
||||
## jerry_value_is_undefined
|
||||
|
||||
**Summary**
|
||||
@@ -3129,6 +3188,151 @@ jerry_create_string_sz (const jerry_char_t *str_p,
|
||||
- [jerry_create_string_from_utf8](#jerry_create_string_from_utf8)
|
||||
|
||||
|
||||
## jerry_create_typedarray
|
||||
|
||||
**Summary**
|
||||
|
||||
Create a jerry_value_t representing an TypedArray object.
|
||||
|
||||
For the new object the type of the TypedArray (see: [jerry_typedarray_type_t](#jerry_typedarray_type_t))
|
||||
and element count can be specified.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerry_value_t
|
||||
jerry_create_typedarray (jerry_typedarray_type_t type_name, jerry_length_t item_count);
|
||||
```
|
||||
|
||||
- `type_name` - type of TypedArray to create
|
||||
- `item_count` - number of items in the new TypedArray
|
||||
- return value - the new TypedArray as a `jerry_value_t`
|
||||
|
||||
**Example**
|
||||
|
||||
```c
|
||||
{
|
||||
jerry_value_t array = jerry_create_typedarray (JERRY_TYPEDARRAY_UINT16, 15);
|
||||
|
||||
... // use the TypedArray
|
||||
|
||||
jerry_release_value (array);
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_typedarray_type_t](#jerry_typedarray_type_t)
|
||||
- [jerry_value_is_typedarray](#jerry_value_is_typedarray)
|
||||
- [jerry_release_value](#jerry_release_value)
|
||||
|
||||
|
||||
## jerry_create_typedarray_for_arraybuffer
|
||||
|
||||
**Summary**
|
||||
|
||||
Create a jerry_value_t representing an TypedArray object using
|
||||
an already existing ArrayBuffer object.
|
||||
|
||||
For the new object the type of the TypedArray (see: [jerry_typedarray_type_t](#jerry_typedarray_type_t))
|
||||
and element count can be specified.
|
||||
|
||||
The developer must ensure that the ArrayBuffer has the correct length for the given
|
||||
type of TypedArray otherwise an error is generated.
|
||||
|
||||
The JavaScript equivalent of this function is: `new %TypedArray%(arraybuffer)` where `%TypedArray%` is
|
||||
one of the allowed TypedArray functions.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerry_value_t
|
||||
jerry_create_typedarray_for_arraybuffer (jerry_typedarray_type_t type_name,
|
||||
const jerry_value_t arraybuffer);
|
||||
```
|
||||
|
||||
- `type_name` - type of TypedArray to create
|
||||
- `arraybuffer` - the ArrayBuffer to use for the new TypedArray
|
||||
- return value
|
||||
- the new TypedArray as a `jerry_value_t`
|
||||
- Error if the ArrayBuffer does not have enough space for the given type of TypedArray
|
||||
|
||||
**Example**
|
||||
|
||||
```c
|
||||
{
|
||||
jerry_value_t buffer = jerry_create_array_buffer (12 * 2);
|
||||
jerry_value_t array = jerry_create_typedarray_for_arraybuffer (JERRY_TYPEDARRAY_UINT16, buffer);
|
||||
jerry_release_value (buffer);
|
||||
|
||||
... // use the TypedArray
|
||||
|
||||
jerry_release_value (array);
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_typedarray_type_t](#jerry_typedarray_type_t)
|
||||
- [jerry_value_is_typedarray](#jerry_value_is_typedarray)
|
||||
- [jerry_release_value](#jerry_release_value)
|
||||
|
||||
|
||||
## jerry_create_typedarray_for_arraybuffer_sz
|
||||
|
||||
**Summary**
|
||||
|
||||
Create a jerry_value_t representing an TypedArray object using
|
||||
an already existing ArrayBuffer object and by specifying the byteOffset, and length properties.
|
||||
|
||||
For the new object the type of the TypedArray (see: [jerry_typedarray_type_t](#jerry_typedarray_type_t))
|
||||
and element count can be specified.
|
||||
|
||||
The developer must ensure that the ArrayBuffer has the correct length for the given
|
||||
type of TypedArray otherwise an error is generated.
|
||||
|
||||
The JavaScript equivalent of this function is: `new %TypedArray%(arraybuffer, byteOffset, length)` where `%TypedArray%` is
|
||||
one of the allowed TypedArray functions.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerry_value_t
|
||||
jerry_create_typedarray_for_arraybuffer_sz (jerry_typedarray_type_t type_name,
|
||||
const jerry_value_t arraybuffer,
|
||||
jerry_length_t byte_offset,
|
||||
jerry_length_t length);
|
||||
```
|
||||
|
||||
- `type_name` - type of TypedArray to create
|
||||
- `arraybuffer` - the ArrayBuffer to use for the new TypedArray
|
||||
- `byte_offset` - start offset to use for the ArrayBuffer
|
||||
- `length` - number of elements to used from the ArrayBuffer (this is not the same as the byteLength)
|
||||
- return value
|
||||
- the new TypedArray as a `jerry_value_t`
|
||||
- Error if the ArrayBuffer does not have enough space for the given type of TypedArray
|
||||
|
||||
**Example**
|
||||
|
||||
```c
|
||||
{
|
||||
jerry_value_t buffer = jerry_create_array_buffer (12 * 2);
|
||||
jerry_value_t array = jerry_create_typedarray_for_arraybuffer_sz (JERRY_TYPEDARRAY_UINT16, buffer, 4, 10);
|
||||
jerry_release_value (buffer);
|
||||
|
||||
... // use the TypedArray
|
||||
|
||||
jerry_release_value (array);
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_typedarray_type_t](#jerry_typedarray_type_t)
|
||||
- [jerry_value_is_typedarray](#jerry_value_is_typedarray)
|
||||
- [jerry_release_value](#jerry_release_value)
|
||||
|
||||
|
||||
## jerry_create_undefined
|
||||
|
||||
**Summary**
|
||||
@@ -5123,3 +5327,134 @@ jerry_get_arraybuffer_pointer (const jerry_value_t value);
|
||||
**See also**
|
||||
|
||||
- [jerry_create_arraybuffer_external](#jerry_create_arraybuffer_external)
|
||||
|
||||
|
||||
## jerry_get_typedarray_type
|
||||
|
||||
**Summary**
|
||||
|
||||
Get the type of the TypedArray.
|
||||
|
||||
The returned type is one of the [jerry_typedarray_type_t](#jerry_typedarray_type_t)
|
||||
enum value.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerry_typedarray_type_t
|
||||
jerry_get_typedarray_type (jerry_value_t value);
|
||||
```
|
||||
|
||||
- `value` - TypedArray object to query for type.
|
||||
- return
|
||||
- the type of the TypedArray
|
||||
- JERRY_TYPEDARRAY_INVALID if the object was not a TypedArray
|
||||
|
||||
**Example**
|
||||
|
||||
```c
|
||||
{
|
||||
jerry_typedarray_type_t expected_type = JERRY_TYPEDARRAY_UINT32;
|
||||
jerry_value_t typedarray = jerry_create_typedarray (expected_klass, 25);
|
||||
|
||||
jerry_typedarray_type_t type = jerry_get_typedarray_type (typedarray);
|
||||
|
||||
// 'type' is now JERRY_TYPEDARRAY_UINT32
|
||||
|
||||
jerry_release_value (typedarray);
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_create_typedarray](#jerry_create_typedarray)
|
||||
- [jerry_typedarray_type_t](#jerry_typedarray_type_t)
|
||||
|
||||
|
||||
## jerry_get_typedarray_length
|
||||
|
||||
**Summary**
|
||||
|
||||
Get the element count of the TypedArray as specified during creation.
|
||||
|
||||
This is not the same as the byteLength property of a TypedArray object.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```
|
||||
jerry_length_t
|
||||
jerry_get_typedarray_length (jerry_value_t value);
|
||||
```
|
||||
|
||||
- `value` - TypedArray object to query
|
||||
- return
|
||||
- length (element count) of the TypedArray object
|
||||
- 0 if the object is not a TypedArray
|
||||
|
||||
**Example**
|
||||
|
||||
```c
|
||||
{
|
||||
jerry_value_t array = jerry_create_typedarray (JERRY_TYPEDARRAY_INT32, 21);
|
||||
|
||||
jerry_length_t element_count = jerry_get_typedarray_length (array);
|
||||
|
||||
// element_count is now 21.
|
||||
|
||||
jerry_release_value (array);
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_create_typedarray](#jerry_create_typedarray)
|
||||
|
||||
|
||||
## jerry_get_typedarray_buffer
|
||||
|
||||
**Summary**
|
||||
|
||||
Get the ArrayBuffer object used by a TypedArray object.
|
||||
Additionally returns the byteLength and byteOffset properties
|
||||
of the TypedArray object.
|
||||
|
||||
For the returned ArrayBuffer the [jerry_release_value](#jerry_release_value)
|
||||
must be called.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerry_value_t jerry_get_typedarray_buffer (jerry_value_t value,
|
||||
jerry_length_t *byteOffset,
|
||||
jerry_length_t *byteLength);
|
||||
```
|
||||
|
||||
- `value` - TypedArray to get the ArrayBuffer from
|
||||
- `byteOffset` - (Optional) returns the start offset of the ArrayBuffer for the TypedArray
|
||||
- `byteLength` - (Optional) returns the number of bytes used from the ArrayBuffer for the TypedArray
|
||||
- return
|
||||
- TypedArray object's underlying ArrayBuffer object
|
||||
- TypeError if the `value` is not a TypedArray object
|
||||
|
||||
**Example**
|
||||
|
||||
```c
|
||||
{
|
||||
jerry_value_t array = jerry_create_typedarray (JERRY_TYPEDARRAY_INT16, 11);
|
||||
|
||||
jerry_length_t byteLength = 0;
|
||||
jerry_length_t byteOffset = 0;
|
||||
jerry_value_t buffer = jerry_get_typedarray_buffer (array, &byteOffset, &byteLength);
|
||||
|
||||
// buffer is an ArrayBuffer object and ArrayBuffer operations can be performed on it
|
||||
// byteLength is 11 * 2 (2 as the TypedArray stores Int16 that is 2 byte elements)
|
||||
// byteOffset is 0
|
||||
|
||||
jerry_release_value (buffer);
|
||||
jerry_release_value (array);
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_create_typedarray](#jerry_create_typedarray)
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "ecma-objects.h"
|
||||
#include "ecma-objects-general.h"
|
||||
#include "ecma-promise-object.h"
|
||||
#include "ecma-typedarray-object.h"
|
||||
#include "jcontext.h"
|
||||
#include "jerryscript.h"
|
||||
#include "jmem.h"
|
||||
@@ -2936,6 +2937,321 @@ jerry_get_arraybuffer_pointer (const jerry_value_t value) /**< Array Buffer to u
|
||||
return NULL;
|
||||
} /* jerry_get_arraybuffer_pointer */
|
||||
|
||||
|
||||
/**
|
||||
* TypedArray related functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Check if the given value is a TypedArray object.
|
||||
*
|
||||
* @return true - if it is a TypedArray object
|
||||
* false - otherwise
|
||||
*/
|
||||
bool
|
||||
jerry_value_is_typedarray (jerry_value_t value) /**< value to check if it is a TypedArray */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
#ifndef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN
|
||||
jerry_value_t array = jerry_get_arg_value (value);
|
||||
return ecma_is_typedarray (array);
|
||||
#else /* CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
||||
JERRY_UNUSED (value);
|
||||
return false;
|
||||
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
||||
} /* jerry_value_is_typedarray */
|
||||
|
||||
#ifndef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN
|
||||
typedef struct
|
||||
{
|
||||
jerry_typedarray_type_t api_type;
|
||||
ecma_builtin_id_t prototype_id;
|
||||
lit_magic_string_id_t lit_id;
|
||||
uint8_t element_size_shift;
|
||||
} jerry_typedarray_mapping_t;
|
||||
|
||||
static jerry_typedarray_mapping_t jerry_typedarray_mappings[] =
|
||||
{
|
||||
#define TYPEDARRAY_ENTRY(NAME, LIT_NAME, SIZE_SHIFT) \
|
||||
{ JERRY_TYPEDARRAY_ ## NAME, ECMA_BUILTIN_ID_ ## NAME ## ARRAY_PROTOTYPE, \
|
||||
LIT_MAGIC_STRING_ ## LIT_NAME ## _ARRAY_UL, SIZE_SHIFT }
|
||||
|
||||
TYPEDARRAY_ENTRY (UINT8, UINT8, 0),
|
||||
TYPEDARRAY_ENTRY (UINT8CLAMPED, UINT8_CLAMPED, 0),
|
||||
TYPEDARRAY_ENTRY (INT8, INT8, 0),
|
||||
TYPEDARRAY_ENTRY (UINT16, UINT16, 1),
|
||||
TYPEDARRAY_ENTRY (INT16, INT16, 1),
|
||||
TYPEDARRAY_ENTRY (UINT32, UINT32, 2),
|
||||
TYPEDARRAY_ENTRY (INT32, INT32, 2),
|
||||
TYPEDARRAY_ENTRY (FLOAT32, FLOAT32, 2),
|
||||
#if CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT64
|
||||
TYPEDARRAY_ENTRY (FLOAT64, FLOAT64, 3),
|
||||
#endif
|
||||
|
||||
#undef TYPEDARRAY_ENTRY
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper function to get the TypedArray prototype, literal id, and element size shift
|
||||
* information.
|
||||
*
|
||||
* @return true - if the TypedArray information was found
|
||||
* false - if there is no such TypedArray type
|
||||
*/
|
||||
static bool
|
||||
jerry_typedarray_find_by_type (jerry_typedarray_type_t type_name, /**< type of the TypedArray */
|
||||
ecma_builtin_id_t *prototype_id, /**< [out] found prototype object id */
|
||||
lit_magic_string_id_t *lit_id, /**< [out] found literal id */
|
||||
uint8_t *element_size_shift) /**< [out] found element size shift value */
|
||||
{
|
||||
JERRY_ASSERT (prototype_id != NULL);
|
||||
JERRY_ASSERT (lit_id != NULL);
|
||||
JERRY_ASSERT (element_size_shift != NULL);
|
||||
|
||||
for (uint32_t i = 0; i < sizeof (jerry_typedarray_mappings) / sizeof (jerry_typedarray_mappings[0]); i++)
|
||||
{
|
||||
if (type_name == jerry_typedarray_mappings[i].api_type)
|
||||
{
|
||||
*prototype_id = jerry_typedarray_mappings[i].prototype_id;
|
||||
*lit_id = jerry_typedarray_mappings[i].lit_id;
|
||||
*element_size_shift = jerry_typedarray_mappings[i].element_size_shift;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} /* jerry_typedarray_find_by_type */
|
||||
|
||||
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
||||
|
||||
/**
|
||||
* Create a TypedArray object with a given type and length.
|
||||
*
|
||||
* Notes:
|
||||
* * returns TypeError if an incorrect type (type_name) is specified.
|
||||
* * byteOffset property will be set to 0.
|
||||
* * byteLength property will be a multiple of the length parameter (based on the type).
|
||||
*
|
||||
* @return - new TypedArray object
|
||||
*/
|
||||
jerry_value_t
|
||||
jerry_create_typedarray (jerry_typedarray_type_t type_name, /**< type of TypedArray to create */
|
||||
jerry_length_t length) /**< element count of the new TypedArray */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
#ifndef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN
|
||||
ecma_builtin_id_t prototype_id = 0;
|
||||
lit_magic_string_id_t lit_id = 0;
|
||||
uint8_t element_size_shift = 0;
|
||||
|
||||
if (!jerry_typedarray_find_by_type (type_name, &prototype_id, &lit_id, &element_size_shift))
|
||||
{
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("incorrect type for TypedArray.")));
|
||||
}
|
||||
|
||||
ecma_object_t *prototype_obj_p = ecma_builtin_get (prototype_id);
|
||||
|
||||
ecma_value_t array_value = ecma_typedarray_create_object_with_length (length,
|
||||
prototype_obj_p,
|
||||
element_size_shift,
|
||||
lit_id);
|
||||
ecma_deref_object (prototype_obj_p);
|
||||
|
||||
JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (array_value));
|
||||
|
||||
return array_value;
|
||||
#else /* CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
||||
JERRY_UNUSED (type_name);
|
||||
JERRY_UNUSED (length);
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("TypedArray not supported.")));
|
||||
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
||||
} /* jerry_create_typedarray */
|
||||
|
||||
/**
|
||||
* Create a TypedArray object using the given arraybuffer and size information.
|
||||
*
|
||||
* Notes:
|
||||
* * returns TypeError if an incorrect type (type_name) is specified.
|
||||
* * this is the 'new %TypedArray%(arraybuffer, byteOffset, length)' equivalent call.
|
||||
*
|
||||
* @return - new TypedArray object
|
||||
*/
|
||||
jerry_value_t
|
||||
jerry_create_typedarray_for_arraybuffer_sz (jerry_typedarray_type_t type_name, /**< type of TypedArray to create */
|
||||
const jerry_value_t arraybuffer, /**< ArrayBuffer to use */
|
||||
jerry_length_t byte_offset, /**< offset for the ArrayBuffer */
|
||||
jerry_length_t length) /**< number of elements to use from ArrayBuffer */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
#ifndef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN
|
||||
ecma_builtin_id_t prototype_id = 0;
|
||||
lit_magic_string_id_t lit_id = 0;
|
||||
uint8_t element_size_shift = 0;
|
||||
|
||||
if (!jerry_typedarray_find_by_type (type_name, &prototype_id, &lit_id, &element_size_shift))
|
||||
{
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("incorrect type for TypedArray.")));
|
||||
}
|
||||
|
||||
jerry_value_t buffer = jerry_get_arg_value (arraybuffer);
|
||||
if (!ecma_is_arraybuffer (buffer))
|
||||
{
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Argument is not an ArrayBuffer")));
|
||||
}
|
||||
|
||||
ecma_object_t *prototype_obj_p = ecma_builtin_get (prototype_id);
|
||||
ecma_value_t arguments_p[3] =
|
||||
{
|
||||
arraybuffer,
|
||||
ecma_make_uint32_value (byte_offset),
|
||||
ecma_make_uint32_value (length)
|
||||
};
|
||||
|
||||
ecma_value_t array_value = ecma_op_create_typedarray (arguments_p, 3, prototype_obj_p, element_size_shift, lit_id);
|
||||
ecma_free_value (arguments_p[1]);
|
||||
ecma_free_value (arguments_p[2]);
|
||||
ecma_deref_object (prototype_obj_p);
|
||||
|
||||
return jerry_return (array_value);
|
||||
#else /* CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
||||
JERRY_UNUSED (type_name);
|
||||
JERRY_UNUSED (arraybuffer);
|
||||
JERRY_UNUSED (byte_offset);
|
||||
JERRY_UNUSED (length);
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("TypedArray not supported.")));
|
||||
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
||||
} /* jerry_create_typedarray_for_arraybuffer_sz */
|
||||
|
||||
/**
|
||||
* Create a TypedArray object using the given arraybuffer and size information.
|
||||
*
|
||||
* Notes:
|
||||
* * returns TypeError if an incorrect type (type_name) is specified.
|
||||
* * this is the 'new %TypedArray%(arraybuffer)' equivalent call.
|
||||
*
|
||||
* @return - new TypedArray object
|
||||
*/
|
||||
jerry_value_t
|
||||
jerry_create_typedarray_for_arraybuffer (jerry_typedarray_type_t type_name, /**< type of TypedArray to create */
|
||||
const jerry_value_t arraybuffer) /**< ArrayBuffer to use */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
jerry_length_t byteLength = jerry_get_arraybuffer_byte_length (arraybuffer);
|
||||
return jerry_create_typedarray_for_arraybuffer_sz (type_name, arraybuffer, 0, byteLength);
|
||||
} /* jerry_create_typedarray_for_arraybuffer */
|
||||
|
||||
/**
|
||||
* Get the type of the TypedArray.
|
||||
*
|
||||
* @return - type of the TypedArray
|
||||
* - JERRY_TYPEDARRAY_INVALID if the argument is not a TypedArray
|
||||
*/
|
||||
jerry_typedarray_type_t
|
||||
jerry_get_typedarray_type (jerry_value_t value) /**< object to get the TypedArray type */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
#ifndef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN
|
||||
jerry_value_t array = jerry_get_arg_value (value);
|
||||
if (!ecma_is_typedarray (array))
|
||||
{
|
||||
return JERRY_TYPEDARRAY_INVALID;
|
||||
}
|
||||
|
||||
ecma_object_t *array_p = ecma_get_object_from_value (array);
|
||||
|
||||
lit_magic_string_id_t class_name_id = ecma_object_get_class_name (array_p);
|
||||
for (uint32_t i = 0; i < sizeof (jerry_typedarray_mappings) / sizeof (jerry_typedarray_mappings[0]); i++)
|
||||
{
|
||||
if (class_name_id == jerry_typedarray_mappings[i].lit_id)
|
||||
{
|
||||
return jerry_typedarray_mappings[i].api_type;
|
||||
}
|
||||
}
|
||||
#else /* CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
||||
JERRY_UNUSED (value);
|
||||
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
||||
|
||||
return JERRY_TYPEDARRAY_INVALID;
|
||||
} /* jerry_get_typedarray_type */
|
||||
|
||||
/**
|
||||
* Get the element count of the TypedArray.
|
||||
*
|
||||
* @return length of the TypedArray.
|
||||
*/
|
||||
jerry_length_t
|
||||
jerry_get_typedarray_length (jerry_value_t value) /**< TypedArray to query */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
#ifndef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN
|
||||
jerry_value_t array = jerry_get_arg_value (value);
|
||||
if (ecma_is_typedarray (array))
|
||||
{
|
||||
ecma_object_t *array_p = ecma_get_object_from_value (array);
|
||||
return ecma_typedarray_get_length (array_p);
|
||||
}
|
||||
#else /* CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
||||
JERRY_UNUSED (value);
|
||||
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
||||
|
||||
return 0;
|
||||
} /* jerry_get_typedarray_length */
|
||||
|
||||
/**
|
||||
* Get the underlying ArrayBuffer from a TypedArray.
|
||||
*
|
||||
* Additionally the byteLength and byteOffset properties are also returned
|
||||
* which were specified when the TypedArray was created.
|
||||
*
|
||||
* Note:
|
||||
* the returned value must be freed with a jerry_release_value call
|
||||
*
|
||||
* @return ArrayBuffer of a TypedArray
|
||||
* TypeError if the object is not a TypedArray.
|
||||
*/
|
||||
jerry_value_t
|
||||
jerry_get_typedarray_buffer (jerry_value_t value, /**< TypedArray to get the arraybuffer from */
|
||||
jerry_length_t *byte_offset, /**< [out] byteOffset property */
|
||||
jerry_length_t *byte_length) /**< [out] byteLength property */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
#ifndef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN
|
||||
jerry_value_t array = jerry_get_arg_value (value);
|
||||
if (!ecma_is_typedarray (array))
|
||||
{
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Object is not a TypedArray.")));
|
||||
}
|
||||
|
||||
ecma_object_t *array_p = ecma_get_object_from_value (array);
|
||||
uint8_t shift = ecma_typedarray_get_element_size_shift (array_p);
|
||||
|
||||
if (byte_length != NULL)
|
||||
{
|
||||
*byte_length = (jerry_length_t) (ecma_typedarray_get_length (array_p) << shift);
|
||||
}
|
||||
|
||||
if (byte_offset != NULL)
|
||||
{
|
||||
*byte_offset = (jerry_length_t) ecma_typedarray_get_offset (array_p);
|
||||
}
|
||||
|
||||
ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (array_p);
|
||||
ecma_ref_object (arraybuffer_p);
|
||||
return jerry_return (ecma_make_object_value (arraybuffer_p));
|
||||
#else /* CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
||||
JERRY_UNUSED (value);
|
||||
JERRY_UNUSED (byte_length);
|
||||
JERRY_UNUSED (byte_offset);
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("TypedArray is not supported.")));
|
||||
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
||||
} /* jerry_get_typedarray_buffer */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -226,7 +226,7 @@ ecma_set_typedarray_element (lit_utf8_byte_t *dst_p, /**< the location in the in
|
||||
* @return ecma value of the new typedarray object
|
||||
* Returned value must be freed with ecma_free_value
|
||||
*/
|
||||
static ecma_value_t
|
||||
ecma_value_t
|
||||
ecma_typedarray_create_object_with_length (ecma_length_t array_length, /**< length of the typedarray */
|
||||
ecma_object_t *proto_p, /**< prototype object */
|
||||
uint8_t element_size_shift, /**< the size shift of the element length */
|
||||
|
||||
@@ -57,6 +57,10 @@ bool ecma_op_typedarray_define_index_prop (ecma_object_t *obj_p,
|
||||
bool ecma_op_typedarray_set_index_prop (ecma_object_t *obj_p, uint32_t index, ecma_value_t value);
|
||||
ecma_value_t ecma_op_create_typedarray_with_type_and_length (ecma_object_t *obj_p,
|
||||
ecma_length_t array_length);
|
||||
ecma_value_t ecma_typedarray_create_object_with_length (ecma_length_t array_length,
|
||||
ecma_object_t *proto_p,
|
||||
uint8_t element_size_shift,
|
||||
lit_magic_string_id_t class_id);
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
||||
@@ -462,6 +462,43 @@ jerry_length_t jerry_arraybuffer_read (const jerry_value_t value,
|
||||
jerry_length_t jerry_get_arraybuffer_byte_length (const jerry_value_t value);
|
||||
uint8_t *jerry_get_arraybuffer_pointer (const jerry_value_t value);
|
||||
|
||||
|
||||
/**
|
||||
* TypedArray functions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* TypedArray types.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
JERRY_TYPEDARRAY_INVALID = 0,
|
||||
JERRY_TYPEDARRAY_UINT8,
|
||||
JERRY_TYPEDARRAY_UINT8CLAMPED,
|
||||
JERRY_TYPEDARRAY_INT8,
|
||||
JERRY_TYPEDARRAY_UINT16,
|
||||
JERRY_TYPEDARRAY_INT16,
|
||||
JERRY_TYPEDARRAY_UINT32,
|
||||
JERRY_TYPEDARRAY_INT32,
|
||||
JERRY_TYPEDARRAY_FLOAT32,
|
||||
JERRY_TYPEDARRAY_FLOAT64,
|
||||
} jerry_typedarray_type_t;
|
||||
|
||||
|
||||
bool jerry_value_is_typedarray (jerry_value_t value);
|
||||
jerry_value_t jerry_create_typedarray (jerry_typedarray_type_t type_name, jerry_length_t length);
|
||||
jerry_value_t jerry_create_typedarray_for_arraybuffer_sz (jerry_typedarray_type_t type_name,
|
||||
const jerry_value_t arraybuffer,
|
||||
jerry_length_t byte_offset,
|
||||
jerry_length_t length);
|
||||
jerry_value_t jerry_create_typedarray_for_arraybuffer (jerry_typedarray_type_t type_name,
|
||||
const jerry_value_t arraybuffer);
|
||||
jerry_typedarray_type_t jerry_get_typedarray_type (jerry_value_t value);
|
||||
jerry_length_t jerry_get_typedarray_length (jerry_value_t value);
|
||||
jerry_value_t jerry_get_typedarray_buffer (jerry_value_t value,
|
||||
jerry_length_t *byte_offset,
|
||||
jerry_length_t *byte_length);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,475 @@
|
||||
/* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "jerryscript.h"
|
||||
#include "jerryscript-port.h"
|
||||
#include "jerryscript-port-default.h"
|
||||
#include "test-common.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/**
|
||||
* Type to describe test cases.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
jerry_typedarray_type_t typedarray_type; /**< what kind of TypedArray */
|
||||
char *constructor_name; /**< JS constructor name for TypedArray */
|
||||
uint32_t element_count; /**< number of elements for the TypedArray */
|
||||
uint32_t bytes_per_element; /**< bytes per elment of the given typedarray_type */
|
||||
} test_entry_t;
|
||||
|
||||
/**
|
||||
* Register a JavaScript value in the global object.
|
||||
*/
|
||||
static void
|
||||
register_js_value (const char *name_p, /**< name of the function */
|
||||
jerry_value_t value) /**< function callback */
|
||||
{
|
||||
jerry_value_t global_obj_val = jerry_get_global_object ();
|
||||
|
||||
jerry_value_t name_val = jerry_create_string ((const jerry_char_t *) name_p);
|
||||
jerry_value_t result_val = jerry_set_property (global_obj_val, name_val, value);
|
||||
|
||||
jerry_release_value (name_val);
|
||||
jerry_release_value (global_obj_val);
|
||||
|
||||
jerry_release_value (result_val);
|
||||
} /* register_js_value */
|
||||
|
||||
static jerry_value_t
|
||||
assert_handler (const jerry_value_t func_obj_val, /**< function object */
|
||||
const jerry_value_t this_val, /**< this arg */
|
||||
const jerry_value_t args_p[], /**< function arguments */
|
||||
const jerry_length_t args_cnt) /**< number of function arguments */
|
||||
{
|
||||
JERRY_UNUSED (func_obj_val);
|
||||
JERRY_UNUSED (this_val);
|
||||
|
||||
if (jerry_value_is_boolean (args_p[0])
|
||||
&& jerry_get_boolean_value (args_p[0]))
|
||||
{
|
||||
return jerry_create_boolean (true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (args_cnt > 1
|
||||
&& jerry_value_is_string (args_p[1]))
|
||||
{
|
||||
jerry_length_t utf8_sz = jerry_get_string_size (args_p[1]);
|
||||
char string_from_utf8[utf8_sz];
|
||||
string_from_utf8[utf8_sz] = 0;
|
||||
|
||||
jerry_string_to_char_buffer (args_p[1], (jerry_char_t *) string_from_utf8, utf8_sz);
|
||||
|
||||
printf ("JS assert: %s\n", string_from_utf8);
|
||||
}
|
||||
TEST_ASSERT (false);
|
||||
}
|
||||
} /* assert_handler */
|
||||
|
||||
/**
|
||||
* Checks whether global object has typedarray.
|
||||
*/
|
||||
static bool
|
||||
typedarray_is_available (void)
|
||||
{
|
||||
jerry_value_t global_obj_val = jerry_get_global_object ();
|
||||
jerry_value_t prop_name = jerry_create_string ((const jerry_char_t *) "Int8Array");
|
||||
|
||||
jerry_value_t prop_value = jerry_has_property (global_obj_val, prop_name);
|
||||
bool has_prop = jerry_get_boolean_value (prop_value);
|
||||
|
||||
jerry_release_value (global_obj_val);
|
||||
jerry_release_value (prop_name);
|
||||
jerry_release_value (prop_value);
|
||||
|
||||
return has_prop;
|
||||
} /* typedarray_is_available */
|
||||
|
||||
/**
|
||||
* Do simple TypedArray property validation.
|
||||
*/
|
||||
static void
|
||||
test_typedarray_info (jerry_value_t typedarray, /**< target TypedArray to query */
|
||||
jerry_typedarray_type_t typedarray_type, /**< expected TypedArray type */
|
||||
jerry_length_t element_count, /**< expected element count */
|
||||
jerry_length_t bytes_per_element) /**< bytes per element for the given type */
|
||||
{
|
||||
TEST_ASSERT (!jerry_value_has_error_flag (typedarray));
|
||||
TEST_ASSERT (jerry_value_is_typedarray (typedarray));
|
||||
TEST_ASSERT (jerry_get_typedarray_type (typedarray) == typedarray_type);
|
||||
TEST_ASSERT (jerry_get_typedarray_length (typedarray) == element_count);
|
||||
|
||||
jerry_length_t byte_length = (uint32_t) -1;
|
||||
jerry_length_t byte_offset = (uint32_t) -1;
|
||||
jerry_value_t arraybuffer = jerry_get_typedarray_buffer (typedarray, &byte_offset, &byte_length);
|
||||
TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer));
|
||||
|
||||
TEST_ASSERT (byte_length == element_count * bytes_per_element);
|
||||
TEST_ASSERT (byte_offset == 0);
|
||||
|
||||
jerry_release_value (arraybuffer);
|
||||
} /* test_typedarray_info */
|
||||
|
||||
/**
|
||||
* Test construction of TypedArrays and validate properties.
|
||||
*/
|
||||
static void
|
||||
test_typedarray_queries (test_entry_t test_entries[]) /**< test cases */
|
||||
{
|
||||
jerry_value_t global_obj_val = jerry_get_global_object ();
|
||||
|
||||
for (uint32_t i = 0; test_entries[i].constructor_name != NULL; i++)
|
||||
{
|
||||
/* Create TypedArray via construct call */
|
||||
{
|
||||
jerry_value_t prop_name = jerry_create_string ((const jerry_char_t *) test_entries[i].constructor_name);
|
||||
jerry_value_t prop_value = jerry_get_property (global_obj_val, prop_name);
|
||||
TEST_ASSERT (!jerry_value_has_error_flag (prop_value));
|
||||
jerry_value_t length_arg = jerry_create_number (test_entries[i].element_count);
|
||||
|
||||
jerry_value_t typedarray = jerry_construct_object (prop_value, &length_arg, 1);
|
||||
|
||||
jerry_release_value (prop_name);
|
||||
jerry_release_value (prop_value);
|
||||
jerry_release_value (length_arg);
|
||||
|
||||
test_typedarray_info (typedarray,
|
||||
test_entries[i].typedarray_type,
|
||||
test_entries[i].element_count,
|
||||
test_entries[i].bytes_per_element);
|
||||
jerry_release_value (typedarray);
|
||||
}
|
||||
|
||||
/* Create TypedArray via api call */
|
||||
{
|
||||
jerry_value_t typedarray = jerry_create_typedarray (test_entries[i].typedarray_type,
|
||||
test_entries[i].element_count);
|
||||
test_typedarray_info (typedarray,
|
||||
test_entries[i].typedarray_type,
|
||||
test_entries[i].element_count,
|
||||
test_entries[i].bytes_per_element);
|
||||
jerry_release_value (typedarray);
|
||||
}
|
||||
}
|
||||
|
||||
jerry_release_value (global_obj_val);
|
||||
} /* test_typedarray_queries */
|
||||
|
||||
/**
|
||||
* Test value at given position in the buffer based on TypedArray type.
|
||||
*/
|
||||
static
|
||||
void test_buffer_value (uint64_t value, /**< value to test for */
|
||||
const uint8_t *buffer, /**< buffer to read value from */
|
||||
uint32_t start_offset, /**< start offset of the value */
|
||||
jerry_typedarray_type_t typedarray_type, /**< type of TypedArray */
|
||||
uint32_t bytes_per_element) /**< bytes per element for the given type */
|
||||
{
|
||||
uint32_t offset = start_offset / bytes_per_element;
|
||||
|
||||
#define TEST_VALUE_AT(TYPE, BUFFER, OFFSET, VALUE) TEST_ASSERT (((TYPE *) BUFFER)[OFFSET] == (TYPE) (VALUE))
|
||||
|
||||
switch (typedarray_type)
|
||||
{
|
||||
case JERRY_TYPEDARRAY_UINT8: TEST_VALUE_AT (uint8_t, buffer, offset, value); break;
|
||||
case JERRY_TYPEDARRAY_INT8: TEST_VALUE_AT (int8_t, buffer, offset, value); break;
|
||||
case JERRY_TYPEDARRAY_UINT16: TEST_VALUE_AT (uint16_t, buffer, offset, value); break;
|
||||
case JERRY_TYPEDARRAY_INT16: TEST_VALUE_AT (int16_t, buffer, offset, value); break;
|
||||
case JERRY_TYPEDARRAY_UINT32: TEST_VALUE_AT (uint32_t, buffer, offset, value); break;
|
||||
case JERRY_TYPEDARRAY_INT32: TEST_VALUE_AT (int32_t, buffer, offset, value); break;
|
||||
case JERRY_TYPEDARRAY_FLOAT32: TEST_VALUE_AT (float, buffer, offset, value); break;
|
||||
case JERRY_TYPEDARRAY_FLOAT64: TEST_VALUE_AT (double, buffer, offset, value); break;
|
||||
|
||||
case JERRY_TYPEDARRAY_UINT8CLAMPED:
|
||||
{
|
||||
int64_t signed_value = (int64_t) value;
|
||||
uint8_t expected = (uint8_t) value;
|
||||
|
||||
/* clamp the value if required*/
|
||||
if (signed_value > 0xFF)
|
||||
{
|
||||
expected = 0xFF;
|
||||
}
|
||||
else if (signed_value < 0)
|
||||
{
|
||||
expected = 0;
|
||||
}
|
||||
|
||||
TEST_VALUE_AT (uint8_t, buffer, offset, expected); break;
|
||||
}
|
||||
default: TEST_ASSERT (false); break;
|
||||
}
|
||||
|
||||
#undef TEST_VALUE_AT
|
||||
} /* test_buffer_value */
|
||||
|
||||
static void
|
||||
test_typedarray_complex_creation (test_entry_t test_entries[], /**< test cases */
|
||||
bool use_external_buffer) /**< run tests using arraybuffer with external memory */
|
||||
{
|
||||
const uint32_t arraybuffer_size = 256;
|
||||
|
||||
uint8_t buffer_ext[arraybuffer_size];
|
||||
memset (buffer_ext, 0, arraybuffer_size);
|
||||
|
||||
for (uint32_t i = 0; test_entries[i].constructor_name != NULL; i++)
|
||||
{
|
||||
const uint32_t offset = 8;
|
||||
uint32_t element_count = test_entries[i].element_count;
|
||||
uint32_t bytes_per_element = test_entries[i].bytes_per_element;
|
||||
|
||||
/* new %TypedArray% (buffer, offset, length); */
|
||||
jerry_value_t typedarray;
|
||||
{
|
||||
jerry_value_t arraybuffer;
|
||||
|
||||
if (use_external_buffer)
|
||||
{
|
||||
arraybuffer = jerry_create_arraybuffer_external (arraybuffer_size, buffer_ext, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
arraybuffer = jerry_create_arraybuffer (arraybuffer_size);
|
||||
}
|
||||
|
||||
jerry_value_t js_offset = jerry_create_number (offset);
|
||||
jerry_value_t js_element_count = jerry_create_number (element_count);
|
||||
|
||||
register_js_value ("expected_offset", js_offset);
|
||||
register_js_value ("expected_length", js_element_count);
|
||||
|
||||
typedarray = jerry_create_typedarray_for_arraybuffer_sz (test_entries[i].typedarray_type,
|
||||
arraybuffer,
|
||||
offset,
|
||||
element_count);
|
||||
TEST_ASSERT (!jerry_value_has_error_flag (typedarray));
|
||||
|
||||
jerry_release_value (js_offset);
|
||||
jerry_release_value (js_element_count);
|
||||
jerry_release_value (arraybuffer);
|
||||
}
|
||||
|
||||
register_js_value ("array", typedarray);
|
||||
|
||||
const char *eval_src_p = (
|
||||
"assert (array.length == expected_length,"
|
||||
" 'expected length: ' + expected_length + ' got: ' + array.length);"
|
||||
"assert (array.byteOffset == expected_offset);"
|
||||
"array[0] = 0x11223344;");
|
||||
jerry_value_t result = jerry_eval ((jerry_char_t *) eval_src_p,
|
||||
strlen (eval_src_p),
|
||||
true);
|
||||
TEST_ASSERT (!jerry_value_has_error_flag (result));
|
||||
jerry_release_value (result);
|
||||
|
||||
{
|
||||
jerry_length_t byte_length = 0;
|
||||
jerry_length_t byte_offset = 0;
|
||||
jerry_value_t buffer = jerry_get_typedarray_buffer (typedarray, &byte_offset, &byte_length);
|
||||
TEST_ASSERT (byte_length == element_count * bytes_per_element);
|
||||
TEST_ASSERT (byte_offset == offset);
|
||||
|
||||
uint8_t test_buffer[arraybuffer_size];
|
||||
|
||||
jerry_typedarray_type_t type = jerry_get_typedarray_type (typedarray);
|
||||
jerry_value_t read_count = jerry_arraybuffer_read (buffer, 0, test_buffer, offset + byte_length);
|
||||
TEST_ASSERT (read_count == offset + byte_length);
|
||||
test_buffer_value (0x11223344, test_buffer, offset, type, bytes_per_element);
|
||||
|
||||
if (use_external_buffer)
|
||||
{
|
||||
test_buffer_value (0x11223344, buffer_ext, offset, type, bytes_per_element);
|
||||
TEST_ASSERT (memcmp (buffer_ext, test_buffer, offset + byte_length) == 0);
|
||||
}
|
||||
|
||||
jerry_release_value (buffer);
|
||||
}
|
||||
|
||||
jerry_release_value (typedarray);
|
||||
}
|
||||
} /* test_typedarray_complex_creation */
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
if (!typedarray_is_available ())
|
||||
{
|
||||
jerry_port_log (JERRY_LOG_LEVEL_ERROR, "TypedArray is disabled!\n");
|
||||
jerry_cleanup ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
jerry_value_t function_val = jerry_create_external_function (assert_handler);
|
||||
register_js_value ("assert", function_val);
|
||||
jerry_release_value (function_val);
|
||||
|
||||
test_entry_t test_entries[] =
|
||||
{
|
||||
#define TEST_ENTRY(TYPE, CONSTRUCTOR, COUNT, BYTES_PER_ELEMENT) \
|
||||
{ TYPE, CONSTRUCTOR, COUNT, BYTES_PER_ELEMENT }
|
||||
|
||||
TEST_ENTRY (JERRY_TYPEDARRAY_UINT8, "Uint8Array", 12, 1),
|
||||
TEST_ENTRY (JERRY_TYPEDARRAY_UINT8CLAMPED, "Uint8ClampedArray", 12, 1),
|
||||
TEST_ENTRY (JERRY_TYPEDARRAY_INT8, "Int8Array", 12, 1),
|
||||
TEST_ENTRY (JERRY_TYPEDARRAY_UINT16, "Uint16Array", 12, 2),
|
||||
TEST_ENTRY (JERRY_TYPEDARRAY_INT16, "Int16Array", 12, 2),
|
||||
TEST_ENTRY (JERRY_TYPEDARRAY_UINT16, "Uint16Array", 12, 2),
|
||||
TEST_ENTRY (JERRY_TYPEDARRAY_INT32, "Int32Array", 12, 4),
|
||||
TEST_ENTRY (JERRY_TYPEDARRAY_UINT32, "Uint32Array", 12, 4),
|
||||
TEST_ENTRY (JERRY_TYPEDARRAY_FLOAT32, "Float32Array", 12, 4),
|
||||
/* TODO: add check if the float64 is supported */
|
||||
TEST_ENTRY (JERRY_TYPEDARRAY_FLOAT64, "Float64Array", 12, 8),
|
||||
|
||||
TEST_ENTRY (JERRY_TYPEDARRAY_INVALID, NULL, 0, 0)
|
||||
#undef TEST_ENTRY
|
||||
};
|
||||
|
||||
/* Test TypedArray queries */
|
||||
test_typedarray_queries (test_entries);
|
||||
|
||||
/* Test TypedArray operations in js */
|
||||
{
|
||||
const uint32_t element_count = 14;
|
||||
uint8_t expected_value = 42;
|
||||
|
||||
jerry_value_t array = jerry_create_typedarray (JERRY_TYPEDARRAY_UINT8, element_count);
|
||||
|
||||
{
|
||||
uint8_t expected_data[element_count];
|
||||
memset (expected_data, expected_value, element_count);
|
||||
|
||||
jerry_length_t byte_length;
|
||||
jerry_length_t offset;
|
||||
jerry_value_t buffer = jerry_get_typedarray_buffer (array, &offset, &byte_length);
|
||||
TEST_ASSERT (byte_length == element_count);
|
||||
jerry_length_t written = jerry_arraybuffer_write (buffer, offset, expected_data, element_count);
|
||||
TEST_ASSERT (written == element_count);
|
||||
jerry_release_value (buffer);
|
||||
|
||||
jerry_value_t js_element_count = jerry_create_number (element_count);
|
||||
jerry_value_t js_expected_value = jerry_create_number (expected_value);
|
||||
|
||||
register_js_value ("array", array);
|
||||
register_js_value ("expected_length", js_element_count);
|
||||
register_js_value ("expected_value", js_expected_value);
|
||||
|
||||
jerry_release_value (js_element_count);
|
||||
jerry_release_value (js_expected_value);
|
||||
}
|
||||
|
||||
/* Check read and to write */
|
||||
const char *eval_src_p = (
|
||||
"assert (array.length == expected_length, 'expected length: ' + expected_length + ' got: ' + array.length);"
|
||||
"for (var i = 0; i < array.length; i++)"
|
||||
"{"
|
||||
" assert (array[i] == expected_value);"
|
||||
" array[i] = i;"
|
||||
"};");
|
||||
jerry_value_t result = jerry_eval ((jerry_char_t *) eval_src_p,
|
||||
strlen (eval_src_p),
|
||||
true);
|
||||
|
||||
TEST_ASSERT (!jerry_value_has_error_flag (result));
|
||||
jerry_release_value (result);
|
||||
|
||||
/* Check write results */
|
||||
{
|
||||
jerry_length_t byte_length;
|
||||
jerry_length_t offset;
|
||||
jerry_value_t buffer = jerry_get_typedarray_buffer (array, &offset, &byte_length);
|
||||
TEST_ASSERT (byte_length == element_count);
|
||||
|
||||
uint8_t result_data[element_count];
|
||||
|
||||
jerry_length_t read_count = jerry_arraybuffer_read (buffer, offset, result_data, byte_length);
|
||||
TEST_ASSERT (read_count == byte_length);
|
||||
|
||||
for (uint8_t i = 0; i < read_count; i++)
|
||||
{
|
||||
TEST_ASSERT (result_data[i] == i);
|
||||
}
|
||||
|
||||
jerry_release_value (buffer);
|
||||
}
|
||||
|
||||
jerry_release_value (array);
|
||||
}
|
||||
|
||||
test_typedarray_complex_creation (test_entries, false);
|
||||
test_typedarray_complex_creation (test_entries, true);
|
||||
|
||||
/* test invalid things */
|
||||
{
|
||||
jerry_value_t values[] =
|
||||
{
|
||||
jerry_create_number (11),
|
||||
jerry_create_boolean (false),
|
||||
jerry_create_string ((const jerry_char_t *) "test"),
|
||||
jerry_create_object (),
|
||||
jerry_create_null (),
|
||||
jerry_create_arraybuffer (16),
|
||||
jerry_create_error (JERRY_ERROR_TYPE, (const jerry_char_t *) "error"),
|
||||
jerry_create_undefined (),
|
||||
jerry_create_promise (),
|
||||
};
|
||||
|
||||
for (size_t idx = 0; idx < sizeof (values) / sizeof (values[0]); idx++)
|
||||
{
|
||||
/* A non-TypedArray object should not be regarded a TypedArray. */
|
||||
bool is_typedarray = jerry_value_is_typedarray (values[idx]);
|
||||
TEST_ASSERT (is_typedarray == false);
|
||||
|
||||
/* JERRY_TYPEDARRAY_INVALID should be returned for non-TypedArray objects */
|
||||
jerry_typedarray_type_t type = jerry_get_typedarray_type (values[idx]);
|
||||
TEST_ASSERT (type == JERRY_TYPEDARRAY_INVALID);
|
||||
|
||||
/* Zero should be returned for non-TypedArray objects */
|
||||
jerry_length_t length = jerry_get_typedarray_length (values[idx]);
|
||||
TEST_ASSERT (length == 0);
|
||||
|
||||
/**
|
||||
* Getting the ArrayBuffer from a non-TypedArray object(s) should return an error
|
||||
* and should not modify the output parameter values.
|
||||
*/
|
||||
{
|
||||
jerry_length_t offset = 22;
|
||||
jerry_length_t byte_count = 23;
|
||||
jerry_value_t error = jerry_get_typedarray_buffer (values[idx], &offset, &byte_count);
|
||||
TEST_ASSERT (jerry_value_has_error_flag (error));
|
||||
TEST_ASSERT (offset == 22);
|
||||
TEST_ASSERT (byte_count == 23);
|
||||
jerry_release_value (error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creating a TypedArray from a non-ArrayBuffer should result an error.
|
||||
*/
|
||||
if (!jerry_value_is_arraybuffer (values[idx]))
|
||||
{
|
||||
jerry_value_t error = jerry_create_typedarray_for_arraybuffer (JERRY_TYPEDARRAY_UINT8, values[idx]);
|
||||
TEST_ASSERT (jerry_value_has_error_flag (error));
|
||||
jerry_release_value (error);
|
||||
}
|
||||
|
||||
jerry_release_value (values[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
jerry_cleanup ();
|
||||
} /* main */
|
||||
Reference in New Issue
Block a user