diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-object.c b/jerry-core/ecma/builtin-objects/ecma-builtin-object.c index 23f6588a7..0da291082 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-object.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-object.c @@ -840,8 +840,13 @@ ecma_builtin_object_object_define_properties (ecma_object_t *obj_p, /**< routine ecma_object_t *props_p = ecma_get_object_from_value (props); /* 3. */ - ecma_collection_t *prop_names_p = ecma_op_object_get_property_names (props_p, ECMA_LIST_CONVERT_FAST_ARRAYS - | ECMA_LIST_ENUMERABLE); + uint32_t options = ECMA_LIST_CONVERT_FAST_ARRAYS | ECMA_LIST_ENUMERABLE; + +#if ENABLED (JERRY_ESNEXT) + options |= ECMA_LIST_SYMBOLS; +#endif /* ENABLED (JERRY_ESNEXT) */ + + ecma_collection_t *prop_names_p = ecma_op_object_get_property_names (props_p, options); ecma_value_t ret_value = ECMA_VALUE_ERROR; #if ENABLED (JERRY_BUILTIN_PROXY) @@ -861,7 +866,7 @@ ecma_builtin_object_object_define_properties (ecma_object_t *obj_p, /**< routine for (uint32_t i = 0; i < prop_names_p->item_count; i++) { /* 5.a */ - ecma_value_t desc_obj = ecma_op_object_get (props_p, ecma_get_string_from_value (buffer_p[i])); + ecma_value_t desc_obj = ecma_op_object_get (props_p, ecma_get_prop_name_from_value (buffer_p[i])); if (ECMA_IS_VALUE_ERROR (desc_obj)) { @@ -887,13 +892,11 @@ ecma_builtin_object_object_define_properties (ecma_object_t *obj_p, /**< routine } /* 6. */ - buffer_p = prop_names_p->buffer_p; - for (uint32_t i = 0; i < prop_names_p->item_count; i++) { - ecma_value_t define_own_prop_ret = ecma_op_object_define_own_property (obj_p, - ecma_get_string_from_value (buffer_p[i]), - &property_descriptors[i]); + ecma_value_t define_own_prop_ret = ecma_op_object_define_own_property (obj_p, + ecma_get_prop_name_from_value (buffer_p[i]), + &property_descriptors[i]); if (ECMA_IS_VALUE_ERROR (define_own_prop_ret)) { goto cleanup; diff --git a/tests/jerry/es.next/object-define-properties.js b/tests/jerry/es.next/object-define-properties.js new file mode 100644 index 000000000..9c3caad00 --- /dev/null +++ b/tests/jerry/es.next/object-define-properties.js @@ -0,0 +1,150 @@ +// 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 object = {}; +var symbol = Symbol("symbol"); + +Object.defineProperties(object, { + "foo": { + value: true, + writable: true + }, + [symbol]: { + value: "a symbol", + configurable: true + } +}); + +assert (object.foo === true); +assert (object[symbol] === "a symbol"); + +try { + Object.defineProperties(undefined, { + [symbol]: { + value: "a symbol", + writable: true + } + }); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} + +// If one of the properties is wrong than it shouldn't update the object. +var obj2 = { + a: 5 +}; +try { + Object.defineProperties(obj2, { + "foo": { + value: true, + writable: true + }, + [symbol]: { + value: "a symbol", + set: 3 + } + }); + assert (false); +} catch (e) { + assert (e instanceof TypeError); + assert (obj2.foo === undefined); + assert (obj2[symbol] === undefined); + assert (obj2.a === 5); +} + +// Define accessors +var object = {}; +Object.defineProperties(object, { + "foo": { + value: 42, + writable: true, + }, + [symbol]: { + get: function() { return this.foo }, + set: function(v) { this.foo = v } + } +}); + +assert (object[symbol] === 42); +object[symbol] = "baz"; +assert (object[symbol] === "baz"); + +// Define get method which throws error +var object = {}; +var props = { + [symbol]: { + value: 3, + writable: true + }, + get bar() { + throw new TypeError("foo"); + return { value : 2, writable : true }; + }, +}; + +try { + Object.defineProperties(object, props); + assert (false); +} catch (e) { + assert (e instanceof TypeError); + assert (e.message === "foo"); +} +// Define get method which deletes a property +var object = {}; +Object.defineProperties(object, { + "foo": { + value: 42, + writable: true, + }, + [symbol]: { + value: "a symbol", + configurable: true + }, + "bar": { + get: function() { + delete this[symbol]; + return this.foo; + }, + } +}); + +assert (object[symbol] === "a symbol"); +assert (object.bar === 42); +assert (object[symbol] === undefined); + +// This code should throw TypeError +var object = {}; +var props = { + [symbol]: { + value: "a symbol", + configurable: true + }, + get bar() { + delete props[symbol]; + delete props.prop1; + return { value : 2, writable : true }; + }, + prop1: { + value: 3, + writable: true, + }, +}; + +try { + Object.defineProperties(object, props); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +}