mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Create namespace with references for modules (#4646)
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
parent
ef35c0329c
commit
b3ec217b50
@ -861,9 +861,10 @@ jerry_module_get_namespace (const jerry_value_t module_val) /**< module */
|
||||
|
||||
if (module_p->namespace_object_p == NULL)
|
||||
{
|
||||
if (module_p->header.u.cls.u1.module_state != JERRY_MODULE_STATE_EVALUATED)
|
||||
if (module_p->header.u.cls.u1.module_state < JERRY_MODULE_STATE_LINKED
|
||||
|| module_p->header.u.cls.u1.module_state > JERRY_MODULE_STATE_EVALUATED)
|
||||
{
|
||||
return jerry_throw (ecma_raise_range_error (ECMA_ERR_MSG ("Namespace object has not been created yet")));
|
||||
return jerry_throw (ecma_raise_range_error (ECMA_ERR_MSG ("Namespace object cannot be created")));
|
||||
}
|
||||
|
||||
ecma_module_create_namespace_object (module_p);
|
||||
@ -1264,6 +1265,9 @@ static const uint8_t jerry_class_object_type[] =
|
||||
#if JERRY_BUILTIN_TYPEDARRAY
|
||||
JERRY_OBJECT_TYPE_TYPEDARRAY, /**< type of ECMA_OBJECT_CLASS_TYPEDARRAY */
|
||||
#endif /* JERRY_BUILTIN_TYPEDARRAY */
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
JERRY_OBJECT_TYPE_GENERIC, /**< type of ECMA_OBJECT_CLASS_MODULE_NAMESPACE */
|
||||
#endif
|
||||
|
||||
/* These objects are marked by Garbage Collector. */
|
||||
#if JERRY_ESNEXT
|
||||
@ -5130,9 +5134,7 @@ jerry_realm_set_this (jerry_value_t realm_value, /**< realm value */
|
||||
ecma_global_object_t *global_object_p = (ecma_global_object_t *) object_p;
|
||||
global_object_p->this_binding = this_value;
|
||||
|
||||
ecma_object_t *global_lex_env_p = ecma_create_object_lex_env (NULL,
|
||||
ecma_get_object_from_value (this_value),
|
||||
ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND);
|
||||
ecma_object_t *global_lex_env_p = ecma_create_object_lex_env (NULL, ecma_get_object_from_value (this_value));
|
||||
|
||||
ECMA_SET_NON_NULL_POINTER (global_object_p->global_env_cp, global_lex_env_p);
|
||||
#if JERRY_ESNEXT
|
||||
|
||||
@ -138,12 +138,22 @@ const char * const ecma_error_local_variable_is_redeclared = "Local variable is
|
||||
*/
|
||||
const char * const ecma_error_expected_a_function = "Expected a function";
|
||||
|
||||
#if JERRY_ESNEXT
|
||||
|
||||
/**
|
||||
* Error message, class constructor invoked without new keyword
|
||||
*/
|
||||
const char * const ecma_error_class_constructor_new = "Class constructor cannot be invoked without 'new'";
|
||||
|
||||
#endif /* JERRY_ERROR_MESSAGES */
|
||||
/**
|
||||
* Error message, variables declared by let/const must be initialized before reading their value
|
||||
*/
|
||||
const char * const ecma_error_let_const_not_initialized = ("Variables declared by let/const must be"
|
||||
" initialized before reading their value");
|
||||
|
||||
#endif /* JERRY_ESNEXT */
|
||||
|
||||
#endif /* JERRY_ERROR_MESSAGES */
|
||||
|
||||
#if JERRY_SNAPSHOT_SAVE || JERRY_SNAPSHOT_EXEC
|
||||
|
||||
|
||||
@ -18,6 +18,8 @@
|
||||
#ifndef ECMA_ERRORS_H
|
||||
#define ECMA_ERRORS_H
|
||||
|
||||
#if JERRY_ERROR_MESSAGES
|
||||
|
||||
extern const char * const ecma_error_value_msg_p;
|
||||
extern const char * const ecma_error_wrong_args_msg_p;
|
||||
|
||||
@ -65,7 +67,13 @@ extern const char * const ecma_error_argument_is_not_an_regexp;
|
||||
extern const char * const ecma_error_invalid_array_length;
|
||||
extern const char * const ecma_error_local_variable_is_redeclared;
|
||||
extern const char * const ecma_error_expected_a_function;
|
||||
|
||||
#if JERRY_ESNEXT
|
||||
extern const char * const ecma_error_class_constructor_new;
|
||||
extern const char * const ecma_error_let_const_not_initialized;
|
||||
#endif /* JERRY_ESNEXT */
|
||||
|
||||
#endif /* JERRY_ERROR_MESSAGES */
|
||||
|
||||
/* snapshot errors */
|
||||
extern const char * const ecma_error_maximum_snapshot_size;
|
||||
|
||||
@ -293,6 +293,55 @@ ecma_gc_mark_properties (ecma_property_pair_t *property_pair_p) /**< property pa
|
||||
}
|
||||
} /* ecma_gc_mark_properties */
|
||||
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
|
||||
/**
|
||||
* Mark objects with references (e.g. namespace objects)
|
||||
*/
|
||||
static void
|
||||
ecma_gc_mark_properties_with_references (ecma_object_t *object_p) /**< object */
|
||||
{
|
||||
jmem_cpointer_t prop_iter_cp = object_p->u1.property_list_cp;
|
||||
|
||||
#if JERRY_PROPRETY_HASHMAP
|
||||
if (prop_iter_cp != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t,
|
||||
prop_iter_cp);
|
||||
if (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP)
|
||||
{
|
||||
prop_iter_cp = object_p->u1.property_list_cp;
|
||||
}
|
||||
}
|
||||
#endif /* JERRY_PROPRETY_HASHMAP */
|
||||
|
||||
while (prop_iter_cp != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp);
|
||||
JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p));
|
||||
|
||||
for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
|
||||
{
|
||||
ecma_property_t *property_p = (ecma_property_t *) (prop_iter_p->types + i);
|
||||
|
||||
if (ECMA_PROPERTY_IS_RAW (*property_p)
|
||||
&& (*property_p & ECMA_PROPERTY_FLAG_DATA))
|
||||
{
|
||||
ecma_value_t value = ((ecma_property_pair_t *) prop_iter_p)->values[i].value;
|
||||
|
||||
if (ecma_is_value_object (value))
|
||||
{
|
||||
ecma_gc_set_object_visited (ecma_get_object_from_value (value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
prop_iter_cp = prop_iter_p->next_property_cp;
|
||||
}
|
||||
} /* ecma_gc_mark_properties_with_references */
|
||||
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
|
||||
/**
|
||||
* Mark objects referenced by bound function object.
|
||||
*/
|
||||
@ -659,11 +708,32 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
|
||||
ecma_gc_set_object_visited (ECMA_GET_NON_NULL_POINTER (ecma_object_t, outer_lex_env_cp));
|
||||
}
|
||||
|
||||
if (ecma_get_lex_env_type (object_p) != ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
|
||||
switch (ecma_get_lex_env_type (object_p))
|
||||
{
|
||||
ecma_object_t *binding_object_p = ecma_get_lex_env_binding_object (object_p);
|
||||
ecma_gc_set_object_visited (binding_object_p);
|
||||
return;
|
||||
#if JERRY_ESNEXT
|
||||
case ECMA_LEXICAL_ENVIRONMENT_CLASS:
|
||||
{
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
if (object_p->type_flags_refs & ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA)
|
||||
{
|
||||
ecma_gc_mark_properties_with_references (object_p);
|
||||
ecma_gc_set_object_visited (((ecma_lexical_environment_class_t *) object_p)->module_p);
|
||||
return;
|
||||
}
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
/* FALLTHRU */
|
||||
}
|
||||
#endif /* JERRY_ESNEXT */
|
||||
case ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND:
|
||||
{
|
||||
ecma_object_t *binding_object_p = ecma_get_lex_env_binding_object (object_p);
|
||||
ecma_gc_set_object_visited (binding_object_p);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -733,10 +803,32 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
|
||||
break;
|
||||
}
|
||||
#endif /* JERRY_BUILTIN_TYPEDARRAY */
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
case ECMA_OBJECT_CLASS_MODULE_NAMESPACE:
|
||||
{
|
||||
JERRY_ASSERT (proto_cp == JMEM_CP_NULL);
|
||||
ecma_gc_set_object_visited (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t,
|
||||
ext_object_p->u.cls.u3.value));
|
||||
ecma_gc_mark_properties_with_references (object_p);
|
||||
return;
|
||||
}
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
case ECMA_OBJECT_CLASS_MODULE:
|
||||
{
|
||||
ecma_module_node_t *node_p = ((ecma_module_t *) ext_object_p)->imports_p;
|
||||
ecma_module_t *module_p = ((ecma_module_t *) ext_object_p);
|
||||
|
||||
if (module_p->scope_p != NULL)
|
||||
{
|
||||
ecma_gc_set_object_visited (((ecma_module_t *) ext_object_p)->scope_p);
|
||||
}
|
||||
|
||||
if (module_p->namespace_object_p != NULL)
|
||||
{
|
||||
ecma_gc_set_object_visited (((ecma_module_t *) ext_object_p)->namespace_object_p);
|
||||
}
|
||||
|
||||
ecma_module_node_t *node_p = module_p->imports_p;
|
||||
|
||||
while (node_p != NULL)
|
||||
{
|
||||
@ -1083,21 +1175,16 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
|
||||
* Free the native handle/pointer by calling its free callback.
|
||||
*/
|
||||
static void
|
||||
ecma_gc_free_native_pointer (ecma_property_t *property_p) /**< property */
|
||||
ecma_gc_free_native_pointer (ecma_value_t value) /**< property value */
|
||||
{
|
||||
JERRY_ASSERT (property_p != NULL);
|
||||
|
||||
ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
|
||||
|
||||
if (value_p->value == JMEM_CP_NULL)
|
||||
if (value == JMEM_CP_NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ecma_native_pointer_t *native_pointer_p;
|
||||
|
||||
native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t,
|
||||
value_p->value);
|
||||
native_pointer_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_native_pointer_t, value);
|
||||
JERRY_ASSERT (native_pointer_p != NULL);
|
||||
|
||||
do
|
||||
@ -1317,11 +1404,132 @@ ecma_gc_free_executable_object (ecma_object_t *object_p) /**< object */
|
||||
|
||||
#endif /* JERRY_ESNEXT */
|
||||
|
||||
JERRY_STATIC_ASSERT (!ECMA_PROPERTY_IS_RAW (ECMA_PROPERTY_TYPE_DELETED),
|
||||
ecma_property_type_deleted_must_not_be_raw_property);
|
||||
JERRY_STATIC_ASSERT ((ECMA_PROPERTY_TYPE_DELETED & ECMA_PROPERTY_FLAG_LCACHED) == 0,
|
||||
ecma_property_type_deleted_must_not_have_lcached_flag);
|
||||
JERRY_STATIC_ASSERT (ECMA_GC_FREE_SECOND_PROPERTY == 1,
|
||||
ecma_gc_free_second_must_be_one);
|
||||
|
||||
/**
|
||||
* Free property of an object
|
||||
*/
|
||||
void
|
||||
ecma_gc_free_property (ecma_object_t *object_p, /**< object */
|
||||
ecma_property_pair_t *prop_pair_p, /**< property pair */
|
||||
uint32_t options) /**< option bits including property index */
|
||||
{
|
||||
/* Both cannot be deleted. */
|
||||
JERRY_ASSERT (prop_pair_p->header.types[0] != ECMA_PROPERTY_TYPE_DELETED
|
||||
|| prop_pair_p->header.types[1] != ECMA_PROPERTY_TYPE_DELETED);
|
||||
JERRY_ASSERT (prop_pair_p->header.types[0] != ECMA_PROPERTY_TYPE_HASHMAP);
|
||||
|
||||
uint32_t index = (options & ECMA_GC_FREE_SECOND_PROPERTY);
|
||||
jmem_cpointer_t name_cp = prop_pair_p->names_cp[index];
|
||||
ecma_property_t *property_p = prop_pair_p->header.types + index;
|
||||
ecma_property_t property = *property_p;
|
||||
|
||||
#if JERRY_LCACHE
|
||||
if ((property & ECMA_PROPERTY_FLAG_LCACHED) != 0)
|
||||
{
|
||||
ecma_lcache_invalidate (object_p, name_cp, property_p);
|
||||
}
|
||||
#endif /* JERRY_LCACHE */
|
||||
|
||||
if (ECMA_PROPERTY_IS_RAW (property))
|
||||
{
|
||||
if (ECMA_PROPERTY_GET_NAME_TYPE (property) == ECMA_DIRECT_STRING_PTR)
|
||||
{
|
||||
ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, name_cp);
|
||||
ecma_deref_ecma_string (prop_name_p);
|
||||
}
|
||||
|
||||
if (property & ECMA_PROPERTY_FLAG_DATA)
|
||||
{
|
||||
ecma_free_value_if_not_object (prop_pair_p->values[index].value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (JERRY_UNLIKELY (options & ECMA_GC_FREE_REFERENCES))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#if JERRY_CPOINTER_32_BIT
|
||||
ecma_getter_setter_pointers_t *getter_setter_pair_p;
|
||||
getter_setter_pair_p = ECMA_GET_NON_NULL_POINTER (ecma_getter_setter_pointers_t,
|
||||
prop_pair_p->values[index].getter_setter_pair_cp);
|
||||
jmem_pools_free (getter_setter_pair_p, sizeof (ecma_getter_setter_pointers_t));
|
||||
#endif /* JERRY_CPOINTER_32_BIT */
|
||||
return;
|
||||
}
|
||||
|
||||
if (property == ECMA_PROPERTY_TYPE_DELETED)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ecma_value_t value = prop_pair_p->values[index].value;
|
||||
|
||||
switch (name_cp)
|
||||
{
|
||||
#if JERRY_ESNEXT
|
||||
case LIT_INTERNAL_MAGIC_STRING_ENVIRONMENT_RECORD:
|
||||
{
|
||||
ecma_environment_record_t *environment_record_p;
|
||||
environment_record_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_environment_record_t, value);
|
||||
jmem_heap_free_block (environment_record_p, sizeof (ecma_environment_record_t));
|
||||
break;
|
||||
}
|
||||
case LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_COMPUTED:
|
||||
{
|
||||
ecma_value_t *compact_collection_p;
|
||||
compact_collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, value);
|
||||
ecma_compact_collection_free (compact_collection_p);
|
||||
break;
|
||||
}
|
||||
#endif /* JERRY_ESNEXT */
|
||||
#if JERRY_BUILTIN_WEAKMAP || JERRY_BUILTIN_WEAKSET || JERRY_BUILTIN_WEAKREF
|
||||
case LIT_INTERNAL_MAGIC_STRING_WEAK_REFS:
|
||||
{
|
||||
ecma_collection_t *refs_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, value);
|
||||
for (uint32_t j = 0; j < refs_p->item_count; j++)
|
||||
{
|
||||
const ecma_value_t reference_value = refs_p->buffer_p[j];
|
||||
|
||||
if (!ecma_is_value_empty (reference_value))
|
||||
{
|
||||
ecma_object_t *obj_p = ecma_get_object_from_value (reference_value);
|
||||
|
||||
if (ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_WEAKREF))
|
||||
{
|
||||
ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p;
|
||||
ext_obj_p->u.cls.u3.target = ECMA_VALUE_UNDEFINED;
|
||||
continue;
|
||||
}
|
||||
ecma_op_container_remove_weak_entry (obj_p, ecma_make_object_value (object_p));
|
||||
}
|
||||
}
|
||||
|
||||
ecma_collection_destroy (refs_p);
|
||||
break;
|
||||
}
|
||||
#endif /* JERRY_BUILTIN_WEAKMAP || JERRY_BUILTIN_WEAKSET || JERRY_BUILTIN_WEAKREF */
|
||||
default:
|
||||
{
|
||||
JERRY_ASSERT (name_cp == LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER);
|
||||
ecma_gc_free_native_pointer (value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} /* ecma_gc_free_property */
|
||||
|
||||
/**
|
||||
* Free properties of an object
|
||||
*/
|
||||
void
|
||||
ecma_gc_free_properties (ecma_object_t *object_p) /**< object */
|
||||
ecma_gc_free_properties (ecma_object_t *object_p, /**< object */
|
||||
uint32_t options) /**< option bits */
|
||||
{
|
||||
jmem_cpointer_t prop_iter_cp = object_p->u1.property_list_cp;
|
||||
|
||||
@ -1343,89 +1551,11 @@ ecma_gc_free_properties (ecma_object_t *object_p) /**< object */
|
||||
ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp);
|
||||
JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p));
|
||||
|
||||
/* Both cannot be deleted. */
|
||||
JERRY_ASSERT (prop_iter_p->types[0] != ECMA_PROPERTY_TYPE_DELETED
|
||||
|| prop_iter_p->types[1] != ECMA_PROPERTY_TYPE_DELETED);
|
||||
|
||||
ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p;
|
||||
|
||||
for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
|
||||
for (uint32_t i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
|
||||
{
|
||||
ecma_property_t *property_p = (ecma_property_t *) (prop_iter_p->types + i);
|
||||
jmem_cpointer_t name_cp = prop_pair_p->names_cp[i];
|
||||
|
||||
if (*property_p == ECMA_PROPERTY_TYPE_DELETED)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ECMA_PROPERTY_IS_INTERNAL (*property_p))
|
||||
{
|
||||
ecma_free_property (object_p, name_cp, property_p);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Call the native's free callback. */
|
||||
switch (name_cp)
|
||||
{
|
||||
#if JERRY_ESNEXT
|
||||
case LIT_INTERNAL_MAGIC_STRING_ENVIRONMENT_RECORD:
|
||||
{
|
||||
ecma_environment_record_t *environment_record_p;
|
||||
environment_record_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_environment_record_t,
|
||||
prop_pair_p->values[i].value);
|
||||
jmem_heap_free_block (environment_record_p, sizeof (ecma_environment_record_t));
|
||||
break;
|
||||
}
|
||||
case LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_COMPUTED:
|
||||
{
|
||||
ecma_value_t *compact_collection_p;
|
||||
compact_collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t,
|
||||
prop_pair_p->values[i].value);
|
||||
ecma_compact_collection_free (compact_collection_p);
|
||||
break;
|
||||
}
|
||||
#endif /* JERRY_ESNEXT */
|
||||
#if JERRY_BUILTIN_WEAKMAP || JERRY_BUILTIN_WEAKSET || JERRY_BUILTIN_WEAKREF
|
||||
case LIT_INTERNAL_MAGIC_STRING_WEAK_REFS:
|
||||
{
|
||||
ecma_collection_t *refs_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t,
|
||||
prop_pair_p->values[i].value);
|
||||
for (uint32_t j = 0; j < refs_p->item_count; j++)
|
||||
{
|
||||
const ecma_value_t value = refs_p->buffer_p[j];
|
||||
if (!ecma_is_value_empty (value))
|
||||
{
|
||||
ecma_object_t *obj_p = ecma_get_object_from_value (value);
|
||||
|
||||
if (ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_WEAKREF))
|
||||
{
|
||||
ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p;
|
||||
ext_obj_p->u.cls.u3.target = ECMA_VALUE_UNDEFINED;
|
||||
continue;
|
||||
}
|
||||
ecma_op_container_remove_weak_entry (obj_p, ecma_make_object_value (object_p));
|
||||
}
|
||||
}
|
||||
|
||||
ecma_collection_destroy (refs_p);
|
||||
break;
|
||||
}
|
||||
#endif /* JERRY_BUILTIN_WEAKMAP || JERRY_BUILTIN_WEAKSET || JERRY_BUILTIN_WEAKREF */
|
||||
default:
|
||||
{
|
||||
JERRY_ASSERT (name_cp == LIT_INTERNAL_MAGIC_STRING_NATIVE_POINTER);
|
||||
ecma_gc_free_native_pointer (property_p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if JERRY_LCACHE
|
||||
if (ecma_is_property_lcached (property_p))
|
||||
{
|
||||
ecma_lcache_invalidate (object_p, name_cp, property_p);
|
||||
}
|
||||
#endif /* JERRY_LCACHE */
|
||||
ecma_gc_free_property (object_p, prop_pair_p, i | options);
|
||||
}
|
||||
|
||||
prop_iter_cp = prop_iter_p->next_property_cp;
|
||||
@ -1447,9 +1577,19 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
|
||||
|
||||
if (ecma_is_lexical_environment (object_p))
|
||||
{
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
if (ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_CLASS
|
||||
&& (object_p->type_flags_refs & ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA))
|
||||
{
|
||||
ecma_gc_free_properties (object_p, ECMA_GC_FREE_REFERENCES);
|
||||
ecma_dealloc_extended_object (object_p, sizeof (ecma_lexical_environment_class_t));
|
||||
return;
|
||||
}
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
|
||||
if (ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
|
||||
{
|
||||
ecma_gc_free_properties (object_p);
|
||||
ecma_gc_free_properties (object_p, ECMA_GC_FREE_NO_OPTIONS);
|
||||
}
|
||||
|
||||
ecma_dealloc_object (object_p);
|
||||
@ -1538,9 +1678,7 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
|
||||
ext_object_size += sizeof (uint64_t) * (length_and_bitset_size >> ECMA_BUILT_IN_BITSET_SHIFT);
|
||||
}
|
||||
|
||||
ecma_gc_free_properties (object_p);
|
||||
ecma_dealloc_extended_object (object_p, ext_object_size);
|
||||
return;
|
||||
goto free_properties;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1548,7 +1686,7 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
|
||||
{
|
||||
case ECMA_OBJECT_TYPE_GENERAL:
|
||||
{
|
||||
ecma_gc_free_properties (object_p);
|
||||
ecma_gc_free_properties (object_p, ECMA_GC_FREE_NO_OPTIONS);
|
||||
ecma_dealloc_object (object_p);
|
||||
return;
|
||||
}
|
||||
@ -1599,6 +1737,14 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
|
||||
break;
|
||||
}
|
||||
#endif /* JERRY_BUILTIN_TYPEDARRAY */
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
case ECMA_OBJECT_CLASS_MODULE_NAMESPACE:
|
||||
{
|
||||
ecma_gc_free_properties (object_p, ECMA_GC_FREE_REFERENCES);
|
||||
ecma_dealloc_extended_object (object_p, sizeof (ecma_extended_object_t));
|
||||
return;
|
||||
}
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
#if JERRY_PARSER
|
||||
case ECMA_OBJECT_CLASS_SCRIPT:
|
||||
{
|
||||
@ -1832,7 +1978,8 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
|
||||
}
|
||||
}
|
||||
|
||||
ecma_gc_free_properties (object_p);
|
||||
free_properties:
|
||||
ecma_gc_free_properties (object_p, ECMA_GC_FREE_NO_OPTIONS);
|
||||
ecma_dealloc_extended_object (object_p, ext_object_size);
|
||||
} /* ecma_gc_free_object */
|
||||
|
||||
|
||||
@ -26,11 +26,22 @@
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Free option flags
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ECMA_GC_FREE_NO_OPTIONS = 0, /**< no options */
|
||||
ECMA_GC_FREE_SECOND_PROPERTY = (1 << 0), /**< free second property of a property pair */
|
||||
ECMA_GC_FREE_REFERENCES = (1 << 1), /**< free references */
|
||||
} ecma_gc_free_options_t;
|
||||
|
||||
void ecma_init_gc_info (ecma_object_t *object_p);
|
||||
void ecma_ref_object (ecma_object_t *object_p);
|
||||
void ecma_ref_object_inline (ecma_object_t *object_p);
|
||||
void ecma_deref_object (ecma_object_t *object_p);
|
||||
void ecma_gc_free_properties (ecma_object_t *object_p);
|
||||
void ecma_gc_free_property (ecma_object_t *object_p, ecma_property_pair_t *prop_pair_p, uint32_t options);
|
||||
void ecma_gc_free_properties (ecma_object_t *object_p, uint32_t options);
|
||||
void ecma_gc_run (void);
|
||||
void ecma_free_unused_memory (jmem_pressure_t pressure);
|
||||
|
||||
|
||||
@ -711,6 +711,9 @@ typedef enum
|
||||
#if JERRY_BUILTIN_TYPEDARRAY
|
||||
ECMA_OBJECT_CLASS_TYPEDARRAY, /**< TypedArray which does NOT need extra space to store length and offset */
|
||||
#endif /* JERRY_BUILTIN_TYPEDARRAY */
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
ECMA_OBJECT_CLASS_MODULE_NAMESPACE, /**< Module Namespace (ECMAScript v11, 9.4.6) */
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
|
||||
/* These objects are marked by Garbage Collector. */
|
||||
#if JERRY_ESNEXT
|
||||
@ -776,14 +779,14 @@ typedef enum
|
||||
/* Types between 0 - 12 are ecma_object_type_t which can have a built-in flag. */
|
||||
|
||||
ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE = 13, /**< declarative lexical environment */
|
||||
ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND = 14, /**< object-bound lexical environment
|
||||
* with provideThis flag */
|
||||
ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND = 15, /**< object-bound lexical environment
|
||||
* with provided home object reference */
|
||||
#if JERRY_ESNEXT
|
||||
ECMA_LEXICAL_ENVIRONMENT_CLASS = 14, /**< lexical environment with class */
|
||||
#endif /* JERRY_ESNEXT */
|
||||
ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND = 15, /**< object-bound lexical environment */
|
||||
|
||||
ECMA_LEXICAL_ENVIRONMENT_TYPE_START = ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE, /**< first lexical
|
||||
* environment type */
|
||||
ECMA_LEXICAL_ENVIRONMENT_TYPE__MAX = ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND /**< maximum value */
|
||||
ECMA_LEXICAL_ENVIRONMENT_TYPE__MAX = ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND /**< maximum value */
|
||||
} ecma_lexical_environment_type_t;
|
||||
|
||||
#if JERRY_ESNEXT
|
||||
@ -848,10 +851,15 @@ typedef enum
|
||||
#define ECMA_OBJECT_FLAG_EXTENSIBLE 0x20
|
||||
|
||||
/**
|
||||
* Lexical environments created for non-closure code blocks
|
||||
* Declarative lexical environments created for non-closure code blocks
|
||||
*/
|
||||
#define ECMA_OBJECT_FLAG_BLOCK ECMA_OBJECT_FLAG_EXTENSIBLE
|
||||
|
||||
/**
|
||||
* Lexical environments with class has extra data
|
||||
*/
|
||||
#define ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA ECMA_OBJECT_FLAG_EXTENSIBLE
|
||||
|
||||
/**
|
||||
* Bitshift index for an ecma-object reference count field
|
||||
*/
|
||||
@ -1142,6 +1150,16 @@ typedef struct
|
||||
#define ECMA_BUILTIN_IS_EXTENDED_BUILT_IN(object_type) \
|
||||
((object_type) == ECMA_OBJECT_TYPE_CLASS || (object_type) == ECMA_OBJECT_TYPE_ARRAY)
|
||||
|
||||
/**
|
||||
* Description of lexical environment with class
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
ecma_object_t lexical_env; /**< lexical environment header */
|
||||
|
||||
ecma_object_t *module_p; /**< module reference */
|
||||
} ecma_lexical_environment_class_t;
|
||||
|
||||
/**
|
||||
* Description of native functions
|
||||
*/
|
||||
|
||||
@ -123,7 +123,7 @@ ecma_create_decl_lex_env (ecma_object_t *outer_lexical_environment_p) /**< outer
|
||||
|
||||
/**
|
||||
* Create a object lexical environment with specified outer lexical environment
|
||||
* (or NULL if the environment is not nested), binding object and provided type flag.
|
||||
* (or NULL if the environment is not nested), and binding object.
|
||||
*
|
||||
* See also: ECMA-262 v5, 10.2.1.2
|
||||
*
|
||||
@ -133,23 +133,15 @@ ecma_create_decl_lex_env (ecma_object_t *outer_lexical_environment_p) /**< outer
|
||||
*/
|
||||
ecma_object_t *
|
||||
ecma_create_object_lex_env (ecma_object_t *outer_lexical_environment_p, /**< outer lexical environment */
|
||||
ecma_object_t *binding_obj_p, /**< binding object */
|
||||
ecma_lexical_environment_type_t type) /**< type of the new lexical environment */
|
||||
ecma_object_t *binding_obj_p) /**< binding object */
|
||||
{
|
||||
#if JERRY_ESNEXT
|
||||
JERRY_ASSERT (type == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND
|
||||
|| type == ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND);
|
||||
#else /* !JERRY_ESNEXT */
|
||||
JERRY_ASSERT (type == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND);
|
||||
#endif /* JERRY_ESNEXT */
|
||||
|
||||
JERRY_ASSERT (binding_obj_p != NULL
|
||||
&& !ecma_is_lexical_environment (binding_obj_p));
|
||||
|
||||
ecma_object_t *new_lexical_environment_p = ecma_alloc_object ();
|
||||
|
||||
const ecma_object_descriptor_t lexical_env_flag = ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV;
|
||||
new_lexical_environment_p->type_flags_refs = (ecma_object_descriptor_t) (type | lexical_env_flag);
|
||||
new_lexical_environment_p->type_flags_refs = (ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV
|
||||
| ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND);
|
||||
|
||||
ecma_init_gc_info (new_lexical_environment_p);
|
||||
|
||||
@ -161,6 +153,45 @@ ecma_create_object_lex_env (ecma_object_t *outer_lexical_environment_p, /**< out
|
||||
return new_lexical_environment_p;
|
||||
} /* ecma_create_object_lex_env */
|
||||
|
||||
#if JERRY_ESNEXT
|
||||
|
||||
/**
|
||||
* Create a lexical environment with a specified size.
|
||||
*
|
||||
* @return pointer to the descriptor of the lexical environment
|
||||
*/
|
||||
ecma_object_t *
|
||||
ecma_create_lex_env_class (ecma_object_t *outer_lexical_environment_p, /**< outer lexical environment */
|
||||
size_t lexical_env_size) /**< size of the lexical environment */
|
||||
{
|
||||
ecma_object_t *new_lexical_environment_p;
|
||||
|
||||
ecma_object_descriptor_t type_flags_refs = (ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV
|
||||
| ECMA_LEXICAL_ENVIRONMENT_CLASS);
|
||||
|
||||
if (lexical_env_size > 0)
|
||||
{
|
||||
new_lexical_environment_p = (ecma_object_t *) ecma_alloc_extended_object (lexical_env_size);
|
||||
type_flags_refs |= ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_lexical_environment_p = ecma_alloc_object ();
|
||||
}
|
||||
|
||||
new_lexical_environment_p->type_flags_refs = type_flags_refs;
|
||||
|
||||
ecma_init_gc_info (new_lexical_environment_p);
|
||||
|
||||
new_lexical_environment_p->u1.property_list_cp = JMEM_CP_NULL;
|
||||
|
||||
ECMA_SET_POINTER (new_lexical_environment_p->u2.outer_reference_cp, outer_lexical_environment_p);
|
||||
|
||||
return new_lexical_environment_p;
|
||||
} /* ecma_create_lex_env_class */
|
||||
|
||||
#endif /* JERRY_ESNEXT */
|
||||
|
||||
/**
|
||||
* Check if the object is lexical environment.
|
||||
*
|
||||
@ -203,6 +234,29 @@ ecma_get_object_type (const ecma_object_t *object_p) /**< object */
|
||||
return (ecma_object_type_t) (object_p->type_flags_refs & ECMA_OBJECT_TYPE_MASK);
|
||||
} /* ecma_get_object_type */
|
||||
|
||||
/**
|
||||
* Get value of an object if the class matches
|
||||
*
|
||||
* @return value of the object if the class matches
|
||||
* ECMA_VALUE_NOT_FOUND otherwise
|
||||
*/
|
||||
extern inline bool JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_object_class_is (ecma_object_t *object_p, /**< object */
|
||||
ecma_object_class_type_t class_id) /**< class id */
|
||||
{
|
||||
if (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_CLASS)
|
||||
{
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
if (ext_object_p->u.cls.type == (uint8_t) class_id)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} /* ecma_object_class_is */
|
||||
|
||||
/**
|
||||
* Check if the object is a built-in object
|
||||
*
|
||||
@ -286,7 +340,8 @@ ecma_get_lex_env_binding_object (const ecma_object_t *object_p) /**< object-boun
|
||||
JERRY_ASSERT (ecma_is_lexical_environment (object_p));
|
||||
#if JERRY_ESNEXT
|
||||
JERRY_ASSERT (ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND
|
||||
|| ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND);
|
||||
|| (ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_CLASS
|
||||
&& (object_p->type_flags_refs & ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA) == 0));
|
||||
#else /* !JERRY_ESNEXT */
|
||||
JERRY_ASSERT (ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND);
|
||||
#endif /* JERRY_ESNEXT */
|
||||
@ -568,6 +623,51 @@ ecma_create_named_accessor_property (ecma_object_t *object_p, /**< object */
|
||||
return ecma_create_property (object_p, name_p, type_and_flags, value, out_prop_p);
|
||||
} /* ecma_create_named_accessor_property */
|
||||
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
/**
|
||||
* Create property reference
|
||||
*/
|
||||
void
|
||||
ecma_create_named_reference_property (ecma_object_t *object_p, /**< object */
|
||||
ecma_string_t *name_p, /**< property name */
|
||||
ecma_property_t *property_p) /**< referenced property */
|
||||
{
|
||||
JERRY_ASSERT (object_p != NULL && name_p != NULL && property_p != NULL);
|
||||
JERRY_ASSERT (*property_p & ECMA_PROPERTY_FLAG_DATA);
|
||||
JERRY_ASSERT (ecma_find_named_property (object_p, name_p) == NULL);
|
||||
JERRY_ASSERT ((ecma_is_lexical_environment (object_p)
|
||||
&& ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_CLASS
|
||||
&& (object_p->type_flags_refs & ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA))
|
||||
|| ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_MODULE_NAMESPACE));
|
||||
|
||||
uint8_t type_and_flags = ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE;
|
||||
|
||||
ecma_property_value_t *value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
|
||||
|
||||
jmem_cpointer_tag_t offset = (jmem_cpointer_tag_t) (((uintptr_t) property_p) & 0x1);
|
||||
|
||||
#if JERRY_CPOINTER_32_BIT
|
||||
if (offset != 0)
|
||||
{
|
||||
--value_p;
|
||||
}
|
||||
#else /* !JERRY_CPOINTER_32_BIT */
|
||||
if (offset == 0)
|
||||
{
|
||||
++value_p;
|
||||
}
|
||||
#endif /* JERRY_CPOINTER_32_BIT */
|
||||
|
||||
JERRY_ASSERT ((((uintptr_t) value_p) & (((uintptr_t) 1 << JMEM_ALIGNMENT_LOG) - 1)) == 0);
|
||||
|
||||
ecma_property_value_t value;
|
||||
ECMA_SET_NON_NULL_POINTER_TAG (value.value, value_p, offset);
|
||||
|
||||
ecma_create_property (object_p, name_p, type_and_flags, value, NULL);
|
||||
} /* ecma_create_named_reference_property */
|
||||
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
|
||||
/**
|
||||
* Find named data property or named accessor property in a specified object.
|
||||
*
|
||||
@ -748,48 +848,6 @@ ecma_get_named_data_property (ecma_object_t *obj_p, /**< object to find property
|
||||
return ECMA_PROPERTY_VALUE_PTR (property_p);
|
||||
} /* ecma_get_named_data_property */
|
||||
|
||||
/**
|
||||
* Free property values and change their type to deleted.
|
||||
*
|
||||
* Note:
|
||||
* internal properties are not supported
|
||||
*/
|
||||
void
|
||||
ecma_free_property (ecma_object_t *object_p, /**< object the property belongs to */
|
||||
jmem_cpointer_t name_cp, /**< name of the property or ECMA_NULL_POINTER */
|
||||
ecma_property_t *property_p) /**< property */
|
||||
{
|
||||
JERRY_ASSERT (object_p != NULL && property_p != NULL);
|
||||
JERRY_ASSERT (ECMA_PROPERTY_IS_RAW (*property_p));
|
||||
|
||||
if (*property_p & ECMA_PROPERTY_FLAG_DATA)
|
||||
{
|
||||
ecma_free_value_if_not_object (ECMA_PROPERTY_VALUE_PTR (property_p)->value);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if JERRY_CPOINTER_32_BIT
|
||||
ecma_getter_setter_pointers_t *getter_setter_pair_p;
|
||||
getter_setter_pair_p = ECMA_GET_NON_NULL_POINTER (ecma_getter_setter_pointers_t,
|
||||
ECMA_PROPERTY_VALUE_PTR (property_p)->getter_setter_pair_cp);
|
||||
jmem_pools_free (getter_setter_pair_p, sizeof (ecma_getter_setter_pointers_t));
|
||||
#endif /* JERRY_CPOINTER_32_BIT */
|
||||
}
|
||||
|
||||
#if JERRY_LCACHE
|
||||
if (ecma_is_property_lcached (property_p))
|
||||
{
|
||||
ecma_lcache_invalidate (object_p, name_cp, property_p);
|
||||
}
|
||||
#endif /* JERRY_LCACHE */
|
||||
|
||||
if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_DIRECT_STRING_PTR)
|
||||
{
|
||||
ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, name_cp);
|
||||
ecma_deref_ecma_string (prop_name_p);
|
||||
}
|
||||
} /* ecma_free_property */
|
||||
|
||||
/**
|
||||
* Delete the object's property referenced by its value pointer.
|
||||
*
|
||||
@ -829,7 +887,7 @@ ecma_delete_property (ecma_object_t *object_p, /**< object */
|
||||
|
||||
ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) cur_prop_p;
|
||||
|
||||
for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
|
||||
for (uint32_t i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
|
||||
{
|
||||
if ((prop_pair_p->values + i) == prop_value_p)
|
||||
{
|
||||
@ -844,7 +902,7 @@ ecma_delete_property (ecma_object_t *object_p, /**< object */
|
||||
}
|
||||
#endif /* JERRY_PROPRETY_HASHMAP */
|
||||
|
||||
ecma_free_property (object_p, prop_pair_p->names_cp[i], cur_prop_p->types + i);
|
||||
ecma_gc_free_property (object_p, prop_pair_p, i);
|
||||
cur_prop_p->types[i] = ECMA_PROPERTY_TYPE_DELETED;
|
||||
prop_pair_p->names_cp[i] = LIT_INTERNAL_MAGIC_STRING_DELETED;
|
||||
|
||||
@ -1008,6 +1066,36 @@ ecma_set_named_accessor_property_setter (ecma_object_t *object_p, /**< the prope
|
||||
#endif /* JERRY_CPOINTER_32_BIT */
|
||||
} /* ecma_set_named_accessor_property_setter */
|
||||
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
|
||||
/**
|
||||
* Gets the referenced property value
|
||||
*
|
||||
* @return pointer to the value
|
||||
*/
|
||||
extern inline ecma_property_value_t * JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_get_property_value_from_named_reference (ecma_property_value_t *reference_p) /**< data property reference */
|
||||
{
|
||||
ecma_value_t value = reference_p->value;
|
||||
reference_p = ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_property_value_t, value);
|
||||
|
||||
#if JERRY_CPOINTER_32_BIT
|
||||
if (ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (value))
|
||||
{
|
||||
++reference_p;
|
||||
}
|
||||
#else /* !JERRY_CPOINTER_32_BIT */
|
||||
if (!ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (value))
|
||||
{
|
||||
--reference_p;
|
||||
}
|
||||
#endif /* JERRY_CPOINTER_32_BIT */
|
||||
|
||||
return reference_p;
|
||||
} /* ecma_get_property_value_from_named_reference */
|
||||
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
|
||||
/**
|
||||
* Get property's 'Writable' attribute value
|
||||
*
|
||||
|
||||
@ -358,6 +358,9 @@ const lit_utf8_byte_t *ecma_string_get_chars (const ecma_string_t *string_p,
|
||||
bool ecma_compare_ecma_string_to_magic_id (const ecma_string_t *string_p, lit_magic_string_id_t id);
|
||||
bool ecma_string_is_empty (const ecma_string_t *string_p);
|
||||
bool ecma_string_is_length (const ecma_string_t *string_p);
|
||||
#if JERRY_ESNEXT
|
||||
bool ecma_compare_ecma_string_to_global_symbol (ecma_string_t *string_p, lit_magic_string_id_t property_id);
|
||||
#endif /* JERRY_ESNEXT */
|
||||
|
||||
jmem_cpointer_t ecma_string_to_property_name (ecma_string_t *prop_name_p, ecma_property_t *name_type_p);
|
||||
ecma_string_t *ecma_string_from_property_name (ecma_property_t property, jmem_cpointer_t prop_name_cp);
|
||||
@ -457,11 +460,14 @@ void ecma_compact_collection_free (ecma_value_t *compact_collection_p);
|
||||
/* ecma-helpers.c */
|
||||
ecma_object_t *ecma_create_object (ecma_object_t *prototype_object_p, size_t ext_object_size, ecma_object_type_t type);
|
||||
ecma_object_t *ecma_create_decl_lex_env (ecma_object_t *outer_lexical_environment_p);
|
||||
ecma_object_t *ecma_create_object_lex_env (ecma_object_t *outer_lexical_environment_p, ecma_object_t *binding_obj_p,
|
||||
ecma_lexical_environment_type_t type);
|
||||
ecma_object_t *ecma_create_object_lex_env (ecma_object_t *outer_lexical_environment_p, ecma_object_t *binding_obj_p);
|
||||
#if JERRY_ESNEXT
|
||||
ecma_object_t *ecma_create_lex_env_class (ecma_object_t *outer_lexical_environment_p, size_t lexical_env_size);
|
||||
#endif /* JERRY_ESNEXT */
|
||||
bool JERRY_ATTR_PURE ecma_is_lexical_environment (const ecma_object_t *object_p);
|
||||
void ecma_op_ordinary_object_set_extensible (ecma_object_t *object_p);
|
||||
ecma_object_type_t JERRY_ATTR_PURE ecma_get_object_type (const ecma_object_t *object_p);
|
||||
bool JERRY_ATTR_PURE ecma_object_class_is (ecma_object_t *object_p, ecma_object_class_type_t class_id);
|
||||
bool JERRY_ATTR_PURE ecma_get_object_is_builtin (const ecma_object_t *object_p);
|
||||
void ecma_set_object_is_builtin (ecma_object_t *object_p);
|
||||
uint8_t ecma_get_object_builtin_id (ecma_object_t *object_p);
|
||||
@ -475,13 +481,15 @@ ecma_create_named_data_property (ecma_object_t *object_p, ecma_string_t *name_p,
|
||||
ecma_property_value_t *
|
||||
ecma_create_named_accessor_property (ecma_object_t *object_p, ecma_string_t *name_p, ecma_object_t *get_p,
|
||||
ecma_object_t *set_p, uint8_t prop_attributes, ecma_property_t **out_prop_p);
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
void ecma_create_named_reference_property (ecma_object_t *object_p, ecma_string_t *name_p,
|
||||
ecma_property_t *property_p);
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
ecma_property_t *
|
||||
ecma_find_named_property (ecma_object_t *obj_p, ecma_string_t *name_p);
|
||||
ecma_property_value_t *
|
||||
ecma_get_named_data_property (ecma_object_t *obj_p, ecma_string_t *name_p);
|
||||
|
||||
void ecma_free_property (ecma_object_t *object_p, jmem_cpointer_t name_cp, ecma_property_t *property_p);
|
||||
|
||||
void ecma_delete_property (ecma_object_t *object_p, ecma_property_value_t *prop_value_p);
|
||||
|
||||
void ecma_named_data_property_assign_value (ecma_object_t *obj_p, ecma_property_value_t *prop_value_p,
|
||||
@ -493,6 +501,10 @@ void ecma_set_named_accessor_property_getter (ecma_object_t *object_p, ecma_prop
|
||||
ecma_object_t *getter_p);
|
||||
void ecma_set_named_accessor_property_setter (ecma_object_t *object_p, ecma_property_value_t *prop_value_p,
|
||||
ecma_object_t *setter_p);
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
ecma_property_value_t *
|
||||
ecma_get_property_value_from_named_reference (ecma_property_value_t *reference_p);
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
bool ecma_is_property_writable (ecma_property_t property);
|
||||
void ecma_set_property_writable_attr (ecma_property_t *property_p, bool is_writable);
|
||||
bool ecma_is_property_enumerable (ecma_property_t property);
|
||||
|
||||
@ -393,15 +393,9 @@ ecma_module_evaluate (ecma_module_t *module_p) /**< module */
|
||||
}
|
||||
|
||||
JERRY_ASSERT (module_p->header.u.cls.u1.module_state == JERRY_MODULE_STATE_LINKED);
|
||||
|
||||
#if JERRY_BUILTIN_REALMS
|
||||
ecma_object_t *global_object_p = (ecma_object_t *) ecma_op_function_get_realm (module_p->compiled_code_p);
|
||||
#else /* !JERRY_BUILTIN_REALMS */
|
||||
ecma_object_t *global_object_p = ecma_builtin_get_global ();
|
||||
#endif /* JERRY_BUILTIN_REALMS */
|
||||
JERRY_ASSERT (module_p->scope_p != NULL);
|
||||
|
||||
module_p->header.u.cls.u1.module_state = JERRY_MODULE_STATE_EVALUATING;
|
||||
module_p->scope_p = ecma_create_decl_lex_env (ecma_get_global_environment (global_object_p));
|
||||
|
||||
ecma_value_t ret_value;
|
||||
ret_value = vm_run_module (module_p);
|
||||
@ -457,21 +451,11 @@ ecma_module_namespace_object_add_export_if_needed (ecma_module_t *module_p, /**<
|
||||
return result;
|
||||
}
|
||||
|
||||
ecma_object_t *ref_base_lex_env_p;
|
||||
ecma_value_t prop_value = ecma_op_get_value_lex_env_base (record.module_p->scope_p,
|
||||
&ref_base_lex_env_p,
|
||||
record.name_p);
|
||||
ecma_property_t *new_property_p;
|
||||
ecma_create_named_data_property (module_p->namespace_object_p,
|
||||
export_name_p,
|
||||
ECMA_PROPERTY_FIXED,
|
||||
&new_property_p);
|
||||
ecma_property_t *property_p = ecma_find_named_property (record.module_p->scope_p, record.name_p);
|
||||
|
||||
ecma_named_data_property_assign_value (module_p->namespace_object_p,
|
||||
ECMA_PROPERTY_VALUE_PTR (new_property_p),
|
||||
prop_value);
|
||||
|
||||
ecma_free_value (prop_value);
|
||||
ecma_create_named_reference_property (module_p->namespace_object_p,
|
||||
export_name_p,
|
||||
property_p);
|
||||
return result;
|
||||
} /* ecma_module_namespace_object_add_export_if_needed */
|
||||
|
||||
@ -491,13 +475,23 @@ ecma_module_create_namespace_object (ecma_module_t *module_p) /**< module */
|
||||
return result;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (module_p->header.u.cls.u1.module_state == JERRY_MODULE_STATE_EVALUATED);
|
||||
JERRY_ASSERT (module_p->header.u.cls.u1.module_state >= JERRY_MODULE_STATE_LINKED
|
||||
&& module_p->header.u.cls.u1.module_state <= JERRY_MODULE_STATE_EVALUATED);
|
||||
ecma_module_resolve_set_t *resolve_set_p = NULL;
|
||||
ecma_module_resolve_stack_t *stack_p = NULL;
|
||||
|
||||
module_p->namespace_object_p = ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE),
|
||||
0,
|
||||
ECMA_OBJECT_TYPE_GENERAL);
|
||||
ecma_object_t *namespace_object_p = ecma_create_object (NULL,
|
||||
sizeof (ecma_extended_object_t),
|
||||
ECMA_OBJECT_TYPE_CLASS);
|
||||
|
||||
namespace_object_p->type_flags_refs &= (ecma_object_descriptor_t) ~ECMA_OBJECT_FLAG_EXTENSIBLE;
|
||||
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) namespace_object_p;
|
||||
ext_object_p->u.cls.type = ECMA_OBJECT_CLASS_MODULE_NAMESPACE;
|
||||
ECMA_SET_INTERNAL_VALUE_POINTER (ext_object_p->u.cls.u3.value, module_p);
|
||||
|
||||
module_p->namespace_object_p = namespace_object_p;
|
||||
ecma_deref_object (namespace_object_p);
|
||||
|
||||
ecma_module_resolve_stack_push (&stack_p, module_p, ecma_get_magic_string (LIT_MAGIC_STRING_ASTERIX_CHAR));
|
||||
while (stack_p != NULL)
|
||||
@ -516,13 +510,6 @@ ecma_module_create_namespace_object (ecma_module_t *module_p) /**< module */
|
||||
continue;
|
||||
}
|
||||
|
||||
result = ecma_module_evaluate (current_module_p);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (result))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ecma_module_names_t *export_names_p = current_module_p->local_exports_p;
|
||||
|
||||
if (export_names_p != NULL)
|
||||
@ -569,6 +556,11 @@ ecma_module_create_namespace_object (ecma_module_t *module_p) /**< module */
|
||||
|
||||
star_export_p = star_export_p->next_p;
|
||||
}
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (result))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clean up. */
|
||||
@ -659,8 +651,6 @@ ecma_module_connect_imports (ecma_module_t *module_p)
|
||||
const bool is_namespace_import = ecma_compare_ecma_string_to_magic_id (import_names_p->imex_name_p,
|
||||
LIT_MAGIC_STRING_ASTERIX_CHAR);
|
||||
|
||||
ecma_value_t prop_value;
|
||||
|
||||
if (is_namespace_import)
|
||||
{
|
||||
result = ecma_module_create_namespace_object (imported_module_p);
|
||||
@ -670,8 +660,12 @@ ecma_module_connect_imports (ecma_module_t *module_p)
|
||||
return result;
|
||||
}
|
||||
|
||||
ecma_ref_object (imported_module_p->namespace_object_p);
|
||||
prop_value = ecma_make_object_value (imported_module_p->namespace_object_p);
|
||||
ecma_property_value_t *value_p;
|
||||
value_p = ecma_create_named_data_property (module_p->scope_p,
|
||||
import_names_p->local_name_p,
|
||||
ECMA_PROPERTY_FLAG_WRITABLE,
|
||||
NULL);
|
||||
value_p->value = ecma_make_object_value (imported_module_p->namespace_object_p);
|
||||
}
|
||||
else /* !is_namespace_import */
|
||||
{
|
||||
@ -691,46 +685,28 @@ ecma_module_connect_imports (ecma_module_t *module_p)
|
||||
if (record.module_p->header.u.cls.u1.module_state == JERRY_MODULE_STATE_NATIVE)
|
||||
{
|
||||
ecma_object_t *object_p = record.module_p->namespace_object_p;
|
||||
ecma_value_t prop_value;
|
||||
|
||||
prop_value = ecma_op_object_find_own (ecma_make_object_value (object_p), object_p, record.name_p);
|
||||
JERRY_ASSERT (ecma_is_value_found (prop_value));
|
||||
|
||||
ecma_property_value_t *value_p;
|
||||
value_p = ecma_create_named_data_property (module_p->scope_p,
|
||||
import_names_p->local_name_p,
|
||||
ECMA_PROPERTY_FLAG_WRITABLE,
|
||||
NULL);
|
||||
value_p->value = ecma_copy_value_if_not_object (prop_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = ecma_module_evaluate (record.module_p);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
ecma_object_t *ref_base_lex_env_p;
|
||||
prop_value = ecma_op_get_value_lex_env_base (record.module_p->scope_p,
|
||||
&ref_base_lex_env_p,
|
||||
record.name_p);
|
||||
ecma_property_t *property_p = ecma_find_named_property (record.module_p->scope_p, record.name_p);
|
||||
|
||||
ecma_create_named_reference_property (module_p->scope_p,
|
||||
import_names_p->local_name_p,
|
||||
property_p);
|
||||
}
|
||||
}
|
||||
|
||||
ecma_property_t *prop_p = ecma_op_create_mutable_binding (local_env_p,
|
||||
import_names_p->local_name_p,
|
||||
true /* is_deletable */);
|
||||
JERRY_ASSERT (prop_p != ECMA_PROPERTY_POINTER_ERROR);
|
||||
|
||||
if (prop_p != NULL)
|
||||
{
|
||||
JERRY_ASSERT (ecma_is_value_undefined (ECMA_PROPERTY_VALUE_PTR (prop_p)->value));
|
||||
ECMA_PROPERTY_VALUE_PTR (prop_p)->value = prop_value;
|
||||
ecma_deref_if_object (prop_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_op_set_mutable_binding (local_env_p,
|
||||
import_names_p->local_name_p,
|
||||
prop_value,
|
||||
false /* is_strict */);
|
||||
ecma_free_value (prop_value);
|
||||
}
|
||||
|
||||
import_names_p = import_names_p->next_p;
|
||||
}
|
||||
|
||||
@ -975,6 +951,20 @@ restart:
|
||||
node_p = node_p->next_p;
|
||||
}
|
||||
|
||||
if (current_module_p->scope_p == NULL)
|
||||
{
|
||||
/* Initialize scope for handling circular references. */
|
||||
ecma_value_t result = vm_init_module_scope (current_module_p);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (result))
|
||||
{
|
||||
module_p->header.u.cls.u1.module_state = JERRY_MODULE_STATE_ERROR;
|
||||
goto error;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (result == ECMA_VALUE_EMPTY);
|
||||
}
|
||||
|
||||
if (current_module_p->header.u.cls.u3.dfs_ancestor_index != current_p->dfs_index)
|
||||
{
|
||||
current_p = current_p->parent_p;
|
||||
@ -1079,15 +1069,10 @@ ecma_module_release_module (ecma_module_t *module_p) /**< module */
|
||||
|
||||
JERRY_ASSERT (state != JERRY_MODULE_STATE_INVALID);
|
||||
|
||||
if (module_p->namespace_object_p != NULL)
|
||||
{
|
||||
/* The module structure keeps a strong reference to the namespace object, which will require an extra GC call. */
|
||||
JERRY_CONTEXT (ecma_gc_new_objects)++;
|
||||
ecma_deref_object (module_p->namespace_object_p);
|
||||
#ifndef JERRY_NDEBUG
|
||||
module_p->namespace_object_p = NULL;
|
||||
module_p->scope_p = NULL;
|
||||
module_p->namespace_object_p = NULL;
|
||||
#endif /* JERRY_NDEBUG */
|
||||
}
|
||||
|
||||
if (state == JERRY_MODULE_STATE_NATIVE)
|
||||
{
|
||||
@ -1099,13 +1084,6 @@ ecma_module_release_module (ecma_module_t *module_p) /**< module */
|
||||
ecma_module_release_module_nodes (module_p->indirect_exports_p, false);
|
||||
ecma_module_release_module_nodes (module_p->star_exports_p, false);
|
||||
|
||||
if (state >= JERRY_MODULE_STATE_EVALUATING)
|
||||
{
|
||||
/* The module structure keeps a strong reference to the module scope, which will require an extra GC call. */
|
||||
JERRY_CONTEXT (ecma_gc_new_objects)++;
|
||||
ecma_deref_object (module_p->scope_p);
|
||||
}
|
||||
|
||||
if (module_p->compiled_code_p != NULL)
|
||||
{
|
||||
ecma_bytecode_deref (module_p->compiled_code_p);
|
||||
|
||||
@ -593,9 +593,7 @@ ecma_builtin_create_global_object (void)
|
||||
global_object_p->global_scope_cp = global_object_p->global_env_cp;
|
||||
#endif /* JERRY_ESNEXT */
|
||||
|
||||
ecma_object_t *global_lex_env_p = ecma_create_object_lex_env (NULL,
|
||||
object_p,
|
||||
ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND);
|
||||
ecma_object_t *global_lex_env_p = ecma_create_object_lex_env (NULL, object_p);
|
||||
ECMA_SET_NON_NULL_POINTER (global_object_p->global_env_cp, global_lex_env_p);
|
||||
#if JERRY_ESNEXT
|
||||
global_object_p->global_scope_cp = global_object_p->global_env_cp;
|
||||
|
||||
@ -899,7 +899,7 @@ ecma_delete_array_properties (ecma_object_t *object_p, /**< object */
|
||||
JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (current_prop_p));
|
||||
ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) current_prop_p;
|
||||
|
||||
for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
|
||||
for (uint32_t i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
|
||||
{
|
||||
if (current_prop_p->types[i] != ECMA_PROPERTY_TYPE_DELETED
|
||||
&& ecma_is_property_configurable (current_prop_p->types[i]))
|
||||
@ -920,7 +920,7 @@ ecma_delete_array_properties (ecma_object_t *object_p, /**< object */
|
||||
}
|
||||
#endif /* JERRY_PROPRETY_HASHMAP */
|
||||
|
||||
ecma_free_property (object_p, prop_pair_p->names_cp[i], current_prop_p->types + i);
|
||||
ecma_gc_free_property (object_p, prop_pair_p, i);
|
||||
current_prop_p->types[i] = ECMA_PROPERTY_TYPE_DELETED;
|
||||
prop_pair_p->names_cp[i] = LIT_INTERNAL_MAGIC_STRING_DELETED;
|
||||
}
|
||||
|
||||
@ -67,8 +67,7 @@ ecma_op_get_value_lex_env_base (ecma_object_t *lex_env_p, /**< lexical environme
|
||||
#if JERRY_ESNEXT
|
||||
if (JERRY_UNLIKELY (property_value_p->value == ECMA_VALUE_UNINITIALIZED))
|
||||
{
|
||||
return ecma_raise_reference_error (ECMA_ERR_MSG ("Variables declared by let/const must be"
|
||||
" initialized before reading their value"));
|
||||
return ecma_raise_reference_error (ECMA_ERR_MSG (ecma_error_let_const_not_initialized));
|
||||
}
|
||||
#endif /* JERRY_ESNEXT */
|
||||
|
||||
@ -77,8 +76,32 @@ ecma_op_get_value_lex_env_base (ecma_object_t *lex_env_p, /**< lexical environme
|
||||
break;
|
||||
}
|
||||
#if JERRY_ESNEXT
|
||||
case ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND:
|
||||
case ECMA_LEXICAL_ENVIRONMENT_CLASS:
|
||||
{
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
if (lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA)
|
||||
{
|
||||
ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p);
|
||||
|
||||
if (property_p != NULL)
|
||||
{
|
||||
*ref_base_lex_env_p = lex_env_p;
|
||||
ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
|
||||
|
||||
if (!(*property_p & ECMA_PROPERTY_FLAG_DATA))
|
||||
{
|
||||
property_value_p = ecma_get_property_value_from_named_reference (property_value_p);
|
||||
}
|
||||
|
||||
if (JERRY_UNLIKELY (property_value_p->value == ECMA_VALUE_UNINITIALIZED))
|
||||
{
|
||||
return ecma_raise_reference_error (ECMA_ERR_MSG (ecma_error_let_const_not_initialized));
|
||||
}
|
||||
|
||||
return ecma_fast_copy_value (property_value_p->value);
|
||||
}
|
||||
}
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
break;
|
||||
}
|
||||
#endif /* JERRY_ESNEXT */
|
||||
@ -215,52 +238,47 @@ ecma_op_put_value_lex_env_base (ecma_object_t *lex_env_p, /**< lexical environme
|
||||
{
|
||||
switch (ecma_get_lex_env_type (lex_env_p))
|
||||
{
|
||||
#if JERRY_ESNEXT
|
||||
case ECMA_LEXICAL_ENVIRONMENT_CLASS:
|
||||
{
|
||||
if ((lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
}
|
||||
#endif /* JERRY_ESNEXT */
|
||||
case ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE:
|
||||
{
|
||||
ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p);
|
||||
|
||||
if (property_p != NULL)
|
||||
{
|
||||
#if JERRY_ESNEXT
|
||||
ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
|
||||
|
||||
JERRY_ASSERT (!(*property_p & ECMA_PROPERTY_FLAG_WRITABLE)
|
||||
|| (*property_p & ECMA_PROPERTY_FLAG_DATA));
|
||||
|
||||
if ((*property_p & ECMA_PROPERTY_FLAG_WRITABLE)
|
||||
&& property_value_p->value != ECMA_VALUE_UNINITIALIZED)
|
||||
{
|
||||
ecma_named_data_property_assign_value (lex_env_p, property_value_p, value);
|
||||
return ECMA_VALUE_EMPTY;
|
||||
}
|
||||
#else /* JERRY_ESNEXT */
|
||||
if (ecma_is_property_writable (*property_p))
|
||||
{
|
||||
ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
|
||||
|
||||
#if JERRY_ESNEXT
|
||||
if (JERRY_UNLIKELY (property_value_p->value == ECMA_VALUE_UNINITIALIZED))
|
||||
{
|
||||
return ecma_raise_reference_error (ECMA_ERR_MSG ("Variables declared by let/const must be"
|
||||
" initialized before writing their value"));
|
||||
}
|
||||
#endif /* JERRY_ESNEXT */
|
||||
|
||||
ecma_named_data_property_assign_value (lex_env_p, property_value_p, value);
|
||||
}
|
||||
#if JERRY_ESNEXT
|
||||
else if (ecma_is_property_enumerable (*property_p))
|
||||
{
|
||||
if (JERRY_UNLIKELY (ECMA_PROPERTY_VALUE_PTR (property_p)->value == ECMA_VALUE_UNINITIALIZED))
|
||||
{
|
||||
return ecma_raise_reference_error (ECMA_ERR_MSG ("Variables declared by let/const must be"
|
||||
" initialized before writing their value"));
|
||||
}
|
||||
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Constant bindings cannot be reassigned"));
|
||||
return ECMA_VALUE_EMPTY;
|
||||
}
|
||||
#endif /* JERRY_ESNEXT */
|
||||
else if (is_strict)
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Binding cannot be set"));
|
||||
}
|
||||
return ECMA_VALUE_EMPTY;
|
||||
|
||||
return ecma_op_raise_set_binding_error (property_p, is_strict);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#if JERRY_ESNEXT
|
||||
case ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND:
|
||||
{
|
||||
break;
|
||||
}
|
||||
#endif /* JERRY_ESNEXT */
|
||||
default:
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND);
|
||||
|
||||
@ -88,6 +88,42 @@ ecma_create_global_lexical_block (ecma_object_t *global_object_p) /**< global ob
|
||||
} /* ecma_create_global_lexical_block */
|
||||
#endif /* JERRY_ESNEXT */
|
||||
|
||||
/**
|
||||
* Raise the appropriate error when setting a binding is failed
|
||||
*
|
||||
* @return ECMA_VALUE_EMPTY or ECMA_VALUE_ERROR
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_op_raise_set_binding_error (ecma_property_t *property_p, /**< property */
|
||||
bool is_strict) /**< flag indicating strict mode */
|
||||
{
|
||||
JERRY_UNUSED (property_p);
|
||||
|
||||
#if JERRY_ESNEXT
|
||||
const ecma_property_t expected_bits = (ECMA_PROPERTY_FLAG_DATA | ECMA_PROPERTY_FLAG_ENUMERABLE);
|
||||
|
||||
if ((*property_p & expected_bits) == expected_bits)
|
||||
{
|
||||
ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
|
||||
|
||||
if (JERRY_UNLIKELY (property_value_p->value == ECMA_VALUE_UNINITIALIZED))
|
||||
{
|
||||
return ecma_raise_reference_error (ECMA_ERR_MSG (ecma_error_let_const_not_initialized));
|
||||
}
|
||||
|
||||
JERRY_ASSERT (!ecma_is_property_writable (*property_p));
|
||||
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Constant bindings cannot be reassigned"));
|
||||
}
|
||||
#endif /* JERRY_ESNEXT */
|
||||
|
||||
if (is_strict)
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Binding cannot be set"));
|
||||
}
|
||||
return ECMA_VALUE_EMPTY;
|
||||
} /* ecma_op_raise_set_binding_error */
|
||||
|
||||
/**
|
||||
* Get reference to Global lexical scope
|
||||
* without increasing its reference count.
|
||||
@ -125,18 +161,33 @@ ecma_op_has_binding (ecma_object_t *lex_env_p, /**< lexical environment */
|
||||
|
||||
ecma_lexical_environment_type_t lex_env_type = ecma_get_lex_env_type (lex_env_p);
|
||||
|
||||
if (lex_env_type == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
|
||||
switch (lex_env_type)
|
||||
{
|
||||
ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p);
|
||||
#if JERRY_ESNEXT
|
||||
case ECMA_LEXICAL_ENVIRONMENT_CLASS:
|
||||
{
|
||||
if ((lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA) == 0)
|
||||
{
|
||||
return ECMA_VALUE_FALSE;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
}
|
||||
#endif /* JERRY_ESNEXT */
|
||||
case ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE:
|
||||
{
|
||||
ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p);
|
||||
|
||||
return ecma_make_boolean_value (property_p != NULL);
|
||||
return ecma_make_boolean_value (property_p != NULL);
|
||||
}
|
||||
default:
|
||||
{
|
||||
JERRY_ASSERT (lex_env_type == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND);
|
||||
|
||||
ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p);
|
||||
|
||||
return ecma_op_object_has_property (binding_obj_p, name_p);
|
||||
}
|
||||
}
|
||||
|
||||
JERRY_ASSERT (lex_env_type == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND);
|
||||
|
||||
ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p);
|
||||
|
||||
return ecma_op_object_has_property (binding_obj_p, name_p);
|
||||
} /* ecma_op_has_binding */
|
||||
|
||||
/**
|
||||
@ -245,53 +296,64 @@ ecma_op_set_mutable_binding (ecma_object_t *lex_env_p, /**< lexical environment
|
||||
&& ecma_is_lexical_environment (lex_env_p));
|
||||
JERRY_ASSERT (name_p != NULL);
|
||||
|
||||
if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
|
||||
switch (ecma_get_lex_env_type (lex_env_p))
|
||||
{
|
||||
ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p);
|
||||
|
||||
if (JERRY_UNLIKELY (property_p == NULL))
|
||||
{
|
||||
property_p = ecma_op_create_mutable_binding (lex_env_p, name_p, is_strict);
|
||||
JERRY_ASSERT (property_p != ECMA_PROPERTY_POINTER_ERROR);
|
||||
}
|
||||
|
||||
JERRY_ASSERT (property_p != NULL && ECMA_PROPERTY_IS_RAW_DATA (*property_p));
|
||||
|
||||
if (ecma_is_property_writable (*property_p))
|
||||
{
|
||||
ecma_named_data_property_assign_value (lex_env_p, ECMA_PROPERTY_VALUE_PTR (property_p), value);
|
||||
}
|
||||
#if JERRY_ESNEXT
|
||||
else if (ecma_is_property_enumerable (*property_p))
|
||||
case ECMA_LEXICAL_ENVIRONMENT_CLASS:
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Constant bindings cannot be reassigned"));
|
||||
if ((lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA) == 0)
|
||||
{
|
||||
return ECMA_VALUE_EMPTY;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
}
|
||||
#endif /* JERRY_ESNEXT */
|
||||
else if (is_strict)
|
||||
case ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE:
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Binding cannot be set"));
|
||||
ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p);
|
||||
|
||||
if (JERRY_UNLIKELY (property_p == NULL))
|
||||
{
|
||||
property_p = ecma_op_create_mutable_binding (lex_env_p, name_p, is_strict);
|
||||
JERRY_ASSERT (property_p != ECMA_PROPERTY_POINTER_ERROR);
|
||||
}
|
||||
|
||||
JERRY_ASSERT (property_p != NULL && ECMA_PROPERTY_IS_RAW_DATA (*property_p));
|
||||
JERRY_ASSERT (!(*property_p & ECMA_PROPERTY_FLAG_WRITABLE)
|
||||
|| (*property_p & ECMA_PROPERTY_FLAG_DATA));
|
||||
|
||||
if ((*property_p & ECMA_PROPERTY_FLAG_WRITABLE))
|
||||
{
|
||||
ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
|
||||
|
||||
JERRY_ASSERT (property_value_p->value != ECMA_VALUE_UNINITIALIZED);
|
||||
|
||||
ecma_named_data_property_assign_value (lex_env_p, property_value_p, value);
|
||||
return ECMA_VALUE_EMPTY;
|
||||
}
|
||||
|
||||
return ecma_op_raise_set_binding_error (property_p, is_strict);
|
||||
}
|
||||
default:
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND);
|
||||
|
||||
ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p);
|
||||
|
||||
ecma_value_t completion = ecma_op_object_put (binding_obj_p,
|
||||
name_p,
|
||||
value,
|
||||
is_strict);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (completion))
|
||||
{
|
||||
return completion;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_boolean (completion));
|
||||
return ECMA_VALUE_EMPTY;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND);
|
||||
|
||||
ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p);
|
||||
|
||||
ecma_value_t completion = ecma_op_object_put (binding_obj_p,
|
||||
name_p,
|
||||
value,
|
||||
is_strict);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (completion))
|
||||
{
|
||||
return completion;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (ecma_is_value_boolean (completion));
|
||||
}
|
||||
|
||||
return ECMA_VALUE_EMPTY;
|
||||
} /* ecma_op_set_mutable_binding */
|
||||
|
||||
/**
|
||||
|
||||
@ -37,6 +37,7 @@ ecma_object_t *ecma_get_global_scope (ecma_object_t *global_object_p);
|
||||
#if JERRY_ESNEXT
|
||||
void ecma_create_global_lexical_block (ecma_object_t *global_object_p);
|
||||
#endif /* JERRY_ESNEXT */
|
||||
ecma_value_t ecma_op_raise_set_binding_error (ecma_property_t *property_p, bool is_strict);
|
||||
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
void ecma_module_add_lex_env (ecma_object_t *lex_env_p);
|
||||
|
||||
@ -425,12 +425,33 @@ ecma_op_general_object_define_own_property (ecma_object_t *object_p, /**< the ob
|
||||
|
||||
if (ECMA_PROPERTY_IS_VIRTUAL (current_prop))
|
||||
{
|
||||
bool writable_check_failed = (property_desc_p->flags & ECMA_PROP_IS_WRITABLE);
|
||||
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
if (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_MODULE_NAMESPACE))
|
||||
{
|
||||
if (JERRY_UNLIKELY (ext_property_ref.property_ref.virtual_value == ECMA_VALUE_UNINITIALIZED))
|
||||
{
|
||||
return ecma_raise_reference_error (ECMA_ERR_MSG (ecma_error_let_const_not_initialized));
|
||||
}
|
||||
|
||||
if (property_desc_p->flags & ECMA_PROP_IS_WRITABLE_DEFINED)
|
||||
{
|
||||
writable_check_failed = ((property_desc_p->flags ^ current_prop) & ECMA_PROP_IS_WRITABLE) != 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (!is_current_configurable && !ecma_is_property_writable (current_prop));
|
||||
}
|
||||
#else /* !JERRY_MODULE_SYSTEM */
|
||||
JERRY_ASSERT (!is_current_configurable && !ecma_is_property_writable (current_prop));
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
|
||||
ecma_value_t result = ECMA_VALUE_TRUE;
|
||||
|
||||
if (property_desc_type == ECMA_OP_OBJECT_DEFINE_ACCESSOR
|
||||
|| (property_desc_p->flags & ECMA_PROP_IS_WRITABLE)
|
||||
|| writable_check_failed
|
||||
|| ((property_desc_p->flags & ECMA_PROP_IS_VALUE_DEFINED)
|
||||
&& !ecma_op_same_value (property_desc_p->value,
|
||||
ext_property_ref.property_ref.virtual_value)))
|
||||
|
||||
@ -183,6 +183,59 @@ ecma_op_object_get_own_property (ecma_object_t *object_p, /**< the object */
|
||||
break;
|
||||
}
|
||||
#endif /* JERRY_BUILTIN_TYPEDARRAY */
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
case ECMA_OBJECT_CLASS_MODULE_NAMESPACE:
|
||||
{
|
||||
if (JERRY_UNLIKELY (ecma_prop_name_is_symbol (property_name_p)))
|
||||
{
|
||||
if (!ecma_op_compare_string_to_global_symbol (property_name_p, LIT_GLOBAL_SYMBOL_TO_STRING_TAG))
|
||||
{
|
||||
return ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP;
|
||||
}
|
||||
|
||||
/* ECMA-262 v11, 26.3.1 */
|
||||
if (options & ECMA_PROPERTY_GET_VALUE)
|
||||
{
|
||||
property_ref_p->virtual_value = ecma_make_magic_string_value (LIT_MAGIC_STRING_MODULE_UL);
|
||||
}
|
||||
|
||||
return ECMA_PROPERTY_VIRTUAL;
|
||||
}
|
||||
|
||||
ecma_property_t *property_p = ecma_find_named_property (object_p, property_name_p);
|
||||
|
||||
if (property_p == NULL)
|
||||
{
|
||||
return ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (ECMA_PROPERTY_IS_RAW (*property_p));
|
||||
|
||||
if (*property_p & ECMA_PROPERTY_FLAG_DATA)
|
||||
{
|
||||
if (options & ECMA_PROPERTY_GET_EXT_REFERENCE)
|
||||
{
|
||||
((ecma_extended_property_ref_t *) property_ref_p)->property_p = property_p;
|
||||
}
|
||||
|
||||
if (property_ref_p != NULL)
|
||||
{
|
||||
property_ref_p->value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
|
||||
}
|
||||
|
||||
return *property_p;
|
||||
}
|
||||
|
||||
if (options & ECMA_PROPERTY_GET_VALUE)
|
||||
{
|
||||
ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
|
||||
prop_value_p = ecma_get_property_value_from_named_reference (prop_value_p);
|
||||
property_ref_p->virtual_value = ecma_fast_copy_value (prop_value_p->value);
|
||||
}
|
||||
|
||||
return ECMA_PROPERTY_ENUMERABLE_WRITABLE | ECMA_PROPERTY_VIRTUAL;
|
||||
}
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -538,6 +591,44 @@ ecma_op_object_find_own (ecma_value_t base_value, /**< base value */
|
||||
break;
|
||||
}
|
||||
#endif /* JERRY_BUILTIN_TYPEDARRAY */
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
case ECMA_OBJECT_CLASS_MODULE_NAMESPACE:
|
||||
{
|
||||
if (JERRY_UNLIKELY (ecma_prop_name_is_symbol (property_name_p)))
|
||||
{
|
||||
/* ECMA-262 v11, 26.3.1 */
|
||||
if (ecma_op_compare_string_to_global_symbol (property_name_p, LIT_GLOBAL_SYMBOL_TO_STRING_TAG))
|
||||
{
|
||||
return ecma_make_magic_string_value (LIT_MAGIC_STRING_MODULE_UL);
|
||||
}
|
||||
|
||||
return ECMA_VALUE_NOT_FOUND;
|
||||
}
|
||||
|
||||
ecma_property_t *property_p = ecma_find_named_property (object_p, property_name_p);
|
||||
|
||||
if (property_p == NULL)
|
||||
{
|
||||
return ECMA_VALUE_NOT_FOUND;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (ECMA_PROPERTY_IS_RAW (*property_p));
|
||||
|
||||
ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
|
||||
|
||||
if (!(*property_p & ECMA_PROPERTY_FLAG_DATA))
|
||||
{
|
||||
prop_value_p = ecma_get_property_value_from_named_reference (prop_value_p);
|
||||
|
||||
if (JERRY_UNLIKELY (prop_value_p->value == ECMA_VALUE_UNINITIALIZED))
|
||||
{
|
||||
return ecma_raise_reference_error (ECMA_ERR_MSG (ecma_error_let_const_not_initialized));
|
||||
}
|
||||
}
|
||||
|
||||
return ecma_fast_copy_value (prop_value_p->value);
|
||||
}
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -940,6 +1031,25 @@ ecma_op_get_global_symbol (lit_magic_string_id_t property_id) /**< property symb
|
||||
return symbol_p;
|
||||
} /* ecma_op_get_global_symbol */
|
||||
|
||||
/**
|
||||
* Checks whether the string equals to the global symbol.
|
||||
*
|
||||
* @return true - if the string equals to the global symbol
|
||||
* false - otherwise
|
||||
*/
|
||||
bool
|
||||
ecma_op_compare_string_to_global_symbol (ecma_string_t *string_p, /**< string to compare */
|
||||
lit_magic_string_id_t property_id) /**< property symbol id */
|
||||
{
|
||||
JERRY_ASSERT (LIT_IS_GLOBAL_SYMBOL (property_id));
|
||||
|
||||
uint32_t symbol_index = (uint32_t) property_id - (uint32_t) LIT_GLOBAL_SYMBOL__FIRST;
|
||||
jmem_cpointer_t symbol_cp = JERRY_CONTEXT (global_symbols_cp)[symbol_index];
|
||||
|
||||
return (symbol_cp != JMEM_CP_NULL
|
||||
&& string_p == ECMA_GET_NON_NULL_POINTER (ecma_string_t, symbol_cp));
|
||||
} /* ecma_op_compare_string_to_global_symbol */
|
||||
|
||||
/**
|
||||
* [[Get]] operation of ecma object where the property is a well-known symbol
|
||||
*
|
||||
@ -1327,6 +1437,12 @@ ecma_op_object_put_with_receiver (ecma_object_t *object_p, /**< the object */
|
||||
break;
|
||||
}
|
||||
#endif /* JERRY_BUILTIN_TYPEDARRAY */
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
case ECMA_OBJECT_CLASS_MODULE_NAMESPACE:
|
||||
{
|
||||
return ecma_raise_readonly_assignment (property_name_p, is_throw);
|
||||
}
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1837,6 +1953,12 @@ ecma_op_object_get_own_property_descriptor (ecma_object_t *object_p, /**< the ob
|
||||
}
|
||||
else
|
||||
{
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
if (JERRY_UNLIKELY (property_ref.virtual_value == ECMA_VALUE_UNINITIALIZED))
|
||||
{
|
||||
return ecma_raise_reference_error (ECMA_ERR_MSG (ecma_error_let_const_not_initialized));
|
||||
}
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
prop_desc_p->value = property_ref.virtual_value;
|
||||
}
|
||||
|
||||
@ -2685,6 +2807,9 @@ static const uint16_t ecma_class_object_magic_string_id[] =
|
||||
#if JERRY_BUILTIN_TYPEDARRAY
|
||||
LIT_MAGIC_STRING__EMPTY, /**< ECMA_OBJECT_CLASS_TYPEDARRAY needs special resolver */
|
||||
#endif /* JERRY_BUILTIN_TYPEDARRAY */
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
LIT_MAGIC_STRING_MODULE_UL, /**< magic string id of ECMA_OBJECT_CLASS_MODULE_NAMESPACE */
|
||||
#endif
|
||||
|
||||
/* These objects are marked by Garbage Collector. */
|
||||
#if JERRY_ESNEXT
|
||||
@ -2887,29 +3012,6 @@ ecma_object_get_class_name (ecma_object_t *obj_p) /**< object */
|
||||
}
|
||||
} /* ecma_object_get_class_name */
|
||||
|
||||
/**
|
||||
* Get value of an object if the class matches
|
||||
*
|
||||
* @return value of the object if the class matches
|
||||
* ECMA_VALUE_NOT_FOUND otherwise
|
||||
*/
|
||||
extern inline bool JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_object_class_is (ecma_object_t *object_p, /**< object */
|
||||
ecma_object_class_type_t class_id) /**< class id */
|
||||
{
|
||||
if (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_CLASS)
|
||||
{
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
if (ext_object_p->u.cls.type == (uint8_t) class_id)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} /* ecma_object_class_is */
|
||||
|
||||
#if JERRY_BUILTIN_REGEXP
|
||||
/**
|
||||
* Checks if the given argument has [[RegExpMatcher]] internal slot
|
||||
|
||||
@ -71,6 +71,7 @@ ecma_value_t ecma_op_object_get_by_index (ecma_object_t *object_p, ecma_length_t
|
||||
ecma_value_t ecma_op_object_get_by_magic_id (ecma_object_t *object_p, lit_magic_string_id_t property_id);
|
||||
#if JERRY_ESNEXT
|
||||
ecma_string_t *ecma_op_get_global_symbol (lit_magic_string_id_t property_id);
|
||||
bool ecma_op_compare_string_to_global_symbol (ecma_string_t *string_p, lit_magic_string_id_t property_id);
|
||||
ecma_value_t ecma_op_object_get_by_symbol_id (ecma_object_t *object_p, lit_magic_string_id_t property_id);
|
||||
ecma_value_t ecma_op_get_method_by_symbol_id (ecma_value_t value, lit_magic_string_id_t symbol_id);
|
||||
ecma_value_t ecma_op_get_method_by_magic_id (ecma_value_t value, lit_magic_string_id_t magic_id);
|
||||
@ -100,7 +101,6 @@ ecma_collection_t *ecma_op_object_own_property_keys (ecma_object_t *obj_p);
|
||||
ecma_collection_t *ecma_op_object_enumerate (ecma_object_t *obj_p);
|
||||
|
||||
lit_magic_string_id_t ecma_object_get_class_name (ecma_object_t *obj_p);
|
||||
bool ecma_object_class_is (ecma_object_t *object_p, ecma_object_class_type_t class_id);
|
||||
#if JERRY_BUILTIN_REGEXP
|
||||
bool ecma_object_is_regexp_object (ecma_value_t arg);
|
||||
#endif /* JERRY_BUILTIN_REGEXP */
|
||||
|
||||
@ -47,14 +47,6 @@ ecma_op_resolve_reference_base (ecma_object_t *lex_env_p, /**< starting lexical
|
||||
|
||||
while (true)
|
||||
{
|
||||
#if JERRY_ESNEXT
|
||||
if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND)
|
||||
{
|
||||
JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL);
|
||||
lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
|
||||
}
|
||||
#endif /* JERRY_ESNEXT */
|
||||
|
||||
ecma_value_t has_binding = ecma_op_has_binding (lex_env_p, name_p);
|
||||
|
||||
#if JERRY_BUILTIN_PROXY
|
||||
@ -114,11 +106,12 @@ ecma_op_is_global_environment (ecma_object_t *lex_env_p) /**< lexical environmen
|
||||
ecma_value_t
|
||||
ecma_op_resolve_super_base (ecma_object_t *lex_env_p) /**< starting lexical environment */
|
||||
{
|
||||
JERRY_ASSERT (lex_env_p != NULL);
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND)
|
||||
JERRY_ASSERT (lex_env_p != NULL);
|
||||
|
||||
if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_CLASS
|
||||
&& (lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA) == 0)
|
||||
{
|
||||
ecma_object_t *home_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u1.home_object_cp);
|
||||
|
||||
@ -297,82 +290,109 @@ ecma_op_resolve_reference_value (ecma_object_t *lex_env_p, /**< starting lexical
|
||||
|
||||
while (true)
|
||||
{
|
||||
ecma_lexical_environment_type_t lex_env_type = ecma_get_lex_env_type (lex_env_p);
|
||||
|
||||
if (lex_env_type == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
|
||||
switch (ecma_get_lex_env_type (lex_env_p))
|
||||
{
|
||||
ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p);
|
||||
|
||||
if (property_p != NULL)
|
||||
case ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE:
|
||||
{
|
||||
ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p);
|
||||
|
||||
if (property_p == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
|
||||
|
||||
#if JERRY_ESNEXT
|
||||
if (JERRY_UNLIKELY (property_value_p->value == ECMA_VALUE_UNINITIALIZED))
|
||||
{
|
||||
return ecma_raise_reference_error (ECMA_ERR_MSG ("Variables declared by let/const must be"
|
||||
" initialized before reading their value"));
|
||||
return ecma_raise_reference_error (ECMA_ERR_MSG (ecma_error_let_const_not_initialized));
|
||||
}
|
||||
#endif /* JERRY_ESNEXT */
|
||||
|
||||
return ecma_fast_copy_value (property_value_p->value);
|
||||
}
|
||||
}
|
||||
else if (lex_env_type == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND)
|
||||
{
|
||||
#if JERRY_ESNEXT
|
||||
bool lcache_lookup_allowed = ecma_op_is_global_environment (lex_env_p);
|
||||
#else /* !JERRY_ESNEXT*/
|
||||
bool lcache_lookup_allowed = true;
|
||||
#endif /* JERRY_ESNEXT */
|
||||
|
||||
if (lcache_lookup_allowed)
|
||||
case ECMA_LEXICAL_ENVIRONMENT_CLASS:
|
||||
{
|
||||
#if JERRY_LCACHE
|
||||
ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p);
|
||||
ecma_property_t *property_p = ecma_lcache_lookup (binding_obj_p, name_p);
|
||||
|
||||
if (property_p != NULL)
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
if (lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA)
|
||||
{
|
||||
JERRY_ASSERT (ECMA_PROPERTY_IS_RAW (*property_p));
|
||||
ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p);
|
||||
|
||||
ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
|
||||
|
||||
if (*property_p & ECMA_PROPERTY_FLAG_DATA)
|
||||
if (property_p == NULL)
|
||||
{
|
||||
return ecma_fast_copy_value (prop_value_p->value);
|
||||
break;
|
||||
}
|
||||
|
||||
ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (prop_value_p);
|
||||
ecma_property_value_t *property_value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
|
||||
|
||||
if (get_set_pair_p->getter_cp == JMEM_CP_NULL)
|
||||
if (!(*property_p & ECMA_PROPERTY_FLAG_DATA))
|
||||
{
|
||||
return ECMA_VALUE_UNDEFINED;
|
||||
property_value_p = ecma_get_property_value_from_named_reference (property_value_p);
|
||||
}
|
||||
|
||||
ecma_object_t *getter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->getter_cp);
|
||||
if (JERRY_UNLIKELY (property_value_p->value == ECMA_VALUE_UNINITIALIZED))
|
||||
{
|
||||
return ecma_raise_reference_error (ECMA_ERR_MSG (ecma_error_let_const_not_initialized));
|
||||
}
|
||||
|
||||
ecma_value_t base_value = ecma_make_object_value (binding_obj_p);
|
||||
return ecma_op_function_call (getter_p, base_value, NULL, 0);
|
||||
return ecma_fast_copy_value (property_value_p->value);
|
||||
}
|
||||
#endif /* JERRY_LCACHE */
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
break;
|
||||
}
|
||||
|
||||
ecma_value_t result = ecma_op_object_bound_environment_resolve_reference_value (lex_env_p, name_p);
|
||||
|
||||
if (ecma_is_value_found (result))
|
||||
{
|
||||
/* Note: the result may contains ECMA_VALUE_ERROR */
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if JERRY_ESNEXT
|
||||
JERRY_ASSERT (lex_env_type == ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND);
|
||||
#else /* !JERRY_ESNEXT */
|
||||
JERRY_UNREACHABLE ();
|
||||
#endif /* JERRY_ESNEXT */
|
||||
default:
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND);
|
||||
#if JERRY_ESNEXT
|
||||
bool lcache_lookup_allowed = ecma_op_is_global_environment (lex_env_p);
|
||||
#else /* !JERRY_ESNEXT*/
|
||||
bool lcache_lookup_allowed = true;
|
||||
#endif /* JERRY_ESNEXT */
|
||||
|
||||
if (lcache_lookup_allowed)
|
||||
{
|
||||
#if JERRY_LCACHE
|
||||
ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p);
|
||||
ecma_property_t *property_p = ecma_lcache_lookup (binding_obj_p, name_p);
|
||||
|
||||
if (property_p != NULL)
|
||||
{
|
||||
JERRY_ASSERT (ECMA_PROPERTY_IS_RAW (*property_p));
|
||||
|
||||
ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
|
||||
|
||||
if (*property_p & ECMA_PROPERTY_FLAG_DATA)
|
||||
{
|
||||
return ecma_fast_copy_value (prop_value_p->value);
|
||||
}
|
||||
|
||||
ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (prop_value_p);
|
||||
|
||||
if (get_set_pair_p->getter_cp == JMEM_CP_NULL)
|
||||
{
|
||||
return ECMA_VALUE_UNDEFINED;
|
||||
}
|
||||
|
||||
ecma_object_t *getter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->getter_cp);
|
||||
|
||||
ecma_value_t base_value = ecma_make_object_value (binding_obj_p);
|
||||
return ecma_op_function_call (getter_p, base_value, NULL, 0);
|
||||
}
|
||||
#endif /* JERRY_LCACHE */
|
||||
}
|
||||
|
||||
ecma_value_t result = ecma_op_object_bound_environment_resolve_reference_value (lex_env_p, name_p);
|
||||
|
||||
if (ecma_is_value_found (result))
|
||||
{
|
||||
/* Note: the result may contains ECMA_VALUE_ERROR */
|
||||
return result;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (lex_env_p->u2.outer_reference_cp == JMEM_CP_NULL)
|
||||
|
||||
@ -1979,7 +1979,13 @@ parser_parse_source (const uint8_t *arg_list_p, /**< function argument list */
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
else if (parse_opts & ECMA_PARSE_MODULE)
|
||||
{
|
||||
parser_branch_t branch;
|
||||
parser_emit_cbc_forward_branch (&context, CBC_JUMP_FORWARD, &branch);
|
||||
|
||||
scanner_create_variables (&context, SCANNER_CREATE_VARS_NO_OPTS);
|
||||
parser_emit_cbc (&context, CBC_RETURN_WITH_BLOCK);
|
||||
|
||||
parser_set_branch_to_current_position (&context, &branch);
|
||||
}
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
else
|
||||
|
||||
@ -1307,9 +1307,8 @@ opfunc_init_class (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
|
||||
|
||||
if (ecma_get_object_type (ctor_p) == ECMA_OBJECT_TYPE_FUNCTION)
|
||||
{
|
||||
ecma_object_t *proto_env_p = ecma_create_object_lex_env (frame_ctx_p->lex_env_p,
|
||||
proto_p,
|
||||
ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND);
|
||||
ecma_object_t *proto_env_p = ecma_create_lex_env_class (frame_ctx_p->lex_env_p, 0);
|
||||
ECMA_SET_NON_NULL_POINTER (proto_env_p->u1.bound_object_cp, proto_p);
|
||||
|
||||
ECMA_SET_NON_NULL_POINTER_TAG (((ecma_extended_object_t *) ctor_p)->u.function.scope_cp, proto_env_p, 0);
|
||||
|
||||
@ -1433,12 +1432,10 @@ opfunc_finalize_class (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
|
||||
ecma_op_initialize_binding (class_env_p, ecma_get_string_from_value (class_name), stack_top_p[-2]);
|
||||
}
|
||||
|
||||
ecma_object_t *ctor_env_p = ecma_create_object_lex_env (class_env_p,
|
||||
ctor_p,
|
||||
ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND);
|
||||
ecma_object_t *proto_env_p = ecma_create_object_lex_env (class_env_p,
|
||||
proto_p,
|
||||
ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND);
|
||||
ecma_object_t *ctor_env_p = ecma_create_lex_env_class (class_env_p, 0);
|
||||
ECMA_SET_NON_NULL_POINTER (ctor_env_p->u1.bound_object_cp, ctor_p);
|
||||
ecma_object_t *proto_env_p = ecma_create_lex_env_class (class_env_p, 0);
|
||||
ECMA_SET_NON_NULL_POINTER (proto_env_p->u1.bound_object_cp, proto_p);
|
||||
|
||||
opfunc_set_class_attributes (ctor_p, ctor_env_p);
|
||||
opfunc_set_class_attributes (proto_p, proto_env_p);
|
||||
|
||||
@ -262,33 +262,6 @@ static const uint16_t vm_decode_table[] JERRY_ATTR_CONST_DATA =
|
||||
|
||||
#undef CBC_OPCODE
|
||||
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
/**
|
||||
* Run module code
|
||||
*
|
||||
* Note:
|
||||
* returned value must be freed with ecma_free_value, when it is no longer needed.
|
||||
*
|
||||
* @return ecma value
|
||||
*/
|
||||
ecma_value_t
|
||||
vm_run_module (ecma_module_t *module_p) /**< module to be executed */
|
||||
{
|
||||
const ecma_value_t module_init_result = ecma_module_initialize (module_p);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (module_init_result))
|
||||
{
|
||||
return module_init_result;
|
||||
}
|
||||
|
||||
vm_frame_ctx_shared_t shared;
|
||||
shared.bytecode_header_p = module_p->compiled_code_p;
|
||||
shared.status_flags = 0;
|
||||
|
||||
return vm_run (&shared, ECMA_VALUE_UNDEFINED, module_p->scope_p);
|
||||
} /* vm_run_module */
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
|
||||
/**
|
||||
* Run global code
|
||||
*
|
||||
@ -432,6 +405,35 @@ vm_run_eval (ecma_compiled_code_t *bytecode_data_p, /**< byte-code data */
|
||||
return completion_value;
|
||||
} /* vm_run_eval */
|
||||
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
|
||||
/**
|
||||
* Run module code
|
||||
*
|
||||
* Note:
|
||||
* returned value must be freed with ecma_free_value, when it is no longer needed.
|
||||
*
|
||||
* @return ecma value
|
||||
*/
|
||||
ecma_value_t
|
||||
vm_run_module (ecma_module_t *module_p) /**< module to be executed */
|
||||
{
|
||||
const ecma_value_t module_init_result = ecma_module_initialize (module_p);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (module_init_result))
|
||||
{
|
||||
return module_init_result;
|
||||
}
|
||||
|
||||
vm_frame_ctx_shared_t shared;
|
||||
shared.bytecode_header_p = module_p->compiled_code_p;
|
||||
shared.status_flags = 0;
|
||||
|
||||
return vm_run (&shared, ECMA_VALUE_UNDEFINED, module_p->scope_p);
|
||||
} /* vm_run_module */
|
||||
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
|
||||
/**
|
||||
* Construct object
|
||||
*
|
||||
@ -1578,12 +1580,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
{
|
||||
uint32_t literal_index, value_index;
|
||||
ecma_value_t lit_value;
|
||||
bool release = false;
|
||||
|
||||
READ_LITERAL_INDEX (value_index);
|
||||
READ_LITERAL_INDEX (literal_index);
|
||||
|
||||
JERRY_ASSERT (value_index != literal_index);
|
||||
JERRY_ASSERT (value_index >= register_end || literal_index >= register_end);
|
||||
|
||||
if (value_index < register_end)
|
||||
{
|
||||
@ -1594,11 +1593,18 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
{
|
||||
lit_value = vm_construct_literal_object (frame_ctx_p,
|
||||
literal_start_p[value_index]);
|
||||
release = true;
|
||||
}
|
||||
|
||||
READ_LITERAL_INDEX (literal_index);
|
||||
|
||||
JERRY_ASSERT (value_index != literal_index);
|
||||
JERRY_ASSERT (value_index >= register_end || literal_index >= register_end);
|
||||
|
||||
if (literal_index < register_end)
|
||||
{
|
||||
ecma_fast_free_value (VM_GET_REGISTER (frame_ctx_p, literal_index));
|
||||
JERRY_ASSERT (release);
|
||||
VM_GET_REGISTER (frame_ctx_p, literal_index) = lit_value;
|
||||
continue;
|
||||
}
|
||||
@ -1617,11 +1623,10 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
JERRY_ASSERT (property_value_p->value == ECMA_VALUE_UNDEFINED);
|
||||
property_value_p->value = lit_value;
|
||||
|
||||
if (value_index >= register_end)
|
||||
if (release)
|
||||
{
|
||||
ecma_free_value (lit_value);
|
||||
ecma_deref_object (ecma_get_object_from_value (lit_value));
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
#if JERRY_ESNEXT
|
||||
@ -1701,12 +1706,16 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
READ_LITERAL_INDEX (literal_index);
|
||||
|
||||
JERRY_ASSERT (literal_index >= register_end);
|
||||
JERRY_ASSERT (ecma_get_lex_env_type (frame_ctx_p->lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE);
|
||||
JERRY_ASSERT (ecma_get_lex_env_type (frame_ctx_p->lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE
|
||||
|| (ecma_get_lex_env_type (frame_ctx_p->lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_CLASS
|
||||
&& (frame_ctx_p->lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA)));
|
||||
|
||||
ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]);
|
||||
ecma_property_t *property_p = ecma_find_named_property (frame_ctx_p->lex_env_p, name_p);
|
||||
|
||||
JERRY_ASSERT (property_p != NULL && ECMA_PROPERTY_IS_RAW_DATA (*property_p));
|
||||
JERRY_ASSERT (property_p != NULL
|
||||
&& ECMA_PROPERTY_IS_RAW_DATA (*property_p)
|
||||
&& (*property_p & ECMA_PROPERTY_FLAG_DATA));
|
||||
JERRY_ASSERT (ECMA_PROPERTY_VALUE_PTR (property_p)->value == ECMA_VALUE_UNINITIALIZED);
|
||||
|
||||
ECMA_PROPERTY_VALUE_PTR (property_p)->value = left_value;
|
||||
@ -2176,10 +2185,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
if (opcode == CBC_EXT_PUSH_OBJECT_SUPER_ENVIRONMENT)
|
||||
{
|
||||
ecma_value_t obj_value = stack_top_p[-1];
|
||||
ecma_object_t *obj_env_p = ecma_create_object_lex_env (frame_ctx_p->lex_env_p,
|
||||
ecma_get_object_from_value (obj_value),
|
||||
ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND);
|
||||
ecma_object_t *obj_env_p = ecma_create_lex_env_class (frame_ctx_p->lex_env_p, 0);
|
||||
|
||||
ECMA_SET_NON_NULL_POINTER (obj_env_p->u1.bound_object_cp, ecma_get_object_from_value (obj_value));
|
||||
stack_top_p[-1] = ecma_make_object_value (obj_env_p);
|
||||
*stack_top_p++ = obj_value;
|
||||
}
|
||||
@ -4029,9 +4037,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
|
||||
object_p = ecma_get_object_from_value (result);
|
||||
|
||||
with_env_p = ecma_create_object_lex_env (frame_ctx_p->lex_env_p,
|
||||
object_p,
|
||||
ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND);
|
||||
with_env_p = ecma_create_object_lex_env (frame_ctx_p->lex_env_p, object_p);
|
||||
ecma_deref_object (object_p);
|
||||
|
||||
VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_WITH_CONTEXT_STACK_ALLOCATION);
|
||||
@ -4914,6 +4920,172 @@ finish:
|
||||
}
|
||||
} /* vm_loop */
|
||||
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
|
||||
/**
|
||||
* Create and initialize module scope with all data properties
|
||||
*
|
||||
* @return ECMA_VALUE_EMPTY on success,
|
||||
* ECMA_VALUE_ERROR on failure
|
||||
*/
|
||||
ecma_value_t
|
||||
vm_init_module_scope (ecma_module_t *module_p) /**< module without scope */
|
||||
{
|
||||
ecma_object_t *global_object_p;
|
||||
#if JERRY_BUILTIN_REALMS
|
||||
global_object_p = (ecma_object_t *) ecma_op_function_get_realm (module_p->compiled_code_p);
|
||||
#else /* !JERRY_BUILTIN_REALMS */
|
||||
global_object_p = ecma_builtin_get_global ();
|
||||
#endif /* JERRY_BUILTIN_REALMS */
|
||||
|
||||
ecma_object_t *scope_p = ecma_create_lex_env_class (ecma_get_global_environment (global_object_p),
|
||||
sizeof (ecma_lexical_environment_class_t));
|
||||
const ecma_compiled_code_t *compiled_code_p = module_p->compiled_code_p;
|
||||
ecma_value_t *literal_start_p;
|
||||
uint8_t *byte_code_p;
|
||||
uint16_t encoding_limit;
|
||||
uint16_t encoding_delta;
|
||||
|
||||
((ecma_lexical_environment_class_t *) scope_p)->module_p = (ecma_object_t *) module_p;
|
||||
|
||||
module_p->scope_p = scope_p;
|
||||
ecma_deref_object (scope_p);
|
||||
|
||||
if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
|
||||
{
|
||||
cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) compiled_code_p;
|
||||
|
||||
literal_start_p = (ecma_value_t *) (args_p + 1);
|
||||
literal_start_p -= args_p->register_end;
|
||||
byte_code_p = (uint8_t *) (literal_start_p + args_p->literal_end);
|
||||
}
|
||||
else
|
||||
{
|
||||
cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) compiled_code_p;
|
||||
|
||||
literal_start_p = (ecma_value_t *) (args_p + 1);
|
||||
literal_start_p -= args_p->register_end;
|
||||
byte_code_p = (uint8_t *) (literal_start_p + args_p->literal_end);
|
||||
}
|
||||
|
||||
/* Prepare for byte code execution. */
|
||||
if (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_FULL_LITERAL_ENCODING))
|
||||
{
|
||||
encoding_limit = CBC_SMALL_LITERAL_ENCODING_LIMIT;
|
||||
encoding_delta = CBC_SMALL_LITERAL_ENCODING_DELTA;
|
||||
}
|
||||
else
|
||||
{
|
||||
encoding_limit = CBC_FULL_LITERAL_ENCODING_LIMIT;
|
||||
encoding_delta = CBC_FULL_LITERAL_ENCODING_DELTA;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (*byte_code_p >= CBC_JUMP_FORWARD && *byte_code_p <= CBC_JUMP_FORWARD_3);
|
||||
|
||||
byte_code_p += 1 + CBC_BRANCH_OFFSET_LENGTH (*byte_code_p);
|
||||
|
||||
while (true)
|
||||
{
|
||||
uint8_t opcode = *byte_code_p++;
|
||||
|
||||
switch (opcode)
|
||||
{
|
||||
case CBC_CREATE_VAR:
|
||||
case CBC_CREATE_LET:
|
||||
case CBC_CREATE_CONST:
|
||||
{
|
||||
uint32_t literal_index;
|
||||
|
||||
READ_LITERAL_INDEX (literal_index);
|
||||
|
||||
ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]);
|
||||
|
||||
JERRY_ASSERT (ecma_find_named_property (scope_p, name_p) == NULL);
|
||||
|
||||
uint8_t prop_attributes = ECMA_PROPERTY_FLAG_WRITABLE;
|
||||
|
||||
if (opcode == CBC_CREATE_LET)
|
||||
{
|
||||
prop_attributes = ECMA_PROPERTY_ENUMERABLE_WRITABLE;
|
||||
}
|
||||
else if (opcode == CBC_CREATE_CONST)
|
||||
{
|
||||
prop_attributes = ECMA_PROPERTY_FLAG_ENUMERABLE;
|
||||
}
|
||||
|
||||
ecma_property_value_t *property_value_p;
|
||||
property_value_p = ecma_create_named_data_property (scope_p, name_p, prop_attributes, NULL);
|
||||
|
||||
if (opcode != CBC_CREATE_VAR)
|
||||
{
|
||||
property_value_p->value = ECMA_VALUE_UNINITIALIZED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CBC_INIT_ARG_OR_FUNC:
|
||||
{
|
||||
uint32_t literal_index;
|
||||
|
||||
READ_LITERAL_INDEX (literal_index);
|
||||
|
||||
ecma_compiled_code_t *function_bytecode_p;
|
||||
#if JERRY_SNAPSHOT_EXEC
|
||||
if (JERRY_LIKELY (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)))
|
||||
{
|
||||
#endif /* JERRY_SNAPSHOT_EXEC */
|
||||
function_bytecode_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t,
|
||||
literal_start_p[literal_index]);
|
||||
#if JERRY_SNAPSHOT_EXEC
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t *byte_p = ((uint8_t *) compiled_code_p) + literal_start_p[literal_index];
|
||||
function_bytecode_p = (ecma_compiled_code_t *) byte_p;
|
||||
}
|
||||
#endif /* JERRY_SNAPSHOT_EXEC */
|
||||
|
||||
JERRY_ASSERT (CBC_IS_FUNCTION (function_bytecode_p->status_flags));
|
||||
|
||||
ecma_object_t *function_obj_p;
|
||||
|
||||
if (JERRY_UNLIKELY (CBC_FUNCTION_IS_ARROW (function_bytecode_p->status_flags)))
|
||||
{
|
||||
function_obj_p = ecma_op_create_arrow_function_object (scope_p,
|
||||
function_bytecode_p,
|
||||
ECMA_VALUE_UNDEFINED);
|
||||
}
|
||||
else
|
||||
{
|
||||
function_obj_p = ecma_op_create_any_function_object (scope_p, function_bytecode_p);
|
||||
}
|
||||
|
||||
READ_LITERAL_INDEX (literal_index);
|
||||
ecma_string_t *name_p = ecma_get_string_from_value (literal_start_p[literal_index]);
|
||||
|
||||
JERRY_ASSERT (ecma_find_named_property (scope_p, name_p) == NULL);
|
||||
|
||||
ecma_property_value_t *property_value_p;
|
||||
property_value_p = ecma_create_named_data_property (scope_p,
|
||||
name_p,
|
||||
ECMA_PROPERTY_FLAG_WRITABLE,
|
||||
NULL);
|
||||
|
||||
JERRY_ASSERT (property_value_p->value == ECMA_VALUE_UNDEFINED);
|
||||
property_value_p->value = ecma_make_object_value (function_obj_p);
|
||||
ecma_deref_object (function_obj_p);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
JERRY_ASSERT (opcode == CBC_RETURN_WITH_BLOCK);
|
||||
return ECMA_VALUE_EMPTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
} /* vm_init_module_scope */
|
||||
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
|
||||
#undef READ_LITERAL
|
||||
#undef READ_LITERAL_INDEX
|
||||
|
||||
|
||||
@ -481,6 +481,7 @@ ecma_value_t vm_run_eval (ecma_compiled_code_t *bytecode_data_p, uint32_t parse_
|
||||
|
||||
#if JERRY_MODULE_SYSTEM
|
||||
ecma_value_t vm_run_module (ecma_module_t *module_p);
|
||||
ecma_value_t vm_init_module_scope (ecma_module_t *module_p);
|
||||
#endif /* JERRY_MODULE_SYSTEM */
|
||||
|
||||
ecma_value_t vm_run (vm_frame_ctx_shared_t *shared_p, ecma_value_t this_binding_value, ecma_object_t *lex_env_p);
|
||||
|
||||
38
tests/jerry/es.next/module-circular-01.mjs
Normal file
38
tests/jerry/es.next/module-circular-01.mjs
Normal file
@ -0,0 +1,38 @@
|
||||
// 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.
|
||||
|
||||
export var a = 0
|
||||
export let b = 1
|
||||
|
||||
function other() {
|
||||
return 33.5
|
||||
}
|
||||
|
||||
export function early() {
|
||||
// This function is called before the module is executed
|
||||
assert(other() === 33.5)
|
||||
assert(a === undefined)
|
||||
a = "X"
|
||||
|
||||
try {
|
||||
b
|
||||
assert(false)
|
||||
} catch (e) {
|
||||
assert(e instanceof ReferenceError)
|
||||
}
|
||||
}
|
||||
|
||||
early = "Loaded"
|
||||
|
||||
import * as o from "module-circular-02.mjs"
|
||||
85
tests/jerry/es.next/module-circular-02.mjs
Normal file
85
tests/jerry/es.next/module-circular-02.mjs
Normal file
@ -0,0 +1,85 @@
|
||||
// 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.
|
||||
|
||||
import * as o from "module-circular-01.mjs"
|
||||
|
||||
if (o.early != "Loaded")
|
||||
{
|
||||
// The scope of module-circular-01.mjs is initialized and functions are usable
|
||||
// However, the module script has not been executed
|
||||
|
||||
assert(o.a === undefined)
|
||||
o.early()
|
||||
assert(o.a === "X")
|
||||
|
||||
try {
|
||||
o.b
|
||||
assert(false)
|
||||
} catch (e) {
|
||||
assert(e instanceof ReferenceError)
|
||||
}
|
||||
|
||||
try {
|
||||
o.a = "X"
|
||||
assert(false)
|
||||
} catch (e) {
|
||||
assert(e instanceof TypeError)
|
||||
}
|
||||
|
||||
assert(o[Symbol.toStringTag] === "Module")
|
||||
|
||||
var result = Object.getOwnPropertyDescriptor(o, "a")
|
||||
assert(result.value === "X")
|
||||
assert(result.configurable === false)
|
||||
assert(result.enumerable === true)
|
||||
assert(result.writable === true)
|
||||
|
||||
try {
|
||||
Object.getOwnPropertyDescriptor(o, "b")
|
||||
assert(false)
|
||||
} catch (e) {
|
||||
assert(e instanceof ReferenceError)
|
||||
}
|
||||
|
||||
result = Object.getOwnPropertyDescriptor(o, Symbol.toStringTag)
|
||||
assert(result.value === "Module")
|
||||
assert(result.configurable === false)
|
||||
assert(result.enumerable === false)
|
||||
assert(result.writable === false)
|
||||
|
||||
Object.defineProperty(o, "a", { value: "X" })
|
||||
|
||||
try {
|
||||
Object.defineProperty(o, "a", { value: "Y" })
|
||||
assert(false)
|
||||
} catch (e) {
|
||||
assert(e instanceof TypeError)
|
||||
}
|
||||
|
||||
try {
|
||||
Object.defineProperty(o, "b", { value:5 })
|
||||
assert(false)
|
||||
} catch (e) {
|
||||
assert(e instanceof ReferenceError)
|
||||
}
|
||||
|
||||
Object.defineProperty(o, Symbol.toStringTag, { value: "Module", writable:false })
|
||||
|
||||
try {
|
||||
Object.defineProperty(o, Symbol.toStringTag, { writable:true })
|
||||
assert(false)
|
||||
} catch (e) {
|
||||
assert(e instanceof TypeError)
|
||||
}
|
||||
}
|
||||
38
tests/jerry/es.next/module-circular-03.mjs
Normal file
38
tests/jerry/es.next/module-circular-03.mjs
Normal file
@ -0,0 +1,38 @@
|
||||
// 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.
|
||||
|
||||
export var a = 0
|
||||
export let b = 1
|
||||
|
||||
function other() {
|
||||
return 33.5
|
||||
}
|
||||
|
||||
export function early() {
|
||||
// This function is called before the module is executed
|
||||
assert(other() === 33.5)
|
||||
assert(a === undefined)
|
||||
a = "X"
|
||||
|
||||
try {
|
||||
b
|
||||
assert(false)
|
||||
} catch (e) {
|
||||
assert(e instanceof ReferenceError)
|
||||
}
|
||||
}
|
||||
|
||||
early = "Loaded"
|
||||
|
||||
import * as o from "module-circular-04.mjs"
|
||||
50
tests/jerry/es.next/module-circular-04.mjs
Normal file
50
tests/jerry/es.next/module-circular-04.mjs
Normal file
@ -0,0 +1,50 @@
|
||||
// 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.
|
||||
|
||||
import {a as aa, b as bb, early} from "module-circular-03.mjs"
|
||||
|
||||
export var a = 5
|
||||
|
||||
if (early != "Loaded")
|
||||
{
|
||||
// The scope of module-circular-03.mjs is initialized and functions are usable
|
||||
// However, the module script has not been executed
|
||||
|
||||
assert(aa === undefined)
|
||||
early()
|
||||
assert(aa === "X")
|
||||
|
||||
try {
|
||||
bb
|
||||
assert(false)
|
||||
} catch (e) {
|
||||
assert(e instanceof ReferenceError)
|
||||
}
|
||||
|
||||
a = 7
|
||||
|
||||
try {
|
||||
aa = "X"
|
||||
assert(false)
|
||||
} catch (e) {
|
||||
assert(e instanceof TypeError)
|
||||
}
|
||||
|
||||
try {
|
||||
c = 4
|
||||
assert(false)
|
||||
} catch (e) {
|
||||
assert(e instanceof ReferenceError)
|
||||
}
|
||||
}
|
||||
@ -17,4 +17,20 @@ import * as f from "./module-export-08.mjs";
|
||||
|
||||
assert (f.c === 5)
|
||||
assert (f.x === 41)
|
||||
assert (!Object.hasOwnProperty(f, "default"));
|
||||
assert (Object.getPrototypeOf(f) === null)
|
||||
|
||||
try {
|
||||
Object.hasOwnProperty(f, "default")
|
||||
assert (false);
|
||||
} catch (e) {
|
||||
assert (e instanceof TypeError)
|
||||
}
|
||||
|
||||
Object.setPrototypeOf(f, null)
|
||||
|
||||
try {
|
||||
Object.setPrototypeOf(f, {})
|
||||
assert (false);
|
||||
} catch (e) {
|
||||
assert (e instanceof TypeError)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user