diff --git a/docs/02.API-REFERENCE.md b/docs/02.API-REFERENCE.md index ab43cb8e3..7ee5bc086 100644 --- a/docs/02.API-REFERENCE.md +++ b/docs/02.API-REFERENCE.md @@ -164,10 +164,10 @@ Container object types: Well-known symbols: + - JERRY_SYMBOL_ASYNC_ITERATOR - @@asyncIterator well-known symbol - JERRY_SYMBOL_HAS_INSTANCE - @@hasInstance well-known symbol - JERRY_SYMBOL_IS_CONCAT_SPREADABLE - @@isConcatSpreadable well-known symbol - JERRY_SYMBOL_ITERATOR - @@iterator well-known symbol - - JERRY_SYMBOL_ASYNC_ITERATOR - @@asyncIterator well-known symbol - JERRY_SYMBOL_MATCH - @@match well-known symbol - JERRY_SYMBOL_REPLACE - @@replace well-known symbol - JERRY_SYMBOL_SEARCH - @@search well-known symbol @@ -9118,6 +9118,59 @@ main (int argc, char** argv) - [jerry_construct_object](#jerry_construct_object) +## jerry_set_realm + +**Summary** + +Replaces the currently active realm (including the global object) with another realm. +The replacement should be temporary, and the original realm must be restored after +the tasks are completed. During the replacement, the realm must be referenced +by the application (i.e. the gc must not reclaim it). This is also true to +the returned previously active realm, so there is no need to free the value +after the restoration. The function can only fail if realms are not supported +or the passed argument is not a realm. In this case the returned exception must +be freed by [jerry_release_value](#jerry_release_value). + +This function is useful to parse a script, create a native function, load a snapshot +or create an exception in another realm. Each ECMAScript code runs in the realm +which was active when the code was parsed or loaded regardless of the current realm. + +*Notes*: +- This feature depends on build option (`JERRY_BUILTIN_REALMS`) and can be checked + in runtime with the `JERRY_FEATURE_REALM` feature enum value, + see: [jerry_is_feature_enabled](#jerry_is_feature_enabled). + +**Prototype** + +```c +jerry_value_t +jerry_set_realm (jerry_value_t realm_value); +``` +- `realm_value` - the new realm value +- return + - previous realm value - if the passed value is a realm + - exception - otherwise + +*New in version [[NEXT_RELEASE]]*. + +**Example** + +```c +{ + jerry_value_t realm_value = jerry_create_realm (); + + jerry_value_t old_realm = jerry_set_realm (realm_value); + + ... // usage of the realm + + jerry_set_realm (old_realm); +} +``` + +**See also** + +- [jerry_create_realm](#jerry_create_realm) + # ArrayBuffer and TypedArray functions These APIs all depend on the es.next profile. diff --git a/jerry-core/api/jerry.c b/jerry-core/api/jerry.c index a4b3a3cb9..1a80269fb 100644 --- a/jerry-core/api/jerry.c +++ b/jerry-core/api/jerry.c @@ -4204,7 +4204,7 @@ jerry_get_well_known_symbol (jerry_well_known_symbol_t symbol) /**< jerry_well_k jerry_assert_api_available (); #if ENABLED (JERRY_ESNEXT) - lit_magic_string_id_t id = (lit_magic_string_id_t) (LIT_GLOBAL_SYMBOL__FISRT + symbol); + lit_magic_string_id_t id = (lit_magic_string_id_t) (LIT_GLOBAL_SYMBOL__FIRST + symbol); if (!LIT_IS_GLOBAL_SYMBOL (id)) { @@ -4564,6 +4564,44 @@ jerry_get_new_target (void) #endif /* ENABLED (JERRY_ESNEXT) */ } /* jerry_get_new_target */ +/** + * Replaces the currently active realm with another realm. + * + * The replacement should be temporary, and the original realm must be + * restored after the tasks are completed. During the replacement, the + * realm must be referenced by the application (i.e. the gc must not + * reclaim it). This is also true to the returned previously active + * realm, so there is no need to free the value after the restoration. + * + * @return previous realm value - if the passed value is a realm + * exception - otherwise + */ +jerry_value_t +jerry_set_realm (jerry_value_t realm_value) /**< jerry api value */ +{ + jerry_assert_api_available (); + +#if ENABLED (JERRY_BUILTIN_REALMS) + if (ecma_is_value_object (realm_value)) + { + ecma_object_t *object_p = ecma_get_object_from_value (realm_value); + + if (ecma_get_object_is_builtin (object_p) + && ecma_builtin_is_global (object_p)) + { + ecma_global_object_t *previous_global_object_p = JERRY_CONTEXT (global_object_p); + JERRY_CONTEXT (global_object_p) = (ecma_global_object_t *) object_p; + return ecma_make_object_value ((ecma_object_t *) previous_global_object_p); + } + } + + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Passed argument is not a realm"))); +#else /* !ENABLED (JERRY_BUILTIN_REALMS) */ + JERRY_UNUSED (realm_value); + return jerry_throw (ecma_raise_reference_error (ECMA_ERR_MSG ("Realm is not available"))); +#endif /* ENABLED (JERRY_BUILTIN_REALMS) */ +} /* jerry_set_realm */ + /** * Check if the given value is an ArrayBuffer object. * diff --git a/jerry-core/ecma/base/ecma-gc.c b/jerry-core/ecma/base/ecma-gc.c index 50a624234..64186b591 100644 --- a/jerry-core/ecma/base/ecma-gc.c +++ b/jerry-core/ecma/base/ecma-gc.c @@ -936,13 +936,25 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */ #endif /* ENABLED (JERRY_BUILTIN_REALMS) */ break; } -#if ENABLED (JERRY_ESNEXT) +#if ENABLED (JERRY_ESNEXT) || ENABLED (JERRY_BUILTIN_REALMS) case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: { +#endif /* ENABLED (JERRY_ESNEXT) || ENABLED (JERRY_BUILTIN_REALMS) */ + + if (!ecma_get_object_is_builtin (object_p)) + { +#if ENABLED (JERRY_BUILTIN_REALMS) + ecma_native_function_t *native_function_p = (ecma_native_function_t *) object_p; + ecma_gc_set_object_visited (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, + native_function_p->realm_value)); +#endif /* ENABLED (JERRY_BUILTIN_REALMS) */ + break; + } + +#if ENABLED (JERRY_ESNEXT) ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; - if (ecma_get_object_is_builtin (object_p) - && ext_func_p->u.built_in.id == ECMA_BUILTIN_ID_HANDLER) + if (ext_func_p->u.built_in.id == ECMA_BUILTIN_ID_HANDLER) { switch (ext_func_p->u.built_in.routine_id) { @@ -1005,10 +1017,12 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */ } } } +#endif /* ENABLED (JERRY_ESNEXT) */ +#if ENABLED (JERRY_ESNEXT) || ENABLED (JERRY_BUILTIN_REALMS) break; } -#endif /* ENABLED (JERRY_ESNEXT) */ +#endif /* ENABLED (JERRY_ESNEXT) || ENABLED (JERRY_BUILTIN_REALMS) */ default: { break; @@ -1496,6 +1510,7 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */ } case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: { + ext_object_size = sizeof (ecma_native_function_t); break; } case ECMA_OBJECT_TYPE_CLASS: diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index 74af0237c..1b429b873 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -994,8 +994,6 @@ typedef struct jmem_cpointer_tag_t target_function; /**< target function */ ecma_value_t args_len_or_this; /**< length of arguments or this value */ } bound_function; - - ecma_native_handler_t external_handler_cb; /**< external function */ } u; } ecma_extended_object_t; @@ -1014,6 +1012,18 @@ typedef struct #define ECMA_BUILTIN_IS_EXTENDED_BUILT_IN(object_type) \ ((object_type) == ECMA_OBJECT_TYPE_CLASS || (object_type) == ECMA_OBJECT_TYPE_ARRAY) +/** + * Description of native functions + */ +typedef struct +{ + ecma_extended_object_t extended_object; /**< extended object part */ +#if ENABLED (JERRY_BUILTIN_REALMS) + ecma_value_t realm_value; /**< realm value */ +#endif /* ENABLED (JERRY_BUILTIN_REALMS) */ + ecma_native_handler_t native_handler_cb; /**< external function */ +} ecma_native_function_t; + /** * Flags for array.length_prop_and_hole_count */ diff --git a/jerry-core/ecma/base/ecma-init-finalize.c b/jerry-core/ecma/base/ecma-init-finalize.c index 8acab129b..c522d54b2 100644 --- a/jerry-core/ecma/base/ecma-init-finalize.c +++ b/jerry-core/ecma/base/ecma-init-finalize.c @@ -88,6 +88,18 @@ ecma_finalize (void) } while (JERRY_CONTEXT (ecma_gc_new_objects) != 0); +#if ENABLED (JERRY_ESNEXT) + jmem_cpointer_t *global_symbols_cp = JERRY_CONTEXT (global_symbols_cp); + + for (uint32_t i = 0; i < ECMA_BUILTIN_GLOBAL_SYMBOL_COUNT; i++) + { + if (global_symbols_cp[i] != JMEM_CP_NULL) + { + ecma_deref_ecma_string (ECMA_GET_NON_NULL_POINTER (ecma_string_t, global_symbols_cp[i])); + } + } +#endif /* ENABLED (JERRY_ESNEXT) */ + ecma_finalize_lit_storage (); } /* ecma_finalize */ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-internal-routines-template.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-internal-routines-template.inc.h index 826f20aae..9302fd939 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-internal-routines-template.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-internal-routines-template.inc.h @@ -190,12 +190,12 @@ const ecma_builtin_property_descriptor_t PROPERTY_DESCRIPTOR_LIST_NAME[] = magic_string_id \ }, #if ENABLED (JERRY_ESNEXT) -#define SYMBOL_VALUE(symbol, desc_magic_string_id) \ +#define SYMBOL_VALUE(name, symbol) \ { \ - symbol, \ + name, \ ECMA_BUILTIN_PROPERTY_SYMBOL, \ ECMA_PROPERTY_FIXED, \ - desc_magic_string_id \ + symbol \ }, #define INTRINSIC_PROPERTY(name, magic_string_id, prop_attributes) \ { \ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.inc.h index d0063f7c9..9803fcabc 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-intrinsic.inc.h @@ -21,53 +21,6 @@ #if ENABLED (JERRY_ESNEXT) -/* ECMA-262 v10, 19.4.2.1 */ -SYMBOL_VALUE (LIT_GLOBAL_SYMBOL_ASYNC_ITERATOR, - LIT_MAGIC_STRING_ASYNC_ITERATOR) - -/* ECMA-262 v6, 19.4.2.2 */ -SYMBOL_VALUE (LIT_GLOBAL_SYMBOL_HAS_INSTANCE, - LIT_MAGIC_STRING_HAS_INSTANCE) - -/* ECMA-262 v6, 19.4.2.3 */ -SYMBOL_VALUE (LIT_GLOBAL_SYMBOL_IS_CONCAT_SPREADABLE, - LIT_MAGIC_STRING_IS_CONCAT_SPREADABLE) - -/* ECMA-262 v6, 19.4.2.4 */ -SYMBOL_VALUE (LIT_GLOBAL_SYMBOL_ITERATOR, - LIT_MAGIC_STRING_ITERATOR) - -/* ECMA-262 v6, 19.4.2.6 */ -SYMBOL_VALUE (LIT_GLOBAL_SYMBOL_MATCH, - LIT_MAGIC_STRING_MATCH) - -/* ECMA-262 v6, 19.4.2.8 */ -SYMBOL_VALUE (LIT_GLOBAL_SYMBOL_REPLACE, - LIT_MAGIC_STRING_REPLACE) - -/* ECMA-262 v6, 19.4.2.9 */ -SYMBOL_VALUE (LIT_GLOBAL_SYMBOL_SEARCH, - LIT_MAGIC_STRING_SEARCH) - -/* ECMA-262 v6, 19.4.2.10 */ -SYMBOL_VALUE (LIT_GLOBAL_SYMBOL_SPECIES, - LIT_MAGIC_STRING_SPECIES) - -/* ECMA-262 v6, 19.4.2.11 */ -SYMBOL_VALUE (LIT_GLOBAL_SYMBOL_SPLIT, - LIT_MAGIC_STRING_SPLIT) - -/* ECMA-262 v6, 19.4.2.12 */ -SYMBOL_VALUE (LIT_GLOBAL_SYMBOL_TO_PRIMITIVE, - LIT_MAGIC_STRING_TO_PRIMITIVE) - -/* ECMA-262 v6, 19.4.2.13 */ -SYMBOL_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, - LIT_MAGIC_STRING_TO_STRING_TAG) - -/* ECMA-262 v6, 19.4.2.14 */ -SYMBOL_VALUE (LIT_GLOBAL_SYMBOL_UNSCOPABLES, - LIT_MAGIC_STRING_UNSCOPABLES) /* Routine properties: * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ ROUTINE (LIT_INTERNAL_MAGIC_STRING_ARRAY_PROTOTYPE_VALUES, ECMA_INTRINSIC_ARRAY_PROTOTYPE_VALUES, 0, 0) diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.inc.h index 840a91a36..111c82596 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.inc.h @@ -42,64 +42,52 @@ OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_PROPERTY_FIXED) /* ECMA-262 v10, 19.4.2.1 */ -INTRINSIC_PROPERTY (LIT_MAGIC_STRING_ASYNC_ITERATOR, - LIT_GLOBAL_SYMBOL_ASYNC_ITERATOR, - ECMA_PROPERTY_FIXED) +SYMBOL_VALUE (LIT_MAGIC_STRING_ASYNC_ITERATOR, + LIT_GLOBAL_SYMBOL_ASYNC_ITERATOR) /* ECMA-262 v6, 19.4.2.2 */ -INTRINSIC_PROPERTY (LIT_MAGIC_STRING_HAS_INSTANCE, - LIT_GLOBAL_SYMBOL_HAS_INSTANCE, - ECMA_PROPERTY_FIXED) +SYMBOL_VALUE (LIT_MAGIC_STRING_HAS_INSTANCE, + LIT_GLOBAL_SYMBOL_HAS_INSTANCE) /* ECMA-262 v6, 19.4.2.3 */ -INTRINSIC_PROPERTY (LIT_MAGIC_STRING_IS_CONCAT_SPREADABLE, - LIT_GLOBAL_SYMBOL_IS_CONCAT_SPREADABLE, - ECMA_PROPERTY_FIXED) +SYMBOL_VALUE (LIT_MAGIC_STRING_IS_CONCAT_SPREADABLE, + LIT_GLOBAL_SYMBOL_IS_CONCAT_SPREADABLE) /* ECMA-262 v6, 19.4.2.4 */ -INTRINSIC_PROPERTY (LIT_MAGIC_STRING_ITERATOR, - LIT_GLOBAL_SYMBOL_ITERATOR, - ECMA_PROPERTY_FIXED) +SYMBOL_VALUE (LIT_MAGIC_STRING_ITERATOR, + LIT_GLOBAL_SYMBOL_ITERATOR) /* ECMA-262 v6, 19.4.2.6 */ -INTRINSIC_PROPERTY (LIT_MAGIC_STRING_MATCH, - LIT_GLOBAL_SYMBOL_MATCH, - ECMA_PROPERTY_FIXED) +SYMBOL_VALUE (LIT_MAGIC_STRING_MATCH, + LIT_GLOBAL_SYMBOL_MATCH) /* ECMA-262 v6, 19.4.2.8 */ -INTRINSIC_PROPERTY (LIT_MAGIC_STRING_REPLACE, - LIT_GLOBAL_SYMBOL_REPLACE, - ECMA_PROPERTY_FIXED) +SYMBOL_VALUE (LIT_MAGIC_STRING_REPLACE, + LIT_GLOBAL_SYMBOL_REPLACE) /* ECMA-262 v6, 19.4.2.9 */ -INTRINSIC_PROPERTY (LIT_MAGIC_STRING_SEARCH, - LIT_GLOBAL_SYMBOL_SEARCH, - ECMA_PROPERTY_FIXED) +SYMBOL_VALUE (LIT_MAGIC_STRING_SEARCH, + LIT_GLOBAL_SYMBOL_SEARCH) /* ECMA-262 v6, 19.4.2.10 */ -INTRINSIC_PROPERTY (LIT_MAGIC_STRING_SPECIES, - LIT_GLOBAL_SYMBOL_SPECIES, - ECMA_PROPERTY_FIXED) +SYMBOL_VALUE (LIT_MAGIC_STRING_SPECIES, + LIT_GLOBAL_SYMBOL_SPECIES) /* ECMA-262 v6, 19.4.2.11 */ -INTRINSIC_PROPERTY (LIT_MAGIC_STRING_SPLIT, - LIT_GLOBAL_SYMBOL_SPLIT, - ECMA_PROPERTY_FIXED) +SYMBOL_VALUE (LIT_MAGIC_STRING_SPLIT, + LIT_GLOBAL_SYMBOL_SPLIT) /* ECMA-262 v6, 19.4.2.12 */ -INTRINSIC_PROPERTY (LIT_MAGIC_STRING_TO_PRIMITIVE, - LIT_GLOBAL_SYMBOL_TO_PRIMITIVE, - ECMA_PROPERTY_FIXED) +SYMBOL_VALUE (LIT_MAGIC_STRING_TO_PRIMITIVE, + LIT_GLOBAL_SYMBOL_TO_PRIMITIVE) /* ECMA-262 v6, 19.4.2.13 */ -INTRINSIC_PROPERTY (LIT_MAGIC_STRING_TO_STRING_TAG, - LIT_GLOBAL_SYMBOL_TO_STRING_TAG, - ECMA_PROPERTY_FIXED) +SYMBOL_VALUE (LIT_MAGIC_STRING_TO_STRING_TAG, + LIT_GLOBAL_SYMBOL_TO_STRING_TAG) /* ECMA-262 v6, 19.4.2.14 */ -INTRINSIC_PROPERTY (LIT_MAGIC_STRING_UNSCOPABLES, - LIT_GLOBAL_SYMBOL_UNSCOPABLES, - ECMA_PROPERTY_FIXED) +SYMBOL_VALUE (LIT_MAGIC_STRING_UNSCOPABLES, + LIT_GLOBAL_SYMBOL_UNSCOPABLES) /* Routine properties: * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins.c b/jerry-core/ecma/builtin-objects/ecma-builtins.c index 8ecad7ec8..38811155e 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtins.c @@ -668,6 +668,8 @@ ecma_builtin_get (ecma_builtin_id_t builtin_id) /**< id of built-in to check on return ECMA_GET_NON_NULL_POINTER (ecma_object_t, *builtin_p); } /* ecma_builtin_get */ +#if ENABLED (JERRY_BUILTIN_REALMS) + /** * Get reference to specified built-in object using the realm provided by another built-in object * @@ -676,14 +678,12 @@ ecma_builtin_get (ecma_builtin_id_t builtin_id) /**< id of built-in to check on * * @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_object_t * +ecma_builtin_get_from_realm (ecma_global_object_t *global_object_p, /**< global 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)) @@ -692,11 +692,31 @@ ecma_builtin_get_from_realm (ecma_object_t *builtin_object_p, /**< built-in obje } return ECMA_GET_NON_NULL_POINTER (ecma_object_t, *builtin_p); +} /* ecma_builtin_get_from_realm */ + +#endif /* ENABLED (JERRY_BUILTIN_REALMS) */ + +/** + * 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 inline ecma_object_t * JERRY_ATTR_ALWAYS_INLINE +ecma_builtin_get_from_builtin (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) + return ecma_builtin_get_from_realm (ecma_builtin_get_realm (builtin_object_p), builtin_id); #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 */ +} /* ecma_builtin_get_from_builtin */ /** * Construct a Function object for specified built-in routine @@ -712,8 +732,8 @@ ecma_builtin_make_function_object_for_routine (ecma_object_t *builtin_object_p, 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_from_realm (builtin_object_p, - ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); + ecma_object_t *prototype_obj_p = ecma_builtin_get_from_builtin (builtin_object_p, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); size_t ext_object_size = sizeof (ecma_extended_object_t); @@ -1169,20 +1189,14 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object * #if ENABLED (JERRY_ESNEXT) case ECMA_BUILTIN_PROPERTY_SYMBOL: { - ecma_string_t *symbol_dot_p = ecma_get_magic_string (LIT_MAGIC_STRING_SYMBOL_DOT_UL); - ecma_string_t *name_p = ecma_get_magic_string ((lit_magic_string_id_t) curr_property_p->value); - ecma_string_t *descriptor_p = ecma_concat_ecma_strings (symbol_dot_p, name_p); + lit_magic_string_id_t symbol_id = (lit_magic_string_id_t) curr_property_p->value; - ecma_string_t *symbol_p = ecma_new_symbol_from_descriptor_string (ecma_make_string_value (descriptor_p)); - lit_magic_string_id_t symbol_id = (lit_magic_string_id_t) curr_property_p->magic_string_id; - symbol_p->u.hash = (uint16_t) ((symbol_id << ECMA_GLOBAL_SYMBOL_SHIFT) | ECMA_GLOBAL_SYMBOL_FLAG); - - value = ecma_make_symbol_value (symbol_p); + value = ecma_make_symbol_value (ecma_op_get_global_symbol (symbol_id)); break; } case ECMA_BUILTIN_PROPERTY_INTRINSIC_PROPERTY: { - ecma_object_t *intrinsic_object_p = ecma_builtin_get_from_realm (object_p, ECMA_BUILTIN_ID_INTRINSIC_OBJECT); + ecma_object_t *intrinsic_object_p = ecma_builtin_get_from_builtin (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; } @@ -1191,8 +1205,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_from_realm (object_p, getter_id); - setter_p = ecma_builtin_get_from_realm (object_p, setter_id); + getter_p = ecma_builtin_get_from_builtin (object_p, getter_id); + setter_p = ecma_builtin_get_from_builtin (object_p, setter_id); ecma_ref_object (getter_p); ecma_ref_object (setter_p); break; @@ -1201,7 +1215,7 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object * case ECMA_BUILTIN_PROPERTY_OBJECT: { ecma_object_t *builtin_object_p; - builtin_object_p = ecma_builtin_get_from_realm (object_p, (ecma_builtin_id_t) curr_property_p->value); + builtin_object_p = ecma_builtin_get_from_builtin (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; diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins.h b/jerry-core/ecma/builtin-objects/ecma-builtins.h index 86d17c325..ef3ffa043 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtins.h @@ -56,6 +56,12 @@ typedef enum */ #define ECMA_BUILTIN_ID_HANDLER ECMA_BUILTIN_ID__COUNT +/** + * Number of global symbols + */ +#define ECMA_BUILTIN_GLOBAL_SYMBOL_COUNT \ + (LIT_GLOBAL_SYMBOL__LAST - LIT_GLOBAL_SYMBOL__FIRST + 1) + #endif /* ENABLED (JERRY_ESNEXT) */ /** @@ -143,4 +149,9 @@ ecma_builtin_get_global (void); bool ecma_builtin_function_is_routine (ecma_object_t *func_obj_p); +#if ENABLED (JERRY_BUILTIN_REALMS) +ecma_object_t * +ecma_builtin_get_from_realm (ecma_global_object_t *global_object_p, ecma_builtin_id_t builtin_id); +#endif /* ENABLED (JERRY_BUILTIN_REALMS) */ + #endif /* !ECMA_BUILTINS_H */ diff --git a/jerry-core/ecma/operations/ecma-array-object.c b/jerry-core/ecma/operations/ecma-array-object.c index df78dc3c5..084350daf 100644 --- a/jerry-core/ecma/operations/ecma-array-object.c +++ b/jerry-core/ecma/operations/ecma-array-object.c @@ -708,13 +708,22 @@ ecma_op_array_species_create (ecma_object_t *original_array_p, /**< The object f return NULL; } - if (ecma_is_constructor (constructor) - && ecma_get_object_from_value (constructor) == ecma_builtin_get (ECMA_BUILTIN_ID_ARRAY)) +#if ENABLED (JERRY_BUILTIN_REALMS) + if (ecma_is_constructor (constructor)) { - ecma_free_value (constructor); - constructor = ECMA_VALUE_UNDEFINED; + ecma_object_t *constructor_p = ecma_get_object_from_value (constructor); + ecma_global_object_t *global_object_p = ecma_op_function_get_function_realm (constructor_p); + + if ((ecma_object_t *) global_object_p != ecma_builtin_get_global () + && constructor_p == ecma_builtin_get_from_realm (global_object_p, ECMA_BUILTIN_ID_ARRAY)) + { + ecma_deref_object (constructor_p); + constructor = ECMA_VALUE_UNDEFINED; + } } - else if (ecma_is_value_object (constructor)) +#endif /* ENABLED (JERRY_BUILTIN_REALMS) */ + + if (ecma_is_value_object (constructor)) { ecma_object_t *ctor_object_p = ecma_get_object_from_value (constructor); constructor = ecma_op_object_get_by_symbol_id (ctor_object_p, LIT_GLOBAL_SYMBOL_SPECIES); diff --git a/jerry-core/ecma/operations/ecma-function-object.c b/jerry-core/ecma/operations/ecma-function-object.c index 87f93a84a..064b98111 100644 --- a/jerry-core/ecma/operations/ecma-function-object.c +++ b/jerry-core/ecma/operations/ecma-function-object.c @@ -672,10 +672,9 @@ ecma_op_create_external_function_object (ecma_native_handler_t handler_cb) /**< { ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); - ecma_object_t *function_obj_p; - function_obj_p = ecma_create_object (prototype_obj_p, - sizeof (ecma_extended_object_t), - ECMA_OBJECT_TYPE_NATIVE_FUNCTION); + ecma_object_t *function_obj_p = ecma_create_object (prototype_obj_p, + sizeof (ecma_native_function_t), + ECMA_OBJECT_TYPE_NATIVE_FUNCTION); /* * [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_NATIVE_FUNCTION type. @@ -683,8 +682,12 @@ ecma_op_create_external_function_object (ecma_native_handler_t handler_cb) /**< * See also: ecma_object_get_class_name */ - ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) function_obj_p; - ext_func_obj_p->u.external_handler_cb = handler_cb; + ecma_native_function_t *native_function_p = (ecma_native_function_t *) function_obj_p; +#if ENABLED (JERRY_BUILTIN_REALMS) + ECMA_SET_INTERNAL_VALUE_POINTER (native_function_p->realm_value, + ecma_builtin_get_global ()); +#endif /* ENABLED (JERRY_BUILTIN_REALMS) */ + native_function_p->native_handler_cb = handler_cb; return function_obj_p; } /* ecma_op_create_external_function_object */ @@ -782,6 +785,39 @@ ecma_op_function_get_realm (const ecma_compiled_code_t *bytecode_header_p) /**< #endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */ } /* ecma_op_function_get_realm */ +/** + * Get realm from a function + * + * Note: + * Does not increase the reference counter. + * + * @return realm (global) object + */ +ecma_global_object_t * +ecma_op_function_get_function_realm (ecma_object_t *func_obj_p) /**< function object */ +{ + if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION) + { + ecma_extended_object_t *ext_function_obj_p = (ecma_extended_object_t *) func_obj_p; + const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_function_obj_p); + ecma_value_t realm_value = ecma_op_function_get_realm (bytecode_data_p); + return (ecma_global_object_t *) ecma_get_object_from_value (realm_value); + } + + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_NATIVE_FUNCTION); + + if (ecma_get_object_is_builtin (func_obj_p)) + { + ecma_extended_object_t *ext_function_obj_p = (ecma_extended_object_t *) func_obj_p; + return ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, + ext_function_obj_p->u.built_in.realm_value); + } + + ecma_native_function_t *native_function_p = (ecma_native_function_t *) func_obj_p; + return ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, + native_function_p->realm_value); +} /* ecma_op_function_get_function_realm */ + #endif /* ENABLED (JERRY_BUILTIN_REALMS) */ /** @@ -986,7 +1022,11 @@ ecma_op_get_prototype_from_constructor (ecma_object_t *ctor_obj_p, /**< construc } #endif /* ENABLED (JERRY_BUILTIN_PROXY) */ +#if ENABLED (JERRY_BUILTIN_REALMS) + proto_obj_p = ecma_builtin_get_from_realm (ecma_op_function_get_function_realm (ctor_obj_p), default_proto_id); +#else /* !ENABLED (JERRY_BUILTIN_REALMS) */ proto_obj_p = ecma_builtin_get (default_proto_id); +#endif /* ENABLED (JERRY_BUILTIN_REALMS) */ ecma_ref_object (proto_obj_p); } else @@ -1171,14 +1211,15 @@ ecma_op_function_call_native (ecma_object_t *func_obj_p, /**< Function object */ { JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_NATIVE_FUNCTION); - ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) func_obj_p; if (ecma_get_object_is_builtin (func_obj_p)) { #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); + + ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) func_obj_p; + JERRY_CONTEXT (global_object_p) = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, + ext_func_obj_p->u.built_in.realm_value); #endif /* ENABLED (JERRY_BUILTIN_REALMS) */ ecma_value_t ret_value = ecma_builtin_dispatch_call (func_obj_p, @@ -1192,11 +1233,23 @@ ecma_op_function_call_native (ecma_object_t *func_obj_p, /**< Function object */ return ret_value; } - JERRY_ASSERT (ext_func_obj_p->u.external_handler_cb != NULL); - ecma_value_t ret_value = ext_func_obj_p->u.external_handler_cb (ecma_make_object_value (func_obj_p), - this_arg_value, - arguments_list_p, - arguments_list_len); + ecma_native_function_t *native_function_p = (ecma_native_function_t *) func_obj_p; + +#if ENABLED (JERRY_BUILTIN_REALMS) + ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p); + JERRY_CONTEXT (global_object_p) = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, + native_function_p->realm_value); +#endif /* ENABLED (JERRY_BUILTIN_REALMS) */ + + JERRY_ASSERT (native_function_p->native_handler_cb != NULL); + ecma_value_t ret_value = native_function_p->native_handler_cb (ecma_make_object_value (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) */ + if (JERRY_UNLIKELY (ecma_is_value_error_reference (ret_value))) { ecma_raise_error_from_error_reference (ret_value); @@ -1573,6 +1626,26 @@ ecma_op_lazy_instantiate_prototype_object (ecma_object_t *object_p) /**< the fun JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION || ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_NATIVE_FUNCTION); +#if ENABLED (JERRY_BUILTIN_REALMS) + ecma_global_object_t *global_object_p; + + if (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION) + { + const ecma_compiled_code_t *bytecode_data_p; + bytecode_data_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) object_p); + + ecma_value_t realm_value = ecma_op_function_get_realm (bytecode_data_p); + global_object_p = (ecma_global_object_t *) ecma_get_object_from_value (realm_value); + } + else + { + ecma_native_function_t *native_function_p = (ecma_native_function_t *) object_p; + + global_object_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, + native_function_p->realm_value); + } +#endif /* ENABLED (JERRY_BUILTIN_REALMS) */ + /* ECMA-262 v5, 13.2, 16-18 */ ecma_object_t *proto_object_p = NULL; @@ -1590,17 +1663,29 @@ ecma_op_lazy_instantiate_prototype_object (ecma_object_t *object_p) /**< the fun if (CBC_FUNCTION_GET_TYPE (byte_code_p->status_flags) == CBC_FUNCTION_GENERATOR) { - proto_object_p = ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_GENERATOR_PROTOTYPE), - 0, - ECMA_OBJECT_TYPE_GENERAL); + ecma_object_t *prototype_p; + +#if ENABLED (JERRY_BUILTIN_REALMS) + prototype_p = ecma_builtin_get_from_realm (global_object_p, ECMA_BUILTIN_ID_GENERATOR_PROTOTYPE); +#else /* !ENABLED (JERRY_BUILTIN_REALMS) */ + prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_GENERATOR_PROTOTYPE); +#endif /* ENABLED (JERRY_BUILTIN_REALMS) */ + + proto_object_p = ecma_create_object (prototype_p, 0, ECMA_OBJECT_TYPE_GENERAL); init_constructor = false; } if (CBC_FUNCTION_GET_TYPE (byte_code_p->status_flags) == CBC_FUNCTION_ASYNC_GENERATOR) { - proto_object_p = ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_ASYNC_GENERATOR_PROTOTYPE), - 0, - ECMA_OBJECT_TYPE_GENERAL); + ecma_object_t *prototype_p; + +#if ENABLED (JERRY_BUILTIN_REALMS) + prototype_p = ecma_builtin_get_from_realm (global_object_p, ECMA_BUILTIN_ID_ASYNC_GENERATOR_PROTOTYPE); +#else /* !ENABLED (JERRY_BUILTIN_REALMS) */ + prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_ASYNC_GENERATOR_PROTOTYPE); +#endif /* ENABLED (JERRY_BUILTIN_REALMS) */ + + proto_object_p = ecma_create_object (prototype_p, 0, ECMA_OBJECT_TYPE_GENERAL); init_constructor = false; } } @@ -1610,7 +1695,15 @@ ecma_op_lazy_instantiate_prototype_object (ecma_object_t *object_p) /**< the fun if (proto_object_p == NULL) #endif /* ENABLED (JERRY_ESNEXT) */ { - proto_object_p = ecma_op_create_object_object_noarg (); + ecma_object_t *prototype_p; + +#if ENABLED (JERRY_BUILTIN_REALMS) + prototype_p = ecma_builtin_get_from_realm (global_object_p, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); +#else /* !ENABLED (JERRY_BUILTIN_REALMS) */ + prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); +#endif /* ENABLED (JERRY_BUILTIN_REALMS) */ + + proto_object_p = ecma_op_create_object_object_noarg_and_set_prototype (prototype_p); } /* 17. */ diff --git a/jerry-core/ecma/operations/ecma-function-object.h b/jerry-core/ecma/operations/ecma-function-object.h index 5223bd627..f1de6a25f 100644 --- a/jerry-core/ecma/operations/ecma-function-object.h +++ b/jerry-core/ecma/operations/ecma-function-object.h @@ -59,6 +59,9 @@ 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); + +ecma_global_object_t * +ecma_op_function_get_function_realm (ecma_object_t *func_obj_p); #endif /* ENABLED (JERRY_BUILTIN_REALMS) */ ecma_value_t diff --git a/jerry-core/ecma/operations/ecma-objects.c b/jerry-core/ecma/operations/ecma-objects.c index 78220af7b..327776915 100644 --- a/jerry-core/ecma/operations/ecma-objects.c +++ b/jerry-core/ecma/operations/ecma-objects.c @@ -882,6 +882,29 @@ ecma_op_object_get_by_magic_id (ecma_object_t *object_p, /**< the object */ } /* ecma_op_object_get_by_magic_id */ #if ENABLED (JERRY_ESNEXT) + +/** + * Descriptor string for each global symbol + */ +static const uint16_t ecma_global_symbol_descriptions[] = +{ + LIT_MAGIC_STRING_ASYNC_ITERATOR, + LIT_MAGIC_STRING_HAS_INSTANCE, + LIT_MAGIC_STRING_IS_CONCAT_SPREADABLE, + LIT_MAGIC_STRING_ITERATOR, + LIT_MAGIC_STRING_MATCH, + LIT_MAGIC_STRING_REPLACE, + LIT_MAGIC_STRING_SEARCH, + LIT_MAGIC_STRING_SPECIES, + LIT_MAGIC_STRING_SPLIT, + LIT_MAGIC_STRING_TO_PRIMITIVE, + LIT_MAGIC_STRING_TO_STRING_TAG, + LIT_MAGIC_STRING_UNSCOPABLES +}; + +JERRY_STATIC_ASSERT (sizeof (ecma_global_symbol_descriptions) / sizeof (uint16_t) == ECMA_BUILTIN_GLOBAL_SYMBOL_COUNT, + ecma_global_symbol_descriptions_must_have_global_symbol_count_elements); + /** * [[Get]] a well-known symbol by the given property id * @@ -890,11 +913,30 @@ ecma_op_object_get_by_magic_id (ecma_object_t *object_p, /**< the object */ ecma_string_t * ecma_op_get_global_symbol (lit_magic_string_id_t property_id) /**< property symbol id */ { - ecma_value_t symbol_value = ecma_op_object_get_by_magic_id (ecma_builtin_get (ECMA_BUILTIN_ID_INTRINSIC_OBJECT), - property_id); - JERRY_ASSERT (ecma_is_value_symbol (symbol_value)); + JERRY_ASSERT (LIT_IS_GLOBAL_SYMBOL (property_id)); - return ecma_get_symbol_from_value (symbol_value); + uint32_t symbol_index = (uint32_t) property_id - (uint32_t) LIT_GLOBAL_SYMBOL__FIRST; + jmem_cpointer_t symbol_cp = JERRY_CONTEXT (global_symbols_cp)[symbol_index]; + + if (symbol_cp != JMEM_CP_NULL) + { + ecma_string_t *symbol_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, symbol_cp); + ecma_ref_ecma_string (symbol_p); + return symbol_p; + } + + ecma_string_t *symbol_dot_p = ecma_get_magic_string (LIT_MAGIC_STRING_SYMBOL_DOT_UL); + uint16_t description = ecma_global_symbol_descriptions[symbol_index]; + ecma_string_t *name_p = ecma_get_magic_string ((lit_magic_string_id_t) description); + ecma_string_t *descriptor_p = ecma_concat_ecma_strings (symbol_dot_p, name_p); + + ecma_string_t *symbol_p = ecma_new_symbol_from_descriptor_string (ecma_make_string_value (descriptor_p)); + symbol_p->u.hash = (uint16_t) ((property_id << ECMA_GLOBAL_SYMBOL_SHIFT) | ECMA_GLOBAL_SYMBOL_FLAG); + + ECMA_SET_NON_NULL_POINTER (JERRY_CONTEXT (global_symbols_cp)[symbol_index], symbol_p); + + ecma_ref_ecma_string (symbol_p); + return symbol_p; } /* ecma_op_get_global_symbol */ /** diff --git a/jerry-core/include/jerryscript-core.h b/jerry-core/include/jerryscript-core.h index 60d3f1c7a..b0955d947 100644 --- a/jerry-core/include/jerryscript-core.h +++ b/jerry-core/include/jerryscript-core.h @@ -691,10 +691,10 @@ jerry_promise_state_t jerry_get_promise_state (const jerry_value_t promise); */ typedef enum { + JERRY_SYMBOL_ASYNC_ITERATOR, /**< @@asyncIterator well-known symbol */ JERRY_SYMBOL_HAS_INSTANCE, /**< @@hasInstance well-known symbol */ JERRY_SYMBOL_IS_CONCAT_SPREADABLE, /**< @@isConcatSpreadable well-known symbol */ JERRY_SYMBOL_ITERATOR, /**< @@iterator well-known symbol */ - JERRY_SYMBOL_ASYNC_ITERATOR, /**< @@asyncIterator well-known symbol */ JERRY_SYMBOL_MATCH, /**< @@match well-known symbol */ JERRY_SYMBOL_REPLACE, /**< @@replace well-known symbol */ JERRY_SYMBOL_SEARCH, /**< @@search well-known symbol */ @@ -739,6 +739,7 @@ void jerry_set_vm_exec_stop_callback (jerry_vm_exec_stop_callback_t stop_cb, voi jerry_value_t jerry_get_backtrace (uint32_t max_depth); jerry_value_t jerry_get_resource_name (const jerry_value_t value); jerry_value_t jerry_get_new_target (void); +jerry_value_t jerry_set_realm (jerry_value_t realm_value); /** * Array buffer components. diff --git a/jerry-core/jcontext/jcontext.h b/jerry-core/jcontext/jcontext.h index 43f8d4f31..eebd5906d 100644 --- a/jerry-core/jcontext/jcontext.h +++ b/jerry-core/jcontext/jcontext.h @@ -145,6 +145,9 @@ 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) */ +#if ENABLED (JERRY_ESNEXT) + jmem_cpointer_t global_symbols_cp[ECMA_BUILTIN_GLOBAL_SYMBOL_COUNT]; /**< global symbols */ +#endif /* ENABLED (JERRY_ESNEXT) */ #if ENABLED (JERRY_MODULE_SYSTEM) ecma_module_t *ecma_modules_p; /**< list of referenced modules */ diff --git a/jerry-core/lit/lit-magic-strings.h b/jerry-core/lit/lit-magic-strings.h index 670263c8e..0bcf9df20 100644 --- a/jerry-core/lit/lit-magic-strings.h +++ b/jerry-core/lit/lit-magic-strings.h @@ -42,11 +42,11 @@ typedef enum LIT_INTERNAL_MAGIC_STRING_MAP_PROTOTYPE_ENTRIES, /**< Map.prototype entries and [@@iterator] routines */ LIT_INTERNAL_MAGIC_PROMISE_CAPABILITY, /**< PromiseCapability record */ /* List of well known symbols */ + LIT_GLOBAL_SYMBOL_ASYNC_ITERATOR, /**< @@asyncIterator well known symbol */ + LIT_GLOBAL_SYMBOL__FIRST = LIT_GLOBAL_SYMBOL_ASYNC_ITERATOR, /**< first global symbol */ LIT_GLOBAL_SYMBOL_HAS_INSTANCE, /**< @@hasInstance well known symbol */ - LIT_GLOBAL_SYMBOL__FISRT = LIT_GLOBAL_SYMBOL_HAS_INSTANCE, /**< first global symbol */ LIT_GLOBAL_SYMBOL_IS_CONCAT_SPREADABLE, /**< @@isConcatSpreadable well known symbol */ LIT_GLOBAL_SYMBOL_ITERATOR, /**< @@iterator well known symbol */ - LIT_GLOBAL_SYMBOL_ASYNC_ITERATOR, /**< @@asyncIterator well known symbol */ LIT_GLOBAL_SYMBOL_MATCH, /**< @@match well known symbol */ LIT_GLOBAL_SYMBOL_REPLACE, /**< @@replace well known symbol */ LIT_GLOBAL_SYMBOL_SEARCH, /**< @@search well known symbol */ @@ -73,7 +73,7 @@ typedef enum /** * Checks whether the given id corresponds to a global symbol */ -#define LIT_IS_GLOBAL_SYMBOL(id) ((id) >= LIT_GLOBAL_SYMBOL__FISRT && (id) <= LIT_GLOBAL_SYMBOL__LAST) +#define LIT_IS_GLOBAL_SYMBOL(id) ((id) >= LIT_GLOBAL_SYMBOL__FIRST && (id) <= LIT_GLOBAL_SYMBOL__LAST) /** * Identifiers of implementation-defined external magic string constants diff --git a/jerry-core/vm/opcodes.c b/jerry-core/vm/opcodes.c index 324d85195..1e6b5021b 100644 --- a/jerry-core/vm/opcodes.c +++ b/jerry-core/vm/opcodes.c @@ -1219,32 +1219,37 @@ ecma_value_t opfunc_create_implicit_class_constructor (uint8_t opcode) /**< current cbc opcode */ { /* 8. */ - ecma_object_t *func_obj_p = ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE), - sizeof (ecma_extended_object_t), - ECMA_OBJECT_TYPE_NATIVE_FUNCTION); + ecma_object_t *function_obj_p = ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE), + sizeof (ecma_native_function_t), + ECMA_OBJECT_TYPE_NATIVE_FUNCTION); - ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) func_obj_p; + ecma_native_function_t *native_function_p = (ecma_native_function_t *) function_obj_p; + +#if ENABLED (JERRY_BUILTIN_REALMS) + ECMA_SET_INTERNAL_VALUE_POINTER (native_function_p->realm_value, + ecma_builtin_get_global ()); +#endif /* ENABLED (JERRY_BUILTIN_REALMS) */ /* 10.a.i */ if (opcode == CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR_HERITAGE) { - ext_func_obj_p->u.external_handler_cb = ecma_op_implicit_constructor_handler_heritage_cb; + native_function_p->native_handler_cb = ecma_op_implicit_constructor_handler_heritage_cb; } /* 10.b.i */ else { - ext_func_obj_p->u.external_handler_cb = ecma_op_implicit_constructor_handler_cb; + native_function_p->native_handler_cb = ecma_op_implicit_constructor_handler_cb; } ecma_property_value_t *prop_value_p; - prop_value_p = ecma_create_named_data_property (func_obj_p, + prop_value_p = ecma_create_named_data_property (function_obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), ECMA_PROPERTY_FLAG_CONFIGURABLE, NULL); prop_value_p->value = ecma_make_uint32_value (0); - return ecma_make_object_value (func_obj_p); + return ecma_make_object_value (function_obj_p); } /* opfunc_create_implicit_class_constructor */ /** diff --git a/jerry-main/main-utils.c b/jerry-main/main-utils.c index 8b6767c35..b108f1806 100644 --- a/jerry-main/main-utils.c +++ b/jerry-main/main-utils.c @@ -148,17 +148,50 @@ test262_eval_script (const jerry_value_t func_obj_val, /**< function object */ return ret_value; } /* test262_eval_script */ +static jerry_value_t +create_test262 (jerry_value_t global_obj); + /** - * Init the $262 object + * $262.createRealm + * + * A function which creates a new realm object, and returns a newly created $262 object + * + * @return a new $262 object */ -static void -register_test262 (void) +static jerry_value_t +test262_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 */ + + jerry_value_t realm_object = jerry_create_realm (); + jerry_value_t previous_realm = jerry_set_realm (realm_object); + assert (!jerry_value_is_error (previous_realm)); + jerry_value_t test262_object = create_test262 (realm_object); + jerry_set_realm (previous_realm); + jerry_release_value (realm_object); + + return test262_object; +} /* test262_create_realm */ + +/** + * Create a new $262 object + * + * @return a new $262 object + */ +static jerry_value_t +create_test262 (jerry_value_t global_obj) /**< global object */ { - jerry_value_t global_obj = jerry_get_global_object (); jerry_value_t test262_object = jerry_create_object (); test262_register_function (test262_object, "detachArrayBuffer", test262_detach_array_buffer); test262_register_function (test262_object, "evalScript", test262_eval_script); + test262_register_function (test262_object, "createRealm", test262_create_realm); test262_register_function (test262_object, "gc", jerryx_handler_gc); jerry_value_t prop_name = jerry_create_string ((const jerry_char_t *) "global"); @@ -171,17 +204,16 @@ register_test262 (void) jerry_release_value (prop_name); assert (!jerry_value_is_error (result)); - - jerry_release_value (global_obj); - jerry_release_value (test262_object); jerry_release_value (result); -} /* register_test262 */ + + return test262_object; +} /* create_test262 */ /** * Inits the engine and the debugger */ void -main_init_engine (main_args_t *arguments_p) /** main arguments */ +main_init_engine (main_args_t *arguments_p) /**< main arguments */ { jerry_init (arguments_p->init_flags); @@ -211,7 +243,10 @@ main_init_engine (main_args_t *arguments_p) /** main arguments */ } if (arguments_p->option_flags & OPT_FLAG_TEST262_OBJECT) { - register_test262 (); + jerry_value_t global_obj = jerry_get_global_object (); + jerry_value_t test262_object = create_test262 (global_obj); + jerry_release_value (test262_object); + jerry_release_value (global_obj); } main_register_global_function ("assert", jerryx_handler_assert); main_register_global_function ("gc", jerryx_handler_gc); diff --git a/tests/jerry/es.next/realms4.js b/tests/jerry/es.next/realms4.js new file mode 100644 index 000000000..02734f51c --- /dev/null +++ b/tests/jerry/es.next/realms4.js @@ -0,0 +1,35 @@ +// 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() + +function compare(a, b) +{ + assert (a === b) + assert (typeof a === "symbol") + assert (typeof b === "symbol") +} + +compare(Symbol.asyncIterator, realm.Symbol.asyncIterator) +compare(Symbol.hasInstance, realm.Symbol.hasInstance) +compare(Symbol.isConcatSpreadable, realm.Symbol.isConcatSpreadable) +compare(Symbol.iterator, realm.Symbol.iterator) +compare(Symbol.match, realm.Symbol.match) +compare(Symbol.replace, realm.Symbol.replace) +compare(Symbol.search, realm.Symbol.search) +compare(Symbol.species, realm.Symbol.species) +compare(Symbol.split, realm.Symbol.split) +compare(Symbol.toPrimitive, realm.Symbol.toPrimitive) +compare(Symbol.toStringTag, realm.Symbol.toStringTag) +compare(Symbol.unscopables, realm.Symbol.unscopables) diff --git a/tests/test262-esnext-excludelist.xml b/tests/test262-esnext-excludelist.xml index 67187c072..e6bcc830b 100644 --- a/tests/test262-esnext-excludelist.xml +++ b/tests/test262-esnext-excludelist.xml @@ -7932,8 +7932,6 @@ - - @@ -8012,7 +8010,6 @@ - @@ -9532,26 +9529,8 @@ - - - - - - - - - - - - - - - - - - @@ -9663,34 +9642,14 @@ - - - - - - - - - - - - - - - - - - - - @@ -9699,46 +9658,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -9746,43 +9668,20 @@ - - - - - - - - - - - - - - - - - - - - - - - @@ -9793,9 +9692,7 @@ - - @@ -9805,8 +9702,6 @@ - - @@ -9822,10 +9717,6 @@ - - - - @@ -9833,8 +9724,6 @@ - -