mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Add missing isArray checks based on the ES11 standard (#3983)
Added checks to the following methods: - ecma_builtin_json_stringify, ECMA-262 v11, 24.5.2 - ecma_builtin_json_internalize_property, ECMA-262 v11, 24.5.1.1 Fixes #3945 Fixes #3950 JerryScript-DCO-1.0-Signed-off-by: Adam Szilagyi aszilagy@inf.u-szeged.hu
This commit is contained in:
parent
b90fa63255
commit
dfabfe7a56
@ -602,7 +602,11 @@ ecma_builtin_json_parse_value (ecma_json_token_t *token_p) /**< token argument *
|
||||
} /* ecma_builtin_json_parse_value */
|
||||
|
||||
/**
|
||||
* Abstract operation InternalizeJSONProperty defined in 24.3.1.1
|
||||
* Abstract operation InternalizeJSONProperty
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v5, 24.3.1.1
|
||||
* ECMA-262 v11, 24.5.1.1
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
@ -628,48 +632,111 @@ ecma_builtin_json_internalize_property (ecma_object_t *reviver_p, /**< reviver f
|
||||
/* 3. */
|
||||
if (ecma_is_value_object (value))
|
||||
{
|
||||
/* 3.a */
|
||||
ecma_value_t is_array = ecma_is_value_array (value);
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
if (ECMA_IS_VALUE_ERROR (is_array))
|
||||
{
|
||||
ecma_free_value (value);
|
||||
return is_array;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
ecma_object_t *object_p = ecma_get_object_from_value (value);
|
||||
|
||||
ecma_collection_t *props_p = ecma_op_object_get_property_names (object_p, ECMA_LIST_ENUMERABLE);
|
||||
|
||||
ecma_value_t *buffer_p = props_p->buffer_p;
|
||||
|
||||
/* 3.d.iii */
|
||||
for (uint32_t i = 0; i < props_p->item_count; i++)
|
||||
/* 3.c */
|
||||
if (ecma_is_value_true (is_array))
|
||||
{
|
||||
ecma_string_t *property_name_p = ecma_get_string_from_value (buffer_p[i]);
|
||||
/* 3.c.ii */
|
||||
uint32_t len;
|
||||
ecma_value_t to_len = ecma_op_object_get_length (object_p, &len);
|
||||
|
||||
/* 3.d.iii.1 */
|
||||
ecma_value_t result = ecma_builtin_json_internalize_property (reviver_p, object_p, property_name_p);
|
||||
|
||||
/* 3.d.iii.2 */
|
||||
if (ECMA_IS_VALUE_ERROR (result))
|
||||
/* 3.c.iii */
|
||||
if (ECMA_IS_VALUE_ERROR (to_len))
|
||||
{
|
||||
ecma_collection_free (props_p);
|
||||
ecma_deref_object (object_p);
|
||||
|
||||
return result;
|
||||
return to_len;
|
||||
}
|
||||
|
||||
/* 3.d.iii.3 */
|
||||
if (ecma_is_value_undefined (result))
|
||||
/* 3.c.iv */
|
||||
for (uint32_t i = 0; i < len; i++)
|
||||
{
|
||||
ecma_value_t delete_val = ecma_op_general_object_delete (object_p,
|
||||
property_name_p,
|
||||
false);
|
||||
JERRY_ASSERT (ecma_is_value_boolean (delete_val));
|
||||
}
|
||||
/* 3.d.iii.4 */
|
||||
else
|
||||
{
|
||||
ecma_builtin_json_define_value_property (object_p,
|
||||
property_name_p,
|
||||
result);
|
||||
ecma_free_value (result);
|
||||
ecma_string_t *prop_index = ecma_new_ecma_string_from_uint32 (i);
|
||||
|
||||
ecma_value_t new_element = ecma_builtin_json_internalize_property (reviver_p, object_p, prop_index);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (new_element))
|
||||
{
|
||||
ecma_deref_ecma_string (prop_index);
|
||||
ecma_deref_object (object_p);
|
||||
return new_element;
|
||||
}
|
||||
|
||||
if (ecma_is_value_undefined (new_element))
|
||||
{
|
||||
ecma_value_t delete_val = ecma_op_object_delete_by_uint32_index (object_p,
|
||||
i,
|
||||
false);
|
||||
JERRY_ASSERT (ecma_is_value_boolean (delete_val));
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_builtin_json_define_value_property (object_p,
|
||||
prop_index,
|
||||
new_element);
|
||||
ecma_free_value (new_element);
|
||||
}
|
||||
|
||||
ecma_deref_ecma_string (prop_index);
|
||||
}
|
||||
}
|
||||
/* 3.d */
|
||||
else
|
||||
{
|
||||
ecma_collection_t *props_p = ecma_op_object_get_property_names (object_p, ECMA_LIST_ENUMERABLE);
|
||||
|
||||
ecma_collection_free (props_p);
|
||||
JERRY_ASSERT (props_p != NULL);
|
||||
|
||||
ecma_value_t *buffer_p = props_p->buffer_p;
|
||||
|
||||
/* 3.d.iii */
|
||||
for (uint32_t i = 0; i < props_p->item_count; i++)
|
||||
{
|
||||
ecma_string_t *property_name_p = ecma_get_string_from_value (buffer_p[i]);
|
||||
|
||||
/* 3.d.iii.1 */
|
||||
ecma_value_t result = ecma_builtin_json_internalize_property (reviver_p, object_p, property_name_p);
|
||||
|
||||
/* 3.d.iii.2 */
|
||||
if (ECMA_IS_VALUE_ERROR (result))
|
||||
{
|
||||
ecma_collection_free (props_p);
|
||||
ecma_deref_object (object_p);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* 3.d.iii.3 */
|
||||
if (ecma_is_value_undefined (result))
|
||||
{
|
||||
ecma_value_t delete_val = ecma_op_general_object_delete (object_p,
|
||||
property_name_p,
|
||||
false);
|
||||
JERRY_ASSERT (ecma_is_value_boolean (delete_val));
|
||||
}
|
||||
/* 3.d.iii.4 */
|
||||
else
|
||||
{
|
||||
ecma_builtin_json_define_value_property (object_p,
|
||||
property_name_p,
|
||||
result);
|
||||
ecma_free_value (result);
|
||||
}
|
||||
}
|
||||
|
||||
ecma_collection_free (props_p);
|
||||
}
|
||||
}
|
||||
|
||||
ecma_value_t arguments_list[2];
|
||||
@ -677,10 +744,10 @@ ecma_builtin_json_internalize_property (ecma_object_t *reviver_p, /**< reviver f
|
||||
arguments_list[1] = value;
|
||||
|
||||
/* 4. */
|
||||
ecma_value_t ret_value = ecma_op_function_call (reviver_p,
|
||||
ecma_make_object_value (holder_p),
|
||||
arguments_list,
|
||||
2);
|
||||
ecma_value_t ret_value = ecma_op_function_call (reviver_p,
|
||||
ecma_make_object_value (holder_p),
|
||||
arguments_list,
|
||||
2);
|
||||
ecma_free_value (value);
|
||||
return ret_value;
|
||||
} /* ecma_builtin_json_internalize_property */
|
||||
@ -1379,6 +1446,7 @@ ecma_builtin_json_stringify_no_opts (const ecma_value_t value) /**< value to str
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v5, 15.12.3
|
||||
* ECMA-262 v11, 24.5.2
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
@ -1406,80 +1474,99 @@ ecma_builtin_json_stringify (ecma_value_t this_arg, /**< 'this' argument */
|
||||
context.replacer_function_p = obj_p;
|
||||
}
|
||||
/* 4.b */
|
||||
else if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY)
|
||||
else
|
||||
{
|
||||
context.property_list_p = ecma_new_collection ();
|
||||
ecma_extended_object_t *array_object_p = (ecma_extended_object_t *) obj_p;
|
||||
uint32_t array_length = array_object_p->u.array.length;
|
||||
uint32_t index = 0;
|
||||
ecma_value_t is_array = ecma_is_value_array (arg2);
|
||||
|
||||
/* 4.b.iii.5 */
|
||||
while (index < array_length)
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
if (ECMA_IS_VALUE_ERROR (is_array))
|
||||
{
|
||||
ecma_value_t value = ecma_op_object_get_by_uint32_index (obj_p, index);
|
||||
return is_array;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (value))
|
||||
if (ecma_is_value_true (is_array))
|
||||
{
|
||||
uint32_t array_length;
|
||||
ecma_value_t to_len = ecma_op_object_get_length (obj_p, &array_length);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (to_len))
|
||||
{
|
||||
ecma_collection_free (context.property_list_p);
|
||||
return value;
|
||||
return to_len;
|
||||
}
|
||||
|
||||
/* 4.b.iii.5.c */
|
||||
ecma_value_t item = ECMA_VALUE_UNDEFINED;
|
||||
context.property_list_p = ecma_new_collection ();
|
||||
|
||||
/* 4.b.iii.5.d */
|
||||
if (ecma_is_value_string (value))
|
||||
{
|
||||
ecma_ref_ecma_string (ecma_get_string_from_value (value));
|
||||
item = value;
|
||||
}
|
||||
/* 4.b.iii.5.e */
|
||||
else if (ecma_is_value_number (value))
|
||||
{
|
||||
ecma_string_t *number_str_p = ecma_op_to_string (value);
|
||||
JERRY_ASSERT (number_str_p != NULL);
|
||||
item = ecma_make_string_value (number_str_p);
|
||||
}
|
||||
/* 4.b.iii.5.f */
|
||||
else if (ecma_is_value_object (value))
|
||||
{
|
||||
ecma_object_t *value_obj_p = ecma_get_object_from_value (value);
|
||||
lit_magic_string_id_t class_id = ecma_object_get_class_name (value_obj_p);
|
||||
uint32_t index = 0;
|
||||
|
||||
if (class_id == LIT_MAGIC_STRING_NUMBER_UL || class_id == LIT_MAGIC_STRING_STRING_UL)
|
||||
/* 4.b.iii.5 */
|
||||
while (index < array_length)
|
||||
{
|
||||
ecma_value_t value = ecma_op_object_get_by_uint32_index (obj_p, index);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (value))
|
||||
{
|
||||
ecma_string_t *str_p = ecma_op_to_string (value);
|
||||
ecma_collection_free (context.property_list_p);
|
||||
return value;
|
||||
}
|
||||
|
||||
if (JERRY_UNLIKELY (str_p == NULL))
|
||||
/* 4.b.iii.5.c */
|
||||
ecma_value_t item = ECMA_VALUE_UNDEFINED;
|
||||
|
||||
/* 4.b.iii.5.d */
|
||||
if (ecma_is_value_string (value))
|
||||
{
|
||||
ecma_ref_ecma_string (ecma_get_string_from_value (value));
|
||||
item = value;
|
||||
}
|
||||
/* 4.b.iii.5.e */
|
||||
else if (ecma_is_value_number (value))
|
||||
{
|
||||
ecma_string_t *number_str_p = ecma_op_to_string (value);
|
||||
JERRY_ASSERT (number_str_p != NULL);
|
||||
item = ecma_make_string_value (number_str_p);
|
||||
}
|
||||
/* 4.b.iii.5.f */
|
||||
else if (ecma_is_value_object (value))
|
||||
{
|
||||
ecma_object_t *value_obj_p = ecma_get_object_from_value (value);
|
||||
lit_magic_string_id_t class_id = ecma_object_get_class_name (value_obj_p);
|
||||
|
||||
if (class_id == LIT_MAGIC_STRING_NUMBER_UL || class_id == LIT_MAGIC_STRING_STRING_UL)
|
||||
{
|
||||
ecma_collection_free (context.property_list_p);
|
||||
ecma_free_value (value);
|
||||
return ECMA_VALUE_ERROR;
|
||||
ecma_string_t *str_p = ecma_op_to_string (value);
|
||||
|
||||
if (JERRY_UNLIKELY (str_p == NULL))
|
||||
{
|
||||
ecma_collection_free (context.property_list_p);
|
||||
ecma_free_value (value);
|
||||
return ECMA_VALUE_ERROR;
|
||||
}
|
||||
|
||||
item = ecma_make_string_value (str_p);
|
||||
}
|
||||
|
||||
item = ecma_make_string_value (str_p);
|
||||
}
|
||||
}
|
||||
|
||||
ecma_free_value (value);
|
||||
ecma_free_value (value);
|
||||
|
||||
/* 4.b.iii.5.g */
|
||||
if (!ecma_is_value_undefined (item))
|
||||
{
|
||||
JERRY_ASSERT (ecma_is_value_string (item));
|
||||
ecma_string_t *string_p = ecma_get_string_from_value (item);
|
||||
|
||||
if (!ecma_has_string_value_in_collection (context.property_list_p, string_p))
|
||||
/* 4.b.iii.5.g */
|
||||
if (!ecma_is_value_undefined (item))
|
||||
{
|
||||
ecma_collection_push_back (context.property_list_p, item);
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_deref_ecma_string (string_p);
|
||||
}
|
||||
}
|
||||
JERRY_ASSERT (ecma_is_value_string (item));
|
||||
ecma_string_t *string_p = ecma_get_string_from_value (item);
|
||||
|
||||
index++;
|
||||
if (!ecma_has_string_value_in_collection (context.property_list_p, string_p))
|
||||
{
|
||||
ecma_collection_push_back (context.property_list_p, item);
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_deref_ecma_string (string_p);
|
||||
}
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
19
tests/jerry/es.next/regression-test-issue-3945.js
Normal file
19
tests/jerry/es.next/regression-test-issue-3945.js
Normal file
@ -0,0 +1,19 @@
|
||||
// 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.
|
||||
|
||||
function a() {
|
||||
this[2] = { b : new Proxy(Function, {}) }
|
||||
}
|
||||
|
||||
JSON.parse("[1, 2, []]", a);
|
||||
20
tests/jerry/es.next/regression-test-issue-3950.js
Normal file
20
tests/jerry/es.next/regression-test-issue-3950.js
Normal file
@ -0,0 +1,20 @@
|
||||
// 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.
|
||||
|
||||
function a() {
|
||||
this[2] = new Proxy(new function() { return new Array }, {})
|
||||
return {}
|
||||
}
|
||||
|
||||
JSON.parse("[1, 2, []]", a);
|
||||
Loading…
x
Reference in New Issue
Block a user