mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Correctly enumerate function property members.
Functions has several built-in non-enumerable properties, and they are correctly ignored during enumeration after this patch. External function prototype is also lazy enumerated. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
parent
7905422b19
commit
522c7d3f87
@ -142,125 +142,6 @@ ecma_op_create_function_object (ecma_object_t *scope_p, /**< function's scope */
|
||||
return func_p;
|
||||
} /* ecma_op_create_function_object */
|
||||
|
||||
/**
|
||||
* List names of a Function object's lazy instantiated properties,
|
||||
* adding them to corresponding string collections
|
||||
*
|
||||
* See also:
|
||||
* ecma_op_function_try_to_lazy_instantiate_property
|
||||
*/
|
||||
void
|
||||
ecma_op_function_list_lazy_property_names (bool separate_enumerable, /**< true - list enumerable properties into
|
||||
* main collection and non-enumerable
|
||||
* to collection of 'skipped
|
||||
* non-enumerable' properties,
|
||||
* false - list all properties into main
|
||||
* collection.
|
||||
*/
|
||||
ecma_collection_header_t *main_collection_p, /**< 'main' collection */
|
||||
ecma_collection_header_t *non_enum_collection_p) /**< skipped
|
||||
* 'non-enumerable'
|
||||
* collection */
|
||||
{
|
||||
ecma_collection_header_t *for_enumerable_p = main_collection_p;
|
||||
JERRY_UNUSED (for_enumerable_p);
|
||||
|
||||
ecma_collection_header_t *for_non_enumerable_p = separate_enumerable ? non_enum_collection_p : main_collection_p;
|
||||
|
||||
ecma_string_t *name_p;
|
||||
|
||||
/* 'length' property is non-enumerable (ECMA-262 v5, 13.2.5) */
|
||||
name_p = ecma_new_ecma_length_string ();
|
||||
ecma_append_to_values_collection (for_non_enumerable_p, ecma_make_string_value (name_p), true);
|
||||
ecma_deref_ecma_string (name_p);
|
||||
|
||||
/* 'prototype' property is non-enumerable (ECMA-262 v5, 13.2.18) */
|
||||
name_p = ecma_get_magic_string (LIT_MAGIC_STRING_PROTOTYPE);
|
||||
ecma_append_to_values_collection (for_non_enumerable_p, ecma_make_string_value (name_p), true);
|
||||
ecma_deref_ecma_string (name_p);
|
||||
} /* ecma_op_function_list_lazy_property_names */
|
||||
|
||||
/**
|
||||
* Lazy instantation of non-builtin ecma function object's properties
|
||||
*
|
||||
* Warning:
|
||||
* Only non-configurable properties could be instantiated lazily in this function,
|
||||
* as configurable properties could be deleted and it would be incorrect
|
||||
* to reinstantiate them in the function in second time.
|
||||
*
|
||||
* @return pointer to newly instantiated property, if a property was instantiated,
|
||||
* NULL - otherwise
|
||||
*/
|
||||
ecma_property_t *
|
||||
ecma_op_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, /**< the function object */
|
||||
ecma_string_t *property_name_p) /**< property name */
|
||||
{
|
||||
JERRY_ASSERT (!ecma_get_object_is_builtin (object_p));
|
||||
|
||||
if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_PROTOTYPE))
|
||||
{
|
||||
/* ECMA-262 v5, 13.2, 16-18 */
|
||||
|
||||
/* 16. */
|
||||
ecma_object_t *proto_object_p = ecma_op_create_object_object_noarg ();
|
||||
|
||||
/* 17. */
|
||||
ecma_string_t magic_string_constructor;
|
||||
ecma_init_ecma_magic_string (&magic_string_constructor, LIT_MAGIC_STRING_CONSTRUCTOR);
|
||||
|
||||
ecma_property_value_t *constructor_prop_value_p;
|
||||
constructor_prop_value_p = ecma_create_named_data_property (proto_object_p,
|
||||
&magic_string_constructor,
|
||||
ECMA_PROPERTY_CONFIGURABLE_WRITABLE,
|
||||
NULL);
|
||||
|
||||
constructor_prop_value_p->value = ecma_make_object_value (object_p);
|
||||
|
||||
/* 18. */
|
||||
ecma_property_t *prototype_prop_p;
|
||||
ecma_property_value_t *prototype_prop_value_p;
|
||||
prototype_prop_value_p = ecma_create_named_data_property (object_p,
|
||||
property_name_p,
|
||||
ECMA_PROPERTY_FLAG_WRITABLE,
|
||||
&prototype_prop_p);
|
||||
|
||||
prototype_prop_value_p->value = ecma_make_object_value (proto_object_p);
|
||||
|
||||
ecma_deref_object (proto_object_p);
|
||||
|
||||
return prototype_prop_p;
|
||||
}
|
||||
|
||||
if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_CALLER)
|
||||
|| ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_ARGUMENTS))
|
||||
{
|
||||
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
const ecma_compiled_code_t *bytecode_data_p;
|
||||
bytecode_data_p = ECMA_GET_INTERNAL_VALUE_POINTER (const ecma_compiled_code_t,
|
||||
ext_func_p->u.function.bytecode_cp);
|
||||
|
||||
if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE)
|
||||
{
|
||||
ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER);
|
||||
|
||||
ecma_property_t *caller_prop_p;
|
||||
/* The property_name_p argument contans the name. */
|
||||
ecma_create_named_accessor_property (object_p,
|
||||
property_name_p,
|
||||
thrower_p,
|
||||
thrower_p,
|
||||
ECMA_PROPERTY_FIXED,
|
||||
&caller_prop_p);
|
||||
|
||||
ecma_deref_object (thrower_p);
|
||||
return caller_prop_p;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
} /* ecma_op_function_try_to_lazy_instantiate_property */
|
||||
|
||||
/**
|
||||
* External function object creation operation.
|
||||
*
|
||||
@ -291,17 +172,6 @@ ecma_op_create_external_function_object (ecma_external_handler_t handler_cb) /**
|
||||
ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) function_obj_p;
|
||||
ext_func_obj_p->u.external_handler_cb = handler_cb;
|
||||
|
||||
ecma_string_t *magic_string_prototype_p = ecma_get_magic_string (LIT_MAGIC_STRING_PROTOTYPE);
|
||||
ecma_builtin_helper_def_prop (function_obj_p,
|
||||
magic_string_prototype_p,
|
||||
ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED),
|
||||
true, /* Writable */
|
||||
false, /* Enumerable */
|
||||
false, /* Configurable */
|
||||
false); /* Failure handling */
|
||||
|
||||
ecma_deref_ecma_string (magic_string_prototype_p);
|
||||
|
||||
return function_obj_p;
|
||||
} /* ecma_op_create_external_function_object */
|
||||
|
||||
@ -757,6 +627,118 @@ ecma_op_function_construct (ecma_object_t *func_obj_p, /**< Function object */
|
||||
return ret_value;
|
||||
} /* ecma_op_function_construct */
|
||||
|
||||
/**
|
||||
* Lazy instantation of non-builtin ecma function object's properties
|
||||
*
|
||||
* Warning:
|
||||
* Only non-configurable properties could be instantiated lazily in this function,
|
||||
* as configurable properties could be deleted and it would be incorrect
|
||||
* to reinstantiate them in the function in second time.
|
||||
*
|
||||
* @return pointer to newly instantiated property, if a property was instantiated,
|
||||
* NULL - otherwise
|
||||
*/
|
||||
ecma_property_t *
|
||||
ecma_op_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, /**< the function object */
|
||||
ecma_string_t *property_name_p) /**< property name */
|
||||
{
|
||||
JERRY_ASSERT (!ecma_get_object_is_builtin (object_p));
|
||||
|
||||
if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_PROTOTYPE))
|
||||
{
|
||||
/* ECMA-262 v5, 13.2, 16-18 */
|
||||
|
||||
/* 16. */
|
||||
ecma_object_t *proto_object_p = ecma_op_create_object_object_noarg ();
|
||||
|
||||
/* 17. */
|
||||
ecma_string_t magic_string_constructor;
|
||||
ecma_init_ecma_magic_string (&magic_string_constructor, LIT_MAGIC_STRING_CONSTRUCTOR);
|
||||
|
||||
ecma_property_value_t *constructor_prop_value_p;
|
||||
constructor_prop_value_p = ecma_create_named_data_property (proto_object_p,
|
||||
&magic_string_constructor,
|
||||
ECMA_PROPERTY_CONFIGURABLE_WRITABLE,
|
||||
NULL);
|
||||
|
||||
constructor_prop_value_p->value = ecma_make_object_value (object_p);
|
||||
|
||||
/* 18. */
|
||||
ecma_property_t *prototype_prop_p;
|
||||
ecma_property_value_t *prototype_prop_value_p;
|
||||
prototype_prop_value_p = ecma_create_named_data_property (object_p,
|
||||
property_name_p,
|
||||
ECMA_PROPERTY_FLAG_WRITABLE,
|
||||
&prototype_prop_p);
|
||||
|
||||
prototype_prop_value_p->value = ecma_make_object_value (proto_object_p);
|
||||
|
||||
ecma_deref_object (proto_object_p);
|
||||
|
||||
return prototype_prop_p;
|
||||
}
|
||||
|
||||
if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_CALLER)
|
||||
|| ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_ARGUMENTS))
|
||||
{
|
||||
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
const ecma_compiled_code_t *bytecode_data_p;
|
||||
bytecode_data_p = ECMA_GET_INTERNAL_VALUE_POINTER (const ecma_compiled_code_t,
|
||||
ext_func_p->u.function.bytecode_cp);
|
||||
|
||||
if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE)
|
||||
{
|
||||
ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER);
|
||||
|
||||
ecma_property_t *caller_prop_p;
|
||||
/* The property_name_p argument contans the name. */
|
||||
ecma_create_named_accessor_property (object_p,
|
||||
property_name_p,
|
||||
thrower_p,
|
||||
thrower_p,
|
||||
ECMA_PROPERTY_FIXED,
|
||||
&caller_prop_p);
|
||||
|
||||
ecma_deref_object (thrower_p);
|
||||
return caller_prop_p;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
} /* ecma_op_function_try_to_lazy_instantiate_property */
|
||||
|
||||
/**
|
||||
* Create specification defined non-configurable properties for external functions.
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v5, 15.3.4.5
|
||||
*
|
||||
* @return pointer property, if one was instantiated,
|
||||
* NULL - otherwise.
|
||||
*/
|
||||
ecma_property_t *
|
||||
ecma_op_external_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, /**< object */
|
||||
ecma_string_t *property_name_p) /**< property's name */
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION);
|
||||
|
||||
if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_PROTOTYPE))
|
||||
{
|
||||
ecma_property_t *prototype_prop_p;
|
||||
ecma_property_value_t *prototype_prop_value_p;
|
||||
prototype_prop_value_p = ecma_create_named_data_property (object_p,
|
||||
property_name_p,
|
||||
ECMA_PROPERTY_FLAG_WRITABLE,
|
||||
&prototype_prop_p);
|
||||
|
||||
prototype_prop_value_p->value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
|
||||
return prototype_prop_p;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
} /* ecma_op_external_function_try_to_lazy_instantiate_property */
|
||||
|
||||
/**
|
||||
* Create specification defined non-configurable properties for bound functions.
|
||||
*
|
||||
@ -836,6 +818,134 @@ ecma_op_bound_function_try_to_lazy_instantiate_property (ecma_object_t *object_p
|
||||
return NULL;
|
||||
} /* ecma_op_bound_function_try_to_lazy_instantiate_property */
|
||||
|
||||
/**
|
||||
* List names of a Function object's lazy instantiated properties,
|
||||
* adding them to corresponding string collections
|
||||
*
|
||||
* See also:
|
||||
* ecma_op_function_try_to_lazy_instantiate_property
|
||||
*/
|
||||
void
|
||||
ecma_op_function_list_lazy_property_names (ecma_object_t *object_p, /**< functionobject */
|
||||
bool separate_enumerable, /**< true - list enumerable properties into
|
||||
* main collection and non-enumerable
|
||||
* to collection of 'skipped
|
||||
* non-enumerable' properties,
|
||||
* false - list all properties into main
|
||||
* collection.
|
||||
*/
|
||||
ecma_collection_header_t *main_collection_p, /**< 'main' collection */
|
||||
ecma_collection_header_t *non_enum_collection_p) /**< skipped
|
||||
* 'non-enumerable'
|
||||
* collection */
|
||||
{
|
||||
JERRY_UNUSED (main_collection_p);
|
||||
|
||||
ecma_collection_header_t *for_non_enumerable_p = separate_enumerable ? non_enum_collection_p : main_collection_p;
|
||||
|
||||
/* 'length' property is non-enumerable (ECMA-262 v5, 13.2.5) */
|
||||
ecma_string_t *name_p = ecma_new_ecma_length_string ();
|
||||
ecma_append_to_values_collection (for_non_enumerable_p, ecma_make_string_value (name_p), true);
|
||||
ecma_deref_ecma_string (name_p);
|
||||
|
||||
/* 'prototype' property is non-enumerable (ECMA-262 v5, 13.2.18) */
|
||||
name_p = ecma_get_magic_string (LIT_MAGIC_STRING_PROTOTYPE);
|
||||
ecma_append_to_values_collection (for_non_enumerable_p, ecma_make_string_value (name_p), true);
|
||||
ecma_deref_ecma_string (name_p);
|
||||
|
||||
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
const ecma_compiled_code_t *bytecode_data_p;
|
||||
bytecode_data_p = ECMA_GET_INTERNAL_VALUE_POINTER (const ecma_compiled_code_t,
|
||||
ext_func_p->u.function.bytecode_cp);
|
||||
|
||||
if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE)
|
||||
{
|
||||
/* 'caller' property is non-enumerable (ECMA-262 v5, 13.2.5) */
|
||||
name_p = ecma_get_magic_string (LIT_MAGIC_STRING_CALLER);
|
||||
ecma_append_to_values_collection (for_non_enumerable_p, ecma_make_string_value (name_p), true);
|
||||
ecma_deref_ecma_string (name_p);
|
||||
|
||||
/* 'arguments' property is non-enumerable (ECMA-262 v5, 13.2.5) */
|
||||
name_p = ecma_get_magic_string (LIT_MAGIC_STRING_ARGUMENTS);
|
||||
ecma_append_to_values_collection (for_non_enumerable_p, ecma_make_string_value (name_p), true);
|
||||
ecma_deref_ecma_string (name_p);
|
||||
}
|
||||
} /* ecma_op_function_list_lazy_property_names */
|
||||
|
||||
/**
|
||||
* List names of an External Function object's lazy instantiated properties,
|
||||
* adding them to corresponding string collections
|
||||
*
|
||||
* See also:
|
||||
* ecma_op_external_function_try_to_lazy_instantiate_property
|
||||
*/
|
||||
void
|
||||
ecma_op_external_function_list_lazy_property_names (bool separate_enumerable, /**< true - list enumerable properties
|
||||
* into main collection and
|
||||
* non-enumerable to collection
|
||||
* of 'skipped non-enumerable'
|
||||
* properties,
|
||||
* false - list all properties into
|
||||
* main collection.
|
||||
*/
|
||||
ecma_collection_header_t *main_collection_p, /**< 'main'
|
||||
* collection */
|
||||
ecma_collection_header_t *non_enum_collection_p) /**< skipped
|
||||
* collection */
|
||||
{
|
||||
JERRY_UNUSED (main_collection_p);
|
||||
|
||||
ecma_collection_header_t *for_non_enumerable_p = separate_enumerable ? non_enum_collection_p : main_collection_p;
|
||||
|
||||
/* 'prototype' property is non-enumerable (ECMA-262 v5, 13.2.18) */
|
||||
ecma_string_t *name_p = ecma_get_magic_string (LIT_MAGIC_STRING_PROTOTYPE);
|
||||
ecma_append_to_values_collection (for_non_enumerable_p, ecma_make_string_value (name_p), true);
|
||||
ecma_deref_ecma_string (name_p);
|
||||
} /* ecma_op_external_function_list_lazy_property_names */
|
||||
|
||||
/**
|
||||
* List names of a Bound Function object's lazy instantiated properties,
|
||||
* adding them to corresponding string collections
|
||||
*
|
||||
* See also:
|
||||
* ecma_op_bound_function_try_to_lazy_instantiate_property
|
||||
*/
|
||||
void
|
||||
ecma_op_bound_function_list_lazy_property_names (bool separate_enumerable, /**< true - list enumerable properties
|
||||
* into main collection and
|
||||
* non-enumerable to collection
|
||||
* of 'skipped non-enumerable'
|
||||
* properties,
|
||||
* false - list all properties into
|
||||
* main collection.
|
||||
*/
|
||||
ecma_collection_header_t *main_collection_p, /**< 'main'
|
||||
* collection */
|
||||
ecma_collection_header_t *non_enum_collection_p) /**< skipped
|
||||
* 'non-enumerable'
|
||||
* collection */
|
||||
{
|
||||
JERRY_UNUSED (main_collection_p);
|
||||
|
||||
ecma_collection_header_t *for_non_enumerable_p = separate_enumerable ? non_enum_collection_p : main_collection_p;
|
||||
|
||||
/* 'length' property is non-enumerable (ECMA-262 v5, 13.2.5) */
|
||||
ecma_string_t *name_p = ecma_new_ecma_length_string ();
|
||||
ecma_append_to_values_collection (for_non_enumerable_p, ecma_make_string_value (name_p), true);
|
||||
ecma_deref_ecma_string (name_p);
|
||||
|
||||
/* 'caller' property is non-enumerable (ECMA-262 v5, 13.2.5) */
|
||||
name_p = ecma_get_magic_string (LIT_MAGIC_STRING_CALLER);
|
||||
ecma_append_to_values_collection (for_non_enumerable_p, ecma_make_string_value (name_p), true);
|
||||
ecma_deref_ecma_string (name_p);
|
||||
|
||||
/* 'arguments' property is non-enumerable (ECMA-262 v5, 13.2.5) */
|
||||
name_p = ecma_get_magic_string (LIT_MAGIC_STRING_ARGUMENTS);
|
||||
ecma_append_to_values_collection (for_non_enumerable_p, ecma_make_string_value (name_p), true);
|
||||
ecma_deref_ecma_string (name_p);
|
||||
} /* ecma_op_bound_function_list_lazy_property_names */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
|
||||
@ -32,14 +32,6 @@ bool ecma_is_constructor (ecma_value_t value);
|
||||
ecma_object_t *
|
||||
ecma_op_create_function_object (ecma_object_t *scope_p, const ecma_compiled_code_t *bytecode_data_p);
|
||||
|
||||
void
|
||||
ecma_op_function_list_lazy_property_names (bool separate_enumerable,
|
||||
ecma_collection_header_t *main_collection_p,
|
||||
ecma_collection_header_t *non_enum_collection_p);
|
||||
|
||||
ecma_property_t *
|
||||
ecma_op_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, ecma_string_t *property_name_p);
|
||||
|
||||
ecma_object_t *
|
||||
ecma_op_create_external_function_object (ecma_external_handler_t handler_cb);
|
||||
|
||||
@ -54,9 +46,31 @@ ecma_op_function_construct (ecma_object_t *func_obj_p, const ecma_value_t *argum
|
||||
ecma_value_t
|
||||
ecma_op_function_has_instance (ecma_object_t *func_obj_p, ecma_value_t value);
|
||||
|
||||
ecma_property_t *
|
||||
ecma_op_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, ecma_string_t *property_name_p);
|
||||
|
||||
ecma_property_t *
|
||||
ecma_op_external_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, ecma_string_t *property_name_p);
|
||||
|
||||
ecma_property_t *
|
||||
ecma_op_bound_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, ecma_string_t *property_name_p);
|
||||
|
||||
void
|
||||
ecma_op_function_list_lazy_property_names (ecma_object_t *object_p,
|
||||
bool separate_enumerable,
|
||||
ecma_collection_header_t *main_collection_p,
|
||||
ecma_collection_header_t *non_enum_collection_p);
|
||||
|
||||
void
|
||||
ecma_op_external_function_list_lazy_property_names (bool separate_enumerable,
|
||||
ecma_collection_header_t *main_collection_p,
|
||||
ecma_collection_header_t *non_enum_collection_p);
|
||||
|
||||
void
|
||||
ecma_op_bound_function_list_lazy_property_names (bool separate_enumerable,
|
||||
ecma_collection_header_t *main_collection_p,
|
||||
ecma_collection_header_t *non_enum_collection_p);
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
|
||||
@ -233,6 +233,10 @@ ecma_op_object_get_own_property (ecma_object_t *object_p, /**< the object */
|
||||
/* Get prototype physical property. */
|
||||
property_p = ecma_op_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
||||
}
|
||||
else if (type == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION)
|
||||
{
|
||||
property_p = ecma_op_external_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
||||
}
|
||||
else if (type == ECMA_OBJECT_TYPE_BOUND_FUNCTION)
|
||||
{
|
||||
property_p = ecma_op_bound_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
||||
@ -535,6 +539,10 @@ ecma_op_object_find_own (ecma_value_t base_value, /**< base value */
|
||||
/* Get prototype physical property. */
|
||||
property_p = ecma_op_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
||||
}
|
||||
else if (type == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION)
|
||||
{
|
||||
property_p = ecma_op_external_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
||||
}
|
||||
else if (type == ECMA_OBJECT_TYPE_BOUND_FUNCTION)
|
||||
{
|
||||
property_p = ecma_op_bound_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
||||
@ -826,6 +834,10 @@ ecma_op_object_put (ecma_object_t *object_p, /**< the object */
|
||||
/* Get prototype physical property. */
|
||||
property_p = ecma_op_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
||||
}
|
||||
else if (type == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION)
|
||||
{
|
||||
property_p = ecma_op_external_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
||||
}
|
||||
else if (type == ECMA_OBJECT_TYPE_BOUND_FUNCTION)
|
||||
{
|
||||
property_p = ecma_op_bound_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
||||
@ -1361,8 +1373,6 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */
|
||||
switch (type)
|
||||
{
|
||||
case ECMA_OBJECT_TYPE_GENERAL:
|
||||
case ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION:
|
||||
case ECMA_OBJECT_TYPE_BOUND_FUNCTION:
|
||||
{
|
||||
break;
|
||||
}
|
||||
@ -1378,11 +1388,26 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */
|
||||
}
|
||||
case ECMA_OBJECT_TYPE_FUNCTION:
|
||||
{
|
||||
ecma_op_function_list_lazy_property_names (is_enumerable_only,
|
||||
ecma_op_function_list_lazy_property_names (obj_p,
|
||||
is_enumerable_only,
|
||||
prop_names_p,
|
||||
skipped_non_enumerable_p);
|
||||
break;
|
||||
}
|
||||
case ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION:
|
||||
{
|
||||
ecma_op_external_function_list_lazy_property_names (is_enumerable_only,
|
||||
prop_names_p,
|
||||
skipped_non_enumerable_p);
|
||||
break;
|
||||
}
|
||||
case ECMA_OBJECT_TYPE_BOUND_FUNCTION:
|
||||
{
|
||||
ecma_op_bound_function_list_lazy_property_names (is_enumerable_only,
|
||||
prop_names_p,
|
||||
skipped_non_enumerable_p);
|
||||
break;
|
||||
}
|
||||
case ECMA_OBJECT_TYPE_CLASS:
|
||||
{
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;
|
||||
@ -1504,15 +1529,6 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */
|
||||
ecma_append_to_values_collection (skipped_non_enumerable_p,
|
||||
ecma_make_string_value (name_p),
|
||||
true);
|
||||
|
||||
uint8_t hash = (uint8_t) name_p->hash;
|
||||
uint32_t bitmap_row = (uint32_t) (hash / bitmap_row_size);
|
||||
uint32_t bitmap_column = (uint32_t) (hash % bitmap_row_size);
|
||||
|
||||
if ((names_hashes_bitmap[bitmap_row] & (1u << bitmap_column)) == 0)
|
||||
{
|
||||
names_hashes_bitmap[bitmap_row] |= (1u << bitmap_column);
|
||||
}
|
||||
}
|
||||
|
||||
ecma_deref_ecma_string (name_p);
|
||||
@ -1541,7 +1557,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */
|
||||
}
|
||||
}
|
||||
|
||||
/* Second pass: collecting properties names into arrays */
|
||||
/* Second pass: collecting property names into arrays. */
|
||||
JMEM_DEFINE_LOCAL_ARRAY (names_p,
|
||||
array_index_named_properties_count + string_named_properties_count,
|
||||
ecma_string_t *);
|
||||
@ -1622,7 +1638,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */
|
||||
i < array_index_named_properties_count + string_named_properties_count;
|
||||
i++)
|
||||
{
|
||||
bool is_append;
|
||||
bool is_append = true;
|
||||
|
||||
ecma_string_t *name_p = names_p[i];
|
||||
|
||||
@ -1632,16 +1648,12 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */
|
||||
|
||||
if ((names_hashes_bitmap[bitmap_row] & (1u << bitmap_column)) == 0)
|
||||
{
|
||||
/* no name with the hash is in constructed collection */
|
||||
is_append = true;
|
||||
|
||||
/* This hash has not been used before (for non-skipped). */
|
||||
names_hashes_bitmap[bitmap_row] |= (1u << bitmap_column);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* name with same hash already occured */
|
||||
bool is_equal_found = false;
|
||||
|
||||
/* Name with same hash has already occured. */
|
||||
ecma_collection_iterator_init (&iter, ret_p);
|
||||
|
||||
while (ecma_collection_iterator_next (&iter))
|
||||
@ -1650,10 +1662,14 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */
|
||||
|
||||
if (ecma_compare_ecma_strings (name_p, iter_name_p))
|
||||
{
|
||||
is_equal_found = true;
|
||||
is_append = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_append)
|
||||
{
|
||||
ecma_collection_iterator_init (&iter, skipped_non_enumerable_p);
|
||||
while (ecma_collection_iterator_next (&iter))
|
||||
{
|
||||
@ -1661,11 +1677,10 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */
|
||||
|
||||
if (ecma_compare_ecma_strings (name_p, iter_name_p))
|
||||
{
|
||||
is_equal_found = true;
|
||||
is_append = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
is_append = !is_equal_found;
|
||||
}
|
||||
|
||||
if (is_append)
|
||||
|
||||
46
tests/jerry/es2015/function-properties.js
Normal file
46
tests/jerry/es2015/function-properties.js
Normal file
@ -0,0 +1,46 @@
|
||||
// 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 getProperties(obj)
|
||||
{
|
||||
var str = "";
|
||||
for (name in obj)
|
||||
{
|
||||
if (str)
|
||||
{
|
||||
str += " " + name;
|
||||
}
|
||||
else
|
||||
{
|
||||
str = name;
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
var prototype_obj = { dummy:1, length:1, caller:null,
|
||||
arguments:null, prototype:null };
|
||||
|
||||
var func = function() {};
|
||||
|
||||
Object.setPrototypeOf(func, prototype_obj);
|
||||
assert(getProperties(func) == "dummy caller arguments");
|
||||
|
||||
var bound_func = (function() {}).bind(null);
|
||||
Object.setPrototypeOf(bound_func, prototype_obj);
|
||||
assert(getProperties(bound_func) == "dummy prototype");
|
||||
|
||||
// 'print' is an external function
|
||||
Object.setPrototypeOf(print, prototype_obj);
|
||||
assert(getProperties(print) == "dummy length caller arguments");
|
||||
Loading…
x
Reference in New Issue
Block a user