Skip to content

Commit

Permalink
Add ArrayBuffer detach operations
Browse files Browse the repository at this point in the history
JerryScript-DCO-1.0-Signed-off-by: legendecas [email protected]
  • Loading branch information
legendecas committed Oct 15, 2019
1 parent f0e432c commit 6ed1b35
Show file tree
Hide file tree
Showing 11 changed files with 375 additions and 2 deletions.
79 changes: 79 additions & 0 deletions docs/02.API-REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -7397,6 +7397,85 @@ jerry_get_arraybuffer_pointer (const jerry_value_t value);

- [jerry_create_arraybuffer_external](#jerry_create_arraybuffer_external)

## jerry_is_arraybuffer_detachable

**Summary**

Get if the ArrayBuffer is detachable.

**Prototype**

```c
jerry_value_t
jerry_is_arraybuffer_detachable (const jerry_value_t value);
```

- `value` - ArrayBuffer to be detached
- return
- boolean value if success
- Error otherwise

**Example**

```c
{
// create the ArrayBuffer
jerry_value_t buffer = jerry_create_arraybuffer (16);

jerry_value_t res = jerry_is_arraybuffer_detachable (buffer);
bool is_detachable = jerry_get_boolean_value (res);

// release buffer as it is not needed after this point
jerry_release_value (res);
jerry_release_value (buffer);
}
```

**See also**

- [jerry_detach_arraybuffer](#jerry_detach_arraybuffer)

## jerry_detach_arraybuffer

**Summary**

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`.

**Prototype**

```c
jerry_value_t
jerry_detach_arraybuffer (const jerry_value_t value);
```

- `value` - ArrayBuffer to be detached
- return
- null value if success
- Error otherwise

**Example**

```c
{
uint8_t buf[1];
jerry_size_t length = 1;
// create the ArrayBuffer
jerry_value_t buffer = jerry_create_arraybuffer (length, buf, NULL);

jerry_value_t res = jerry_detach_arraybuffer (buffer);

// release buffer as it is not needed after this point
jerry_release_value (res);
jerry_release_value (buffer);
}
```

**See also**

- [jerry_is_arraybuffer_detachable](#jerry_is_arraybuffer_detachable)

## jerry_get_dataview_buffer

Expand Down
53 changes: 53 additions & 0 deletions jerry-core/api/jerry.c
Original file line number Diff line number Diff line change
Expand Up @@ -3271,6 +3271,59 @@ jerry_get_arraybuffer_pointer (const jerry_value_t array_buffer) /**< Array Buff
return NULL;
} /* jerry_get_arraybuffer_pointer */

/**
* Get if the ArrayBuffer is detachable.
*
* @return boolean value - if success
* value marked with error flag - otherwise
*/
jerry_value_t
jerry_is_arraybuffer_detachable (const jerry_value_t value) /**< ArrayBuffer */
{
jerry_assert_api_available ();

#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
if (ecma_is_arraybuffer (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;
}
#else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
JERRY_UNUSED (value);
#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Expects an ArrayBuffer")));
} /* jerry_is_arraybuffer_detachable */

/**
* 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`.
*
* @return null value - if success
* value marked with error flag - otherwise
*/
jerry_value_t
jerry_detach_arraybuffer (const jerry_value_t value) /**< ArrayBuffer */
{
jerry_assert_api_available ();

#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
if (ecma_is_arraybuffer (value))
{
ecma_object_t *buffer_p = ecma_get_object_from_value (value);
bool detached = 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;
}
#else /* !ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
JERRY_UNUSED (value);
#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Expects an ArrayBuffer")));
} /* jerry_detach_arraybuffer */

/**
* DataView related functions
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ ecma_builtin_arraybuffer_prototype_bytelength_getter (ecma_value_t this_arg) /**

if (ecma_object_class_is (object_p, LIT_MAGIC_STRING_ARRAY_BUFFER_UL))
{
if (ecma_arraybuffer_is_detached (object_p))
{
return ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer has been detached."));
}
ecma_length_t len = ecma_arraybuffer_get_length (object_p);

return ecma_make_uint32_value (len);
Expand Down Expand Up @@ -96,6 +100,11 @@ ecma_builtin_arraybuffer_prototype_object_slice (ecma_value_t this_arg, /**< thi
return ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not an ArrayBuffer object."));
}

if (ecma_arraybuffer_is_detached (object_p))
{
return ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer has been detached."));
}

ecma_length_t len = ecma_arraybuffer_get_length (object_p);

ecma_length_t start = 0, end = len;
Expand Down
11 changes: 11 additions & 0 deletions jerry-core/ecma/builtin-objects/ecma-builtin-dataview-prototype.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
* limitations under the License.
*/

#include "ecma-arraybuffer-object.h"
#include "ecma-exceptions.h"
#include "ecma-dataview-object.h"
#include "ecma-gc.h"

Expand Down Expand Up @@ -110,11 +112,20 @@ ecma_builtin_dataview_prototype_object_getters (ecma_value_t this_arg, /**< this
}
case ECMA_DATAVIEW_PROTOTYPE_BYTE_LENGTH_GETTER:
{
if (ecma_arraybuffer_is_detached (obj_p->buffer_p))
{
return ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer has been detached."));
}
return ecma_make_uint32_value (obj_p->header.u.class_prop.u.length);
}
default:
{
JERRY_ASSERT (builtin_routine_id == ECMA_DATAVIEW_PROTOTYPE_BYTE_OFFSET_GETTER);

if (ecma_arraybuffer_is_detached (obj_p->buffer_p))
{
return ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer has been detached."));
}
return ecma_make_uint32_value (obj_p->byte_offset);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,11 @@ ecma_builtin_typedarray_prototype_exec_routine (ecma_value_t this_arg, /**< this

ecma_object_t *obj_p = ecma_get_object_from_value (this_arg);
ecma_typedarray_info_t info = ecma_typedarray_get_info (obj_p);
ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (obj_p);
if (ecma_arraybuffer_is_detached (arraybuffer_p))
{
return ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer has been detached."));
}

ecma_typedarray_getter_fn_t typedarray_getter_cb = ecma_get_typedarray_getter_fn (info.id);

Expand Down Expand Up @@ -435,6 +440,12 @@ ecma_builtin_typedarray_prototype_map (ecma_value_t this_arg, /**< this argument
}

ecma_object_t *src_obj_p = ecma_get_object_from_value (this_arg);
ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (src_obj_p);
if (ecma_arraybuffer_is_detached (arraybuffer_p))
{
return ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer has been detached."));
}

ecma_typedarray_info_t src_info = ecma_typedarray_get_info (src_obj_p);

ecma_object_t *func_object_p = ecma_get_object_from_value (cb_func_val);
Expand Down Expand Up @@ -517,6 +528,12 @@ ecma_builtin_typedarray_prototype_reduce_with_direction (ecma_value_t this_arg,
}

ecma_object_t *obj_p = ecma_get_object_from_value (this_arg);
ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (obj_p);
if (ecma_arraybuffer_is_detached (arraybuffer_p))
{
return ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer has been detached."));
}

ecma_typedarray_info_t info = ecma_typedarray_get_info (obj_p);

ecma_typedarray_getter_fn_t getter_cb = ecma_get_typedarray_getter_fn (info.id);
Expand Down Expand Up @@ -770,6 +787,12 @@ ecma_builtin_typedarray_prototype_reverse (ecma_value_t this_arg) /**< this argu
}

ecma_object_t *obj_p = ecma_get_object_from_value (this_arg);
ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (obj_p);
if (ecma_arraybuffer_is_detached (arraybuffer_p))
{
return ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer has been detached."));
}

ecma_typedarray_info_t info = ecma_typedarray_get_info (obj_p);

uint32_t middle = (info.length / 2) << info.shift;
Expand Down Expand Up @@ -822,9 +845,21 @@ ecma_op_typedarray_set_with_typedarray (ecma_value_t this_arg, /**< this argumen
}

ecma_object_t *target_typedarray_p = ecma_get_object_from_value (this_arg);
ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (target_typedarray_p);
if (ecma_arraybuffer_is_detached (arraybuffer_p))
{
return ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer has been detached."));
}

ecma_typedarray_info_t target_info = ecma_typedarray_get_info (target_typedarray_p);

ecma_object_t *src_typedarray_p = ecma_get_object_from_value (arr_val);
ecma_object_t *src_arraybuffer_p = ecma_typedarray_get_arraybuffer (src_typedarray_p);
if (ecma_arraybuffer_is_detached (src_arraybuffer_p))
{
return ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer has been detached."));
}

ecma_typedarray_info_t src_info = ecma_typedarray_get_info (src_typedarray_p);

uint32_t target_offset_uint32 = ecma_number_to_uint32 (target_offset_num);
Expand Down Expand Up @@ -911,6 +946,12 @@ ecma_builtin_typedarray_prototype_set (ecma_value_t this_arg, /**< this argument

/* 11. ~ 15. */
ecma_object_t *typedarray_p = ecma_get_object_from_value (this_arg);
ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (typedarray_p);
if (ecma_arraybuffer_is_detached (arraybuffer_p))
{
return ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer has been detached."));
}

ecma_typedarray_info_t target_info = ecma_typedarray_get_info (typedarray_p);

/* 16.~ 17. */
Expand Down Expand Up @@ -1476,6 +1517,11 @@ ecma_builtin_typedarray_prototype_sort (ecma_value_t this_arg, /**< this argumen
}

ecma_object_t *typedarray_p = ecma_get_object_from_value (this_arg);
ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (typedarray_p);
if (ecma_arraybuffer_is_detached (arraybuffer_p))
{
return ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer has been detached."));
}
ecma_typedarray_info_t info = ecma_typedarray_get_info (typedarray_p);

if (!info.length)
Expand Down Expand Up @@ -1577,6 +1623,11 @@ ecma_builtin_typedarray_prototype_find_helper (ecma_value_t this_arg, /**< this

ecma_object_t *typedarray_p = ecma_get_object_from_value (this_arg);
ecma_typedarray_info_t info = ecma_typedarray_get_info (typedarray_p);
ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (typedarray_p);
if (ecma_arraybuffer_is_detached (arraybuffer_p))
{
return ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer has been detached."));
}

uint32_t buffer_index = 0;
uint32_t limit = info.length * info.element_size;
Expand Down Expand Up @@ -1678,6 +1729,11 @@ ecma_builtin_typedarray_prototype_index_helper (ecma_value_t this_arg, /**< this

ecma_object_t *typedarray_p = ecma_get_object_from_value (this_arg);
ecma_typedarray_info_t info = ecma_typedarray_get_info (typedarray_p);
if (ecma_arraybuffer_is_detached (info.array_buffer_p))
{
return ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer has been detached."));
}

uint32_t limit = info.length * info.element_size;
uint32_t from_index;

Expand Down Expand Up @@ -1901,6 +1957,12 @@ ecma_builtin_typedarray_prototype_slice (ecma_value_t this_arg, /**< this argume
}

ecma_object_t *typedarray_p = ecma_get_object_from_value (this_arg);
ecma_object_t *arraybuffer_p = ecma_typedarray_get_arraybuffer (typedarray_p);
if (ecma_arraybuffer_is_detached (arraybuffer_p))
{
return ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer has been detached."));
}

ecma_typedarray_info_t info = ecma_typedarray_get_info (typedarray_p);
uint32_t start = 0;
uint32_t end = info.length;
Expand Down Expand Up @@ -1944,6 +2006,7 @@ ecma_builtin_typedarray_prototype_slice (ecma_value_t this_arg, /**< this argume
if (count > 0)
{
ecma_object_t *new_typedarray_p = ecma_get_object_from_value (new_typedarray);

lit_utf8_byte_t *new_typedarray_buffer_p = ecma_typedarray_get_buffer (new_typedarray_p);
uint32_t src_byte_index = (start * info.element_size);

Expand Down
Loading

0 comments on commit 6ed1b35

Please sign in to comment.