Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ArrayBuffer detach operations #3208

Merged
merged 1 commit into from
Oct 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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