Add ArrayBuffer with user specified buffer
New API functions: - jerry_create_arraybuffer_external - jerry_get_arraybuffer_pointer JerryScript-DCO-1.0-Signed-off-by: Peter Gal pgal.u-szeged@partner.samsung.com
This commit is contained in:
@@ -2670,6 +2670,42 @@ jerry_create_arraybuffer (const jerry_length_t size) /**< size of the ArrayBuffe
|
||||
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
||||
} /* jerry_create_arraybuffer */
|
||||
|
||||
/**
|
||||
* Creates an ArrayBuffer object with user specified buffer.
|
||||
*
|
||||
* Notes:
|
||||
* * the size is specified in bytes.
|
||||
* * the buffer passed should be at least the specified bytes big.
|
||||
* * if the typed arrays are disabled this will return a TypeError.
|
||||
* * if the size is zero or the buffer_p is a null pointer this will return a RangeError.
|
||||
*
|
||||
* @return value of the construced ArrayBuffer 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_object_native_free_callback_t free_cb) /**< buffer free callback */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
#ifndef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN
|
||||
if (size == 0 || buffer_p == NULL)
|
||||
{
|
||||
return jerry_throw (ecma_raise_range_error (ECMA_ERR_MSG ("invalid buffer size or storage reference")));
|
||||
}
|
||||
|
||||
ecma_object_t *arraybuffer = ecma_arraybuffer_new_object_external (size,
|
||||
buffer_p,
|
||||
(ecma_object_native_free_callback_t) free_cb);
|
||||
return jerry_return (ecma_make_object_value (arraybuffer));
|
||||
#else /* CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
||||
JERRY_UNUSED (size);
|
||||
JERRY_UNUSED (buffer_p);
|
||||
JERRY_UNUSED (free_cb);
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer not supported.")));
|
||||
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
||||
} /* jerry_create_arraybuffer_external */
|
||||
|
||||
/**
|
||||
* Copy bytes into the ArrayBuffer from a buffer.
|
||||
*
|
||||
@@ -2798,6 +2834,45 @@ jerry_get_arraybuffer_byte_length (const jerry_value_t value) /**< ArrayBuffer *
|
||||
return 0;
|
||||
} /* jerry_get_arraybuffer_byte_length */
|
||||
|
||||
/**
|
||||
* Get a pointer for the start of the ArrayBuffer.
|
||||
*
|
||||
* Note:
|
||||
* * Only valid for ArrayBuffers created with jerry_create_arraybuffer_external.
|
||||
* * This is a high-risk operation as the bounds are not checked
|
||||
* when accessing the pointer elements.
|
||||
* * jerry_release_value must be called on the ArrayBuffer when the pointer is no longer needed.
|
||||
*
|
||||
* @return pointer to the back-buffer of the ArrayBuffer.
|
||||
* pointer is NULL if the parameter is not an ArrayBuffer with external memory
|
||||
or it is not an ArrayBuffer at all.
|
||||
*/
|
||||
uint8_t *
|
||||
jerry_get_arraybuffer_pointer (const jerry_value_t value) /**< Array Buffer to use */
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
#ifndef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN
|
||||
jerry_value_t buffer = jerry_get_arg_value (value);
|
||||
|
||||
if (!ecma_is_arraybuffer (buffer))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ecma_object_t *buffer_p = ecma_get_object_from_value (buffer);
|
||||
if (ECMA_ARRAYBUFFER_HAS_EXTERNAL_MEMORY (buffer_p))
|
||||
{
|
||||
jerry_acquire_value (value);
|
||||
lit_utf8_byte_t *mem_buffer_p = ecma_arraybuffer_get_buffer (buffer_p);
|
||||
return (uint8_t *const) mem_buffer_p;
|
||||
}
|
||||
#else /* CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
||||
JERRY_UNUSED (value);
|
||||
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
||||
|
||||
return NULL;
|
||||
} /* jerry_get_arraybuffer_pointer */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -570,11 +570,29 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
|
||||
case LIT_MAGIC_STRING_ARRAY_BUFFER_UL:
|
||||
{
|
||||
ecma_length_t arraybuffer_length = ext_object_p->u.class_prop.u.length;
|
||||
size_t size = sizeof (ecma_extended_object_t) + arraybuffer_length;
|
||||
size_t size;
|
||||
|
||||
if (ECMA_ARRAYBUFFER_HAS_EXTERNAL_MEMORY (ext_object_p))
|
||||
{
|
||||
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;
|
||||
JERRY_ASSERT (array_p != NULL);
|
||||
|
||||
if (array_p->free_cb != NULL)
|
||||
{
|
||||
(array_p->free_cb) (array_p->buffer_p);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
size = sizeof (ecma_extended_object_t) + arraybuffer_length;
|
||||
}
|
||||
|
||||
ecma_dealloc_extended_object (object_p, size);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
|
||||
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
|
||||
case LIT_MAGIC_STRING_PROMISE_UL:
|
||||
|
||||
@@ -712,6 +712,8 @@ typedef struct
|
||||
struct
|
||||
{
|
||||
uint16_t class_id; /**< class id of the object */
|
||||
uint16_t extra_info; /**< extra information for the object
|
||||
e.g. array buffer type info (external/internal) */
|
||||
|
||||
/*
|
||||
* Description of extra fields. These extra fields depends on the class_id.
|
||||
@@ -1243,6 +1245,33 @@ typedef struct
|
||||
|
||||
#ifndef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN
|
||||
|
||||
/**
|
||||
* Extra information for ArrayBuffers.
|
||||
*/
|
||||
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_extra_flag_t;
|
||||
|
||||
#define ECMA_ARRAYBUFFER_HAS_EXTERNAL_MEMORY(object_p) \
|
||||
((((ecma_extended_object_t *) object_p)->u.class_prop.extra_info & 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.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
ecma_extended_object_t extended_object; /**< extended object part */
|
||||
void *buffer_p; /**< external buffer pointer */
|
||||
ecma_object_native_free_callback_t free_cb; /**< the free callback for the above buffer pointer */
|
||||
} ecma_arraybuffer_external_info;
|
||||
|
||||
/**
|
||||
* Some internal properties of TypedArray object.
|
||||
* It is only used when the offset is not 0, and
|
||||
|
||||
@@ -51,6 +51,7 @@ ecma_arraybuffer_new_object (ecma_length_t length) /**< length of the arraybuffe
|
||||
ECMA_OBJECT_TYPE_CLASS);
|
||||
ecma_deref_object (prototype_obj_p);
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
ext_object_p->u.class_prop.extra_info = ECMA_ARRAYBUFFER_INTERNAL_MEMORY;
|
||||
ext_object_p->u.class_prop.class_id = LIT_MAGIC_STRING_ARRAY_BUFFER_UL;
|
||||
ext_object_p->u.class_prop.u.length = length;
|
||||
|
||||
@@ -60,6 +61,38 @@ ecma_arraybuffer_new_object (ecma_length_t length) /**< length of the arraybuffe
|
||||
return object_p;
|
||||
} /* ecma_arraybuffer_new_object */
|
||||
|
||||
/**
|
||||
* Helper function: create arraybuffer object with external buffer backing.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
ecma_object_t *
|
||||
ecma_arraybuffer_new_object_external (ecma_length_t length, /**< length of the buffer_p to use */
|
||||
void *buffer_p, /**< pointer for ArrayBuffer's buffer backing */
|
||||
ecma_object_native_free_callback_t free_cb) /**< buffer free callback */
|
||||
{
|
||||
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);
|
||||
ecma_deref_object (prototype_obj_p);
|
||||
ecma_arraybuffer_external_info *array_object_p = (ecma_arraybuffer_external_info *) object_p;
|
||||
array_object_p->extended_object.u.class_prop.extra_info = ECMA_ARRAYBUFFER_EXTERNAL_MEMORY;
|
||||
array_object_p->extended_object.u.class_prop.class_id = LIT_MAGIC_STRING_ARRAY_BUFFER_UL;
|
||||
array_object_p->extended_object.u.class_prop.u.length = length;
|
||||
|
||||
array_object_p->buffer_p = buffer_p;
|
||||
array_object_p->free_cb = free_cb;
|
||||
|
||||
return object_p;
|
||||
} /* ecma_arraybuffer_new_object_external */
|
||||
|
||||
|
||||
/**
|
||||
* ArrayBuffer object creation operation.
|
||||
*
|
||||
@@ -158,7 +191,16 @@ ecma_arraybuffer_get_buffer (ecma_object_t *object_p) /**< pointer to the ArrayB
|
||||
JERRY_ASSERT (ecma_object_class_is (object_p, LIT_MAGIC_STRING_ARRAY_BUFFER_UL));
|
||||
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
return (lit_utf8_byte_t *) (ext_object_p + 1);
|
||||
|
||||
if (ECMA_ARRAYBUFFER_HAS_EXTERNAL_MEMORY (ext_object_p))
|
||||
{
|
||||
ecma_arraybuffer_external_info *array_p = (ecma_arraybuffer_external_info *) ext_object_p;
|
||||
return (lit_utf8_byte_t *) array_p->buffer_p;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (lit_utf8_byte_t *) (ext_object_p + 1);
|
||||
}
|
||||
} /* ecma_arraybuffer_get_buffer */
|
||||
|
||||
/**
|
||||
|
||||
@@ -34,6 +34,10 @@ ecma_op_create_arraybuffer_object (const ecma_value_t *, ecma_length_t);
|
||||
*/
|
||||
ecma_object_t *
|
||||
ecma_arraybuffer_new_object (ecma_length_t lengh);
|
||||
ecma_object_t *
|
||||
ecma_arraybuffer_new_object_external (ecma_length_t length,
|
||||
void *buffer_p,
|
||||
ecma_object_native_free_callback_t free_cb);
|
||||
lit_utf8_byte_t *
|
||||
ecma_arraybuffer_get_buffer (ecma_object_t *obj_p) __attr_pure___;
|
||||
ecma_length_t
|
||||
|
||||
@@ -446,6 +446,9 @@ void jerry_set_vm_exec_stop_callback (jerry_vm_exec_stop_callback_t stop_cb, voi
|
||||
*/
|
||||
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_object_native_free_callback_t free_cb);
|
||||
jerry_length_t jerry_arraybuffer_write (const jerry_value_t value,
|
||||
jerry_length_t offset,
|
||||
const uint8_t *buf_p,
|
||||
@@ -455,6 +458,7 @@ jerry_length_t jerry_arraybuffer_read (const jerry_value_t value,
|
||||
uint8_t *buf_p,
|
||||
jerry_length_t buf_size);
|
||||
jerry_length_t jerry_get_arraybuffer_byte_length (const jerry_value_t value);
|
||||
uint8_t *jerry_get_arraybuffer_pointer (const jerry_value_t value);
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
||||
Reference in New Issue
Block a user