mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Implement realm object and support realms for built-ins and JS functions (#4354)
- Type for realm objects is introduced (ecma_global_object_t) - Realm reference is added to built-in objects and ECMAScript functions - Resolving built-ins, global environments, and scopes require realm object - Unnecessary global object accesses are removed from the code Missing: external functions and static snapshot functions have no realm reference JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
parent
7cb9f808f7
commit
df92c86ecf
@ -141,6 +141,8 @@ Possible compile time enabled feature types:
|
||||
- JERRY_FEATURE_SET - Set support
|
||||
- JERRY_FEATURE_WEAKMAP - WeakMap support
|
||||
- JERRY_FEATURE_WEAKSET - WeakSet support
|
||||
- JERRY_FEATURE_BIGINT - BigInt support
|
||||
- JERRY_FEATURE_REALM - realm support
|
||||
|
||||
*New in version 2.0*.
|
||||
|
||||
@ -5969,6 +5971,38 @@ jerry_create_undefined (void);
|
||||
- [jerry_release_value](#jerry_release_value)
|
||||
|
||||
|
||||
## jerry_create_realm
|
||||
|
||||
**Summary**
|
||||
|
||||
Creates a `jerry_value_t` representing a new global object.
|
||||
|
||||
**Prototype**
|
||||
|
||||
```c
|
||||
jerry_value_t
|
||||
jerry_create_realm (void);
|
||||
```
|
||||
|
||||
- return value - realm object value
|
||||
|
||||
**Example**
|
||||
|
||||
```c
|
||||
{
|
||||
jerry_value_t realm_value = jerry_create_realm ();
|
||||
|
||||
... // usage of the value
|
||||
|
||||
jerry_release_value (realm_value);
|
||||
}
|
||||
```
|
||||
|
||||
**See also**
|
||||
|
||||
- [jerry_release_value](#jerry_release_value)
|
||||
|
||||
|
||||
# General API functions of JS objects
|
||||
|
||||
## jerry_has_property
|
||||
|
||||
@ -49,6 +49,9 @@ snapshot_get_global_flags (bool has_regex, /**< regex literal is present */
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
flags |= (has_class ? JERRY_SNAPSHOT_HAS_CLASS_LITERAL : 0);
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
flags |= JERRY_SNAPSHOT_HAS_REALM_VALUE;
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
return flags;
|
||||
} /* snapshot_get_global_flags */
|
||||
@ -67,6 +70,9 @@ snapshot_check_global_flags (uint32_t global_flags) /**< global flags */
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
global_flags &= (uint32_t) ~JERRY_SNAPSHOT_HAS_CLASS_LITERAL;
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
global_flags |= JERRY_SNAPSHOT_HAS_REALM_VALUE;
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
return global_flags == snapshot_get_global_flags (false, false);
|
||||
} /* snapshot_check_global_flags */
|
||||
@ -380,6 +386,10 @@ static_snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< c
|
||||
cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) buffer_p;
|
||||
literal_end = (uint32_t) (args_p->literal_end - args_p->register_end);
|
||||
const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end);
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
args_p->realm_value = ECMA_VALUE_UNDEFINED;
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -388,6 +398,10 @@ static_snapshot_add_compiled_code (ecma_compiled_code_t *compiled_code_p, /**< c
|
||||
cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) buffer_p;
|
||||
literal_end = (uint32_t) (args_p->literal_end - args_p->register_end);
|
||||
const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end);
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
args_p->realm_value = ECMA_VALUE_UNDEFINED;
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < const_literal_end; i++)
|
||||
@ -585,6 +599,10 @@ snapshot_load_compiled_code (const uint8_t *base_addr_p, /**< base address of th
|
||||
const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end);
|
||||
literal_end = (uint32_t) (args_p->literal_end - args_p->register_end);
|
||||
header_size = sizeof (cbc_uint16_arguments_t);
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
args_p->realm_value = ecma_make_object_value (ecma_builtin_get_global ());
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -595,6 +613,10 @@ snapshot_load_compiled_code (const uint8_t *base_addr_p, /**< base address of th
|
||||
const_literal_end = (uint32_t) (args_p->const_literal_end - args_p->register_end);
|
||||
literal_end = (uint32_t) (args_p->literal_end - args_p->register_end);
|
||||
header_size = sizeof (cbc_uint8_arguments_t);
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
args_p->realm_value = ecma_make_object_value (ecma_builtin_get_global ());
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
}
|
||||
|
||||
if (copy_bytecode
|
||||
@ -1003,14 +1025,20 @@ jerry_snapshot_result (const uint32_t *snapshot_p, /**< snapshot */
|
||||
|
||||
if (as_function)
|
||||
{
|
||||
ecma_object_t *global_object_p = ecma_builtin_get_global ();
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
JERRY_ASSERT (global_object_p == ecma_get_object_from_value (ecma_op_function_get_realm (bytecode_p)));
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
if (bytecode_p->status_flags & CBC_CODE_FLAGS_LEXICAL_BLOCK_NEEDED)
|
||||
{
|
||||
ecma_create_global_lexical_block ();
|
||||
ecma_create_global_lexical_block (global_object_p);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
ecma_object_t *lex_env_p = ecma_get_global_scope ();
|
||||
ecma_object_t *lex_env_p = ecma_get_global_scope (global_object_p);
|
||||
ecma_object_t *func_obj_p = ecma_op_create_simple_function_object (lex_env_p, bytecode_p);
|
||||
|
||||
if (!(bytecode_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION))
|
||||
|
||||
@ -45,7 +45,8 @@ typedef enum
|
||||
{
|
||||
/* 8 bits are reserved for dynamic features */
|
||||
JERRY_SNAPSHOT_HAS_REGEX_LITERAL = (1u << 0), /**< byte code has regex literal */
|
||||
JERRY_SNAPSHOT_HAS_CLASS_LITERAL = (1u << 1), /**< byte code has class literal */
|
||||
JERRY_SNAPSHOT_HAS_REALM_VALUE = (1u << 1), /**< byte code has realm value */
|
||||
JERRY_SNAPSHOT_HAS_CLASS_LITERAL = (1u << 2), /**< byte code has class literal */
|
||||
/* 24 bits are reserved for compile time features */
|
||||
JERRY_SNAPSHOT_FOUR_BYTE_CPOINTER = (1u << 8) /**< deprecated, an unused placeholder now */
|
||||
} jerry_snapshot_global_flags_t;
|
||||
|
||||
@ -468,7 +468,13 @@ jerry_parse (const jerry_char_t *resource_name_p, /**< resource name (usually a
|
||||
return ecma_create_error_reference_from_context ();
|
||||
}
|
||||
|
||||
ecma_object_t *lex_env_p = ecma_get_global_environment ();
|
||||
ecma_object_t *global_object_p = ecma_builtin_get_global ();
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
JERRY_ASSERT (global_object_p == ecma_get_object_from_value (ecma_op_function_get_realm (bytecode_data_p)));
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
ecma_object_t *lex_env_p = ecma_get_global_environment (global_object_p);
|
||||
ecma_object_t *func_obj_p = ecma_op_create_simple_function_object (lex_env_p, bytecode_data_p);
|
||||
ecma_bytecode_deref (bytecode_data_p);
|
||||
|
||||
@ -541,7 +547,13 @@ jerry_parse_function (const jerry_char_t *resource_name_p, /**< resource name (u
|
||||
return ecma_create_error_reference_from_context ();
|
||||
}
|
||||
|
||||
ecma_object_t *lex_env_p = ecma_get_global_environment ();
|
||||
ecma_object_t *global_object_p = ecma_builtin_get_global ();
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
JERRY_ASSERT (global_object_p == ecma_get_object_from_value (ecma_op_function_get_realm (bytecode_p)));
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
ecma_object_t *lex_env_p = ecma_get_global_environment (global_object_p);
|
||||
ecma_object_t *func_obj_p = ecma_op_create_simple_function_object (lex_env_p, bytecode_p);
|
||||
ecma_bytecode_deref (bytecode_p);
|
||||
|
||||
@ -586,10 +598,9 @@ jerry_run (const jerry_value_t func_val) /**< function to run */
|
||||
|
||||
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_obj_p;
|
||||
|
||||
ecma_object_t *scope_p = ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t,
|
||||
ext_func_p->u.function.scope_cp);
|
||||
const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p);
|
||||
|
||||
if (scope_p != ecma_get_global_environment ())
|
||||
if (CBC_FUNCTION_GET_TYPE (bytecode_data_p->status_flags) != CBC_FUNCTION_SCRIPT)
|
||||
{
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p)));
|
||||
}
|
||||
@ -1341,6 +1352,9 @@ jerry_is_feature_enabled (const jerry_feature_t feature) /**< feature to check *
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
|| feature == JERRY_FEATURE_BIGINT
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
|| feature == JERRY_FEATURE_REALM
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
);
|
||||
} /* jerry_is_feature_enabled */
|
||||
|
||||
@ -2299,6 +2313,24 @@ jerry_create_regexp_sz (const jerry_char_t *pattern_p, /**< zero-terminated UTF-
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REGEXP) */
|
||||
} /* jerry_create_regexp_sz */
|
||||
|
||||
/**
|
||||
* Creates a new realm (global object).
|
||||
*
|
||||
* @return new realm object
|
||||
*/
|
||||
jerry_value_t
|
||||
jerry_create_realm (void)
|
||||
{
|
||||
jerry_assert_api_available ();
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
ecma_global_object_t *global_object_p = ecma_builtin_create_global_object ();
|
||||
return ecma_make_object_value ((ecma_object_t *) global_object_p);
|
||||
#else /* !ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Realms are disabled.")));
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
} /* jerry_create_realm */
|
||||
|
||||
/**
|
||||
* Get length of an array object
|
||||
*
|
||||
|
||||
@ -79,6 +79,10 @@
|
||||
# define JERRY_ESNEXT 1
|
||||
#endif /* !defined (JERRY_ESNEXT) */
|
||||
|
||||
#ifndef JERRY_BUILTIN_REALMS
|
||||
# define JERRY_BUILTIN_REALMS JERRY_ESNEXT
|
||||
#endif /* !defined (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
#ifndef JERRY_BUILTIN_DATAVIEW
|
||||
# define JERRY_BUILTIN_DATAVIEW JERRY_ESNEXT
|
||||
#endif /* !defined (JERRY_BUILTIN_DATAVIEW) */
|
||||
@ -523,6 +527,10 @@
|
||||
|| ((JERRY_ESNEXT != 0) && (JERRY_ESNEXT != 1))
|
||||
# error "Invalid value for JERRY_ESNEXT macro."
|
||||
#endif
|
||||
#if !defined (JERRY_BUILTIN_REALMS) \
|
||||
|| ((JERRY_BUILTIN_REALMS != 0) && (JERRY_BUILTIN_REALMS != 1))
|
||||
# error "Invalid value for JERRY_BUILTIN_REALMS macro."
|
||||
#endif
|
||||
#if !defined (JERRY_BUILTIN_DATAVIEW) \
|
||||
|| ((JERRY_BUILTIN_DATAVIEW != 0) && (JERRY_BUILTIN_DATAVIEW != 1))
|
||||
# error "Invalid value for JERRY_BUILTIN_DATAVIEW macro."
|
||||
|
||||
@ -149,6 +149,34 @@ ecma_deref_object (ecma_object_t *object_p) /**< object */
|
||||
object_p->type_flags_refs = (uint16_t) (object_p->type_flags_refs - ECMA_OBJECT_REF_ONE);
|
||||
} /* ecma_deref_object */
|
||||
|
||||
/**
|
||||
* Mark objects referenced by global object
|
||||
*/
|
||||
static void
|
||||
ecma_gc_mark_global_object (ecma_global_object_t *global_object_p) /**< global object */
|
||||
{
|
||||
JERRY_ASSERT (global_object_p->extended_object.u.built_in.routine_id == 0);
|
||||
|
||||
ecma_gc_set_object_visited (ECMA_GET_NON_NULL_POINTER (ecma_object_t, global_object_p->global_env_cp));
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
if (global_object_p->global_scope_cp != global_object_p->global_env_cp)
|
||||
{
|
||||
ecma_gc_set_object_visited (ECMA_GET_NON_NULL_POINTER (ecma_object_t, global_object_p->global_scope_cp));
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
jmem_cpointer_t *builtin_objects_p = global_object_p->builtin_objects;
|
||||
|
||||
for (int i = 0; i < ECMA_BUILTIN_OBJECTS_COUNT; i++)
|
||||
{
|
||||
if (builtin_objects_p[i] != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_gc_set_object_visited (ECMA_GET_NON_NULL_POINTER (ecma_object_t, builtin_objects_p[i]));
|
||||
}
|
||||
}
|
||||
} /* ecma_gc_mark_global_object */
|
||||
|
||||
/**
|
||||
* Mark objects referenced by arguments object
|
||||
*/
|
||||
@ -620,14 +648,52 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
|
||||
{
|
||||
ecma_object_t *binding_object_p = ecma_get_lex_env_binding_object (object_p);
|
||||
ecma_gc_set_object_visited (binding_object_p);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (ecma_get_object_type (object_p))
|
||||
ecma_object_type_t object_type = ecma_get_object_type (object_p);
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
if (JERRY_UNLIKELY (ecma_get_object_is_builtin (object_p)))
|
||||
{
|
||||
ecma_value_t realm_value;
|
||||
|
||||
if (ECMA_BUILTIN_IS_EXTENDED_BUILT_IN (object_type))
|
||||
{
|
||||
realm_value = ((ecma_extended_built_in_object_t *) object_p)->built_in.realm_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_extended_object_t *extended_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
if (object_type == ECMA_OBJECT_TYPE_GENERAL
|
||||
&& extended_object_p->u.built_in.id == ECMA_BUILTIN_ID_GLOBAL)
|
||||
{
|
||||
ecma_gc_mark_global_object ((ecma_global_object_t *) object_p);
|
||||
}
|
||||
|
||||
realm_value = extended_object_p->u.built_in.realm_value;
|
||||
}
|
||||
|
||||
ecma_gc_set_object_visited (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, realm_value));
|
||||
}
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
switch (object_type)
|
||||
{
|
||||
#if !ENABLED (JERRY_BUILTIN_REALMS)
|
||||
case ECMA_OBJECT_TYPE_GENERAL:
|
||||
{
|
||||
if (JERRY_UNLIKELY (ecma_get_object_is_builtin (object_p))
|
||||
&& ((ecma_extended_object_t *) object_p)->u.built_in.id == ECMA_BUILTIN_ID_GLOBAL)
|
||||
{
|
||||
ecma_gc_mark_global_object ((ecma_global_object_t *) object_p);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif /* !ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
case ECMA_OBJECT_TYPE_CLASS:
|
||||
{
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
@ -823,9 +889,11 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
|
||||
ecma_gc_set_object_visited (ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t,
|
||||
ext_func_p->u.function.scope_cp));
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
#if ENABLED (JERRY_ESNEXT) || ENABLED (JERRY_BUILTIN_REALMS)
|
||||
const ecma_compiled_code_t *byte_code_p = ecma_op_function_get_compiled_code (ext_func_p);
|
||||
#endif /* ENABLED (JERRY_ESNEXT) || ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
if (CBC_FUNCTION_IS_ARROW (byte_code_p->status_flags))
|
||||
{
|
||||
ecma_arrow_function_t *arrow_func_p = (ecma_arrow_function_t *) object_p;
|
||||
@ -842,6 +910,30 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
#if ENABLED (JERRY_SNAPSHOT_EXEC)
|
||||
if (ext_func_p->u.function.bytecode_cp == JMEM_CP_NULL)
|
||||
{
|
||||
/* Static snapshot functions have a global realm */
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */
|
||||
|
||||
ecma_value_t realm_value;
|
||||
|
||||
if (byte_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
|
||||
{
|
||||
cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) byte_code_p;
|
||||
realm_value = args_p->realm_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) byte_code_p;
|
||||
realm_value = args_p->realm_value;
|
||||
}
|
||||
|
||||
ecma_gc_set_object_visited (ecma_get_object_from_value (realm_value));
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
break;
|
||||
}
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
@ -1305,7 +1397,7 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
|
||||
{
|
||||
uint8_t length_and_bitset_size;
|
||||
|
||||
if (object_type == ECMA_OBJECT_TYPE_CLASS || object_type == ECMA_OBJECT_TYPE_ARRAY)
|
||||
if (ECMA_BUILTIN_IS_EXTENDED_BUILT_IN (object_type))
|
||||
{
|
||||
ext_object_size = sizeof (ecma_extended_built_in_object_t);
|
||||
length_and_bitset_size = ((ecma_extended_built_in_object_t *) object_p)->built_in.u.length_and_bitset_size;
|
||||
@ -1313,15 +1405,16 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (object_type == ECMA_OBJECT_TYPE_NATIVE_FUNCTION
|
||||
&& ecma_builtin_function_is_routine (object_p))
|
||||
{
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p;
|
||||
ecma_extended_object_t *extended_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
if (ext_obj_p->u.built_in.id == ECMA_BUILTIN_ID_HANDLER)
|
||||
if (extended_object_p->u.built_in.routine_id > 0)
|
||||
{
|
||||
JERRY_ASSERT (object_type == ECMA_OBJECT_TYPE_NATIVE_FUNCTION);
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
if (extended_object_p->u.built_in.id == ECMA_BUILTIN_ID_HANDLER)
|
||||
{
|
||||
switch (ext_obj_p->u.built_in.routine_id)
|
||||
switch (extended_object_p->u.built_in.routine_id)
|
||||
{
|
||||
case ECMA_NATIVE_HANDLER_PROMISE_RESOLVE:
|
||||
case ECMA_NATIVE_HANDLER_PROMISE_REJECT:
|
||||
@ -1367,6 +1460,11 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
}
|
||||
else if (extended_object_p->u.built_in.id == ECMA_BUILTIN_ID_GLOBAL)
|
||||
{
|
||||
JERRY_ASSERT (object_type == ECMA_OBJECT_TYPE_GENERAL);
|
||||
ext_object_size = sizeof (ecma_global_object_t);
|
||||
}
|
||||
else
|
||||
{
|
||||
length_and_bitset_size = ((ecma_extended_object_t *) object_p)->u.built_in.u.length_and_bitset_size;
|
||||
|
||||
@ -864,14 +864,30 @@ typedef struct
|
||||
uint8_t instantiated_bitset[1]; /**< instantiated property bit set for generic built-ins */
|
||||
uint8_t routine_flags; /**< flags for built-in routines */
|
||||
} u2;
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
ecma_value_t realm_value; /**< realm value */
|
||||
#else /* !ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
uint32_t continue_instantiated_bitset[1]; /**< bit set for instantiated properties */
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
} ecma_built_in_props_t;
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
|
||||
/**
|
||||
* Number of bits available in the instantiated bitset without allocation
|
||||
*/
|
||||
#define ECMA_BUILTIN_INSTANTIATED_BITSET_MIN_SIZE (8)
|
||||
|
||||
#else /* !ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
/**
|
||||
* Number of bits available in the instantiated bitset without allocation
|
||||
*/
|
||||
#define ECMA_BUILTIN_INSTANTIATED_BITSET_MIN_SIZE (8 + 32)
|
||||
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
/**
|
||||
* Builtin routine function object status flags
|
||||
*/
|
||||
@ -992,6 +1008,12 @@ typedef struct
|
||||
ecma_built_in_props_t built_in; /**< built-in object part */
|
||||
} ecma_extended_built_in_object_t;
|
||||
|
||||
/**
|
||||
* Checks whether the built-in is an ecma_extended_built_in_object_t
|
||||
*/
|
||||
#define ECMA_BUILTIN_IS_EXTENDED_BUILT_IN(object_type) \
|
||||
((object_type) == ECMA_OBJECT_TYPE_CLASS || (object_type) == ECMA_OBJECT_TYPE_ARRAY)
|
||||
|
||||
/**
|
||||
* Flags for array.length_prop_and_hole_count
|
||||
*/
|
||||
|
||||
@ -250,7 +250,7 @@ ecma_get_object_builtin_id (ecma_object_t *object_p) /**< object */
|
||||
ecma_built_in_props_t *built_in_props_p;
|
||||
ecma_object_type_t object_type = ecma_get_object_type (object_p);
|
||||
|
||||
if (object_type == ECMA_OBJECT_TYPE_CLASS || object_type == ECMA_OBJECT_TYPE_ARRAY)
|
||||
if (ECMA_BUILTIN_IS_EXTENDED_BUILT_IN (object_type))
|
||||
{
|
||||
built_in_props_p = &((ecma_extended_built_in_object_t *) object_p)->built_in;
|
||||
}
|
||||
|
||||
@ -77,9 +77,9 @@ ecma_finalize (void)
|
||||
|
||||
ecma_finalize_global_environment ();
|
||||
uint8_t runs = 0;
|
||||
|
||||
do
|
||||
{
|
||||
ecma_finalize_builtins ();
|
||||
ecma_gc_run ();
|
||||
if (++runs >= JERRY_GC_LOOP_LIMIT)
|
||||
{
|
||||
@ -87,6 +87,7 @@ ecma_finalize (void)
|
||||
}
|
||||
}
|
||||
while (JERRY_CONTEXT (ecma_gc_new_objects) != 0);
|
||||
|
||||
ecma_finalize_lit_storage ();
|
||||
} /* ecma_finalize */
|
||||
|
||||
|
||||
@ -485,8 +485,15 @@ ecma_module_evaluate (ecma_module_t *module_p) /**< module */
|
||||
return ECMA_VALUE_EMPTY;
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
ecma_object_t *global_object_p;
|
||||
global_object_p = ecma_get_object_from_value (ecma_op_function_get_realm (module_p->compiled_code_p));
|
||||
#else /* !ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
ecma_object_t *global_object_p = ecma_builtin_get_global ();
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
module_p->state = ECMA_MODULE_STATE_EVALUATING;
|
||||
module_p->scope_p = ecma_create_decl_lex_env (ecma_get_global_environment ());
|
||||
module_p->scope_p = ecma_create_decl_lex_env (ecma_get_global_environment (global_object_p));
|
||||
module_p->context_p->parent_p = JERRY_CONTEXT (module_top_context_p);
|
||||
JERRY_CONTEXT (module_top_context_p) = module_p->context_p;
|
||||
|
||||
|
||||
@ -34,7 +34,8 @@
|
||||
* @{
|
||||
*/
|
||||
|
||||
static void ecma_instantiate_builtin (ecma_builtin_id_t id);
|
||||
JERRY_STATIC_ASSERT (ECMA_BUILTIN_ID_GLOBAL == ECMA_BUILTIN_OBJECTS_COUNT,
|
||||
ecma_builtin_id_global_must_be_the_last_builtin_id);
|
||||
|
||||
/**
|
||||
* Helper definition for ecma_builtin_property_list_references.
|
||||
@ -270,39 +271,45 @@ ecma_builtin_get_property_count (ecma_builtin_id_t builtin_id) /**< built-in ID
|
||||
* false - otherwise
|
||||
*/
|
||||
bool
|
||||
ecma_builtin_is (ecma_object_t *obj_p, /**< pointer to an object */
|
||||
ecma_builtin_is (ecma_object_t *object_p, /**< pointer to an object */
|
||||
ecma_builtin_id_t builtin_id) /**< id of built-in to check on */
|
||||
{
|
||||
JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p));
|
||||
JERRY_ASSERT (object_p != NULL && !ecma_is_lexical_environment (object_p));
|
||||
JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT);
|
||||
|
||||
/* If a built-in object is not instantiated, its value is NULL,
|
||||
hence it cannot be equal to a valid object. */
|
||||
jmem_cpointer_t builtin_cp = JERRY_CONTEXT (ecma_builtin_objects)[builtin_id];
|
||||
if (!ecma_get_object_is_builtin (object_p))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return (builtin_cp != JMEM_CP_NULL && (obj_p == ECMA_GET_NON_NULL_POINTER (ecma_object_t, builtin_cp)));
|
||||
if (ECMA_BUILTIN_IS_EXTENDED_BUILT_IN (ecma_get_object_type (object_p)))
|
||||
{
|
||||
ecma_extended_built_in_object_t *extended_built_in_object_p = (ecma_extended_built_in_object_t *) object_p;
|
||||
|
||||
return (extended_built_in_object_p->built_in.id == builtin_id
|
||||
&& extended_built_in_object_p->built_in.routine_id == 0);
|
||||
}
|
||||
|
||||
ecma_extended_object_t *built_in_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
return (built_in_object_p->u.built_in.id == builtin_id
|
||||
&& built_in_object_p->u.built_in.routine_id == 0);
|
||||
} /* ecma_builtin_is */
|
||||
|
||||
/**
|
||||
* Get reference to specified built-in object
|
||||
* Check if passed object is a global built-in.
|
||||
*
|
||||
* Note:
|
||||
* Does not increase the reference counter.
|
||||
*
|
||||
* @return pointer to the object's instance
|
||||
* @return true - if the object is a global built-in
|
||||
* false - otherwise
|
||||
*/
|
||||
ecma_object_t *
|
||||
ecma_builtin_get (ecma_builtin_id_t builtin_id) /**< id of built-in to check on */
|
||||
bool
|
||||
ecma_builtin_is_global (ecma_object_t *object_p) /**< pointer to an object */
|
||||
{
|
||||
JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT);
|
||||
JERRY_ASSERT (ecma_get_object_is_builtin (object_p));
|
||||
|
||||
if (JERRY_UNLIKELY (JERRY_CONTEXT (ecma_builtin_objects)[builtin_id] == JMEM_CP_NULL))
|
||||
{
|
||||
ecma_instantiate_builtin (builtin_id);
|
||||
}
|
||||
|
||||
return ECMA_GET_NON_NULL_POINTER (ecma_object_t, JERRY_CONTEXT (ecma_builtin_objects)[builtin_id]);
|
||||
} /* ecma_builtin_get */
|
||||
return (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_GENERAL
|
||||
&& ((ecma_extended_object_t *) object_p)->u.built_in.id == ECMA_BUILTIN_ID_GLOBAL);
|
||||
} /* ecma_builtin_is_global */
|
||||
|
||||
/**
|
||||
* Get reference to the global object
|
||||
@ -315,9 +322,9 @@ ecma_builtin_get (ecma_builtin_id_t builtin_id) /**< id of built-in to check on
|
||||
inline ecma_object_t * JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_builtin_get_global (void)
|
||||
{
|
||||
JERRY_ASSERT (JERRY_CONTEXT (ecma_builtin_objects)[ECMA_BUILTIN_ID_GLOBAL] != JMEM_CP_NULL);
|
||||
JERRY_ASSERT (JERRY_CONTEXT (global_object_p) != NULL);
|
||||
|
||||
return ECMA_GET_NON_NULL_POINTER (ecma_object_t, JERRY_CONTEXT (ecma_builtin_objects)[ECMA_BUILTIN_ID_GLOBAL]);
|
||||
return (ecma_object_t *) JERRY_CONTEXT (global_object_p);
|
||||
} /* ecma_builtin_get_global */
|
||||
|
||||
/**
|
||||
@ -336,14 +343,51 @@ ecma_builtin_function_is_routine (ecma_object_t *func_obj_p) /**< function objec
|
||||
return (ext_func_obj_p->u.built_in.routine_id != 0);
|
||||
} /* ecma_builtin_function_is_routine */
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
|
||||
/**
|
||||
* Get reference to the realm provided by another built-in object
|
||||
*
|
||||
* Note:
|
||||
* Does not increase the reference counter.
|
||||
*
|
||||
* @return pointer to the global object
|
||||
*/
|
||||
static ecma_global_object_t *
|
||||
ecma_builtin_get_realm (ecma_object_t *builtin_object_p) /**< built-in object */
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_object_is_builtin (builtin_object_p));
|
||||
|
||||
ecma_object_type_t object_type = ecma_get_object_type (builtin_object_p);
|
||||
ecma_value_t realm_value;
|
||||
|
||||
if (ECMA_BUILTIN_IS_EXTENDED_BUILT_IN (object_type))
|
||||
{
|
||||
realm_value = ((ecma_extended_built_in_object_t *) builtin_object_p)->built_in.realm_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
realm_value = ((ecma_extended_object_t *) builtin_object_p)->u.built_in.realm_value;
|
||||
}
|
||||
|
||||
return ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, realm_value);
|
||||
} /* ecma_builtin_get_realm */
|
||||
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
/**
|
||||
* Instantiate specified ECMA built-in object
|
||||
*
|
||||
* @return the newly instantiated built-in
|
||||
*/
|
||||
static void
|
||||
ecma_instantiate_builtin (ecma_builtin_id_t obj_builtin_id) /**< built-in id */
|
||||
static ecma_object_t *
|
||||
ecma_instantiate_builtin (ecma_global_object_t *global_object_p, /**< global object */
|
||||
ecma_builtin_id_t obj_builtin_id) /**< built-in id */
|
||||
{
|
||||
JERRY_ASSERT (obj_builtin_id < ECMA_BUILTIN_ID__COUNT);
|
||||
JERRY_ASSERT (JERRY_CONTEXT (ecma_builtin_objects)[obj_builtin_id] == JMEM_CP_NULL);
|
||||
jmem_cpointer_t *builtin_objects = global_object_p->builtin_objects;
|
||||
|
||||
JERRY_ASSERT (obj_builtin_id < ECMA_BUILTIN_OBJECTS_COUNT);
|
||||
JERRY_ASSERT (builtin_objects[obj_builtin_id] == JMEM_CP_NULL);
|
||||
|
||||
ecma_builtin_descriptor_t builtin_desc = ecma_builtin_descriptors[obj_builtin_id];
|
||||
ecma_builtin_id_t object_prototype_builtin_id = (ecma_builtin_id_t) (builtin_desc >> ECMA_BUILTIN_PROTOTYPE_ID_SHIFT);
|
||||
@ -357,19 +401,17 @@ ecma_instantiate_builtin (ecma_builtin_id_t obj_builtin_id) /**< built-in id */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (JERRY_CONTEXT (ecma_builtin_objects)[object_prototype_builtin_id] == JMEM_CP_NULL)
|
||||
if (builtin_objects[object_prototype_builtin_id] == JMEM_CP_NULL)
|
||||
{
|
||||
ecma_instantiate_builtin (object_prototype_builtin_id);
|
||||
ecma_instantiate_builtin (global_object_p, object_prototype_builtin_id);
|
||||
}
|
||||
prototype_obj_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t,
|
||||
JERRY_CONTEXT (ecma_builtin_objects)[object_prototype_builtin_id]);
|
||||
prototype_obj_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, builtin_objects[object_prototype_builtin_id]);
|
||||
JERRY_ASSERT (prototype_obj_p != NULL);
|
||||
}
|
||||
|
||||
ecma_object_type_t obj_type = (ecma_object_type_t) (builtin_desc & ECMA_BUILTIN_OBJECT_TYPE_MASK);
|
||||
|
||||
bool is_extended_built_in = (obj_type == ECMA_OBJECT_TYPE_CLASS
|
||||
|| obj_type == ECMA_OBJECT_TYPE_ARRAY);
|
||||
bool is_extended_built_in = ECMA_BUILTIN_IS_EXTENDED_BUILT_IN (obj_type);
|
||||
|
||||
size_t ext_object_size = (is_extended_built_in ? sizeof (ecma_extended_built_in_object_t)
|
||||
: sizeof (ecma_extended_object_t));
|
||||
@ -418,15 +460,19 @@ ecma_instantiate_builtin (ecma_builtin_id_t obj_builtin_id) /**< built-in id */
|
||||
built_in_props_p->routine_id = 0;
|
||||
built_in_props_p->u.length_and_bitset_size = 0;
|
||||
built_in_props_p->u2.instantiated_bitset[0] = 0;
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
ECMA_SET_INTERNAL_VALUE_POINTER (built_in_props_p->realm_value, global_object_p);
|
||||
#else /* !ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
built_in_props_p->continue_instantiated_bitset[0] = 0;
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
if (property_count > 40)
|
||||
if (property_count > ECMA_BUILTIN_INSTANTIATED_BITSET_MIN_SIZE)
|
||||
{
|
||||
built_in_props_p->u.length_and_bitset_size = 1 << ECMA_BUILT_IN_BITSET_SHIFT;
|
||||
|
||||
uint32_t *instantiated_bitset_p = built_in_props_p->continue_instantiated_bitset;
|
||||
uint32_t *instantiated_bitset_p = (uint32_t *) (built_in_props_p + 1);
|
||||
instantiated_bitset_p[0] = 0;
|
||||
instantiated_bitset_p[1] = 0;
|
||||
instantiated_bitset_p[2] = 0;
|
||||
}
|
||||
|
||||
/** Initializing [[PrimitiveValue]] properties of built-in prototype objects */
|
||||
@ -522,27 +568,135 @@ ecma_instantiate_builtin (ecma_builtin_id_t obj_builtin_id) /**< built-in id */
|
||||
}
|
||||
}
|
||||
|
||||
ECMA_SET_NON_NULL_POINTER (JERRY_CONTEXT (ecma_builtin_objects)[obj_builtin_id], obj_p);
|
||||
ECMA_SET_NON_NULL_POINTER (builtin_objects[obj_builtin_id], obj_p);
|
||||
ecma_deref_object (obj_p);
|
||||
return obj_p;
|
||||
} /* ecma_instantiate_builtin */
|
||||
|
||||
/**
|
||||
* Finalize ECMA built-in objects
|
||||
* Create a global object
|
||||
*
|
||||
* @return a new global object
|
||||
*/
|
||||
void
|
||||
ecma_finalize_builtins (void)
|
||||
ecma_global_object_t *
|
||||
ecma_builtin_create_global_object (void)
|
||||
{
|
||||
for (ecma_builtin_id_t id = (ecma_builtin_id_t) 0;
|
||||
id < ECMA_BUILTIN_ID__COUNT;
|
||||
id = (ecma_builtin_id_t) (id + 1))
|
||||
ecma_builtin_descriptor_t builtin_desc = ecma_builtin_descriptors[ECMA_BUILTIN_ID_GLOBAL];
|
||||
ecma_builtin_id_t prototype_builtin_id = (ecma_builtin_id_t) (builtin_desc >> ECMA_BUILTIN_PROTOTYPE_ID_SHIFT);
|
||||
ecma_object_type_t obj_type = (ecma_object_type_t) (builtin_desc & ECMA_BUILTIN_OBJECT_TYPE_MASK);
|
||||
size_t property_count = ecma_builtin_get_property_count (ECMA_BUILTIN_ID_GLOBAL);
|
||||
|
||||
JERRY_ASSERT (prototype_builtin_id != ECMA_BUILTIN_ID__COUNT);
|
||||
JERRY_ASSERT (obj_type != ECMA_OBJECT_TYPE_CLASS && obj_type != ECMA_OBJECT_TYPE_ARRAY);
|
||||
|
||||
/* Whenever this assertion fails, the size of extra_instantiated_bitset in ecma_global_object_t
|
||||
* must be increased and 32 must be added to these constants. Furthermore the new uint32 item
|
||||
* must be set to zero. */
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
JERRY_ASSERT (property_count <= ECMA_BUILTIN_INSTANTIATED_BITSET_MIN_SIZE + 64);
|
||||
#else /* !ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
JERRY_ASSERT (property_count <= ECMA_BUILTIN_INSTANTIATED_BITSET_MIN_SIZE + 32);
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
ecma_object_t *object_p = ecma_create_object (NULL, sizeof (ecma_global_object_t), obj_type);
|
||||
|
||||
ecma_op_ordinary_object_set_extensible (object_p);
|
||||
ecma_set_object_is_builtin (object_p);
|
||||
|
||||
ecma_global_object_t *global_object_p = (ecma_global_object_t *) object_p;
|
||||
|
||||
global_object_p->extended_object.u.built_in.id = (uint8_t) ECMA_BUILTIN_ID_GLOBAL;
|
||||
global_object_p->extended_object.u.built_in.routine_id = 0;
|
||||
/* Bitset size is ignored by the gc. */
|
||||
global_object_p->extended_object.u.built_in.u.length_and_bitset_size = 0;
|
||||
global_object_p->extended_object.u.built_in.u2.instantiated_bitset[0] = 0;
|
||||
global_object_p->extra_instantiated_bitset[0] = 0;
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
ECMA_SET_INTERNAL_VALUE_POINTER (global_object_p->extended_object.u.built_in.realm_value, global_object_p);
|
||||
global_object_p->extra_realms_bitset = 0;
|
||||
#else /* !ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
global_object_p->extended_object.u.built_in.continue_instantiated_bitset[0] = 0;
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
memset (global_object_p->builtin_objects, 0, (sizeof (jmem_cpointer_t) * ECMA_BUILTIN_OBJECTS_COUNT));
|
||||
|
||||
/* Temporary self reference for GC mark. */
|
||||
ECMA_SET_NON_NULL_POINTER (global_object_p->global_env_cp, object_p);
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
global_object_p->global_scope_cp = global_object_p->global_env_cp;
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
ecma_object_t *global_lex_env_p = ecma_create_object_lex_env (NULL,
|
||||
object_p,
|
||||
ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND);
|
||||
ECMA_SET_NON_NULL_POINTER (global_object_p->global_env_cp, global_lex_env_p);
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
global_object_p->global_scope_cp = global_object_p->global_env_cp;
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
ecma_deref_object (global_lex_env_p);
|
||||
|
||||
ecma_object_t *prototype_object_p;
|
||||
prototype_object_p = ecma_instantiate_builtin (global_object_p, prototype_builtin_id);
|
||||
JERRY_ASSERT (prototype_object_p != NULL);
|
||||
|
||||
ECMA_SET_NON_NULL_POINTER (object_p->u2.prototype_cp, prototype_object_p);
|
||||
|
||||
return global_object_p;
|
||||
} /* ecma_builtin_create_global_object */
|
||||
|
||||
/**
|
||||
* Get reference to specified built-in object
|
||||
*
|
||||
* Note:
|
||||
* Does not increase the reference counter.
|
||||
*
|
||||
* @return pointer to the object's instance
|
||||
*/
|
||||
ecma_object_t *
|
||||
ecma_builtin_get (ecma_builtin_id_t builtin_id) /**< id of built-in to check on */
|
||||
{
|
||||
JERRY_ASSERT (builtin_id < ECMA_BUILTIN_OBJECTS_COUNT);
|
||||
|
||||
ecma_global_object_t *global_object_p = (ecma_global_object_t *) ecma_builtin_get_global ();
|
||||
jmem_cpointer_t *builtin_p = global_object_p->builtin_objects + builtin_id;
|
||||
|
||||
if (JERRY_UNLIKELY (*builtin_p == JMEM_CP_NULL))
|
||||
{
|
||||
if (JERRY_CONTEXT (ecma_builtin_objects)[id] != JMEM_CP_NULL)
|
||||
{
|
||||
ecma_object_t *obj_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, JERRY_CONTEXT (ecma_builtin_objects)[id]);
|
||||
ecma_deref_object (obj_p);
|
||||
JERRY_CONTEXT (ecma_builtin_objects)[id] = JMEM_CP_NULL;
|
||||
}
|
||||
return ecma_instantiate_builtin (global_object_p, builtin_id);
|
||||
}
|
||||
} /* ecma_finalize_builtins */
|
||||
|
||||
return ECMA_GET_NON_NULL_POINTER (ecma_object_t, *builtin_p);
|
||||
} /* ecma_builtin_get */
|
||||
|
||||
/**
|
||||
* Get reference to specified built-in object using the realm provided by another built-in object
|
||||
*
|
||||
* Note:
|
||||
* Does not increase the reference counter.
|
||||
*
|
||||
* @return pointer to the object's instance
|
||||
*/
|
||||
static ecma_object_t *
|
||||
ecma_builtin_get_from_realm (ecma_object_t *builtin_object_p, /**< built-in object */
|
||||
ecma_builtin_id_t builtin_id) /**< id of built-in to check on */
|
||||
{
|
||||
JERRY_ASSERT (builtin_id < ECMA_BUILTIN_OBJECTS_COUNT);
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
ecma_global_object_t *global_object_p = ecma_builtin_get_realm (builtin_object_p);
|
||||
jmem_cpointer_t *builtin_p = global_object_p->builtin_objects + builtin_id;
|
||||
|
||||
if (JERRY_UNLIKELY (*builtin_p == JMEM_CP_NULL))
|
||||
{
|
||||
return ecma_instantiate_builtin (global_object_p, builtin_id);
|
||||
}
|
||||
|
||||
return ECMA_GET_NON_NULL_POINTER (ecma_object_t, *builtin_p);
|
||||
#else /* !ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
JERRY_UNUSED (builtin_object_p);
|
||||
return ecma_builtin_get (builtin_id);
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
} /* ecma_builtin_get_from_realm */
|
||||
|
||||
/**
|
||||
* Construct a Function object for specified built-in routine
|
||||
@ -552,13 +706,14 @@ ecma_finalize_builtins (void)
|
||||
* @return pointer to constructed Function object
|
||||
*/
|
||||
static ecma_object_t *
|
||||
ecma_builtin_make_function_object_for_routine (ecma_builtin_id_t builtin_id, /**< identifier of built-in object */
|
||||
ecma_builtin_make_function_object_for_routine (ecma_object_t *builtin_object_p, /**< builtin object */
|
||||
uint8_t routine_id, /**< builtin-wide identifier of the built-in
|
||||
* object's routine property */
|
||||
uint32_t routine_index, /**< property descriptor index of routine */
|
||||
uint8_t flags) /**< see also: ecma_builtin_routine_flags */
|
||||
{
|
||||
ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE);
|
||||
ecma_object_t *prototype_obj_p = ecma_builtin_get_from_realm (builtin_object_p,
|
||||
ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE);
|
||||
|
||||
size_t ext_object_size = sizeof (ecma_extended_object_t);
|
||||
|
||||
@ -571,12 +726,27 @@ ecma_builtin_make_function_object_for_routine (ecma_builtin_id_t builtin_id, /**
|
||||
JERRY_ASSERT (routine_id > 0);
|
||||
JERRY_ASSERT (routine_index <= UINT8_MAX);
|
||||
|
||||
ecma_built_in_props_t *built_in_props_p;
|
||||
|
||||
if (ECMA_BUILTIN_IS_EXTENDED_BUILT_IN (ecma_get_object_type (builtin_object_p)))
|
||||
{
|
||||
built_in_props_p = &((ecma_extended_built_in_object_t *) builtin_object_p)->built_in;
|
||||
}
|
||||
else
|
||||
{
|
||||
built_in_props_p = &((ecma_extended_object_t *) builtin_object_p)->u.built_in;
|
||||
}
|
||||
|
||||
ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) func_obj_p;
|
||||
ext_func_obj_p->u.built_in.id = (uint8_t) builtin_id;
|
||||
ext_func_obj_p->u.built_in.id = built_in_props_p->id;
|
||||
ext_func_obj_p->u.built_in.routine_id = routine_id;
|
||||
ext_func_obj_p->u.built_in.u.routine_index = (uint8_t) routine_index;
|
||||
ext_func_obj_p->u.built_in.u2.routine_flags = flags;
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
ext_func_obj_p->u.built_in.realm_value = built_in_props_p->realm_value;
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
return func_obj_p;
|
||||
} /* ecma_builtin_make_function_object_for_routine */
|
||||
|
||||
@ -586,13 +756,13 @@ ecma_builtin_make_function_object_for_routine (ecma_builtin_id_t builtin_id, /**
|
||||
* @return pointer to constructed accessor getter Function object
|
||||
*/
|
||||
static ecma_object_t *
|
||||
ecma_builtin_make_function_object_for_getter_accessor (ecma_builtin_id_t builtin_id, /**< id of built-in object */
|
||||
ecma_builtin_make_function_object_for_getter_accessor (ecma_object_t *builtin_object_p, /**< builtin object */
|
||||
uint8_t routine_id, /**< builtin-wide id of the built-in
|
||||
* object's routine property */
|
||||
uint32_t routine_index) /**< property descriptor index
|
||||
* of routine */
|
||||
{
|
||||
return ecma_builtin_make_function_object_for_routine (builtin_id,
|
||||
return ecma_builtin_make_function_object_for_routine (builtin_object_p,
|
||||
routine_id,
|
||||
routine_index,
|
||||
ECMA_BUILTIN_ROUTINE_GETTER);
|
||||
@ -604,13 +774,13 @@ ecma_builtin_make_function_object_for_getter_accessor (ecma_builtin_id_t builtin
|
||||
* @return pointer to constructed accessor getter Function object
|
||||
*/
|
||||
static ecma_object_t *
|
||||
ecma_builtin_make_function_object_for_setter_accessor (ecma_builtin_id_t builtin_id, /**< id of built-in object */
|
||||
ecma_builtin_make_function_object_for_setter_accessor (ecma_object_t *builtin_object_p, /**< builtin object */
|
||||
uint8_t routine_id, /**< builtin-wide id of the built-in
|
||||
* object's routine property */
|
||||
uint32_t routine_index) /**< property descriptor index
|
||||
* of routine */
|
||||
{
|
||||
return ecma_builtin_make_function_object_for_routine (builtin_id,
|
||||
return ecma_builtin_make_function_object_for_routine (builtin_object_p,
|
||||
routine_id,
|
||||
routine_index,
|
||||
ECMA_BUILTIN_ROUTINE_SETTER);
|
||||
@ -865,7 +1035,7 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object *
|
||||
ecma_object_type_t object_type = ecma_get_object_type (object_p);
|
||||
JERRY_ASSERT (object_type != ECMA_OBJECT_TYPE_FUNCTION || !ecma_builtin_function_is_routine (object_p));
|
||||
|
||||
if (object_type == ECMA_OBJECT_TYPE_CLASS || object_type == ECMA_OBJECT_TYPE_ARRAY)
|
||||
if (ECMA_BUILTIN_IS_EXTENDED_BUILT_IN (object_type))
|
||||
{
|
||||
built_in_props_p = &((ecma_extended_built_in_object_t *) object_p)->built_in;
|
||||
}
|
||||
@ -877,7 +1047,6 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object *
|
||||
ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_props_p->id;
|
||||
|
||||
JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT);
|
||||
JERRY_ASSERT (ecma_builtin_is (object_p, builtin_id));
|
||||
|
||||
const ecma_builtin_property_descriptor_t *property_list_p = ecma_builtin_property_list_references[builtin_id];
|
||||
|
||||
@ -894,6 +1063,14 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object *
|
||||
|
||||
uint32_t index = (uint32_t) (curr_property_p - property_list_p);
|
||||
uint8_t *bitset_p = built_in_props_p->u2.instantiated_bitset + (index >> 3);
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
if (index >= 8 * sizeof (uint8_t))
|
||||
{
|
||||
bitset_p += sizeof (ecma_value_t);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
uint8_t bit_for_index = (uint8_t) (1u << (index & 0x7));
|
||||
|
||||
if (*bitset_p & bit_for_index)
|
||||
@ -918,9 +1095,10 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object *
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
if (value == ECMA_VALUE_GLOBAL_THIS)
|
||||
{
|
||||
ecma_object_t *global_object_p = ecma_builtin_get_global ();
|
||||
ecma_ref_object (global_object_p);
|
||||
value = ecma_make_object_value (global_object_p);
|
||||
/* Only the global object has globalThis property. */
|
||||
JERRY_ASSERT (ecma_builtin_is_global (object_p));
|
||||
ecma_ref_object (object_p);
|
||||
value = ecma_make_object_value (object_p);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
break;
|
||||
@ -1004,8 +1182,8 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object *
|
||||
}
|
||||
case ECMA_BUILTIN_PROPERTY_INTRINSIC_PROPERTY:
|
||||
{
|
||||
value = ecma_op_object_get_by_magic_id (ecma_builtin_get (ECMA_BUILTIN_ID_INTRINSIC_OBJECT),
|
||||
(lit_magic_string_id_t) curr_property_p->value);
|
||||
ecma_object_t *intrinsic_object_p = ecma_builtin_get_from_realm (object_p, ECMA_BUILTIN_ID_INTRINSIC_OBJECT);
|
||||
value = ecma_op_object_get_by_magic_id (intrinsic_object_p, (lit_magic_string_id_t) curr_property_p->value);
|
||||
break;
|
||||
}
|
||||
case ECMA_BUILTIN_PROPERTY_ACCESSOR_BUILTIN_FUNCTION:
|
||||
@ -1013,8 +1191,8 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object *
|
||||
is_accessor = true;
|
||||
uint16_t getter_id = ECMA_ACCESSOR_READ_WRITE_GET_GETTER_ID (curr_property_p->value);
|
||||
uint16_t setter_id = ECMA_ACCESSOR_READ_WRITE_GET_SETTER_ID (curr_property_p->value);
|
||||
getter_p = ecma_builtin_get (getter_id);
|
||||
setter_p = ecma_builtin_get (setter_id);
|
||||
getter_p = ecma_builtin_get_from_realm (object_p, getter_id);
|
||||
setter_p = ecma_builtin_get_from_realm (object_p, setter_id);
|
||||
ecma_ref_object (getter_p);
|
||||
ecma_ref_object (setter_p);
|
||||
break;
|
||||
@ -1022,7 +1200,8 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object *
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
case ECMA_BUILTIN_PROPERTY_OBJECT:
|
||||
{
|
||||
ecma_object_t *builtin_object_p = ecma_builtin_get ((ecma_builtin_id_t) curr_property_p->value);
|
||||
ecma_object_t *builtin_object_p;
|
||||
builtin_object_p = ecma_builtin_get_from_realm (object_p, (ecma_builtin_id_t) curr_property_p->value);
|
||||
ecma_ref_object (builtin_object_p);
|
||||
value = ecma_make_object_value (builtin_object_p);
|
||||
break;
|
||||
@ -1030,7 +1209,7 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object *
|
||||
case ECMA_BUILTIN_PROPERTY_ROUTINE:
|
||||
{
|
||||
ecma_object_t *func_obj_p;
|
||||
func_obj_p = ecma_builtin_make_function_object_for_routine (builtin_id,
|
||||
func_obj_p = ecma_builtin_make_function_object_for_routine (object_p,
|
||||
ECMA_GET_ROUTINE_ID (curr_property_p->value),
|
||||
index,
|
||||
ECMA_BUILTIN_ROUTINE_NO_OPTS);
|
||||
@ -1042,8 +1221,8 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object *
|
||||
is_accessor = true;
|
||||
uint8_t getter_id = ECMA_ACCESSOR_READ_WRITE_GET_GETTER_ID (curr_property_p->value);
|
||||
uint8_t setter_id = ECMA_ACCESSOR_READ_WRITE_GET_SETTER_ID (curr_property_p->value);
|
||||
getter_p = ecma_builtin_make_function_object_for_getter_accessor (builtin_id, getter_id, index);
|
||||
setter_p = ecma_builtin_make_function_object_for_setter_accessor (builtin_id, setter_id, index);
|
||||
getter_p = ecma_builtin_make_function_object_for_getter_accessor (object_p, getter_id, index);
|
||||
setter_p = ecma_builtin_make_function_object_for_setter_accessor (object_p, setter_id, index);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -1052,7 +1231,7 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object *
|
||||
|
||||
is_accessor = true;
|
||||
uint8_t getter_id = (uint8_t) curr_property_p->value;
|
||||
getter_p = ecma_builtin_make_function_object_for_getter_accessor (builtin_id, getter_id, index);
|
||||
getter_p = ecma_builtin_make_function_object_for_getter_accessor (object_p, getter_id, index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1177,13 +1356,13 @@ ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in
|
||||
ecma_property_counter_t *prop_counter_p) /**< prop counter */
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_object_is_builtin (object_p));
|
||||
JERRY_ASSERT (ecma_get_object_type (object_p) != ECMA_OBJECT_TYPE_FUNCTION
|
||||
JERRY_ASSERT (ecma_get_object_type (object_p) != ECMA_OBJECT_TYPE_NATIVE_FUNCTION
|
||||
|| !ecma_builtin_function_is_routine (object_p));
|
||||
|
||||
ecma_built_in_props_t *built_in_props_p;
|
||||
ecma_object_type_t object_type = ecma_get_object_type (object_p);
|
||||
|
||||
if (object_type == ECMA_OBJECT_TYPE_CLASS || object_type == ECMA_OBJECT_TYPE_ARRAY)
|
||||
if (ECMA_BUILTIN_IS_EXTENDED_BUILT_IN (object_type))
|
||||
{
|
||||
built_in_props_p = &((ecma_extended_built_in_object_t *) object_p)->built_in;
|
||||
}
|
||||
@ -1195,18 +1374,23 @@ ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in
|
||||
ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_props_p->id;
|
||||
|
||||
JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT);
|
||||
JERRY_ASSERT (ecma_builtin_is (object_p, builtin_id));
|
||||
|
||||
const ecma_builtin_property_descriptor_t *curr_property_p = ecma_builtin_property_list_references[builtin_id];
|
||||
|
||||
uint32_t index = 0;
|
||||
uint8_t *bitset_p = built_in_props_p->u2.instantiated_bitset;
|
||||
uint8_t bitset = built_in_props_p->u2.instantiated_bitset[0];
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
uint8_t *bitset_p = built_in_props_p->u2.instantiated_bitset + 1 + sizeof (ecma_value_t);
|
||||
#else /* !ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
uint8_t *bitset_p = built_in_props_p->u2.instantiated_bitset + 1;
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
while (curr_property_p->magic_string_id != LIT_MAGIC_STRING__COUNT)
|
||||
{
|
||||
if (index == 8)
|
||||
{
|
||||
bitset_p++;
|
||||
bitset = *bitset_p++;
|
||||
index = 0;
|
||||
}
|
||||
|
||||
@ -1219,7 +1403,7 @@ ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in
|
||||
{
|
||||
ecma_string_t *name_p = ecma_op_get_global_symbol (curr_property_p->magic_string_id);
|
||||
|
||||
if (!(*bitset_p & bit_for_index) || ecma_op_ordinary_object_has_own_property (object_p, name_p))
|
||||
if (!(bitset & bit_for_index) || ecma_op_ordinary_object_has_own_property (object_p, name_p))
|
||||
{
|
||||
ecma_value_t name = ecma_make_symbol_value (name_p);
|
||||
ecma_collection_push_back (prop_names_p, name);
|
||||
@ -1236,7 +1420,7 @@ ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in
|
||||
{
|
||||
ecma_string_t *name_p = ecma_get_magic_string ((lit_magic_string_id_t) curr_property_p->magic_string_id);
|
||||
|
||||
if (!(*bitset_p & bit_for_index) || ecma_op_ordinary_object_has_own_property (object_p, name_p))
|
||||
if (!(bitset & bit_for_index) || ecma_op_ordinary_object_has_own_property (object_p, name_p))
|
||||
{
|
||||
ecma_value_t name = ecma_make_magic_string_value ((lit_magic_string_id_t) curr_property_p->magic_string_id);
|
||||
ecma_collection_push_back (prop_names_p, name);
|
||||
@ -1338,7 +1522,6 @@ ecma_builtin_dispatch_call (ecma_object_t *obj_p, /**< built-in object */
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_builtin_dispatch_construct (ecma_object_t *obj_p, /**< built-in object */
|
||||
ecma_object_t *new_target_p, /**< new target */
|
||||
const ecma_value_t *arguments_list_p, /**< arguments list */
|
||||
uint32_t arguments_list_len) /**< arguments list length */
|
||||
{
|
||||
@ -1354,20 +1537,7 @@ ecma_builtin_dispatch_construct (ecma_object_t *obj_p, /**< built-in object */
|
||||
ecma_builtin_id_t builtin_object_id = ext_obj_p->u.built_in.id;
|
||||
JERRY_ASSERT (builtin_object_id < sizeof (ecma_builtin_construct_functions) / sizeof (ecma_builtin_dispatch_call_t));
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
ecma_object_t *old_new_target = JERRY_CONTEXT (current_new_target);
|
||||
JERRY_CONTEXT (current_new_target) = new_target_p;
|
||||
#else /* !ENABLED (JERRY_ESNEXT) */
|
||||
JERRY_UNUSED (new_target_p);
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
ecma_value_t ret_value = ecma_builtin_construct_functions[builtin_object_id] (arguments_list_p, arguments_list_len);
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
JERRY_CONTEXT (current_new_target) = old_new_target;
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
return ret_value;
|
||||
return ecma_builtin_construct_functions[builtin_object_id] (arguments_list_p, arguments_list_len);
|
||||
} /* ecma_builtin_dispatch_construct */
|
||||
|
||||
/**
|
||||
|
||||
@ -88,15 +88,38 @@ typedef enum
|
||||
*/
|
||||
#define ECMA_ACCESSOR_READ_WRITE_GET_GETTER_ID(value) ((uint8_t) ((value) >> 8))
|
||||
|
||||
/**
|
||||
* Number ob built-in objects excluding global object
|
||||
*/
|
||||
#define ECMA_BUILTIN_OBJECTS_COUNT (ECMA_BUILTIN_ID__COUNT - 1)
|
||||
|
||||
/**
|
||||
* Description of built-in global ECMA-object.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
ecma_extended_object_t extended_object; /**< extended object part */
|
||||
uint32_t extra_instantiated_bitset[1]; /**< extra bit set for instantiated properties */
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
uint32_t extra_realms_bitset; /**< extra bit set for instantiated properties when realms is enabled */
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
jmem_cpointer_t global_env_cp; /**< global lexical environment */
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
jmem_cpointer_t global_scope_cp; /**< global lexical scope */
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
jmem_cpointer_t builtin_objects[ECMA_BUILTIN_OBJECTS_COUNT]; /**< pointer to instances of built-in objects */
|
||||
} ecma_global_object_t;
|
||||
|
||||
/* ecma-builtins.c */
|
||||
void ecma_finalize_builtins (void);
|
||||
|
||||
ecma_global_object_t *ecma_builtin_create_global_object (void);
|
||||
|
||||
ecma_value_t
|
||||
ecma_builtin_dispatch_call (ecma_object_t *obj_p, ecma_value_t this_arg_value,
|
||||
const ecma_value_t *arguments_list_p, uint32_t arguments_list_len);
|
||||
ecma_value_t
|
||||
ecma_builtin_dispatch_construct (ecma_object_t *obj_p, ecma_object_t *new_target_p,
|
||||
const ecma_value_t *arguments_list_p, uint32_t arguments_list_len);
|
||||
ecma_builtin_dispatch_construct (ecma_object_t *obj_p, const ecma_value_t *arguments_list_p,
|
||||
uint32_t arguments_list_len);
|
||||
ecma_property_t *
|
||||
ecma_builtin_routine_try_to_instantiate_property (ecma_object_t *object_p, ecma_string_t *string_p);
|
||||
ecma_property_t *
|
||||
@ -110,7 +133,9 @@ ecma_builtin_list_lazy_property_names (ecma_object_t *object_p,
|
||||
ecma_collection_t *prop_names_p,
|
||||
ecma_property_counter_t *prop_counter_p);
|
||||
bool
|
||||
ecma_builtin_is (ecma_object_t *obj_p, ecma_builtin_id_t builtin_id);
|
||||
ecma_builtin_is (ecma_object_t *object_p, ecma_builtin_id_t builtin_id);
|
||||
bool
|
||||
ecma_builtin_is_global (ecma_object_t *object_p);
|
||||
ecma_object_t *
|
||||
ecma_builtin_get (ecma_builtin_id_t builtin_id);
|
||||
ecma_object_t *
|
||||
|
||||
@ -169,6 +169,10 @@ ecma_object_check_constructor (ecma_object_t *obj_p) /**< ecma object */
|
||||
#if ENABLED (JERRY_ERROR_MESSAGES)
|
||||
switch (CBC_FUNCTION_GET_TYPE (byte_code_p->status_flags))
|
||||
{
|
||||
case CBC_FUNCTION_SCRIPT:
|
||||
{
|
||||
return "Script (global) functions cannot be invoked with 'new'.";
|
||||
}
|
||||
case CBC_FUNCTION_GENERATOR:
|
||||
{
|
||||
return "Generator functions cannot be invoked with 'new'.";
|
||||
@ -387,7 +391,7 @@ ecma_op_create_function_object (ecma_object_t *scope_p, /**< function's scope */
|
||||
#if ENABLED (JERRY_SNAPSHOT_EXEC)
|
||||
if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)
|
||||
{
|
||||
ext_func_p->u.function.bytecode_cp = ECMA_NULL_POINTER;
|
||||
ext_func_p->u.function.bytecode_cp = JMEM_CP_NULL;
|
||||
((ecma_static_function_t *) func_p)->bytecode_p = bytecode_data_p;
|
||||
}
|
||||
else
|
||||
@ -477,7 +481,13 @@ ecma_op_create_dynamic_function (const ecma_value_t *arguments_list_p, /**< argu
|
||||
*func_name_p = ecma_make_magic_string_value (LIT_MAGIC_STRING_ANONYMOUS);
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
ecma_object_t *global_env_p = ecma_get_global_environment ();
|
||||
ecma_object_t *global_object_p = ecma_builtin_get_global ();
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
JERRY_ASSERT (global_object_p == ecma_get_object_from_value (ecma_op_function_get_realm (bytecode_p)));
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
ecma_object_t *global_env_p = ecma_get_global_environment (global_object_p);
|
||||
ecma_builtin_id_t fallback_proto = ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE;
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
@ -702,6 +712,11 @@ ecma_op_create_native_handler (ecma_native_handler_id_t id, /**< handler id */
|
||||
ext_func_obj_p->u.built_in.routine_id = (uint8_t) id;
|
||||
ext_func_obj_p->u.built_in.u2.routine_flags = ECMA_NATIVE_HANDLER_FLAGS_NONE;
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
ECMA_SET_INTERNAL_VALUE_POINTER (ext_func_obj_p->u.built_in.realm_value,
|
||||
ecma_builtin_get_global ());
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
return function_obj_p;
|
||||
} /* ecma_op_create_native_handler */
|
||||
|
||||
@ -716,21 +731,59 @@ inline const ecma_compiled_code_t * JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_op_function_get_compiled_code (ecma_extended_object_t *function_p) /**< function pointer */
|
||||
{
|
||||
#if ENABLED (JERRY_SNAPSHOT_EXEC)
|
||||
if (function_p->u.function.bytecode_cp != ECMA_NULL_POINTER)
|
||||
if (JERRY_LIKELY (function_p->u.function.bytecode_cp != ECMA_NULL_POINTER))
|
||||
{
|
||||
return ECMA_GET_INTERNAL_VALUE_POINTER (const ecma_compiled_code_t,
|
||||
function_p->u.function.bytecode_cp);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ((ecma_static_function_t *) function_p)->bytecode_p;
|
||||
}
|
||||
|
||||
return ((ecma_static_function_t *) function_p)->bytecode_p;
|
||||
#else /* !ENABLED (JERRY_SNAPSHOT_EXEC) */
|
||||
return ECMA_GET_INTERNAL_VALUE_POINTER (const ecma_compiled_code_t,
|
||||
function_p->u.function.bytecode_cp);
|
||||
#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */
|
||||
} /* ecma_op_function_get_compiled_code */
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
|
||||
/**
|
||||
* Get realm from a byte code.
|
||||
*
|
||||
* Note:
|
||||
* Does not increase the reference counter.
|
||||
*
|
||||
* @return realm (global) object
|
||||
*/
|
||||
inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_op_function_get_realm (const ecma_compiled_code_t *bytecode_header_p) /**< byte code header */
|
||||
{
|
||||
ecma_value_t realm_value;
|
||||
|
||||
if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
|
||||
{
|
||||
cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_header_p;
|
||||
realm_value = args_p->realm_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_header_p;
|
||||
realm_value = args_p->realm_value;
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_SNAPSHOT_EXEC)
|
||||
if (JERRY_LIKELY (realm_value != ECMA_VALUE_UNDEFINED))
|
||||
{
|
||||
return realm_value;
|
||||
}
|
||||
|
||||
return ecma_make_object_value (ecma_builtin_get_global ());
|
||||
#else /* !ENABLED (JERRY_SNAPSHOT_EXEC) */
|
||||
return realm_value;
|
||||
#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */
|
||||
} /* ecma_op_function_get_realm */
|
||||
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
/**
|
||||
* 15.3.5.3 implementation of [[HasInstance]] for Function objects
|
||||
*
|
||||
@ -980,6 +1033,10 @@ ecma_op_function_call_simple (ecma_object_t *func_obj_p, /**< Function object */
|
||||
|
||||
shared_args.header.bytecode_header_p = bytecode_data_p;
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
ecma_value_t realm_value = ecma_op_function_get_realm (bytecode_data_p);
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
/* 1. */
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
if (JERRY_UNLIKELY (CBC_FUNCTION_IS_ARROW (status_flags)))
|
||||
@ -1007,7 +1064,11 @@ ecma_op_function_call_simple (ecma_object_t *func_obj_p, /**< Function object */
|
||||
|| ecma_is_value_null (this_binding))
|
||||
{
|
||||
/* 2. */
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
this_binding = realm_value;
|
||||
#else /* !ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
this_binding = ecma_make_object_value (ecma_builtin_get_global ());
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
}
|
||||
else if (!ecma_is_value_object (this_binding))
|
||||
{
|
||||
@ -1052,8 +1113,17 @@ ecma_op_function_call_simple (ecma_object_t *func_obj_p, /**< Function object */
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p);
|
||||
JERRY_CONTEXT (global_object_p) = (ecma_global_object_t *) ecma_get_object_from_value (realm_value);
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
ret_value = vm_run (&shared_args.header, this_binding, scope_p);
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
JERRY_CONTEXT (global_object_p) = saved_global_object_p;
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
/* ECMAScript v6, 9.2.2.13 */
|
||||
if (JERRY_UNLIKELY (shared_args.header.status_flags & VM_FRAME_CTX_SHARED_HERITAGE_PRESENT))
|
||||
@ -1105,7 +1175,21 @@ ecma_op_function_call_native (ecma_object_t *func_obj_p, /**< Function object */
|
||||
|
||||
if (ecma_get_object_is_builtin (func_obj_p))
|
||||
{
|
||||
return ecma_builtin_dispatch_call (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len);
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p);
|
||||
ecma_value_t realm_value = ((ecma_extended_object_t *) func_obj_p)->u.built_in.realm_value;
|
||||
JERRY_CONTEXT (global_object_p) = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, realm_value);
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
ecma_value_t ret_value = ecma_builtin_dispatch_call (func_obj_p,
|
||||
this_arg_value,
|
||||
arguments_list_p,
|
||||
arguments_list_len);
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
JERRY_CONTEXT (global_object_p) = saved_global_object_p;
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (ext_func_obj_p->u.external_handler_cb != NULL);
|
||||
@ -1390,7 +1474,27 @@ ecma_op_function_construct (ecma_object_t *func_obj_p, /**< Function object */
|
||||
{
|
||||
if (JERRY_UNLIKELY (ecma_get_object_is_builtin (func_obj_p)))
|
||||
{
|
||||
return ecma_builtin_dispatch_construct (func_obj_p, new_target_p, arguments_list_p, arguments_list_len);
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p);
|
||||
ecma_value_t realm_value = ((ecma_extended_object_t *) func_obj_p)->u.built_in.realm_value;
|
||||
JERRY_CONTEXT (global_object_p) = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, realm_value);
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
ecma_object_t *old_new_target = JERRY_CONTEXT (current_new_target);
|
||||
JERRY_CONTEXT (current_new_target) = new_target_p;
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
ecma_value_t ret_value = ecma_builtin_dispatch_construct (func_obj_p, arguments_list_p, arguments_list_len);
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
JERRY_CONTEXT (current_new_target) = old_new_target;
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
JERRY_CONTEXT (global_object_p) = saved_global_object_p;
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
return ecma_op_function_construct_native (func_obj_p, new_target_p, arguments_list_p, arguments_list_len);
|
||||
|
||||
@ -56,6 +56,11 @@ ecma_op_create_external_function_object (ecma_native_handler_t handler_cb);
|
||||
const ecma_compiled_code_t *
|
||||
ecma_op_function_get_compiled_code (ecma_extended_object_t *function_p);
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
ecma_value_t
|
||||
ecma_op_function_get_realm (const ecma_compiled_code_t *bytecode_header_p);
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
ecma_value_t
|
||||
ecma_op_create_dynamic_function (const ecma_value_t *arguments_list_p,
|
||||
uint32_t arguments_list_len,
|
||||
|
||||
@ -304,6 +304,8 @@ ecma_op_put_value_lex_env_base (ecma_object_t *lex_env_p, /**< lexical environme
|
||||
lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
|
||||
}
|
||||
|
||||
JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND);
|
||||
|
||||
if (is_strict)
|
||||
{
|
||||
#if ENABLED (JERRY_ERROR_MESSAGES)
|
||||
@ -315,7 +317,7 @@ ecma_op_put_value_lex_env_base (ecma_object_t *lex_env_p, /**< lexical environme
|
||||
#endif /* ENABLED (JERRY_ERROR_MESSAGES) */
|
||||
}
|
||||
|
||||
ecma_value_t completion = ecma_op_object_put (ecma_builtin_get_global (),
|
||||
ecma_value_t completion = ecma_op_object_put (ecma_get_lex_env_binding_object (lex_env_p),
|
||||
name_p,
|
||||
value,
|
||||
false);
|
||||
|
||||
@ -39,15 +39,7 @@
|
||||
void
|
||||
ecma_init_global_environment (void)
|
||||
{
|
||||
ecma_object_t *glob_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_GLOBAL);
|
||||
|
||||
ecma_object_t *global_lex_env_p = ecma_create_object_lex_env (NULL,
|
||||
glob_obj_p,
|
||||
ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND);
|
||||
ECMA_SET_NON_NULL_POINTER (JERRY_CONTEXT (ecma_global_env_cp), global_lex_env_p);
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
ECMA_SET_NON_NULL_POINTER (JERRY_CONTEXT (ecma_global_scope_cp), global_lex_env_p);
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
JERRY_CONTEXT (global_object_p) = ecma_builtin_create_global_object ();
|
||||
} /* ecma_init_global_environment */
|
||||
|
||||
/**
|
||||
@ -56,15 +48,9 @@ ecma_init_global_environment (void)
|
||||
void
|
||||
ecma_finalize_global_environment (void)
|
||||
{
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
if (JERRY_CONTEXT (ecma_global_scope_cp) != JERRY_CONTEXT (ecma_global_env_cp))
|
||||
{
|
||||
ecma_deref_object (ECMA_GET_NON_NULL_POINTER (ecma_object_t, JERRY_CONTEXT (ecma_global_scope_cp)));
|
||||
}
|
||||
JERRY_CONTEXT (ecma_global_scope_cp) = JMEM_CP_NULL;
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
ecma_deref_object (ECMA_GET_NON_NULL_POINTER (ecma_object_t, JERRY_CONTEXT (ecma_global_env_cp)));
|
||||
JERRY_CONTEXT (ecma_global_env_cp) = JMEM_CP_NULL;
|
||||
/* After this point the gc can free the global object, but the global_object_p pointer
|
||||
* is not set to NULL because the global object might still be used before the free. */
|
||||
ecma_deref_object ((ecma_object_t *) JERRY_CONTEXT (global_object_p));
|
||||
} /* ecma_finalize_global_environment */
|
||||
|
||||
/**
|
||||
@ -74,10 +60,10 @@ ecma_finalize_global_environment (void)
|
||||
* @return pointer to the object's instance
|
||||
*/
|
||||
ecma_object_t *
|
||||
ecma_get_global_environment (void)
|
||||
ecma_get_global_environment (ecma_object_t *global_object_p) /**< global object */
|
||||
{
|
||||
JERRY_ASSERT (JERRY_CONTEXT (ecma_global_env_cp) != JMEM_CP_NULL);
|
||||
return ECMA_GET_NON_NULL_POINTER (ecma_object_t, JERRY_CONTEXT (ecma_global_env_cp));
|
||||
JERRY_ASSERT (global_object_p != NULL && ecma_builtin_is_global (global_object_p));
|
||||
return ECMA_GET_NON_NULL_POINTER (ecma_object_t, ((ecma_global_object_t *) global_object_p)->global_env_cp);
|
||||
} /* ecma_get_global_environment */
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
@ -85,13 +71,18 @@ ecma_get_global_environment (void)
|
||||
* Create the global lexical block on top of the global environment.
|
||||
*/
|
||||
void
|
||||
ecma_create_global_lexical_block (void)
|
||||
ecma_create_global_lexical_block (ecma_object_t *global_object_p) /**< global object */
|
||||
{
|
||||
if (JERRY_CONTEXT (ecma_global_scope_cp) == JERRY_CONTEXT (ecma_global_env_cp))
|
||||
JERRY_ASSERT (global_object_p != NULL && ecma_builtin_is_global (global_object_p));
|
||||
|
||||
ecma_global_object_t *real_global_object_p = (ecma_global_object_t *) global_object_p;
|
||||
|
||||
if (real_global_object_p->global_scope_cp == real_global_object_p->global_env_cp)
|
||||
{
|
||||
ecma_object_t *global_scope_p = ecma_create_decl_lex_env (ecma_get_global_environment ());
|
||||
ecma_object_t *global_scope_p = ecma_create_decl_lex_env (ecma_get_global_environment (global_object_p));
|
||||
global_scope_p->type_flags_refs |= (uint16_t) ECMA_OBJECT_FLAG_BLOCK;
|
||||
ECMA_SET_NON_NULL_POINTER (JERRY_CONTEXT (ecma_global_scope_cp), global_scope_p);
|
||||
ECMA_SET_NON_NULL_POINTER (real_global_object_p->global_scope_cp, global_scope_p);
|
||||
ecma_deref_object (global_scope_p);
|
||||
}
|
||||
} /* ecma_create_global_lexical_block */
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
@ -103,13 +94,13 @@ ecma_create_global_lexical_block (void)
|
||||
* @return pointer to the object's instance
|
||||
*/
|
||||
ecma_object_t *
|
||||
ecma_get_global_scope (void)
|
||||
ecma_get_global_scope (ecma_object_t *global_object_p) /**< global object */
|
||||
{
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
JERRY_ASSERT (JERRY_CONTEXT (ecma_global_scope_cp) != JMEM_CP_NULL);
|
||||
return ECMA_GET_NON_NULL_POINTER (ecma_object_t, JERRY_CONTEXT (ecma_global_scope_cp));
|
||||
JERRY_ASSERT (global_object_p != NULL && ecma_builtin_is_global (global_object_p));
|
||||
return ECMA_GET_NON_NULL_POINTER (ecma_object_t, ((ecma_global_object_t *) global_object_p)->global_scope_cp);
|
||||
#else /* !ENABLED (JERRY_ESNEXT) */
|
||||
return ecma_get_global_environment ();
|
||||
return ecma_get_global_environment (global_object_p);
|
||||
#endif /* !ENABLED (JERRY_ESNEXT) */
|
||||
} /* ecma_get_global_scope */
|
||||
|
||||
|
||||
@ -32,10 +32,10 @@
|
||||
|
||||
void ecma_init_global_environment (void);
|
||||
void ecma_finalize_global_environment (void);
|
||||
ecma_object_t *ecma_get_global_environment (void);
|
||||
ecma_object_t *ecma_get_global_scope (void);
|
||||
ecma_object_t *ecma_get_global_environment (ecma_object_t *global_object_p);
|
||||
ecma_object_t *ecma_get_global_scope (ecma_object_t *global_object_p);
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
void ecma_create_global_lexical_block (void);
|
||||
void ecma_create_global_lexical_block (ecma_object_t *global_object_p);
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
#if ENABLED (JERRY_MODULE_SYSTEM)
|
||||
|
||||
@ -2537,7 +2537,7 @@ inline static bool
|
||||
ecma_object_check_class_name_is_object (ecma_object_t *obj_p) /**< object */
|
||||
{
|
||||
#ifndef JERRY_NDEBUG
|
||||
return (ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_GLOBAL)
|
||||
return (ecma_builtin_is_global (obj_p)
|
||||
#if ENABLED (JERRY_BUILTIN_PROMISE)
|
||||
|| ecma_builtin_is (obj_p, ECMA_BUILTIN_ID_PROMISE_PROTOTYPE)
|
||||
#endif /* ENABLED (JERRY_BUILTIN_PROMISE) */
|
||||
|
||||
@ -79,6 +79,23 @@ ecma_op_resolve_reference_base (ecma_object_t *lex_env_p, /**< starting lexical
|
||||
} /* ecma_op_resolve_reference_base */
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
|
||||
/**
|
||||
* Check if the passed lexical environment is a global lexical environment
|
||||
*
|
||||
* @return true - if the lexical environment is a global lexical environment
|
||||
* false - otherwise
|
||||
*/
|
||||
static inline bool JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_op_is_global_environment (ecma_object_t *lex_env_p) /**< lexical environment */
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND);
|
||||
JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL
|
||||
|| ecma_get_lex_env_binding_object (lex_env_p) == ecma_builtin_get_global ());
|
||||
|
||||
return lex_env_p->u2.outer_reference_cp == JMEM_CP_NULL;
|
||||
} /* ecma_op_is_global_environment */
|
||||
|
||||
/**
|
||||
* Perform GetThisEnvironment and GetSuperBase operations
|
||||
*
|
||||
@ -173,6 +190,7 @@ ecma_op_is_prop_unscopable (ecma_object_t *binding_obj_p, /**< binding object */
|
||||
|
||||
return ECMA_VALUE_FALSE;
|
||||
} /* ecma_op_is_prop_unscopable */
|
||||
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
/**
|
||||
@ -226,7 +244,7 @@ ecma_op_object_bound_environment_resolve_reference_value (ecma_object_t *lex_env
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
if (JERRY_LIKELY (lex_env_p == ecma_get_global_scope ()))
|
||||
if (JERRY_LIKELY (ecma_op_is_global_environment (lex_env_p)))
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
{
|
||||
return found_binding;
|
||||
@ -297,7 +315,7 @@ ecma_op_resolve_reference_value (ecma_object_t *lex_env_p, /**< starting lexical
|
||||
else if (lex_env_type == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND)
|
||||
{
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
bool lcache_lookup_allowed = (lex_env_p == ecma_get_global_environment ());
|
||||
bool lcache_lookup_allowed = ecma_op_is_global_environment (lex_env_p);
|
||||
#else /* !ENABLED (JERRY_ESNEXT)*/
|
||||
bool lcache_lookup_allowed = true;
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
@ -105,6 +105,7 @@ typedef enum
|
||||
JERRY_FEATURE_WEAKMAP, /**< WeakMap support */
|
||||
JERRY_FEATURE_WEAKSET, /**< WeakSet support */
|
||||
JERRY_FEATURE_BIGINT, /**< BigInt support */
|
||||
JERRY_FEATURE_REALM, /**< realm support */
|
||||
JERRY_FEATURE__COUNT /**< number of features. NOTE: must be at the end of the list */
|
||||
} jerry_feature_t;
|
||||
|
||||
@ -600,6 +601,7 @@ jerry_value_t jerry_create_external_string_sz (const jerry_char_t *str_p, jerry_
|
||||
jerry_value_t jerry_create_symbol (const jerry_value_t value);
|
||||
jerry_value_t jerry_create_bigint (const uint64_t *digits_p, uint32_t size, bool sign);
|
||||
jerry_value_t jerry_create_undefined (void);
|
||||
jerry_value_t jerry_create_realm (void);
|
||||
|
||||
/**
|
||||
* General API functions of JS objects.
|
||||
|
||||
@ -30,7 +30,7 @@ extern "C"
|
||||
/**
|
||||
* Jerry snapshot format version.
|
||||
*/
|
||||
#define JERRY_SNAPSHOT_VERSION (61u)
|
||||
#define JERRY_SNAPSHOT_VERSION (62u)
|
||||
|
||||
/**
|
||||
* Flags for jerry_generate_snapshot and jerry_generate_function_snapshot.
|
||||
|
||||
@ -106,7 +106,7 @@ typedef struct jerry_context_data_header
|
||||
/**
|
||||
* First non-external member of the jerry context
|
||||
*/
|
||||
#define JERRY_CONTEXT_FIRST_MEMBER ecma_builtin_objects
|
||||
#define JERRY_CONTEXT_FIRST_MEMBER global_object_p
|
||||
|
||||
/**
|
||||
* JerryScript context
|
||||
@ -125,18 +125,18 @@ struct jerry_context_t
|
||||
#endif /* ENABLED (JERRY_EXTERNAL_CONTEXT) */
|
||||
|
||||
/* Update JERRY_CONTEXT_FIRST_MEMBER if the first non-external member changes */
|
||||
jmem_cpointer_t ecma_builtin_objects[ECMA_BUILTIN_ID__COUNT]; /**< pointer to instances of built-in objects */
|
||||
ecma_global_object_t *global_object_p; /**< current global object */
|
||||
jmem_heap_free_t *jmem_heap_list_skip_p; /**< improves deallocation performance */
|
||||
jmem_pools_chunk_t *jmem_free_8_byte_chunk_p; /**< list of free eight byte pool chunks */
|
||||
#if ENABLED (JERRY_BUILTIN_REGEXP)
|
||||
re_compiled_code_t *re_cache[RE_CACHE_SIZE]; /**< regex cache */
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REGEXP) */
|
||||
jmem_cpointer_t ecma_gc_objects_cp; /**< List of currently alive objects. */
|
||||
jmem_heap_free_t *jmem_heap_list_skip_p; /**< This is used to speed up deallocation. */
|
||||
jmem_pools_chunk_t *jmem_free_8_byte_chunk_p; /**< list of free eight byte pool chunks */
|
||||
#if ENABLED (JERRY_CPOINTER_32_BIT)
|
||||
jmem_pools_chunk_t *jmem_free_16_byte_chunk_p; /**< list of free sixteen byte pool chunks */
|
||||
#endif /* ENABLED (JERRY_CPOINTER_32_BIT) */
|
||||
const lit_utf8_byte_t * const *lit_magic_string_ex_array; /**< array of external magic strings */
|
||||
const lit_utf8_size_t *lit_magic_string_ex_sizes; /**< external magic string lengths */
|
||||
jmem_cpointer_t ecma_gc_objects_cp; /**< List of currently alive objects. */
|
||||
jmem_cpointer_t string_list_first_cp; /**< first item of the literal string list */
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
jmem_cpointer_t symbol_list_first_cp; /**< first item of the global symbol list */
|
||||
@ -145,10 +145,6 @@ struct jerry_context_t
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
jmem_cpointer_t bigint_list_first_cp; /**< first item of the literal bigint list */
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
jmem_cpointer_t ecma_global_env_cp; /**< global lexical environment */
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
jmem_cpointer_t ecma_global_scope_cp; /**< global lexical scope */
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
#if ENABLED (JERRY_MODULE_SYSTEM)
|
||||
ecma_module_t *ecma_modules_p; /**< list of referenced modules */
|
||||
|
||||
@ -852,6 +852,9 @@ typedef struct
|
||||
uint8_t ident_end; /**< end position of the identifier group */
|
||||
uint8_t const_literal_end; /**< end position of the const literal group */
|
||||
uint8_t literal_end; /**< end position of the literal group */
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
ecma_value_t realm_value; /**< realm value */
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
} cbc_uint8_arguments_t;
|
||||
|
||||
/**
|
||||
@ -867,6 +870,9 @@ typedef struct
|
||||
uint16_t const_literal_end; /**< end position of the const literal group */
|
||||
uint16_t literal_end; /**< end position of the literal group */
|
||||
uint16_t padding; /**< an unused value */
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
ecma_value_t realm_value; /**< realm value */
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
} cbc_uint16_arguments_t;
|
||||
|
||||
/**
|
||||
@ -901,6 +907,7 @@ typedef enum
|
||||
CBC_FUNCTION_CONSTRUCTOR, /**< constructor function */
|
||||
|
||||
/* The following functions cannot be constructed (see CBC_FUNCTION_IS_CONSTRUCTABLE) */
|
||||
CBC_FUNCTION_SCRIPT, /**< script (global) function */
|
||||
CBC_FUNCTION_GENERATOR, /**< generator function */
|
||||
CBC_FUNCTION_ASYNC, /**< async function */
|
||||
CBC_FUNCTION_ASYNC_GENERATOR, /**< async generator function */
|
||||
|
||||
@ -977,6 +977,9 @@ parser_post_processing (parser_context_t *context_p) /**< context */
|
||||
args_p->ident_end = ident_end;
|
||||
args_p->const_literal_end = const_literal_end;
|
||||
args_p->literal_end = context_p->literal_count;
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
args_p->realm_value = ecma_make_object_value ((ecma_object_t *) JERRY_CONTEXT (global_object_p));
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
compiled_code_p->status_flags |= CBC_CODE_FLAGS_UINT16_ARGUMENTS;
|
||||
byte_code_p += sizeof (cbc_uint16_arguments_t);
|
||||
@ -991,6 +994,9 @@ parser_post_processing (parser_context_t *context_p) /**< context */
|
||||
args_p->ident_end = (uint8_t) ident_end;
|
||||
args_p->const_literal_end = (uint8_t) const_literal_end;
|
||||
args_p->literal_end = (uint8_t) context_p->literal_count;
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
args_p->realm_value = ecma_make_object_value ((ecma_object_t *) JERRY_CONTEXT (global_object_p));
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
byte_code_p += sizeof (cbc_uint8_arguments_t);
|
||||
}
|
||||
@ -1032,6 +1038,10 @@ parser_post_processing (parser_context_t *context_p) /**< context */
|
||||
{
|
||||
function_type = CBC_FUNCTION_TO_TYPE_BITS (CBC_FUNCTION_ACCESSOR);
|
||||
}
|
||||
else if (!(context_p->status_flags & PARSER_IS_FUNCTION))
|
||||
{
|
||||
function_type = CBC_FUNCTION_TO_TYPE_BITS (CBC_FUNCTION_SCRIPT);
|
||||
}
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
else if (context_p->status_flags & PARSER_IS_ARROW_FUNCTION)
|
||||
{
|
||||
@ -1067,10 +1077,6 @@ parser_post_processing (parser_context_t *context_p) /**< context */
|
||||
{
|
||||
function_type = CBC_FUNCTION_TO_TYPE_BITS (CBC_FUNCTION_METHOD);
|
||||
}
|
||||
else
|
||||
{
|
||||
function_type = CBC_FUNCTION_TO_TYPE_BITS (CBC_FUNCTION_NORMAL);
|
||||
}
|
||||
|
||||
if (context_p->status_flags & PARSER_LEXICAL_BLOCK_NEEDED)
|
||||
{
|
||||
|
||||
@ -842,8 +842,18 @@ opfunc_resume_executable_object (vm_executable_object_t *executable_object_p, /*
|
||||
ecma_object_t *old_new_target = JERRY_CONTEXT (current_new_target);
|
||||
JERRY_CONTEXT (current_new_target) = NULL;
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p);
|
||||
ecma_value_t realm_value = ecma_op_function_get_realm (bytecode_header_p);
|
||||
JERRY_CONTEXT (global_object_p) = (ecma_global_object_t *) ecma_get_object_from_value (realm_value);
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
ecma_value_t result = vm_execute (&executable_object_p->frame_ctx);
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
JERRY_CONTEXT (global_object_p) = saved_global_object_p;
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
JERRY_CONTEXT (current_new_target) = old_new_target;
|
||||
executable_object_p->extended_object.u.class_prop.extra_info &= (uint16_t) ~ECMA_EXECUTABLE_OBJECT_RUNNING;
|
||||
|
||||
|
||||
@ -301,16 +301,22 @@ vm_run_module (const ecma_compiled_code_t *bytecode_p, /**< pointer to bytecode
|
||||
ecma_value_t
|
||||
vm_run_global (const ecma_compiled_code_t *bytecode_p) /**< pointer to bytecode to run */
|
||||
{
|
||||
ecma_object_t *glob_obj_p = ecma_builtin_get_global ();
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
ecma_value_t realm_value = ecma_op_function_get_realm (bytecode_p);
|
||||
ecma_object_t *global_obj_p = ecma_get_object_from_value (realm_value);
|
||||
#else /* !ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
ecma_object_t *global_obj_p = ecma_builtin_get_global ();
|
||||
ecma_value_t realm_value = ecma_make_object_value (global_obj_p);
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
if (bytecode_p->status_flags & CBC_CODE_FLAGS_LEXICAL_BLOCK_NEEDED)
|
||||
{
|
||||
ecma_create_global_lexical_block ();
|
||||
ecma_create_global_lexical_block (global_obj_p);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
ecma_object_t *const global_scope_p = ecma_get_global_scope ();
|
||||
ecma_object_t *const global_scope_p = ecma_get_global_scope (global_obj_p);
|
||||
|
||||
#if ENABLED (JERRY_MODULE_SYSTEM)
|
||||
if (JERRY_CONTEXT (module_top_context_p) != NULL)
|
||||
@ -337,7 +343,7 @@ vm_run_global (const ecma_compiled_code_t *bytecode_p) /**< pointer to bytecode
|
||||
shared.bytecode_header_p = bytecode_p;
|
||||
shared.status_flags = 0;
|
||||
|
||||
return vm_run (&shared, ecma_make_object_value (glob_obj_p), global_scope_p);
|
||||
return vm_run (&shared, realm_value, global_scope_p);
|
||||
} /* vm_run_global */
|
||||
|
||||
/**
|
||||
@ -381,10 +387,16 @@ vm_run_eval (ecma_compiled_code_t *bytecode_data_p, /**< byte-code data */
|
||||
}
|
||||
else
|
||||
{
|
||||
#if ENABLED (JERRY_BUILTIN_REALMS)
|
||||
ecma_value_t realm_value = ecma_op_function_get_realm (bytecode_data_p);
|
||||
ecma_object_t *global_obj_p = ecma_get_object_from_value (realm_value);
|
||||
#else /* !ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
ecma_object_t *global_obj_p = ecma_builtin_get_global ();
|
||||
ecma_value_t realm_value = ecma_make_object_value (global_obj_p);
|
||||
#endif /* ENABLED (JERRY_BUILTIN_REALMS) */
|
||||
this_binding = realm_value;
|
||||
ecma_ref_object (global_obj_p);
|
||||
this_binding = ecma_make_object_value (global_obj_p);
|
||||
lex_env_p = ecma_get_global_scope ();
|
||||
lex_env_p = ecma_get_global_scope (global_obj_p);
|
||||
}
|
||||
|
||||
ecma_ref_object (lex_env_p);
|
||||
@ -1604,7 +1616,8 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
case VM_OC_CHECK_VAR:
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_global_scope () == frame_ctx_p->lex_env_p);
|
||||
JERRY_ASSERT (CBC_FUNCTION_GET_TYPE (frame_ctx_p->shared_p->bytecode_header_p->status_flags)
|
||||
== CBC_FUNCTION_SCRIPT);
|
||||
|
||||
uint32_t literal_index;
|
||||
READ_LITERAL_INDEX (literal_index);
|
||||
@ -1627,7 +1640,8 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
}
|
||||
case VM_OC_CHECK_LET:
|
||||
{
|
||||
JERRY_ASSERT (ecma_get_global_scope () == frame_ctx_p->lex_env_p);
|
||||
JERRY_ASSERT (CBC_FUNCTION_GET_TYPE (frame_ctx_p->shared_p->bytecode_header_p->status_flags)
|
||||
== CBC_FUNCTION_SCRIPT);
|
||||
|
||||
uint32_t literal_index;
|
||||
READ_LITERAL_INDEX (literal_index);
|
||||
|
||||
@ -44,6 +44,19 @@ main_register_global_function (const char *name_p, /**< name of the function */
|
||||
jerry_release_value (result_val);
|
||||
} /* main_register_global_function */
|
||||
|
||||
static jerry_value_t
|
||||
main_create_realm (const jerry_value_t func_obj_val, /**< function object */
|
||||
const jerry_value_t this_p, /**< this arg */
|
||||
const jerry_value_t args_p[], /**< function arguments */
|
||||
const jerry_length_t args_cnt) /**< number of function arguments */
|
||||
{
|
||||
(void) func_obj_val; /* unused */
|
||||
(void) this_p; /* unused */
|
||||
(void) args_p; /* unused */
|
||||
(void) args_cnt; /* unused */
|
||||
return jerry_create_realm ();
|
||||
} /* main_create_realm */
|
||||
|
||||
/**
|
||||
* Register a method for the $262 object.
|
||||
*/
|
||||
@ -204,6 +217,7 @@ main_init_engine (main_args_t *arguments_p) /** main arguments */
|
||||
main_register_global_function ("gc", jerryx_handler_gc);
|
||||
main_register_global_function ("print", jerryx_handler_print);
|
||||
main_register_global_function ("resourceName", jerryx_handler_resource_name);
|
||||
main_register_global_function ("createRealm", main_create_realm);
|
||||
} /* main_init_engine */
|
||||
|
||||
/**
|
||||
|
||||
@ -9,6 +9,7 @@ f | Function |
|
||||
addX | Function |
|
||||
z | undefined | undefined
|
||||
c | undefined | undefined
|
||||
createRealm | Function |
|
||||
resourceName | Function |
|
||||
print | Function |
|
||||
gc | Function |
|
||||
@ -21,6 +22,7 @@ f | Function |
|
||||
addX | Function |
|
||||
z | undefined | undefined
|
||||
c | undefined | undefined
|
||||
createRealm | Function |
|
||||
resourceName | Function |
|
||||
print | Function |
|
||||
gc | Function |
|
||||
@ -48,6 +50,7 @@ f | Function |
|
||||
addX | Function |
|
||||
z | Number | 5
|
||||
c | Number | 4
|
||||
createRealm | Function |
|
||||
resourceName | Function |
|
||||
print | Function |
|
||||
gc | Function |
|
||||
@ -68,6 +71,7 @@ f | Function |
|
||||
addX | Function |
|
||||
z | Number | 5
|
||||
c | Number | 4
|
||||
createRealm | Function |
|
||||
resourceName | Function |
|
||||
print | Function |
|
||||
gc | Function |
|
||||
|
||||
95
tests/jerry/es.next/realms1.js
Normal file
95
tests/jerry/es.next/realms1.js
Normal file
@ -0,0 +1,95 @@
|
||||
// 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.
|
||||
|
||||
var realm = createRealm()
|
||||
var ev = realm.eval
|
||||
|
||||
assert(realm.Math != Math)
|
||||
assert(typeof realm.Math === "object")
|
||||
assert(realm.Object != Object)
|
||||
assert(typeof realm.Object === "function")
|
||||
assert(realm.eval != eval)
|
||||
assert(typeof realm.eval === "function")
|
||||
|
||||
// Share our 'assert' function with the realm
|
||||
realm.assert = assert
|
||||
|
||||
// Test1: var1 and var2 must be different properties
|
||||
|
||||
realm.var1 = 3.5
|
||||
assert(realm.var2 === undefined)
|
||||
|
||||
var var1 = "X"
|
||||
var var2 = "Y"
|
||||
|
||||
ev("assert(var1 === 3.5); \
|
||||
try { realm; assert(false) } catch (e) { assert(e instanceof ReferenceError) } \
|
||||
assert(this === globalThis); \
|
||||
var var2 = this")
|
||||
assert(realm.var2 === realm)
|
||||
|
||||
assert(var1 === "X")
|
||||
assert(var2 === "Y")
|
||||
|
||||
// Test2: constructing any objects (including errors) must use the realm
|
||||
|
||||
assert (realm.RangeError != RangeError)
|
||||
assert (realm.RangeError.prototype != RangeError.prototype)
|
||||
|
||||
realm.RangeError.prototype.myProperty = "XY"
|
||||
assert(RangeError.prototype.myProperty === undefined)
|
||||
|
||||
try {
|
||||
var NumberToString = realm.Number.prototype.toString;
|
||||
NumberToString.call(0, 0)
|
||||
assert(false)
|
||||
} catch (e) {
|
||||
assert(e instanceof realm.RangeError)
|
||||
assert(!(e instanceof RangeError))
|
||||
assert(e.myProperty === "XY")
|
||||
}
|
||||
|
||||
assert (realm.SyntaxError != SyntaxError)
|
||||
assert (realm.SyntaxError.prototype != SyntaxError.prototype)
|
||||
|
||||
realm.SyntaxError.prototype.myProperty = "AB"
|
||||
assert(SyntaxError.prototype.myProperty === undefined)
|
||||
|
||||
try {
|
||||
ev("5 +")
|
||||
assert(false)
|
||||
} catch (e) {
|
||||
assert(e instanceof realm.SyntaxError)
|
||||
assert(!(e instanceof SyntaxError))
|
||||
assert(e.myProperty === "AB")
|
||||
}
|
||||
|
||||
// Test3: only the realm corresponding to the function matters
|
||||
|
||||
realm.Boolean.prototype.valueOf.a = Function.prototype.apply
|
||||
Boolean.prototype.valueOf.a = realm.Function.prototype.apply
|
||||
|
||||
try {
|
||||
realm.Boolean.prototype.valueOf.a()
|
||||
} catch (e) {
|
||||
assert(e instanceof realm.TypeError)
|
||||
assert(!(e instanceof TypeError))
|
||||
}
|
||||
|
||||
try {
|
||||
Boolean.prototype.valueOf.a()
|
||||
} catch (e) {
|
||||
assert(e instanceof TypeError)
|
||||
assert(!(e instanceof realm.TypeError))
|
||||
}
|
||||
48
tests/jerry/es.next/realms2.js
Normal file
48
tests/jerry/es.next/realms2.js
Normal file
@ -0,0 +1,48 @@
|
||||
// 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.
|
||||
|
||||
// Test1: realm cannot be gc-ed until it is referenced
|
||||
|
||||
function f1() {
|
||||
var ev = createRealm().eval
|
||||
|
||||
gc()
|
||||
|
||||
try {
|
||||
ev("5 +")
|
||||
} catch (e) {
|
||||
assert(e instanceof ev("this").SyntaxError)
|
||||
assert(!(e instanceof SyntaxError))
|
||||
}
|
||||
}
|
||||
f1()
|
||||
|
||||
// Test2: built-ins cannot be gc-ed until the realm exists
|
||||
|
||||
function f2() {
|
||||
var realm = createRealm()
|
||||
|
||||
var str = new realm.String("A");
|
||||
// Assign a property to String.prototype
|
||||
Object.getPrototypeOf(str).myProperty = "XY"
|
||||
|
||||
str = null
|
||||
// No reference to String.prototype
|
||||
gc()
|
||||
|
||||
str = new realm.String("A")
|
||||
assert(Object.getPrototypeOf(str).myProperty === "XY")
|
||||
assert(realm.String.prototype.myProperty === "XY")
|
||||
}
|
||||
f2()
|
||||
198
tests/jerry/es.next/realms3.js
Normal file
198
tests/jerry/es.next/realms3.js
Normal file
@ -0,0 +1,198 @@
|
||||
// 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.
|
||||
|
||||
// Test1: reading global values from other realms
|
||||
|
||||
var a = 4.5
|
||||
|
||||
function f1()
|
||||
{
|
||||
var realm = createRealm()
|
||||
var f = realm.eval("function g() { return a } g")
|
||||
|
||||
realm.a = -6.25
|
||||
assert(f() === -6.25)
|
||||
assert(a === 4.5)
|
||||
assert(realm.g === f)
|
||||
|
||||
realm.eval("var v1 = 6; eval('var v2 = 7.5')")
|
||||
assert(realm.v1 === 6)
|
||||
assert(realm.v2 === 7.5)
|
||||
|
||||
var e = realm.eval
|
||||
|
||||
eval("e('var v3 = -5.25'); var v3 = 1.5; e('v3++')")
|
||||
assert(realm.v3 === -4.25)
|
||||
assert(v3 === 1.5)
|
||||
}
|
||||
f1()
|
||||
|
||||
// Test2: recursive calls
|
||||
|
||||
var b = "S"
|
||||
|
||||
function f2()
|
||||
{
|
||||
function f(fun) {
|
||||
return fun() + b;
|
||||
}
|
||||
|
||||
var realm = createRealm()
|
||||
|
||||
realm.eval("function h() { return b }")
|
||||
|
||||
var g = realm.Function("fun", "return fun(h) + b")
|
||||
|
||||
realm.b = "X"
|
||||
assert(g(f) === "XSX")
|
||||
assert(b === "S")
|
||||
}
|
||||
f2()
|
||||
|
||||
// Test3: built-in functions
|
||||
|
||||
function f3()
|
||||
{
|
||||
var realm = createRealm()
|
||||
|
||||
realm.f = function () { return eval("/a/") }
|
||||
|
||||
var res = realm.eval("[f(), /a/, f(), /b/]")
|
||||
|
||||
assert(Object.getPrototypeOf(res[0]) === RegExp.prototype)
|
||||
assert(Object.getPrototypeOf(res[1]) === realm.RegExp.prototype)
|
||||
assert(Object.getPrototypeOf(res[2]) === RegExp.prototype)
|
||||
assert(Object.getPrototypeOf(res[3]) === realm.RegExp.prototype)
|
||||
|
||||
realm.g = function () { return non_existent }
|
||||
|
||||
try {
|
||||
realm.eval("g()")
|
||||
assert(false)
|
||||
} catch (e) {
|
||||
assert(e instanceof ReferenceError)
|
||||
assert(!(e instanceof realm.ReferenceError))
|
||||
}
|
||||
|
||||
try {
|
||||
realm.eval("non_existent")
|
||||
assert(false)
|
||||
} catch (e) {
|
||||
assert(e instanceof realm.ReferenceError)
|
||||
assert(!(e instanceof ReferenceError))
|
||||
}
|
||||
}
|
||||
f3()
|
||||
|
||||
// Test4: generator functions
|
||||
|
||||
function f4()
|
||||
{
|
||||
function f() {
|
||||
return b;
|
||||
}
|
||||
|
||||
var realm = createRealm()
|
||||
|
||||
function check_gen_result(result, value, done)
|
||||
{
|
||||
assert(Object.getPrototypeOf(result) === realm.Object.prototype)
|
||||
assert(result.value === value)
|
||||
assert(result.done === done)
|
||||
}
|
||||
|
||||
realm.eval("var a = 'P', b = 'Q'")
|
||||
|
||||
var gen = realm.eval("function* gen(f) { yield f() + a; yield f() + b; return a + b + f() }")
|
||||
|
||||
var it = realm.gen(f)
|
||||
|
||||
check_gen_result(it.next(), "SP", false)
|
||||
check_gen_result(it.next(), "SQ", false)
|
||||
check_gen_result(it.next(), "PQS", true)
|
||||
}
|
||||
f4()
|
||||
|
||||
// Test5: async functions
|
||||
|
||||
var successCount = 0
|
||||
|
||||
function f5()
|
||||
{
|
||||
function f() {
|
||||
return b;
|
||||
}
|
||||
|
||||
var r, p = new Promise(function(resolve, reject) { r = resolve })
|
||||
|
||||
var realm = createRealm()
|
||||
|
||||
realm.assert = assert
|
||||
realm.eval("async function asy(p, f) { assert(f() === 'S'); assert(await p === 4.5); return f() + b }")
|
||||
|
||||
realm.b = "X"
|
||||
|
||||
realm.asy(p, f).then(function(v) {
|
||||
assert(v === "SX")
|
||||
successCount++
|
||||
}, function() {
|
||||
assert(false)
|
||||
})
|
||||
r(4.5)
|
||||
}
|
||||
f5()
|
||||
|
||||
// Test6: async generator functions
|
||||
|
||||
function f6()
|
||||
{
|
||||
function f() {
|
||||
return b;
|
||||
}
|
||||
|
||||
var r, p = new Promise(function(resolve, reject) { r = resolve })
|
||||
|
||||
var realm = createRealm()
|
||||
|
||||
function check_fulfilled(p, value, done)
|
||||
{
|
||||
assert(p instanceof realm.Promise)
|
||||
|
||||
p.then(function(v) {
|
||||
assert(v.value === value)
|
||||
assert(v.done === done)
|
||||
successCount++
|
||||
}, function() {
|
||||
assert(false)
|
||||
})
|
||||
}
|
||||
|
||||
realm.assert = assert
|
||||
realm.eval("async function *asygen(p, f) { assert(f() === 'S'); assert(await p === -1.5); yield f() + a; return f() + b }")
|
||||
|
||||
realm.a = "X"
|
||||
realm.b = "Y"
|
||||
|
||||
var gen = realm.asygen(p, f)
|
||||
|
||||
check_fulfilled(gen.next(), "SX", false)
|
||||
check_fulfilled(gen.next(), "SY", true)
|
||||
|
||||
r(-1.5)
|
||||
}
|
||||
f6()
|
||||
|
||||
function __checkAsync() {
|
||||
assert(successCount === 3)
|
||||
}
|
||||
@ -51,4 +51,4 @@ try {
|
||||
/* Check properties of a */
|
||||
assert(Object.keys(a) == "one,two");
|
||||
/* Check properties of global object */
|
||||
assert(Object.keys(this) == "assert,gc,print,resourceName,a,fail,fail_two");
|
||||
assert(Object.keys(this) == "assert,gc,print,resourceName,createRealm,a,fail,fail_two");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user