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:
@@ -142,125 +142,6 @@ ecma_op_create_function_object (ecma_object_t *scope_p, /**< function's scope */
|
|||||||
return func_p;
|
return func_p;
|
||||||
} /* ecma_op_create_function_object */
|
} /* 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.
|
* 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;
|
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;
|
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;
|
return function_obj_p;
|
||||||
} /* ecma_op_create_external_function_object */
|
} /* 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;
|
return ret_value;
|
||||||
} /* ecma_op_function_construct */
|
} /* 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.
|
* 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;
|
return NULL;
|
||||||
} /* ecma_op_bound_function_try_to_lazy_instantiate_property */
|
} /* 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_object_t *
|
||||||
ecma_op_create_function_object (ecma_object_t *scope_p, const ecma_compiled_code_t *bytecode_data_p);
|
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_object_t *
|
||||||
ecma_op_create_external_function_object (ecma_external_handler_t handler_cb);
|
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_value_t
|
||||||
ecma_op_function_has_instance (ecma_object_t *func_obj_p, ecma_value_t value);
|
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_property_t *
|
||||||
ecma_op_bound_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, ecma_string_t *property_name_p);
|
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. */
|
/* Get prototype physical property. */
|
||||||
property_p = ecma_op_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
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)
|
else if (type == ECMA_OBJECT_TYPE_BOUND_FUNCTION)
|
||||||
{
|
{
|
||||||
property_p = ecma_op_bound_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
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. */
|
/* Get prototype physical property. */
|
||||||
property_p = ecma_op_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
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)
|
else if (type == ECMA_OBJECT_TYPE_BOUND_FUNCTION)
|
||||||
{
|
{
|
||||||
property_p = ecma_op_bound_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
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. */
|
/* Get prototype physical property. */
|
||||||
property_p = ecma_op_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
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)
|
else if (type == ECMA_OBJECT_TYPE_BOUND_FUNCTION)
|
||||||
{
|
{
|
||||||
property_p = ecma_op_bound_function_try_to_lazy_instantiate_property (object_p, property_name_p);
|
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)
|
switch (type)
|
||||||
{
|
{
|
||||||
case ECMA_OBJECT_TYPE_GENERAL:
|
case ECMA_OBJECT_TYPE_GENERAL:
|
||||||
case ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION:
|
|
||||||
case ECMA_OBJECT_TYPE_BOUND_FUNCTION:
|
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1378,11 +1388,26 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */
|
|||||||
}
|
}
|
||||||
case ECMA_OBJECT_TYPE_FUNCTION:
|
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,
|
prop_names_p,
|
||||||
skipped_non_enumerable_p);
|
skipped_non_enumerable_p);
|
||||||
break;
|
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:
|
case ECMA_OBJECT_TYPE_CLASS:
|
||||||
{
|
{
|
||||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;
|
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_append_to_values_collection (skipped_non_enumerable_p,
|
||||||
ecma_make_string_value (name_p),
|
ecma_make_string_value (name_p),
|
||||||
true);
|
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);
|
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,
|
JMEM_DEFINE_LOCAL_ARRAY (names_p,
|
||||||
array_index_named_properties_count + string_named_properties_count,
|
array_index_named_properties_count + string_named_properties_count,
|
||||||
ecma_string_t *);
|
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 < array_index_named_properties_count + string_named_properties_count;
|
||||||
i++)
|
i++)
|
||||||
{
|
{
|
||||||
bool is_append;
|
bool is_append = true;
|
||||||
|
|
||||||
ecma_string_t *name_p = names_p[i];
|
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)
|
if ((names_hashes_bitmap[bitmap_row] & (1u << bitmap_column)) == 0)
|
||||||
{
|
{
|
||||||
/* no name with the hash is in constructed collection */
|
/* This hash has not been used before (for non-skipped). */
|
||||||
is_append = true;
|
|
||||||
|
|
||||||
names_hashes_bitmap[bitmap_row] |= (1u << bitmap_column);
|
names_hashes_bitmap[bitmap_row] |= (1u << bitmap_column);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* name with same hash already occured */
|
/* Name with same hash has already occured. */
|
||||||
bool is_equal_found = false;
|
|
||||||
|
|
||||||
ecma_collection_iterator_init (&iter, ret_p);
|
ecma_collection_iterator_init (&iter, ret_p);
|
||||||
|
|
||||||
while (ecma_collection_iterator_next (&iter))
|
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))
|
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);
|
ecma_collection_iterator_init (&iter, skipped_non_enumerable_p);
|
||||||
while (ecma_collection_iterator_next (&iter))
|
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))
|
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)
|
if (is_append)
|
||||||
|
|||||||
@@ -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");
|
||||||
Reference in New Issue
Block a user