From e2be8f4c7914b3763803648dded1039c98b073df Mon Sep 17 00:00:00 2001 From: Zoltan Herczeg Date: Wed, 16 Dec 2020 13:21:20 +0100 Subject: [PATCH] Get the 'this' binding of a realm value (#4365) JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com --- docs/02.API-REFERENCE.md | 56 ++++++++++++++++++++++++++- jerry-core/api/jerry.c | 41 +++++++++++++++++++- jerry-core/include/jerryscript-core.h | 9 ++++- tests/unit-core/test-realm.c | 42 +++++++++++++++++--- 4 files changed, 139 insertions(+), 9 deletions(-) diff --git a/docs/02.API-REFERENCE.md b/docs/02.API-REFERENCE.md index 6620766bb..d26f27c8c 100644 --- a/docs/02.API-REFERENCE.md +++ b/docs/02.API-REFERENCE.md @@ -9125,6 +9125,10 @@ main (int argc, char** argv) - [jerry_construct_object](#jerry_construct_object) +# Functions for realm objects + +These APIs all depend on build option (`JERRY_BUILTIN_REALMS`). + ## jerry_set_realm **Summary** @@ -9146,6 +9150,7 @@ which was active when the code was parsed or loaded regardless of the current re - 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). +- The es.next profile enables this by default. **Prototype** @@ -9178,6 +9183,53 @@ jerry_set_realm (jerry_value_t realm_value); - [jerry_create_realm](#jerry_create_realm) +## jerry_realm_get_this + +**Summary** + +Gets the 'this' binding of a realm. The 'this' binding is always an object. +By default the 'this' binding is the same as the realm object and can be +changed by [jerry_realm_set_this](#jerry_realm_set_this). + +*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). +- The es.next profile enables this by default. + +**Prototype** + +```c +jerry_value_t +jerry_realm_get_this (jerry_value_t realm_value) +``` +- `realm_value` - realm value +- return + - type error - if realm_value is not a realm + - 'this' binding object - otherwise + +*New in version [[NEXT_RELEASE]]*. + +**Example** + +```c +{ + jerry_value_t realm_value = jerry_create_realm (); + + jerry_value_t this_value = jerry_realm_get_this (realm_value); + + ... // usage of the this_value + + jerry_release_value (this_value); + jerry_release_value (realm_value); +} +``` + +**See also** + +- [jerry_create_realm](#jerry_create_realm) +- [jerry_realm_set_this](#jerry_realm_set_this) + ## jerry_realm_set_this **Summary** @@ -9189,6 +9241,7 @@ any script on the realm. Otherwise the operation is undefined. - 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). +- The es.next profile enables this by default. **Prototype** @@ -9199,7 +9252,7 @@ jerry_realm_set_this (jerry_value_t realm_value, jerry_value_t this_value) - `realm_value` - realm value - `this_value` - new this value - return - - exception - if any error is happened + - type error - if realm_value is not a realm or this_value is not object - true - otherwise *New in version [[NEXT_RELEASE]]*. @@ -9225,6 +9278,7 @@ jerry_realm_set_this (jerry_value_t realm_value, jerry_value_t this_value) - [jerry_create_realm](#jerry_create_realm) - [jerry_set_realm](#jerry_set_realm) +- [jerry_realm_get_this](#jerry_realm_get_this) # ArrayBuffer and TypedArray functions diff --git a/jerry-core/api/jerry.c b/jerry-core/api/jerry.c index 6aca8cae6..1b56eff54 100644 --- a/jerry-core/api/jerry.c +++ b/jerry-core/api/jerry.c @@ -4608,13 +4608,52 @@ jerry_set_realm (jerry_value_t realm_value) /**< jerry api value */ #endif /* ENABLED (JERRY_BUILTIN_REALMS) */ } /* jerry_set_realm */ +/** + * Gets the 'this' binding of a realm + * + * @return type error - if realm_value is not a realm + * this value - otherwise + */ +jerry_value_t +jerry_realm_get_this (jerry_value_t realm_value) /**< realm 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 *global_object_p = (ecma_global_object_t *) object_p; + + ecma_ref_object (ecma_get_object_from_value (global_object_p->this_binding)); + return global_object_p->this_binding; + } + } + +#else /* !ENABLED (JERRY_BUILTIN_REALMS) */ + ecma_object_t *global_object_p = ecma_builtin_get_global (); + + if (realm_value == ecma_make_object_value (global_object_p)) + { + ecma_ref_object (global_object_p); + return realm_value; + } +#endif /* ENABLED (JERRY_BUILTIN_REALMS) */ + + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG ("Passed argument is not a realm"))); +} /* jerry_realm_get_this */ + /** * Sets the 'this' binding of a realm * * This function must be called before executing any script on the realm. * Otherwise the operation is undefined. * - * @return thrown error - if any error is happened + * @return type error - if realm_value is not a realm or this_value is not object * true - otherwise */ jerry_value_t diff --git a/jerry-core/include/jerryscript-core.h b/jerry-core/include/jerryscript-core.h index 641a186f4..780f41532 100644 --- a/jerry-core/include/jerryscript-core.h +++ b/jerry-core/include/jerryscript-core.h @@ -710,6 +710,13 @@ jerry_value_t jerry_get_well_known_symbol (jerry_well_known_symbol_t symbol); jerry_value_t jerry_get_symbol_description (const jerry_value_t symbol); jerry_value_t jerry_get_symbol_descriptive_string (const jerry_value_t symbol); +/** + * Realm functions. + */ +jerry_value_t jerry_set_realm (jerry_value_t realm_value); +jerry_value_t jerry_realm_get_this (jerry_value_t realm_value); +jerry_value_t jerry_realm_set_this (jerry_value_t realm_value, jerry_value_t this_value); + /** * BigInt functions. */ @@ -740,8 +747,6 @@ 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); -jerry_value_t jerry_realm_set_this (jerry_value_t realm_value, jerry_value_t this_value); /** * Array buffer components. diff --git a/tests/unit-core/test-realm.c b/tests/unit-core/test-realm.c index 5e1030b1c..43289b8ed 100644 --- a/tests/unit-core/test-realm.c +++ b/tests/unit-core/test-realm.c @@ -61,6 +61,15 @@ eval_and_get_number (char *script_p) /**< script source */ return result; } /* eval_and_get_number */ +static void +check_type_error (jerry_value_t result_value) /**< result value */ +{ + TEST_ASSERT (jerry_value_is_error (result_value)); + result_value = jerry_get_value_from_error (result_value, true); + TEST_ASSERT (jerry_get_error_type (result_value) == JERRY_ERROR_TYPE); + jerry_release_value (result_value); +} /* check_type_error */ + /** * Unit test's main function. */ @@ -71,13 +80,21 @@ main (void) jerry_init (JERRY_INIT_EMPTY); + jerry_value_t global_value = jerry_get_global_object (); + jerry_value_t result_value = jerry_realm_get_this (global_value); + TEST_ASSERT (global_value == result_value); + jerry_release_value (global_value); + + jerry_value_t number_value = jerry_create_number (3); + check_type_error (jerry_realm_get_this (number_value)); + jerry_release_value (number_value); + if (!jerry_is_feature_enabled (JERRY_FEATURE_REALM)) { printf ("Skipping test, Realms not enabled\n"); return 0; } - jerry_value_t global_value = jerry_get_global_object (); jerry_value_t realm_value = jerry_create_realm (); create_number_property (global_value, "a", 3.5); @@ -87,7 +104,7 @@ main (void) TEST_ASSERT (eval_and_get_number ("a") == 3.5); - jerry_value_t result_value = jerry_set_realm (realm_value); + result_value = jerry_set_realm (realm_value); TEST_ASSERT (result_value == global_value); TEST_ASSERT (eval_and_get_number ("a") == -1.25); @@ -103,21 +120,32 @@ main (void) TEST_ASSERT (result_value == realm_value); jerry_value_t object_value = jerry_create_object (); - result_value = jerry_set_realm (object_value); - TEST_ASSERT (jerry_value_is_error (result_value)); - jerry_release_value (result_value); + check_type_error (jerry_set_realm (object_value)); jerry_release_value (object_value); + number_value = jerry_create_number (5); + check_type_error (jerry_set_realm (number_value)); + jerry_release_value (number_value); + jerry_release_value (global_value); jerry_release_value (realm_value); realm_value = jerry_create_realm (); + result_value = jerry_realm_get_this (realm_value); + TEST_ASSERT (result_value == realm_value); + jerry_release_value (result_value); + result_value = jerry_set_realm (realm_value); TEST_ASSERT (!jerry_value_is_error (result_value)); object_value = jerry_create_object (); jerry_set_realm (result_value); + number_value = jerry_create_number (7); + check_type_error (jerry_realm_set_this (realm_value, number_value)); + check_type_error (jerry_realm_set_this (number_value, object_value)); + jerry_release_value (number_value); + result_value = jerry_realm_set_this (realm_value, object_value); TEST_ASSERT (jerry_value_is_boolean (result_value) && jerry_get_boolean_value (result_value)); jerry_release_value (result_value); @@ -132,6 +160,10 @@ main (void) TEST_ASSERT (get_number_property (object_value, "z") == -5.5); + result_value = jerry_realm_get_this (realm_value); + TEST_ASSERT (result_value == object_value); + jerry_release_value (result_value); + jerry_release_value (object_value); jerry_release_value (realm_value);