diff --git a/docs/02.API-REFERENCE.md b/docs/02.API-REFERENCE.md index 780e5fd4e6..9070d9adae 100644 --- a/docs/02.API-REFERENCE.md +++ b/docs/02.API-REFERENCE.md @@ -63,6 +63,7 @@ Possible compile time enabled feature types: - JERRY_FEATURE_LINE_INFO - line info available - JERRY_FEATURE_LOGGING - logging - JERRY_FEATURE_SYMBOL - symbol support + - JERRY_FEATURE_DATAVIEW - DataView support ## jerry_regexp_flags_t @@ -1296,6 +1297,56 @@ jerry_value_is_constructor (const jerry_value_t value) - [jerry_release_value](#jerry_release_value) +## jerry_value_is_dataview + +**Summary** + +Returns whether the given `jerry_value_t` is a DataView object value. + +**Prototype** + +```c +bool +jerry_value_is_dataview (const jerry_value_t value) +``` + +- `value` - API value +- return value + - true, if the given `jerry_value_t` is a DataView object + - false, otherwise + +**Example** + +[doctest]: # () + +```c +#include "jerryscript.h" + +int +main (void) +{ + jerry_init (JERRY_INIT_EMPTY); + + jerry_value_t arraybuffer = jerry_create_arraybuffer (16); + jerry_value_t dataview = jerry_create_dataview (arraybuffer, 0, 16); + + if (jerry_value_is_dataview (dataview)) + { + // usage of dataview + } + + jerry_release_value (dataview); + jerry_release_value (arraybuffer); + + jerry_cleanup (); +} +``` + +**See also** + +- [jerry_release_value](#jerry_release_value) + + ## jerry_value_is_error **Summary** @@ -3246,6 +3297,62 @@ jerry_create_error_sz (jerry_error_t error_type, - [jerry_create_error](#jerry_create_error) +## jerry_create_dataview + +**Summary** + +Create new JavaScript DataView object. + +*Note*: This API depends on the ES2015-subset profile. +*Note*: Returned value must be freed with [jerry_release_value](#jerry_release_value) when it +is no longer needed. + +**Prototype** + +```c +jerry_value_t +jerry_create_dataview (const jerry_value_t array_buffer, + const jerry_length_t byte_offset, + const jerry_length_t byte_length) +``` + +- `array_buffer` - arrayBuffer to create DataView from +- `byte_offset` - offset in bytes, to the first byte in the buffer +- `byte_length` - number of elements in the byte array +- return value + - value of the constructed DataView object - if success + - created error - otherwise + +**Example** + +[doctest]: # () + +```c +#include "jerryscript.h" + +int +main (void) +{ + jerry_init (JERRY_INIT_EMPTY); + + jerry_value_t arraybuffer = jerry_create_arraybuffer (16); + jerry_value_t dataview = jerry_create_dataview (arraybuffer, 0, 16); + + // usage of dataview + + jerry_release_value (dataview); + jerry_release_value (arraybuffer); + + jerry_cleanup (); +} +``` + +**See also** + +- [jerry_value_is_dataview](#jerry_value_is_dataview) +- [jerry_create_arraybuffer](#jerry_create_arraybuffer) + + ## jerry_create_external_function **Summary** @@ -6120,6 +6227,70 @@ jerry_get_arraybuffer_pointer (const jerry_value_t value); - [jerry_create_arraybuffer_external](#jerry_create_arraybuffer_external) +## jerry_get_dataview_buffer + +**Summary** + +Get the ArrayBuffer object used by a DataView object. +Additionally returns the byteLength and byteOffset properties +of the DataView object. + +For the returned ArrayBuffer the [jerry_release_value](#jerry_release_value) +must be called when it is no longer needed. + +**Prototype** + +```c +jerry_value_t +jerry_get_dataview_buffer (const jerry_value_t value, + jerry_length_t *byteOffset, + jerry_length_t *byteLength); +``` + +- `value` - DataView to get the ArrayBuffer from +- `byteOffset` - (Optional) returns the start offset of the ArrayBuffer for the DataView +- `byteLength` - (Optional) returns the number of bytes used from the ArrayBuffer for the DataView +- return + - DataView object's underlying ArrayBuffer object + - TypeError if the `value` is not a DataView object + +**Example** + +[doctest]: # () + +```c +#include "jerryscript.h" + +int +main (void) +{ + jerry_init (JERRY_INIT_EMPTY); + + jerry_value_t arraybuffer = jerry_create_arraybuffer (16); + jerry_value_t dataview = jerry_create_dataview (arraybuffer, 0, 16); + jerry_length_t byteOffset = 0; + jerry_length_t byteLength = 0; + jerry_value_t buffer = jerry_get_dataview_buffer (dataview, &byteOffset, &byteLength); + + // buffer is an ArrayBuffer object and ArrayBuffer operations can be performed on it + // byteOffset is 0 + // byteLength is 16 + + // usage of buffer + + jerry_release_value (buffer); + jerry_release_value (dataview); + jerry_release_value (arraybuffer); + + jerry_cleanup (); +} +``` + +**See also** + +- [jerry_create_dataview](#jerry_create_dataview) + + ## jerry_get_typedarray_type **Summary** diff --git a/jerry-core/api/jerry.c b/jerry-core/api/jerry.c index 5cc072115e..06ce7e32bf 100644 --- a/jerry-core/api/jerry.c +++ b/jerry-core/api/jerry.c @@ -22,6 +22,7 @@ #include "ecma-builtin-helpers.h" #include "ecma-builtins.h" #include "ecma-comparison.h" +#include "ecma-dataview-object.h" #include "ecma-exceptions.h" #include "ecma-eval.h" #include "ecma-function-object.h" @@ -919,6 +920,9 @@ jerry_is_feature_enabled (const jerry_feature_t feature) /**< feature to check * #if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) || feature == JERRY_FEATURE_TYPEDARRAY #endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */ +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) + || feature == JERRY_FEATURE_DATAVIEW +#endif /* ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) */ #if ENABLED (JERRY_BUILTIN_DATE) || feature == JERRY_FEATURE_DATE #endif /* ENABLED (JERRY_BUILTIN_DATE) */ @@ -3205,6 +3209,129 @@ jerry_get_arraybuffer_pointer (const jerry_value_t value) /**< Array Buffer to u return NULL; } /* jerry_get_arraybuffer_pointer */ +/** + * DataView related functions + */ + +/** + * Creates a DataView object with the given ArrayBuffer, ByteOffset and ByteLength arguments. + * + * Notes: + * * returned value must be freed with jerry_release_value, when it is no longer needed. + * * if the DataView bulitin is disabled this will return a TypeError. + * + * @return value of the constructed DataView object - if success + * created error - otherwise + */ +jerry_value_t +jerry_create_dataview (const jerry_value_t array_buffer, /**< arraybuffer to create DataView from */ + const jerry_length_t byte_offset, /**< offset in bytes, to the first byte in the buffer */ + const jerry_length_t byte_length) /**< number of elements in the byte array */ +{ + jerry_assert_api_available (); + +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) + if (ecma_is_value_error_reference (array_buffer)) + { + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p))); + } + + ecma_value_t arguments_p[3] = + { + array_buffer, + ecma_make_uint32_value (byte_offset), + ecma_make_uint32_value (byte_length) + }; + + return jerry_return (ecma_op_dataview_create (arguments_p, 3)); +#else /* !ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) */ + JERRY_UNUSED (array_buffer); + JERRY_UNUSED (byte_offset); + JERRY_UNUSED (byte_length); + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("DataView is not supported."))); +#endif /* ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW */ +} /* jerry_create_dataview */ + +/** + * Check if the given value is a DataView object. + * + * @return true - if it is a DataView object + * false - otherwise + */ +bool +jerry_value_is_dataview (const jerry_value_t value) /**< value to check if it is a DataView object */ +{ + jerry_assert_api_available (); + +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) + if (!ecma_is_value_object (value)) + { + return false; + } + + ecma_dataview_object_t *dataview_object_p = (ecma_dataview_object_t *) ecma_get_object_from_value (value); + + return (ecma_get_object_type (&dataview_object_p->header.object) == ECMA_OBJECT_TYPE_CLASS + && dataview_object_p->header.u.class_prop.class_id == LIT_MAGIC_STRING_DATAVIEW_UL); +#else /* !ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) */ + JERRY_UNUSED (value); + return false; +#endif /* ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW */ +} /* jerry_value_is_dataview */ + +/** + * Get the underlying ArrayBuffer from a DataView. + * + * Additionally the byteLength and byteOffset properties are also returned + * which were specified when the DataView was created. + * + * Note: + * the returned value must be freed with a jerry_release_value call + * + * @return ArrayBuffer of a DataView + * TypeError if the object is not a DataView. + */ +jerry_value_t +jerry_get_dataview_buffer (jerry_value_t value, /**< DataView to get the arraybuffer from */ + jerry_length_t *byte_offset, /**< [out] byteOffset property */ + jerry_length_t *byte_length) /**< [out] byteLength property */ +{ + jerry_assert_api_available (); + +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) + if (ecma_is_value_error_reference (value)) + { + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p))); + } + + ecma_dataview_object_t *dataview_p = ecma_op_dataview_get_object (value); + + if (JERRY_UNLIKELY (dataview_p == NULL)) + { + return ecma_create_error_reference_from_context (); + } + + if (byte_offset != NULL) + { + *byte_offset = dataview_p->byte_offset; + } + + if (byte_length != NULL) + { + *byte_length = dataview_p->header.u.class_prop.u.length; + } + + ecma_object_t *arraybuffer_p = dataview_p->buffer_p; + ecma_ref_object (arraybuffer_p); + + return ecma_make_object_value (arraybuffer_p); +#else /* !ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) */ + JERRY_UNUSED (value); + JERRY_UNUSED (byte_offset); + JERRY_UNUSED (byte_length); + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("DataView is not supported."))); +#endif /* ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW */ +} /* jerry_get_dataview_buffer */ /** * TypedArray related functions diff --git a/jerry-core/config.h b/jerry-core/config.h index be01859c08..8f87e5e729 100644 --- a/jerry-core/config.h +++ b/jerry-core/config.h @@ -74,6 +74,10 @@ # define JERRY_ES2015_BUILTIN JERRY_ES2015 #endif /* !defined (JERRY_ES2015_BUILTIN) */ +#ifndef JERRY_ES2015_BUILTIN_DATAVIEW +# define JERRY_ES2015_BUILTIN_DATAVIEW JERRY_ES2015 +#endif /* !defined (JERRY_ES2015_BUILTIN_DATAVIEW) */ + #ifndef JERRY_ES2015_BUILTIN_ITERATOR # define JERRY_ES2015_BUILTIN_ITERATOR JERRY_ES2015 #endif /* !defined (JERRY_ES2015_BUILTIN_ITERATOR) */ @@ -262,6 +266,10 @@ || ((JERRY_ES2015_BUILTIN_ITERATOR != 0) && (JERRY_ES2015_BUILTIN_ITERATOR != 1)) # error "Invalid value for JERRY_ES2015_BUILTIN_ITERATOR macro." #endif +#if !defined (JERRY_ES2015_BUILTIN_DATAVIEW) \ +|| ((JERRY_ES2015_BUILTIN_DATAVIEW != 0) && (JERRY_ES2015_BUILTIN_DATAVIEW != 1)) +# error "Invalid value for JERRY_ES2015_BUILTIN_DATAVIEW macro." +#endif #if !defined (JERRY_ES2015_BUILTIN_MAP) \ || ((JERRY_ES2015_BUILTIN_MAP != 0) && (JERRY_ES2015_BUILTIN_MAP != 1)) # error "Invalid value for JERRY_ES2015_BUILTIN_MAP macro." diff --git a/jerry-core/ecma/base/ecma-gc.c b/jerry-core/ecma/base/ecma-gc.c index 60dc357c57..ce5229f483 100644 --- a/jerry-core/ecma/base/ecma-gc.c +++ b/jerry-core/ecma/base/ecma-gc.c @@ -683,6 +683,13 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */ return; } #endif /* ENABLED (JERRY_ES2015_BUILTIN_MAP) */ +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) + case LIT_MAGIC_STRING_DATAVIEW_UL: + { + ecma_dealloc_extended_object (object_p, sizeof (ecma_dataview_object_t)); + return; + } +#endif /* ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) */ default: { /* The undefined id represents an uninitialized class. */ diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index a115b08d44..762c304bae 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -1564,6 +1564,18 @@ typedef struct #endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */ +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) +/** + * Description of DataView objects. + */ +typedef struct +{ + ecma_extended_object_t header; /**< header part */ + ecma_object_t *buffer_p; /**< [[ViewedArrayBuffer]] internal slot */ + uint32_t byte_offset; /**< [[ByteOffset]] internal slot */ +} ecma_dataview_object_t; +#endif /* ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW */ + /** * Flag for indicating whether the symbol is a well known symbol * diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-dataview-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-dataview-prototype.c new file mode 100644 index 0000000000..b89114a88e --- /dev/null +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-dataview-prototype.c @@ -0,0 +1,215 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-dataview-object.h" +#include "ecma-gc.h" + +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) + +#ifdef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN +#error "DataView builtin requires ES2015 TypedArray builtin" +#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */ + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_DATAVIEW_PROTOTYPE_ROUTINE_START = ECMA_BUILTIN_ID__COUNT - 1, + ECMA_DATAVIEW_PROTOTYPE_BUFFER_GETTER, + ECMA_DATAVIEW_PROTOTYPE_BYTE_LENGTH_GETTER, + ECMA_DATAVIEW_PROTOTYPE_BYTE_OFFSET_GETTER, + ECMA_DATAVIEW_PROTOTYPE_GET_INT8, + ECMA_DATAVIEW_PROTOTYPE_GET_UINT8, + ECMA_DATAVIEW_PROTOTYPE_GET_INT16, + ECMA_DATAVIEW_PROTOTYPE_GET_UINT16, + ECMA_DATAVIEW_PROTOTYPE_GET_INT32, + ECMA_DATAVIEW_PROTOTYPE_GET_UINT32, + ECMA_DATAVIEW_PROTOTYPE_GET_FLOAT32, +#if ENABLED (JERRY_NUMBER_TYPE_FLOAT64) + ECMA_DATAVIEW_PROTOTYPE_GET_FLOAT64, +#endif /* ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */ + ECMA_DATAVIEW_PROTOTYPE_SET_INT8, + ECMA_DATAVIEW_PROTOTYPE_SET_UINT8, + ECMA_DATAVIEW_PROTOTYPE_SET_INT16, + ECMA_DATAVIEW_PROTOTYPE_SET_UINT16, + ECMA_DATAVIEW_PROTOTYPE_SET_INT32, + ECMA_DATAVIEW_PROTOTYPE_SET_UINT32, + ECMA_DATAVIEW_PROTOTYPE_SET_FLOAT32, +#if ENABLED (JERRY_NUMBER_TYPE_FLOAT64) + ECMA_DATAVIEW_PROTOTYPE_SET_FLOAT64, +#endif /* ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */ +}; + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-dataview-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID dataview_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup dataviewprototype ECMA DataView.prototype object built-in + * @{ + */ + +/** + * Corresponding typedarray mappings for the {get,set}{[U]int, Float}{8, 16, 32, 64} routines + */ +static const uint8_t ecma_dataview_type_mapping[] = +{ + ECMA_BUILTIN_ID_INT8ARRAY, + ECMA_BUILTIN_ID_UINT8ARRAY, + ECMA_BUILTIN_ID_INT16ARRAY, + ECMA_BUILTIN_ID_UINT16ARRAY, + ECMA_BUILTIN_ID_INT32ARRAY, + ECMA_BUILTIN_ID_UINT32ARRAY, + ECMA_BUILTIN_ID_FLOAT32ARRAY, +#if ENABLED (JERRY_NUMBER_TYPE_FLOAT64) + ECMA_BUILTIN_ID_FLOAT64ARRAY, +#endif /* ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */ +}; + +/** + * The DataView.prototype object's {buffer, byteOffset, byteLength} getters + * + * See also: + * ECMA-262 v6, 24.2.4.1 + * ECMA-262 v6, 24.2.4.2 + * ECMA-262 v6, 24.2.4.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_dataview_prototype_object_getters (ecma_value_t this_arg, /**< this argument */ + uint16_t builtin_routine_id) /**< built-in wide routine identifier */ +{ + ecma_dataview_object_t *obj_p = ecma_op_dataview_get_object (this_arg); + + if (JERRY_UNLIKELY (obj_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + switch (builtin_routine_id) + { + case ECMA_DATAVIEW_PROTOTYPE_BUFFER_GETTER: + { + ecma_object_t *buffer_p = obj_p->buffer_p; + ecma_ref_object (buffer_p); + + return ecma_make_object_value (buffer_p); + } + case ECMA_DATAVIEW_PROTOTYPE_BYTE_LENGTH_GETTER: + { + 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); + return ecma_make_uint32_value (obj_p->byte_offset); + } + } +} /* ecma_builtin_dataview_prototype_object_getters */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_dataview_prototype_dispatch_routine (uint16_t builtin_routine_id, /**< built-in wide routine identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + ecma_length_t arguments_number) /**< length of arguments' list */ +{ + ecma_value_t byte_offset = arguments_number > 0 ? arguments_list_p[0] : ECMA_VALUE_UNDEFINED; + + switch (builtin_routine_id) + { + case ECMA_DATAVIEW_PROTOTYPE_BUFFER_GETTER: + case ECMA_DATAVIEW_PROTOTYPE_BYTE_LENGTH_GETTER: + case ECMA_DATAVIEW_PROTOTYPE_BYTE_OFFSET_GETTER: + { + return ecma_builtin_dataview_prototype_object_getters (this_arg, builtin_routine_id); + } + case ECMA_DATAVIEW_PROTOTYPE_GET_FLOAT32: +#if ENABLED (JERRY_NUMBER_TYPE_FLOAT64) + case ECMA_DATAVIEW_PROTOTYPE_GET_FLOAT64: +#endif /* ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */ + case ECMA_DATAVIEW_PROTOTYPE_GET_INT16: + case ECMA_DATAVIEW_PROTOTYPE_GET_INT32: + case ECMA_DATAVIEW_PROTOTYPE_GET_UINT16: + case ECMA_DATAVIEW_PROTOTYPE_GET_UINT32: + { + ecma_value_t little_endian = arguments_number > 1 ? arguments_list_p[1] : ECMA_VALUE_FALSE; + uint8_t type = ecma_dataview_type_mapping[builtin_routine_id - ECMA_DATAVIEW_PROTOTYPE_GET_INT8]; + + return ecma_op_dataview_get_set_view_value (this_arg, byte_offset, little_endian, ECMA_VALUE_EMPTY, type); + } + case ECMA_DATAVIEW_PROTOTYPE_SET_FLOAT32: +#if ENABLED (JERRY_NUMBER_TYPE_FLOAT64) + case ECMA_DATAVIEW_PROTOTYPE_SET_FLOAT64: +#endif /* ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */ + case ECMA_DATAVIEW_PROTOTYPE_SET_INT16: + case ECMA_DATAVIEW_PROTOTYPE_SET_INT32: + case ECMA_DATAVIEW_PROTOTYPE_SET_UINT16: + case ECMA_DATAVIEW_PROTOTYPE_SET_UINT32: + { + ecma_value_t value_to_set = arguments_number > 1 ? arguments_list_p[1] : ECMA_VALUE_UNDEFINED; + ecma_value_t little_endian = arguments_number > 2 ? arguments_list_p[2] : ECMA_VALUE_FALSE; + uint8_t type = ecma_dataview_type_mapping[builtin_routine_id - ECMA_DATAVIEW_PROTOTYPE_SET_INT8]; + + return ecma_op_dataview_get_set_view_value (this_arg, byte_offset, little_endian, value_to_set, type); + } + case ECMA_DATAVIEW_PROTOTYPE_GET_INT8: + case ECMA_DATAVIEW_PROTOTYPE_GET_UINT8: + { + uint8_t type = ecma_dataview_type_mapping[builtin_routine_id - ECMA_DATAVIEW_PROTOTYPE_GET_INT8]; + + return ecma_op_dataview_get_set_view_value (this_arg, byte_offset, ECMA_VALUE_FALSE, ECMA_VALUE_EMPTY, type); + } + default: + { + JERRY_ASSERT (builtin_routine_id == ECMA_DATAVIEW_PROTOTYPE_SET_INT8 + || builtin_routine_id == ECMA_DATAVIEW_PROTOTYPE_SET_UINT8); + ecma_value_t value_to_set = arguments_number > 1 ? arguments_list_p[1] : ECMA_VALUE_UNDEFINED; + uint8_t type = ecma_dataview_type_mapping[builtin_routine_id - ECMA_DATAVIEW_PROTOTYPE_SET_INT8]; + + return ecma_op_dataview_get_set_view_value (this_arg, byte_offset, ECMA_VALUE_FALSE, value_to_set, type); + } + } +} /* ecma_builtin_dataview_prototype_dispatch_routine */ + +/** + * @} + * @} + * @} + */ + +#endif /* ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW */ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-dataview-prototype.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-dataview-prototype.inc.h new file mode 100644 index 0000000000..3dd9efde17 --- /dev/null +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-dataview-prototype.inc.h @@ -0,0 +1,79 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * DataView.prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v6, 24.2.3 */ +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, + ECMA_BUILTIN_ID_DATAVIEW, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +#if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) +/* ECMA-262 v6, 23.2.4.21 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, + LIT_MAGIC_STRING_DATAVIEW_UL, + ECMA_PROPERTY_FLAG_CONFIGURABLE) +#endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */ + +/* Routine properties: + * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ +ROUTINE (LIT_MAGIC_STRING_GET_FLOAT_32_UL, ECMA_DATAVIEW_PROTOTYPE_GET_FLOAT32, 2, 1) +#if ENABLED (JERRY_NUMBER_TYPE_FLOAT64) +ROUTINE (LIT_MAGIC_STRING_GET_FLOAT_64_UL, ECMA_DATAVIEW_PROTOTYPE_GET_FLOAT64, 2, 1) +#endif /* ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */ +ROUTINE (LIT_MAGIC_STRING_GET_INT8_UL, ECMA_DATAVIEW_PROTOTYPE_GET_INT8, 1, 1) +ROUTINE (LIT_MAGIC_STRING_GET_INT16_UL, ECMA_DATAVIEW_PROTOTYPE_GET_INT16, 2, 1) +ROUTINE (LIT_MAGIC_STRING_GET_INT32_UL, ECMA_DATAVIEW_PROTOTYPE_GET_INT32, 2, 1) +ROUTINE (LIT_MAGIC_STRING_GET_UINT8_UL, ECMA_DATAVIEW_PROTOTYPE_GET_UINT8, 2, 1) +ROUTINE (LIT_MAGIC_STRING_GET_UINT16_UL, ECMA_DATAVIEW_PROTOTYPE_GET_UINT16, 2, 1) +ROUTINE (LIT_MAGIC_STRING_GET_UINT32_UL, ECMA_DATAVIEW_PROTOTYPE_GET_UINT32, 2, 1) +ROUTINE (LIT_MAGIC_STRING_SET_FLOAT_32_UL, ECMA_DATAVIEW_PROTOTYPE_SET_FLOAT32, 2, 1) +#if ENABLED (JERRY_NUMBER_TYPE_FLOAT64) +ROUTINE (LIT_MAGIC_STRING_SET_FLOAT_64_UL, ECMA_DATAVIEW_PROTOTYPE_SET_FLOAT64, 2, 1) +#endif /* ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */ +ROUTINE (LIT_MAGIC_STRING_SET_INT8_UL, ECMA_DATAVIEW_PROTOTYPE_SET_INT8, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SET_INT16_UL, ECMA_DATAVIEW_PROTOTYPE_SET_INT16, 2, 1) +ROUTINE (LIT_MAGIC_STRING_SET_INT32_UL, ECMA_DATAVIEW_PROTOTYPE_SET_INT32, 2, 1) +ROUTINE (LIT_MAGIC_STRING_SET_UINT8_UL, ECMA_DATAVIEW_PROTOTYPE_SET_UINT8, 2, 1) +ROUTINE (LIT_MAGIC_STRING_SET_UINT16_UL, ECMA_DATAVIEW_PROTOTYPE_SET_UINT16, 2, 1) +ROUTINE (LIT_MAGIC_STRING_SET_UINT32_UL, ECMA_DATAVIEW_PROTOTYPE_SET_UINT32, 2, 1) + +/* ECMA-262 v6, 24.2.4.1 */ +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_BUFFER, + ECMA_DATAVIEW_PROTOTYPE_BUFFER_GETTER, + ECMA_PROPERTY_FIXED) + +/* ECMA-262 v6, 24.2.4.2 */ +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_BYTE_LENGTH_UL, + ECMA_DATAVIEW_PROTOTYPE_BYTE_LENGTH_GETTER, + ECMA_PROPERTY_FIXED) + +/* ECMA-262 v6, 24.2.4.3 */ +ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_BYTE_OFFSET_UL, + ECMA_DATAVIEW_PROTOTYPE_BYTE_OFFSET_GETTER, + ECMA_PROPERTY_FIXED) + +#endif /* ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-dataview.c b/jerry-core/ecma/builtin-objects/ecma-builtin-dataview.c new file mode 100644 index 0000000000..f77787ab04 --- /dev/null +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-dataview.c @@ -0,0 +1,71 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-dataview-object.h" + +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-dataview.inc.h" +#define BUILTIN_UNDERSCORED_ID dataview +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup dataview ECMA DataView object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in DataView object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_dataview_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + ecma_length_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_MSG ("Constructor DataView requires 'new'.")); +} /* ecma_builtin_dataview_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in DataView object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_dataview_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + ecma_length_t arguments_list_len) /**< number of arguments */ +{ + return ecma_op_dataview_create (arguments_list_p, arguments_list_len); +} /* ecma_builtin_dataview_dispatch_construct */ + +/** + * @} + * @} + * @} + */ + +#endif /* ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW */ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-dataview.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-dataview.inc.h new file mode 100644 index 0000000000..75fbc688fe --- /dev/null +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-dataview.inc.h @@ -0,0 +1,47 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * DataView built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +/* ECMA-262 v6, 23.1.2 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, + 3, + ECMA_PROPERTY_FIXED) + +/* ECMA-262 v6, 23.1 */ +STRING_VALUE (LIT_MAGIC_STRING_NAME, + LIT_MAGIC_STRING_DATAVIEW_UL, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v6, 23.1.2.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, + ECMA_BUILTIN_ID_DATAVIEW_PROTOTYPE, + ECMA_PROPERTY_FIXED) + +#endif /* ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-global.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-global.inc.h index 5d70633ef1..ea03ab2852 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-global.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-global.inc.h @@ -212,6 +212,13 @@ OBJECT_VALUE (LIT_MAGIC_STRING_SYMBOL_UL, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) #endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */ +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) +/* ECMA-262 v6, 23.1.1.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_DATAVIEW_UL, + ECMA_BUILTIN_ID_DATAVIEW, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW */ + /* Routine properties: * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-internal-routines-template.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-internal-routines-template.inc.h index fc28a3fdad..06a10fb67c 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-internal-routines-template.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-internal-routines-template.inc.h @@ -98,6 +98,13 @@ const ecma_builtin_property_descriptor_t PROPERTY_DESCRIPTOR_LIST_NAME[] = ECMA_PROPERTY_FLAG_CONFIGURABLE, \ ECMA_ROUTINE_VALUE (ECMA_ROUTINE_ ## name ## c_function_name, length_prop_value) \ }, +#define ACCESSOR_READ_ONLY(name, c_getter_func_name, prop_attributes) \ + { \ + name, \ + ECMA_BUILTIN_PROPERTY_ACCESSOR_READ_ONLY, \ + prop_attributes, \ + ECMA_ACCESSOR_ ## name ## c_getter_func_name \ + }, #else /* BUILTIN_CUSTOM_DISPATCH */ #define ROUTINE(name, c_function_name, args_number, length_prop_value) \ { \ @@ -113,6 +120,13 @@ const ecma_builtin_property_descriptor_t PROPERTY_DESCRIPTOR_LIST_NAME[] = ECMA_PROPERTY_FLAG_CONFIGURABLE, \ ECMA_ROUTINE_VALUE (c_function_name, length_prop_value) \ }, +#define ACCESSOR_READ_ONLY(name, c_getter_func_name, prop_attributes) \ + { \ + name, \ + ECMA_BUILTIN_PROPERTY_ACCESSOR_READ_ONLY, \ + prop_attributes, \ + c_getter_func_name \ + }, #endif /* !BUILTIN_CUSTOM_DISPATCH */ #define OBJECT_VALUE(name, obj_builtin_id, prop_attributes) \ { \ @@ -158,13 +172,6 @@ const ecma_builtin_property_descriptor_t PROPERTY_DESCRIPTOR_LIST_NAME[] = prop_attributes, \ ECMA_ACCESSOR_READ_WRITE (ECMA_ACCESSOR_ ## name ## c_getter_name, ECMA_ACCESSOR_ ## name ## c_setter_name) \ }, -#define ACCESSOR_READ_ONLY(name, c_getter_func_name, prop_attributes) \ - { \ - name, \ - ECMA_BUILTIN_PROPERTY_ACCESSOR_READ_ONLY, \ - prop_attributes, \ - ECMA_ACCESSOR_ ## name ## c_getter_func_name \ - }, #include BUILTIN_INC_HEADER_NAME { LIT_MAGIC_STRING__COUNT, diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtins.inc.h index 8343c080e5..0254aa98d3 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtins.inc.h @@ -474,6 +474,22 @@ BUILTIN (ECMA_BUILTIN_ID_ARRAY_ITERATOR_PROTOTYPE, array_iterator_prototype) #endif /* ENABLED (JERRY_ES2015_BUILTIN_ITERATOR) */ +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) +/* The DataView prototype object (ECMA-262 v6, 24.2.3.1) */ +BUILTIN (ECMA_BUILTIN_ID_DATAVIEW_PROTOTYPE, + ECMA_OBJECT_TYPE_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + dataview_prototype) + +/* The DataView routine (ECMA-262 v6, 24.2.2.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_DATAVIEW, + ECMA_OBJECT_TYPE_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + dataview) +#endif /* ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW */ + /* The Global object (15.1) */ BUILTIN (ECMA_BUILTIN_ID_GLOBAL, ECMA_OBJECT_TYPE_GENERAL, diff --git a/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-helpers.c b/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-helpers.c index 04472a698d..17b52b45c7 100644 --- a/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-helpers.c +++ b/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-helpers.c @@ -134,15 +134,15 @@ ecma_typedarray_helper_get_builtin_id (ecma_object_t *obj_p) /**< typedarray obj /** * Get the magic string of a TypedArray type. * - * @return uint8_t + * @return lit_magic_string_id_t */ -uint8_t +lit_magic_string_id_t ecma_typedarray_helper_get_magic_string (uint8_t builtin_id) /**< the builtin id of the typedarray **/ { #define TYPEDARRAY_ID_CASE(builtin_id, magic_id) \ case builtin_id: \ { \ - return magic_id; \ + return (lit_magic_string_id_t) magic_id; \ } switch (builtin_id) diff --git a/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-helpers.h b/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-helpers.h index c180c767ba..9276a3f337 100644 --- a/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-helpers.h +++ b/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-helpers.h @@ -29,7 +29,7 @@ bool ecma_typedarray_helper_is_typedarray (uint8_t builtin_id); uint8_t ecma_typedarray_helper_get_shift_size (uint8_t builtin_id); uint8_t ecma_typedarray_helper_get_builtin_id (ecma_object_t *obj_p); -uint8_t ecma_typedarray_helper_get_magic_string (uint8_t builtin_id); +lit_magic_string_id_t ecma_typedarray_helper_get_magic_string (uint8_t builtin_id); uint8_t ecma_typedarray_helper_get_prototype_id (uint8_t builtin_id); ecma_value_t diff --git a/jerry-core/ecma/operations/ecma-dataview-object.c b/jerry-core/ecma/operations/ecma-dataview-object.c new file mode 100644 index 0000000000..e710c60102 --- /dev/null +++ b/jerry-core/ecma/operations/ecma-dataview-object.c @@ -0,0 +1,324 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ecma-arraybuffer-object.h" +#include "ecma-builtins.h" +#include "ecma-builtin-typedarray-helpers.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-helpers.h" +#include "ecma-dataview-object.h" +#include "ecma-typedarray-object.h" +#include "ecma-objects.h" + +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmadataviewobject ECMA builtin DataView helper functions + * @{ + */ + +/** + * Handle calling [[Construct]] of built-in DataView like objects + * + * See also: + * ECMA-262 v6, 24.2.2.1 + * + * @return created DataView object as an ecma-value - if success + * raised error - otherwise + */ +ecma_value_t +ecma_op_dataview_create (const ecma_value_t *arguments_list_p, /**< arguments list */ + ecma_length_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + ecma_value_t buffer = arguments_list_len > 0 ? arguments_list_p[0] : ECMA_VALUE_UNDEFINED; + + /* 2. */ + if (!ecma_is_value_object (buffer)) + { + return ecma_raise_type_error (ECMA_ERR_MSG ("Argument buffer is not an object.")); + } + + ecma_object_t *buffer_p = ecma_get_object_from_value (buffer); + + /* 3. */ + if (!ecma_object_class_is (buffer_p, LIT_MAGIC_STRING_ARRAY_BUFFER_UL)) + { + return ecma_raise_type_error (ECMA_ERR_MSG ("Argument buffer is not an arraybuffer.")); + } + + /* 4 - 6. */ + int32_t offset = 0; + + if (arguments_list_len > 1) + { + ecma_number_t number_offset; + ecma_value_t number_offset_value = ecma_get_number (arguments_list_p[1], &number_offset); + + if (ECMA_IS_VALUE_ERROR (number_offset_value)) + { + return number_offset_value; + } + + offset = ecma_number_to_int32 (number_offset); + + /* 7. */ + if (number_offset != offset || offset < 0) + { + return ecma_raise_range_error (ECMA_ERR_MSG ("Start offset is outside the bounds of the buffer.")); + } + } + + /* 8. TODO: Throw TypeError, when Detached ArrayBuffer will be supported. */ + + /* 9. */ + ecma_length_t buffer_byte_length = ecma_arraybuffer_get_length (buffer_p); + + /* 10. */ + if ((ecma_length_t) offset > buffer_byte_length) + { + return ecma_raise_range_error (ECMA_ERR_MSG ("Start offset is outside the bounds of the buffer.")); + } + + /* 11 - 12. */ + uint32_t viewByteLength; + if (arguments_list_len > 2) + { + /* 12.a */ + ecma_number_t byte_length; + ecma_value_t byte_length_value = ecma_get_number (arguments_list_p[2], &byte_length); + + /* 12.b */ + if (ECMA_IS_VALUE_ERROR (byte_length_value)) + { + return byte_length_value; + } + + int32_t byte_length_int32 = ecma_number_to_int32 (byte_length); + + if (ecma_number_is_infinity (byte_length)) + { + viewByteLength = UINT32_MAX; + } + else if (byte_length_int32 <= 0) + { + viewByteLength = 0; + } + else + { + viewByteLength = JERRY_MIN ((ecma_length_t) byte_length_int32, UINT32_MAX); + } + + /* 12.c */ + if ((ecma_length_t) offset + viewByteLength > buffer_byte_length) + { + return ecma_raise_range_error (ECMA_ERR_MSG ("Start offset is outside the bounds of the buffer.")); + } + } + else + { + /* 11.a */ + viewByteLength = (uint32_t) (buffer_byte_length - (ecma_length_t) offset); + } + + /* 13. */ + ecma_object_t *object_p = ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_DATAVIEW_PROTOTYPE), + sizeof (ecma_dataview_object_t), + ECMA_OBJECT_TYPE_CLASS); + + ecma_dataview_object_t *dataview_obj_p = (ecma_dataview_object_t *) object_p; + dataview_obj_p->header.u.class_prop.class_id = LIT_MAGIC_STRING_DATAVIEW_UL; + dataview_obj_p->header.u.class_prop.u.length = viewByteLength; + dataview_obj_p->buffer_p = buffer_p; + dataview_obj_p->byte_offset = (uint32_t) offset; + + return ecma_make_object_value (object_p); +} /* ecma_op_dataview_create */ + +/** + * Get the DataView object pointer + * + * Note: + * If the function returns with NULL, the error object has + * already set, and the caller must return with ECMA_VALUE_ERROR + * + * @return pointer to the dataView if this_arg is a valid dataView object + * NULL otherwise + */ +ecma_dataview_object_t * +ecma_op_dataview_get_object (ecma_value_t this_arg) /**< this argument */ +{ + if (ecma_is_value_object (this_arg)) + { + ecma_dataview_object_t *dataview_object_p = (ecma_dataview_object_t *) ecma_get_object_from_value (this_arg); + + if (ecma_get_object_type (&dataview_object_p->header.object) == ECMA_OBJECT_TYPE_CLASS + && dataview_object_p->header.u.class_prop.class_id == LIT_MAGIC_STRING_DATAVIEW_UL) + { + return dataview_object_p; + } + } + + ecma_raise_type_error (ECMA_ERR_MSG ("Expected a DataView object.")); + return NULL; +} /* ecma_op_dataview_get_object */ + +/** + * Helper union to specify the system's endiannes + */ +typedef union +{ + uint32_t number; /**< for write numeric data */ + char data[sizeof (uint32_t)]; /**< for read numeric data */ +} ecma_dataview_endiannes_check_t; + +/** + * Helper function to check the current system endiannes + * + * @return true - if the current system has little endian byteorder + * false - otherwise + */ +static bool +ecma_dataview_check_little_endian (void) +{ + ecma_dataview_endiannes_check_t checker; + checker.number = 0x01; + + return checker.data[0] == 0x01; +} /* ecma_dataview_check_little_endian */ + +/** + * Helper function for swap bytes if the system's endiannes + * does not match with the requested endiannes. + */ +static void +ecma_dataview_swap_order (bool system_is_little_endian, /**< true - if the system has little endian byteorder + * false - otherwise */ + bool is_little_endian, /**< true - if little endian byteorder is requested + * false - otherwise */ + uint32_t element_size, /**< element size byte according to the Table 49.*/ + lit_utf8_byte_t *block_p) /**< data block */ +{ + if (system_is_little_endian ^ is_little_endian) + { + for (uint32_t i = 0; i < element_size / 2; i++) + { + lit_utf8_byte_t tmp = block_p[i]; + block_p[i] = block_p[element_size - i - 1]; + block_p[element_size - i - 1] = tmp; + } + } +} /* ecma_dataview_swap_order */ + +/** + * GetViewValue and SetViewValue abstact operation + * + * See also: + * ECMA-262 v6, 24.2.1.1 + * ECMA-262 v6, 24.2.1.2 + * + * @return ecma value + */ +ecma_value_t +ecma_op_dataview_get_set_view_value (ecma_value_t view, /**< the operation's 'view' argument */ + ecma_value_t request_index, /**< the operation's 'requestIndex' argument */ + ecma_value_t is_little_endian_value, /**< the operation's + * 'isLittleEndian' argument */ + ecma_value_t value_to_set, /**< the operation's 'value' argument */ + uint8_t type) /**< the operation's 'type' argument */ +{ + /* 1 - 2. */ + ecma_dataview_object_t *view_p = ecma_op_dataview_get_object (view); + + if (JERRY_UNLIKELY (view_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + /* 3 - 5. */ + ecma_number_t number_index; + ecma_value_t number_index_value = ecma_get_number (request_index, &number_index); + + if (ECMA_IS_VALUE_ERROR (number_index_value)) + { + return number_index_value; + } + + int32_t get_index = ecma_number_to_int32 (number_index); + + /* 6. */ + if (number_index != get_index || get_index < 0) + { + return ecma_raise_range_error (ECMA_ERR_MSG ("Start offset is outside the bounds of the buffer.")); + } + + /* 7. */ + bool is_little_endian = ecma_op_to_boolean (is_little_endian_value); + + /* 8. TODO: Throw TypeError, when Detached ArrayBuffer will be supported. */ + + /* 9. */ + ecma_object_t *buffer_p = view_p->buffer_p; + JERRY_ASSERT (ecma_object_class_is (buffer_p, LIT_MAGIC_STRING_ARRAY_BUFFER_UL)); + + /* 10. */ + uint32_t view_offset = view_p->byte_offset; + + /* 11. */ + uint32_t view_size = view_p->header.u.class_prop.u.length; + + /* 12. */ + uint8_t element_size = (uint8_t) (1 << (ecma_typedarray_helper_get_shift_size (type))); + + /* 13. */ + if ((uint32_t) get_index + element_size > view_size) + { + return ecma_raise_range_error (ECMA_ERR_MSG ("Start offset is outside the bounds of the buffer.")); + } + + /* 14. */ + uint32_t buffer_index = (uint32_t) get_index + view_offset; + lit_magic_string_id_t id = ecma_typedarray_helper_get_magic_string (type); + lit_utf8_byte_t *block_p = ecma_arraybuffer_get_buffer (buffer_p) + buffer_index; + + bool system_is_little_endian = ecma_dataview_check_little_endian (); + + if (ecma_is_value_empty (value_to_set)) + { + lit_utf8_byte_t swap_block_p[element_size]; + memcpy (swap_block_p, block_p, element_size * sizeof (lit_utf8_byte_t)); + ecma_dataview_swap_order (system_is_little_endian, is_little_endian, element_size, swap_block_p); + return ecma_make_number_value (ecma_get_typedarray_element (swap_block_p, id)); + } + + if (ecma_is_value_number (value_to_set)) + { + ecma_set_typedarray_element (block_p, ecma_get_number_from_value (value_to_set), id); + ecma_dataview_swap_order (system_is_little_endian, is_little_endian, element_size, block_p); + } + + return ECMA_VALUE_UNDEFINED; +} /* ecma_op_dataview_get_set_view_value */ + +/** + * @} + * @} + */ + +#endif /* ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW */ diff --git a/jerry-core/ecma/operations/ecma-dataview-object.h b/jerry-core/ecma/operations/ecma-dataview-object.h new file mode 100644 index 0000000000..fa2c619089 --- /dev/null +++ b/jerry-core/ecma/operations/ecma-dataview-object.h @@ -0,0 +1,42 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ECMA_DATAVIEW_OBJECT_H +#define ECMA_DATAVIEW_OBJECT_H + +#include "ecma-globals.h" + +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmadataviewobject ECMA builtin DataView helper functions + * @{ + */ + +ecma_value_t ecma_op_dataview_create (const ecma_value_t *arguments_list_p, ecma_length_t arguments_list_len); +ecma_dataview_object_t *ecma_op_dataview_get_object (ecma_value_t this_arg); +ecma_value_t ecma_op_dataview_get_set_view_value (ecma_value_t view, ecma_value_t request_index, + ecma_value_t little_endian, ecma_value_t value_to_set, uint8_t type); + +/** + * @} + * @} + */ + +#endif /* ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW */ + +#endif /* !ECMA_DATAVIEW_OBJECT_H */ diff --git a/jerry-core/ecma/operations/ecma-objects.c b/jerry-core/ecma/operations/ecma-objects.c index a8d63401f5..0d63b03831 100644 --- a/jerry-core/ecma/operations/ecma-objects.c +++ b/jerry-core/ecma/operations/ecma-objects.c @@ -1841,6 +1841,9 @@ ecma_object_check_class_name_is_object (ecma_object_t *obj_p) /**< object */ #if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_SYMBOL_PROTOTYPE) #endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */ +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) + || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_DATAVIEW_PROTOTYPE) +#endif /* ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) */ || ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE)); #else /* JERRY_NDEBUG */ JERRY_UNUSED (obj_p); diff --git a/jerry-core/include/jerryscript-core.h b/jerry-core/include/jerryscript-core.h index 2bec6dd94a..3b1611f3a1 100644 --- a/jerry-core/include/jerryscript-core.h +++ b/jerry-core/include/jerryscript-core.h @@ -93,6 +93,7 @@ typedef enum JERRY_FEATURE_LINE_INFO, /**< line info available */ JERRY_FEATURE_LOGGING, /**< logging */ JERRY_FEATURE_SYMBOL, /**< symbol support */ + JERRY_FEATURE_DATAVIEW, /**< DataView support */ JERRY_FEATURE__COUNT /**< number of features. NOTE: must be at the end of the list */ } jerry_feature_t; @@ -593,6 +594,21 @@ jerry_length_t jerry_arraybuffer_read (const jerry_value_t value, jerry_length_t jerry_get_arraybuffer_byte_length (const jerry_value_t value); uint8_t *jerry_get_arraybuffer_pointer (const jerry_value_t value); +/** + * DataView functions. + */ +jerry_value_t +jerry_create_dataview (const jerry_value_t value, + const jerry_length_t byte_offset, + const jerry_length_t byte_length); + +bool +jerry_value_is_dataview (const jerry_value_t value); + +jerry_value_t +jerry_get_dataview_buffer (const jerry_value_t dataview, + jerry_length_t *byte_offset, + jerry_length_t *byte_length); /** * TypedArray functions. diff --git a/jerry-core/lit/lit-magic-strings.inc.h b/jerry-core/lit/lit-magic-strings.inc.h index 159a3ca914..579a272d99 100644 --- a/jerry-core/lit/lit-magic-strings.inc.h +++ b/jerry-core/lit/lit-magic-strings.inc.h @@ -236,7 +236,8 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SYMBOL_UL, "Symbol") #if ENABLED (JERRY_ES2015_BUILTIN) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ASSIGN, "assign") #endif -#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) \ +|| ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BUFFER, "buffer") #endif LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CALLEE, "callee") @@ -333,6 +334,11 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FOR_EACH_UL, "forEach") #endif #if ENABLED (JERRY_BUILTIN_DATE) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_DATE_UL, "getDate") +#endif +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_INT8_UL, "getInt8") +#endif +#if ENABLED (JERRY_BUILTIN_DATE) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_TIME_UL, "getTime") #endif #if ENABLED (JERRY_BUILTIN_ANNEXB) && ENABLED (JERRY_BUILTIN_DATE) @@ -359,6 +365,11 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REVERSE, "reverse") #endif #if ENABLED (JERRY_BUILTIN_DATE) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_DATE_UL, "setDate") +#endif +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_INT8_UL, "setInt8") +#endif +#if ENABLED (JERRY_BUILTIN_DATE) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_TIME_UL, "setTime") #endif #if ENABLED (JERRY_BUILTIN_ANNEXB) && ENABLED (JERRY_BUILTIN_DATE) @@ -374,6 +385,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_FIXED_UL, "toFixed") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UNSHIFT, "unshift") #endif LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_VALUE_OF_UL, "valueOf") +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DATAVIEW_UL, "DataView") +#endif LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FUNCTION_UL, "Function") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_INFINITY_UL, "Infinity") #if ENABLED (JERRY_BUILTIN_ERRORS) @@ -382,8 +396,17 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_URI_ERROR_UL, "URIError") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FUNCTION, "function") #if ENABLED (JERRY_BUILTIN_DATE) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_HOURS_UL, "getHours") +#endif +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_INT16_UL, "getInt16") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_INT32_UL, "getInt32") +#endif +#if ENABLED (JERRY_BUILTIN_DATE) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_MONTH_UL, "getMonth") #endif +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UINT8_UL, "getUint8") +#endif LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_FINITE, "isFinite") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_FROZEN_UL, "isFrozen") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_SEALED_UL, "isSealed") @@ -393,8 +416,17 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ITERATOR, "iterator") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PARSE_INT, "parseInt") #if ENABLED (JERRY_BUILTIN_DATE) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_HOURS_UL, "setHours") +#endif +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_INT16_UL, "setInt16") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_INT32_UL, "setInt32") +#endif +#if ENABLED (JERRY_BUILTIN_DATE) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_MONTH_UL, "setMonth") #endif +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UINT8_UL, "setUint8") +#endif #if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SUBARRAY, "subarray") #endif @@ -425,11 +457,19 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ENCODE_URI, "encodeURI") #if ENABLED (JERRY_BUILTIN_DATE) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UTC_DAY_UL, "getUTCDay") #endif +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UINT16_UL, "getUint16") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UINT32_UL, "getUint32") +#endif #if ENABLED (JERRY_BUILTIN_REGEXP) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LASTINDEX_UL, "lastIndex") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MULTILINE, "multiline") #endif LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PROTOTYPE, "prototype") +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UINT16_UL, "setUint16") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UINT32_UL, "setUint32") +#endif #if ENABLED (JERRY_BUILTIN_JSON) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_STRINGIFY, "stringify") #endif @@ -447,6 +487,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_RANGE_ERROR_UL, "RangeError") #if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TYPED_ARRAY_UL, "TypedArray") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UINT8_ARRAY_UL, "Uint8Array") +#endif +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) \ +|| ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BYTE_LENGTH_UL, "byteLength") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BYTE_OFFSET_UL, "byteOffset") #endif @@ -454,6 +497,12 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BYTE_OFFSET_UL, "byteOffset") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CHAR_CODE_AT_UL, "charCodeAt") #endif LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ENUMERABLE, "enumerable") +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_FLOAT_32_UL, "getFloat32") +#endif +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) && ENABLED (JERRY_NUMBER_TYPE_FLOAT64) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_FLOAT_64_UL, "getFloat64") +#endif #if ENABLED (JERRY_BUILTIN_DATE) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_MINUTES_UL, "getMinutes") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_SECONDS_UL, "getSeconds") @@ -463,12 +512,19 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UTC_DATE_UL, "getUTCDate") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IGNORECASE_UL, "ignoreCase") #endif LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PARSE_FLOAT, "parseFloat") +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_FLOAT_32_UL, "setFloat32") +#endif +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) && ENABLED (JERRY_NUMBER_TYPE_FLOAT64) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_FLOAT_64_UL, "setFloat64") +#endif #if ENABLED (JERRY_BUILTIN_DATE) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_MINUTES_UL, "setMinutes") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_SECONDS_UL, "setSeconds") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UTC_DATE_UL, "setUTCDate") #endif -#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) \ +|| ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ARRAY_BUFFER_UL, "ArrayBuffer") #endif #if ENABLED (JERRY_BUILTIN_ERRORS) @@ -651,7 +707,11 @@ LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (6, LIT_MAGIC_STRING_LOG10E_U) LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (6, LIT_MAGIC_STRING_NUMBER_UL) #endif LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (7, LIT_MAGIC_STRING_BOOLEAN_UL) +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (8, LIT_MAGIC_STRING_DATAVIEW_UL) +#else LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (8, LIT_MAGIC_STRING_FUNCTION_UL) +#endif LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (9, LIT_MAGIC_STRING_NEGATIVE_INFINITY_UL) #if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (10, LIT_MAGIC_STRING_INT16_ARRAY_UL) @@ -659,12 +719,16 @@ LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (10, LIT_MAGIC_STRING_INT16_ARRAY_UL) LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (10, LIT_MAGIC_STRING_RANGE_ERROR_UL) #elif ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (10, LIT_MAGIC_STRING_TYPED_ARRAY_UL) +#elif ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) \ +|| ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (10, LIT_MAGIC_STRING_BYTE_LENGTH_UL) #elif ENABLED (JERRY_BUILTIN_STRING) LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (10, LIT_MAGIC_STRING_CHAR_CODE_AT_UL) #else LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (10, LIT_MAGIC_STRING_ENUMERABLE) #endif -#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) +#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) \ +|| ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (11, LIT_MAGIC_STRING_ARRAY_BUFFER_UL) #elif ENABLED (JERRY_BUILTIN_ERRORS) LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (11, LIT_MAGIC_STRING_SYNTAX_ERROR_UL) diff --git a/jerry-core/lit/lit-magic-strings.ini b/jerry-core/lit/lit-magic-strings.ini index f3b461fb57..fcc722ca29 100644 --- a/jerry-core/lit/lit-magic-strings.ini +++ b/jerry-core/lit/lit-magic-strings.ini @@ -154,6 +154,7 @@ LIT_MAGIC_STRING_BOOLEAN = "boolean" LIT_MAGIC_STRING_COMPILE = "compile" LIT_MAGIC_STRING_FOR_EACH_UL = "forEach" LIT_MAGIC_STRING_GET_DATE_UL = "getDate" +LIT_MAGIC_STRING_GET_INT8_UL = "getInt8" LIT_MAGIC_STRING_GET_TIME_UL = "getTime" LIT_MAGIC_STRING_GET_YEAR_UL = "getYear" LIT_MAGIC_STRING_INDEX_OF_UL = "indexOf" @@ -164,24 +165,32 @@ LIT_MAGIC_STRING_RESOLVE = "resolve" LIT_MAGIC_STRING_REVERSE = "reverse" LIT_MAGIC_STRING_SET_DATE_UL = "setDate" LIT_MAGIC_STRING_SET_TIME_UL = "setTime" +LIT_MAGIC_STRING_SET_INT8_UL = "setInt8" LIT_MAGIC_STRING_SET_YEAR_UL = "setYear" LIT_MAGIC_STRING_SPECIES = "species" LIT_MAGIC_STRING_TO_FIXED_UL = "toFixed" LIT_MAGIC_STRING_UNSHIFT = "unshift" LIT_MAGIC_STRING_VALUE_OF_UL = "valueOf" +LIT_MAGIC_STRING_DATAVIEW_UL = "DataView" LIT_MAGIC_STRING_FUNCTION_UL = "Function" LIT_MAGIC_STRING_INFINITY_UL = "Infinity" LIT_MAGIC_STRING_URI_ERROR_UL = "URIError" LIT_MAGIC_STRING_FUNCTION = "function" LIT_MAGIC_STRING_GET_HOURS_UL = "getHours" +LIT_MAGIC_STRING_GET_INT16_UL = "getInt16" +LIT_MAGIC_STRING_GET_INT32_UL = "getInt32" LIT_MAGIC_STRING_GET_MONTH_UL = "getMonth" +LIT_MAGIC_STRING_GET_UINT8_UL = "getUint8" LIT_MAGIC_STRING_IS_FINITE = "isFinite" LIT_MAGIC_STRING_IS_FROZEN_UL = "isFrozen" LIT_MAGIC_STRING_IS_SEALED_UL = "isSealed" LIT_MAGIC_STRING_ITERATOR = "iterator" LIT_MAGIC_STRING_PARSE_INT = "parseInt" LIT_MAGIC_STRING_SET_HOURS_UL = "setHours" +LIT_MAGIC_STRING_SET_INT16_UL = "setInt16" +LIT_MAGIC_STRING_SET_INT32_UL = "setInt32" LIT_MAGIC_STRING_SET_MONTH_UL = "setMonth" +LIT_MAGIC_STRING_SET_UINT8_UL = "setUint8" LIT_MAGIC_STRING_SUBARRAY = "subarray" LIT_MAGIC_STRING_TO_STRING_UL = "toString" LIT_MAGIC_STRING_UNESCAPE = "unescape" @@ -198,10 +207,14 @@ LIT_MAGIC_STRING_ARGUMENTS = "arguments" LIT_MAGIC_STRING_DECODE_URI = "decodeURI" LIT_MAGIC_STRING_ENCODE_URI = "encodeURI" LIT_MAGIC_STRING_GET_UTC_DAY_UL = "getUTCDay" +LIT_MAGIC_STRING_GET_UINT16_UL = "getUint16" +LIT_MAGIC_STRING_GET_UINT32_UL = "getUint32" LIT_MAGIC_STRING_LASTINDEX_UL = "lastIndex" LIT_MAGIC_STRING_MULTILINE = "multiline" LIT_MAGIC_STRING_PROTOTYPE = "prototype" LIT_MAGIC_STRING_STRINGIFY = "stringify" +LIT_MAGIC_STRING_SET_UINT16_UL = "setUint16" +LIT_MAGIC_STRING_SET_UINT32_UL = "setUint32" LIT_MAGIC_STRING_SUBSTRING = "substring" LIT_MAGIC_STRING_UNDEFINED = "undefined" LIT_MAGIC_STRING_INT16_ARRAY_UL = "Int16Array" @@ -213,11 +226,15 @@ LIT_MAGIC_STRING_BYTE_LENGTH_UL = "byteLength" LIT_MAGIC_STRING_BYTE_OFFSET_UL = "byteOffset" LIT_MAGIC_STRING_CHAR_CODE_AT_UL = "charCodeAt" LIT_MAGIC_STRING_ENUMERABLE = "enumerable" +LIT_MAGIC_STRING_GET_FLOAT_32_UL = "getFloat32" +LIT_MAGIC_STRING_GET_FLOAT_64_UL = "getFloat64" LIT_MAGIC_STRING_GET_MINUTES_UL = "getMinutes" LIT_MAGIC_STRING_GET_SECONDS_UL = "getSeconds" LIT_MAGIC_STRING_GET_UTC_DATE_UL = "getUTCDate" LIT_MAGIC_STRING_IGNORECASE_UL = "ignoreCase" LIT_MAGIC_STRING_PARSE_FLOAT = "parseFloat" +LIT_MAGIC_STRING_SET_FLOAT_32_UL = "setFloat32" +LIT_MAGIC_STRING_SET_FLOAT_64_UL = "setFloat64" LIT_MAGIC_STRING_SET_MINUTES_UL = "setMinutes" LIT_MAGIC_STRING_SET_SECONDS_UL = "setSeconds" LIT_MAGIC_STRING_SET_UTC_DATE_UL = "setUTCDate" diff --git a/jerry-core/profiles/README.md b/jerry-core/profiles/README.md index ce9e56279f..db7cfd1917 100644 --- a/jerry-core/profiles/README.md +++ b/jerry-core/profiles/README.md @@ -31,6 +31,7 @@ Alternatively, if you want to use a custom profile at ``` # Turn off every ES2015 feature EXCEPT the arrow functions JERRY_ES2015_BUILTIN=0 +JERRY_ES2015_BUILTIN_DATAVIEW=0 JERRY_ES2015_BUILTIN_ITERATOR=0 JERRY_ES2015_BUILTIN_MAP=0 JERRY_ES2015_BUILTIN_PROMISE=0 @@ -109,6 +110,8 @@ defined to `1`. Enables or disables the [arrow functions](http://www.ecma-international.org/ecma-262/6.0/#sec-arrow-function-definitions). * `JERRY_ES2015_BUILTIN`: Enables or disables the built-in updates of the 5.1 standard. There are some differences in those built-ins which available in both [5.1](http://www.ecma-international.org/ecma-262/5.1/) and [2015](http://www.ecma-international.org/ecma-262/6.0/) versions of the standard. JerryScript uses the latest definition by default. +* `JERRY_ES2015_BUILTIN_DATAVIEW`: + Enables or disables the [DataView](https://www.ecma-international.org/ecma-262/6.0/#sec-dataview-objects) built-in. * `JERRY_ES2015_BUILTIN_ITERATOR`: Enables or disables the [Iterator](https://www.ecma-international.org/ecma-262/6.0/#sec-iterator-interface) built-in. * `JERRY_ES2015_BUILTIN_MAP`: @@ -136,6 +139,7 @@ defined to `1`. Equivalent with setting the following defines to the `JERRY_ES2015` value: * `JERRY_ES2015_ARROW_FUNCTION` * `JERRY_ES2015_BUILTIN` + * `JERRY_ES2015_BUILTIN_DATAVIEW` * `JERRY_ES2015_BUILTIN_ITERATOR` * `JERRY_ES2015_BUILTIN_MAP` * `JERRY_ES2015_BUILTIN_PROMISE` diff --git a/tests/jerry/es2015/dataview.js b/tests/jerry/es2015/dataview.js new file mode 100644 index 0000000000..6faa2bc3fb --- /dev/null +++ b/tests/jerry/es2015/dataview.js @@ -0,0 +1,229 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* ES2015 24.2.2.1.1 */ +try { + DataView (); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} + +/* ES2015 24.2.2.1.2 */ +try { + new DataView (5); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} + +/* ES2015 24.2.2.1.3 */ +try { + new DataView ({}); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} + +var buffer = new ArrayBuffer (16); + +/* ES2015 24.2.2.1.6 */ +try { + new DataView (buffer, { toString: function () { throw new ReferenceError ('foo') } }); + assert (false); +} catch (e) { + assert (e instanceof ReferenceError); + assert (e.message === 'foo'); +} + +/* ES2015 24.2.2.1.7 (numberOffset != offset)*/ +try { + new DataView (buffer, 1.5); + assert (false); +} catch (e) { + assert (e instanceof RangeError); +} + + +/* ES2015 24.2.2.1.7 (offset < 0) */ +try { + new DataView (buffer, -1); + assert (false); +} catch (e) { + assert (e instanceof RangeError); +} + +/* ES2015 24.2.2.1.10 */ +try { + new DataView (buffer, 17); + assert (false); +} catch (e) { + assert (e instanceof RangeError); +} + +/* ES2015 24.2.2.1.12.b */ +try { + new DataView (buffer, 0, { toString: function () { throw new ReferenceError ('bar') } }); + assert (false); +} catch (e) { + assert (e instanceof ReferenceError); + assert (e.message === 'bar'); +} + +/* ES2015 24.2.2.1.12.b */ +try { + new DataView (buffer, 0, Infinity); + assert (false); +} catch (e) { + assert (e instanceof RangeError); +} + +/* ES2015 24.2.2.1.12.c */ +try { + new DataView (buffer, 4, 13); + assert (false); +} catch (e) { + assert (e instanceof RangeError); +} + +/* Tests accessors: ES2015 24.2.2.1 - 24.2.2.3 */ +var accessorList = ['buffer', 'byteOffset', 'byteLength']; + +accessorList.forEach (function (prop) { + /* ES2015 24.2.4.{1, 2, 3}.{2, 3} */ + try { + var obj = {}; + Object.setPrototypeOf (obj, DataView.prototype); + obj[prop]; + assert (false); + } catch (e) { + assert (e instanceof TypeError); + } +}); + +buffer = new ArrayBuffer (32); +var view1 = new DataView (buffer); + +assert (view1.buffer === buffer); +assert (view1.byteOffset === 0); +assert (view1.byteLength === buffer.byteLength); + +var view2 = new DataView (buffer, 8); +assert (view2.buffer === buffer); +assert (view2.byteOffset === 8); +assert (view2.byteLength === buffer.byteLength - view2.byteOffset); + +var view3 = new DataView (buffer, 8, 16); +assert (view3.buffer === buffer); +assert (view3.byteOffset === 8); +assert (view3.byteLength === 16); + +/* Test get/set routines */ +var getters = ['getInt8', 'getUint8', 'getInt16', 'getUint16', 'getInt32', 'getUint32', 'getFloat32', 'getFloat64']; +var setters = ['setInt8', 'setUint8', 'setInt16', 'setUint16', 'setInt32', 'setUint32', 'setFloat32', 'setFloat64']; +var gettersSetters = getters.concat (setters); + +gettersSetters.forEach (function (propName) { + /* ES2015 24.2.1.{1, 2}.1 */ + var routine = DataView.prototype[propName]; + try { + DataView.prototype[propName].call (5); + assert (false); + } catch (e) { + assert (e instanceof TypeError); + } + + /* ES2015 24.2.1.{1, 2}.2 */ + try { + DataView.prototype[propName].call ({}); + assert (false); + } catch (e) { + assert (e instanceof TypeError); + } + + /* ES2015 24.2.1.{1, 2}.5 */ + try { + var buffer = new ArrayBuffer (16); + var view = new DataView (buffer) + view[propName] ({ toString : function () { throw new ReferenceError ('fooBar') } }); + assert (false); + } catch (e) { + assert (e instanceof ReferenceError); + assert (e.message == 'fooBar'); + } + + var buffer = new ArrayBuffer (16); + var view = new DataView (buffer) + + /* ES2015 24.2.1.{1, 2}.6 (numberIndex != getIndex) */ + try { + view[propName] (1.5); + assert (false); + } catch (e) { + assert (e instanceof RangeError); + } + + /* ES2015 24.2.1.{1, 2}.6 (getIndex < 0) */ + try { + view[propName] (-1); + assert (false); + } catch (e) { + assert (e instanceof RangeError); + } + + /* ES2015 24.2.1.{1, 2}.13 */ + try { + view[propName] (20); + assert (false); + } catch (e) { + assert (e instanceof RangeError); + } +}); + +/* Test the endianness */ +function validateResult (view, offset, isLitteEndian, results) { + for (var i = 0; i < getters.length; i++) { + assert (results[i] === view[getters[i]](offset, isLitteEndian)); + } +} + +buffer = new ArrayBuffer (24); +view1 = new DataView (buffer); +view2 = new DataView (buffer, 4, 12); +view3 = new DataView (buffer, 6, 18); + +view1.setUint8 (0, 255); +validateResult(view1, 0, false, [-1, 255, -256, 65280, -16777216, 4278190080, -1.7014118346046924e+38, -5.486124068793689e+303]); +validateResult(view1, 0, true, [-1, 255, 255, 255, 255, 255, 3.5733110840282835e-43, 1.26e-321]); +validateResult(view1, 2, false, [0, 0, 0, 0, 0, 0, 0, 0]); +validateResult(view1, 2, true, [0, 0, 0, 0, 0, 0, 0, 0]); + +view1.setInt16 (4, 40000); +validateResult(view1, 4, false, [-100, 156, -25536, 40000, -1673527296, 2621440000, -6.352747104407253e-22, -1.2938158758247024e-172]); +validateResult(view2, 0, false, [-100, 156, -25536, 40000, -1673527296, 2621440000, -6.352747104407253e-22, -1.2938158758247024e-172]); +validateResult(view1, 4, true, [-100, 156, 16540, 16540, 16540, 16540, 2.3177476599932474e-41, 8.172e-320]); +validateResult(view2, 0, true, [-100, 156, 16540, 16540, 16540, 16540, 2.3177476599932474e-41, 8.172e-320]); + +view2.setUint32 (2, 3000000000, true); +validateResult(view2, 2, false, [0, 0, 94, 94, 6213810, 6213810, 8.707402410606192e-39, 6.856613170926581e-307]); +validateResult(view3, 0, false, [0, 0, 94, 94, 6213810, 6213810, 8.707402410606192e-39, 6.856613170926581e-307]); +validateResult(view2, 2, true, [0, 0, 24064, 24064, -1294967296, 3000000000, -2.425713319098577e-8, 1.4821969375e-314]); +validateResult(view3, 0, true, [0, 0, 24064, 24064, -1294967296, 3000000000, -2.425713319098577e-8, 1.4821969375e-314]); + +view3.setFloat32 (4, 8.5); +validateResult(view3, 4, false, [65, 65, 16648, 16648, 1091043328, 1091043328, 8.5, 196608]); +validateResult(view3, 4, true, [65, 65, 2113, 2113, 2113, 2113, 2.9609436551183385e-42, 1.044e-320]); +validateResult(view2, 4, false, [-48, 208, -12110, 53426, -793624312, 3501342984, -23924850688, -5.411000515087672e+80]); +validateResult(view2, 4, true, [-48, 208, -19760, 45776, 138523344, 138523344, 5.828901796903399e-34, 6.84396254e-316]); diff --git a/tests/jerry/es2015/regression-test-issue-2733.js b/tests/jerry/es2015/regression-test-issue-2733.js deleted file mode 100644 index 098fb65c93..0000000000 --- a/tests/jerry/es2015/regression-test-issue-2733.js +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright JS Foundation and other contributors, http://js.foundation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -var recursion_counter = 0; -var recursion_limit = 1000; -var fz_globalObject = this - -function fz_is_primitive(value) { - var value_type = typeof value - if (value_type !== "function" && value_type !== "object") - return value_type -} - -function fz_starts_with(str, pattern) { - for (var i = 0; i < pattern.length; i++) - if (str[i] !== pattern[i]) - return - return true -} - -function fz_collect_values(value) { - if (++recursion_counter >= recursion_limit) { - return - } - - var primitive = fz_is_primitive(value) - if (primitive) - return - var prop_names = Object.getOwnPropertyNames(value) - for (var i = 0; i < prop_names.length; i++) { - var prop_name = prop_names[i] - if (!fz_starts_with(prop_name, "fz_")) { - fz_collect_values(value[prop_name]) - } - } -} - -fz_collect_values(fz_globalObject) diff --git a/tests/unit-core/test-dataview.c b/tests/unit-core/test-dataview.c new file mode 100644 index 0000000000..30dd7a62a7 --- /dev/null +++ b/tests/unit-core/test-dataview.c @@ -0,0 +1,103 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "jerryscript.h" +#include "jerryscript-port.h" +#include "jerryscript-port-default.h" +#include "test-common.h" + +int +main (void) +{ + if (!jerry_is_feature_enabled (JERRY_FEATURE_DATAVIEW)) + { + jerry_port_log (JERRY_LOG_LEVEL_ERROR, "DataView support is disabled!\n"); + return 0; + } + + /* DataView builtin requires the TypedArray builtin */ + TEST_ASSERT (jerry_is_feature_enabled (JERRY_FEATURE_TYPEDARRAY)); + + jerry_init (JERRY_INIT_EMPTY); + + /* Test accessors */ + jerry_value_t arraybuffer = jerry_create_arraybuffer (16); + jerry_value_t view1 = jerry_create_dataview (arraybuffer, 0, 16); + TEST_ASSERT (!jerry_value_is_error (view1)); + TEST_ASSERT (jerry_value_is_dataview (view1)); + + jerry_length_t byteOffset = 0; + jerry_length_t byteLength = 0;; + jerry_value_t internal_buffer = jerry_get_dataview_buffer (view1, &byteOffset, &byteLength); + TEST_ASSERT (jerry_binary_operation (JERRY_BIN_OP_STRICT_EQUAL, internal_buffer, arraybuffer)); + TEST_ASSERT (byteOffset == 0); + TEST_ASSERT (byteLength == 16); + jerry_release_value (internal_buffer); + + jerry_value_t view2 = jerry_create_dataview (arraybuffer, 12, 4); + TEST_ASSERT (!jerry_value_is_error (view1)); + TEST_ASSERT (jerry_value_is_dataview (view2)); + internal_buffer = jerry_get_dataview_buffer (view2, &byteOffset, &byteLength); + TEST_ASSERT (jerry_binary_operation (JERRY_BIN_OP_STRICT_EQUAL, internal_buffer, arraybuffer)); + TEST_ASSERT (byteOffset == 12); + TEST_ASSERT (byteLength == 4); + jerry_release_value (internal_buffer); + + /* Test invalid construction */ + jerry_value_t empty_object = jerry_create_object (); + jerry_value_t view3 = jerry_create_dataview (empty_object, 20, 10); + TEST_ASSERT (jerry_value_is_error (view3)); + jerry_value_t error_obj = jerry_get_value_from_error (view3, true); + TEST_ASSERT (jerry_get_error_type (error_obj) == JERRY_ERROR_TYPE); + jerry_release_value (error_obj); + jerry_release_value (empty_object); + + jerry_value_t view4 = jerry_create_dataview (arraybuffer, 20, 10); + TEST_ASSERT (jerry_value_is_error (view3)); + error_obj = jerry_get_value_from_error (view4, true); + TEST_ASSERT (jerry_get_error_type (error_obj) == JERRY_ERROR_RANGE); + jerry_release_value (error_obj); + + /* Test getting/setting values */ + jerry_value_t global_obj = jerry_get_global_object (); + jerry_value_t view1_str = jerry_create_string ((const jerry_char_t *) "view1"); + jerry_value_t view2_str = jerry_create_string ((const jerry_char_t *) "view2"); + TEST_ASSERT (jerry_set_property (global_obj, view1_str, view1)); + TEST_ASSERT (jerry_set_property (global_obj, view2_str, view2)); + + jerry_release_value (view1_str); + jerry_release_value (view2_str); + jerry_release_value (global_obj); + + const jerry_char_t set_src[] = "view1.setInt16 (12, 255)"; + TEST_ASSERT (jerry_value_is_undefined (jerry_eval (set_src, sizeof (set_src) - 1, JERRY_PARSE_NO_OPTS))); + + const jerry_char_t get_src[] = "view2.getInt16 (0)"; + TEST_ASSERT (jerry_get_number_value (jerry_eval (get_src, sizeof (get_src) - 1, JERRY_PARSE_NO_OPTS)) == 255); + + const jerry_char_t get_src_little_endian[] = "view2.getInt16 (0, true)"; + TEST_ASSERT (jerry_get_number_value (jerry_eval (get_src_little_endian, + sizeof (get_src_little_endian) - 1, + JERRY_PARSE_NO_OPTS)) == -256); + + /* Cleanup */ + jerry_release_value (view2); + jerry_release_value (view1); + jerry_release_value (arraybuffer); + + jerry_cleanup (); + + return 0; +} /* main */