Introduce new API function to obtain well-known symbols (#4163)
- jerry_get_well_known_symbol JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
This commit is contained in:
@@ -141,6 +141,25 @@ Container object types:
|
|||||||
|
|
||||||
*New in version 2.3*.
|
*New in version 2.3*.
|
||||||
|
|
||||||
|
## jerry_well_known_symbol_t
|
||||||
|
|
||||||
|
Well-known symbols:
|
||||||
|
|
||||||
|
- 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
|
||||||
|
- JERRY_SYMBOL_SPECIES - @@species well-known symbol
|
||||||
|
- JERRY_SYMBOL_SPLIT - @@split well-known symbol
|
||||||
|
- JERRY_SYMBOL_TO_PRIMITIVE - @@toPrimitive well-known symbol
|
||||||
|
- JERRY_SYMBOL_TO_STRING_TAG - @@toStringTag well-known symbol
|
||||||
|
- JERRY_SYMBOL_UNSCOPABLES - @@unscopables well-known symbol
|
||||||
|
|
||||||
|
*New in version [[NEXT_RELEASE]]*.
|
||||||
|
|
||||||
## jerry_regexp_flags_t
|
## jerry_regexp_flags_t
|
||||||
|
|
||||||
RegExp object optional flags:
|
RegExp object optional flags:
|
||||||
@@ -3917,6 +3936,66 @@ jerry_resolve_or_reject_promise (jerry_value_t promise,
|
|||||||
|
|
||||||
These APIs all depend on the es.next profile (or on build options).
|
These APIs all depend on the es.next profile (or on build options).
|
||||||
|
|
||||||
|
## jerry_get_well_known_symbol
|
||||||
|
|
||||||
|
**Summary**
|
||||||
|
|
||||||
|
Get the well-known symbol corresponding to the given [well-known symbol id](#jerry_well_known_symbol_t).
|
||||||
|
|
||||||
|
*Notes*:
|
||||||
|
- Returned value must be freed with [jerry_release_value](#jerry_release_value) when it
|
||||||
|
is no longer needed.
|
||||||
|
- This API depends on a build option (`JERRY_BUILTIN_SYMBOL`) and can be checked
|
||||||
|
in runtime with the `JERRY_FEATURE_SYMBOL` feature enum value,
|
||||||
|
see: [jerry_is_feature_enabled](#jerry_is_feature_enabled).
|
||||||
|
- The es.next profile enables this by default.
|
||||||
|
- If the symbol support is not enabled an undefined will be returned.
|
||||||
|
|
||||||
|
**Prototype**
|
||||||
|
|
||||||
|
```c
|
||||||
|
jerry_value_t
|
||||||
|
jerry_get_well_known_symbol (jerry_well_known_symbol_t symbol);
|
||||||
|
```
|
||||||
|
|
||||||
|
- `symbol` - [jerry_well_known_symbol_t](#jerry_well_known_symbol_t) enum value
|
||||||
|
- return value
|
||||||
|
- undefined value - if invalid well-known symbol was requested
|
||||||
|
- well-known symbol value, otherwise
|
||||||
|
|
||||||
|
*New in version [[NEXT_RELEASE]]*.
|
||||||
|
|
||||||
|
**Example**
|
||||||
|
|
||||||
|
[doctest]: # ()
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include "jerryscript.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{
|
||||||
|
jerry_init (JERRY_INIT_EMPTY);
|
||||||
|
|
||||||
|
jerry_value_t array_value = jerry_create_array (5);
|
||||||
|
jerry_value_t symbol_iterator = jerry_get_well_known_symbol (JERRY_SYMBOL_ITERATOR);
|
||||||
|
jerry_value_t array_iterator = jerry_get_property (array_value, symbol_iterator);
|
||||||
|
|
||||||
|
// usage of array_iterator
|
||||||
|
|
||||||
|
jerry_release_value (array_iterator);
|
||||||
|
jerry_release_value (symbol_iterator);
|
||||||
|
jerry_release_value (array_value);
|
||||||
|
|
||||||
|
jerry_cleanup ();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**See also**
|
||||||
|
|
||||||
|
- [jerry_well_known_symbol_t](#jerry_well_known_symbol_t)
|
||||||
|
|
||||||
## jerry_get_symbol_descriptive_string
|
## jerry_get_symbol_descriptive_string
|
||||||
|
|
||||||
**Summary**
|
**Summary**
|
||||||
|
|||||||
@@ -3766,6 +3766,36 @@ jerry_get_promise_state (const jerry_value_t promise) /**< promise object to get
|
|||||||
#endif /* ENABLED (JERRY_BUILTIN_PROMISE) */
|
#endif /* ENABLED (JERRY_BUILTIN_PROMISE) */
|
||||||
} /* jerry_get_promise_state */
|
} /* jerry_get_promise_state */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the well-knwon symbol represented by the given `symbol` enum value.
|
||||||
|
*
|
||||||
|
* Note:
|
||||||
|
* returned value must be freed with jerry_release_value, when it is no longer needed.
|
||||||
|
*
|
||||||
|
* @return undefined value - if invalid well-known symbol was requested
|
||||||
|
* well-known symbol value - otherwise
|
||||||
|
*/
|
||||||
|
jerry_value_t
|
||||||
|
jerry_get_well_known_symbol (jerry_well_known_symbol_t symbol) /**< jerry_well_known_symbol_t enum value */
|
||||||
|
{
|
||||||
|
jerry_assert_api_available ();
|
||||||
|
|
||||||
|
#if ENABLED (JERRY_ESNEXT)
|
||||||
|
lit_magic_string_id_t id = (lit_magic_string_id_t) (LIT_GLOBAL_SYMBOL__FISRT + symbol);
|
||||||
|
|
||||||
|
if (!LIT_IS_GLOBAL_SYMBOL (id))
|
||||||
|
{
|
||||||
|
return ECMA_VALUE_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ecma_make_symbol_value (ecma_op_get_global_symbol (id));
|
||||||
|
#else /* !ENABLED (JERRY_ESNEXT) */
|
||||||
|
JERRY_UNUSED (symbol);
|
||||||
|
|
||||||
|
return ECMA_VALUE_UNDEFINED;
|
||||||
|
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||||
|
} /** jerry_get_well_known_symbol */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call the SymbolDescriptiveString ecma builtin operation on the symbol value.
|
* Call the SymbolDescriptiveString ecma builtin operation on the symbol value.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -650,6 +650,27 @@ jerry_promise_state_t jerry_get_promise_state (const jerry_value_t promise);
|
|||||||
/**
|
/**
|
||||||
* Symbol functions.
|
* Symbol functions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of well-known symbols.
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
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 */
|
||||||
|
JERRY_SYMBOL_SPECIES, /**< @@species well-known symbol */
|
||||||
|
JERRY_SYMBOL_SPLIT, /**< @@split well-known symbol */
|
||||||
|
JERRY_SYMBOL_TO_PRIMITIVE, /**< @@toPrimitive well-known symbol */
|
||||||
|
JERRY_SYMBOL_TO_STRING_TAG, /**< @@toStringTag well-known symbol */
|
||||||
|
JERRY_SYMBOL_UNSCOPABLES, /**< @@unscopables well-known symbol */
|
||||||
|
} jerry_well_known_symbol_t;
|
||||||
|
|
||||||
|
jerry_value_t jerry_get_well_known_symbol (jerry_well_known_symbol_t symbol);
|
||||||
jerry_value_t jerry_get_symbol_descriptive_string (const jerry_value_t symbol);
|
jerry_value_t jerry_get_symbol_descriptive_string (const jerry_value_t symbol);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ typedef enum
|
|||||||
LIT_INTERNAL_MAGIC_PROMISE_CAPABILITY, /**< PromiseCapability record */
|
LIT_INTERNAL_MAGIC_PROMISE_CAPABILITY, /**< PromiseCapability record */
|
||||||
/* List of well known symbols */
|
/* List of well known symbols */
|
||||||
LIT_GLOBAL_SYMBOL_HAS_INSTANCE, /**< @@hasInstance well known 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_IS_CONCAT_SPREADABLE, /**< @@isConcatSpreadable well known symbol */
|
||||||
LIT_GLOBAL_SYMBOL_ITERATOR, /**< @@iterator well known symbol */
|
LIT_GLOBAL_SYMBOL_ITERATOR, /**< @@iterator well known symbol */
|
||||||
LIT_GLOBAL_SYMBOL_ASYNC_ITERATOR, /**< @@asyncIterator well known symbol */
|
LIT_GLOBAL_SYMBOL_ASYNC_ITERATOR, /**< @@asyncIterator well known symbol */
|
||||||
@@ -59,6 +60,7 @@ typedef enum
|
|||||||
LIT_GLOBAL_SYMBOL_TO_PRIMITIVE, /**< @@toPrimitive well known symbol */
|
LIT_GLOBAL_SYMBOL_TO_PRIMITIVE, /**< @@toPrimitive well known symbol */
|
||||||
LIT_GLOBAL_SYMBOL_TO_STRING_TAG, /**< @@toStringTag well known symbol */
|
LIT_GLOBAL_SYMBOL_TO_STRING_TAG, /**< @@toStringTag well known symbol */
|
||||||
LIT_GLOBAL_SYMBOL_UNSCOPABLES, /**< @@unscopables well known symbol */
|
LIT_GLOBAL_SYMBOL_UNSCOPABLES, /**< @@unscopables well known symbol */
|
||||||
|
LIT_GLOBAL_SYMBOL__LAST = LIT_GLOBAL_SYMBOL_UNSCOPABLES, /**< last global symbol */
|
||||||
LIT_GC_MARK_REQUIRED_MAGIC_STRING__COUNT, /**< number of internal magic strings which will be used as
|
LIT_GC_MARK_REQUIRED_MAGIC_STRING__COUNT, /**< number of internal magic strings which will be used as
|
||||||
* property names, and their values need to be marked during gc. */
|
* property names, and their values need to be marked during gc. */
|
||||||
LIT_INTERNAL_MAGIC_STRING_DELETED = LIT_GC_MARK_REQUIRED_MAGIC_STRING__COUNT, /**< special value for
|
LIT_INTERNAL_MAGIC_STRING_DELETED = LIT_GC_MARK_REQUIRED_MAGIC_STRING__COUNT, /**< special value for
|
||||||
@@ -75,7 +77,7 @@ typedef enum
|
|||||||
/**
|
/**
|
||||||
* Checks whether the given id corresponds to a global symbol
|
* Checks whether the given id corresponds to a global symbol
|
||||||
*/
|
*/
|
||||||
#define LIT_IS_GLOBAL_SYMBOL(id) ((id) >= LIT_GLOBAL_SYMBOL_HAS_INSTANCE && (id) <= LIT_GLOBAL_SYMBOL_UNSCOPABLES)
|
#define LIT_IS_GLOBAL_SYMBOL(id) ((id) >= LIT_GLOBAL_SYMBOL__FISRT && (id) <= LIT_GLOBAL_SYMBOL__LAST)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Identifiers of implementation-defined external magic string constants
|
* Identifiers of implementation-defined external magic string constants
|
||||||
|
|||||||
@@ -191,6 +191,132 @@ main (void)
|
|||||||
jerry_release_value (error_obj);
|
jerry_release_value (error_obj);
|
||||||
jerry_release_value (null_value);
|
jerry_release_value (null_value);
|
||||||
|
|
||||||
|
const jerry_char_t obj_src[] = ""
|
||||||
|
"({"
|
||||||
|
" [Symbol.hasInstance]: 1,"
|
||||||
|
" [Symbol.isConcatSpreadable]: 2,"
|
||||||
|
" [Symbol.iterator]: 3,"
|
||||||
|
" [Symbol.asyncIterator]: 4,"
|
||||||
|
" [Symbol.match]: 5,"
|
||||||
|
" [Symbol.replace]: 6,"
|
||||||
|
" [Symbol.search]: 7,"
|
||||||
|
" [Symbol.species]: 8,"
|
||||||
|
" [Symbol.split]: 9,"
|
||||||
|
" [Symbol.toPrimitive]: 10,"
|
||||||
|
" [Symbol.toStringTag]: 11,"
|
||||||
|
" [Symbol.unscopables]: 12,"
|
||||||
|
"})";
|
||||||
|
|
||||||
|
const char *symbols[] =
|
||||||
|
{
|
||||||
|
"hasInstance",
|
||||||
|
"isConcatSpreadable",
|
||||||
|
"iterator",
|
||||||
|
"asyncIterator",
|
||||||
|
"match",
|
||||||
|
"replace",
|
||||||
|
"search",
|
||||||
|
"species",
|
||||||
|
"split",
|
||||||
|
"toPrimitive",
|
||||||
|
"toStringTag",
|
||||||
|
"unscopables",
|
||||||
|
};
|
||||||
|
|
||||||
|
jerry_value_t obj = jerry_eval (obj_src, sizeof (obj_src) - 1, JERRY_PARSE_NO_OPTS);
|
||||||
|
TEST_ASSERT (jerry_value_is_object (obj));
|
||||||
|
|
||||||
|
jerry_value_t global_obj = jerry_get_global_object ();
|
||||||
|
jerry_value_t symbol_str = jerry_create_string ((const jerry_char_t *) "Symbol");
|
||||||
|
jerry_value_t builtin_symbol = jerry_get_property (global_obj, symbol_str);
|
||||||
|
TEST_ASSERT (jerry_value_is_object (builtin_symbol));
|
||||||
|
|
||||||
|
double expected = 1.0;
|
||||||
|
uint32_t prop_index = 0;
|
||||||
|
|
||||||
|
for (jerry_well_known_symbol_t id = JERRY_SYMBOL_HAS_INSTANCE;
|
||||||
|
id <= JERRY_SYMBOL_UNSCOPABLES;
|
||||||
|
id++, expected++, prop_index++)
|
||||||
|
{
|
||||||
|
jerry_value_t well_known_symbol = jerry_get_well_known_symbol (id);
|
||||||
|
|
||||||
|
jerry_value_t prop_str = jerry_create_string ((const jerry_char_t *) symbols[prop_index]);
|
||||||
|
jerry_value_t current_global_symbol = jerry_get_property (builtin_symbol, prop_str);
|
||||||
|
jerry_release_value (prop_str);
|
||||||
|
|
||||||
|
jerry_value_t relation = jerry_binary_operation (JERRY_BIN_OP_STRICT_EQUAL,
|
||||||
|
well_known_symbol,
|
||||||
|
current_global_symbol);
|
||||||
|
|
||||||
|
TEST_ASSERT (jerry_value_is_boolean (relation)
|
||||||
|
&& jerry_get_boolean_value (relation));
|
||||||
|
|
||||||
|
jerry_release_value (relation);
|
||||||
|
|
||||||
|
jerry_value_t prop_result_wn = jerry_get_property (obj, well_known_symbol);
|
||||||
|
jerry_value_t prop_result_global = jerry_get_property (obj, current_global_symbol);
|
||||||
|
|
||||||
|
TEST_ASSERT (jerry_value_is_number (prop_result_wn));
|
||||||
|
double number_wn = jerry_get_number_value (prop_result_wn);
|
||||||
|
TEST_ASSERT (number_wn == expected);
|
||||||
|
|
||||||
|
TEST_ASSERT (jerry_value_is_number (prop_result_global));
|
||||||
|
double number_global = jerry_get_number_value (prop_result_global);
|
||||||
|
TEST_ASSERT (number_global == expected);
|
||||||
|
|
||||||
|
jerry_release_value (prop_result_global);
|
||||||
|
jerry_release_value (prop_result_wn);
|
||||||
|
jerry_release_value (current_global_symbol);
|
||||||
|
jerry_release_value (well_known_symbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
jerry_release_value (builtin_symbol);
|
||||||
|
|
||||||
|
/* Deletion of the 'Symbol' builtin makes the well-known symbols unaccessible from JS context
|
||||||
|
but the symbols still can be obtained via 'jerry_get_well_known_symbol' */
|
||||||
|
const jerry_char_t deleter_src[] = "delete Symbol";
|
||||||
|
|
||||||
|
jerry_value_t deleter = jerry_eval (deleter_src, sizeof (deleter_src) - 1, JERRY_PARSE_NO_OPTS);
|
||||||
|
TEST_ASSERT (jerry_value_is_boolean (deleter)
|
||||||
|
&& jerry_get_boolean_value (deleter));
|
||||||
|
jerry_release_value (deleter);
|
||||||
|
|
||||||
|
builtin_symbol = jerry_get_property (global_obj, symbol_str);
|
||||||
|
TEST_ASSERT (jerry_value_is_undefined (builtin_symbol));
|
||||||
|
jerry_release_value (builtin_symbol);
|
||||||
|
|
||||||
|
expected = 1.0;
|
||||||
|
prop_index = 0;
|
||||||
|
|
||||||
|
for (jerry_well_known_symbol_t id = JERRY_SYMBOL_HAS_INSTANCE;
|
||||||
|
id <= JERRY_SYMBOL_UNSCOPABLES;
|
||||||
|
id++, expected++, prop_index++)
|
||||||
|
{
|
||||||
|
jerry_value_t well_known_symbol = jerry_get_well_known_symbol (id);
|
||||||
|
jerry_value_t prop_result_wn = jerry_get_property (obj, well_known_symbol);
|
||||||
|
|
||||||
|
TEST_ASSERT (jerry_value_is_number (prop_result_wn));
|
||||||
|
double number_wn = jerry_get_number_value (prop_result_wn);
|
||||||
|
TEST_ASSERT (number_wn == expected);
|
||||||
|
|
||||||
|
jerry_release_value (prop_result_wn);
|
||||||
|
jerry_release_value (well_known_symbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
jerry_well_known_symbol_t invalid_symbol = (jerry_well_known_symbol_t) (JERRY_SYMBOL_UNSCOPABLES + 1);
|
||||||
|
jerry_value_t invalid_well_known_symbol = jerry_get_well_known_symbol (invalid_symbol);
|
||||||
|
TEST_ASSERT (jerry_value_is_undefined (invalid_well_known_symbol));
|
||||||
|
jerry_release_value (invalid_well_known_symbol);
|
||||||
|
|
||||||
|
invalid_symbol = (jerry_well_known_symbol_t) (JERRY_SYMBOL_HAS_INSTANCE - 1);
|
||||||
|
invalid_well_known_symbol = jerry_get_well_known_symbol (invalid_symbol);
|
||||||
|
TEST_ASSERT (jerry_value_is_undefined (invalid_well_known_symbol));
|
||||||
|
jerry_release_value (invalid_well_known_symbol);
|
||||||
|
|
||||||
|
jerry_release_value (symbol_str);
|
||||||
|
jerry_release_value (global_obj);
|
||||||
|
jerry_release_value (obj);
|
||||||
|
|
||||||
jerry_cleanup ();
|
jerry_cleanup ();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user