diff --git a/jerry-core/ecma/base/ecma-helpers.cpp b/jerry-core/ecma/base/ecma-helpers.cpp index dc94ae486b..ea009f8d91 100644 --- a/jerry-core/ecma/base/ecma-helpers.cpp +++ b/jerry-core/ecma/base/ecma-helpers.cpp @@ -1239,6 +1239,35 @@ ecma_free_property_descriptor (ecma_property_descriptor_t *prop_desc_p) /**< pro *prop_desc_p = ecma_make_empty_property_descriptor (); } /* ecma_free_property_descriptor */ +/** + * Return property descriptor of property. + */ +ecma_property_descriptor_t +ecma_get_property_descriptor_from_property (ecma_property_t *prop_p) /**< property */ +{ + ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); + + prop_desc.is_enumerable = ecma_is_property_enumerable (prop_p); + prop_desc.is_configurable = ecma_is_property_configurable (prop_p); + + if (prop_p->type == ECMA_PROPERTY_NAMEDDATA) + { + prop_desc.value = ecma_get_named_data_property_value (prop_p); + prop_desc.is_value_defined = true; + prop_desc.is_writable = ecma_is_property_writable (prop_p); + prop_desc.is_writable_defined = true; + } + else if (prop_p->type == ECMA_PROPERTY_NAMEDACCESSOR) + { + prop_desc.get_p = ecma_get_named_accessor_property_getter (prop_p); + prop_desc.is_get_defined = prop_desc.get_p != NULL ? true : false; + prop_desc.set_p = ecma_get_named_accessor_property_setter (prop_p); + prop_desc.is_set_defined = prop_desc.set_p != NULL ? true : false; + } + + return prop_desc; +} /* ecma_get_property_descriptor_from_property */ + /** * @} * @} diff --git a/jerry-core/ecma/base/ecma-helpers.h b/jerry-core/ecma/base/ecma-helpers.h index 5ef1a6dac1..b03f98c78d 100644 --- a/jerry-core/ecma/base/ecma-helpers.h +++ b/jerry-core/ecma/base/ecma-helpers.h @@ -290,6 +290,7 @@ extern void ecma_set_property_lcached (ecma_property_t *prop_p, extern ecma_property_descriptor_t ecma_make_empty_property_descriptor (void); extern void ecma_free_property_descriptor (ecma_property_descriptor_t *prop_desc_p); +extern ecma_property_descriptor_t ecma_get_property_descriptor_from_property (ecma_property_t *prop_p); /* ecma-helpers-external-pointers.c */ extern bool diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-object.cpp b/jerry-core/ecma/builtin-objects/ecma-builtin-object.cpp index fe13ced982..dd53e37586 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-object.cpp +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-object.cpp @@ -256,11 +256,48 @@ ecma_builtin_object_object_keys (ecma_value_t this_arg, /**< 'this' argument */ * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t -ecma_builtin_object_object_get_own_property_descriptor (ecma_value_t this_arg, /**< 'this' argument */ +ecma_builtin_object_object_get_own_property_descriptor (ecma_value_t this_arg __attr_unused___, /**< 'this' argument */ ecma_value_t arg1, /**< routine's first argument */ ecma_value_t arg2) /**< routine's second argument */ { - ECMA_BUILTIN_CP_UNIMPLEMENTED (this_arg, arg1, arg2); + ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); + + // 1. + if (!ecma_is_value_object (arg1)) + { + ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); + return ret_value; + } + + ecma_object_t *obj_p = ecma_get_object_from_value (arg1); + + // 2. + ECMA_TRY_CATCH (name_str_value, + ecma_op_to_string (arg2), + ret_value); + + ecma_string_t *name_str_p = ecma_get_string_from_value (name_str_value); + + // 3. + ecma_property_t *prop_p = ecma_op_general_object_get_own_property (obj_p, name_str_p); + + if (prop_p != NULL) + { + ecma_property_descriptor_t prop_desc = ecma_get_property_descriptor_from_property (prop_p); + + // 4. + ecma_object_t* desc_obj_p = ecma_op_from_property_descriptor (&prop_desc); + + ret_value = ecma_make_normal_completion_value (ecma_make_object_value (desc_obj_p)); + } + else + { + ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_UNDEFINED); + } + + ECMA_FINALIZE (name_str_value); + + return ret_value; } /* ecma_builtin_object_object_get_own_property_descriptor */ /** diff --git a/tests/jerry/object_get_own_property_descriptor.js b/tests/jerry/object_get_own_property_descriptor.js new file mode 100644 index 0000000000..f75ea0cf67 --- /dev/null +++ b/tests/jerry/object_get_own_property_descriptor.js @@ -0,0 +1,72 @@ +// Copyright 2015 Samsung Electronics Co., Ltd. +// Copyright 2015 University of Szeged. +// +// 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 obj; +var desc; + +obj = { bar: 42 }; +desc = Object.getOwnPropertyDescriptor (obj, 'bar'); +// desc is { configurable: true, enumerable: true, value: 42, writable: true } +assert (desc.value === 42); +assert (desc.configurable); +assert (desc.writable); +assert (desc.enumerable); + +obj = { "foo": "bar" }; +desc = Object.getOwnPropertyDescriptor (obj, 'foo'); +assert (desc.value === "bar"); + +obj = {}; +Object.defineProperty (obj, 'baz', { value: 8675309, writable: false, enumerable: false }); +desc = Object.getOwnPropertyDescriptor (obj, 'baz'); +// desc is { value: 8675309, writable: false, enumerable: false, configurable: false } +assert (desc.value === 8675309); +assert (!desc.configurable); +assert (!desc.writable); +assert (!desc.enumerable); + +obj = { "0.00001": 1 }; +desc = Object.getOwnPropertyDescriptor (obj, 1e-5); +assert ( desc.value === 1); + +obj = { "123": 1 }; +desc = Object.getOwnPropertyDescriptor (obj, 123); +assert (desc.value === 1); + +obj = { "undefined": 1 }; +var desc1 = Object.getOwnPropertyDescriptor (obj, undefined); +var desc2 = Object.getOwnPropertyDescriptor (obj, "undefined"); +assert (desc1.value === 1 && desc2.value === 1); + +obj = { "0": 1 }; +desc = Object.getOwnPropertyDescriptor (obj, -0); +assert (desc.value === 1); + +obj = { "Hellobj": 42 }; +desc = Object.getOwnPropertyDescriptor (obj, new String ("Hellobj")); +assert (desc.value === 42); + +obj = {}; +desc = Object.getOwnPropertyDescriptor (obj, 'baz'); +assert (desc === undefined); + +obj = { get foo() { return obj.bar; }, set foo(a) { obj.bar = a; }, bar: 0 }; +desc = Object.getOwnPropertyDescriptor(obj, 'foo'); +// d is { configurable: true, enumerable: true, get: /*the getter function*/, set: /*the setter function*/ } +assert (typeof(desc.get) === 'function'); +assert (typeof(desc.set) === 'function'); +assert (desc.configurable); +assert (desc.enumerable); +assert (obj.foo === 0)