Major property rework: introducing virtual properties.
Properties are changed to a type and value pair instead of a pointer to an internal representation. Functions such as ecma_op_object_get_[own_]property do not return with property pointers anymore. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
@@ -105,11 +105,13 @@ ecma_op_create_array_object (const ecma_value_t *arguments_list_p, /**< list of
|
||||
|
||||
ecma_string_t *length_magic_string_p = ecma_new_ecma_length_string ();
|
||||
|
||||
ecma_property_t *length_prop_p = ecma_create_named_data_property (obj_p,
|
||||
length_magic_string_p,
|
||||
ECMA_PROPERTY_FLAG_WRITABLE);
|
||||
ecma_property_value_t *length_prop_value_p;
|
||||
length_prop_value_p = ecma_create_named_data_property (obj_p,
|
||||
length_magic_string_p,
|
||||
ECMA_PROPERTY_FLAG_WRITABLE,
|
||||
NULL);
|
||||
|
||||
ecma_set_named_data_property_value (length_prop_p, ecma_make_number_value ((ecma_number_t) length));
|
||||
length_prop_value_p->value = ecma_make_number_value ((ecma_number_t) length);
|
||||
|
||||
ecma_deref_ecma_string (length_magic_string_p);
|
||||
|
||||
@@ -158,11 +160,13 @@ ecma_op_array_object_define_own_property (ecma_object_t *obj_p, /**< the array o
|
||||
|
||||
// 1.
|
||||
ecma_string_t *magic_string_length_p = ecma_new_ecma_length_string ();
|
||||
ecma_property_t *len_prop_p = ecma_op_object_get_own_property (obj_p, magic_string_length_p);
|
||||
JERRY_ASSERT (len_prop_p != NULL && ECMA_PROPERTY_GET_TYPE (len_prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA);
|
||||
ecma_property_t *len_prop_p = ecma_find_named_property (obj_p, magic_string_length_p);
|
||||
|
||||
JERRY_ASSERT (len_prop_p != NULL
|
||||
&& ECMA_PROPERTY_GET_TYPE (*len_prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA);
|
||||
|
||||
// 2.
|
||||
ecma_value_t old_len_value = ecma_get_named_data_property_value (len_prop_p);
|
||||
ecma_value_t old_len_value = ECMA_PROPERTY_VALUE_PTR (len_prop_p)->value;
|
||||
|
||||
uint32_t old_len_uint32 = ecma_get_uint32_from_value (old_len_value);
|
||||
|
||||
@@ -231,7 +235,7 @@ ecma_op_array_object_define_own_property (ecma_object_t *obj_p, /**< the array o
|
||||
else
|
||||
{
|
||||
// g.
|
||||
if (!ecma_is_property_writable (len_prop_p))
|
||||
if (!ecma_is_property_writable (*len_prop_p))
|
||||
{
|
||||
ret_value = ecma_reject (is_throw);
|
||||
}
|
||||
@@ -410,7 +414,7 @@ ecma_op_array_object_define_own_property (ecma_object_t *obj_p, /**< the array o
|
||||
|
||||
// b.
|
||||
if (index >= old_len_uint32
|
||||
&& !ecma_is_property_writable (len_prop_p))
|
||||
&& !ecma_is_property_writable (*len_prop_p))
|
||||
{
|
||||
return ecma_reject (is_throw);
|
||||
}
|
||||
|
||||
@@ -118,14 +118,16 @@ ecma_new_standard_error_with_message (ecma_standard_error_t error_type, /**< nat
|
||||
ecma_object_t *new_error_obj_p = ecma_new_standard_error (error_type);
|
||||
|
||||
ecma_string_t *message_magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_MESSAGE);
|
||||
ecma_property_t *prop_p = ecma_create_named_data_property (new_error_obj_p,
|
||||
message_magic_string_p,
|
||||
ECMA_PROPERTY_CONFIGURABLE_WRITABLE);
|
||||
|
||||
ecma_property_value_t *prop_value_p;
|
||||
prop_value_p = ecma_create_named_data_property (new_error_obj_p,
|
||||
message_magic_string_p,
|
||||
ECMA_PROPERTY_CONFIGURABLE_WRITABLE,
|
||||
NULL);
|
||||
ecma_deref_ecma_string (message_magic_string_p);
|
||||
|
||||
ecma_ref_ecma_string (message_string_p);
|
||||
ecma_set_named_data_property_value (prop_p,
|
||||
ecma_make_string_value (message_string_p));
|
||||
ecma_deref_ecma_string (message_magic_string_p);
|
||||
prop_value_p->value = ecma_make_string_value (message_string_p);
|
||||
|
||||
return new_error_obj_p;
|
||||
} /* ecma_new_standard_error_with_message */
|
||||
|
||||
@@ -184,8 +184,7 @@ ecma_op_create_function_object (ecma_object_t *scope_p, /**< function's scope */
|
||||
/*
|
||||
* 'length' and 'prototype' properties are instantiated lazily
|
||||
*
|
||||
* See also: ecma_op_function_object_get_own_property
|
||||
* ecma_op_function_try_lazy_instantiate_property
|
||||
* See also: ecma_op_function_try_lazy_instantiate_property
|
||||
*/
|
||||
|
||||
// 19.
|
||||
@@ -278,124 +277,69 @@ ecma_op_function_list_lazy_property_names (bool separate_enumerable, /**< true -
|
||||
* NULL - otherwise
|
||||
*/
|
||||
ecma_property_t *
|
||||
ecma_op_function_try_lazy_instantiate_property (ecma_object_t *obj_p, /**< the function object */
|
||||
ecma_op_function_try_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 (obj_p));
|
||||
static const char prototype_str_p[] = "prototype";
|
||||
|
||||
if (ecma_string_is_length (property_name_p))
|
||||
JERRY_ASSERT (!ecma_get_object_is_builtin (object_p));
|
||||
|
||||
ecma_string_container_t container = ECMA_STRING_GET_CONTAINER (property_name_p);
|
||||
|
||||
/* Check whether the property_name_p is prototype */
|
||||
if (container == ECMA_STRING_CONTAINER_MAGIC_STRING)
|
||||
{
|
||||
/* ECMA-262 v5, 13.2, 14-15 */
|
||||
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) obj_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);
|
||||
|
||||
// 14
|
||||
uint32_t len;
|
||||
if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
|
||||
if (property_name_p->u.magic_string_id != LIT_MAGIC_STRING_PROTOTYPE)
|
||||
{
|
||||
cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_data_p;
|
||||
len = args_p->argument_end;
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
}
|
||||
else if (container != ECMA_STRING_CONTAINER_HEAP_UTF8_STRING
|
||||
|| property_name_p->u.utf8_string.size != (sizeof (prototype_str_p) - 1))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strncmp ((char *) (property_name_p + 1), prototype_str_p, (sizeof (prototype_str_p) - 1)) != 0)
|
||||
{
|
||||
cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_data_p;
|
||||
len = args_p->argument_end;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// 15
|
||||
ecma_property_t *length_prop_p = ecma_create_named_data_property (obj_p,
|
||||
property_name_p,
|
||||
ECMA_PROPERTY_FIXED);
|
||||
|
||||
ecma_named_data_property_assign_value (obj_p, length_prop_p, ecma_make_uint32_value (len));
|
||||
|
||||
JERRY_ASSERT (!ecma_is_property_configurable (length_prop_p));
|
||||
return length_prop_p;
|
||||
}
|
||||
|
||||
ecma_string_t *magic_string_prototype_p = ecma_get_magic_string (LIT_MAGIC_STRING_PROTOTYPE);
|
||||
/* ECMA-262 v5, 13.2, 16-18 */
|
||||
|
||||
bool is_prototype_property = ecma_compare_ecma_strings (magic_string_prototype_p, property_name_p);
|
||||
/* 16. */
|
||||
ecma_object_t *proto_object_p = ecma_op_create_object_object_noarg ();
|
||||
|
||||
ecma_deref_ecma_string (magic_string_prototype_p);
|
||||
/* 17. */
|
||||
ecma_string_t *magic_string_constructor_p = ecma_get_magic_string (LIT_MAGIC_STRING_CONSTRUCTOR);
|
||||
|
||||
if (is_prototype_property)
|
||||
{
|
||||
/* ECMA-262 v5, 13.2, 16-18 */
|
||||
ecma_property_value_t *constructor_prop_value_p;
|
||||
constructor_prop_value_p = ecma_create_named_data_property (proto_object_p,
|
||||
magic_string_constructor_p,
|
||||
ECMA_PROPERTY_CONFIGURABLE_WRITABLE,
|
||||
NULL);
|
||||
|
||||
// 16.
|
||||
ecma_object_t *proto_p = ecma_op_create_object_object_noarg ();
|
||||
constructor_prop_value_p->value = ecma_make_object_value (object_p);
|
||||
|
||||
// 17.
|
||||
ecma_string_t *magic_string_constructor_p = ecma_get_magic_string (LIT_MAGIC_STRING_CONSTRUCTOR);
|
||||
ecma_builtin_helper_def_prop (proto_p,
|
||||
magic_string_constructor_p,
|
||||
ecma_make_object_value (obj_p),
|
||||
true, /* Writable */
|
||||
false, /* Enumerable */
|
||||
true, /* Configurable */
|
||||
false); /* Failure handling */
|
||||
ecma_deref_ecma_string (magic_string_constructor_p);
|
||||
|
||||
ecma_deref_ecma_string (magic_string_constructor_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);
|
||||
|
||||
// 18.
|
||||
ecma_property_t *prototype_prop_p = ecma_create_named_data_property (obj_p,
|
||||
property_name_p,
|
||||
ECMA_PROPERTY_FLAG_WRITABLE);
|
||||
prototype_prop_value_p->value = ecma_make_object_value (proto_object_p);
|
||||
|
||||
ecma_named_data_property_assign_value (obj_p, prototype_prop_p, ecma_make_object_value (proto_p));
|
||||
ecma_deref_object (proto_object_p);
|
||||
|
||||
ecma_deref_object (proto_p);
|
||||
|
||||
JERRY_ASSERT (!ecma_is_property_configurable (prototype_prop_p));
|
||||
return prototype_prop_p;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return prototype_prop_p;
|
||||
} /* ecma_op_function_try_lazy_instantiate_property */
|
||||
|
||||
/**
|
||||
* Implementation-defined extension of [[GetOwnProperty]] ecma function object's operation
|
||||
*
|
||||
* Note:
|
||||
* The [[GetOwnProperty]] is used only for lazy property instantiation,
|
||||
* i.e. externally visible behaviour of [[GetOwnProperty]] is specification-defined
|
||||
*
|
||||
* @return pointer to a property - if it already existed
|
||||
* or was lazy instantiated in context of
|
||||
* current invocation,
|
||||
* NULL (i.e. ecma-undefined) - otherwise.
|
||||
*/
|
||||
ecma_property_t *
|
||||
ecma_op_function_object_get_own_property (ecma_object_t *obj_p, /**< the function object */
|
||||
ecma_string_t *property_name_p) /**< property name */
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION);
|
||||
|
||||
ecma_property_t *prop_p = ecma_op_general_object_get_own_property (obj_p, property_name_p);
|
||||
|
||||
if (prop_p != NULL)
|
||||
{
|
||||
return prop_p;
|
||||
}
|
||||
else if (!ecma_get_object_is_builtin (obj_p))
|
||||
{
|
||||
prop_p = ecma_op_function_try_lazy_instantiate_property (obj_p, property_name_p);
|
||||
|
||||
/*
|
||||
* Only non-configurable properties could be instantiated lazily in the function,
|
||||
* as configurable properties could be deleted and it would be incorrect
|
||||
* to reinstantiate them in the function in second time.
|
||||
*/
|
||||
JERRY_ASSERT (prop_p == NULL || !ecma_is_property_configurable (prop_p));
|
||||
}
|
||||
|
||||
return prop_p;
|
||||
} /* ecma_op_function_object_get_own_property */
|
||||
|
||||
/**
|
||||
* External function object creation operation.
|
||||
*
|
||||
|
||||
@@ -47,9 +47,6 @@ extern ecma_value_t
|
||||
ecma_op_function_call (ecma_object_t *, ecma_value_t,
|
||||
const ecma_value_t *, ecma_length_t);
|
||||
|
||||
extern ecma_property_t *
|
||||
ecma_op_function_object_get_own_property (ecma_object_t *, ecma_string_t *);
|
||||
|
||||
extern ecma_value_t
|
||||
ecma_op_function_construct (ecma_object_t *, const ecma_value_t *, ecma_length_t);
|
||||
|
||||
|
||||
@@ -104,24 +104,33 @@ ecma_op_get_value_object_base (ecma_value_t base, /**< base value */
|
||||
&& !ecma_is_lexical_environment (obj_p));
|
||||
|
||||
// 2.
|
||||
ecma_property_t *prop_p = ecma_op_object_get_property (obj_p, property_name_p);
|
||||
ecma_property_ref_t property_ref;
|
||||
ecma_property_t property = ecma_op_object_get_property (obj_p,
|
||||
property_name_p,
|
||||
&property_ref,
|
||||
ECMA_PROPERTY_GET_VALUE);
|
||||
|
||||
if (prop_p == NULL)
|
||||
if (property == ECMA_PROPERTY_TYPE_NOT_FOUND)
|
||||
{
|
||||
// 3.
|
||||
ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
|
||||
}
|
||||
else if (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA)
|
||||
else if (ECMA_PROPERTY_GET_TYPE (property) == ECMA_PROPERTY_TYPE_NAMEDDATA)
|
||||
{
|
||||
// 4.
|
||||
ret_value = ecma_copy_value (ecma_get_named_data_property_value (prop_p));
|
||||
ret_value = ecma_copy_value (property_ref.value_p->value);
|
||||
}
|
||||
else if (ECMA_PROPERTY_GET_TYPE (property) == ECMA_PROPERTY_TYPE_VIRTUAL)
|
||||
{
|
||||
// 4.
|
||||
ret_value = property_ref.virtual_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 5.
|
||||
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);
|
||||
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (property) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);
|
||||
|
||||
ecma_object_t *obj_p = ecma_get_named_accessor_property_getter (prop_p);
|
||||
ecma_object_t *obj_p = ecma_get_named_accessor_property_getter (property_ref.value_p);
|
||||
|
||||
// 6.
|
||||
if (obj_p == NULL)
|
||||
|
||||
@@ -136,7 +136,8 @@ ecma_op_create_mutable_binding (ecma_object_t *lex_env_p, /**< lexical environme
|
||||
|
||||
ecma_create_named_data_property (lex_env_p,
|
||||
name_p,
|
||||
prop_attributes);
|
||||
prop_attributes,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -187,11 +188,14 @@ ecma_op_set_mutable_binding (ecma_object_t *lex_env_p, /**< lexical environment
|
||||
|
||||
if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
|
||||
{
|
||||
ecma_property_t *property_p = ecma_get_named_data_property (lex_env_p, name_p);
|
||||
ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p);
|
||||
|
||||
if (ecma_is_property_writable (property_p))
|
||||
JERRY_ASSERT (property_p != NULL
|
||||
&& ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA);
|
||||
|
||||
if (ecma_is_property_writable (*property_p))
|
||||
{
|
||||
ecma_named_data_property_assign_value (lex_env_p, property_p, value);
|
||||
ecma_named_data_property_assign_value (lex_env_p, ECMA_PROPERTY_VALUE_PTR (property_p), value);
|
||||
}
|
||||
else if (is_strict)
|
||||
{
|
||||
@@ -242,26 +246,9 @@ ecma_op_get_binding_value (ecma_object_t *lex_env_p, /**< lexical environment */
|
||||
|
||||
if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
|
||||
{
|
||||
ecma_property_t *property_p = ecma_get_named_data_property (lex_env_p, name_p);
|
||||
ecma_property_value_t *prop_value_p = ecma_get_named_data_property (lex_env_p, name_p);
|
||||
|
||||
ecma_value_t prop_value = ecma_get_named_data_property_value (property_p);
|
||||
|
||||
/* is the binding mutable? */
|
||||
if (!ecma_is_property_writable (property_p)
|
||||
&& ecma_is_value_empty (prop_value))
|
||||
{
|
||||
/* unitialized immutable binding */
|
||||
if (is_strict)
|
||||
{
|
||||
return ecma_raise_reference_error (ECMA_ERR_MSG (""));
|
||||
}
|
||||
else
|
||||
{
|
||||
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
|
||||
}
|
||||
}
|
||||
|
||||
return ecma_copy_value (prop_value);
|
||||
return ecma_copy_value (prop_value_p->value);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -317,15 +304,15 @@ ecma_op_delete_binding (ecma_object_t *lex_env_p, /**< lexical environment */
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA);
|
||||
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA);
|
||||
|
||||
if (!ecma_is_property_configurable (prop_p))
|
||||
if (!ecma_is_property_configurable (*prop_p))
|
||||
{
|
||||
ret_val = ECMA_SIMPLE_VALUE_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_delete_property (lex_env_p, prop_p);
|
||||
ecma_delete_property (lex_env_p, ECMA_PROPERTY_VALUE_PTR (prop_p));
|
||||
|
||||
ret_val = ECMA_SIMPLE_VALUE_TRUE;
|
||||
}
|
||||
@@ -388,7 +375,8 @@ ecma_op_implicit_this_value (ecma_object_t *lex_env_p) /**< lexical environment
|
||||
*/
|
||||
void
|
||||
ecma_op_create_immutable_binding (ecma_object_t *lex_env_p, /**< lexical environment */
|
||||
ecma_string_t *name_p) /**< argument N */
|
||||
ecma_string_t *name_p, /**< argument N */
|
||||
ecma_value_t value) /**< argument V */
|
||||
{
|
||||
JERRY_ASSERT (lex_env_p != NULL
|
||||
&& ecma_is_lexical_environment (lex_env_p));
|
||||
@@ -398,39 +386,14 @@ ecma_op_create_immutable_binding (ecma_object_t *lex_env_p, /**< lexical environ
|
||||
* Warning:
|
||||
* Whether immutable bindings are deletable seems not to be defined by ECMA v5.
|
||||
*/
|
||||
ecma_property_t *prop_p = ecma_create_named_data_property (lex_env_p,
|
||||
name_p,
|
||||
ECMA_PROPERTY_FIXED);
|
||||
ecma_property_value_t *prop_value_p = ecma_create_named_data_property (lex_env_p,
|
||||
name_p,
|
||||
ECMA_PROPERTY_FIXED,
|
||||
NULL);
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_undefined (ecma_get_named_data_property_value (prop_p)));
|
||||
|
||||
ecma_set_named_data_property_value (prop_p,
|
||||
ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY));
|
||||
prop_value_p->value = ecma_copy_value_if_not_object (value);
|
||||
} /* ecma_op_create_immutable_binding */
|
||||
|
||||
/**
|
||||
* InitializeImmutableBinding operation.
|
||||
*
|
||||
* See also: ECMA-262 v5, 10.2.1
|
||||
*/
|
||||
void
|
||||
ecma_op_initialize_immutable_binding (ecma_object_t *lex_env_p, /**< lexical environment */
|
||||
ecma_string_t *name_p, /**< argument N */
|
||||
ecma_value_t value) /**< argument V */
|
||||
{
|
||||
JERRY_ASSERT (lex_env_p != NULL
|
||||
&& ecma_is_lexical_environment (lex_env_p));
|
||||
JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE);
|
||||
|
||||
ecma_property_t *prop_p = ecma_get_named_data_property (lex_env_p, name_p);
|
||||
|
||||
/* The binding must be unitialized immutable binding */
|
||||
JERRY_ASSERT (!ecma_is_property_writable (prop_p)
|
||||
&& ecma_is_value_empty (ecma_get_named_data_property_value (prop_p)));
|
||||
|
||||
ecma_named_data_property_assign_value (lex_env_p, prop_p, value);
|
||||
} /* ecma_op_initialize_immutable_binding */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
|
||||
@@ -52,8 +52,7 @@ extern ecma_value_t ecma_op_delete_binding (ecma_object_t *, ecma_string_t *);
|
||||
extern ecma_value_t ecma_op_implicit_this_value (ecma_object_t *);
|
||||
|
||||
/* ECMA-262 v5, Table 18. Additional methods of Declarative Environment Records */
|
||||
extern void ecma_op_create_immutable_binding (ecma_object_t *, ecma_string_t *);
|
||||
extern void ecma_op_initialize_immutable_binding (ecma_object_t *, ecma_string_t *, ecma_value_t);
|
||||
extern void ecma_op_create_immutable_binding (ecma_object_t *, ecma_string_t *, ecma_value_t);
|
||||
|
||||
extern ecma_object_t *ecma_op_create_global_environment (ecma_object_t *);
|
||||
|
||||
|
||||
@@ -233,10 +233,9 @@ ecma_op_create_arguments_object (ecma_object_t *func_obj_p, /**< callee function
|
||||
|
||||
if (is_strict)
|
||||
{
|
||||
ecma_op_create_immutable_binding (lex_env_p, arguments_string_p);
|
||||
ecma_op_initialize_immutable_binding (lex_env_p,
|
||||
arguments_string_p,
|
||||
ecma_make_object_value (obj_p));
|
||||
ecma_op_create_immutable_binding (lex_env_p,
|
||||
arguments_string_p,
|
||||
ecma_make_object_value (obj_p));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -293,7 +292,7 @@ ecma_arguments_update_mapped_arg_value (ecma_object_t *object_p, /**< the object
|
||||
|
||||
JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (value));
|
||||
|
||||
ecma_named_data_property_assign_value (object_p, property_p, value);
|
||||
ecma_named_data_property_assign_value (object_p, ECMA_PROPERTY_VALUE_PTR (property_p), value);
|
||||
ecma_free_value (value);
|
||||
|
||||
/* These properties cannot be cached. This is a temporary
|
||||
@@ -362,15 +361,13 @@ ecma_op_arguments_object_define_own_property (ecma_object_t *obj_p, /**< the obj
|
||||
ecma_value_t *scope_prop_p = ecma_get_internal_property (map_p, ECMA_INTERNAL_PROPERTY_SCOPE);
|
||||
ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, *scope_prop_p);
|
||||
|
||||
ecma_property_t *mapped_prop_p = ecma_op_object_get_own_property (map_p, property_name_p);
|
||||
ecma_value_t arg_name_prop_value = ecma_get_named_data_property_value (mapped_prop_p);
|
||||
|
||||
ecma_string_t *arg_name_p = ecma_get_string_from_value (arg_name_prop_value);
|
||||
ecma_property_value_t *arg_name_value_p = ecma_get_named_data_property (map_p, property_name_p);
|
||||
|
||||
completion = ecma_op_set_mutable_binding (lex_env_p,
|
||||
arg_name_p,
|
||||
ecma_get_string_from_value (arg_name_value_p->value),
|
||||
property_desc_p->value,
|
||||
true);
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_empty (completion));
|
||||
}
|
||||
|
||||
|
||||
@@ -128,27 +128,6 @@ ecma_op_create_object_object_noarg_and_set_prototype (ecma_object_t *object_prot
|
||||
return obj_p;
|
||||
} /* ecma_op_create_object_object_noarg_and_set_prototype */
|
||||
|
||||
/**
|
||||
* [[GetOwnProperty]] ecma general object's operation
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
|
||||
* ECMA-262 v5, 8.12.2
|
||||
*
|
||||
* @return pointer to a property - if it exists,
|
||||
* NULL (i.e. ecma-undefined) - otherwise.
|
||||
*/
|
||||
ecma_property_t *
|
||||
ecma_op_general_object_get_own_property (ecma_object_t *obj_p, /**< the object */
|
||||
ecma_string_t *property_name_p) /**< property name */
|
||||
{
|
||||
JERRY_ASSERT (obj_p != NULL
|
||||
&& !ecma_is_lexical_environment (obj_p));
|
||||
JERRY_ASSERT (property_name_p != NULL);
|
||||
|
||||
return ecma_find_named_property (obj_p, property_name_p);
|
||||
} /* ecma_op_general_object_get_own_property */
|
||||
|
||||
/**
|
||||
* [[Delete]] ecma general object's operation
|
||||
*
|
||||
@@ -169,19 +148,24 @@ ecma_op_general_object_delete (ecma_object_t *obj_p, /**< the object */
|
||||
JERRY_ASSERT (property_name_p != NULL);
|
||||
|
||||
// 1.
|
||||
ecma_property_t *desc_p = ecma_op_object_get_own_property (obj_p, property_name_p);
|
||||
ecma_property_ref_t property_ref;
|
||||
|
||||
ecma_property_t property = ecma_op_object_get_own_property (obj_p,
|
||||
property_name_p,
|
||||
&property_ref,
|
||||
ECMA_PROPERTY_GET_NO_OPTIONS);
|
||||
|
||||
// 2.
|
||||
if (desc_p == NULL)
|
||||
if (property == ECMA_PROPERTY_TYPE_NOT_FOUND)
|
||||
{
|
||||
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
|
||||
}
|
||||
|
||||
// 3.
|
||||
if (ecma_is_property_configurable (desc_p))
|
||||
if (ecma_is_property_configurable (property))
|
||||
{
|
||||
// a.
|
||||
ecma_delete_property (obj_p, desc_p);
|
||||
ecma_delete_property (obj_p, property_ref.value_p);
|
||||
|
||||
// b.
|
||||
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
|
||||
@@ -330,9 +314,14 @@ ecma_op_general_object_define_own_property (ecma_object_t *obj_p, /**< the objec
|
||||
JERRY_ASSERT (property_desc_p->is_writable_defined || !property_desc_p->is_writable);
|
||||
|
||||
// 1.
|
||||
ecma_property_t *current_p = ecma_op_object_get_own_property (obj_p, property_name_p);
|
||||
ecma_property_ref_t property_ref;
|
||||
|
||||
if (current_p == NULL)
|
||||
ecma_property_t current_prop = ecma_op_object_get_own_property (obj_p,
|
||||
property_name_p,
|
||||
&property_ref,
|
||||
ECMA_PROPERTY_GET_VALUE);
|
||||
|
||||
if (current_prop == ECMA_PROPERTY_TYPE_NOT_FOUND)
|
||||
{
|
||||
// 3.
|
||||
if (!ecma_get_object_extensible (obj_p))
|
||||
@@ -365,14 +354,15 @@ ecma_op_general_object_define_own_property (ecma_object_t *obj_p, /**< the objec
|
||||
prop_attributes = (uint8_t) (prop_attributes | ECMA_PROPERTY_FLAG_WRITABLE);
|
||||
}
|
||||
|
||||
ecma_property_t *new_prop_p = ecma_create_named_data_property (obj_p,
|
||||
property_name_p,
|
||||
prop_attributes);
|
||||
ecma_property_value_t *new_prop_value_p = ecma_create_named_data_property (obj_p,
|
||||
property_name_p,
|
||||
prop_attributes,
|
||||
NULL);
|
||||
|
||||
JERRY_ASSERT (property_desc_p->is_value_defined
|
||||
|| ecma_is_value_undefined (property_desc_p->value));
|
||||
|
||||
ecma_named_data_property_assign_value (obj_p, new_prop_p, property_desc_p->value);
|
||||
new_prop_value_p->value = ecma_copy_value_if_not_object (property_desc_p->value);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -400,21 +390,45 @@ ecma_op_general_object_define_own_property (ecma_object_t *obj_p, /**< the objec
|
||||
}
|
||||
|
||||
// 6.
|
||||
ecma_property_types_t current_property_type = ECMA_PROPERTY_GET_TYPE (current_p);
|
||||
const bool is_current_configurable = ecma_is_property_configurable (current_p);
|
||||
ecma_property_types_t current_property_type = ECMA_PROPERTY_GET_TYPE (current_prop);
|
||||
const bool is_current_configurable = ecma_is_property_configurable (current_prop);
|
||||
|
||||
JERRY_ASSERT (current_property_type == ECMA_PROPERTY_TYPE_NAMEDDATA
|
||||
|| current_property_type == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);
|
||||
|| current_property_type == ECMA_PROPERTY_TYPE_NAMEDACCESSOR
|
||||
|| current_property_type == ECMA_PROPERTY_TYPE_VIRTUAL);
|
||||
|
||||
// 7. a., b.
|
||||
if (!is_current_configurable
|
||||
&& (property_desc_p->is_configurable
|
||||
|| (property_desc_p->is_enumerable_defined
|
||||
&& (property_desc_p->is_enumerable != ecma_is_property_enumerable (current_p)))))
|
||||
&& (property_desc_p->is_enumerable != ecma_is_property_enumerable (current_prop)))))
|
||||
{
|
||||
if (current_property_type == ECMA_PROPERTY_TYPE_VIRTUAL)
|
||||
{
|
||||
ecma_free_value (property_ref.virtual_value);
|
||||
}
|
||||
return ecma_reject (is_throw);
|
||||
}
|
||||
|
||||
if (current_property_type == ECMA_PROPERTY_TYPE_VIRTUAL)
|
||||
{
|
||||
JERRY_ASSERT (!is_current_configurable && !ecma_is_property_writable (current_prop));
|
||||
|
||||
ecma_value_t result = ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
|
||||
|
||||
if (property_desc_type == ECMA_PROPERTY_TYPE_NAMEDACCESSOR
|
||||
|| property_desc_p->is_writable
|
||||
|| (property_desc_p->is_value_defined
|
||||
&& !ecma_op_same_value (property_desc_p->value,
|
||||
property_ref.virtual_value)))
|
||||
{
|
||||
result = ecma_reject (is_throw);
|
||||
}
|
||||
|
||||
ecma_free_value (property_ref.virtual_value);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 8.
|
||||
if (property_desc_type == ECMA_PROPERTY_TYPE_GENERIC)
|
||||
{
|
||||
@@ -428,11 +442,11 @@ ecma_op_general_object_define_own_property (ecma_object_t *obj_p, /**< the objec
|
||||
if (property_desc_type == ECMA_PROPERTY_TYPE_NAMEDDATA)
|
||||
{
|
||||
// 10. a. i. & ii.
|
||||
if (!ecma_is_property_writable (current_p)
|
||||
if (!ecma_is_property_writable (current_prop)
|
||||
&& (property_desc_p->is_writable
|
||||
|| (property_desc_p->is_value_defined
|
||||
&& !ecma_op_same_value (property_desc_p->value,
|
||||
ecma_get_named_data_property_value (current_p)))))
|
||||
property_ref.value_p->value))))
|
||||
{
|
||||
return ecma_reject (is_throw);
|
||||
}
|
||||
@@ -443,9 +457,9 @@ ecma_op_general_object_define_own_property (ecma_object_t *obj_p, /**< the objec
|
||||
|
||||
// a.
|
||||
if ((property_desc_p->is_get_defined
|
||||
&& property_desc_p->get_p != ecma_get_named_accessor_property_getter (current_p))
|
||||
&& property_desc_p->get_p != ecma_get_named_accessor_property_getter (property_ref.value_p))
|
||||
|| (property_desc_p->is_set_defined
|
||||
&& property_desc_p->set_p != ecma_get_named_accessor_property_setter (current_p)))
|
||||
&& property_desc_p->set_p != ecma_get_named_accessor_property_setter (property_ref.value_p)))
|
||||
{
|
||||
// i., ii.
|
||||
return ecma_reject (is_throw);
|
||||
@@ -466,41 +480,46 @@ ecma_op_general_object_define_own_property (ecma_object_t *obj_p, /**< the objec
|
||||
* the fields of current_p if this code path is performance critical. */
|
||||
uint8_t prop_attributes = ECMA_PROPERTY_FLAG_CONFIGURABLE;
|
||||
|
||||
if (ecma_is_property_enumerable (current_p))
|
||||
if (ecma_is_property_enumerable (current_prop))
|
||||
{
|
||||
prop_attributes = (uint8_t) (prop_attributes | ECMA_PROPERTY_FLAG_ENUMERABLE);
|
||||
}
|
||||
|
||||
ecma_delete_property (obj_p, current_p);
|
||||
ecma_delete_property (obj_p, property_ref.value_p);
|
||||
|
||||
if (property_desc_type == ECMA_PROPERTY_TYPE_NAMEDACCESSOR)
|
||||
{
|
||||
// b.
|
||||
|
||||
current_p = ecma_create_named_accessor_property (obj_p,
|
||||
property_name_p,
|
||||
NULL,
|
||||
NULL,
|
||||
prop_attributes);
|
||||
property_ref.value_p = ecma_create_named_accessor_property (obj_p,
|
||||
property_name_p,
|
||||
NULL,
|
||||
NULL,
|
||||
prop_attributes);
|
||||
}
|
||||
else
|
||||
{
|
||||
// c.
|
||||
|
||||
current_p = ecma_create_named_data_property (obj_p,
|
||||
property_name_p,
|
||||
prop_attributes);
|
||||
property_ref.value_p = ecma_create_named_data_property (obj_p,
|
||||
property_name_p,
|
||||
prop_attributes,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
ecma_property_t *current_p = ecma_find_named_property (obj_p, property_name_p);
|
||||
|
||||
JERRY_ASSERT (ECMA_PROPERTY_VALUE_PTR (current_p) == property_ref.value_p);
|
||||
|
||||
// 12.
|
||||
if (property_desc_type == ECMA_PROPERTY_TYPE_NAMEDDATA)
|
||||
{
|
||||
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (current_p) == ECMA_PROPERTY_TYPE_NAMEDDATA);
|
||||
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*current_p) == ECMA_PROPERTY_TYPE_NAMEDDATA);
|
||||
|
||||
if (property_desc_p->is_value_defined)
|
||||
{
|
||||
ecma_named_data_property_assign_value (obj_p, current_p, property_desc_p->value);
|
||||
ecma_named_data_property_assign_value (obj_p, property_ref.value_p, property_desc_p->value);
|
||||
}
|
||||
|
||||
if (property_desc_p->is_writable_defined)
|
||||
@@ -510,16 +529,16 @@ ecma_op_general_object_define_own_property (ecma_object_t *obj_p, /**< the objec
|
||||
}
|
||||
else if (property_desc_type == ECMA_PROPERTY_TYPE_NAMEDACCESSOR)
|
||||
{
|
||||
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (current_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);
|
||||
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*current_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);
|
||||
|
||||
if (property_desc_p->is_get_defined)
|
||||
{
|
||||
ecma_set_named_accessor_property_getter (obj_p, current_p, property_desc_p->get_p);
|
||||
ecma_set_named_accessor_property_getter (obj_p, property_ref.value_p, property_desc_p->get_p);
|
||||
}
|
||||
|
||||
if (property_desc_p->is_set_defined)
|
||||
{
|
||||
ecma_set_named_accessor_property_setter (obj_p, current_p, property_desc_p->set_p);
|
||||
ecma_set_named_accessor_property_setter (obj_p, property_ref.value_p, property_desc_p->set_p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@ extern ecma_object_t *ecma_op_create_object_object_noarg (void);
|
||||
extern ecma_value_t ecma_op_create_object_object_arg (ecma_value_t);
|
||||
extern ecma_object_t *ecma_op_create_object_object_noarg_and_set_prototype (ecma_object_t *);
|
||||
|
||||
extern ecma_property_t *ecma_op_general_object_get_own_property (ecma_object_t *, ecma_string_t *);
|
||||
extern ecma_value_t ecma_op_general_object_delete (ecma_object_t *, ecma_string_t *, bool);
|
||||
extern ecma_value_t ecma_op_general_object_default_value (ecma_object_t *, ecma_preferred_type_hint_t);
|
||||
extern ecma_value_t ecma_op_general_object_define_own_property (ecma_object_t *, ecma_string_t *,
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "ecma-builtins.h"
|
||||
#include "ecma-builtin-helpers.h"
|
||||
#include "ecma-exceptions.h"
|
||||
#include "ecma-gc.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-function-object.h"
|
||||
#include "ecma-lcache.h"
|
||||
@@ -57,76 +58,6 @@
|
||||
#define JERRY_ASSERT_OBJECT_TYPE_IS_VALID(type)
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
/**
|
||||
* Long path for ecma_op_object_get_own_property
|
||||
*
|
||||
* @return pointer to a property - if it exists,
|
||||
* NULL (i.e. ecma-undefined) - otherwise.
|
||||
*/
|
||||
static ecma_property_t * __attr_noinline___
|
||||
ecma_op_object_get_own_property_longpath (ecma_object_t *obj_p, /**< the object */
|
||||
ecma_string_t *property_name_p) /**< property name */
|
||||
{
|
||||
const ecma_object_type_t type = ecma_get_object_type (obj_p);
|
||||
const bool is_builtin = ecma_get_object_is_builtin (obj_p);
|
||||
|
||||
ecma_property_t *prop_p = NULL;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case ECMA_OBJECT_TYPE_GENERAL:
|
||||
case ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION:
|
||||
case ECMA_OBJECT_TYPE_ARRAY:
|
||||
case ECMA_OBJECT_TYPE_BOUND_FUNCTION:
|
||||
{
|
||||
prop_p = ecma_op_general_object_get_own_property (obj_p, property_name_p);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ECMA_OBJECT_TYPE_FUNCTION:
|
||||
{
|
||||
prop_p = ecma_op_function_object_get_own_property (obj_p, property_name_p);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ECMA_OBJECT_TYPE_STRING:
|
||||
{
|
||||
prop_p = ecma_op_string_object_get_own_property (obj_p, property_name_p);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ECMA_OBJECT_TYPE_ARGUMENTS:
|
||||
{
|
||||
prop_p = ecma_op_general_object_get_own_property (obj_p, property_name_p);
|
||||
|
||||
if (prop_p != NULL)
|
||||
{
|
||||
ecma_arguments_update_mapped_arg_value (obj_p, property_name_p, prop_p);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
JERRY_UNREACHABLE ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (unlikely (prop_p == NULL))
|
||||
{
|
||||
if (is_builtin)
|
||||
{
|
||||
prop_p = ecma_builtin_try_to_instantiate_property (obj_p, property_name_p);
|
||||
}
|
||||
}
|
||||
|
||||
return prop_p;
|
||||
} /* ecma_op_object_get_own_property_longpath */
|
||||
|
||||
/**
|
||||
* [[GetOwnProperty]] ecma object's operation
|
||||
*
|
||||
@@ -136,22 +67,123 @@ ecma_op_object_get_own_property_longpath (ecma_object_t *obj_p, /**< the object
|
||||
* @return pointer to a property - if it exists,
|
||||
* NULL (i.e. ecma-undefined) - otherwise.
|
||||
*/
|
||||
ecma_property_t *
|
||||
ecma_op_object_get_own_property (ecma_object_t *obj_p, /**< the object */
|
||||
ecma_string_t *property_name_p) /**< property name */
|
||||
ecma_property_t
|
||||
ecma_op_object_get_own_property (ecma_object_t *object_p, /**< the object */
|
||||
ecma_string_t *property_name_p, /**< property name */
|
||||
ecma_property_ref_t *property_ref_p, /**< property reference */
|
||||
uint32_t options) /**< option bits */
|
||||
{
|
||||
JERRY_ASSERT (obj_p != NULL
|
||||
&& !ecma_is_lexical_environment (obj_p));
|
||||
JERRY_ASSERT (object_p != NULL
|
||||
&& !ecma_is_lexical_environment (object_p));
|
||||
JERRY_ASSERT (property_name_p != NULL);
|
||||
|
||||
ecma_property_t *prop_p = ecma_lcache_lookup (obj_p, property_name_p);
|
||||
ecma_object_type_t type = ecma_get_object_type (object_p);
|
||||
|
||||
if (likely (prop_p != NULL))
|
||||
ecma_property_t *property_p = ecma_find_named_property (object_p, property_name_p);
|
||||
|
||||
if (property_p == NULL)
|
||||
{
|
||||
return prop_p;
|
||||
if (type == ECMA_OBJECT_TYPE_STRING)
|
||||
{
|
||||
uint32_t index;
|
||||
|
||||
if (ecma_string_get_array_index (property_name_p, &index))
|
||||
{
|
||||
ecma_value_t *prim_value_p = ecma_get_internal_property (object_p,
|
||||
ECMA_INTERNAL_PROPERTY_ECMA_VALUE);
|
||||
|
||||
ecma_string_t *prim_value_str_p = ecma_get_string_from_value (*prim_value_p);
|
||||
|
||||
if (index < ecma_string_get_length (prim_value_str_p))
|
||||
{
|
||||
if (options & ECMA_PROPERTY_GET_VALUE)
|
||||
{
|
||||
ecma_char_t char_at_idx = ecma_string_get_char_at_pos (prim_value_str_p, index);
|
||||
ecma_string_t *char_str_p = ecma_new_ecma_string_from_code_unit (char_at_idx);
|
||||
property_ref_p->virtual_value = ecma_make_string_value (char_str_p);
|
||||
}
|
||||
|
||||
return ECMA_PROPERTY_FLAG_ENUMERABLE | ECMA_PROPERTY_TYPE_VIRTUAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ecma_get_object_is_builtin (object_p))
|
||||
{
|
||||
property_p = ecma_builtin_try_to_instantiate_property (object_p, property_name_p);
|
||||
}
|
||||
else if (type == ECMA_OBJECT_TYPE_FUNCTION)
|
||||
{
|
||||
if (ecma_string_is_length (property_name_p))
|
||||
{
|
||||
if (options & ECMA_PROPERTY_GET_VALUE)
|
||||
{
|
||||
/* Get length virtual property. */
|
||||
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);
|
||||
|
||||
uint32_t len;
|
||||
if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
|
||||
{
|
||||
cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_data_p;
|
||||
len = args_p->argument_end;
|
||||
}
|
||||
else
|
||||
{
|
||||
cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_data_p;
|
||||
len = args_p->argument_end;
|
||||
}
|
||||
|
||||
property_ref_p->virtual_value = ecma_make_uint32_value (len);
|
||||
}
|
||||
|
||||
return ECMA_PROPERTY_TYPE_VIRTUAL;
|
||||
}
|
||||
|
||||
/* Get prototype physical property. */
|
||||
property_p = ecma_op_function_try_lazy_instantiate_property (object_p, property_name_p);
|
||||
}
|
||||
|
||||
if (property_p == NULL)
|
||||
{
|
||||
return ECMA_PROPERTY_TYPE_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
else if (type == ECMA_OBJECT_TYPE_ARGUMENTS)
|
||||
{
|
||||
ecma_value_t *map_prop_p = ecma_get_internal_property (object_p, ECMA_INTERNAL_PROPERTY_PARAMETERS_MAP);
|
||||
ecma_object_t *map_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, *map_prop_p);
|
||||
|
||||
ecma_value_t arg_name = ecma_op_object_find_own (*map_prop_p, map_p, property_name_p);
|
||||
|
||||
if (ecma_is_value_found (arg_name))
|
||||
{
|
||||
ecma_value_t *scope_prop_p = ecma_get_internal_property (map_p, ECMA_INTERNAL_PROPERTY_SCOPE);
|
||||
ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, *scope_prop_p);
|
||||
|
||||
JERRY_ASSERT (lex_env_p != NULL
|
||||
&& ecma_is_lexical_environment (lex_env_p));
|
||||
|
||||
ecma_string_t *arg_name_p = ecma_get_string_from_value (arg_name);
|
||||
ecma_value_t binding_value = ecma_op_get_binding_value (lex_env_p, arg_name_p, true);
|
||||
ecma_deref_ecma_string (arg_name_p);
|
||||
|
||||
ecma_named_data_property_assign_value (object_p,
|
||||
ECMA_PROPERTY_VALUE_PTR (property_p),
|
||||
binding_value);
|
||||
ecma_free_value (binding_value);
|
||||
}
|
||||
}
|
||||
|
||||
return ecma_op_object_get_own_property_longpath (obj_p, property_name_p);
|
||||
if (property_ref_p != NULL)
|
||||
{
|
||||
property_ref_p->value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
|
||||
}
|
||||
|
||||
return *property_p;
|
||||
} /* ecma_op_object_get_own_property */
|
||||
|
||||
/**
|
||||
@@ -163,20 +195,25 @@ ecma_op_object_get_own_property (ecma_object_t *obj_p, /**< the object */
|
||||
* @return pointer to a property - if it exists,
|
||||
* NULL (i.e. ecma-undefined) - otherwise.
|
||||
*/
|
||||
ecma_property_t *
|
||||
ecma_property_t
|
||||
ecma_op_object_get_property (ecma_object_t *object_p, /**< the object */
|
||||
ecma_string_t *property_name_p) /**< property name */
|
||||
ecma_string_t *property_name_p, /**< property name */
|
||||
ecma_property_ref_t *property_ref_p, /**< property reference */
|
||||
uint32_t options) /**< option bits */
|
||||
{
|
||||
/* Circular reference is possible in JavaScript and testing it is complicated. */
|
||||
int max_depth = 128;
|
||||
|
||||
do
|
||||
{
|
||||
ecma_property_t *property_p = ecma_op_object_get_own_property (object_p, property_name_p);
|
||||
ecma_property_t property = ecma_op_object_get_own_property (object_p,
|
||||
property_name_p,
|
||||
property_ref_p,
|
||||
options);
|
||||
|
||||
if (property_p != NULL)
|
||||
if (property != ECMA_PROPERTY_TYPE_NOT_FOUND)
|
||||
{
|
||||
return property_p;
|
||||
return property;
|
||||
}
|
||||
|
||||
if (--max_depth == 0)
|
||||
@@ -188,7 +225,7 @@ ecma_op_object_get_property (ecma_object_t *object_p, /**< the object */
|
||||
}
|
||||
while (object_p != NULL);
|
||||
|
||||
return NULL;
|
||||
return ECMA_PROPERTY_TYPE_NOT_FOUND;
|
||||
} /* ecma_op_object_get_property */
|
||||
|
||||
/**
|
||||
@@ -201,7 +238,11 @@ inline bool __attr_always_inline___
|
||||
ecma_op_object_has_own_property (ecma_object_t *object_p, /**< the object */
|
||||
ecma_string_t *property_name_p) /**< property name */
|
||||
{
|
||||
return ecma_op_object_get_own_property (object_p, property_name_p) != NULL;
|
||||
ecma_property_t property = ecma_op_object_get_own_property (object_p,
|
||||
property_name_p,
|
||||
NULL,
|
||||
ECMA_PROPERTY_GET_NO_OPTIONS);
|
||||
return property != ECMA_PROPERTY_TYPE_NOT_FOUND;
|
||||
} /* ecma_op_object_has_own_property */
|
||||
|
||||
/**
|
||||
@@ -214,7 +255,11 @@ inline bool __attr_always_inline___
|
||||
ecma_op_object_has_property (ecma_object_t *object_p, /**< the object */
|
||||
ecma_string_t *property_name_p) /**< property name */
|
||||
{
|
||||
return ecma_op_object_get_property (object_p, property_name_p) != NULL;
|
||||
ecma_property_t property = ecma_op_object_get_property (object_p,
|
||||
property_name_p,
|
||||
NULL,
|
||||
ECMA_PROPERTY_GET_NO_OPTIONS);
|
||||
return property != ECMA_PROPERTY_TYPE_NOT_FOUND;
|
||||
} /* ecma_op_object_has_property */
|
||||
|
||||
/**
|
||||
@@ -322,12 +367,16 @@ ecma_op_object_find_own (ecma_value_t base_value, /**< base value */
|
||||
}
|
||||
}
|
||||
|
||||
if (ECMA_PROPERTY_GET_TYPE (property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA)
|
||||
ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
|
||||
|
||||
if (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA)
|
||||
{
|
||||
return ecma_fast_copy_value (ecma_get_named_data_property_value (property_p));
|
||||
return ecma_fast_copy_value (prop_value_p->value);
|
||||
}
|
||||
|
||||
ecma_object_t *getter_p = ecma_get_named_accessor_property_getter (property_p);
|
||||
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);
|
||||
|
||||
ecma_object_t *getter_p = ecma_get_named_accessor_property_getter (prop_value_p);
|
||||
|
||||
if (getter_p == NULL)
|
||||
{
|
||||
@@ -387,15 +436,22 @@ inline ecma_value_t __attr_always_inline___
|
||||
ecma_op_object_get_own_data_prop (ecma_object_t *object_p, /**< the object */
|
||||
ecma_string_t *property_name_p) /**< property name */
|
||||
{
|
||||
ecma_value_t result = ecma_op_object_find_own (ecma_make_object_value (object_p),
|
||||
object_p,
|
||||
property_name_p);
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
ecma_property_t *property_p = ecma_op_object_get_own_property (object_p, property_name_p);
|
||||
/* Because ecma_op_object_find_own might create a property
|
||||
* this check is executed after the function return. */
|
||||
ecma_property_t *property_p = ecma_find_named_property (object_p,
|
||||
property_name_p);
|
||||
|
||||
JERRY_ASSERT (property_p != NULL
|
||||
&& ECMA_PROPERTY_GET_TYPE (property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA
|
||||
&& !ecma_is_property_configurable (property_p));
|
||||
&& ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA
|
||||
&& !ecma_is_property_configurable (*property_p));
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
return ecma_op_object_find (object_p, property_name_p);
|
||||
return result;
|
||||
} /* ecma_op_object_get_own_data_prop */
|
||||
|
||||
/**
|
||||
@@ -411,14 +467,29 @@ ecma_value_t
|
||||
ecma_op_object_get (ecma_object_t *object_p, /**< the object */
|
||||
ecma_string_t *property_name_p) /**< property name */
|
||||
{
|
||||
ecma_value_t value = ecma_op_object_find (object_p, property_name_p);
|
||||
/* Circular reference is possible in JavaScript and testing it is complicated. */
|
||||
int max_depth = 128;
|
||||
|
||||
if (!ecma_is_value_found (value))
|
||||
ecma_value_t base_value = ecma_make_object_value (object_p);
|
||||
do
|
||||
{
|
||||
value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
|
||||
}
|
||||
ecma_value_t value = ecma_op_object_find_own (base_value, object_p, property_name_p);
|
||||
|
||||
return value;
|
||||
if (ecma_is_value_found (value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
if (--max_depth == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
object_p = ecma_get_object_prototype (object_p);
|
||||
}
|
||||
while (object_p != NULL);
|
||||
|
||||
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
|
||||
} /* ecma_op_object_get */
|
||||
|
||||
/**
|
||||
@@ -514,9 +585,9 @@ ecma_op_object_put (ecma_object_t *object_p, /**< the object */
|
||||
|
||||
if (property_p != NULL)
|
||||
{
|
||||
if (ECMA_PROPERTY_GET_TYPE (property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA)
|
||||
if (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA)
|
||||
{
|
||||
if (ecma_is_property_writable (property_p))
|
||||
if (ecma_is_property_writable (*property_p))
|
||||
{
|
||||
if (type == ECMA_OBJECT_TYPE_ARRAY && ecma_string_is_length (property_name_p))
|
||||
{
|
||||
@@ -534,15 +605,17 @@ ecma_op_object_put (ecma_object_t *object_p, /**< the object */
|
||||
|
||||
/* There is no need for special casing arrays here because changing the
|
||||
* value of an existing property never changes the length of an array. */
|
||||
ecma_named_data_property_assign_value (object_p, property_p, value);
|
||||
ecma_named_data_property_assign_value (object_p,
|
||||
ECMA_PROPERTY_VALUE_PTR (property_p),
|
||||
value);
|
||||
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);
|
||||
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);
|
||||
|
||||
setter_p = ecma_get_named_accessor_property_setter (property_p);
|
||||
setter_p = ecma_get_named_accessor_property_setter (ECMA_PROPERTY_VALUE_PTR (property_p));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -552,18 +625,23 @@ ecma_op_object_put (ecma_object_t *object_p, /**< the object */
|
||||
|
||||
if (proto_p != NULL)
|
||||
{
|
||||
ecma_property_t *inherited_property_p = ecma_op_object_get_property (proto_p, property_name_p);
|
||||
ecma_property_ref_t property_ref;
|
||||
|
||||
if (inherited_property_p != NULL)
|
||||
ecma_property_t inherited_property = ecma_op_object_get_property (proto_p,
|
||||
property_name_p,
|
||||
&property_ref,
|
||||
ECMA_PROPERTY_GET_NO_OPTIONS);
|
||||
|
||||
if (inherited_property != ECMA_PROPERTY_TYPE_NOT_FOUND)
|
||||
{
|
||||
if (ECMA_PROPERTY_GET_TYPE (inherited_property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR)
|
||||
if (ECMA_PROPERTY_GET_TYPE (inherited_property) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR)
|
||||
{
|
||||
setter_p = ecma_get_named_accessor_property_setter (inherited_property_p);
|
||||
setter_p = ecma_get_named_accessor_property_setter (property_ref.value_p);
|
||||
create_new_property = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
create_new_property = ecma_is_property_writable (inherited_property_p);
|
||||
create_new_property = ecma_is_property_writable (inherited_property);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -597,33 +675,34 @@ ecma_op_object_put (ecma_object_t *object_p, /**< the object */
|
||||
ecma_string_t magic_string_length;
|
||||
ecma_init_ecma_length_string (&magic_string_length);
|
||||
|
||||
ecma_property_t *len_prop_p = ecma_op_object_get_own_property (object_p, &magic_string_length);
|
||||
ecma_property_t *len_prop_p = ecma_find_named_property (object_p, &magic_string_length);
|
||||
|
||||
JERRY_ASSERT (len_prop_p != NULL
|
||||
&& ECMA_PROPERTY_GET_TYPE (len_prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA);
|
||||
&& ECMA_PROPERTY_GET_TYPE (*len_prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA);
|
||||
|
||||
uint32_t old_len = ecma_get_uint32_from_value (ecma_get_named_data_property_value (len_prop_p));
|
||||
ecma_property_value_t *len_prop_value_p = ECMA_PROPERTY_VALUE_PTR (len_prop_p);
|
||||
uint32_t old_len = ecma_get_uint32_from_value (len_prop_value_p->value);
|
||||
|
||||
if (index < UINT32_MAX
|
||||
&& index >= old_len)
|
||||
{
|
||||
if (!ecma_is_property_writable (len_prop_p))
|
||||
if (!ecma_is_property_writable (*len_prop_p))
|
||||
{
|
||||
return ecma_reject (is_throw);
|
||||
}
|
||||
|
||||
ecma_property_value_t *len_prop_value_p = ECMA_PROPERTY_VALUE_PTR (len_prop_p);
|
||||
ecma_value_assign_uint32 (&len_prop_value_p->value, index + 1);
|
||||
}
|
||||
}
|
||||
|
||||
ecma_property_t *new_prop_p;
|
||||
new_prop_p = ecma_create_named_data_property (object_p,
|
||||
property_name_p,
|
||||
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE);
|
||||
ecma_property_value_t *new_prop_value_p;
|
||||
new_prop_value_p = ecma_create_named_data_property (object_p,
|
||||
property_name_p,
|
||||
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE,
|
||||
NULL);
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_undefined (ecma_get_named_data_property_value (new_prop_p)));
|
||||
ecma_set_named_data_property_value (new_prop_p, ecma_copy_value_if_not_object (value));
|
||||
JERRY_ASSERT (ecma_is_value_undefined (new_prop_value_p->value));
|
||||
new_prop_value_p->value = ecma_copy_value_if_not_object (value);
|
||||
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
|
||||
}
|
||||
}
|
||||
@@ -796,6 +875,83 @@ ecma_op_object_define_own_property (ecma_object_t *obj_p, /**< the object */
|
||||
}
|
||||
} /* ecma_op_object_define_own_property */
|
||||
|
||||
/**
|
||||
* Get property descriptor from specified property
|
||||
*
|
||||
* depending on the property type the following fields are set:
|
||||
* - for named data properties: { [Value], [Writable], [Enumerable], [Configurable] };
|
||||
* - for named accessor properties: { [Get] - if defined,
|
||||
* [Set] - if defined,
|
||||
* [Enumerable], [Configurable]
|
||||
* }.
|
||||
*
|
||||
* @return true if property found
|
||||
* false otherwise
|
||||
*/
|
||||
bool
|
||||
ecma_op_object_get_own_property_descriptor (ecma_object_t *object_p, /**< the object */
|
||||
ecma_string_t *property_name_p, /**< property name */
|
||||
ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */
|
||||
{
|
||||
ecma_property_ref_t property_ref;
|
||||
|
||||
ecma_property_t property = ecma_op_object_get_own_property (object_p,
|
||||
property_name_p,
|
||||
&property_ref,
|
||||
ECMA_PROPERTY_GET_VALUE);
|
||||
|
||||
if (property == ECMA_PROPERTY_TYPE_NOT_FOUND)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
*prop_desc_p = ecma_make_empty_property_descriptor ();
|
||||
|
||||
prop_desc_p->is_enumerable = ecma_is_property_enumerable (property);
|
||||
prop_desc_p->is_enumerable_defined = true;
|
||||
prop_desc_p->is_configurable = ecma_is_property_configurable (property);
|
||||
prop_desc_p->is_configurable_defined = true;
|
||||
|
||||
ecma_property_types_t type = ECMA_PROPERTY_GET_TYPE (property);
|
||||
|
||||
if (type != ECMA_PROPERTY_TYPE_NAMEDACCESSOR)
|
||||
{
|
||||
if (type == ECMA_PROPERTY_TYPE_NAMEDDATA)
|
||||
{
|
||||
prop_desc_p->value = ecma_copy_value (property_ref.value_p->value);
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (type == ECMA_PROPERTY_TYPE_VIRTUAL);
|
||||
prop_desc_p->value = property_ref.virtual_value;
|
||||
}
|
||||
|
||||
prop_desc_p->is_value_defined = true;
|
||||
prop_desc_p->is_writable = ecma_is_property_writable (property);
|
||||
prop_desc_p->is_writable_defined = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
prop_desc_p->get_p = ecma_get_named_accessor_property_getter (property_ref.value_p);
|
||||
prop_desc_p->is_get_defined = true;
|
||||
|
||||
if (prop_desc_p->get_p != NULL)
|
||||
{
|
||||
ecma_ref_object (prop_desc_p->get_p);
|
||||
}
|
||||
|
||||
prop_desc_p->set_p = ecma_get_named_accessor_property_setter (property_ref.value_p);
|
||||
prop_desc_p->is_set_defined = true;
|
||||
|
||||
if (prop_desc_p->set_p != NULL)
|
||||
{
|
||||
ecma_ref_object (prop_desc_p->set_p);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} /* ecma_op_object_get_own_property_descriptor */
|
||||
|
||||
/**
|
||||
* [[HasInstance]] ecma object's operation
|
||||
*
|
||||
@@ -976,7 +1132,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */
|
||||
ecma_property_header_t *prop_iter_p = ecma_get_property_list (prototype_chain_iter_p);
|
||||
|
||||
if (prop_iter_p != NULL
|
||||
&& ECMA_PROPERTY_GET_TYPE (prop_iter_p->types + 0) == ECMA_PROPERTY_TYPE_HASHMAP)
|
||||
&& ECMA_PROPERTY_GET_TYPE (prop_iter_p->types[0]) == ECMA_PROPERTY_TYPE_HASHMAP)
|
||||
{
|
||||
prop_iter_p = ECMA_GET_POINTER (ecma_property_header_t,
|
||||
prop_iter_p->next_property_cp);
|
||||
@@ -990,13 +1146,13 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */
|
||||
{
|
||||
ecma_property_t *property_p = prop_iter_p->types + i;
|
||||
|
||||
if (ECMA_PROPERTY_GET_TYPE (property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA
|
||||
|| ECMA_PROPERTY_GET_TYPE (property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR)
|
||||
if (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA
|
||||
|| ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR)
|
||||
{
|
||||
ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p;
|
||||
ecma_string_t *name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_pair_p->names_cp[i]);
|
||||
|
||||
if (!(is_enumerable_only && !ecma_is_property_enumerable (property_p)))
|
||||
if (!(is_enumerable_only && !ecma_is_property_enumerable (*property_p)))
|
||||
{
|
||||
uint8_t hash = (uint8_t) name_p->hash;
|
||||
uint32_t bitmap_row = (uint32_t) (hash / bitmap_row_size);
|
||||
@@ -1031,7 +1187,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (is_enumerable_only && !ecma_is_property_enumerable (property_p));
|
||||
JERRY_ASSERT (is_enumerable_only && !ecma_is_property_enumerable (*property_p));
|
||||
|
||||
ecma_append_to_values_collection (skipped_non_enumerable_p,
|
||||
ecma_make_string_value (name_p),
|
||||
|
||||
@@ -26,8 +26,10 @@
|
||||
* @{
|
||||
*/
|
||||
|
||||
extern ecma_property_t *ecma_op_object_get_own_property (ecma_object_t *, ecma_string_t *);
|
||||
extern ecma_property_t *ecma_op_object_get_property (ecma_object_t *, ecma_string_t *);
|
||||
extern ecma_property_t ecma_op_object_get_own_property (ecma_object_t *, ecma_string_t *,
|
||||
ecma_property_ref_t *, uint32_t);
|
||||
extern ecma_property_t ecma_op_object_get_property (ecma_object_t *, ecma_string_t *,
|
||||
ecma_property_ref_t *, uint32_t);
|
||||
extern bool ecma_op_object_has_own_property (ecma_object_t *, ecma_string_t *);
|
||||
extern bool ecma_op_object_has_property (ecma_object_t *, ecma_string_t *);
|
||||
extern ecma_value_t ecma_op_object_find_own (ecma_value_t, ecma_object_t *, ecma_string_t *);
|
||||
@@ -39,6 +41,8 @@ extern ecma_value_t ecma_op_object_delete (ecma_object_t *, ecma_string_t *, boo
|
||||
extern ecma_value_t ecma_op_object_default_value (ecma_object_t *, ecma_preferred_type_hint_t);
|
||||
extern ecma_value_t ecma_op_object_define_own_property (ecma_object_t *, ecma_string_t *,
|
||||
const ecma_property_descriptor_t *, bool);
|
||||
extern bool ecma_op_object_get_own_property_descriptor (ecma_object_t *, ecma_string_t *,
|
||||
ecma_property_descriptor_t *);
|
||||
extern ecma_value_t ecma_op_object_has_instance (ecma_object_t *, ecma_value_t);
|
||||
extern bool ecma_op_object_is_prototype_of (ecma_object_t *, ecma_object_t *);
|
||||
extern ecma_collection_header_t * ecma_op_object_get_property_names (ecma_object_t *, bool, bool, bool);
|
||||
|
||||
@@ -66,8 +66,7 @@ ecma_op_resolve_reference_base (ecma_object_t *lex_env_p, /**< starting lexical
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_op_resolve_reference_value (ecma_object_t *lex_env_p, /**< starting lexical environment */
|
||||
ecma_string_t *name_p, /**< identifier's name */
|
||||
bool is_strict) /**< strict mode */
|
||||
ecma_string_t *name_p) /**< identifier's name */
|
||||
{
|
||||
JERRY_ASSERT (lex_env_p != NULL);
|
||||
|
||||
@@ -79,23 +78,7 @@ ecma_op_resolve_reference_value (ecma_object_t *lex_env_p, /**< starting lexical
|
||||
|
||||
if (property_p != NULL)
|
||||
{
|
||||
ecma_value_t prop_value = ecma_get_named_data_property_value (property_p);
|
||||
|
||||
/* is the binding mutable? */
|
||||
if (unlikely (!ecma_is_property_writable (property_p)
|
||||
&& ecma_is_value_empty (prop_value)))
|
||||
{
|
||||
/* unitialized mutable binding */
|
||||
if (is_strict)
|
||||
{
|
||||
return ecma_raise_reference_error (ECMA_ERR_MSG (""));
|
||||
}
|
||||
else
|
||||
{
|
||||
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
|
||||
}
|
||||
}
|
||||
return ecma_fast_copy_value (prop_value);
|
||||
return ecma_fast_copy_value (ECMA_PROPERTY_VALUE_PTR (property_p)->value);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
*/
|
||||
|
||||
extern ecma_object_t *ecma_op_resolve_reference_base (ecma_object_t *, ecma_string_t *);
|
||||
extern ecma_value_t ecma_op_resolve_reference_value (ecma_object_t *, ecma_string_t *, bool);
|
||||
extern ecma_value_t ecma_op_resolve_reference_value (ecma_object_t *, ecma_string_t *);
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
||||
@@ -126,90 +126,86 @@ re_parse_regexp_flags (ecma_string_t *flags_str_p, /**< Input string with flags
|
||||
return ret_value;
|
||||
} /* re_parse_regexp_flags */
|
||||
|
||||
/**
|
||||
* Set a data property value for a regexp object.
|
||||
*/
|
||||
static void
|
||||
re_set_data_property (ecma_object_t *re_object_p, /**< RegExp object */
|
||||
ecma_string_t *property_name_p, /**< property name */
|
||||
uint8_t prop_attributes, /**< property attributes */
|
||||
ecma_value_t value) /**< property value */
|
||||
{
|
||||
ecma_property_ref_t property_ref;
|
||||
ecma_property_t property = ecma_op_object_get_own_property (re_object_p,
|
||||
property_name_p,
|
||||
&property_ref,
|
||||
ECMA_PROPERTY_GET_VALUE);
|
||||
|
||||
if (property == ECMA_PROPERTY_TYPE_NOT_FOUND)
|
||||
{
|
||||
property_ref.value_p = ecma_create_named_data_property (re_object_p,
|
||||
property_name_p,
|
||||
prop_attributes,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (property) == ECMA_PROPERTY_TYPE_NAMEDDATA
|
||||
&& !ecma_is_property_configurable (property));
|
||||
}
|
||||
|
||||
ecma_named_data_property_assign_value (re_object_p, property_ref.value_p, value);
|
||||
} /* re_set_data_property */
|
||||
|
||||
/**
|
||||
* Initializes the source, global, ignoreCase, multiline, and lastIndex properties of RegExp instance.
|
||||
*/
|
||||
void
|
||||
re_initialize_props (ecma_object_t *re_obj_p, /**< RegExp obejct */
|
||||
re_initialize_props (ecma_object_t *re_obj_p, /**< RegExp object */
|
||||
ecma_string_t *source_p, /**< source string */
|
||||
uint16_t flags) /**< flags */
|
||||
{
|
||||
/* Set source property. ECMA-262 v5, 15.10.7.1 */
|
||||
ecma_string_t *magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_SOURCE);
|
||||
ecma_property_t *prop_p = ecma_find_named_property (re_obj_p, magic_string_p);
|
||||
|
||||
if (prop_p == NULL)
|
||||
{
|
||||
prop_p = ecma_create_named_data_property (re_obj_p,
|
||||
magic_string_p,
|
||||
ECMA_PROPERTY_FIXED);
|
||||
}
|
||||
ecma_string_t *magic_string_p;
|
||||
|
||||
magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_SOURCE);
|
||||
re_set_data_property (re_obj_p,
|
||||
magic_string_p,
|
||||
ECMA_PROPERTY_FIXED,
|
||||
ecma_make_string_value (source_p));
|
||||
ecma_deref_ecma_string (magic_string_p);
|
||||
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA);
|
||||
ecma_named_data_property_assign_value (re_obj_p,
|
||||
prop_p,
|
||||
ecma_make_string_value (source_p));
|
||||
|
||||
/* Set global property. ECMA-262 v5, 15.10.7.2 */
|
||||
magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_GLOBAL);
|
||||
prop_p = ecma_find_named_property (re_obj_p, magic_string_p);
|
||||
|
||||
if (prop_p == NULL)
|
||||
{
|
||||
prop_p = ecma_create_named_data_property (re_obj_p,
|
||||
magic_string_p,
|
||||
ECMA_PROPERTY_FIXED);
|
||||
}
|
||||
|
||||
re_set_data_property (re_obj_p,
|
||||
magic_string_p,
|
||||
ECMA_PROPERTY_FIXED,
|
||||
ecma_make_boolean_value (flags & RE_FLAG_GLOBAL));
|
||||
ecma_deref_ecma_string (magic_string_p);
|
||||
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA);
|
||||
ecma_set_named_data_property_value (prop_p, ecma_make_boolean_value (flags & RE_FLAG_GLOBAL));
|
||||
|
||||
/* Set ignoreCase property. ECMA-262 v5, 15.10.7.3 */
|
||||
magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_IGNORECASE_UL);
|
||||
prop_p = ecma_find_named_property (re_obj_p, magic_string_p);
|
||||
|
||||
if (prop_p == NULL)
|
||||
{
|
||||
prop_p = ecma_create_named_data_property (re_obj_p,
|
||||
magic_string_p,
|
||||
ECMA_PROPERTY_FIXED);
|
||||
}
|
||||
|
||||
re_set_data_property (re_obj_p,
|
||||
magic_string_p,
|
||||
ECMA_PROPERTY_FIXED,
|
||||
ecma_make_boolean_value (flags & RE_FLAG_IGNORE_CASE));
|
||||
ecma_deref_ecma_string (magic_string_p);
|
||||
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA);
|
||||
ecma_set_named_data_property_value (prop_p, ecma_make_boolean_value (flags & RE_FLAG_IGNORE_CASE));
|
||||
|
||||
/* Set multiline property. ECMA-262 v5, 15.10.7.4 */
|
||||
magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_MULTILINE);
|
||||
prop_p = ecma_find_named_property (re_obj_p, magic_string_p);
|
||||
|
||||
if (prop_p == NULL)
|
||||
{
|
||||
prop_p = ecma_create_named_data_property (re_obj_p,
|
||||
magic_string_p,
|
||||
ECMA_PROPERTY_FIXED);
|
||||
}
|
||||
|
||||
re_set_data_property (re_obj_p,
|
||||
magic_string_p,
|
||||
ECMA_PROPERTY_FIXED,
|
||||
ecma_make_boolean_value (flags & RE_FLAG_MULTILINE));
|
||||
ecma_deref_ecma_string (magic_string_p);
|
||||
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA);
|
||||
ecma_set_named_data_property_value (prop_p, ecma_make_boolean_value (flags & RE_FLAG_MULTILINE));
|
||||
|
||||
/* Set lastIndex property. ECMA-262 v5, 15.10.7.5 */
|
||||
magic_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL);
|
||||
prop_p = ecma_find_named_property (re_obj_p, magic_string_p);
|
||||
|
||||
if (prop_p == NULL)
|
||||
{
|
||||
prop_p = ecma_create_named_data_property (re_obj_p,
|
||||
magic_string_p,
|
||||
ECMA_PROPERTY_FLAG_WRITABLE);
|
||||
}
|
||||
|
||||
re_set_data_property (re_obj_p,
|
||||
magic_string_p,
|
||||
ECMA_PROPERTY_FLAG_WRITABLE,
|
||||
ecma_make_integer_value (0));
|
||||
ecma_deref_ecma_string (magic_string_p);
|
||||
|
||||
ecma_named_data_property_assign_value (re_obj_p, prop_p, ecma_make_integer_value (0));
|
||||
} /* re_initialize_props */
|
||||
|
||||
/**
|
||||
@@ -1432,11 +1428,12 @@ ecma_regexp_exec_helper (ecma_value_t regexp_value, /**< RegExp object */
|
||||
capture_value = ecma_make_string_value (capture_str_p);
|
||||
}
|
||||
|
||||
ecma_property_t *prop_p;
|
||||
prop_p = ecma_create_named_data_property (result_array_obj_p,
|
||||
index_str_p,
|
||||
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE);
|
||||
ecma_set_named_data_property_value (prop_p, capture_value);
|
||||
ecma_property_value_t *prop_value_p;
|
||||
prop_value_p = ecma_create_named_data_property (result_array_obj_p,
|
||||
index_str_p,
|
||||
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE,
|
||||
NULL);
|
||||
prop_value_p->value = capture_value;
|
||||
|
||||
JERRY_ASSERT (!ecma_is_value_object (capture_value));
|
||||
ecma_deref_ecma_string (index_str_p);
|
||||
|
||||
@@ -100,115 +100,20 @@ ecma_op_create_string_object (const ecma_value_t *arguments_list_p, /**< list of
|
||||
|
||||
// 15.5.5.1
|
||||
ecma_string_t *length_magic_string_p = ecma_new_ecma_length_string ();
|
||||
ecma_property_t *length_prop_p = ecma_create_named_data_property (obj_p,
|
||||
length_magic_string_p,
|
||||
ECMA_PROPERTY_FIXED);
|
||||
|
||||
ecma_set_named_data_property_value (length_prop_p, ecma_make_number_value (length_value));
|
||||
ecma_property_value_t *length_prop_value_p = ecma_create_named_data_property (obj_p,
|
||||
length_magic_string_p,
|
||||
ECMA_PROPERTY_FIXED,
|
||||
NULL);
|
||||
ecma_deref_ecma_string (length_magic_string_p);
|
||||
|
||||
length_prop_value_p->value = ecma_make_number_value (length_value);
|
||||
|
||||
return ecma_make_object_value (obj_p);
|
||||
} /* ecma_op_create_string_object */
|
||||
|
||||
/**
|
||||
* [[GetOwnProperty]] ecma String object's operation
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8
|
||||
* ECMA-262 v5, 15.5.5.2
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value
|
||||
*/
|
||||
ecma_property_t *
|
||||
ecma_op_string_object_get_own_property (ecma_object_t *obj_p, /**< a String object */
|
||||
ecma_string_t *property_name_p) /**< property name */
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_STRING);
|
||||
|
||||
// 1.
|
||||
ecma_property_t *prop_p = ecma_op_general_object_get_own_property (obj_p, property_name_p);
|
||||
|
||||
// 2.
|
||||
if (prop_p != NULL)
|
||||
{
|
||||
return prop_p;
|
||||
}
|
||||
|
||||
// 3., 5.
|
||||
uint32_t uint32_index;
|
||||
ecma_string_t *new_prop_name_p;
|
||||
|
||||
if (ECMA_STRING_GET_CONTAINER (property_name_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC)
|
||||
{
|
||||
uint32_index = property_name_p->u.uint32_number;
|
||||
|
||||
new_prop_name_p = property_name_p;
|
||||
ecma_ref_ecma_string (new_prop_name_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_number_t index = ecma_string_to_number (property_name_p);
|
||||
uint32_index = ecma_number_to_uint32 (index);
|
||||
|
||||
ecma_string_t *to_str_p = ecma_new_ecma_string_from_uint32 (uint32_index);
|
||||
|
||||
bool are_equal = ecma_compare_ecma_strings (to_str_p, property_name_p);
|
||||
|
||||
if (!are_equal)
|
||||
{
|
||||
ecma_deref_ecma_string (to_str_p);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_prop_name_p = to_str_p;
|
||||
}
|
||||
}
|
||||
|
||||
// 4.
|
||||
ecma_value_t *prim_value_p = ecma_get_internal_property (obj_p,
|
||||
ECMA_INTERNAL_PROPERTY_ECMA_VALUE);
|
||||
ecma_string_t *prim_value_str_p = ecma_get_string_from_value (*prim_value_p);
|
||||
|
||||
// 6.
|
||||
ecma_length_t length = ecma_string_get_length (prim_value_str_p);
|
||||
|
||||
ecma_property_t *new_prop_p;
|
||||
|
||||
if (uint32_index >= (uint32_t) length)
|
||||
{
|
||||
// 7.
|
||||
new_prop_p = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 8.
|
||||
ecma_char_t c = ecma_string_get_char_at_pos (prim_value_str_p, uint32_index);
|
||||
|
||||
// 9.
|
||||
ecma_string_t *new_prop_str_value_p = ecma_new_ecma_string_from_code_unit (c);
|
||||
|
||||
new_prop_p = ecma_create_named_data_property (obj_p,
|
||||
new_prop_name_p,
|
||||
ECMA_PROPERTY_FLAG_ENUMERABLE);
|
||||
|
||||
ecma_set_named_data_property_value (new_prop_p,
|
||||
ecma_make_string_value (new_prop_str_value_p));
|
||||
}
|
||||
|
||||
ecma_deref_ecma_string (new_prop_name_p);
|
||||
|
||||
return new_prop_p;
|
||||
} /* ecma_op_string_object_get_own_property */
|
||||
|
||||
/**
|
||||
* List names of a String object's lazy instantiated properties
|
||||
*
|
||||
* See also:
|
||||
* ecma_op_string_object_get_own_property
|
||||
*
|
||||
* @return string values collection
|
||||
*/
|
||||
void
|
||||
|
||||
@@ -28,9 +28,6 @@
|
||||
extern ecma_value_t
|
||||
ecma_op_create_string_object (const ecma_value_t *, ecma_length_t);
|
||||
|
||||
extern ecma_property_t *
|
||||
ecma_op_string_object_get_own_property (ecma_object_t *, ecma_string_t *);
|
||||
|
||||
extern void
|
||||
ecma_op_string_list_lazy_property_names (ecma_object_t *,
|
||||
bool,
|
||||
|
||||
Reference in New Issue
Block a user