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)
|
#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.
|
* 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));
|
JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p));
|
||||||
|
|
||||||
ecma_property_t *property_p = ecma_find_named_property (object_p, prop_name_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;
|
ecma_property_value_t *prop_value_p;
|
||||||
|
|
||||||
if (property_p == NULL)
|
if (property_p == NULL)
|
||||||
@@ -151,6 +143,21 @@ opfunc_set_data_property (ecma_object_t *object_p, /**< object */
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
|
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);
|
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));
|
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_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_object_t *getter_func_p = NULL;
|
||||||
&& ECMA_PROPERTY_GET_TYPE (*property_p) != ECMA_PROPERTY_TYPE_NAMEDACCESSOR)
|
ecma_object_t *setter_func_p = NULL;
|
||||||
|
|
||||||
|
if (is_getter)
|
||||||
{
|
{
|
||||||
ecma_delete_property (object_p, ECMA_PROPERTY_VALUE_PTR (property_p));
|
getter_func_p = accessor_p;
|
||||||
property_p = NULL;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setter_func_p = accessor_p;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (property_p == NULL)
|
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,
|
ecma_create_named_accessor_property (object_p,
|
||||||
accessor_name_p,
|
accessor_name_p,
|
||||||
getter_func_p,
|
getter_func_p,
|
||||||
@@ -199,21 +200,40 @@ opfunc_set_accessor (bool is_getter, /**< is getter accessor */
|
|||||||
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE,
|
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE,
|
||||||
NULL);
|
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
|
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,
|
if (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA)
|
||||||
ECMA_PROPERTY_VALUE_PTR (property_p),
|
{
|
||||||
setter_func_p);
|
#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 */
|
} /* 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