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
This commit is contained in:
Szilagyi Adam
2020-08-28 14:00:49 +02:00
committed by GitHub
parent cd1c06510e
commit 28c186c98f
3 changed files with 109 additions and 34 deletions
@@ -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 */
/**
@@ -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) */
-9
View File
@@ -164,14 +164,6 @@
<test id="built-ins/ArrayBuffer/prototype-from-newtarget.js"><reason></reason></test>
<test id="built-ins/ArrayBuffer/prototype/byteLength/detached-buffer.js"><reason></reason></test>
<test id="built-ins/ArrayBuffer/prototype/byteLength/this-is-sharedarraybuffer.js"><reason></reason></test>
<test id="built-ins/ArrayBuffer/prototype/slice/species-constructor-is-not-object.js"><reason></reason></test>
<test id="built-ins/ArrayBuffer/prototype/slice/species-is-not-constructor.js"><reason></reason></test>
<test id="built-ins/ArrayBuffer/prototype/slice/species-is-not-object.js"><reason></reason></test>
<test id="built-ins/ArrayBuffer/prototype/slice/species-returns-larger-arraybuffer.js"><reason></reason></test>
<test id="built-ins/ArrayBuffer/prototype/slice/species-returns-not-arraybuffer.js"><reason></reason></test>
<test id="built-ins/ArrayBuffer/prototype/slice/species-returns-same-arraybuffer.js"><reason></reason></test>
<test id="built-ins/ArrayBuffer/prototype/slice/species-returns-smaller-arraybuffer.js"><reason></reason></test>
<test id="built-ins/ArrayBuffer/prototype/slice/species.js"><reason></reason></test>
<test id="built-ins/ArrayBuffer/prototype/slice/this-is-sharedarraybuffer.js"><reason></reason></test>
<test id="built-ins/ArrayIteratorPrototype/next/detach-typedarray-in-progress.js"><reason></reason></test>
<test id="built-ins/AsyncFromSyncIteratorPrototype/next/absent-value-not-passed.js"><reason></reason></test>
@@ -4259,7 +4251,6 @@
<test id="language/statements/class/name-binding/in-extends-expression.js"><reason></reason></test>
<test id="language/statements/class/setter-length-dflt.js"><reason></reason></test>
<test id="language/statements/class/static-method-length-dflt.js"><reason></reason></test>
<test id="language/statements/class/subclass/builtin-objects/ArrayBuffer/regular-subclassing.js"><reason></reason></test>
<test id="language/statements/class/subclass/default-constructor-spread-override.js"><reason></reason></test>
<test id="language/statements/class/subclass/superclass-arrow-function.js"><reason></reason></test>
<test id="language/statements/class/subclass/superclass-async-function.js"><reason></reason></test>