Skip to content

Commit 53d52c6

Browse files
committed
Add ArrayBuffer detach operations
JerryScript-DCO-1.0-Signed-off-by: legendecas legendecas@gmail.com
1 parent 6f515f0 commit 53d52c6

File tree

6 files changed

+226
-0
lines changed

6 files changed

+226
-0
lines changed

docs/02.API-REFERENCE.md

+66
Original file line numberDiff line numberDiff line change
@@ -7398,6 +7398,72 @@ jerry_get_arraybuffer_pointer (const jerry_value_t value);
73987398
- [jerry_create_arraybuffer_external](#jerry_create_arraybuffer_external)
73997399

74007400

7401+
## jerry_is_arraybuffer_detachable
7402+
7403+
**Summary**
7404+
Get if the ArrayBuffer is detachable.
7405+
7406+
**Prototype**
7407+
7408+
```c
7409+
jerry_value_t
7410+
jerry_is_arraybuffer_detachable (const jerry_value_t value);
7411+
```
7412+
7413+
**Example**
7414+
7415+
```c
7416+
{
7417+
// create the ArrayBuffer
7418+
jerry_value_t buffer = jerry_create_arraybuffer (16);
7419+
7420+
jerry_value_t res = jerry_is_arraybuffer_detachable (buffer);
7421+
bool is_detachable = jerry_get_boolean_value (res);
7422+
7423+
// release buffer as it is not needed after this point
7424+
jerry_release_value (buffer);
7425+
}
7426+
```
7427+
7428+
**See also**
7429+
- [jerry_detach_arraybuffer](#jerry_detach_arraybuffer)
7430+
7431+
## jerry_detach_arraybuffer
7432+
7433+
**Summary**
7434+
Detach the underlying data block from ArrayBuffer and set its bytelength to 0.
7435+
7436+
This operation requires the ArrayBuffer to be external that created by
7437+
`jerry_create_arraybuffer_external`.
7438+
7439+
**Prototype**
7440+
7441+
```c
7442+
jerry_value_t
7443+
jerry_detach_arraybuffer (const jerry_value_t value);
7444+
```
7445+
7446+
**Example**
7447+
7448+
```c
7449+
{
7450+
uint8_t buf[1];
7451+
jerry_size_t length = 1;
7452+
// create the ArrayBuffer
7453+
jerry_value_t buffer = jerry_create_arraybuffer (length, buf, NULL);
7454+
7455+
jerry_value_t res = jerry_detach_arraybuffer (buffer);
7456+
7457+
// release buffer as it is not needed after this point
7458+
jerry_release_value(res);
7459+
jerry_release_value (buffer);
7460+
}
7461+
```
7462+
7463+
**See also**
7464+
- [jerry_is_arraybuffer_detachable](#jerry_is_arraybuffer_detachable)
7465+
7466+
74017467
## jerry_get_dataview_buffer
74027468

74037469
**Summary**

jerry-core/api/jerry.c

+53
Original file line numberDiff line numberDiff line change
@@ -3271,6 +3271,59 @@ jerry_get_arraybuffer_pointer (const jerry_value_t array_buffer) /**< Array Buff
32713271
return NULL;
32723272
} /* jerry_get_arraybuffer_pointer */
32733273

3274+
/**
3275+
* Get if the ArrayBuffer is detachable.
3276+
*
3277+
* @return boolean value - if success
3278+
* value marked with error flag - otherwise
3279+
*/
3280+
jerry_value_t
3281+
jerry_is_arraybuffer_detachable (const jerry_value_t value) /**< ArrayBuffer */
3282+
{
3283+
jerry_assert_api_available ();
3284+
3285+
#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
3286+
if (ecma_is_arraybuffer (value))
3287+
{
3288+
ecma_object_t *buffer_p = ecma_get_object_from_value (value);
3289+
return ecma_arraybuffer_is_detachable (buffer_p) ? ECMA_VALUE_TRUE : ECMA_VALUE_FALSE;
3290+
}
3291+
#else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3292+
JERRY_UNUSED (value);
3293+
#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3294+
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Expects an ArrayBuffer")));
3295+
} /* jerry_is_arraybuffer_detachable */
3296+
3297+
/**
3298+
* Detach the underlying data block from ArrayBuffer and set its bytelength to 0.
3299+
* This operation requires the ArrayBuffer to be external that created by
3300+
* `jerry_create_arraybuffer_external`.
3301+
*
3302+
* @return undefined value - if success
3303+
* value marked with error flag - otherwise
3304+
*/
3305+
jerry_value_t
3306+
jerry_detach_arraybuffer (const jerry_value_t value) /**< ArrayBuffer */
3307+
{
3308+
jerry_assert_api_available ();
3309+
3310+
#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
3311+
if (ecma_is_arraybuffer (value))
3312+
{
3313+
ecma_object_t *buffer_p = ecma_get_object_from_value (value);
3314+
bool detached = ecma_arraybuffer_detach (buffer_p);
3315+
if (!detached)
3316+
{
3317+
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Expects a detachable ArrayBuffer.")));
3318+
}
3319+
return ECMA_VALUE_UNDEFINED;
3320+
}
3321+
#else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3322+
JERRY_UNUSED (value);
3323+
#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
3324+
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Expects an ArrayBuffer")));
3325+
} /* jerry_detach_arraybuffer */
3326+
32743327
/**
32753328
* DataView related functions
32763329
*/

jerry-core/ecma/operations/ecma-arraybuffer-object.c

+56
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,62 @@ ecma_arraybuffer_get_buffer (ecma_object_t *object_p) /**< pointer to the ArrayB
203203
}
204204
} /* ecma_arraybuffer_get_buffer */
205205

206+
207+
/**
208+
* Helper function: check if the target ArrayBuffer is detachable
209+
*
210+
*
211+
* @return true - if value is an detachable ArrayBuffer object
212+
* false - otherwise
213+
*/
214+
inline bool JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
215+
ecma_arraybuffer_is_detachable (ecma_object_t *object_p) /**< pointer to the ArrayBuffer object */
216+
{
217+
JERRY_ASSERT (ecma_object_class_is (object_p, LIT_MAGIC_STRING_ARRAY_BUFFER_UL));
218+
219+
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
220+
221+
if (ECMA_ARRAYBUFFER_HAS_EXTERNAL_MEMORY (ext_object_p))
222+
{
223+
ecma_arraybuffer_external_info *array_p = (ecma_arraybuffer_external_info *) ext_object_p;
224+
/* in case the arraybuffer has been detached */
225+
return array_p->buffer_p != NULL;
226+
}
227+
else
228+
{
229+
return false;
230+
}
231+
} /* ecma_arraybuffer_is_detachable */
232+
233+
234+
/**
235+
* ArrayBuffer object detaching operation
236+
*
237+
*
238+
* See also: ES2015 24.1.1.3
239+
*
240+
* @return true - if detach op succeeded
241+
* false - otherwise
242+
*/
243+
inline bool JERRY_ATTR_ALWAYS_INLINE
244+
ecma_arraybuffer_detach (ecma_object_t *object_p) /**< pointer to the ArrayBuffer object */
245+
{
246+
JERRY_ASSERT (ecma_object_class_is (object_p, LIT_MAGIC_STRING_ARRAY_BUFFER_UL));
247+
248+
if (!ecma_arraybuffer_is_detachable (object_p))
249+
{
250+
return false;
251+
}
252+
253+
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
254+
255+
ecma_arraybuffer_external_info *array_object_p = (ecma_arraybuffer_external_info *) ext_object_p;
256+
array_object_p->buffer_p = NULL;
257+
array_object_p->extended_object.u.class_prop.u.length = 0;
258+
259+
return true;
260+
} /* ecma_arraybuffer_detach */
261+
206262
/**
207263
* @}
208264
* @}

jerry-core/ecma/operations/ecma-arraybuffer-object.h

+4
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ lit_utf8_byte_t * JERRY_ATTR_PURE
4343
ecma_arraybuffer_get_buffer (ecma_object_t *obj_p);
4444
ecma_length_t JERRY_ATTR_PURE
4545
ecma_arraybuffer_get_length (ecma_object_t *obj_p);
46+
bool JERRY_ATTR_PURE
47+
ecma_arraybuffer_is_detachable (ecma_object_t *obj_p);
48+
bool
49+
ecma_arraybuffer_detach (ecma_object_t *obj_p);
4650
bool
4751
ecma_is_arraybuffer (ecma_value_t val);
4852

jerry-core/include/jerryscript-core.h

+2
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,8 @@ jerry_length_t jerry_arraybuffer_read (const jerry_value_t value,
595595
jerry_length_t buf_size);
596596
jerry_length_t jerry_get_arraybuffer_byte_length (const jerry_value_t value);
597597
uint8_t *jerry_get_arraybuffer_pointer (const jerry_value_t value);
598+
jerry_value_t jerry_is_arraybuffer_detachable (const jerry_value_t value);
599+
jerry_value_t jerry_detach_arraybuffer (const jerry_value_t value);
598600

599601
/**
600602
* DataView functions.

tests/unit-core/test-arraybuffer.c

+45
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,51 @@ main (void)
354354
jerry_release_value (input_buffer);
355355
}
356356

357+
/* Test ArrayBuffer detach */
358+
{
359+
const uint32_t length = 1;
360+
jerry_value_t arraybuffer = jerry_create_arraybuffer (length);
361+
TEST_ASSERT (!jerry_value_is_error (arraybuffer));
362+
TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer));
363+
TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length);
364+
365+
jerry_value_t is_detachable = jerry_is_arraybuffer_detachable (arraybuffer);
366+
TEST_ASSERT (!jerry_value_is_error (is_detachable));
367+
TEST_ASSERT (!jerry_value_to_boolean (is_detachable));
368+
369+
jerry_value_t res = jerry_detach_arraybuffer (arraybuffer);
370+
TEST_ASSERT (jerry_value_is_error (res));
371+
372+
jerry_release_value (res);
373+
jerry_release_value (arraybuffer);
374+
}
375+
376+
/* Test external ArrayBuffer detach */
377+
{
378+
uint8_t buf[1];
379+
const uint32_t length = 1;
380+
jerry_value_t arraybuffer = jerry_create_arraybuffer_external (length, buf, NULL);
381+
TEST_ASSERT (!jerry_value_is_error (arraybuffer));
382+
TEST_ASSERT (jerry_value_is_arraybuffer (arraybuffer));
383+
TEST_ASSERT (jerry_get_arraybuffer_byte_length (arraybuffer) == length);
384+
385+
jerry_value_t is_detachable = jerry_is_arraybuffer_detachable (arraybuffer);
386+
TEST_ASSERT (!jerry_value_is_error (is_detachable));
387+
TEST_ASSERT (jerry_value_to_boolean (is_detachable));
388+
jerry_release_value (is_detachable);
389+
390+
jerry_value_t res = jerry_detach_arraybuffer (arraybuffer);
391+
TEST_ASSERT (!jerry_value_is_error (res));
392+
393+
is_detachable = jerry_is_arraybuffer_detachable (arraybuffer);
394+
TEST_ASSERT (!jerry_value_is_error (is_detachable));
395+
TEST_ASSERT (!jerry_value_to_boolean (is_detachable));
396+
jerry_release_value (is_detachable);
397+
398+
jerry_release_value (res);
399+
jerry_release_value (arraybuffer);
400+
}
401+
357402
jerry_cleanup ();
358403

359404
TEST_ASSERT (callback_called == true);

0 commit comments

Comments
 (0)