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:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user