From 28c186c98fc617c7100ea5b4121bd5a141a0c904 Mon Sep 17 00:00:00 2001 From: Szilagyi Adam Date: Fri, 28 Aug 2020 14:00:49 +0200 Subject: [PATCH] Refactor ArrayBuffer.prototype.slice to conform ES11 standard (#4174) The algorithm is based on ECMA-262 v11, 24.1.4.3 JerryScript-DCO-1.0-Signed-off-by: Adam Szilagyi aszilagy@inf.u-szeged.hu --- .../ecma-builtin-arraybuffer-prototype.c | 132 ++++++++++++++---- .../ecma-builtin-arraybuffer-prototype.inc.h | 2 +- tests/test262-esnext-excludelist.xml | 9 -- 3 files changed, 109 insertions(+), 34 deletions(-) diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer-prototype.c index 39d9105e2..c9cb34795 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer-prototype.c @@ -15,7 +15,10 @@ #include "ecma-builtin-helpers.h" #include "ecma-builtins.h" +#include "ecma-conversion.h" #include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" #include "ecma-globals.h" #include "ecma-helpers.h" #include "ecma-objects.h" @@ -78,15 +81,15 @@ ecma_builtin_arraybuffer_prototype_bytelength_getter (ecma_value_t this_arg) /** * The ArrayBuffer.prototype object's 'slice' routine * * See also: - * ES2015, 24.1.4.3 + * ECMA-262 v11, 24.1.4.3 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t ecma_builtin_arraybuffer_prototype_object_slice (ecma_value_t this_arg, /**< this argument */ - ecma_value_t arg1, /**< routine's first argument */ - ecma_value_t arg2) /**< routine's second argument */ + const ecma_value_t *argument_list_p, /**< arguments list */ + uint32_t arguments_number) /**< number of arguments */ { if (!ecma_is_value_object (this_arg)) { @@ -95,53 +98,134 @@ ecma_builtin_arraybuffer_prototype_object_slice (ecma_value_t this_arg, /**< thi ecma_object_t *object_p = ecma_get_object_from_value (this_arg); + /* 2. */ if (!ecma_object_class_is (object_p, LIT_MAGIC_STRING_ARRAY_BUFFER_UL)) { return ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not an ArrayBuffer object.")); } + /* TODO: step 3. if SharedArrayBuffer will be implemented */ + + /* 4. */ if (ecma_arraybuffer_is_detached (object_p)) { return ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer has been detached.")); } + /* 5. */ uint32_t len = ecma_arraybuffer_get_length (object_p); - uint32_t start = 0, end = len; + uint32_t start = 0; + uint32_t end = len; - ecma_value_t ret_value = ECMA_VALUE_EMPTY; - - if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (arg1, - len, - &start))) + if (arguments_number > 0) { - return ECMA_VALUE_ERROR; - } - - if (!ecma_is_value_undefined (arg2)) - { - if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (arg2, + /* 6-7. */ + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (argument_list_p[0], len, - &end))) + &start))) { return ECMA_VALUE_ERROR; } + + if (arguments_number > 1 && !ecma_is_value_undefined (argument_list_p[1])) + { + /* 8-9 .*/ + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_uint32_index_normalize (argument_list_p[1], + len, + &end))) + { + return ECMA_VALUE_ERROR; + } + } } - if (ret_value != ECMA_VALUE_EMPTY) - { - return ret_value; - } - - JERRY_ASSERT (start <= len && end <= len); + /* 10. */ uint32_t new_len = (end >= start) ? (end - start) : 0; - ecma_object_t *new_arraybuffer_p = ecma_arraybuffer_new_object (new_len); + + /* 11. */ + ecma_value_t ctor = ecma_op_species_constructor (object_p, ECMA_BUILTIN_ID_ARRAYBUFFER); + + if (ECMA_IS_VALUE_ERROR (ctor)) + { + return ctor; + } + + /* 12. */ + ecma_object_t *ctor_obj_p = ecma_get_object_from_value (ctor); + ecma_value_t new_len_value = ecma_make_uint32_value (new_len); + + ecma_value_t new_arraybuffer = ecma_op_function_construct (ctor_obj_p, ctor_obj_p, &new_len_value, 1); + + ecma_deref_object (ctor_obj_p); + ecma_free_value (new_len_value); + + if (ECMA_IS_VALUE_ERROR (new_arraybuffer)) + { + return new_arraybuffer; + } + + ecma_object_t *new_arraybuffer_p = ecma_get_object_from_value (new_arraybuffer); + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + /* 13. */ + if (!ecma_object_class_is (new_arraybuffer_p, LIT_MAGIC_STRING_ARRAY_BUFFER_UL)) + { + ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Return value is not an ArrayBuffer object.")); + goto free_new_arraybuffer; + } + + /* TODO: step 14. if SharedArrayBuffer will be implemented */ + + /* 15. */ + if (ecma_arraybuffer_is_detached (new_arraybuffer_p)) + { + ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Return ArrayBuffer has been detached.")); + goto free_new_arraybuffer; + } + + /* 16. */ + if (ecma_op_same_value (new_arraybuffer, this_arg)) + { + ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer subclass returned this from species constructor")); + goto free_new_arraybuffer; + } + + /* 17. */ + if (ecma_arraybuffer_get_length (new_arraybuffer_p) < new_len) + { + ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Derived ArrayBuffer constructor created a too small buffer.")); + goto free_new_arraybuffer; + } + + /* 19. */ + if (ecma_arraybuffer_is_detached (object_p)) + { + ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Original ArrayBuffer has been detached.")); + goto free_new_arraybuffer; + } + + /* 20. */ lit_utf8_byte_t *old_buf = ecma_arraybuffer_get_buffer (object_p); + + /* 21. */ lit_utf8_byte_t *new_buf = ecma_arraybuffer_get_buffer (new_arraybuffer_p); + /* 22. */ memcpy (new_buf, old_buf + start, new_len); - return ecma_make_object_value (new_arraybuffer_p); +free_new_arraybuffer: + if (ret_value != ECMA_VALUE_EMPTY) + { + ecma_deref_object (new_arraybuffer_p); + } + else + { + /* 23. */ + ret_value = ecma_make_object_value (new_arraybuffer_p); + } + + return ret_value; } /* ecma_builtin_arraybuffer_prototype_object_slice */ /** diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer-prototype.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer-prototype.inc.h index 9b1ebb5e1..0cd59f17e 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer-prototype.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer-prototype.inc.h @@ -40,7 +40,7 @@ STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, /* Routine properties: * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ -ROUTINE (LIT_MAGIC_STRING_SLICE, ecma_builtin_arraybuffer_prototype_object_slice, 2, 2) +ROUTINE (LIT_MAGIC_STRING_SLICE, ecma_builtin_arraybuffer_prototype_object_slice, NON_FIXED, 2) #endif /* ENABLED (JERRY_BUILTIN_TYPEDARRAY) */ diff --git a/tests/test262-esnext-excludelist.xml b/tests/test262-esnext-excludelist.xml index 21ae9c096..5af5acdc8 100644 --- a/tests/test262-esnext-excludelist.xml +++ b/tests/test262-esnext-excludelist.xml @@ -164,14 +164,6 @@ - - - - - - - - @@ -4259,7 +4251,6 @@ -