mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Add allocate/free callbacks to ArrayBuffers (#4801)
Larger buffer allocations will throw error instead of calling jerry_fatal. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
parent
d2388e907f
commit
a024eb2118
@ -1457,6 +1457,86 @@ typedef struct
|
||||
- [jerry_source_info_enabled_fields_t](#jerry_source_info_enabled_fields_t)
|
||||
- [jerry_get_source_info](#jerry_get_source_info)
|
||||
|
||||
## jerry_arraybuffer_type_t
|
||||
|
||||
**Summary**
|
||||
|
||||
Enum that contains the JerryScript type of an array buffer:
|
||||
|
||||
- JERRY_ARRAYBUFFER_TYPE_ARRAYBUFFER - the object is an array buffer object
|
||||
- JERRY_ARRAYBUFFER_TYPE_SHARED_ARRAYBUFFER - the object is a shared array buffer object
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_arraybuffer_allocate_t](#jerry_arraybuffer_allocate_t)
|
||||
- [jerry_arraybuffer_free_t](#jerry_arraybuffer_free_t)
|
||||
|
||||
## jerry_arraybuffer_allocate_t
|
||||
|
||||
**Summary**
|
||||
|
||||
Callback for allocating the backing store of array buffer or shared array buffer objects.
|
||||
|
||||
*Note*:
|
||||
- The value referenced by `arraybuffer_user_p` is always NULL unless the buffer is created by
|
||||
[jerry_create_arraybuffer_external](#jerry_create_arraybuffer_external) or
|
||||
[jerry_create_shared_arraybuffer_external](#jerry_create_shared_arraybuffer_external).
|
||||
The value referenced by `arraybuffer_user_p` can be changed, and the new value is passed to
|
||||
[jerry_arraybuffer_free_t](#jerry_arraybuffer_free_t).
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
typedef uint8_t *(*jerry_arraybuffer_allocate_t) (jerry_arraybuffer_type_t buffer_type, uint32_t buffer_size,
|
||||
void **arraybuffer_user_p, void *user_p);
|
||||
```
|
||||
|
||||
- `buffer_type` - type of the array buffer object, see: [jerry_arraybuffer_type_t](#jerry_arraybuffer_type_t).
|
||||
- `buffer_size` - size of the requested buffer.
|
||||
- `arraybuffer_user_p` - [in/out] user pointer assigned to the array buffer or shared array buffer object.
|
||||
- `user_p` - user pointer passed to [jerry_arraybuffer_set_allocator_callbacks](#jerry_arraybuffer_set_allocator_callbacks)
|
||||
- return value
|
||||
- Pointer to the buffer, if the allocation is successful, NULL otherwise.
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_arraybuffer_set_allocator_callbacks](#jerry_arraybuffer_set_allocator_callbacks)
|
||||
|
||||
## jerry_arraybuffer_free_t
|
||||
|
||||
**Summary**
|
||||
|
||||
Callback for freeing the backing store of array buffer or shared array buffer objects.
|
||||
|
||||
*Note*:
|
||||
- The value passed to `arraybuffer_user_p` is always NULL unless the buffer is created by
|
||||
[jerry_create_arraybuffer_external](#jerry_create_arraybuffer_external) or
|
||||
[jerry_create_shared_arraybuffer_external](#jerry_create_shared_arraybuffer_external),
|
||||
or the value is modified by [jerry_arraybuffer_allocate_t](#jerry_arraybuffer_allocate_t).
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
typedef void (*jerry_arraybuffer_free_t) (jerry_arraybuffer_type_t buffer_type, uint8_t *buffer_p,
|
||||
uint32_t buffer_size, void *arraybuffer_user_p, void *user_p);
|
||||
```
|
||||
|
||||
- `buffer_type` - type of the array buffer object, see: [jerry_arraybuffer_type_t](#jerry_arraybuffer_type_t).
|
||||
- `buffer_p` - pointer to the allocated buffer.
|
||||
- `buffer_size` - size of the allocated buffer.
|
||||
- `arraybuffer_user_p` - [in/out] user pointer assigned to the array buffer or shared array buffer object.
|
||||
- `user_p` - user pointer passed to [jerry_arraybuffer_set_allocator_callbacks](#jerry_arraybuffer_set_allocator_callbacks)
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_arraybuffer_set_allocator_callbacks](#jerry_arraybuffer_set_allocator_callbacks)
|
||||
|
||||
|
||||
# General engine functions
|
||||
|
||||
@ -6893,9 +6973,11 @@ jerry_create_array (uint32_t size);
|
||||
Create a jerry_value_t representing an ArrayBuffer object.
|
||||
|
||||
*Note*:
|
||||
- This API depends on the es.next profile.
|
||||
- Returned value must be freed with [jerry_release_value](#jerry_release_value)
|
||||
when it is no longer needed.
|
||||
- This API depends on a build option (`JERRY_BUILTIN_TYPEDARRAY`) and can be checked
|
||||
in runtime with the `JERRY_FEATURE_TYPEDARRAY` feature enum value,
|
||||
see: [jerry_is_feature_enabled](#jerry_is_feature_enabled).
|
||||
- Returned value must be freed with [jerry_release_value](#jerry_release_value)
|
||||
when it is no longer needed.
|
||||
|
||||
**Prototype**
|
||||
|
||||
@ -6904,7 +6986,7 @@ jerry_value_t
|
||||
jerry_create_arraybuffer (jerry_length_t size);
|
||||
```
|
||||
|
||||
- `size` - size of the ArrayBuffer to create **in bytes**
|
||||
- `size` - size of the backing store allocated for the array buffer **in bytes**.
|
||||
- return value - the new ArrayBuffer as a `jerry_value_t`
|
||||
|
||||
*New in version 2.0*.
|
||||
@ -6941,29 +7023,31 @@ After the object is not needed the GC will call the `free_cb`
|
||||
so the user can release the buffer which was provided.
|
||||
|
||||
*Note*:
|
||||
- This API depends on the es.next profile.
|
||||
- Returned value must be freed with [jerry_release_value](#jerry_release_value)
|
||||
when it is no longer needed.
|
||||
- This API depends on a build option (`JERRY_BUILTIN_TYPEDARRAY`) and can be checked
|
||||
in runtime with the `JERRY_FEATURE_TYPEDARRAY` feature enum value,
|
||||
see: [jerry_is_feature_enabled](#jerry_is_feature_enabled).
|
||||
- If `buffer_p` is NULL, the buffer is allocated by the allocator callback passed to
|
||||
[jerry_arraybuffer_set_allocator_callbacks](#jerry_arraybuffer_set_allocator_callbacks)
|
||||
- Returned value must be freed with [jerry_release_value](#jerry_release_value)
|
||||
when it is no longer needed.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerry_value_t
|
||||
jerry_create_arraybuffer_external (const jerry_length_t size
|
||||
uint8_t *buffer_p,
|
||||
jerry_value_free_callback_t free_cb);
|
||||
uint8_t *buffer_p, void *arraybuffer_user_p);
|
||||
```
|
||||
|
||||
- `size` - size of the buffer to use **in bytes** (should not be 0)
|
||||
- `buffer_p` - the buffer used for the Array Buffer object (should not be a null pointer)
|
||||
- `free_cb` - the callback function called when the object is released
|
||||
- `size` - size of the buffer **in bytes**.
|
||||
- `buffer_p` - the backing store used by the array buffer object.
|
||||
- `arraybuffer_user_p` - user pointer assigned to the array buffer object.
|
||||
- return value
|
||||
- the new ArrayBuffer as a `jerry_value_t`
|
||||
- if the `size` is zero or `buffer_p` is a null pointer this will return an empty ArrayBuffer.
|
||||
- value of the newly construced array buffer object.
|
||||
|
||||
*New in version 2.0*.
|
||||
|
||||
*Changed in version [[NEXT_RELEASE]]*: type of `free_cb` has been changed.
|
||||
*Changed in version [[NEXT_RELEASE]]*: `free_cb` has been replaced by `arraybuffer_user_p`.
|
||||
|
||||
**Example**
|
||||
|
||||
@ -6995,7 +7079,7 @@ jerry_create_arraybuffer_external (const jerry_length_t size
|
||||
Create a jerry_value_t representing a SharedArrayBuffer object.
|
||||
|
||||
*Note*:
|
||||
- This API depends on the es.next profile.
|
||||
- This API depends on a build option (`JERRY_BUILTIN_SHAREDARRAYBUFFER`).
|
||||
- Returned value must be freed with [jerry_release_value](#jerry_release_value)
|
||||
when it is no longer needed.
|
||||
|
||||
@ -7006,7 +7090,7 @@ jerry_value_t
|
||||
jerry_create_shared_arraybuffer (jerry_length_t size);
|
||||
```
|
||||
|
||||
- `size` - size of the SharedArrayBuffer to create **in bytes**
|
||||
- `size` - size of the backing store allocated for the shared array buffer **in bytes**.
|
||||
- return value - the new SharedArrayBuffer as a `jerry_value_t`
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
@ -7043,7 +7127,9 @@ After the object is not needed the GC will call the `free_cb`
|
||||
so the user can release the buffer which was provided.
|
||||
|
||||
*Note*:
|
||||
- This API depends on the es.next profile.
|
||||
- This API depends on a build option (`JERRY_BUILTIN_SHAREDARRAYBUFFER`).
|
||||
- If `buffer_p` is NULL, the buffer is allocated by the allocator callback passed to
|
||||
[jerry_arraybuffer_set_allocator_callbacks](#jerry_arraybuffer_set_allocator_callbacks)
|
||||
- Returned value must be freed with [jerry_release_value](#jerry_release_value)
|
||||
when it is no longer needed.
|
||||
|
||||
@ -7056,12 +7142,11 @@ jerry_create_shared_arraybuffer_external (const jerry_length_t size
|
||||
jerry_value_free_callback_t free_cb);
|
||||
```
|
||||
|
||||
- `size` - size of the buffer to use **in bytes** (should not be 0)
|
||||
- `buffer_p` - the buffer used for the Shared Array Buffer object (should not be a null pointer)
|
||||
- `free_cb` - the callback function called when the object is released
|
||||
- `size` - size of the buffer **in bytes**.
|
||||
- `buffer_p` - the backing store used by the shared array buffer object.
|
||||
- `arraybuffer_user_p` - user pointer assigned to the shared array buffer object.
|
||||
- return value
|
||||
- the new SharedArrayBuffer as a `jerry_value_t`
|
||||
- if the `size` is zero or `buffer_p` is a null pointer this will return an empty SharedArrayBuffer.
|
||||
- value of the newly construced shared array buffer object.
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
@ -12702,6 +12787,231 @@ jerry_detach_arraybuffer (const jerry_value_t value);
|
||||
|
||||
- [jerry_is_arraybuffer_detachable](#jerry_is_arraybuffer_detachable)
|
||||
|
||||
## jerry_arraybuffer_has_buffer
|
||||
|
||||
**Summary**
|
||||
|
||||
Checks whether a buffer is currently allocated for an array buffer or typed array.
|
||||
|
||||
*Notes*:
|
||||
- This API depends on a build option (`JERRY_BUILTIN_TYPEDARRAY`) and can be checked
|
||||
in runtime with the `JERRY_FEATURE_TYPEDARRAY` feature enum value,
|
||||
see: [jerry_is_feature_enabled](#jerry_is_feature_enabled).
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
bool
|
||||
jerry_arraybuffer_has_buffer (const jerry_value_t value);
|
||||
```
|
||||
|
||||
- `value` - array buffer or typed array value.
|
||||
- return
|
||||
- true, if a buffer is allocated for an array buffer or typed array
|
||||
- false, otherwise
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="compile")
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
jerry_value_t array_buffer_value = jerry_create_arraybuffer (1024 * 1024);
|
||||
|
||||
/* By default, the backing store of large array buffers
|
||||
* is allocated when it is used the first time. */
|
||||
|
||||
if (!jerry_arraybuffer_has_buffer (array_buffer_value))
|
||||
{
|
||||
/* Code enters here in this case. */
|
||||
}
|
||||
|
||||
jerry_release_value (array_buffer_value);
|
||||
|
||||
jerry_cleanup ();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_create_arraybuffer_external](#jerry_create_arraybuffer_external)
|
||||
- [jerry_create_shared_arraybuffer_external](#jerry_create_shared_arraybuffer_external)
|
||||
- [jerry_arraybuffer_set_compact_allocation_limit](#jerry_arraybuffer_set_compact_allocation_limit)
|
||||
- [jerry_arraybuffer_set_allocator_callbacks](#jerry_arraybuffer_set_allocator_callbacks)
|
||||
|
||||
## jerry_arraybuffer_set_compact_allocation_limit
|
||||
|
||||
**Summary**
|
||||
|
||||
Array buffers which size is less or equal than the limit passed to this
|
||||
function are allocated in a single memory block. The allocator callbacks set by
|
||||
[jerry_arraybuffer_set_allocation_callbacks](#jerry_arraybuffer_set_allocation_callbacks)
|
||||
are not called for these array buffers.
|
||||
|
||||
*Notes*:
|
||||
- This API depends on a build option (`JERRY_BUILTIN_TYPEDARRAY`) and can be checked
|
||||
in runtime with the `JERRY_FEATURE_TYPEDARRAY` feature enum value,
|
||||
see: [jerry_is_feature_enabled](#jerry_is_feature_enabled).
|
||||
- The default limit is 256 bytes.
|
||||
- When an array buffer is allocated in a single memory block, its
|
||||
backing store is not freed when the array buffer is detached.
|
||||
- This limit does not affect shared array buffers, their backing store is always
|
||||
allocated by the allocator callback.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
void
|
||||
jerry_arraybuffer_set_compact_allocation_limit (const jerry_length_t allocation_limit);
|
||||
```
|
||||
|
||||
- `allocation_limit` - maximum size of compact allocation.
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="compile")
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
jerry_arraybuffer_set_compact_allocation_limit (1);
|
||||
|
||||
jerry_value_t array_buffer_value = jerry_create_arraybuffer (1);
|
||||
|
||||
if (jerry_arraybuffer_has_buffer (array_buffer_value))
|
||||
{
|
||||
/* Code enters here because the backing store
|
||||
* is allocated during buffer creation. */
|
||||
}
|
||||
|
||||
jerry_release_value (array_buffer_value);
|
||||
|
||||
array_buffer_value = jerry_create_arraybuffer (2);
|
||||
|
||||
if (jerry_arraybuffer_has_buffer (array_buffer_value))
|
||||
{
|
||||
/* Code does not enter here because the backing store
|
||||
* is allocated when it is used the first time. */
|
||||
}
|
||||
|
||||
jerry_release_value (array_buffer_value);
|
||||
|
||||
jerry_cleanup ();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_arraybuffer_has_buffer](#jerry_arraybuffer_has_buffer)
|
||||
- [jerry_arraybuffer_set_allocator_callbacks](#jerry_arraybuffer_set_allocator_callbacks)
|
||||
|
||||
## jerry_arraybuffer_set_allocator_callbacks
|
||||
|
||||
**Summary**
|
||||
|
||||
Set callbacks for allocating and freeing backing stores for array buffer objects.
|
||||
|
||||
*Notes*:
|
||||
- This API depends on a build option (`JERRY_BUILTIN_TYPEDARRAY`) and can be checked
|
||||
in runtime with the `JERRY_FEATURE_TYPEDARRAY` feature enum value,
|
||||
see: [jerry_is_feature_enabled](#jerry_is_feature_enabled).
|
||||
- This function is recommended to be called after [jerry_init](#jerry_init) before
|
||||
any array buffer is allocated.
|
||||
- The callbacks can be NULL to use the default callbacks. The default `allocate_callback`
|
||||
allocates memory using [jerry_heap_alloc](#jerry_heap_alloc) and the default
|
||||
`free_callback` frees memory using [jerry_heap_free](#jerry_heap_free).
|
||||
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
void
|
||||
jerry_arraybuffer_set_allocator_callbacks (jerry_arraybuffer_allocate_t allocate_callback,
|
||||
jerry_arraybuffer_free_t free_callback,
|
||||
void *user_p)
|
||||
```
|
||||
|
||||
- `allocate_callback` - callback for allocating array buffer memory.
|
||||
- `free_callback` - callback for freeing array buffer memory.
|
||||
- `user_p` - user pointer passed to the callbacks.
|
||||
|
||||
*New in version [[NEXT_RELEASE]]*.
|
||||
|
||||
**Example**
|
||||
|
||||
[doctest]: # (test="compile")
|
||||
|
||||
```c
|
||||
#include "jerryscript.h"
|
||||
|
||||
static uint8_t global_buffer[64];
|
||||
|
||||
static void
|
||||
array_buffer_free_cb (jerry_arraybuffer_type_t buffer_type, /**< type of the array buffer object */
|
||||
uint8_t *buffer_p, /**< pointer to the allocated buffer */
|
||||
uint32_t buffer_size, /**< size of the allocated buffer */
|
||||
void *arraybuffer_user_p, /**< user pointer assigned to the array buffer object */
|
||||
void *user_p) /**< user pointer passed to jerry_arraybuffer_set_allocation_callbacks */
|
||||
{
|
||||
(void) buffer_type;
|
||||
(void) user_p;
|
||||
|
||||
/* As for this example, only the free callback is redirected. This callback
|
||||
* function does not free the memory if the arraybuffer_user_p is non-NULL. */
|
||||
|
||||
if (arraybuffer_user_p == NULL)
|
||||
{
|
||||
jerry_heap_free (buffer_p, buffer_size);
|
||||
}
|
||||
} /* array_buffer_free_cb */
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
jerry_init (JERRY_INIT_EMPTY);
|
||||
|
||||
jerry_arraybuffer_set_allocator_callbacks (NULL, array_buffer_free_cb, NULL);
|
||||
|
||||
/* The buffer of the array buffer object is allocated by the default
|
||||
* allocator using jerry_heap_alloc and freed by array_buffer_free_cb. */
|
||||
|
||||
const jerry_char_t script[] = "var result = new uint32Array(1024); result[0] = 1; result";
|
||||
jerry_value_t array_buffer_value = jerry_eval (script, sizeof (script) - 1, JERRY_PARSE_NO_OPTS);
|
||||
jerry_release_value (array_buffer_value);
|
||||
|
||||
/* The buffer of the array buffer object has a non-NULL
|
||||
* arraybuffer_user_p value, so it is not freed by array_buffer_free_cb. */
|
||||
|
||||
array_buffer_value = jerry_create_arraybuffer_external (sizeof (global_buffer), global_buffer, global_buffer);
|
||||
jerry_release_value (array_buffer_value);
|
||||
|
||||
jerry_cleanup ();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_arraybuffer_has_buffer](#jerry_arraybuffer_has_buffer)
|
||||
- [jerry_arraybuffer_set_allocator_callbacks](#jerry_arraybuffer_set_allocator_callbacks)
|
||||
|
||||
## jerry_get_dataview_buffer
|
||||
|
||||
**Summary**
|
||||
|
||||
@ -5923,7 +5923,8 @@ jerry_value_is_arraybuffer (const jerry_value_t value) /**< value to check if it
|
||||
* @return value of the constructed ArrayBuffer object
|
||||
*/
|
||||
jerry_value_t
|
||||
jerry_create_arraybuffer (const jerry_length_t size) /**< size of the ArrayBuffer to create */
|
||||
jerry_create_arraybuffer (const jerry_length_t size) /**< size of the backing store allocated
|
||||
* for the array buffer in bytes */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
@ -5944,32 +5945,41 @@ jerry_create_arraybuffer (const jerry_length_t size) /**< size of the ArrayBuffe
|
||||
* * if the typed arrays are disabled this will return a TypeError.
|
||||
* * if the size is zero or buffer_p is a null pointer this will return an empty ArrayBuffer.
|
||||
*
|
||||
* @return value of the construced ArrayBuffer object
|
||||
* @return value of the newly construced array buffer object
|
||||
*/
|
||||
jerry_value_t
|
||||
jerry_create_arraybuffer_external (const jerry_length_t size, /**< size of the buffer to used */
|
||||
uint8_t *buffer_p, /**< buffer to use as the ArrayBuffer's backing */
|
||||
jerry_value_free_callback_t free_cb) /**< buffer free callback */
|
||||
jerry_create_arraybuffer_external (const jerry_length_t size, /**< size of the buffer in bytes */
|
||||
uint8_t *buffer_p, /**< the backing store used by the array buffer object */
|
||||
void *arraybuffer_user_p) /**< user pointer assigned to the array buffer object */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
#if JERRY_BUILTIN_TYPEDARRAY
|
||||
ecma_object_t *arraybuffer;
|
||||
ecma_object_t *arraybuffer_p;
|
||||
|
||||
if (JERRY_UNLIKELY (size == 0 || buffer_p == NULL))
|
||||
if (JERRY_UNLIKELY (size == 0))
|
||||
{
|
||||
arraybuffer = ecma_arraybuffer_new_object (0);
|
||||
arraybuffer_p = ecma_arraybuffer_new_object (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
arraybuffer = ecma_arraybuffer_new_object_external (size, buffer_p, free_cb);
|
||||
arraybuffer_p = ecma_arraybuffer_create_object_with_buffer (ECMA_OBJECT_CLASS_ARRAY_BUFFER, size);
|
||||
|
||||
ecma_arraybuffer_pointer_t *arraybuffer_pointer_p = (ecma_arraybuffer_pointer_t *) arraybuffer_p;
|
||||
arraybuffer_pointer_p->arraybuffer_user_p = arraybuffer_user_p;
|
||||
|
||||
if (buffer_p != NULL)
|
||||
{
|
||||
arraybuffer_pointer_p->extended_object.u.cls.u1.array_buffer_flags |= ECMA_ARRAYBUFFER_ALLOCATED;
|
||||
arraybuffer_pointer_p->buffer_p = buffer_p;
|
||||
}
|
||||
}
|
||||
|
||||
return jerry_return (ecma_make_object_value (arraybuffer));
|
||||
return jerry_return (ecma_make_object_value (arraybuffer_p));
|
||||
#else /* !JERRY_BUILTIN_TYPEDARRAY */
|
||||
JERRY_UNUSED (size);
|
||||
JERRY_UNUSED (buffer_p);
|
||||
JERRY_UNUSED (free_cb);
|
||||
JERRY_UNUSED (arraybuffer_user_p);
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_typed_array_not_supported_p)));
|
||||
#endif /* JERRY_BUILTIN_TYPEDARRAY */
|
||||
} /* jerry_create_arraybuffer_external */
|
||||
@ -5999,7 +6009,8 @@ jerry_value_is_shared_arraybuffer (const jerry_value_t value) /**< value to chec
|
||||
* @return value of the constructed SharedArrayBuffer object
|
||||
*/
|
||||
jerry_value_t
|
||||
jerry_create_shared_arraybuffer (const jerry_length_t size) /**< size of the SharedArrayBuffer to create */
|
||||
jerry_create_shared_arraybuffer (const jerry_length_t size) /**< size of the backing store allocated
|
||||
* for the shared array buffer in bytes */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
@ -6020,32 +6031,43 @@ jerry_create_shared_arraybuffer (const jerry_length_t size) /**< size of the Sha
|
||||
* * if the typed arrays are disabled this will return a TypeError.
|
||||
* * if the size is zero or buffer_p is a null pointer this will return an empty SharedArrayBuffer.
|
||||
*
|
||||
* @return value of the construced SharedArrayBuffer object
|
||||
* @return value of the newly construced shared array buffer object
|
||||
*/
|
||||
jerry_value_t
|
||||
jerry_create_shared_arraybuffer_external (const jerry_length_t size, /**< size of the buffer to used */
|
||||
uint8_t *buffer_p, /**< buffer to use as the SharedArrayBuffer's backing */
|
||||
jerry_value_free_callback_t free_cb) /**< buffer free callback */
|
||||
jerry_create_shared_arraybuffer_external (const jerry_length_t size, /**< size of the buffer in bytes */
|
||||
uint8_t *buffer_p, /**< the backing store used by the
|
||||
* shared array buffer object */
|
||||
void *arraybuffer_user_p) /**< user pointer assigned to the
|
||||
* shared array buffer object */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
#if JERRY_BUILTIN_SHAREDARRAYBUFFER
|
||||
ecma_object_t *shared_arraybuffer;
|
||||
ecma_object_t *shared_arraybuffer_p;
|
||||
|
||||
if (JERRY_UNLIKELY (size == 0 || buffer_p == NULL))
|
||||
if (JERRY_UNLIKELY (size == 0))
|
||||
{
|
||||
shared_arraybuffer = ecma_shared_arraybuffer_new_object (0);
|
||||
shared_arraybuffer_p = ecma_shared_arraybuffer_new_object (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
shared_arraybuffer = ecma_shared_arraybuffer_new_object_external (size, buffer_p, free_cb);
|
||||
shared_arraybuffer_p = ecma_arraybuffer_create_object_with_buffer (ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER, size);
|
||||
|
||||
ecma_arraybuffer_pointer_t *shared_arraybuffer_pointer_p = (ecma_arraybuffer_pointer_t *) shared_arraybuffer_p;
|
||||
shared_arraybuffer_pointer_p->arraybuffer_user_p = arraybuffer_user_p;
|
||||
|
||||
if (buffer_p != NULL)
|
||||
{
|
||||
shared_arraybuffer_pointer_p->extended_object.u.cls.u1.array_buffer_flags |= ECMA_ARRAYBUFFER_ALLOCATED;
|
||||
shared_arraybuffer_pointer_p->buffer_p = buffer_p;
|
||||
}
|
||||
}
|
||||
|
||||
return jerry_return (ecma_make_object_value (shared_arraybuffer));
|
||||
return jerry_return (ecma_make_object_value (shared_arraybuffer_p));
|
||||
#else /* !JERRY_BUILTIN_SHAREDARRAYBUFFER */
|
||||
JERRY_UNUSED (size);
|
||||
JERRY_UNUSED (buffer_p);
|
||||
JERRY_UNUSED (free_cb);
|
||||
JERRY_UNUSED (arraybuffer_user_p);
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_shared_arraybuffer_not_supported_p)));
|
||||
#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */
|
||||
} /* jerry_create_shared_arraybuffer_external */
|
||||
@ -6073,6 +6095,13 @@ jerry_arraybuffer_write (const jerry_value_t value, /**< target ArrayBuffer or S
|
||||
}
|
||||
|
||||
ecma_object_t *buffer_p = ecma_get_object_from_value (value);
|
||||
|
||||
if (ECMA_ARRAYBUFFER_CHECK_BUFFER_ERROR (buffer_p))
|
||||
{
|
||||
jerry_release_value (jcontext_take_exception ());
|
||||
return 0;
|
||||
}
|
||||
|
||||
jerry_length_t length = ecma_arraybuffer_get_length (buffer_p);
|
||||
|
||||
if (offset >= length)
|
||||
@ -6122,6 +6151,13 @@ jerry_arraybuffer_read (const jerry_value_t value, /**< ArrayBuffer or SharedArr
|
||||
}
|
||||
|
||||
ecma_object_t *buffer_p = ecma_get_object_from_value (value);
|
||||
|
||||
if (ECMA_ARRAYBUFFER_CHECK_BUFFER_ERROR (buffer_p))
|
||||
{
|
||||
jerry_release_value (jcontext_take_exception ());
|
||||
return 0;
|
||||
}
|
||||
|
||||
jerry_length_t length = ecma_arraybuffer_get_length (buffer_p);
|
||||
|
||||
if (offset >= length)
|
||||
@ -6191,15 +6227,19 @@ jerry_get_arraybuffer_pointer (const jerry_value_t array_buffer) /**< Array Buff
|
||||
jerry_assert_api_available ();
|
||||
|
||||
#if JERRY_BUILTIN_TYPEDARRAY
|
||||
if (ecma_is_value_error_reference (array_buffer)
|
||||
|| !(ecma_is_arraybuffer (array_buffer) || ecma_is_shared_arraybuffer (array_buffer)))
|
||||
if (!(ecma_is_arraybuffer (array_buffer) || ecma_is_shared_arraybuffer (array_buffer)))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ecma_object_t *buffer_p = ecma_get_object_from_value (array_buffer);
|
||||
lit_utf8_byte_t *mem_buffer_p = ecma_arraybuffer_get_buffer (buffer_p);
|
||||
return (uint8_t *const) mem_buffer_p;
|
||||
|
||||
if (!(ECMA_ARRAYBUFFER_GET_FLAGS (buffer_p) & ECMA_ARRAYBUFFER_ALLOCATED))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (uint8_t *) ecma_arraybuffer_get_buffer (buffer_p);
|
||||
#else /* !JERRY_BUILTIN_TYPEDARRAY */
|
||||
JERRY_UNUSED (array_buffer);
|
||||
#endif /* JERRY_BUILTIN_TYPEDARRAY */
|
||||
@ -6222,7 +6262,7 @@ jerry_is_arraybuffer_detachable (const jerry_value_t value) /**< ArrayBuffer */
|
||||
if (ecma_is_arraybuffer (value))
|
||||
{
|
||||
ecma_object_t *buffer_p = ecma_get_object_from_value (value);
|
||||
return ecma_arraybuffer_is_detached (buffer_p) ? ECMA_VALUE_FALSE : ECMA_VALUE_TRUE;
|
||||
return ecma_make_boolean_value (!ecma_arraybuffer_is_detached (buffer_p));
|
||||
}
|
||||
#else /* !JERRY_BUILTIN_TYPEDARRAY */
|
||||
JERRY_UNUSED (value);
|
||||
@ -6233,8 +6273,8 @@ jerry_is_arraybuffer_detachable (const jerry_value_t value) /**< ArrayBuffer */
|
||||
/**
|
||||
* Detach the underlying data block from ArrayBuffer and set its bytelength to 0.
|
||||
*
|
||||
* Note: If the ArrayBuffer has been created with `jerry_create_arraybuffer_external`
|
||||
* the optional free callback is called on a successful detach operation
|
||||
* Note: if the ArrayBuffer has a separate data buffer, the free callback set by
|
||||
* jerry_arraybuffer_set_allocation_callbacks is called for this buffer
|
||||
*
|
||||
* @return null value - if success
|
||||
* value marked with error flag - otherwise
|
||||
@ -6260,6 +6300,83 @@ jerry_detach_arraybuffer (const jerry_value_t value) /**< ArrayBuffer */
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Expected an ArrayBuffer")));
|
||||
} /* jerry_detach_arraybuffer */
|
||||
|
||||
/**
|
||||
* Checks whether a buffer is currently allocated for an array buffer or typed array.
|
||||
*
|
||||
* @return true, if a buffer is allocated for an array buffer or typed array
|
||||
* false, otherwise
|
||||
*/
|
||||
bool
|
||||
jerry_arraybuffer_has_buffer (const jerry_value_t value) /**< array buffer or typed array value */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
#if JERRY_BUILTIN_TYPEDARRAY
|
||||
if (!ecma_is_value_object (value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ecma_object_t *object_p = ecma_get_object_from_value (value);
|
||||
|
||||
if (ecma_object_is_typedarray (object_p))
|
||||
{
|
||||
object_p = ecma_typedarray_get_arraybuffer (object_p);
|
||||
}
|
||||
else if (!(ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER)
|
||||
|| ecma_object_is_shared_arraybuffer (object_p)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return (ECMA_ARRAYBUFFER_GET_FLAGS (object_p) & ECMA_ARRAYBUFFER_ALLOCATED) != 0;
|
||||
#else /* !JERRY_BUILTIN_TYPEDARRAY */
|
||||
JERRY_UNUSED (value);
|
||||
return false;
|
||||
#endif /* JERRY_BUILTIN_TYPEDARRAY */
|
||||
} /* jerry_arraybuffer_has_buffer */
|
||||
|
||||
/**
|
||||
* Array buffers which size is less or equal than the limit passed to this function are allocated in
|
||||
* a single memory block. The allocator callbacks set by jerry_arraybuffer_set_allocation_callbacks
|
||||
* are not called for these array buffers. The default limit is 256 bytes.
|
||||
*/
|
||||
void
|
||||
jerry_arraybuffer_set_compact_allocation_limit (const jerry_length_t allocation_limit) /**< maximum size of
|
||||
* compact allocation */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
#if JERRY_BUILTIN_TYPEDARRAY
|
||||
JERRY_CONTEXT (arraybuffer_compact_allocation_limit) = allocation_limit;
|
||||
#else /* !JERRY_BUILTIN_TYPEDARRAY */
|
||||
JERRY_UNUSED (allocation_limit);
|
||||
#endif /* JERRY_BUILTIN_TYPEDARRAY */
|
||||
} /* jerry_arraybuffer_set_compact_allocation_limit */
|
||||
|
||||
/**
|
||||
* Set callbacks for allocating and freeing backing stores for array buffer objects.
|
||||
*/
|
||||
void
|
||||
jerry_arraybuffer_set_allocator_callbacks (jerry_arraybuffer_allocate_t allocate_callback, /**< callback for allocating
|
||||
* array buffer memory */
|
||||
jerry_arraybuffer_free_t free_callback, /**< callback for freeing
|
||||
* array buffer memory */
|
||||
void *user_p) /**< user pointer passed to the callbacks */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
#if JERRY_BUILTIN_TYPEDARRAY
|
||||
JERRY_CONTEXT (arraybuffer_allocate_callback) = allocate_callback;
|
||||
JERRY_CONTEXT (arraybuffer_free_callback) = free_callback;
|
||||
JERRY_CONTEXT (arraybuffer_allocate_callback_user_p) = user_p;
|
||||
#else /* !JERRY_BUILTIN_TYPEDARRAY */
|
||||
JERRY_UNUSED (allocate_callback);
|
||||
JERRY_UNUSED (free_callback);
|
||||
JERRY_UNUSED (user_p);
|
||||
#endif /* JERRY_BUILTIN_TYPEDARRAY */
|
||||
} /* jerry_arraybuffer_set_allocator_callbacks */
|
||||
|
||||
/**
|
||||
* DataView related functions
|
||||
*/
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
|
||||
#include "ecma-alloc.h"
|
||||
#include "ecma-array-object.h"
|
||||
#include "ecma-arraybuffer-object.h"
|
||||
#include "ecma-builtin-handlers.h"
|
||||
#include "ecma-container-object.h"
|
||||
#include "ecma-function-object.h"
|
||||
@ -1854,25 +1855,18 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
|
||||
case ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER:
|
||||
#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */
|
||||
{
|
||||
uint32_t arraybuffer_length = ext_object_p->u.cls.u3.length;
|
||||
|
||||
if (ECMA_ARRAYBUFFER_HAS_EXTERNAL_MEMORY (ext_object_p))
|
||||
if (!(ECMA_ARRAYBUFFER_GET_FLAGS (ext_object_p) & ECMA_ARRAYBUFFER_HAS_POINTER))
|
||||
{
|
||||
ext_object_size = sizeof (ecma_arraybuffer_external_info);
|
||||
|
||||
/* Call external free callback if any. */
|
||||
ecma_arraybuffer_external_info *array_p = (ecma_arraybuffer_external_info *) ext_object_p;
|
||||
|
||||
if (array_p->free_cb != NULL)
|
||||
{
|
||||
array_p->free_cb (array_p->buffer_p);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ext_object_size += arraybuffer_length;
|
||||
ext_object_size += ext_object_p->u.cls.u3.length;
|
||||
break;
|
||||
}
|
||||
|
||||
ext_object_size = sizeof (ecma_arraybuffer_pointer_t);
|
||||
|
||||
if (ECMA_ARRAYBUFFER_GET_FLAGS (ext_object_p) & ECMA_ARRAYBUFFER_ALLOCATED)
|
||||
{
|
||||
ecma_arraybuffer_release_buffer (object_p);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif /* JERRY_BUILTIN_TYPEDARRAY */
|
||||
|
||||
@ -2084,35 +2084,24 @@ typedef enum
|
||||
} ecma_typedarray_flag_t;
|
||||
|
||||
/**
|
||||
* ArrayBuffers flags.
|
||||
* Array buffer flags.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ECMA_ARRAYBUFFER_INTERNAL_MEMORY = 0u, /* ArrayBuffer memory is handled internally. */
|
||||
ECMA_ARRAYBUFFER_EXTERNAL_MEMORY = (1u << 0), /* ArrayBuffer created via jerry_create_arraybuffer_external. */
|
||||
ECMA_ARRAYBUFFER_DETACHED = (1u << 1), /* ArrayBuffer has been detached */
|
||||
ECMA_ARRAYBUFFER_HAS_POINTER = (1u << 0), /* ArrayBuffer has a buffer pointer. */
|
||||
ECMA_ARRAYBUFFER_ALLOCATED = (1u << 1), /* ArrayBuffer memory is allocated */
|
||||
ECMA_ARRAYBUFFER_DETACHED = (1u << 2), /* ArrayBuffer has been detached */
|
||||
} ecma_arraybuffer_flag_t;
|
||||
|
||||
/**
|
||||
* Check whether the ArrayBuffer has external underlying buffer
|
||||
*/
|
||||
#define ECMA_ARRAYBUFFER_HAS_EXTERNAL_MEMORY(object_p) \
|
||||
((((ecma_extended_object_t *) object_p)->u.cls.u1.array_buffer_flags & ECMA_ARRAYBUFFER_EXTERNAL_MEMORY) != 0)
|
||||
|
||||
/**
|
||||
* Struct to store information for ArrayBuffers with external memory.
|
||||
*
|
||||
* The following elements are stored in Jerry memory.
|
||||
*
|
||||
* buffer_p - pointer to the external memory.
|
||||
* free_cb - pointer to a callback function which is called when the ArrayBuffer is freed.
|
||||
* Structure for array buffers with a backing store pointer.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
ecma_extended_object_t extended_object; /**< extended object part */
|
||||
void *buffer_p; /**< external buffer pointer */
|
||||
jerry_value_free_callback_t free_cb; /**< the free callback for the above buffer pointer */
|
||||
} ecma_arraybuffer_external_info;
|
||||
void *buffer_p; /**< pointer to the backing store of the array buffer object */
|
||||
void *arraybuffer_user_p; /**< user pointer passed to the free callback */
|
||||
} ecma_arraybuffer_pointer_t;
|
||||
|
||||
/**
|
||||
* Some internal properties of TypedArray object.
|
||||
@ -2132,10 +2121,6 @@ typedef struct
|
||||
typedef struct
|
||||
{
|
||||
ecma_object_t *array_buffer_p; /**< pointer to the typedArray's [[ViewedArrayBuffer]] internal slot */
|
||||
lit_utf8_byte_t *buffer_p; /**< pointer to the underlying raw data buffer.
|
||||
* Note:
|
||||
* - This address is increased by the [ByteOffset]] internal property.
|
||||
* - This address must be used during indexed read/write operation. */
|
||||
ecma_typedarray_type_t id; /**< [[TypedArrayName]] internal slot */
|
||||
uint32_t length; /**< [[ByteLength]] internal slot */
|
||||
uint32_t offset; /**< [[ByteOffset]] internal slot. */
|
||||
|
||||
@ -63,6 +63,10 @@ ecma_init (void)
|
||||
#if JERRY_ESNEXT
|
||||
JERRY_CONTEXT (current_new_target_p) = NULL;
|
||||
#endif /* JERRY_ESNEXT */
|
||||
|
||||
#if JERRY_BUILTIN_TYPEDARRAY
|
||||
JERRY_CONTEXT (arraybuffer_compact_allocation_limit) = 256;
|
||||
#endif /* JERRY_BUILTIN_TYPEDARRAY */
|
||||
} /* ecma_init */
|
||||
|
||||
/**
|
||||
|
||||
@ -130,15 +130,15 @@ ecma_builtin_typedarray_prototype_exec_routine (ecma_value_t this_arg, /**< this
|
||||
JERRY_ASSERT (mode < TYPEDARRAY_ROUTINE__COUNT);
|
||||
|
||||
ecma_typedarray_getter_fn_t typedarray_getter_cb = ecma_get_typedarray_getter_fn (info_p->id);
|
||||
|
||||
ecma_object_t *func_object_p = ecma_get_object_from_value (cb_func_val);
|
||||
uint8_t *buffer_p = ecma_arraybuffer_get_buffer (info_p->array_buffer_p) + info_p->offset;
|
||||
uint32_t byte_pos = 0;
|
||||
ecma_value_t ret_value = ECMA_VALUE_EMPTY;
|
||||
|
||||
for (uint32_t index = 0; index < info_p->length && ecma_is_value_empty (ret_value); index++)
|
||||
{
|
||||
ecma_value_t current_index = ecma_make_uint32_value (index);
|
||||
ecma_value_t element = typedarray_getter_cb (info_p->buffer_p + byte_pos);
|
||||
ecma_value_t element = typedarray_getter_cb (buffer_p + byte_pos);
|
||||
|
||||
ecma_value_t call_args[] = { element, current_index, this_arg };
|
||||
|
||||
@ -221,17 +221,31 @@ ecma_builtin_typedarray_prototype_map (ecma_value_t this_arg, /**< this object *
|
||||
}
|
||||
|
||||
ecma_object_t *target_obj_p = ecma_get_object_from_value (new_typedarray);
|
||||
uint8_t *src_buffer_p = ecma_typedarray_get_buffer (src_info_p);
|
||||
|
||||
if (JERRY_UNLIKELY (src_buffer_p == NULL))
|
||||
{
|
||||
ecma_deref_object (target_obj_p);
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
ecma_typedarray_info_t target_info = ecma_typedarray_get_info (target_obj_p);
|
||||
uint8_t *target_buffer_p = ecma_typedarray_get_buffer (&target_info);
|
||||
|
||||
if (JERRY_UNLIKELY (target_buffer_p == NULL))
|
||||
{
|
||||
ecma_deref_object (target_obj_p);
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
ecma_typedarray_getter_fn_t src_typedarray_getter_cb = ecma_get_typedarray_getter_fn (src_info_p->id);
|
||||
ecma_typedarray_setter_fn_t target_typedarray_setter_cb = ecma_get_typedarray_setter_fn (target_info.id);
|
||||
|
||||
uint32_t src_byte_pos = 0;
|
||||
|
||||
for (uint32_t index = 0; index < src_info_p->length; index++)
|
||||
{
|
||||
ecma_value_t current_index = ecma_make_uint32_value (index);
|
||||
ecma_value_t element = src_typedarray_getter_cb (src_info_p->buffer_p + src_byte_pos);
|
||||
ecma_value_t element = src_typedarray_getter_cb (src_buffer_p);
|
||||
src_buffer_p += src_info_p->element_size;
|
||||
|
||||
ecma_value_t call_args[] = { element, current_index, this_arg };
|
||||
ecma_value_t mapped_value = ecma_op_function_call (func_object_p, cb_this_arg, call_args, 3);
|
||||
@ -252,8 +266,8 @@ ecma_builtin_typedarray_prototype_map (ecma_value_t this_arg, /**< this object *
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_arraybuffer_is_detached));
|
||||
}
|
||||
|
||||
uint32_t target_byte_pos = index << target_info.shift;
|
||||
ecma_value_t set_element = target_typedarray_setter_cb (target_info.buffer_p + target_byte_pos, mapped_value);
|
||||
ecma_value_t set_element = target_typedarray_setter_cb (target_buffer_p, mapped_value);
|
||||
target_buffer_p += target_info.element_size;
|
||||
ecma_free_value (mapped_value);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (set_element))
|
||||
@ -261,8 +275,6 @@ ecma_builtin_typedarray_prototype_map (ecma_value_t this_arg, /**< this object *
|
||||
ecma_free_value (new_typedarray);
|
||||
return set_element;
|
||||
}
|
||||
|
||||
src_byte_pos += src_info_p->element_size;
|
||||
}
|
||||
|
||||
return new_typedarray;
|
||||
@ -299,11 +311,12 @@ ecma_builtin_typedarray_prototype_reduce_with_direction (ecma_value_t this_arg,
|
||||
|
||||
ecma_value_t accumulator = ECMA_VALUE_UNDEFINED;
|
||||
uint32_t index = is_right ? (info_p->length - 1) : 0;
|
||||
uint8_t *buffer_p = ecma_arraybuffer_get_buffer (info_p->array_buffer_p) + info_p->offset;
|
||||
|
||||
if (ecma_is_value_undefined (arguments_list_p[1]))
|
||||
{
|
||||
byte_pos = index << info_p->shift;
|
||||
accumulator = getter_cb (info_p->buffer_p + byte_pos);
|
||||
accumulator = getter_cb (buffer_p + byte_pos);
|
||||
|
||||
if (is_right)
|
||||
{
|
||||
@ -335,7 +348,7 @@ ecma_builtin_typedarray_prototype_reduce_with_direction (ecma_value_t this_arg,
|
||||
{
|
||||
ecma_value_t current_index = ecma_make_uint32_value (index);
|
||||
byte_pos = index << info_p->shift;
|
||||
ecma_value_t get_value = getter_cb (info_p->buffer_p + byte_pos);
|
||||
ecma_value_t get_value = getter_cb (buffer_p + byte_pos);
|
||||
|
||||
ecma_value_t call_args[] = { accumulator, get_value, current_index, this_arg };
|
||||
|
||||
@ -413,12 +426,12 @@ ecma_builtin_typedarray_prototype_filter (ecma_value_t this_arg, /**< this objec
|
||||
}
|
||||
|
||||
ecma_collection_t *collected_p = ecma_new_collection ();
|
||||
uint32_t byte_pos = 0;
|
||||
uint8_t *buffer_p = ecma_arraybuffer_get_buffer (info_p->array_buffer_p) + info_p->offset;
|
||||
|
||||
for (uint32_t index = 0; index < info_p->length; index++)
|
||||
{
|
||||
ecma_value_t current_index = ecma_make_uint32_value (index);
|
||||
ecma_value_t get_value = getter_cb (info_p->buffer_p + byte_pos);
|
||||
ecma_value_t get_value = getter_cb (buffer_p);
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_number (get_value) || ecma_is_value_bigint (get_value));
|
||||
|
||||
@ -451,7 +464,7 @@ ecma_builtin_typedarray_prototype_filter (ecma_value_t this_arg, /**< this objec
|
||||
ecma_fast_free_value (get_value);
|
||||
}
|
||||
|
||||
byte_pos += info_p->element_size;
|
||||
buffer_p += info_p->element_size;
|
||||
ecma_fast_free_value (call_value);
|
||||
}
|
||||
|
||||
@ -461,24 +474,35 @@ ecma_builtin_typedarray_prototype_filter (ecma_value_t this_arg, /**< this objec
|
||||
|
||||
if (!ECMA_IS_VALUE_ERROR (ret_value))
|
||||
{
|
||||
ecma_object_t *obj_p = ecma_get_object_from_value (ret_value);
|
||||
ecma_typedarray_info_t target_info = ecma_typedarray_get_info (obj_p);
|
||||
ecma_object_t *new_typedarray_p = ecma_get_object_from_value (ret_value);
|
||||
ecma_typedarray_info_t target_info = ecma_typedarray_get_info (new_typedarray_p);
|
||||
|
||||
JERRY_ASSERT (target_info.offset == 0);
|
||||
|
||||
uint8_t *target_buffer_p = ecma_typedarray_get_buffer (&target_info);
|
||||
|
||||
if (JERRY_UNLIKELY (target_buffer_p == NULL))
|
||||
{
|
||||
ecma_deref_object (new_typedarray_p);
|
||||
ret_value = ECMA_VALUE_ERROR;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ecma_typedarray_setter_fn_t target_typedarray_setter_cb = ecma_get_typedarray_setter_fn (target_info.id);
|
||||
uint32_t target_byte_index = 0;
|
||||
|
||||
for (uint32_t idx = 0; idx < collected_p->item_count; idx++)
|
||||
{
|
||||
ecma_value_t set_element = target_typedarray_setter_cb (target_info.buffer_p + target_byte_index,
|
||||
ecma_value_t set_element = target_typedarray_setter_cb (target_buffer_p,
|
||||
collected_p->buffer_p[idx]);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (set_element))
|
||||
{
|
||||
ecma_deref_object (new_typedarray_p);
|
||||
ret_value = ECMA_VALUE_ERROR;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
target_byte_index += target_info.element_size;
|
||||
target_buffer_p += target_info.element_size;
|
||||
}
|
||||
}
|
||||
|
||||
@ -501,16 +525,17 @@ static ecma_value_t
|
||||
ecma_builtin_typedarray_prototype_reverse (ecma_value_t this_arg, /**< this argument */
|
||||
ecma_typedarray_info_t *info_p) /**< object info */
|
||||
{
|
||||
uint8_t *buffer_p = ecma_arraybuffer_get_buffer (info_p->array_buffer_p) + info_p->offset;
|
||||
uint32_t middle = (info_p->length / 2) << info_p->shift;
|
||||
uint32_t buffer_last = (info_p->length << info_p->shift) - info_p->element_size;
|
||||
|
||||
for (uint32_t lower = 0; lower < middle; lower += info_p->element_size)
|
||||
{
|
||||
uint32_t upper = buffer_last - lower;
|
||||
lit_utf8_byte_t *lower_p = info_p->buffer_p + lower;
|
||||
lit_utf8_byte_t *upper_p = info_p->buffer_p + upper;
|
||||
uint8_t *lower_p = buffer_p + lower;
|
||||
uint8_t *upper_p = buffer_p + upper;
|
||||
|
||||
lit_utf8_byte_t tmp[8];
|
||||
uint8_t tmp[8];
|
||||
memcpy (&tmp[0], lower_p, info_p->element_size);
|
||||
memcpy (lower_p, upper_p, info_p->element_size);
|
||||
memcpy (upper_p, &tmp[0], info_p->element_size);
|
||||
@ -546,22 +571,22 @@ ecma_op_typedarray_set_with_typedarray (ecma_value_t this_arg, /**< this argumen
|
||||
}
|
||||
|
||||
ecma_object_t *target_typedarray_p = ecma_get_object_from_value (this_arg);
|
||||
ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (target_typedarray_p);
|
||||
if (ecma_arraybuffer_is_detached (arraybuffer_p))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_arraybuffer_is_detached));
|
||||
}
|
||||
|
||||
ecma_typedarray_info_t target_info = ecma_typedarray_get_info (target_typedarray_p);
|
||||
uint8_t *target_buffer_p = ecma_typedarray_get_buffer (&target_info);
|
||||
|
||||
if (JERRY_UNLIKELY (target_buffer_p == NULL))
|
||||
{
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
ecma_object_t *src_typedarray_p = ecma_get_object_from_value (arr_val);
|
||||
ecma_object_t *src_arraybuffer_p = ecma_typedarray_get_arraybuffer (src_typedarray_p);
|
||||
if (ecma_arraybuffer_is_detached (src_arraybuffer_p))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_arraybuffer_is_detached));
|
||||
}
|
||||
|
||||
ecma_typedarray_info_t src_info = ecma_typedarray_get_info (src_typedarray_p);
|
||||
uint8_t *src_buffer_p = ecma_typedarray_get_buffer (&src_info);
|
||||
|
||||
if (JERRY_UNLIKELY (src_buffer_p == NULL))
|
||||
{
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
uint32_t target_offset_uint32 = ecma_number_to_uint32 (target_offset_num);
|
||||
|
||||
@ -577,26 +602,25 @@ ecma_op_typedarray_set_with_typedarray (ecma_value_t this_arg, /**< this argumen
|
||||
}
|
||||
|
||||
/* 26. targetByteIndex */
|
||||
uint32_t target_byte_index = target_offset_uint32 * target_info.element_size;
|
||||
target_buffer_p += target_offset_uint32 << target_info.shift;
|
||||
|
||||
/* 27. limit */
|
||||
uint32_t limit = target_byte_index + target_info.element_size * src_info.length;
|
||||
uint32_t limit = src_info.length << target_info.shift;
|
||||
|
||||
if (src_info.id == target_info.id)
|
||||
{
|
||||
memmove (target_info.buffer_p + target_byte_index, src_info.buffer_p,
|
||||
target_info.element_size * src_info.length);
|
||||
memmove (target_buffer_p, src_buffer_p, limit);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t *target_limit_p = target_buffer_p + limit;
|
||||
ecma_typedarray_getter_fn_t src_typedarray_getter_cb = ecma_get_typedarray_getter_fn (src_info.id);
|
||||
ecma_typedarray_setter_fn_t target_typedarray_setter_cb = ecma_get_typedarray_setter_fn (target_info.id);
|
||||
|
||||
uint32_t src_byte_index = 0;
|
||||
while (target_byte_index < limit)
|
||||
while (target_buffer_p < target_limit_p)
|
||||
{
|
||||
ecma_value_t element = src_typedarray_getter_cb (src_info.buffer_p + src_byte_index);
|
||||
ecma_value_t set_element = target_typedarray_setter_cb (target_info.buffer_p + target_byte_index, element);
|
||||
ecma_value_t element = src_typedarray_getter_cb (src_buffer_p);
|
||||
ecma_value_t set_element = target_typedarray_setter_cb (target_buffer_p, element);
|
||||
ecma_free_value (element);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (set_element))
|
||||
@ -604,8 +628,8 @@ ecma_op_typedarray_set_with_typedarray (ecma_value_t this_arg, /**< this argumen
|
||||
return set_element;
|
||||
}
|
||||
|
||||
src_byte_index += src_info.element_size;
|
||||
target_byte_index += target_info.element_size;
|
||||
src_buffer_p += src_info.element_size;
|
||||
target_buffer_p += target_info.element_size;
|
||||
}
|
||||
}
|
||||
|
||||
@ -649,13 +673,13 @@ ecma_builtin_typedarray_prototype_set (ecma_value_t this_arg, /**< this argument
|
||||
|
||||
/* 11. ~ 15. */
|
||||
ecma_object_t *typedarray_p = ecma_get_object_from_value (this_arg);
|
||||
ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (typedarray_p);
|
||||
if (ecma_arraybuffer_is_detached (arraybuffer_p))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_arraybuffer_is_detached));
|
||||
}
|
||||
|
||||
ecma_typedarray_info_t target_info = ecma_typedarray_get_info (typedarray_p);
|
||||
uint8_t *target_buffer_p = ecma_typedarray_get_buffer (&target_info);
|
||||
|
||||
if (JERRY_UNLIKELY (target_buffer_p == NULL))
|
||||
{
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
/* 16.~ 17. */
|
||||
ecma_value_t source_obj = ecma_op_to_object (arr_val);
|
||||
@ -686,10 +710,10 @@ ecma_builtin_typedarray_prototype_set (ecma_value_t this_arg, /**< this argument
|
||||
uint32_t source_length_uint32 = (uint32_t) source_length;
|
||||
|
||||
/* 21.~ 25. */
|
||||
uint32_t target_byte_index = target_offset_uint32 * target_info.element_size;
|
||||
uint32_t k = 0;
|
||||
target_buffer_p += target_offset_uint32 << target_info.shift;
|
||||
|
||||
ecma_typedarray_setter_fn_t target_typedarray_setter_cb = ecma_get_typedarray_setter_fn (target_info.id);
|
||||
uint32_t k = 0;
|
||||
|
||||
while (k < source_length_uint32)
|
||||
{
|
||||
@ -731,14 +755,14 @@ ecma_builtin_typedarray_prototype_set (ecma_value_t this_arg, /**< this argument
|
||||
|
||||
ecma_free_value (elem);
|
||||
|
||||
if (ecma_arraybuffer_is_detached (arraybuffer_p))
|
||||
if (ecma_arraybuffer_is_detached (target_info.array_buffer_p))
|
||||
{
|
||||
ecma_deref_object (source_obj_p);
|
||||
ecma_free_value (value_to_set);
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_arraybuffer_is_detached));
|
||||
}
|
||||
|
||||
ecma_value_t set_element = target_typedarray_setter_cb (target_info.buffer_p + target_byte_index, value_to_set);
|
||||
ecma_value_t set_element = target_typedarray_setter_cb (target_buffer_p, value_to_set);
|
||||
|
||||
ecma_free_value (value_to_set);
|
||||
|
||||
@ -749,7 +773,7 @@ ecma_builtin_typedarray_prototype_set (ecma_value_t this_arg, /**< this argument
|
||||
}
|
||||
|
||||
k++;
|
||||
target_byte_index += target_info.element_size;
|
||||
target_buffer_p += target_info.element_size;
|
||||
}
|
||||
|
||||
ecma_deref_object (source_obj_p);
|
||||
@ -929,7 +953,7 @@ ecma_builtin_typedarray_prototype_subarray (ecma_value_t this_arg, /**< this obj
|
||||
}
|
||||
|
||||
/* 17. beginByteOffset */
|
||||
uint32_t begin_byte_offset = info_p->offset + begin_index_uint32 * info_p->element_size;
|
||||
uint32_t begin_byte_offset = info_p->offset + (begin_index_uint32 << info_p->shift);
|
||||
|
||||
ecma_value_t arguments_p[3] =
|
||||
{
|
||||
@ -1019,18 +1043,21 @@ ecma_builtin_typedarray_prototype_fill (ecma_value_t this_arg, /**< this object
|
||||
subarray_length = end_index_uint32 - begin_index_uint32;
|
||||
}
|
||||
|
||||
ecma_typedarray_setter_fn_t typedarray_setter_cb = ecma_get_typedarray_setter_fn (info_p->id);
|
||||
uint32_t byte_index = begin_index_uint32 * info_p->element_size;
|
||||
uint32_t limit = byte_index + subarray_length * info_p->element_size;
|
||||
uint8_t *buffer_p = ecma_typedarray_get_buffer (info_p);
|
||||
|
||||
if (ecma_arraybuffer_is_detached (info_p->array_buffer_p))
|
||||
if (JERRY_UNLIKELY (buffer_p == NULL))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_arraybuffer_is_detached));
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
while (byte_index < limit)
|
||||
buffer_p += begin_index_uint32 << info_p->shift;
|
||||
|
||||
uint8_t *limit_p = buffer_p + (subarray_length << info_p->shift);
|
||||
ecma_typedarray_setter_fn_t typedarray_setter_cb = ecma_get_typedarray_setter_fn (info_p->id);
|
||||
|
||||
while (buffer_p < limit_p)
|
||||
{
|
||||
ecma_value_t set_element = typedarray_setter_cb (info_p->buffer_p + byte_index, value_to_set);
|
||||
ecma_value_t set_element = typedarray_setter_cb (buffer_p, value_to_set);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (set_element))
|
||||
{
|
||||
@ -1038,7 +1065,7 @@ ecma_builtin_typedarray_prototype_fill (ecma_value_t this_arg, /**< this object
|
||||
return set_element;
|
||||
}
|
||||
|
||||
byte_index += info_p->element_size;
|
||||
buffer_p += info_p->element_size;
|
||||
}
|
||||
|
||||
ecma_free_value (value_to_set);
|
||||
@ -1171,17 +1198,19 @@ ecma_builtin_typedarray_prototype_sort (ecma_value_t this_arg, /**< this argumen
|
||||
ecma_value_t ret_value = ECMA_VALUE_EMPTY;
|
||||
JMEM_DEFINE_LOCAL_ARRAY (values_buffer, info_p->length, ecma_value_t);
|
||||
|
||||
uint32_t byte_index = 0, buffer_index = 0;
|
||||
uint32_t limit = info_p->length * info_p->element_size;
|
||||
uint32_t buffer_index = 0;
|
||||
|
||||
ecma_typedarray_getter_fn_t typedarray_getter_cb = ecma_get_typedarray_getter_fn (info_p->id);
|
||||
uint8_t *buffer_p = ecma_arraybuffer_get_buffer (info_p->array_buffer_p) + info_p->offset;
|
||||
uint8_t *limit_p = buffer_p + (info_p->length << info_p->shift);
|
||||
|
||||
/* Copy unsorted array into a native c array. */
|
||||
while (byte_index < limit)
|
||||
while (buffer_p < limit_p)
|
||||
{
|
||||
JERRY_ASSERT (buffer_index < info_p->length);
|
||||
ecma_value_t element_value = typedarray_getter_cb (info_p->buffer_p + byte_index);
|
||||
ecma_value_t element_value = typedarray_getter_cb (buffer_p);
|
||||
values_buffer[buffer_index++] = element_value;
|
||||
byte_index += info_p->element_size;
|
||||
buffer_p += info_p->element_size;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (buffer_index == info_p->length);
|
||||
@ -1209,15 +1238,15 @@ ecma_builtin_typedarray_prototype_sort (ecma_value_t this_arg, /**< this argumen
|
||||
|
||||
ecma_typedarray_setter_fn_t typedarray_setter_cb = ecma_get_typedarray_setter_fn (info_p->id);
|
||||
|
||||
byte_index = 0;
|
||||
buffer_p = limit_p - (info_p->length << info_p->shift);
|
||||
buffer_index = 0;
|
||||
limit = info_p->length * info_p->element_size;
|
||||
|
||||
/* Put sorted values from the native array back into the typedarray buffer. */
|
||||
while (byte_index < limit)
|
||||
while (buffer_p < limit_p)
|
||||
{
|
||||
JERRY_ASSERT (buffer_index < info_p->length);
|
||||
ecma_value_t element_value = values_buffer[buffer_index++];
|
||||
ecma_value_t set_element = typedarray_setter_cb (info_p->buffer_p + byte_index, element_value);
|
||||
ecma_value_t set_element = typedarray_setter_cb (buffer_p, element_value);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (set_element))
|
||||
{
|
||||
@ -1225,7 +1254,7 @@ ecma_builtin_typedarray_prototype_sort (ecma_value_t this_arg, /**< this argumen
|
||||
goto free_values;
|
||||
}
|
||||
|
||||
byte_index += info_p->element_size;
|
||||
buffer_p += info_p->element_size;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (buffer_index == info_p->length);
|
||||
@ -1261,16 +1290,16 @@ ecma_builtin_typedarray_prototype_find_helper (ecma_value_t this_arg, /**< this
|
||||
{
|
||||
JERRY_ASSERT (ecma_is_value_object (predicate));
|
||||
ecma_object_t *func_object_p = ecma_get_object_from_value (predicate);
|
||||
|
||||
uint32_t buffer_index = 0;
|
||||
uint32_t limit = info_p->length * info_p->element_size;
|
||||
|
||||
uint8_t *buffer_p = ecma_arraybuffer_get_buffer (info_p->array_buffer_p) + info_p->offset;
|
||||
uint8_t *limit_p = buffer_p + (info_p->length << info_p->shift);
|
||||
ecma_typedarray_getter_fn_t typedarray_getter_cb = ecma_get_typedarray_getter_fn (info_p->id);
|
||||
uint32_t buffer_index = 0;
|
||||
|
||||
for (uint32_t byte_index = 0; byte_index < limit; byte_index += info_p->element_size)
|
||||
while (buffer_p < limit_p)
|
||||
{
|
||||
JERRY_ASSERT (buffer_index < info_p->length);
|
||||
ecma_value_t element_value = typedarray_getter_cb (info_p->buffer_p + byte_index);
|
||||
ecma_value_t element_value = typedarray_getter_cb (buffer_p);
|
||||
buffer_p += info_p->element_size;
|
||||
|
||||
ecma_value_t call_args[] = { element_value, ecma_make_uint32_value (buffer_index), this_arg };
|
||||
ecma_value_t call_value = ecma_op_function_call (func_object_p, predicate_this_arg, call_args, 3);
|
||||
@ -1355,7 +1384,6 @@ ecma_builtin_typedarray_prototype_index_of (ecma_typedarray_info_t *info_p, /**<
|
||||
bool is_bigint = false;
|
||||
#endif /* JERRY_BUILTIN_BIGINT */
|
||||
|
||||
uint32_t limit = info_p->length * info_p->element_size;
|
||||
uint32_t from_index;
|
||||
|
||||
/* 5. */
|
||||
@ -1377,25 +1405,34 @@ ecma_builtin_typedarray_prototype_index_of (ecma_typedarray_info_t *info_p, /**<
|
||||
{
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uint8_t *buffer_p = ecma_typedarray_get_buffer (info_p);
|
||||
|
||||
if (JERRY_UNLIKELY (buffer_p == NULL))
|
||||
{
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
uint8_t *limit_p = buffer_p + (info_p->length << info_p->shift);
|
||||
ecma_typedarray_getter_fn_t getter_cb = ecma_get_typedarray_getter_fn (info_p->id);
|
||||
|
||||
buffer_p += from_index << info_p->shift;
|
||||
|
||||
/* 11. */
|
||||
for (uint32_t position = from_index * info_p->element_size;
|
||||
position < limit;
|
||||
position += info_p->element_size)
|
||||
while (buffer_p < limit_p)
|
||||
{
|
||||
ecma_value_t element = getter_cb (info_p->buffer_p + position);
|
||||
ecma_value_t element = getter_cb (buffer_p);
|
||||
|
||||
if (ecma_op_same_value_zero (args[0], element, true))
|
||||
{
|
||||
ecma_free_value (element);
|
||||
return ecma_make_number_value ((ecma_number_t) position / info_p->element_size);
|
||||
return ecma_make_number_value (from_index);
|
||||
}
|
||||
|
||||
ecma_free_value (element);
|
||||
buffer_p += info_p->element_size;
|
||||
from_index++;
|
||||
}
|
||||
|
||||
/* 12. */
|
||||
@ -1461,17 +1498,18 @@ ecma_builtin_typedarray_prototype_last_index_of (ecma_typedarray_info_t *info_p,
|
||||
}
|
||||
|
||||
ecma_typedarray_getter_fn_t getter_cb = ecma_get_typedarray_getter_fn (info_p->id);
|
||||
uint8_t *current_element_p = info_p->buffer_p + from_index * info_p->element_size;
|
||||
uint8_t *buffer_p = ecma_arraybuffer_get_buffer (info_p->array_buffer_p) + info_p->offset;
|
||||
uint8_t *current_element_p = buffer_p + (from_index << info_p->shift);
|
||||
|
||||
/* 10. */
|
||||
while (current_element_p >= info_p->buffer_p)
|
||||
while (current_element_p >= buffer_p)
|
||||
{
|
||||
ecma_value_t element = getter_cb (info_p->buffer_p + from_index * info_p->element_size);
|
||||
ecma_value_t element = getter_cb (current_element_p);
|
||||
|
||||
if (ecma_op_same_value_zero (args[0], element, true))
|
||||
{
|
||||
ecma_free_value (element);
|
||||
return ecma_make_number_value ((ecma_number_t) from_index * info_p->element_size / info_p->element_size);
|
||||
return ecma_make_number_value ((ecma_number_t) from_index);
|
||||
}
|
||||
|
||||
ecma_free_value (element);
|
||||
@ -1532,26 +1570,26 @@ ecma_builtin_typedarray_prototype_copy_within (ecma_value_t this_arg, /**< this
|
||||
}
|
||||
}
|
||||
|
||||
if (ecma_arraybuffer_is_detached (info_p->array_buffer_p))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_arraybuffer_is_detached));
|
||||
}
|
||||
|
||||
if (relative_target >= info_p->length || relative_start >= relative_end || relative_end == 0)
|
||||
{
|
||||
return ecma_copy_value (this_arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t distance = relative_end - relative_start;
|
||||
uint32_t offset = info_p->length - relative_target;
|
||||
uint32_t count = JERRY_MIN (distance, offset);
|
||||
|
||||
memmove (info_p->buffer_p + (relative_target * info_p->element_size),
|
||||
info_p->buffer_p + (relative_start * info_p->element_size),
|
||||
(size_t) (count * info_p->element_size));
|
||||
uint8_t *buffer_p = ecma_typedarray_get_buffer (info_p);
|
||||
|
||||
if (JERRY_UNLIKELY (buffer_p == NULL))
|
||||
{
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
uint32_t distance = relative_end - relative_start;
|
||||
uint32_t offset = info_p->length - relative_target;
|
||||
uint32_t count = JERRY_MIN (distance, offset);
|
||||
|
||||
memmove (buffer_p + (relative_target << info_p->shift),
|
||||
buffer_p + (relative_start << info_p->shift),
|
||||
(size_t) (count << info_p->shift));
|
||||
|
||||
return ecma_copy_value (this_arg);
|
||||
} /* ecma_builtin_typedarray_prototype_copy_within */
|
||||
|
||||
@ -1606,23 +1644,31 @@ ecma_builtin_typedarray_prototype_slice (ecma_value_t this_arg, /**< this argume
|
||||
}
|
||||
|
||||
ecma_object_t *new_typedarray_p = ecma_get_object_from_value (new_typedarray);
|
||||
uint8_t *src_buffer_p = ecma_typedarray_get_buffer (info_p);
|
||||
|
||||
if (ecma_arraybuffer_is_detached (info_p->array_buffer_p))
|
||||
if (JERRY_UNLIKELY (src_buffer_p == NULL))
|
||||
{
|
||||
ecma_deref_object (new_typedarray_p);
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_arraybuffer_is_detached));
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
ecma_typedarray_info_t new_typedarray_info = ecma_typedarray_get_info (new_typedarray_p);
|
||||
uint8_t *dst_buffer_p = ecma_typedarray_get_buffer (&new_typedarray_info);
|
||||
|
||||
if (JERRY_UNLIKELY (dst_buffer_p == NULL))
|
||||
{
|
||||
ecma_deref_object (new_typedarray_p);
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (new_typedarray_info.offset == 0);
|
||||
|
||||
src_buffer_p += relative_start << info_p->shift;
|
||||
|
||||
if (info_p->id == new_typedarray_info.id)
|
||||
{
|
||||
// 22.2.3.23. Step 22. h-i.
|
||||
uint32_t src_byte_index = (relative_start * info_p->element_size);
|
||||
|
||||
memcpy (new_typedarray_info.buffer_p,
|
||||
info_p->buffer_p + src_byte_index,
|
||||
count * info_p->element_size);
|
||||
memcpy (dst_buffer_p, src_buffer_p, count << info_p->shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1630,13 +1676,10 @@ ecma_builtin_typedarray_prototype_slice (ecma_value_t this_arg, /**< this argume
|
||||
ecma_typedarray_getter_fn_t src_typedarray_getter_cb = ecma_get_typedarray_getter_fn (info_p->id);
|
||||
ecma_typedarray_setter_fn_t new_typedarray_setter_cb = ecma_get_typedarray_setter_fn (new_typedarray_info.id);
|
||||
|
||||
uint32_t src_byte_index = (relative_start * info_p->element_size);
|
||||
uint32_t dst_byte_index = 0;
|
||||
|
||||
for (uint32_t idx = 0; idx < count; idx++)
|
||||
{
|
||||
ecma_value_t element = src_typedarray_getter_cb (info_p->buffer_p + src_byte_index);
|
||||
ecma_value_t set_element = new_typedarray_setter_cb (new_typedarray_info.buffer_p + dst_byte_index, element);
|
||||
ecma_value_t element = src_typedarray_getter_cb (src_buffer_p);
|
||||
ecma_value_t set_element = new_typedarray_setter_cb (dst_buffer_p, element);
|
||||
ecma_free_value (element);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (set_element))
|
||||
@ -1645,8 +1688,8 @@ ecma_builtin_typedarray_prototype_slice (ecma_value_t this_arg, /**< this argume
|
||||
return set_element;
|
||||
}
|
||||
|
||||
src_byte_index += info_p->element_size;
|
||||
dst_byte_index += new_typedarray_info.element_size;
|
||||
src_buffer_p += info_p->element_size;
|
||||
dst_buffer_p += new_typedarray_info.element_size;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1747,8 +1790,6 @@ ecma_builtin_typedarray_prototype_includes (ecma_typedarray_info_t *info_p, /**<
|
||||
const ecma_value_t args[], /**< arguments list */
|
||||
uint32_t args_number) /**< number of arguments */
|
||||
{
|
||||
uint32_t limit = info_p->length * info_p->element_size;
|
||||
|
||||
#if JERRY_BUILTIN_BIGINT
|
||||
bool is_bigint = ECMA_TYPEDARRAY_IS_BIGINT_TYPE (info_p->id);
|
||||
#else /* !JERRRY_BUILTIN_BIGINT */
|
||||
@ -1772,18 +1813,21 @@ ecma_builtin_typedarray_prototype_includes (ecma_typedarray_info_t *info_p, /**<
|
||||
}
|
||||
}
|
||||
|
||||
ecma_typedarray_getter_fn_t getter_cb = ecma_get_typedarray_getter_fn (info_p->id);
|
||||
uint8_t *buffer_p = ecma_typedarray_get_buffer (info_p);
|
||||
|
||||
uint32_t search_pos = (uint32_t) from_index * info_p->element_size;
|
||||
|
||||
if (ecma_arraybuffer_is_detached (info_p->array_buffer_p))
|
||||
if (JERRY_UNLIKELY (buffer_p == NULL))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_arraybuffer_is_detached));
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
while (search_pos < limit)
|
||||
ecma_typedarray_getter_fn_t getter_cb = ecma_get_typedarray_getter_fn (info_p->id);
|
||||
uint8_t *limit_p = buffer_p + (info_p->length << info_p->shift);
|
||||
|
||||
buffer_p += from_index << info_p->shift;
|
||||
|
||||
while (buffer_p < limit_p)
|
||||
{
|
||||
ecma_value_t element = getter_cb (info_p->buffer_p + search_pos);
|
||||
ecma_value_t element = getter_cb (buffer_p);
|
||||
|
||||
if (ecma_op_same_value_zero (args[0], element, false))
|
||||
{
|
||||
@ -1792,7 +1836,7 @@ ecma_builtin_typedarray_prototype_includes (ecma_typedarray_info_t *info_p, /**<
|
||||
}
|
||||
|
||||
ecma_free_value (element);
|
||||
search_pos += info_p->element_size;
|
||||
buffer_p += info_p->element_size;
|
||||
}
|
||||
|
||||
return ECMA_VALUE_FALSE;
|
||||
@ -1828,10 +1872,10 @@ ecma_builtin_typedarray_prototype_dispatch_routine (uint8_t builtin_routine_id,
|
||||
{
|
||||
info = ecma_typedarray_get_info (typedarray_p);
|
||||
|
||||
if (ecma_arraybuffer_is_detached (info.array_buffer_p)
|
||||
&& builtin_routine_id != ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SUBARRAY)
|
||||
if (builtin_routine_id != ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_SUBARRAY
|
||||
&& ECMA_ARRAYBUFFER_CHECK_BUFFER_ERROR (info.array_buffer_p))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_arraybuffer_is_detached));
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -131,10 +131,17 @@ ecma_builtin_typedarray_of (ecma_value_t this_arg, /**< 'this' argument */
|
||||
ecma_object_t *ret_obj_p = ecma_get_object_from_value (ret_val);
|
||||
ecma_typedarray_info_t info = ecma_typedarray_get_info (ret_obj_p);
|
||||
ecma_typedarray_setter_fn_t setter_cb = ecma_get_typedarray_setter_fn (info.id);
|
||||
lit_utf8_byte_t *buffer_p = ecma_typedarray_get_buffer (&info);
|
||||
|
||||
if (JERRY_UNLIKELY (buffer_p == NULL))
|
||||
{
|
||||
ecma_deref_object (ret_obj_p);
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
while (k < arguments_list_len)
|
||||
{
|
||||
ecma_value_t set_element = setter_cb (info.buffer_p, arguments_list_p[k]);
|
||||
ecma_value_t set_element = setter_cb (buffer_p, arguments_list_p[k]);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (set_element))
|
||||
{
|
||||
@ -143,7 +150,7 @@ ecma_builtin_typedarray_of (ecma_value_t this_arg, /**< 'this' argument */
|
||||
}
|
||||
|
||||
k++;
|
||||
info.buffer_p += info.element_size;
|
||||
buffer_p += info.element_size;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
|
||||
@ -13,19 +13,18 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecma-builtin-helpers.h"
|
||||
#include "ecma-arraybuffer-object.h"
|
||||
#include "ecma-shared-arraybuffer-object.h"
|
||||
#include "ecma-typedarray-object.h"
|
||||
#include "ecma-objects.h"
|
||||
#include "ecma-builtins.h"
|
||||
#include "ecma-builtin-helpers.h"
|
||||
#include "ecma-exceptions.h"
|
||||
#include "ecma-function-object.h"
|
||||
#include "ecma-gc.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "jmem.h"
|
||||
#include "ecma-objects.h"
|
||||
#include "ecma-shared-arraybuffer-object.h"
|
||||
#include "ecma-typedarray-object.h"
|
||||
#include "jcontext.h"
|
||||
#include "ecma-function-object.h"
|
||||
|
||||
#if JERRY_BUILTIN_TYPEDARRAY
|
||||
|
||||
@ -37,64 +36,187 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Helper function: create arraybuffer object based on the array length
|
||||
* Creating ArrayBuffer objects with a buffer after the arraybuffer header
|
||||
*
|
||||
* The struct of arraybuffer object:
|
||||
* ecma_object_t
|
||||
* extend_part
|
||||
* data buffer
|
||||
*
|
||||
* @return ecma_object_t *
|
||||
* @return new ArrayBuffer object
|
||||
*/
|
||||
ecma_object_t *
|
||||
ecma_arraybuffer_new_object (uint32_t length) /**< length of the arraybuffer */
|
||||
ecma_arraybuffer_create_object (uint8_t type, /**< type of the arraybuffer */
|
||||
uint32_t length) /**< length of the arraybuffer */
|
||||
{
|
||||
ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_ARRAYBUFFER_PROTOTYPE);
|
||||
ecma_object_t *object_p = ecma_create_object (prototype_obj_p,
|
||||
ecma_builtin_id_t prototype_id;
|
||||
|
||||
#if JERRY_BUILTIN_SHAREDARRAYBUFFER
|
||||
JERRY_ASSERT (type == ECMA_OBJECT_CLASS_ARRAY_BUFFER
|
||||
|| type == ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER);
|
||||
|
||||
prototype_id = (type == ECMA_OBJECT_CLASS_ARRAY_BUFFER ? ECMA_BUILTIN_ID_ARRAYBUFFER_PROTOTYPE
|
||||
: ECMA_BUILTIN_ID_SHARED_ARRAYBUFFER_PROTOTYPE);
|
||||
#else /* !JERRY_BUILTIN_SHAREDARRAYBUFFER */
|
||||
JERRY_ASSERT (type == ECMA_OBJECT_CLASS_ARRAY_BUFFER);
|
||||
|
||||
prototype_id = ECMA_BUILTIN_ID_ARRAYBUFFER_PROTOTYPE;
|
||||
#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */
|
||||
|
||||
ecma_object_t *object_p = ecma_create_object (ecma_builtin_get (prototype_id),
|
||||
sizeof (ecma_extended_object_t) + length,
|
||||
ECMA_OBJECT_TYPE_CLASS);
|
||||
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_ARRAY_BUFFER;
|
||||
ext_object_p->u.cls.u1.array_buffer_flags = ECMA_ARRAYBUFFER_INTERNAL_MEMORY;
|
||||
ext_object_p->u.cls.type = type;
|
||||
ext_object_p->u.cls.u1.array_buffer_flags = ECMA_ARRAYBUFFER_ALLOCATED;
|
||||
ext_object_p->u.cls.u3.length = length;
|
||||
|
||||
lit_utf8_byte_t *buf = (lit_utf8_byte_t *) (ext_object_p + 1);
|
||||
memset (buf, 0, length);
|
||||
memset ((uint8_t *) (ext_object_p + 1), 0, length);
|
||||
return object_p;
|
||||
} /* ecma_arraybuffer_create_object */
|
||||
|
||||
/**
|
||||
* Creating ArrayBuffer objects with a pointer to its buffer
|
||||
*
|
||||
* @return new ArrayBuffer object
|
||||
*/
|
||||
ecma_object_t *
|
||||
ecma_arraybuffer_create_object_with_buffer (uint8_t type, /**< type of the arraybuffer */
|
||||
uint32_t length)
|
||||
{
|
||||
ecma_builtin_id_t prototype_id;
|
||||
|
||||
#if JERRY_BUILTIN_SHAREDARRAYBUFFER
|
||||
JERRY_ASSERT (type == ECMA_OBJECT_CLASS_ARRAY_BUFFER
|
||||
|| type == ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER);
|
||||
|
||||
prototype_id = (type == ECMA_OBJECT_CLASS_ARRAY_BUFFER ? ECMA_BUILTIN_ID_ARRAYBUFFER_PROTOTYPE
|
||||
: ECMA_BUILTIN_ID_SHARED_ARRAYBUFFER_PROTOTYPE);
|
||||
#else /* !JERRY_BUILTIN_SHAREDARRAYBUFFER */
|
||||
JERRY_ASSERT (type == ECMA_OBJECT_CLASS_ARRAY_BUFFER);
|
||||
|
||||
prototype_id = ECMA_BUILTIN_ID_ARRAYBUFFER_PROTOTYPE;
|
||||
#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */
|
||||
|
||||
ecma_object_t *object_p = ecma_create_object (ecma_builtin_get (prototype_id),
|
||||
sizeof (ecma_arraybuffer_pointer_t),
|
||||
ECMA_OBJECT_TYPE_CLASS);
|
||||
|
||||
ecma_arraybuffer_pointer_t *arraybuffer_pointer_p = (ecma_arraybuffer_pointer_t *) object_p;
|
||||
arraybuffer_pointer_p->extended_object.u.cls.type = type;
|
||||
arraybuffer_pointer_p->extended_object.u.cls.u1.array_buffer_flags = ECMA_ARRAYBUFFER_HAS_POINTER;
|
||||
arraybuffer_pointer_p->extended_object.u.cls.u3.length = length;
|
||||
|
||||
arraybuffer_pointer_p->buffer_p = NULL;
|
||||
arraybuffer_pointer_p->arraybuffer_user_p = NULL;
|
||||
|
||||
return object_p;
|
||||
} /* ecma_arraybuffer_create_object_with_buffer */
|
||||
|
||||
/**
|
||||
* Creating ArrayBuffer objects based on the array length
|
||||
*
|
||||
* @return new ArrayBuffer object
|
||||
*/
|
||||
ecma_object_t *
|
||||
ecma_arraybuffer_new_object (uint32_t length) /**< length of the arraybuffer */
|
||||
{
|
||||
if (length > JERRY_CONTEXT (arraybuffer_compact_allocation_limit))
|
||||
{
|
||||
return ecma_arraybuffer_create_object_with_buffer (ECMA_OBJECT_CLASS_ARRAY_BUFFER, length);
|
||||
}
|
||||
|
||||
return ecma_arraybuffer_create_object (ECMA_OBJECT_CLASS_ARRAY_BUFFER, length);
|
||||
} /* ecma_arraybuffer_new_object */
|
||||
|
||||
/**
|
||||
* Helper function: create arraybuffer object with external buffer backing.
|
||||
* Allocate a backing store for an array buffer.
|
||||
*
|
||||
* The struct of external arraybuffer object:
|
||||
* ecma_object_t
|
||||
* extend_part
|
||||
* arraybuffer external info part
|
||||
*
|
||||
* @return ecma_object_t *, pointer to the created ArrayBuffer object
|
||||
* @return ECMA_VALUE_UNDEFINED on success,
|
||||
* ECMA_VALUE_ERROR otherwise
|
||||
*/
|
||||
ecma_object_t *
|
||||
ecma_arraybuffer_new_object_external (uint32_t length, /**< length of the buffer_p to use */
|
||||
void *buffer_p, /**< pointer for ArrayBuffer's buffer backing */
|
||||
jerry_value_free_callback_t free_cb) /**< buffer free callback */
|
||||
ecma_value_t
|
||||
ecma_arraybuffer_allocate_buffer (ecma_object_t *object_p) /**< ArrayBuffer object */
|
||||
{
|
||||
ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_ARRAYBUFFER_PROTOTYPE);
|
||||
ecma_object_t *object_p = ecma_create_object (prototype_obj_p,
|
||||
sizeof (ecma_arraybuffer_external_info),
|
||||
ECMA_OBJECT_TYPE_CLASS);
|
||||
JERRY_ASSERT (!(ECMA_ARRAYBUFFER_GET_FLAGS (object_p) & ECMA_ARRAYBUFFER_ALLOCATED));
|
||||
|
||||
ecma_arraybuffer_external_info *array_object_p = (ecma_arraybuffer_external_info *) object_p;
|
||||
array_object_p->extended_object.u.cls.type = ECMA_OBJECT_CLASS_ARRAY_BUFFER;
|
||||
array_object_p->extended_object.u.cls.u1.array_buffer_flags = ECMA_ARRAYBUFFER_EXTERNAL_MEMORY;
|
||||
array_object_p->extended_object.u.cls.u3.length = length;
|
||||
if (ECMA_ARRAYBUFFER_GET_FLAGS (object_p) & ECMA_ARRAYBUFFER_DETACHED)
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_arraybuffer_is_detached));
|
||||
}
|
||||
|
||||
array_object_p->buffer_p = buffer_p;
|
||||
array_object_p->free_cb = free_cb;
|
||||
JERRY_ASSERT (ECMA_ARRAYBUFFER_GET_FLAGS (object_p) & ECMA_ARRAYBUFFER_HAS_POINTER);
|
||||
|
||||
return object_p;
|
||||
} /* ecma_arraybuffer_new_object_external */
|
||||
ecma_extended_object_t *extended_object_p = (ecma_extended_object_t *) object_p;
|
||||
uint32_t arraybuffer_length = extended_object_p->u.cls.u3.length;
|
||||
ecma_arraybuffer_pointer_t *arraybuffer_pointer_p = (ecma_arraybuffer_pointer_t *) object_p;
|
||||
jerry_arraybuffer_allocate_t arraybuffer_allocate_callback = JERRY_CONTEXT (arraybuffer_allocate_callback);
|
||||
void *buffer_p;
|
||||
|
||||
if (arraybuffer_allocate_callback != NULL)
|
||||
{
|
||||
jerry_arraybuffer_type_t type = JERRY_ARRAYBUFFER_TYPE_ARRAYBUFFER;
|
||||
|
||||
#if JERRY_BUILTIN_SHAREDARRAYBUFFER
|
||||
if (extended_object_p->u.cls.type == ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER)
|
||||
{
|
||||
type = JERRY_ARRAYBUFFER_TYPE_SHARED_ARRAYBUFFER;
|
||||
}
|
||||
#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */
|
||||
|
||||
buffer_p = arraybuffer_allocate_callback (type,
|
||||
arraybuffer_length,
|
||||
&arraybuffer_pointer_p->arraybuffer_user_p,
|
||||
JERRY_CONTEXT (arraybuffer_allocate_callback_user_p));
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer_p = jmem_heap_alloc_block_null_on_error (arraybuffer_length);
|
||||
}
|
||||
|
||||
if (buffer_p == NULL)
|
||||
{
|
||||
extended_object_p->u.cls.u1.array_buffer_flags |= ECMA_ARRAYBUFFER_DETACHED;
|
||||
return ecma_raise_range_error (ECMA_ERR_MSG ("Cannot allocate memory for ArrayBuffer"));
|
||||
}
|
||||
|
||||
arraybuffer_pointer_p->buffer_p = buffer_p;
|
||||
extended_object_p->u.cls.u1.array_buffer_flags |= ECMA_ARRAYBUFFER_ALLOCATED;
|
||||
|
||||
memset (buffer_p, 0, arraybuffer_length);
|
||||
return ECMA_VALUE_UNDEFINED;
|
||||
} /* ecma_arraybuffer_allocate_buffer */
|
||||
|
||||
/**
|
||||
* Release the backing store allocated by an array buffer.
|
||||
*/
|
||||
void
|
||||
ecma_arraybuffer_release_buffer (ecma_object_t *object_p) /**< ArrayBuffer object */
|
||||
{
|
||||
JERRY_ASSERT (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER)
|
||||
|| ecma_object_is_shared_arraybuffer (object_p));
|
||||
|
||||
jerry_arraybuffer_free_t free_callback = JERRY_CONTEXT (arraybuffer_free_callback);
|
||||
ecma_arraybuffer_pointer_t *arraybuffer_pointer_p = (ecma_arraybuffer_pointer_t *) object_p;
|
||||
uint32_t arraybuffer_length = arraybuffer_pointer_p->extended_object.u.cls.u3.length;
|
||||
|
||||
if (free_callback == NULL)
|
||||
{
|
||||
jmem_heap_free_block (arraybuffer_pointer_p->buffer_p, arraybuffer_length);
|
||||
return;
|
||||
}
|
||||
|
||||
jerry_arraybuffer_type_t type = JERRY_ARRAYBUFFER_TYPE_ARRAYBUFFER;
|
||||
|
||||
#if JERRY_BUILTIN_SHAREDARRAYBUFFER
|
||||
if (arraybuffer_pointer_p->extended_object.u.cls.type == ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER)
|
||||
{
|
||||
type = JERRY_ARRAYBUFFER_TYPE_SHARED_ARRAYBUFFER;
|
||||
}
|
||||
#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */
|
||||
|
||||
free_callback (type,
|
||||
arraybuffer_pointer_p->buffer_p,
|
||||
arraybuffer_length,
|
||||
arraybuffer_pointer_p->arraybuffer_user_p,
|
||||
JERRY_CONTEXT (arraybuffer_allocate_callback_user_p));
|
||||
} /* ecma_arraybuffer_release_buffer */
|
||||
|
||||
/**
|
||||
* ArrayBuffer object creation operation.
|
||||
@ -198,26 +320,21 @@ ecma_arraybuffer_get_length (ecma_object_t *object_p) /**< pointer to the ArrayB
|
||||
*
|
||||
* @return pointer to the data buffer
|
||||
*/
|
||||
extern inline lit_utf8_byte_t * JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
|
||||
extern inline uint8_t * JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_arraybuffer_get_buffer (ecma_object_t *object_p) /**< pointer to the ArrayBuffer object */
|
||||
{
|
||||
JERRY_ASSERT (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER)
|
||||
|| ecma_object_is_shared_arraybuffer (object_p));
|
||||
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
JERRY_ASSERT (ECMA_ARRAYBUFFER_GET_FLAGS (object_p) & ECMA_ARRAYBUFFER_ALLOCATED);
|
||||
|
||||
if (ECMA_ARRAYBUFFER_HAS_EXTERNAL_MEMORY (ext_object_p))
|
||||
if (!(ECMA_ARRAYBUFFER_GET_FLAGS (object_p) & ECMA_ARRAYBUFFER_HAS_POINTER))
|
||||
{
|
||||
ecma_arraybuffer_external_info *array_p = (ecma_arraybuffer_external_info *) ext_object_p;
|
||||
JERRY_ASSERT (!ecma_arraybuffer_is_detached (object_p) || array_p->buffer_p == NULL);
|
||||
return (lit_utf8_byte_t *) array_p->buffer_p;
|
||||
}
|
||||
else if (ext_object_p->u.cls.u1.array_buffer_flags & ECMA_ARRAYBUFFER_DETACHED)
|
||||
{
|
||||
return NULL;
|
||||
return (uint8_t *) object_p + sizeof (ecma_extended_object_t);
|
||||
}
|
||||
|
||||
return (lit_utf8_byte_t *) (ext_object_p + 1);
|
||||
ecma_arraybuffer_pointer_t *arraybuffer_pointer_p = (ecma_arraybuffer_pointer_t *) object_p;
|
||||
return (uint8_t *) arraybuffer_pointer_p->buffer_p;
|
||||
} /* ecma_arraybuffer_get_buffer */
|
||||
|
||||
/**
|
||||
@ -232,7 +349,7 @@ ecma_arraybuffer_is_detached (ecma_object_t *object_p) /**< pointer to the Array
|
||||
JERRY_ASSERT (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER)
|
||||
|| ecma_object_is_shared_arraybuffer (object_p));
|
||||
|
||||
return (((ecma_extended_object_t *) object_p)->u.cls.u1.array_buffer_flags & ECMA_ARRAYBUFFER_DETACHED) != 0;
|
||||
return (ECMA_ARRAYBUFFER_GET_FLAGS (object_p) & ECMA_ARRAYBUFFER_DETACHED) != 0;
|
||||
} /* ecma_arraybuffer_is_detached */
|
||||
|
||||
/**
|
||||
@ -240,7 +357,7 @@ ecma_arraybuffer_is_detached (ecma_object_t *object_p) /**< pointer to the Array
|
||||
*
|
||||
* See also: ES2015 24.1.1.3
|
||||
*
|
||||
* @return true - if detach op succeeded
|
||||
* @return true - if detach operation is succeeded
|
||||
* false - otherwise
|
||||
*/
|
||||
extern inline bool JERRY_ATTR_ALWAYS_INLINE
|
||||
@ -248,7 +365,7 @@ ecma_arraybuffer_detach (ecma_object_t *object_p) /**< pointer to the ArrayBuffe
|
||||
{
|
||||
JERRY_ASSERT (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER));
|
||||
|
||||
if (ecma_arraybuffer_is_detached (object_p))
|
||||
if (ECMA_ARRAYBUFFER_GET_FLAGS (object_p) & ECMA_ARRAYBUFFER_DETACHED)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -256,23 +373,31 @@ ecma_arraybuffer_detach (ecma_object_t *object_p) /**< pointer to the ArrayBuffe
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
ext_object_p->u.cls.u1.array_buffer_flags |= ECMA_ARRAYBUFFER_DETACHED;
|
||||
|
||||
if (ECMA_ARRAYBUFFER_HAS_EXTERNAL_MEMORY (ext_object_p))
|
||||
if (!(ECMA_ARRAYBUFFER_GET_FLAGS (object_p) & ECMA_ARRAYBUFFER_ALLOCATED))
|
||||
{
|
||||
ecma_arraybuffer_external_info *array_p = (ecma_arraybuffer_external_info *) ext_object_p;
|
||||
|
||||
if (array_p->free_cb != NULL)
|
||||
{
|
||||
array_p->free_cb (array_p->buffer_p);
|
||||
array_p->free_cb = NULL;
|
||||
}
|
||||
|
||||
ext_object_p->u.cls.u3.length = 0;
|
||||
array_p->buffer_p = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
ext_object_p->u.cls.u1.array_buffer_flags &= (uint8_t) ~ECMA_ARRAYBUFFER_ALLOCATED;
|
||||
|
||||
if (!(ECMA_ARRAYBUFFER_GET_FLAGS (object_p) & ECMA_ARRAYBUFFER_HAS_POINTER))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
ecma_arraybuffer_release_buffer (object_p);
|
||||
return true;
|
||||
} /* ecma_arraybuffer_detach */
|
||||
|
||||
/**
|
||||
* ArrayBuffer slice operation
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v11, 24.1.4.3
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_builtin_arraybuffer_slice (ecma_value_t this_arg,
|
||||
const ecma_value_t *argument_list_p,
|
||||
@ -280,10 +405,10 @@ ecma_builtin_arraybuffer_slice (ecma_value_t this_arg,
|
||||
{
|
||||
ecma_object_t *object_p = ecma_get_object_from_value (this_arg);
|
||||
|
||||
/* 4. */
|
||||
if (ecma_arraybuffer_is_detached (object_p))
|
||||
/* 3-4. */
|
||||
if (ECMA_ARRAYBUFFER_CHECK_BUFFER_ERROR (object_p))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_arraybuffer_is_detached));
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
/* 5. */
|
||||
@ -358,7 +483,7 @@ ecma_builtin_arraybuffer_slice (ecma_value_t this_arg,
|
||||
}
|
||||
|
||||
/* 14-15. */
|
||||
if (ecma_arraybuffer_is_detached (new_arraybuffer_p))
|
||||
if (ECMA_ARRAYBUFFER_CHECK_BUFFER_ERROR (new_arraybuffer_p))
|
||||
{
|
||||
ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Returned ArrayBuffer has been detached"));
|
||||
goto free_new_arraybuffer;
|
||||
@ -381,7 +506,7 @@ ecma_builtin_arraybuffer_slice (ecma_value_t this_arg,
|
||||
/* 19. */
|
||||
if (ecma_arraybuffer_is_detached (object_p))
|
||||
{
|
||||
ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Original ArrayBuffer has been detached"));
|
||||
ret_value = ECMA_VALUE_ERROR;
|
||||
goto free_new_arraybuffer;
|
||||
}
|
||||
|
||||
|
||||
@ -27,6 +27,19 @@
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get array buffer flags.
|
||||
*/
|
||||
#define ECMA_ARRAYBUFFER_GET_FLAGS(arraybuffer_p) \
|
||||
(((ecma_extended_object_t *) (arraybuffer_p))->u.cls.u1.array_buffer_flags)
|
||||
|
||||
/**
|
||||
* Check whether the backing store is allocated for an array buffer.
|
||||
*/
|
||||
#define ECMA_ARRAYBUFFER_CHECK_BUFFER_ERROR(arraybuffer_p) \
|
||||
(JERRY_UNLIKELY (!(ECMA_ARRAYBUFFER_GET_FLAGS (arraybuffer_p) & ECMA_ARRAYBUFFER_ALLOCATED)) \
|
||||
&& ecma_arraybuffer_allocate_buffer (arraybuffer_p) == ECMA_VALUE_ERROR)
|
||||
|
||||
ecma_value_t
|
||||
ecma_op_create_arraybuffer_object (const ecma_value_t *, uint32_t);
|
||||
|
||||
@ -34,12 +47,16 @@ ecma_op_create_arraybuffer_object (const ecma_value_t *, uint32_t);
|
||||
* Helper functions for arraybuffer.
|
||||
*/
|
||||
ecma_object_t *
|
||||
ecma_arraybuffer_new_object (uint32_t lengh);
|
||||
ecma_arraybuffer_create_object (uint8_t type, uint32_t length);
|
||||
ecma_object_t *
|
||||
ecma_arraybuffer_new_object_external (uint32_t length,
|
||||
void *buffer_p,
|
||||
jerry_value_free_callback_t free_cb);
|
||||
lit_utf8_byte_t * JERRY_ATTR_PURE
|
||||
ecma_arraybuffer_create_object_with_buffer (uint8_t type, uint32_t length);
|
||||
ecma_object_t *
|
||||
ecma_arraybuffer_new_object (uint32_t length);
|
||||
ecma_value_t
|
||||
ecma_arraybuffer_allocate_buffer (ecma_object_t *object_p);
|
||||
void
|
||||
ecma_arraybuffer_release_buffer (ecma_object_t *object_p);
|
||||
uint8_t * JERRY_ATTR_PURE
|
||||
ecma_arraybuffer_get_buffer (ecma_object_t *obj_p);
|
||||
uint32_t JERRY_ATTR_PURE
|
||||
ecma_arraybuffer_get_length (ecma_object_t *obj_p);
|
||||
|
||||
@ -298,10 +298,9 @@ ecma_op_dataview_get_set_view_value (ecma_value_t view, /**< the operation's 'vi
|
||||
/* GetViewValue 4., SetViewValue 6. */
|
||||
bool is_little_endian = ecma_op_to_boolean (is_little_endian_value);
|
||||
|
||||
if (ecma_arraybuffer_is_detached (buffer_p))
|
||||
if (ECMA_ARRAYBUFFER_CHECK_BUFFER_ERROR (buffer_p))
|
||||
{
|
||||
ecma_free_value (value_to_set);
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_arraybuffer_is_detached));
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
/* GetViewValue 7., SetViewValue 9. */
|
||||
@ -320,10 +319,12 @@ ecma_op_dataview_get_set_view_value (ecma_value_t view, /**< the operation's 'vi
|
||||
return ecma_raise_range_error (ECMA_ERR_MSG ("Start offset is outside the bounds of the buffer"));
|
||||
}
|
||||
|
||||
/* GetViewValue 11., SetViewValue 13. */
|
||||
uint32_t buffer_index = (uint32_t) get_index + view_offset;
|
||||
lit_utf8_byte_t *block_p = ecma_arraybuffer_get_buffer (buffer_p) + buffer_index;
|
||||
if (ECMA_ARRAYBUFFER_CHECK_BUFFER_ERROR (buffer_p))
|
||||
{
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
/* GetViewValue 11., SetViewValue 13. */
|
||||
bool system_is_little_endian = ecma_dataview_check_little_endian ();
|
||||
|
||||
ecma_typedarray_info_t info;
|
||||
@ -335,21 +336,27 @@ ecma_op_dataview_get_set_view_value (ecma_value_t view, /**< the operation's 'vi
|
||||
info.array_buffer_p = buffer_p;
|
||||
|
||||
/* GetViewValue 12. */
|
||||
uint8_t *block_p = ecma_arraybuffer_get_buffer (buffer_p) + (uint32_t) get_index + view_offset;
|
||||
|
||||
if (ecma_is_value_empty (value_to_set))
|
||||
{
|
||||
JERRY_VLA (lit_utf8_byte_t, swap_block_p, element_size);
|
||||
memcpy (swap_block_p, block_p, element_size * sizeof (lit_utf8_byte_t));
|
||||
ecma_dataview_swap_order (system_is_little_endian, is_little_endian, element_size, swap_block_p);
|
||||
info.buffer_p = swap_block_p;
|
||||
return ecma_get_typedarray_element (&info, 0);
|
||||
|
||||
ecma_typedarray_getter_fn_t typedarray_getter_cb = ecma_get_typedarray_getter_fn (info.id);
|
||||
return typedarray_getter_cb (swap_block_p);
|
||||
}
|
||||
|
||||
if (!ecma_number_is_nan (get_index) && get_index <= 0)
|
||||
{
|
||||
get_index = 0;
|
||||
}
|
||||
|
||||
/* SetViewValue 14. */
|
||||
info.buffer_p = block_p;
|
||||
ecma_value_t set_element = ecma_set_typedarray_element (&info, value_to_set, 0);
|
||||
ecma_typedarray_setter_fn_t typedarray_setter_cb = ecma_get_typedarray_setter_fn (info.id);
|
||||
ecma_value_t set_element = typedarray_setter_cb (block_p, value_to_set);
|
||||
|
||||
ecma_free_value (value_to_set);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (set_element))
|
||||
|
||||
@ -13,17 +13,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecma-shared-arraybuffer-object.h"
|
||||
#include "ecma-typedarray-object.h"
|
||||
#include "ecma-objects.h"
|
||||
#include "ecma-arraybuffer-object.h"
|
||||
#include "ecma-builtins.h"
|
||||
#include "ecma-exceptions.h"
|
||||
#include "ecma-function-object.h"
|
||||
#include "ecma-gc.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "jmem.h"
|
||||
#include "ecma-objects.h"
|
||||
#include "ecma-shared-arraybuffer-object.h"
|
||||
#include "ecma-typedarray-object.h"
|
||||
#include "jcontext.h"
|
||||
#include "ecma-function-object.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
@ -35,65 +35,21 @@
|
||||
#if JERRY_BUILTIN_SHAREDARRAYBUFFER
|
||||
|
||||
/**
|
||||
* Helper function: create SharedArrayBuffer object based on the array length
|
||||
* Creating SharedArrayBuffer objects based on the array length
|
||||
*
|
||||
* The struct of arraybuffer object:
|
||||
* ecma_object_t
|
||||
* extend_part
|
||||
* data buffer
|
||||
*
|
||||
* @return ecma_object_t *
|
||||
* @return new SharedArrayBuffer object
|
||||
*/
|
||||
ecma_object_t *
|
||||
ecma_shared_arraybuffer_new_object (uint32_t length) /**< length of the SharedArrayBuffer */
|
||||
{
|
||||
ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_SHARED_ARRAYBUFFER_PROTOTYPE);
|
||||
ecma_object_t *object_p = ecma_create_object (prototype_obj_p,
|
||||
sizeof (ecma_extended_object_t) + length,
|
||||
ECMA_OBJECT_TYPE_CLASS);
|
||||
if (length > 0)
|
||||
{
|
||||
return ecma_arraybuffer_create_object_with_buffer (ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER, length);
|
||||
}
|
||||
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER;
|
||||
ext_object_p->u.cls.u1.array_buffer_flags = ECMA_ARRAYBUFFER_INTERNAL_MEMORY;
|
||||
ext_object_p->u.cls.u3.length = length;
|
||||
|
||||
lit_utf8_byte_t *buf = (lit_utf8_byte_t *) (ext_object_p + 1);
|
||||
memset (buf, 0, length);
|
||||
|
||||
return object_p;
|
||||
return ecma_arraybuffer_create_object (ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER, length);
|
||||
} /* ecma_shared_arraybuffer_new_object */
|
||||
|
||||
/**
|
||||
* Helper function: create SharedArrayBuffer object with external buffer backing.
|
||||
*
|
||||
* The struct of external arraybuffer object:
|
||||
* ecma_object_t
|
||||
* extend_part
|
||||
* SharedArrayBuffer external info part
|
||||
*
|
||||
* @return ecma_object_t *, pointer to the created SharedArrayBuffer object
|
||||
*/
|
||||
ecma_object_t *
|
||||
ecma_shared_arraybuffer_new_object_external (uint32_t length, /**< length of the buffer_p to use */
|
||||
void *buffer_p, /**< pointer for SharedArrayBuffer's buffer backing */
|
||||
jerry_value_free_callback_t free_cb) /**< buffer free callback */
|
||||
{
|
||||
ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_SHARED_ARRAYBUFFER_PROTOTYPE);
|
||||
ecma_object_t *object_p = ecma_create_object (prototype_obj_p,
|
||||
sizeof (ecma_arraybuffer_external_info),
|
||||
ECMA_OBJECT_TYPE_CLASS);
|
||||
|
||||
ecma_arraybuffer_external_info *array_object_p = (ecma_arraybuffer_external_info *) object_p;
|
||||
array_object_p->extended_object.u.cls.type = ECMA_OBJECT_CLASS_SHARED_ARRAY_BUFFER;
|
||||
array_object_p->extended_object.u.cls.u1.array_buffer_flags = ECMA_ARRAYBUFFER_EXTERNAL_MEMORY;
|
||||
array_object_p->extended_object.u.cls.u3.length = length;
|
||||
|
||||
array_object_p->buffer_p = buffer_p;
|
||||
array_object_p->free_cb = free_cb;
|
||||
|
||||
return object_p;
|
||||
} /* ecma_shared_arraybuffer_new_object_external */
|
||||
|
||||
/**
|
||||
* SharedArrayBuffer object creation operation.
|
||||
*
|
||||
|
||||
@ -35,10 +35,6 @@ ecma_op_create_shared_arraybuffer_object (const ecma_value_t *, uint32_t);
|
||||
*/
|
||||
ecma_object_t *
|
||||
ecma_shared_arraybuffer_new_object (uint32_t lengh);
|
||||
ecma_object_t *
|
||||
ecma_shared_arraybuffer_new_object_external (uint32_t length,
|
||||
void *buffer_p,
|
||||
jerry_value_free_callback_t free_cb);
|
||||
#endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */
|
||||
bool
|
||||
ecma_is_shared_arraybuffer (ecma_value_t val);
|
||||
|
||||
@ -622,34 +622,35 @@ ecma_get_typedarray_magic_string_id (ecma_typedarray_type_t typedarray_id)
|
||||
* @return ecma_typedarray_getter_fn_t: the getter function for the given builtin TypedArray id
|
||||
*/
|
||||
extern inline ecma_typedarray_getter_fn_t JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_get_typedarray_getter_fn (ecma_typedarray_type_t typedarray_id)
|
||||
ecma_get_typedarray_getter_fn (ecma_typedarray_type_t typedarray_id) /**< typedarray id */
|
||||
{
|
||||
return ecma_typedarray_getters[typedarray_id];
|
||||
} /* ecma_get_typedarray_getter_fn */
|
||||
|
||||
/**
|
||||
* get typedarray's element value
|
||||
* Get element from a TypedArray
|
||||
*
|
||||
* @return ecma_number_t: the value of the element
|
||||
* @return the value of the element
|
||||
*/
|
||||
extern inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_get_typedarray_element (ecma_typedarray_info_t *info_p,
|
||||
ecma_number_t num)
|
||||
ecma_get_typedarray_element (ecma_typedarray_info_t *info_p, /**< typedarray info */
|
||||
ecma_number_t num) /**< element index */
|
||||
{
|
||||
if (ecma_arraybuffer_is_detached (info_p->array_buffer_p))
|
||||
uint8_t *buffer_p = ecma_typedarray_get_buffer (info_p);
|
||||
|
||||
if (JERRY_UNLIKELY (buffer_p == NULL))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_arraybuffer_is_detached));
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
if (!ecma_op_is_integer (num)
|
||||
if (ecma_number_is_negative (num)
|
||||
|| num >= info_p->length
|
||||
|| num < 0
|
||||
|| (ecma_number_is_negative (num) && ecma_number_is_zero (num)))
|
||||
|| ((ecma_number_t) (uint32_t) num) != num)
|
||||
{
|
||||
return ECMA_VALUE_UNDEFINED;
|
||||
}
|
||||
uint32_t byte_pos = (uint32_t) num << info_p->shift;
|
||||
return ecma_typedarray_getters[info_p->id](info_p->buffer_p + byte_pos);
|
||||
|
||||
return ecma_typedarray_getters[info_p->id](buffer_p + ((uint32_t) num << info_p->shift));
|
||||
} /* ecma_get_typedarray_element */
|
||||
|
||||
/**
|
||||
@ -658,7 +659,7 @@ ecma_get_typedarray_element (ecma_typedarray_info_t *info_p,
|
||||
* @return ecma_typedarray_setter_fn_t: the setter function for the given builtin TypedArray id
|
||||
*/
|
||||
extern inline ecma_typedarray_setter_fn_t JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_get_typedarray_setter_fn (ecma_typedarray_type_t typedarray_id)
|
||||
ecma_get_typedarray_setter_fn (ecma_typedarray_type_t typedarray_id) /**< typedarray id */
|
||||
{
|
||||
return ecma_typedarray_setters[typedarray_id];
|
||||
} /* ecma_get_typedarray_setter_fn */
|
||||
@ -667,9 +668,9 @@ ecma_get_typedarray_setter_fn (ecma_typedarray_type_t typedarray_id)
|
||||
* set typedarray's element value
|
||||
*/
|
||||
extern inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_set_typedarray_element (ecma_typedarray_info_t *info_p,
|
||||
ecma_value_t value,
|
||||
ecma_number_t num)
|
||||
ecma_set_typedarray_element (ecma_typedarray_info_t *info_p, /**< typedarray info */
|
||||
ecma_value_t value, /**< value to be set */
|
||||
ecma_number_t num) /**< element index */
|
||||
{
|
||||
ecma_value_t to_num;
|
||||
if (ECMA_TYPEDARRAY_IS_BIGINT_TYPE (info_p->id))
|
||||
@ -692,23 +693,25 @@ ecma_set_typedarray_element (ecma_typedarray_info_t *info_p,
|
||||
}
|
||||
}
|
||||
|
||||
if (ecma_arraybuffer_is_detached (info_p->array_buffer_p))
|
||||
uint8_t *buffer_p = ecma_typedarray_get_buffer (info_p);
|
||||
|
||||
if (JERRY_UNLIKELY (buffer_p == NULL))
|
||||
{
|
||||
ecma_free_value (to_num);
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_arraybuffer_is_detached));
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
if (!ecma_op_is_integer (num)
|
||||
if (ecma_number_is_negative (num)
|
||||
|| num >= info_p->length
|
||||
|| num < 0
|
||||
|| (ecma_number_is_negative (num) && ecma_number_is_zero (num)))
|
||||
|| ((ecma_number_t) (uint32_t) num) != num)
|
||||
{
|
||||
ecma_free_value (to_num);
|
||||
return ECMA_VALUE_FALSE;
|
||||
}
|
||||
|
||||
ecma_free_value (to_num);
|
||||
lit_utf8_byte_t *src_buffer = info_p->buffer_p + ((uint32_t) num << info_p->shift);
|
||||
return ecma_typedarray_setters[info_p->id](src_buffer, value);
|
||||
|
||||
return ecma_typedarray_setters[info_p->id](buffer_p + ((uint32_t) num << info_p->shift), value);
|
||||
} /* ecma_set_typedarray_element */
|
||||
|
||||
/**
|
||||
@ -830,6 +833,7 @@ ecma_typedarray_create_object_with_length (uint32_t array_length, /**< length of
|
||||
else
|
||||
{
|
||||
ecma_value_t ctor_proto = ecma_op_species_constructor (src_buffer_p, ECMA_BUILTIN_ID_ARRAYBUFFER);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (ctor_proto))
|
||||
{
|
||||
return ctor_proto;
|
||||
@ -856,7 +860,7 @@ ecma_typedarray_create_object_with_length (uint32_t array_length, /**< length of
|
||||
if (ecma_arraybuffer_is_detached (src_buffer_p))
|
||||
{
|
||||
ecma_deref_object (new_arraybuffer_p);
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Maximum TypedArray size is reached"));
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_arraybuffer_is_detached));
|
||||
}
|
||||
}
|
||||
|
||||
@ -875,53 +879,6 @@ ecma_typedarray_create_object_with_length (uint32_t array_length, /**< length of
|
||||
return ecma_make_object_value (object_p);
|
||||
} /* ecma_typedarray_create_object_with_length */
|
||||
|
||||
/**
|
||||
* Create a TypedArray object by given buffer, offset, and array_length
|
||||
*
|
||||
* See also: ES2015 22.2.1.5
|
||||
*
|
||||
* @return ecma value of the new typedarray object
|
||||
* Returned value must be freed with ecma_free_value
|
||||
*/
|
||||
static ecma_value_t
|
||||
ecma_typedarray_create_object_with_buffer (ecma_object_t *arraybuffer_p, /**< the arraybuffer inside */
|
||||
uint32_t byte_offset, /**< the byte offset of the arraybuffer */
|
||||
uint32_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 */
|
||||
ecma_typedarray_type_t typedarray_id) /**< id of the typedarray */
|
||||
{
|
||||
if (ecma_arraybuffer_is_detached (arraybuffer_p))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_arraybuffer_is_detached));
|
||||
}
|
||||
uint32_t expected_length = (ecma_arraybuffer_get_length (arraybuffer_p) >> element_size_shift);
|
||||
|
||||
bool needs_ext_typedarray_obj = (byte_offset != 0 || array_length != expected_length);
|
||||
|
||||
size_t object_size = (needs_ext_typedarray_obj ? sizeof (ecma_extended_typedarray_object_t)
|
||||
: sizeof (ecma_extended_object_t));
|
||||
|
||||
ecma_object_t *object_p = ecma_create_object (proto_p, object_size, ECMA_OBJECT_TYPE_CLASS);
|
||||
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_TYPEDARRAY;
|
||||
ext_object_p->u.cls.u1.typedarray_type = (uint8_t) typedarray_id;
|
||||
ext_object_p->u.cls.u2.typedarray_flags = 0;
|
||||
ext_object_p->u.cls.u3.arraybuffer = ecma_make_object_value (arraybuffer_p);
|
||||
|
||||
if (needs_ext_typedarray_obj)
|
||||
{
|
||||
ext_object_p->u.cls.u2.typedarray_flags |= ECMA_TYPEDARRAY_IS_EXTENDED;
|
||||
|
||||
ecma_extended_typedarray_object_t *typedarray_info_p = (ecma_extended_typedarray_object_t *) object_p;
|
||||
typedarray_info_p->array_length = array_length;
|
||||
typedarray_info_p->byte_offset = byte_offset;
|
||||
}
|
||||
|
||||
return ecma_make_object_value (object_p);
|
||||
} /* ecma_typedarray_create_object_with_buffer */
|
||||
|
||||
/**
|
||||
* Create a TypedArray object by given another TypedArray object
|
||||
*
|
||||
@ -938,9 +895,10 @@ ecma_typedarray_create_object_with_typedarray (ecma_object_t *typedarray_p, /**<
|
||||
{
|
||||
uint32_t array_length = ecma_typedarray_get_length (typedarray_p);
|
||||
ecma_object_t *src_arraybuffer_p = ecma_typedarray_get_arraybuffer (typedarray_p);
|
||||
if (ecma_arraybuffer_is_detached (src_arraybuffer_p))
|
||||
|
||||
if (ECMA_ARRAYBUFFER_CHECK_BUFFER_ERROR (src_arraybuffer_p))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Invalid detached ArrayBuffer"));
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
ecma_value_t new_typedarray = ecma_typedarray_create_object_with_length (array_length,
|
||||
@ -955,10 +913,14 @@ ecma_typedarray_create_object_with_typedarray (ecma_object_t *typedarray_p, /**<
|
||||
}
|
||||
|
||||
ecma_object_t *new_typedarray_p = ecma_get_object_from_value (new_typedarray);
|
||||
ecma_object_t *dst_arraybuffer_p = ecma_typedarray_get_arraybuffer (new_typedarray_p);
|
||||
|
||||
if (ECMA_ARRAYBUFFER_CHECK_BUFFER_ERROR (dst_arraybuffer_p))
|
||||
{
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
lit_utf8_byte_t *src_buf_p = ecma_arraybuffer_get_buffer (src_arraybuffer_p);
|
||||
|
||||
ecma_object_t *dst_arraybuffer_p = ecma_typedarray_get_arraybuffer (new_typedarray_p);
|
||||
lit_utf8_byte_t *dst_buf_p = ecma_arraybuffer_get_buffer (dst_arraybuffer_p);
|
||||
|
||||
src_buf_p += ecma_typedarray_get_offset (typedarray_p);
|
||||
@ -1017,15 +979,10 @@ ecma_op_typedarray_from_helper (ecma_value_t this_val, /**< this_arg for the abo
|
||||
ecma_value_t current_value, /**< given value to set */
|
||||
uint32_t index, /**< currrent index */
|
||||
ecma_object_t *func_object_p, /**< map function object */
|
||||
ecma_typedarray_info_t *info_p, /**< typedarray info */
|
||||
uint8_t *buffer_p, /**< target buffer */
|
||||
ecma_typedarray_setter_fn_t setter_cb) /**< setter callback function */
|
||||
{
|
||||
ecma_value_t mapped_value;
|
||||
|
||||
if (!ecma_is_value_found (current_value))
|
||||
{
|
||||
current_value = ECMA_VALUE_UNDEFINED;
|
||||
}
|
||||
ecma_value_t mapped_value = current_value;
|
||||
|
||||
if (func_object_p != NULL)
|
||||
{
|
||||
@ -1045,17 +1002,8 @@ ecma_op_typedarray_from_helper (ecma_value_t this_val, /**< this_arg for the abo
|
||||
|
||||
mapped_value = cb_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
mapped_value = current_value;
|
||||
}
|
||||
|
||||
if (index >= info_p->length)
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Invalid argument type"));
|
||||
}
|
||||
|
||||
ecma_value_t set_element = setter_cb (info_p->buffer_p + (index << info_p->shift), mapped_value);
|
||||
ecma_value_t set_element = setter_cb (buffer_p, mapped_value);
|
||||
ecma_free_value (mapped_value);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (set_element))
|
||||
@ -1080,7 +1028,6 @@ ecma_typedarray_create_object_with_object (ecma_value_t items_val, /**< the sour
|
||||
uint8_t element_size_shift, /**< the size shift of the element length */
|
||||
ecma_typedarray_type_t typedarray_id) /**< id of the typedarray */
|
||||
{
|
||||
|
||||
/* 5 */
|
||||
ecma_value_t using_iterator = ecma_op_get_method_by_symbol_id (items_val, LIT_GLOBAL_SYMBOL_ITERATOR);
|
||||
|
||||
@ -1156,39 +1103,48 @@ ecma_typedarray_create_object_with_object (ecma_value_t items_val, /**< the sour
|
||||
|
||||
ecma_object_t *new_typedarray_p = ecma_get_object_from_value (new_typedarray);
|
||||
ecma_typedarray_info_t info = ecma_typedarray_get_info (new_typedarray_p);
|
||||
ecma_typedarray_setter_fn_t setter_cb = ecma_get_typedarray_setter_fn (info.id);
|
||||
ecma_value_t *next_value_p = values_p->buffer_p;
|
||||
uint8_t *buffer_p = ecma_typedarray_get_buffer (&info);
|
||||
|
||||
ret_value = ecma_make_object_value (new_typedarray_p);
|
||||
ret_value = ECMA_VALUE_ERROR;
|
||||
|
||||
/* 8.e */
|
||||
for (uint32_t index = 0; index < values_p->item_count; index++)
|
||||
if (buffer_p != NULL)
|
||||
{
|
||||
ecma_value_t set_value = ecma_op_typedarray_from_helper (ECMA_VALUE_UNDEFINED,
|
||||
values_p->buffer_p[index],
|
||||
index,
|
||||
NULL,
|
||||
&info,
|
||||
setter_cb);
|
||||
ecma_typedarray_setter_fn_t setter_cb = ecma_get_typedarray_setter_fn (info.id);
|
||||
uint8_t *limit_p = buffer_p + (values_p->item_count << info.shift);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (set_value))
|
||||
ret_value = ecma_make_object_value (new_typedarray_p);
|
||||
|
||||
/* 8.e */
|
||||
while (buffer_p < limit_p)
|
||||
{
|
||||
for (uint32_t j = index + 1; j < values_p->item_count; j++)
|
||||
ecma_value_t value = *next_value_p++;
|
||||
ecma_value_t set_value = setter_cb (buffer_p, value);
|
||||
ecma_free_value (value);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (set_value))
|
||||
{
|
||||
ecma_free_value (values_p->buffer_p[j]);
|
||||
ret_value = set_value;
|
||||
break;
|
||||
}
|
||||
|
||||
ret_value = set_value;
|
||||
break;
|
||||
buffer_p += info.element_size;
|
||||
}
|
||||
}
|
||||
|
||||
ecma_collection_destroy (values_p);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (ret_value))
|
||||
{
|
||||
ecma_value_t *last_value_p = values_p->buffer_p + values_p->item_count;
|
||||
|
||||
while (next_value_p < last_value_p)
|
||||
{
|
||||
ecma_free_value (*next_value_p++);
|
||||
}
|
||||
|
||||
ecma_deref_object (new_typedarray_p);
|
||||
}
|
||||
|
||||
ecma_collection_destroy (values_p);
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
@ -1235,31 +1191,41 @@ ecma_typedarray_create_object_with_object (ecma_value_t items_val, /**< the sour
|
||||
|
||||
ecma_object_t *new_typedarray_p = ecma_get_object_from_value (new_typedarray);
|
||||
ecma_typedarray_info_t info = ecma_typedarray_get_info (new_typedarray_p);
|
||||
ecma_typedarray_setter_fn_t setter_cb = ecma_get_typedarray_setter_fn (info.id);
|
||||
ecma_value_t ret_value = ecma_make_object_value (new_typedarray_p);
|
||||
uint8_t *buffer_p = ecma_typedarray_get_buffer (&info);
|
||||
ecma_value_t ret_value = ECMA_VALUE_ERROR;
|
||||
|
||||
/* 12 */
|
||||
for (uint32_t index = 0; index < len; index++)
|
||||
if (buffer_p != NULL)
|
||||
{
|
||||
ecma_value_t current_value = ecma_op_object_find_by_index (arraylike_object_p, index);
|
||||
ecma_typedarray_setter_fn_t setter_cb = ecma_get_typedarray_setter_fn (info.id);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (current_value))
|
||||
ret_value = ecma_make_object_value (new_typedarray_p);
|
||||
|
||||
/* 12 */
|
||||
for (uint32_t index = 0; index < len; index++)
|
||||
{
|
||||
ret_value = current_value;
|
||||
break;
|
||||
}
|
||||
ecma_value_t value = ecma_op_object_find_by_index (arraylike_object_p, index);
|
||||
|
||||
ecma_value_t set_value = ecma_op_typedarray_from_helper (ECMA_VALUE_UNDEFINED,
|
||||
current_value,
|
||||
index,
|
||||
NULL,
|
||||
&info,
|
||||
setter_cb);
|
||||
if (ECMA_IS_VALUE_ERROR (value))
|
||||
{
|
||||
ret_value = value;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (set_value))
|
||||
{
|
||||
ret_value = set_value;
|
||||
break;
|
||||
if (!ecma_is_value_found (value))
|
||||
{
|
||||
value = ECMA_VALUE_UNDEFINED;
|
||||
}
|
||||
|
||||
ecma_value_t set_value = setter_cb (buffer_p, value);
|
||||
ecma_free_value (value);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (set_value))
|
||||
{
|
||||
ret_value = set_value;
|
||||
break;
|
||||
}
|
||||
|
||||
buffer_p += info.element_size;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1377,38 +1343,48 @@ ecma_op_typedarray_from (ecma_value_t this_val, /**< this value */
|
||||
ecma_object_t *new_typedarray_p = ecma_get_object_from_value (new_typedarray);
|
||||
ecma_typedarray_info_t info = ecma_typedarray_get_info (new_typedarray_p);
|
||||
ecma_typedarray_setter_fn_t setter_cb = ecma_get_typedarray_setter_fn (info.id);
|
||||
ecma_value_t *next_value_p = values_p->buffer_p;
|
||||
uint8_t *buffer_p = ecma_typedarray_get_buffer (&info);
|
||||
|
||||
ret_value = ecma_make_object_value (new_typedarray_p);
|
||||
ret_value = ECMA_VALUE_ERROR;
|
||||
|
||||
/* 6.e */
|
||||
for (uint32_t index = 0; index < values_p->item_count; index++)
|
||||
if (buffer_p != NULL)
|
||||
{
|
||||
ecma_value_t set_value = ecma_op_typedarray_from_helper (this_arg,
|
||||
values_p->buffer_p[index],
|
||||
index,
|
||||
func_object_p,
|
||||
&info,
|
||||
setter_cb);
|
||||
ret_value = ecma_make_object_value (new_typedarray_p);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (set_value))
|
||||
/* 6.e */
|
||||
for (uint32_t index = 0; index < values_p->item_count; index++)
|
||||
{
|
||||
for (uint32_t j = index + 1; j < values_p->item_count; j++)
|
||||
ecma_value_t set_value = ecma_op_typedarray_from_helper (this_arg,
|
||||
*next_value_p++,
|
||||
index,
|
||||
func_object_p,
|
||||
buffer_p,
|
||||
setter_cb);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (set_value))
|
||||
{
|
||||
ecma_free_value (values_p->buffer_p[j]);
|
||||
ret_value = set_value;
|
||||
break;
|
||||
}
|
||||
|
||||
ret_value = set_value;
|
||||
break;
|
||||
buffer_p += info.element_size;
|
||||
}
|
||||
}
|
||||
|
||||
ecma_collection_destroy (values_p);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (ret_value))
|
||||
{
|
||||
ecma_value_t *last_value_p = values_p->buffer_p + values_p->item_count;
|
||||
|
||||
while (next_value_p < last_value_p)
|
||||
{
|
||||
ecma_free_value (*next_value_p++);
|
||||
}
|
||||
|
||||
ecma_deref_object (new_typedarray_p);
|
||||
}
|
||||
|
||||
ecma_collection_destroy (values_p);
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
@ -1454,31 +1430,45 @@ ecma_op_typedarray_from (ecma_value_t this_val, /**< this value */
|
||||
|
||||
ecma_object_t *new_typedarray_p = ecma_get_object_from_value (new_typedarray);
|
||||
ecma_typedarray_info_t info = ecma_typedarray_get_info (new_typedarray_p);
|
||||
ecma_typedarray_setter_fn_t setter_cb = ecma_get_typedarray_setter_fn (info.id);
|
||||
ecma_value_t ret_value = ecma_make_object_value (new_typedarray_p);
|
||||
uint8_t *buffer_p = ecma_typedarray_get_buffer (&info);
|
||||
ecma_value_t ret_value = ECMA_VALUE_ERROR;
|
||||
|
||||
/* 12 */
|
||||
for (uint32_t index = 0; index < len; index++)
|
||||
if (buffer_p != NULL)
|
||||
{
|
||||
ecma_value_t current_value = ecma_op_object_find_by_index (arraylike_object_p, index);
|
||||
ecma_typedarray_setter_fn_t setter_cb = ecma_get_typedarray_setter_fn (info.id);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (current_value))
|
||||
ret_value = ecma_make_object_value (new_typedarray_p);
|
||||
|
||||
/* 12 */
|
||||
for (uint32_t index = 0; index < len; index++)
|
||||
{
|
||||
ret_value = current_value;
|
||||
break;
|
||||
}
|
||||
ecma_value_t value = ecma_op_object_find_by_index (arraylike_object_p, index);
|
||||
|
||||
ecma_value_t set_value = ecma_op_typedarray_from_helper (this_arg,
|
||||
current_value,
|
||||
index,
|
||||
func_object_p,
|
||||
&info,
|
||||
setter_cb);
|
||||
if (ECMA_IS_VALUE_ERROR (value))
|
||||
{
|
||||
ret_value = value;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (set_value))
|
||||
{
|
||||
ret_value = set_value;
|
||||
break;
|
||||
if (!ecma_is_value_found (value))
|
||||
{
|
||||
value = ECMA_VALUE_UNDEFINED;
|
||||
}
|
||||
|
||||
ecma_value_t set_value = ecma_op_typedarray_from_helper (this_arg,
|
||||
value,
|
||||
index,
|
||||
func_object_p,
|
||||
buffer_p,
|
||||
setter_cb);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (set_value))
|
||||
{
|
||||
ret_value = set_value;
|
||||
break;
|
||||
}
|
||||
|
||||
buffer_p += info.element_size;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1543,6 +1533,7 @@ ecma_typedarray_get_length (ecma_object_t *typedarray_p) /**< the pointer to the
|
||||
}
|
||||
|
||||
ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (typedarray_p);
|
||||
|
||||
if (ecma_arraybuffer_is_detached (arraybuffer_p))
|
||||
{
|
||||
return 0;
|
||||
@ -1571,6 +1562,7 @@ ecma_typedarray_get_offset (ecma_object_t *typedarray_p) /**< the pointer to the
|
||||
}
|
||||
|
||||
ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (typedarray_p);
|
||||
|
||||
if (ecma_arraybuffer_is_detached (arraybuffer_p))
|
||||
{
|
||||
return 0;
|
||||
@ -1582,16 +1574,22 @@ ecma_typedarray_get_offset (ecma_object_t *typedarray_p) /**< the pointer to the
|
||||
} /* ecma_typedarray_get_offset */
|
||||
|
||||
/**
|
||||
* Utility function: return the pointer of the data buffer referenced by the typed array
|
||||
* Utility function: return the pointer of the data buffer referenced by the typedarray info
|
||||
*
|
||||
* @return pointer to the data buffer
|
||||
* @return pointer to the data buffer if successfull,
|
||||
* NULL otherwise
|
||||
*/
|
||||
lit_utf8_byte_t *
|
||||
ecma_typedarray_get_buffer (ecma_object_t *typedarray_p) /**< the pointer to the typed array object */
|
||||
uint8_t *
|
||||
ecma_typedarray_get_buffer (ecma_typedarray_info_t *info_p) /**< typedarray info */
|
||||
{
|
||||
ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (typedarray_p);
|
||||
ecma_object_t *array_buffer_p = info_p->array_buffer_p;
|
||||
|
||||
return ecma_arraybuffer_get_buffer (arraybuffer_p) + ecma_typedarray_get_offset (typedarray_p);
|
||||
if (ECMA_ARRAYBUFFER_CHECK_BUFFER_ERROR (array_buffer_p))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ecma_arraybuffer_get_buffer (array_buffer_p) + info_p->offset;
|
||||
} /* ecma_typedarray_get_buffer */
|
||||
|
||||
/**
|
||||
@ -1614,14 +1612,13 @@ ecma_op_create_typedarray (const ecma_value_t *arguments_list_p, /**< the arg li
|
||||
{
|
||||
JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);
|
||||
|
||||
ecma_value_t ret = ECMA_VALUE_EMPTY;
|
||||
|
||||
if (arguments_list_len == 0)
|
||||
{
|
||||
/* 22.2.1.1 */
|
||||
ret = ecma_typedarray_create_object_with_length (0, NULL, proto_p, element_size_shift, typedarray_id);
|
||||
return ecma_typedarray_create_object_with_length (0, NULL, proto_p, element_size_shift, typedarray_id);
|
||||
}
|
||||
else if (!ecma_is_value_object (arguments_list_p[0]))
|
||||
|
||||
if (!ecma_is_value_object (arguments_list_p[0]))
|
||||
{
|
||||
ecma_number_t num = 0;
|
||||
|
||||
@ -1636,127 +1633,144 @@ ecma_op_create_typedarray (const ecma_value_t *arguments_list_p, /**< the arg li
|
||||
if (num > UINT32_MAX)
|
||||
{
|
||||
#if JERRY_ERROR_MESSAGES
|
||||
ret = ecma_raise_standard_error_with_format (JERRY_ERROR_RANGE,
|
||||
"Invalid typed array length: %",
|
||||
arguments_list_p[0]);
|
||||
return ecma_raise_standard_error_with_format (JERRY_ERROR_RANGE,
|
||||
"Invalid typed array length: %",
|
||||
arguments_list_p[0]);
|
||||
#else /* !JERRY_ERROR_MESSAGES */
|
||||
ret = ecma_raise_range_error (NULL);
|
||||
return ecma_raise_range_error (NULL);
|
||||
#endif /* JERRY_ERROR_MESSAGES */
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = ecma_typedarray_create_object_with_length ((uint32_t) num,
|
||||
NULL,
|
||||
proto_p,
|
||||
element_size_shift,
|
||||
typedarray_id);
|
||||
}
|
||||
|
||||
return ecma_typedarray_create_object_with_length ((uint32_t) num,
|
||||
NULL,
|
||||
proto_p,
|
||||
element_size_shift,
|
||||
typedarray_id);
|
||||
}
|
||||
else if (ecma_is_value_object (arguments_list_p[0]))
|
||||
|
||||
ecma_object_t *obj_p = ecma_get_object_from_value (arguments_list_p[0]);
|
||||
|
||||
if (ecma_object_is_typedarray (obj_p))
|
||||
{
|
||||
ecma_object_t *obj_p = ecma_get_object_from_value (arguments_list_p[0]);
|
||||
if (ecma_object_is_typedarray (obj_p))
|
||||
/* 22.2.1.3 */
|
||||
ecma_object_t *typedarray_p = obj_p;
|
||||
return ecma_typedarray_create_object_with_typedarray (typedarray_p,
|
||||
proto_p,
|
||||
element_size_shift,
|
||||
typedarray_id);
|
||||
}
|
||||
|
||||
if (!ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER)
|
||||
&& !ecma_object_is_shared_arraybuffer (obj_p))
|
||||
{
|
||||
/* 22.2.1.4 */
|
||||
return ecma_typedarray_create_object_with_object (arguments_list_p[0],
|
||||
proto_p,
|
||||
element_size_shift,
|
||||
typedarray_id);
|
||||
}
|
||||
|
||||
/* 22.2.1.5 */
|
||||
ecma_object_t *arraybuffer_p = obj_p;
|
||||
ecma_value_t byte_offset_value = ((arguments_list_len > 1) ? arguments_list_p[1]
|
||||
: ECMA_VALUE_UNDEFINED);
|
||||
|
||||
ecma_value_t length_value = ((arguments_list_len > 2) ? arguments_list_p[2]
|
||||
: ECMA_VALUE_UNDEFINED);
|
||||
|
||||
ecma_number_t offset;
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (ecma_op_to_index (byte_offset_value, &offset)))
|
||||
{
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
if (ecma_number_is_negative (offset) || fmod (offset, (1 << element_size_shift)) != 0)
|
||||
{
|
||||
/* ES2015 22.2.1.5: 9 - 10. */
|
||||
if (ecma_number_is_zero (offset))
|
||||
{
|
||||
/* 22.2.1.3 */
|
||||
ecma_object_t *typedarray_p = obj_p;
|
||||
ret = ecma_typedarray_create_object_with_typedarray (typedarray_p,
|
||||
proto_p,
|
||||
element_size_shift,
|
||||
typedarray_id);
|
||||
}
|
||||
else if (ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_ARRAY_BUFFER)
|
||||
|| ecma_object_is_shared_arraybuffer (obj_p))
|
||||
{
|
||||
/* 22.2.1.5 */
|
||||
ecma_object_t *arraybuffer_p = obj_p;
|
||||
ecma_value_t arg2 = ((arguments_list_len > 1) ? arguments_list_p[1]
|
||||
: ECMA_VALUE_UNDEFINED);
|
||||
|
||||
ecma_value_t arg3 = ((arguments_list_len > 2) ? arguments_list_p[2]
|
||||
: ECMA_VALUE_UNDEFINED);
|
||||
|
||||
ecma_number_t offset;
|
||||
if (ECMA_IS_VALUE_ERROR (ecma_op_to_index (arg2, &offset)))
|
||||
{
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
if (ecma_number_is_negative (offset) && ecma_number_is_zero (offset))
|
||||
{
|
||||
offset = 0;
|
||||
}
|
||||
if (ecma_number_is_negative (offset) || fmod (offset, (1 << element_size_shift)) != 0)
|
||||
{
|
||||
/* ES2015 22.2.1.5: 9 - 10. */
|
||||
ret = ecma_raise_range_error (ECMA_ERR_MSG ("Invalid offset"));
|
||||
}
|
||||
else if (ecma_arraybuffer_is_detached (arraybuffer_p))
|
||||
{
|
||||
ret = ecma_raise_type_error (ECMA_ERR_MSG ("Invalid detached ArrayBuffer"));
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t buf_byte_length = ecma_arraybuffer_get_length (arraybuffer_p);
|
||||
uint32_t new_byte_length = 0;
|
||||
|
||||
if (ecma_is_value_undefined (arg3))
|
||||
{
|
||||
if ((buf_byte_length % (uint32_t) (1 << element_size_shift) != 0)
|
||||
|| (buf_byte_length < offset))
|
||||
{
|
||||
ret = ecma_raise_range_error (ECMA_ERR_MSG ("Invalid length"));
|
||||
}
|
||||
else
|
||||
{
|
||||
new_byte_length = (uint32_t) (buf_byte_length - offset);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_number_t new_length;
|
||||
if (ECMA_IS_VALUE_ERROR (ecma_op_to_index (arg3, &new_length)))
|
||||
{
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
if (new_length > (UINT32_MAX >> element_size_shift))
|
||||
{
|
||||
ret = ecma_raise_range_error (ECMA_ERR_MSG ("Maximum TypedArray size is reached"));
|
||||
}
|
||||
else
|
||||
{
|
||||
new_byte_length = (uint32_t) new_length << element_size_shift;
|
||||
|
||||
if (((ecma_number_t) new_byte_length + offset) > buf_byte_length)
|
||||
{
|
||||
ret = ecma_raise_range_error (ECMA_ERR_MSG ("Invalid length"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ecma_is_value_empty (ret))
|
||||
{
|
||||
uint32_t array_length = new_byte_length >> element_size_shift;
|
||||
ret = ecma_typedarray_create_object_with_buffer (arraybuffer_p,
|
||||
(uint32_t) offset,
|
||||
array_length,
|
||||
proto_p,
|
||||
element_size_shift,
|
||||
typedarray_id);
|
||||
}
|
||||
}
|
||||
offset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 22.2.1.4 */
|
||||
ret = ecma_typedarray_create_object_with_object (arguments_list_p[0],
|
||||
proto_p,
|
||||
element_size_shift,
|
||||
typedarray_id);
|
||||
return ecma_raise_range_error (ECMA_ERR_MSG ("Invalid offset"));
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
ecma_number_t new_length = 0;
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (ecma_op_to_index (length_value, &new_length)))
|
||||
{
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
if (ecma_arraybuffer_is_detached (arraybuffer_p))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_arraybuffer_is_detached));
|
||||
}
|
||||
|
||||
const char *invalid_length_p = ECMA_ERR_MSG ("Invalid length");
|
||||
|
||||
if (offset > UINT32_MAX)
|
||||
{
|
||||
return ecma_raise_range_error (invalid_length_p);
|
||||
}
|
||||
|
||||
uint32_t byte_offset = (uint32_t) offset;
|
||||
|
||||
uint32_t buf_byte_length = ecma_arraybuffer_get_length (arraybuffer_p);
|
||||
uint32_t new_byte_length = 0;
|
||||
|
||||
if (ecma_is_value_undefined (length_value))
|
||||
{
|
||||
if ((buf_byte_length % (uint32_t) (1 << element_size_shift) != 0)
|
||||
|| (buf_byte_length < byte_offset))
|
||||
{
|
||||
return ecma_raise_range_error (invalid_length_p);
|
||||
}
|
||||
|
||||
new_byte_length = (uint32_t) (buf_byte_length - byte_offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (new_length > (UINT32_MAX >> element_size_shift))
|
||||
{
|
||||
return ecma_raise_range_error (ECMA_ERR_MSG ("Maximum TypedArray size is reached"));
|
||||
}
|
||||
|
||||
new_byte_length = (uint32_t) new_length << element_size_shift;
|
||||
|
||||
if (byte_offset > buf_byte_length
|
||||
|| new_byte_length > (buf_byte_length - byte_offset))
|
||||
{
|
||||
return ecma_raise_range_error (invalid_length_p);
|
||||
}
|
||||
}
|
||||
|
||||
bool needs_ext_typedarray_obj = (byte_offset != 0 || new_byte_length != buf_byte_length);
|
||||
|
||||
size_t object_size = (needs_ext_typedarray_obj ? sizeof (ecma_extended_typedarray_object_t)
|
||||
: sizeof (ecma_extended_object_t));
|
||||
|
||||
ecma_object_t *object_p = ecma_create_object (proto_p, object_size, ECMA_OBJECT_TYPE_CLASS);
|
||||
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_TYPEDARRAY;
|
||||
ext_object_p->u.cls.u1.typedarray_type = (uint8_t) typedarray_id;
|
||||
ext_object_p->u.cls.u2.typedarray_flags = 0;
|
||||
ext_object_p->u.cls.u3.arraybuffer = ecma_make_object_value (arraybuffer_p);
|
||||
|
||||
if (needs_ext_typedarray_obj)
|
||||
{
|
||||
ext_object_p->u.cls.u2.typedarray_flags |= ECMA_TYPEDARRAY_IS_EXTENDED;
|
||||
|
||||
ecma_extended_typedarray_object_t *typedarray_info_p = (ecma_extended_typedarray_object_t *) object_p;
|
||||
typedarray_info_p->array_length = new_byte_length >> element_size_shift;
|
||||
typedarray_info_p->byte_offset = byte_offset;
|
||||
}
|
||||
|
||||
return ecma_make_object_value (object_p);
|
||||
} /* ecma_op_create_typedarray */
|
||||
|
||||
/**
|
||||
@ -1955,6 +1969,7 @@ ecma_typedarray_create (ecma_object_t *constructor_p, /**< constructor function
|
||||
ecma_object_t *typedarray_p = ecma_get_object_from_value (ret_val);
|
||||
|
||||
ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (ecma_get_object_from_value (ret_val));
|
||||
|
||||
if (ecma_arraybuffer_is_detached (arraybuffer_p))
|
||||
{
|
||||
ecma_deref_object (typedarray_p);
|
||||
@ -2065,7 +2080,6 @@ ecma_typedarray_get_info (ecma_object_t *typedarray_p)
|
||||
info.element_size = (uint8_t) (1 << info.shift);
|
||||
info.offset = ecma_typedarray_get_offset (typedarray_p);
|
||||
info.array_buffer_p = ecma_typedarray_get_arraybuffer (typedarray_p);
|
||||
info.buffer_p = ecma_arraybuffer_get_buffer (info.array_buffer_p) + info.offset;
|
||||
|
||||
return info;
|
||||
} /* ecma_typedarray_get_info */
|
||||
|
||||
@ -49,7 +49,7 @@ ecma_value_t ecma_op_typedarray_from (ecma_value_t this_val,
|
||||
ecma_value_t this_arg);
|
||||
uint32_t ecma_typedarray_get_length (ecma_object_t *typedarray_p);
|
||||
uint32_t ecma_typedarray_get_offset (ecma_object_t *typedarray_p);
|
||||
lit_utf8_byte_t *ecma_typedarray_get_buffer (ecma_object_t *typedarray_p);
|
||||
uint8_t *ecma_typedarray_get_buffer (ecma_typedarray_info_t *info_p);
|
||||
uint8_t ecma_typedarray_get_element_size_shift (ecma_object_t *typedarray_p);
|
||||
ecma_object_t *ecma_typedarray_get_arraybuffer (ecma_object_t *typedarray_p);
|
||||
ecma_value_t ecma_op_create_typedarray (const ecma_value_t *arguments_list_p,
|
||||
|
||||
@ -374,8 +374,7 @@ void jerry_free_source_info (jerry_source_info_t *source_info_p);
|
||||
bool jerry_value_is_arraybuffer (const jerry_value_t value);
|
||||
jerry_value_t jerry_create_arraybuffer (const jerry_length_t size);
|
||||
jerry_value_t jerry_create_arraybuffer_external (const jerry_length_t size,
|
||||
uint8_t *buffer_p,
|
||||
jerry_value_free_callback_t free_cb);
|
||||
uint8_t *buffer_p, void *buffer_user_p);
|
||||
jerry_length_t jerry_arraybuffer_write (const jerry_value_t value,
|
||||
jerry_length_t offset,
|
||||
const uint8_t *buf_p,
|
||||
@ -388,6 +387,11 @@ jerry_length_t jerry_get_arraybuffer_byte_length (const jerry_value_t value);
|
||||
uint8_t *jerry_get_arraybuffer_pointer (const jerry_value_t value);
|
||||
jerry_value_t jerry_is_arraybuffer_detachable (const jerry_value_t value);
|
||||
jerry_value_t jerry_detach_arraybuffer (const jerry_value_t value);
|
||||
bool jerry_arraybuffer_has_buffer (const jerry_value_t value);
|
||||
void jerry_arraybuffer_set_compact_allocation_limit (const jerry_length_t allocation_limit);
|
||||
void jerry_arraybuffer_set_allocator_callbacks (jerry_arraybuffer_allocate_t allocate_callback,
|
||||
jerry_arraybuffer_free_t free_callback,
|
||||
void *user_p);
|
||||
|
||||
/**
|
||||
* SharedArrayBuffer components.
|
||||
@ -396,8 +400,7 @@ jerry_value_t jerry_detach_arraybuffer (const jerry_value_t value);
|
||||
bool jerry_value_is_shared_arraybuffer (const jerry_value_t value);
|
||||
jerry_value_t jerry_create_shared_arraybuffer (const jerry_length_t size);
|
||||
jerry_value_t jerry_create_shared_arraybuffer_external (const jerry_length_t size,
|
||||
uint8_t *buffer_p,
|
||||
jerry_value_free_callback_t free_cb);
|
||||
uint8_t *buffer_p, void *buffer_user_p);
|
||||
|
||||
/**
|
||||
* DataView functions.
|
||||
|
||||
@ -818,6 +818,31 @@ typedef struct
|
||||
uint32_t source_range_length; /**< source length of the function in the source code */
|
||||
} jerry_source_info_t;
|
||||
|
||||
/**
|
||||
* Array buffer types.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Type of an array buffer.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
JERRY_ARRAYBUFFER_TYPE_ARRAYBUFFER, /**< the object is an array buffer object */
|
||||
JERRY_ARRAYBUFFER_TYPE_SHARED_ARRAYBUFFER, /**< the object is a shared array buffer object */
|
||||
} jerry_arraybuffer_type_t;
|
||||
|
||||
/**
|
||||
* Callback for allocating the backing store of array buffer or shared array buffer objects.
|
||||
*/
|
||||
typedef uint8_t *(*jerry_arraybuffer_allocate_t) (jerry_arraybuffer_type_t buffer_type, uint32_t buffer_size,
|
||||
void **arraybuffer_user_p, void *user_p);
|
||||
|
||||
/**
|
||||
* Callback for freeing the backing store of array buffer or shared array buffer objects.
|
||||
*/
|
||||
typedef void (*jerry_arraybuffer_free_t) (jerry_arraybuffer_type_t buffer_type, uint8_t *buffer_p,
|
||||
uint32_t buffer_size, void *arraybuffer_user_p, void *user_p);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@ -197,6 +197,15 @@ struct jerry_context_t
|
||||
#endif /* JERRY_PROMISE_CALLBACK */
|
||||
#endif /* JERRY_ESNEXT */
|
||||
|
||||
#if JERRY_BUILTIN_TYPEDARRAY
|
||||
uint32_t arraybuffer_compact_allocation_limit; /**< maximum size of compact allocation */
|
||||
jerry_arraybuffer_allocate_t arraybuffer_allocate_callback; /**< callback for allocating
|
||||
* arraybuffer memory */
|
||||
jerry_arraybuffer_free_t arraybuffer_free_callback; /**< callback for freeing arraybuffer memory */
|
||||
void *arraybuffer_allocate_callback_user_p; /**< user pointer passed to arraybuffer_allocate_callback
|
||||
* and arraybuffer_free_callback functions */
|
||||
#endif /* JERRY_BUILTIN_TYPEDARRAY */
|
||||
|
||||
#if JERRY_VM_EXEC_STOP
|
||||
uint32_t vm_exec_stop_frequency; /**< reset value for vm_exec_stop_counter */
|
||||
uint32_t vm_exec_stop_counter; /**< down counter for reducing the calls of vm_exec_stop_cb */
|
||||
|
||||
@ -151,21 +151,61 @@ static void test_write_with_offset (uint8_t offset) /**< offset for buffer write
|
||||
jerry_release_value (arraybuffer);
|
||||
} /* test_write_with_offset */
|
||||
|
||||
static bool callback_called = false;
|
||||
static bool detach_free_callback_called = false;
|
||||
static int allocate_mode = 0;
|
||||
static int allocate_count = 0;
|
||||
static int free_count = 0;
|
||||
|
||||
static void test_free_cb (void *buffer) /**< buffer to free (if needed) */
|
||||
static uint8_t *
|
||||
test_allocate_cb (jerry_arraybuffer_type_t buffer_type, /**< type of the array buffer object */
|
||||
uint32_t buffer_size, /**< size of the requested buffer */
|
||||
void **buffer_user_p, /**< [in/out] user pointer assigned to the array buffer object */
|
||||
void *user_p) /**< user pointer passed to jerry_arraybuffer_set_allocation_callbacks */
|
||||
{
|
||||
(void) buffer;
|
||||
callback_called = true;
|
||||
TEST_ASSERT (buffer_type == JERRY_ARRAYBUFFER_TYPE_ARRAYBUFFER);
|
||||
TEST_ASSERT (user_p == (void *) &allocate_mode);
|
||||
|
||||
if (*buffer_user_p != NULL)
|
||||
{
|
||||
TEST_ASSERT (*buffer_user_p == (void *) &allocate_count);
|
||||
TEST_ASSERT (buffer_size == 20);
|
||||
allocate_count++;
|
||||
*buffer_user_p = (void *) &free_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
*buffer_user_p = (void *) &allocate_mode;
|
||||
}
|
||||
return (uint8_t *) malloc (buffer_size);
|
||||
} /* test_allocate_cb */
|
||||
|
||||
static void
|
||||
test_free_cb (jerry_arraybuffer_type_t buffer_type, /**< type of the array buffer object */
|
||||
uint8_t *buffer_p, /**< pointer to the allocated buffer */
|
||||
uint32_t buffer_size, /**< size of the allocated buffer */
|
||||
void *buffer_user_p, /**< user pointer assigned to the array buffer object */
|
||||
void *user_p) /**< user pointer passed to jerry_arraybuffer_set_allocation_callbacks */
|
||||
{
|
||||
TEST_ASSERT (buffer_type == JERRY_ARRAYBUFFER_TYPE_ARRAYBUFFER);
|
||||
TEST_ASSERT (user_p == (void *) &allocate_mode);
|
||||
|
||||
if (buffer_user_p == NULL)
|
||||
{
|
||||
TEST_ASSERT (buffer_size == 15);
|
||||
free_count++;
|
||||
}
|
||||
else if (buffer_user_p == (void *) &free_count)
|
||||
{
|
||||
TEST_ASSERT (buffer_size == 20);
|
||||
free_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
TEST_ASSERT (buffer_user_p == (void *) &allocate_mode);
|
||||
}
|
||||
|
||||
free (buffer_p);
|
||||
} /* test_free_cb */
|
||||
|
||||
static void test_detach_free_cb (void *buffer) /**< buffer to free */
|
||||
{
|
||||
free (buffer);
|
||||
detach_free_callback_called = true;
|
||||
} /* test_detach_free_cb */
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
@ -178,6 +218,9 @@ main (void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
jerry_arraybuffer_set_compact_allocation_limit (4);
|
||||
jerry_arraybuffer_set_allocator_callbacks (test_allocate_cb, test_free_cb, (void *) &allocate_mode);
|
||||
|
||||
jerry_value_t function_val = jerry_create_external_function (assert_handler);
|
||||
register_js_value ("assert", function_val);
|
||||
jerry_release_value (function_val);
|
||||
@ -278,10 +321,10 @@ main (void)
|
||||
const uint32_t buffer_size = 15;
|
||||
const uint8_t base_value = 51;
|
||||
|
||||
JERRY_VLA (uint8_t, buffer_p, buffer_size);
|
||||
uint8_t *buffer_p = (uint8_t *) malloc (buffer_size);
|
||||
memset (buffer_p, base_value, buffer_size);
|
||||
|
||||
jerry_value_t arrayb = jerry_create_arraybuffer_external (buffer_size, buffer_p, test_free_cb);
|
||||
jerry_value_t arrayb = jerry_create_arraybuffer_external (buffer_size, buffer_p, NULL);
|
||||
uint8_t new_value = 123;
|
||||
jerry_length_t copied = jerry_arraybuffer_write (arrayb, 0, &new_value, 1);
|
||||
TEST_ASSERT (copied == 1);
|
||||
@ -310,9 +353,8 @@ main (void)
|
||||
/* Test ArrayBuffer external memory map/unmap */
|
||||
{
|
||||
const uint32_t buffer_size = 20;
|
||||
JERRY_VLA (uint8_t, buffer_p, buffer_size);
|
||||
|
||||
jerry_value_t input_buffer = jerry_create_arraybuffer_external (buffer_size, buffer_p, NULL);
|
||||
jerry_value_t input_buffer = jerry_create_arraybuffer_external (buffer_size, NULL, (void *) &allocate_count);
|
||||
register_js_value ("input_buffer", input_buffer);
|
||||
jerry_release_value (input_buffer);
|
||||
|
||||
@ -370,35 +412,43 @@ main (void)
|
||||
|
||||
/* Test internal ArrayBuffer detach */
|
||||
{
|
||||
const uint32_t length = 1;
|
||||
const uint32_t length = 4;
|
||||
jerry_value_t arraybuffer = jerry_create_arraybuffer (length);
|
||||
TEST_ASSERT (jerry_arraybuffer_has_buffer (arraybuffer));
|
||||
TEST_ASSERT (!jerry_value_is_error (arraybuffer));
|
||||
TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer));
|
||||
TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length);
|
||||
|
||||
jerry_value_t is_detachable = jerry_is_arraybuffer_detachable (arraybuffer);
|
||||
TEST_ASSERT (!jerry_value_is_error (is_detachable));
|
||||
TEST_ASSERT (jerry_value_is_true (is_detachable));
|
||||
TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length);
|
||||
jerry_release_value (is_detachable);
|
||||
|
||||
jerry_value_t res = jerry_detach_arraybuffer (arraybuffer);
|
||||
TEST_ASSERT (!jerry_arraybuffer_has_buffer (arraybuffer));
|
||||
TEST_ASSERT (!jerry_value_is_error (res));
|
||||
TEST_ASSERT (jerry_get_arraybuffer_pointer (arraybuffer) == NULL);
|
||||
TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == 0);
|
||||
|
||||
is_detachable = jerry_is_arraybuffer_detachable (arraybuffer);
|
||||
TEST_ASSERT (jerry_value_is_false (is_detachable));
|
||||
jerry_release_value (is_detachable);
|
||||
|
||||
jerry_release_value (res);
|
||||
jerry_release_value (arraybuffer);
|
||||
}
|
||||
|
||||
/* Test external ArrayBuffer detach */
|
||||
{
|
||||
uint8_t buf[1];
|
||||
const uint32_t length = 1;
|
||||
jerry_value_t arraybuffer = jerry_create_arraybuffer_external (length, buf, NULL);
|
||||
const uint32_t length = 64;
|
||||
jerry_value_t arraybuffer = jerry_create_arraybuffer_external (length, NULL, NULL);
|
||||
TEST_ASSERT (!jerry_value_is_error (arraybuffer));
|
||||
TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer));
|
||||
TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length);
|
||||
TEST_ASSERT (!jerry_arraybuffer_has_buffer (arraybuffer));
|
||||
|
||||
uint8_t buf[1] = { 1 };
|
||||
TEST_ASSERT (jerry_arraybuffer_write (arraybuffer, 0, buf, 1) == 1);
|
||||
TEST_ASSERT (jerry_arraybuffer_has_buffer (arraybuffer));
|
||||
|
||||
jerry_value_t is_detachable = jerry_is_arraybuffer_detachable (arraybuffer);
|
||||
TEST_ASSERT (!jerry_value_is_error (is_detachable));
|
||||
@ -414,45 +464,32 @@ main (void)
|
||||
is_detachable = jerry_is_arraybuffer_detachable (arraybuffer);
|
||||
TEST_ASSERT (!jerry_value_is_error (is_detachable));
|
||||
TEST_ASSERT (!jerry_value_is_true (is_detachable));
|
||||
TEST_ASSERT (!jerry_arraybuffer_has_buffer (arraybuffer));
|
||||
jerry_release_value (is_detachable);
|
||||
|
||||
jerry_release_value (res);
|
||||
jerry_release_value (arraybuffer);
|
||||
}
|
||||
|
||||
/* Test external ArrayBuffer with callback detach */
|
||||
/* Test ArrayBuffer created in ECMAScript */
|
||||
{
|
||||
const uint32_t length = 8;
|
||||
uint8_t *buf = (uint8_t *) malloc (length);
|
||||
jerry_value_t arraybuffer = jerry_create_arraybuffer_external (length, buf, test_detach_free_cb);
|
||||
const jerry_char_t source[] = TEST_STRING_LITERAL ("new ArrayBuffer(64)");
|
||||
jerry_value_t arraybuffer = jerry_eval (source, sizeof (source) - 1, JERRY_PARSE_NO_OPTS);
|
||||
TEST_ASSERT (!jerry_value_is_error (arraybuffer));
|
||||
TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer));
|
||||
TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length);
|
||||
TEST_ASSERT (!jerry_arraybuffer_has_buffer (arraybuffer));
|
||||
|
||||
jerry_value_t is_detachable = jerry_is_arraybuffer_detachable (arraybuffer);
|
||||
TEST_ASSERT (!jerry_value_is_error (is_detachable));
|
||||
TEST_ASSERT (jerry_value_is_true (is_detachable));
|
||||
TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length);
|
||||
jerry_release_value (is_detachable);
|
||||
uint8_t buf[2] = { 2, 3 };
|
||||
TEST_ASSERT (jerry_arraybuffer_write (arraybuffer, 63, buf, 2) == 1);
|
||||
TEST_ASSERT (jerry_arraybuffer_has_buffer (arraybuffer));
|
||||
|
||||
jerry_value_t res = jerry_detach_arraybuffer (arraybuffer);
|
||||
TEST_ASSERT (!jerry_value_is_error (res));
|
||||
TEST_ASSERT (jerry_get_arraybuffer_pointer (arraybuffer) == NULL);
|
||||
TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == 0);
|
||||
TEST_ASSERT (detach_free_callback_called);
|
||||
|
||||
is_detachable = jerry_is_arraybuffer_detachable (arraybuffer);
|
||||
TEST_ASSERT (!jerry_value_is_error (is_detachable));
|
||||
TEST_ASSERT (!jerry_value_is_true (is_detachable));
|
||||
jerry_release_value (is_detachable);
|
||||
|
||||
jerry_release_value (res);
|
||||
jerry_release_value (arraybuffer);
|
||||
}
|
||||
|
||||
jerry_cleanup ();
|
||||
|
||||
TEST_ASSERT (callback_called == true);
|
||||
TEST_ASSERT (allocate_count == 1);
|
||||
TEST_ASSERT (free_count == 2);
|
||||
|
||||
return 0;
|
||||
} /* main */
|
||||
|
||||
@ -36,7 +36,7 @@ typedef struct
|
||||
*/
|
||||
static void
|
||||
register_js_value (const char *name_p, /**< name of the function */
|
||||
jerry_value_t value) /**< function callback */
|
||||
jerry_value_t value) /**< function callback */
|
||||
{
|
||||
jerry_value_t global_obj_val = jerry_get_global_object ();
|
||||
|
||||
@ -204,14 +204,12 @@ test_typedarray_complex_creation (test_entry_t test_entries[], /**< test cases *
|
||||
{
|
||||
const uint32_t arraybuffer_size = 256;
|
||||
|
||||
JERRY_VLA (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;
|
||||
uint8_t *buffer_p = NULL;
|
||||
|
||||
/* new %TypedArray% (buffer, offset, length); */
|
||||
jerry_value_t typedarray;
|
||||
@ -220,7 +218,8 @@ test_typedarray_complex_creation (test_entry_t test_entries[], /**< test cases *
|
||||
|
||||
if (use_external_buffer)
|
||||
{
|
||||
arraybuffer = jerry_create_arraybuffer_external (arraybuffer_size, buffer_ext, NULL);
|
||||
buffer_p = (uint8_t *) jerry_heap_alloc (arraybuffer_size);
|
||||
arraybuffer = jerry_create_arraybuffer_external (arraybuffer_size, buffer_p, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -290,8 +289,8 @@ test_typedarray_complex_creation (test_entry_t test_entries[], /**< test cases *
|
||||
|
||||
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);
|
||||
test_buffer_value (0x11223344, buffer_p, offset, type, bytes_per_element);
|
||||
TEST_ASSERT (memcmp (buffer_p, test_buffer, offset + byte_length) == 0);
|
||||
}
|
||||
|
||||
jerry_release_value (buffer);
|
||||
@ -504,9 +503,9 @@ test_detached_arraybuffer (void)
|
||||
|
||||
/* Creating an TypedArray for a detached array buffer with a given length/offset is invalid */
|
||||
{
|
||||
uint8_t buf[1];
|
||||
const uint32_t length = 1;
|
||||
jerry_value_t arraybuffer = jerry_create_arraybuffer_external (length, buf, NULL);
|
||||
uint8_t *buffer_p = (uint8_t *) jerry_heap_alloc (length);
|
||||
jerry_value_t arraybuffer = jerry_create_arraybuffer_external (length, buffer_p, NULL);
|
||||
TEST_ASSERT (!jerry_value_is_error (arraybuffer));
|
||||
TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer));
|
||||
TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length);
|
||||
@ -533,9 +532,9 @@ test_detached_arraybuffer (void)
|
||||
|
||||
/* Creating an TypedArray for a detached array buffer without length/offset is valid */
|
||||
{
|
||||
uint8_t buf[1];
|
||||
const uint32_t length = 1;
|
||||
jerry_value_t arraybuffer = jerry_create_arraybuffer_external (length, buf, NULL);
|
||||
uint8_t *buffer_p = (uint8_t *) jerry_heap_alloc (length);
|
||||
jerry_value_t arraybuffer = jerry_create_arraybuffer_external (length, buffer_p, NULL);
|
||||
TEST_ASSERT (!jerry_value_is_error (arraybuffer));
|
||||
TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer));
|
||||
TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user