Revise the API ArrayBuffer related operations (#4284)
- External ArrayBuffer construction with 0 length should be equivalent to `new ArrayBuffer(0)` - Internally allocated ArrayBuffers should be detachable - Externally allocated ArrayBuffers free callback should be called when underlying buffer is detached JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
This commit is contained in:
@@ -9011,7 +9011,9 @@ jerry_get_arraybuffer_pointer (const jerry_value_t value);
|
|||||||
- `value` - Array Buffer object.
|
- `value` - Array Buffer object.
|
||||||
- return value
|
- return value
|
||||||
- pointer to the Array Buffer's data area.
|
- pointer to the Array Buffer's data area.
|
||||||
- NULL if the `value` is not an Array Buffer object.
|
- NULL if the `value` is:
|
||||||
|
- not an ArrayBuffer object
|
||||||
|
- an external ArrayBuffer has been detached
|
||||||
|
|
||||||
*New in version 2.0*.
|
*New in version 2.0*.
|
||||||
|
|
||||||
@@ -9096,6 +9098,8 @@ jerry_value_t
|
|||||||
jerry_detach_arraybuffer (const jerry_value_t value);
|
jerry_detach_arraybuffer (const jerry_value_t value);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
*Note*: If the ArrayBuffer has been created with `jerry_create_arraybuffer_external` the optional free callback is called on a successful detach operation
|
||||||
|
|
||||||
- `value` - ArrayBuffer to be detached
|
- `value` - ArrayBuffer to be detached
|
||||||
- return
|
- return
|
||||||
- null value if success
|
- null value if success
|
||||||
|
|||||||
+13
-11
@@ -4204,7 +4204,7 @@ jerry_create_arraybuffer_external (const jerry_length_t size, /**< size of the b
|
|||||||
|
|
||||||
if (JERRY_UNLIKELY (size == 0 || buffer_p == NULL))
|
if (JERRY_UNLIKELY (size == 0 || buffer_p == NULL))
|
||||||
{
|
{
|
||||||
arraybuffer = ecma_arraybuffer_new_object_external (0, NULL, (ecma_object_native_free_callback_t) free_cb);
|
arraybuffer = ecma_arraybuffer_new_object (0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -4353,7 +4353,9 @@ jerry_get_arraybuffer_byte_length (const jerry_value_t value) /**< ArrayBuffer *
|
|||||||
* when accessing the pointer elements.
|
* when accessing the pointer elements.
|
||||||
*
|
*
|
||||||
* @return pointer to the back-buffer of the ArrayBuffer.
|
* @return pointer to the back-buffer of the ArrayBuffer.
|
||||||
* pointer is NULL if the parameter is not an ArrayBuffer
|
* pointer is NULL if:
|
||||||
|
* - the parameter is not an ArrayBuffer
|
||||||
|
* - an external ArrayBuffer has been detached
|
||||||
*/
|
*/
|
||||||
uint8_t *
|
uint8_t *
|
||||||
jerry_get_arraybuffer_pointer (const jerry_value_t array_buffer) /**< Array Buffer to use */
|
jerry_get_arraybuffer_pointer (const jerry_value_t array_buffer) /**< Array Buffer to use */
|
||||||
@@ -4392,18 +4394,19 @@ jerry_is_arraybuffer_detachable (const jerry_value_t value) /**< ArrayBuffer */
|
|||||||
if (ecma_is_arraybuffer (value))
|
if (ecma_is_arraybuffer (value))
|
||||||
{
|
{
|
||||||
ecma_object_t *buffer_p = ecma_get_object_from_value (value);
|
ecma_object_t *buffer_p = ecma_get_object_from_value (value);
|
||||||
return ecma_arraybuffer_is_detachable (buffer_p) ? ECMA_VALUE_TRUE : ECMA_VALUE_FALSE;
|
return ecma_arraybuffer_is_detached (buffer_p) ? ECMA_VALUE_FALSE : ECMA_VALUE_TRUE;
|
||||||
}
|
}
|
||||||
#else /* !ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
|
#else /* !ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
|
||||||
JERRY_UNUSED (value);
|
JERRY_UNUSED (value);
|
||||||
#endif /* ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
|
#endif /* ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
|
||||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Expects an ArrayBuffer")));
|
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Expected an ArrayBuffer")));
|
||||||
} /* jerry_is_arraybuffer_detachable */
|
} /* jerry_is_arraybuffer_detachable */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detach the underlying data block from ArrayBuffer and set its bytelength to 0.
|
* Detach the underlying data block from ArrayBuffer and set its bytelength to 0.
|
||||||
* This operation requires the ArrayBuffer to be external that created by
|
*
|
||||||
* `jerry_create_arraybuffer_external`.
|
* Note: If the ArrayBuffer has been created with `jerry_create_arraybuffer_external`
|
||||||
|
* the optional free callback is called on a successful detach operation
|
||||||
*
|
*
|
||||||
* @return null value - if success
|
* @return null value - if success
|
||||||
* value marked with error flag - otherwise
|
* value marked with error flag - otherwise
|
||||||
@@ -4417,17 +4420,16 @@ jerry_detach_arraybuffer (const jerry_value_t value) /**< ArrayBuffer */
|
|||||||
if (ecma_is_arraybuffer (value))
|
if (ecma_is_arraybuffer (value))
|
||||||
{
|
{
|
||||||
ecma_object_t *buffer_p = ecma_get_object_from_value (value);
|
ecma_object_t *buffer_p = ecma_get_object_from_value (value);
|
||||||
bool detached = ecma_arraybuffer_detach (buffer_p);
|
if (ecma_arraybuffer_detach (buffer_p))
|
||||||
if (!detached)
|
|
||||||
{
|
{
|
||||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Expects a detachable ArrayBuffer.")));
|
return ECMA_VALUE_NULL;
|
||||||
}
|
}
|
||||||
return ECMA_VALUE_NULL;
|
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer has already been detached.")));
|
||||||
}
|
}
|
||||||
#else /* !ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
|
#else /* !ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
|
||||||
JERRY_UNUSED (value);
|
JERRY_UNUSED (value);
|
||||||
#endif /* ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
|
#endif /* ENABLED (JERRY_BUILTIN_TYPEDARRAY) */
|
||||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Expects an ArrayBuffer")));
|
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Expected an ArrayBuffer")));
|
||||||
} /* jerry_detach_arraybuffer */
|
} /* jerry_detach_arraybuffer */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1384,11 +1384,10 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
|
|||||||
|
|
||||||
/* Call external free callback if any. */
|
/* Call external free callback if any. */
|
||||||
ecma_arraybuffer_external_info *array_p = (ecma_arraybuffer_external_info *) ext_object_p;
|
ecma_arraybuffer_external_info *array_p = (ecma_arraybuffer_external_info *) ext_object_p;
|
||||||
JERRY_ASSERT (array_p != NULL);
|
|
||||||
|
|
||||||
if (array_p->free_cb != NULL)
|
if (array_p->free_cb != NULL)
|
||||||
{
|
{
|
||||||
(array_p->free_cb) (array_p->buffer_p);
|
array_p->free_cb (array_p->buffer_p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -1882,8 +1882,12 @@ typedef enum
|
|||||||
{
|
{
|
||||||
ECMA_ARRAYBUFFER_INTERNAL_MEMORY = 0u, /* ArrayBuffer memory is handled internally. */
|
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_EXTERNAL_MEMORY = (1u << 0), /* ArrayBuffer created via jerry_create_arraybuffer_external. */
|
||||||
|
ECMA_ARRAYBUFFER_DETACHED = (1u << 1), /* ArrayBuffer has been detached */
|
||||||
} ecma_arraybuffer_extra_flag_t;
|
} ecma_arraybuffer_extra_flag_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether the ArrayBuffer has external underlying buffer
|
||||||
|
*/
|
||||||
#define ECMA_ARRAYBUFFER_HAS_EXTERNAL_MEMORY(object_p) \
|
#define ECMA_ARRAYBUFFER_HAS_EXTERNAL_MEMORY(object_p) \
|
||||||
((((ecma_extended_object_t *) object_p)->u.class_prop.extra_info & ECMA_ARRAYBUFFER_EXTERNAL_MEMORY) != 0)
|
((((ecma_extended_object_t *) object_p)->u.class_prop.extra_info & ECMA_ARRAYBUFFER_EXTERNAL_MEMORY) != 0)
|
||||||
|
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ ecma_arraybuffer_get_length (ecma_object_t *object_p) /**< pointer to the ArrayB
|
|||||||
JERRY_ASSERT (ecma_object_class_is (object_p, LIT_MAGIC_STRING_ARRAY_BUFFER_UL));
|
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;
|
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||||
return ext_object_p->u.class_prop.u.length;
|
return ecma_arraybuffer_is_detached (object_p) ? 0 : ext_object_p->u.class_prop.u.length;
|
||||||
} /* ecma_arraybuffer_get_length */
|
} /* ecma_arraybuffer_get_length */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -190,12 +190,15 @@ ecma_arraybuffer_get_buffer (ecma_object_t *object_p) /**< pointer to the ArrayB
|
|||||||
if (ECMA_ARRAYBUFFER_HAS_EXTERNAL_MEMORY (ext_object_p))
|
if (ECMA_ARRAYBUFFER_HAS_EXTERNAL_MEMORY (ext_object_p))
|
||||||
{
|
{
|
||||||
ecma_arraybuffer_external_info *array_p = (ecma_arraybuffer_external_info *) ext_object_p;
|
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;
|
return (lit_utf8_byte_t *) array_p->buffer_p;
|
||||||
}
|
}
|
||||||
else
|
else if (ext_object_p->u.class_prop.extra_info & ECMA_ARRAYBUFFER_DETACHED)
|
||||||
{
|
{
|
||||||
return (lit_utf8_byte_t *) (ext_object_p + 1);
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (lit_utf8_byte_t *) (ext_object_p + 1);
|
||||||
} /* ecma_arraybuffer_get_buffer */
|
} /* ecma_arraybuffer_get_buffer */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -209,41 +212,9 @@ ecma_arraybuffer_is_detached (ecma_object_t *object_p) /**< pointer to the Array
|
|||||||
{
|
{
|
||||||
JERRY_ASSERT (ecma_object_class_is (object_p, LIT_MAGIC_STRING_ARRAY_BUFFER_UL));
|
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 (((ecma_extended_object_t *) object_p)->u.class_prop.extra_info & ECMA_ARRAYBUFFER_DETACHED) != 0;
|
||||||
|
|
||||||
if (ECMA_ARRAYBUFFER_HAS_EXTERNAL_MEMORY (ext_object_p))
|
|
||||||
{
|
|
||||||
ecma_arraybuffer_external_info *array_p = (ecma_arraybuffer_external_info *) ext_object_p;
|
|
||||||
/* in case the arraybuffer has been detached */
|
|
||||||
return array_p->buffer_p == NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
} /* ecma_arraybuffer_is_detached */
|
} /* ecma_arraybuffer_is_detached */
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper function: check if the target ArrayBuffer is detachable
|
|
||||||
*
|
|
||||||
* @return true - if value is an detachable ArrayBuffer object
|
|
||||||
* false - otherwise
|
|
||||||
*/
|
|
||||||
inline bool JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
|
|
||||||
ecma_arraybuffer_is_detachable (ecma_object_t *object_p) /**< pointer to the ArrayBuffer object */
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (ECMA_ARRAYBUFFER_HAS_EXTERNAL_MEMORY (ext_object_p))
|
|
||||||
{
|
|
||||||
ecma_arraybuffer_external_info *array_p = (ecma_arraybuffer_external_info *) ext_object_p;
|
|
||||||
/* in case the arraybuffer has been detached */
|
|
||||||
return array_p->buffer_p != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
} /* ecma_arraybuffer_is_detachable */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ArrayBuffer object detaching operation
|
* ArrayBuffer object detaching operation
|
||||||
*
|
*
|
||||||
@@ -257,16 +228,27 @@ ecma_arraybuffer_detach (ecma_object_t *object_p) /**< pointer to the ArrayBuffe
|
|||||||
{
|
{
|
||||||
JERRY_ASSERT (ecma_object_class_is (object_p, LIT_MAGIC_STRING_ARRAY_BUFFER_UL));
|
JERRY_ASSERT (ecma_object_class_is (object_p, LIT_MAGIC_STRING_ARRAY_BUFFER_UL));
|
||||||
|
|
||||||
if (!ecma_arraybuffer_is_detachable (object_p))
|
if (ecma_arraybuffer_is_detached (object_p))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||||
|
ext_object_p->u.class_prop.extra_info |= ECMA_ARRAYBUFFER_DETACHED;
|
||||||
|
|
||||||
ecma_arraybuffer_external_info *array_object_p = (ecma_arraybuffer_external_info *) ext_object_p;
|
if (ECMA_ARRAYBUFFER_HAS_EXTERNAL_MEMORY (ext_object_p))
|
||||||
array_object_p->buffer_p = NULL;
|
{
|
||||||
array_object_p->extended_object.u.class_prop.u.length = 0;
|
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.class_prop.u.length = 0;
|
||||||
|
array_p->buffer_p = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} /* ecma_arraybuffer_detach */
|
} /* ecma_arraybuffer_detach */
|
||||||
|
|||||||
@@ -45,8 +45,6 @@ uint32_t JERRY_ATTR_PURE
|
|||||||
ecma_arraybuffer_get_length (ecma_object_t *obj_p);
|
ecma_arraybuffer_get_length (ecma_object_t *obj_p);
|
||||||
bool JERRY_ATTR_PURE
|
bool JERRY_ATTR_PURE
|
||||||
ecma_arraybuffer_is_detached (ecma_object_t *obj_p);
|
ecma_arraybuffer_is_detached (ecma_object_t *obj_p);
|
||||||
bool JERRY_ATTR_PURE
|
|
||||||
ecma_arraybuffer_is_detachable (ecma_object_t *obj_p);
|
|
||||||
bool
|
bool
|
||||||
ecma_arraybuffer_detach (ecma_object_t *obj_p);
|
ecma_arraybuffer_detach (ecma_object_t *obj_p);
|
||||||
bool
|
bool
|
||||||
|
|||||||
@@ -154,6 +154,7 @@ static void test_write_with_offset (uint8_t offset) /**< offset for buffer write
|
|||||||
} /* test_write_with_offset */
|
} /* test_write_with_offset */
|
||||||
|
|
||||||
static bool callback_called = false;
|
static bool callback_called = false;
|
||||||
|
static bool detach_free_callback_called = false;
|
||||||
|
|
||||||
static void test_free_cb (void *buffer) /**< buffer to free (if needed) */
|
static void test_free_cb (void *buffer) /**< buffer to free (if needed) */
|
||||||
{
|
{
|
||||||
@@ -161,6 +162,12 @@ static void test_free_cb (void *buffer) /**< buffer to free (if needed) */
|
|||||||
callback_called = true;
|
callback_called = true;
|
||||||
} /* test_free_cb */
|
} /* 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
|
int
|
||||||
main (void)
|
main (void)
|
||||||
{
|
{
|
||||||
@@ -256,6 +263,7 @@ main (void)
|
|||||||
jerry_value_t arraybuffer = jerry_create_arraybuffer_external (length, NULL, NULL);
|
jerry_value_t arraybuffer = jerry_create_arraybuffer_external (length, NULL, NULL);
|
||||||
TEST_ASSERT (!jerry_value_is_error (arraybuffer));
|
TEST_ASSERT (!jerry_value_is_error (arraybuffer));
|
||||||
TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer));
|
TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer));
|
||||||
|
TEST_ASSERT (jerry_is_arraybuffer_detachable (arraybuffer));
|
||||||
TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length);
|
TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length);
|
||||||
|
|
||||||
uint8_t data[20];
|
uint8_t data[20];
|
||||||
@@ -364,7 +372,7 @@ main (void)
|
|||||||
jerry_release_value (buffer);
|
jerry_release_value (buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test ArrayBuffer detach */
|
/* Test internal ArrayBuffer detach */
|
||||||
{
|
{
|
||||||
const uint32_t length = 1;
|
const uint32_t length = 1;
|
||||||
jerry_value_t arraybuffer = jerry_create_arraybuffer (length);
|
jerry_value_t arraybuffer = jerry_create_arraybuffer (length);
|
||||||
@@ -374,10 +382,14 @@ main (void)
|
|||||||
|
|
||||||
jerry_value_t is_detachable = jerry_is_arraybuffer_detachable (arraybuffer);
|
jerry_value_t is_detachable = jerry_is_arraybuffer_detachable (arraybuffer);
|
||||||
TEST_ASSERT (!jerry_value_is_error (is_detachable));
|
TEST_ASSERT (!jerry_value_is_error (is_detachable));
|
||||||
TEST_ASSERT (!jerry_get_boolean_value (is_detachable));
|
TEST_ASSERT (jerry_get_boolean_value (is_detachable));
|
||||||
|
TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length);
|
||||||
|
jerry_release_value (is_detachable);
|
||||||
|
|
||||||
jerry_value_t res = jerry_detach_arraybuffer (arraybuffer);
|
jerry_value_t res = jerry_detach_arraybuffer (arraybuffer);
|
||||||
TEST_ASSERT (jerry_value_is_error (res));
|
TEST_ASSERT (!jerry_value_is_error (res));
|
||||||
|
TEST_ASSERT (jerry_get_arraybuffer_pointer (arraybuffer) == NULL);
|
||||||
|
TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == 0);
|
||||||
|
|
||||||
jerry_release_value (res);
|
jerry_release_value (res);
|
||||||
jerry_release_value (arraybuffer);
|
jerry_release_value (arraybuffer);
|
||||||
@@ -395,10 +407,43 @@ main (void)
|
|||||||
jerry_value_t is_detachable = jerry_is_arraybuffer_detachable (arraybuffer);
|
jerry_value_t is_detachable = jerry_is_arraybuffer_detachable (arraybuffer);
|
||||||
TEST_ASSERT (!jerry_value_is_error (is_detachable));
|
TEST_ASSERT (!jerry_value_is_error (is_detachable));
|
||||||
TEST_ASSERT (jerry_get_boolean_value (is_detachable));
|
TEST_ASSERT (jerry_get_boolean_value (is_detachable));
|
||||||
|
TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length);
|
||||||
jerry_release_value (is_detachable);
|
jerry_release_value (is_detachable);
|
||||||
|
|
||||||
jerry_value_t res = jerry_detach_arraybuffer (arraybuffer);
|
jerry_value_t res = jerry_detach_arraybuffer (arraybuffer);
|
||||||
TEST_ASSERT (!jerry_value_is_error (res));
|
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_error (is_detachable));
|
||||||
|
TEST_ASSERT (!jerry_get_boolean_value (is_detachable));
|
||||||
|
jerry_release_value (is_detachable);
|
||||||
|
|
||||||
|
jerry_release_value (res);
|
||||||
|
jerry_release_value (arraybuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test external ArrayBuffer with callback detach */
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
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_get_boolean_value (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_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);
|
is_detachable = jerry_is_arraybuffer_detachable (arraybuffer);
|
||||||
TEST_ASSERT (!jerry_value_is_error (is_detachable));
|
TEST_ASSERT (!jerry_value_is_error (is_detachable));
|
||||||
|
|||||||
Reference in New Issue
Block a user