Fix property redefinition (#3970)
The previously allocated property should not be deleted only it's type should be change. JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
This commit is contained in:
@@ -427,6 +427,12 @@ typedef enum
|
||||
*/
|
||||
#define ECMA_PROPERTY_NAME_TYPE_SHIFT (ECMA_PROPERTY_FLAG_SHIFT + 4)
|
||||
|
||||
/**
|
||||
* Convert data property to accessor property or accessor property to data property
|
||||
*/
|
||||
#define ECMA_CHANGE_PROPERTY_TYPE(property_p) \
|
||||
*(property_p) ^= ECMA_PROPERTY_TYPE_NAMEDACCESSOR ^ ECMA_PROPERTY_TYPE_NAMEDDATA;
|
||||
|
||||
/**
|
||||
* Convert data property to internal property.
|
||||
*/
|
||||
|
||||
+56
-36
@@ -131,14 +131,6 @@ opfunc_set_data_property (ecma_object_t *object_p, /**< object */
|
||||
JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p));
|
||||
|
||||
ecma_property_t *property_p = ecma_find_named_property (object_p, prop_name_p);
|
||||
|
||||
if (property_p != NULL
|
||||
&& ECMA_PROPERTY_GET_TYPE (*property_p) != ECMA_PROPERTY_TYPE_NAMEDDATA)
|
||||
{
|
||||
ecma_delete_property (object_p, ECMA_PROPERTY_VALUE_PTR (property_p));
|
||||
property_p = NULL;
|
||||
}
|
||||
|
||||
ecma_property_value_t *prop_value_p;
|
||||
|
||||
if (property_p == NULL)
|
||||
@@ -151,6 +143,21 @@ opfunc_set_data_property (ecma_object_t *object_p, /**< object */
|
||||
else
|
||||
{
|
||||
prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
|
||||
|
||||
if (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR)
|
||||
{
|
||||
#if ENABLED (JERRY_CPOINTER_32_BIT)
|
||||
ecma_getter_setter_pointers_t *getter_setter_pair_p;
|
||||
getter_setter_pair_p = ECMA_GET_NON_NULL_POINTER (ecma_getter_setter_pointers_t,
|
||||
ECMA_PROPERTY_VALUE_PTR (property_p)->getter_setter_pair_cp);
|
||||
jmem_pools_free (getter_setter_pair_p, sizeof (ecma_getter_setter_pointers_t));
|
||||
#endif /* ENABLED (JERRY_CPOINTER_32_BIT) */
|
||||
|
||||
ECMA_CHANGE_PROPERTY_TYPE (property_p);
|
||||
*property_p = (uint8_t) (*property_p | ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE);
|
||||
prop_value_p->value = ecma_copy_value_if_not_object (value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ecma_named_data_property_assign_value (object_p, prop_value_p, value);
|
||||
@@ -170,28 +177,22 @@ opfunc_set_accessor (bool is_getter, /**< is getter accessor */
|
||||
JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p));
|
||||
|
||||
ecma_property_t *property_p = ecma_find_named_property (object_p, accessor_name_p);
|
||||
ecma_object_t *accessor_p = ecma_get_object_from_value (accessor);
|
||||
|
||||
if (property_p != NULL
|
||||
&& ECMA_PROPERTY_GET_TYPE (*property_p) != ECMA_PROPERTY_TYPE_NAMEDACCESSOR)
|
||||
ecma_object_t *getter_func_p = NULL;
|
||||
ecma_object_t *setter_func_p = NULL;
|
||||
|
||||
if (is_getter)
|
||||
{
|
||||
ecma_delete_property (object_p, ECMA_PROPERTY_VALUE_PTR (property_p));
|
||||
property_p = NULL;
|
||||
getter_func_p = accessor_p;
|
||||
}
|
||||
else
|
||||
{
|
||||
setter_func_p = accessor_p;
|
||||
}
|
||||
|
||||
if (property_p == NULL)
|
||||
{
|
||||
ecma_object_t *getter_func_p = NULL;
|
||||
ecma_object_t *setter_func_p = NULL;
|
||||
|
||||
if (is_getter)
|
||||
{
|
||||
getter_func_p = ecma_get_object_from_value (accessor);
|
||||
}
|
||||
else
|
||||
{
|
||||
setter_func_p = ecma_get_object_from_value (accessor);
|
||||
}
|
||||
|
||||
ecma_create_named_accessor_property (object_p,
|
||||
accessor_name_p,
|
||||
getter_func_p,
|
||||
@@ -199,21 +200,40 @@ opfunc_set_accessor (bool is_getter, /**< is getter accessor */
|
||||
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE,
|
||||
NULL);
|
||||
}
|
||||
else if (is_getter)
|
||||
{
|
||||
ecma_object_t *getter_func_p = ecma_get_object_from_value (accessor);
|
||||
|
||||
ecma_set_named_accessor_property_getter (object_p,
|
||||
ECMA_PROPERTY_VALUE_PTR (property_p),
|
||||
getter_func_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_object_t *setter_func_p = ecma_get_object_from_value (accessor);
|
||||
ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
|
||||
|
||||
ecma_set_named_accessor_property_setter (object_p,
|
||||
ECMA_PROPERTY_VALUE_PTR (property_p),
|
||||
setter_func_p);
|
||||
if (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA)
|
||||
{
|
||||
#if ENABLED (JERRY_CPOINTER_32_BIT)
|
||||
ecma_getter_setter_pointers_t *getter_setter_pair_p;
|
||||
getter_setter_pair_p = jmem_pools_alloc (sizeof (ecma_getter_setter_pointers_t));
|
||||
#endif /* ENABLED (JERRY_CPOINTER_32_BIT) */
|
||||
|
||||
ecma_free_value_if_not_object (prop_value_p->value);
|
||||
ECMA_CHANGE_PROPERTY_TYPE (property_p);
|
||||
*property_p = (uint8_t) (*property_p & ~ECMA_PROPERTY_FLAG_WRITABLE);
|
||||
|
||||
#if ENABLED (JERRY_CPOINTER_32_BIT)
|
||||
ECMA_SET_POINTER (getter_setter_pair_p->getter_cp, getter_func_p);
|
||||
ECMA_SET_POINTER (getter_setter_pair_p->setter_cp, setter_func_p);
|
||||
ECMA_SET_NON_NULL_POINTER (prop_value_p->getter_setter_pair_cp, getter_setter_pair_p);
|
||||
#else /* !ENABLED (JERRY_CPOINTER_32_BIT) */
|
||||
ECMA_SET_POINTER (prop_value_p->getter_setter_pair.getter_cp, getter_func_p);
|
||||
ECMA_SET_POINTER (prop_value_p->getter_setter_pair.setter_cp, setter_func_p);
|
||||
#endif /* ENABLED (JERRY_CPOINTER_32_BIT) */
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_getter)
|
||||
{
|
||||
ecma_set_named_accessor_property_getter (object_p, prop_value_p, accessor_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_set_named_accessor_property_setter (object_p, prop_value_p, accessor_p);
|
||||
}
|
||||
}
|
||||
} /* opfunc_set_accessor */
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
// 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 checkOwnProperties(obj, propList)
|
||||
{
|
||||
names = Object.getOwnPropertyNames(obj)
|
||||
assert(names.length === propList.length)
|
||||
|
||||
for (var i = 0; i < propList.length; ++i)
|
||||
{
|
||||
assert(names[i] === propList[i])
|
||||
|
||||
var descriptor = Object.getOwnPropertyDescriptor(obj, names[i])
|
||||
if (i % 2 == 0) {
|
||||
assert(descriptor.writable == true);
|
||||
assert(descriptor.enumerable == true);
|
||||
assert(descriptor.configurable == true);
|
||||
assert(descriptor.get === undefined);
|
||||
assert(descriptor.set === undefined);
|
||||
} else {
|
||||
assert(descriptor.writable == undefined);
|
||||
assert(descriptor.enumerable == true);
|
||||
assert(descriptor.configurable == true);
|
||||
assert(descriptor.get !== undefined || descriptor.set !== undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var o = {
|
||||
get a() {},
|
||||
b:6,
|
||||
set c(_) {
|
||||
},
|
||||
d:10,
|
||||
a: 11,
|
||||
get b () {},
|
||||
c: 12,
|
||||
set d (_) {}
|
||||
}
|
||||
|
||||
checkOwnProperties(o, ['a', 'b', 'c', 'd']);
|
||||
Reference in New Issue
Block a user