diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-object.c b/jerry-core/ecma/builtin-objects/ecma-builtin-object.c index 77d7a5b53..e5297fc24 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-object.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-object.c @@ -40,23 +40,32 @@ enum { ECMA_OBJECT_ROUTINE_START = ECMA_BUILTIN_ID__COUNT - 1, - ECMA_OBJECT_ROUTINE_DEFINE_PROPERTY, - ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_DESCRIPTOR, - ECMA_OBJECT_ROUTINE_DEFINE_PROPERTIES, + ECMA_OBJECT_ROUTINE_CREATE, - ECMA_OBJECT_ROUTINE_SEAL, - ECMA_OBJECT_ROUTINE_FREEZE, - ECMA_OBJECT_ROUTINE_PREVENT_EXTENSIONS, - ECMA_OBJECT_ROUTINE_IS_SEALED, - ECMA_OBJECT_ROUTINE_IS_FROZEN, - ECMA_OBJECT_ROUTINE_IS_EXTENSIBLE, + ECMA_OBJECT_ROUTINE_IS, + ECMA_OBJECT_ROUTINE_SET_PROTOTYPE_OF, + + /* These should be in this order. */ + ECMA_OBJECT_ROUTINE_DEFINE_PROPERTY, + ECMA_OBJECT_ROUTINE_DEFINE_PROPERTIES, + + /* These should be in this order. */ + ECMA_OBJECT_ROUTINE_ASSIGN, + ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_DESCRIPTOR, ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_NAMES, ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_SYMBOLS, - ECMA_OBJECT_ROUTINE_KEYS, ECMA_OBJECT_ROUTINE_GET_PROTOTYPE_OF, - ECMA_OBJECT_ROUTINE_SET_PROTOTYPE_OF, - ECMA_OBJECT_ROUTINE_ASSIGN, - ECMA_OBJECT_ROUTINE_IS, + ECMA_OBJECT_ROUTINE_KEYS, + + /* These should be in this order. */ + ECMA_OBJECT_ROUTINE_FREEZE, + ECMA_OBJECT_ROUTINE_PREVENT_EXTENSIONS, + ECMA_OBJECT_ROUTINE_SEAL, + + /* These should be in this order. */ + ECMA_OBJECT_ROUTINE_IS_EXTENSIBLE, + ECMA_OBJECT_ROUTINE_IS_FROZEN, + ECMA_OBJECT_ROUTINE_IS_SEALED, }; #define BUILTIN_INC_HEADER_NAME "ecma-builtin-object.inc.h" @@ -125,47 +134,18 @@ ecma_builtin_object_dispatch_construct (const ecma_value_t *arguments_list_p, /* * Returned value must be freed with ecma_free_value. */ ecma_value_t -ecma_builtin_object_object_get_prototype_of (ecma_value_t arg) /**< routine's argument */ +ecma_builtin_object_object_get_prototype_of (ecma_object_t *obj_p) /**< routine's argument */ { - ecma_value_t ret_value = ECMA_VALUE_EMPTY; - bool was_object = ecma_is_value_object (arg); - - /* 1. */ - if (!was_object) - { -#if ENABLED (JERRY_ES2015_BUILTIN) - arg = ecma_op_to_object (arg); - if (ECMA_IS_VALUE_ERROR (arg)) - { - return arg; - } -#else /* !ENABLED (JERRY_ES2015_BUILTIN) */ - return ecma_raise_type_error (ECMA_ERR_MSG ("Argument is not an object.")); -#endif /* ENABLED (JERRY_ES2015_BUILTIN) */ - } - /* 2. */ - ecma_object_t *obj_p = ecma_get_object_from_value (arg); jmem_cpointer_t prototype_cp = obj_p->u2.prototype_cp; if (prototype_cp != JMEM_CP_NULL) { ecma_object_t *prototype_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, prototype_cp); - ret_value = ecma_make_object_value (prototype_p); ecma_ref_object (prototype_p); - } - else - { - ret_value = ECMA_VALUE_NULL; + return ecma_make_object_value (prototype_p); } -#if ENABLED (JERRY_ES2015_BUILTIN) - if (!was_object) - { - ecma_deref_object (obj_p); - } -#endif /* ENABLED (JERRY_ES2015_BUILTIN) */ - - return ret_value; + return ECMA_VALUE_NULL; } /* ecma_builtin_object_object_get_prototype_of */ #if ENABLED (JERRY_ES2015_BUILTIN) @@ -772,31 +752,14 @@ ecma_builtin_object_object_define_property (ecma_object_t *obj_p, /**< routine's * Returned value must be freed with ecma_free_value. */ static ecma_value_t -ecma_builtin_object_object_assign (const ecma_value_t arguments_list_p[], /**< arguments list */ +ecma_builtin_object_object_assign (ecma_object_t *target_p, /**< target object */ + const ecma_value_t arguments_list_p[], /**< arguments list */ ecma_length_t arguments_list_len) /**< number of arguments */ { - ecma_value_t target = arguments_list_len > 0 ? arguments_list_p[0] : ECMA_VALUE_UNDEFINED; - - /* 1. */ - ecma_value_t to_value = ecma_op_to_object (target); - - if (ECMA_IS_VALUE_ERROR (to_value)) - { - return to_value; - } - - ecma_object_t *to_obj_p = ecma_get_object_from_value (to_value); - - /* 2. */ - if (arguments_list_len == 1) - { - return to_value; - } - ecma_value_t ret_value = ECMA_VALUE_EMPTY; /* 4-5. */ - for (uint32_t i = 1; i < arguments_list_len && ecma_is_value_empty (ret_value); i++) + for (uint32_t i = 0; i < arguments_list_len && ecma_is_value_empty (ret_value); i++) { ecma_value_t next_source = arguments_list_p[i]; @@ -848,7 +811,7 @@ ecma_builtin_object_object_assign (const ecma_value_t arguments_list_p[], /**< a else { /* 5.c.iii.3 */ - ecma_value_t status = ecma_op_object_put (to_obj_p, property_name_p, prop_value, true); + ecma_value_t status = ecma_op_object_put (target_p, property_name_p, prop_value, true); /* 5.c.iii.4 */ if (ECMA_IS_VALUE_ERROR (status)) @@ -869,10 +832,10 @@ ecma_builtin_object_object_assign (const ecma_value_t arguments_list_p[], /**< a /* 6. */ if (ecma_is_value_empty (ret_value)) { - return to_value; + ecma_ref_object (target_p); + return ecma_make_object_value (target_p); } - ecma_deref_object (to_obj_p); return ret_value; } /* ecma_builtin_object_object_assign */ #endif /* ENABLED (JERRY_ES2015_BUILTIN) */ @@ -924,19 +887,11 @@ ecma_builtin_object_dispatch_routine (uint16_t builtin_routine_id, /**< built-in { return ecma_builtin_object_object_create (arg1, arg2); } - case ECMA_OBJECT_ROUTINE_GET_PROTOTYPE_OF: - { - return ecma_builtin_object_object_get_prototype_of (arg1); - } #if ENABLED (JERRY_ES2015_BUILTIN) case ECMA_OBJECT_ROUTINE_SET_PROTOTYPE_OF: { return ecma_builtin_object_object_set_prototype_of (arg1, arg2); } - case ECMA_OBJECT_ROUTINE_ASSIGN: - { - return ecma_builtin_object_object_assign (arguments_list_p, arguments_number); - } case ECMA_OBJECT_ROUTINE_IS: { return ecma_builtin_object_object_is (arg1, arg2); @@ -948,83 +903,169 @@ ecma_builtin_object_dispatch_routine (uint16_t builtin_routine_id, /**< built-in } } + ecma_object_t *obj_p; +#if !ENABLED (JERRY_ES2015) if (!ecma_is_value_object (arg1)) { return ecma_raise_type_error (ECMA_ERR_MSG ("Argument is not an object.")); } +#endif /* !ENABLED (JERRY_ES2015) */ - ecma_object_t *obj_p = ecma_get_object_from_value (arg1); - - if (builtin_routine_id <= ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_DESCRIPTOR) + if (builtin_routine_id <= ECMA_OBJECT_ROUTINE_DEFINE_PROPERTIES) { - ecma_string_t *prop_name_p = ecma_op_to_prop_name (arg2); - - if (prop_name_p == NULL) +#if ENABLED (JERRY_ES2015) + if (!ecma_is_value_object (arg1)) { - return ECMA_VALUE_ERROR; + return ecma_raise_type_error (ECMA_ERR_MSG ("Argument is not an object.")); } +#endif /* ENABLED (JERRY_ES2015) */ - ecma_value_t ret_value; + obj_p = ecma_get_object_from_value (arg1); if (builtin_routine_id == ECMA_OBJECT_ROUTINE_DEFINE_PROPERTY) { - ret_value = ecma_builtin_object_object_define_property (obj_p, prop_name_p, arguments_list_p[2]); - } - else - { - JERRY_ASSERT (builtin_routine_id == ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_DESCRIPTOR); - ret_value = ecma_builtin_object_object_get_own_property_descriptor (obj_p, prop_name_p); + ecma_string_t *prop_name_p = ecma_op_to_prop_name (arg2); + + if (prop_name_p == NULL) + { + return ECMA_VALUE_ERROR; + } + + ecma_value_t result = ecma_builtin_object_object_define_property (obj_p, prop_name_p, arguments_list_p[2]); + + ecma_deref_ecma_string (prop_name_p); + return result; } - ecma_deref_ecma_string (prop_name_p); - return ret_value; + JERRY_ASSERT (builtin_routine_id == ECMA_OBJECT_ROUTINE_DEFINE_PROPERTIES); + return ecma_builtin_object_object_define_properties (obj_p, arg2); } - - switch (builtin_routine_id) + else if (builtin_routine_id <= ECMA_OBJECT_ROUTINE_KEYS) { - case ECMA_OBJECT_ROUTINE_SEAL: - { - return ecma_builtin_object_object_seal (obj_p); - } - case ECMA_OBJECT_ROUTINE_FREEZE: - { - return ecma_builtin_object_object_freeze (obj_p); - } - case ECMA_OBJECT_ROUTINE_PREVENT_EXTENSIONS: - { - return ecma_builtin_object_object_prevent_extensions (obj_p); - } - case ECMA_OBJECT_ROUTINE_IS_SEALED: - case ECMA_OBJECT_ROUTINE_IS_FROZEN: - { - return ecma_builtin_object_frozen_or_sealed_helper (obj_p, - builtin_routine_id); - } - case ECMA_OBJECT_ROUTINE_IS_EXTENSIBLE: - { - return ecma_builtin_object_object_is_extensible (obj_p); - } - case ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_NAMES: - { - return ecma_builtin_object_object_get_own_property_names (obj_p); - } #if ENABLED (JERRY_ES2015) - case ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_SYMBOLS: + ecma_value_t object = ecma_op_to_object (arg1); + if (ECMA_IS_VALUE_ERROR (object)) { - return ecma_builtin_object_object_get_own_property_symbols (obj_p); + return object; + } + + obj_p = ecma_get_object_from_value (object); +#else /* !ENABLED (JERRY_ES2015) */ + obj_p = ecma_get_object_from_value (arg1); +#endif /* ENABLED (JERRY_ES2015) */ + + ecma_value_t result; + switch (builtin_routine_id) + { + case ECMA_OBJECT_ROUTINE_GET_PROTOTYPE_OF: + { + result = ecma_builtin_object_object_get_prototype_of (obj_p); + break; + } + case ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_NAMES: + { + result = ecma_builtin_object_object_get_own_property_names (obj_p); + break; + } +#if ENABLED (JERRY_ES2015) + case ECMA_OBJECT_ROUTINE_ASSIGN: + { + result = ecma_builtin_object_object_assign (obj_p, arguments_list_p + 1, arguments_number - 1); + break; + } + case ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_SYMBOLS: + { + result = ecma_builtin_object_object_get_own_property_symbols (obj_p); + break; + } +#endif /* ENABLED (JERRY_ES2015) */ + case ECMA_OBJECT_ROUTINE_KEYS: + { + result = ecma_builtin_object_object_keys (obj_p); + break; + } + case ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_DESCRIPTOR: + { + ecma_string_t *prop_name_p = ecma_op_to_prop_name (arg2); + + if (prop_name_p == NULL) + { + result = ECMA_VALUE_ERROR; + break; + } + + result = ecma_builtin_object_object_get_own_property_descriptor (obj_p, prop_name_p); + ecma_deref_ecma_string (prop_name_p); + break; + } + default: + { + JERRY_UNREACHABLE (); + } + } + +#if ENABLED (JERRY_ES2015) + ecma_deref_object (obj_p); +#endif /* ENABLED (JERRY_ES2015) */ + return result; + } + else if (builtin_routine_id <= ECMA_OBJECT_ROUTINE_SEAL) + { +#if ENABLED (JERRY_ES2015) + if (!ecma_is_value_object (arg1)) + { + return arg1; } #endif /* ENABLED (JERRY_ES2015) */ - case ECMA_OBJECT_ROUTINE_KEYS: + + obj_p = ecma_get_object_from_value (arg1); + switch (builtin_routine_id) { - return ecma_builtin_object_object_keys (obj_p); + case ECMA_OBJECT_ROUTINE_SEAL: + { + return ecma_builtin_object_object_seal (obj_p); + } + case ECMA_OBJECT_ROUTINE_FREEZE: + { + return ecma_builtin_object_object_freeze (obj_p); + } + case ECMA_OBJECT_ROUTINE_PREVENT_EXTENSIONS: + { + return ecma_builtin_object_object_prevent_extensions (obj_p); + } + default: + { + JERRY_UNREACHABLE (); + } } - case ECMA_OBJECT_ROUTINE_DEFINE_PROPERTIES: + } + else + { + JERRY_ASSERT (builtin_routine_id <= ECMA_OBJECT_ROUTINE_IS_SEALED); +#if ENABLED (JERRY_ES2015) + if (!ecma_is_value_object (arg1)) { - return ecma_builtin_object_object_define_properties (obj_p, arg2); + return ecma_make_boolean_value (builtin_routine_id != ECMA_OBJECT_ROUTINE_IS_EXTENSIBLE); } - default: +#endif /* ENABLED (JERRY_ES2015) */ + + obj_p = ecma_get_object_from_value (arg1); + switch (builtin_routine_id) { - JERRY_UNREACHABLE (); + case ECMA_OBJECT_ROUTINE_IS_SEALED: + case ECMA_OBJECT_ROUTINE_IS_FROZEN: + { + return ecma_builtin_object_frozen_or_sealed_helper (obj_p, + builtin_routine_id); + } + case ECMA_OBJECT_ROUTINE_IS_EXTENSIBLE: + { + return ecma_builtin_object_object_is_extensible (obj_p); + } + default: + { + JERRY_UNREACHABLE (); + } } } } /* ecma_builtin_object_dispatch_routine */ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-object.h b/jerry-core/ecma/builtin-objects/ecma-builtin-object.h index 0ffe8336d..e11e9506a 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-object.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-object.h @@ -15,7 +15,7 @@ #ifndef ECMA_BUILTIN_OBJECT_H #define ECMA_BUILTIN_OBJECT_H -ecma_value_t ecma_builtin_object_object_get_prototype_of (ecma_value_t arg); +ecma_value_t ecma_builtin_object_object_get_prototype_of (ecma_object_t *obj_p); ecma_value_t ecma_builtin_object_object_set_prototype_of (ecma_value_t arg1, ecma_value_t arg2); diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-reflect.c b/jerry-core/ecma/builtin-objects/ecma-builtin-reflect.c index 0559a3493..f78f59f38 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-reflect.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-reflect.c @@ -87,7 +87,7 @@ ecma_builtin_reflect_dispatch_routine (uint16_t builtin_routine_id, /**< built-i { case ECMA_REFLECT_OBJECT_GET_PROTOTYPE_OF_UL: { - return ecma_builtin_object_object_get_prototype_of (arguments_list[0]); + return ecma_builtin_object_object_get_prototype_of (ecma_get_object_from_value (arguments_list[0])); } case ECMA_REFLECT_OBJECT_SET_PROTOTYPE_OF_UL: { diff --git a/tests/jerry/es2015/object-get-own-property-symbols.js b/tests/jerry/es2015/object-get-own-property-symbols.js index 83848f930..540c2271e 100644 --- a/tests/jerry/es2015/object-get-own-property-symbols.js +++ b/tests/jerry/es2015/object-get-own-property-symbols.js @@ -109,11 +109,3 @@ assert (props.indexOf(foo2) !== -1); assert (props.length === 2); assert (Object.getOwnPropertyDescriptor (object, foo).enumerable === true); assert (Object.getOwnPropertyDescriptor (object, foo2).enumerable === false); - -// Test non-object argument -try { - Object.getOwnPropertySymbols ('hello'); - assert (false); -} catch (e) { - assert (e instanceof TypeError); -} diff --git a/tests/jerry/es2015/object-methods.js b/tests/jerry/es2015/object-methods.js new file mode 100644 index 000000000..3b5cea5da --- /dev/null +++ b/tests/jerry/es2015/object-methods.js @@ -0,0 +1,48 @@ +// 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. + +assert (JSON.stringify (Object.getOwnPropertyNames("hello")) === '["0","1","2","3","4","length"]'); + +var n = Object.assign(42, {a: "str"}); +assert (n instanceof Number); +assert (n.valueOf() === 42); +assert (n.a === "str"); + +assert (JSON.stringify (Object.getOwnPropertySymbols("hello")) === '[]'); + +assert (JSON.stringify (Object.keys("str")) === '["0","1","2"]'); + +var d = Object.getOwnPropertyDescriptor("hello", '1'); +assert (d.value === "e"); +assert (d.writable === false); +assert (d.enumerable === true); +assert (d.configurable === false); + +assert (Object.seal(42) === 42); +assert (Object.seal(undefined) === undefined); + +assert (Object.isSealed(42) === true); +assert (Object.isSealed(undefined) === true); + +assert (Object.freeze(42) === 42); +assert (Object.freeze(undefined) === undefined); + +assert (Object.isFrozen(42) === true); +assert (Object.isFrozen(undefined) === true); + +assert (Object.preventExtensions(42) === 42); +assert (Object.preventExtensions(undefined) === undefined); + +assert (Object.isExtensible(42) === false); +assert (Object.isExtensible(undefined) === false); diff --git a/tests/jerry/es5.1/object-methods.js b/tests/jerry/es5.1/object-methods.js new file mode 100644 index 000000000..6331d401f --- /dev/null +++ b/tests/jerry/es5.1/object-methods.js @@ -0,0 +1,89 @@ +// 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. + +try { + Object.getOwnPropertyNames("hello"); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} + +try +{ + Object.preventExtensions(42); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} + +try +{ + Object.isExtensible(42); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} + +try +{ + Object.seal(42); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} + +try +{ + Object.isSealed(42); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} + +try +{ + Object.freeze(42); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} + +try +{ + Object.isFrozen(42); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} + +try { + Object.keys("hello"); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} + +try { + Object.getOwnPropertyNames("hello"); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} + +try { + Object.getOwnPropertyDescriptor("hello", '1'); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} diff --git a/tests/jerry/object-defineproperty.js b/tests/jerry/object-defineproperty.js index 6988f1ab1..ed37dde89 100644 --- a/tests/jerry/object-defineproperty.js +++ b/tests/jerry/object-defineproperty.js @@ -68,3 +68,12 @@ try { } catch (err) { assert (err === 234); } + +try { + Object.defineProperty(42, "prop", { + set: undefined + }); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} diff --git a/tests/jerry/object-get-own-property-names.js b/tests/jerry/object-get-own-property-names.js index f6dfb9fb4..0cb4ac2c8 100644 --- a/tests/jerry/object-get-own-property-names.js +++ b/tests/jerry/object-get-own-property-names.js @@ -62,11 +62,3 @@ assert (props.indexOf("prop") !== -1); assert (props.indexOf("method") !== -1); assert (props.length === 2); - -// Test non-object argument -try { - Object.getOwnPropertyNames("hello"); - assert (false); -} catch (e) { - assert (e instanceof TypeError); -} diff --git a/tests/jerry/object-is-extensible.js b/tests/jerry/object-is-extensible.js index f3e96b5ee..5ecfd602c 100644 --- a/tests/jerry/object-is-extensible.js +++ b/tests/jerry/object-is-extensible.js @@ -20,23 +20,6 @@ assert (Object.isExtensible(empty) === true); Object.preventExtensions(empty); assert(Object.isExtensible(empty) === false); -// Call on undefined should throw TypeError. -try -{ - Object.isExtensible(undefined); - assert (false); -} catch (e) { - assert (e instanceof TypeError); -} - -try -{ - Object.preventExtensions(undefined); - assert (false); -} catch (e) { - assert (e instanceof TypeError); -} - // Sealed objects are by definition non-extensible. var sealed = Object.seal({}); assert (Object.isExtensible(sealed) === false); diff --git a/tests/jerry/object-keys.js b/tests/jerry/object-keys.js index 4ebae6879..e359233f9 100644 --- a/tests/jerry/object-keys.js +++ b/tests/jerry/object-keys.js @@ -61,14 +61,6 @@ assert (props.indexOf("prop") !== -1); assert (props.indexOf("method") !== -1); assert (props.length === 2); -// Test non-object argument -try { - Object.keys("hello"); - assert (false); -} catch (e) { - assert (e instanceof TypeError); -} - var o = {}; Object.defineProperty(o, 'a', {