From 7e3d688e5bfe245b0332302ac8f51f44aa3e366d Mon Sep 17 00:00:00 2001 From: Robert Fancsik Date: Wed, 16 Jan 2019 10:09:23 +0100 Subject: [PATCH] Implement the Symbol builtin object (#2601) This patch contains the base functionalities that the new builtin object requires. Currently unavailable: - print (Symbol('foo')) - this features requires the refactor of the print handler function - Several global symbol based builtin routines (follow up patch) JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu --- jerry-core/config.h | 1 + jerry-core/ecma/base/ecma-gc.c | 3 + jerry-core/ecma/base/ecma-globals.h | 27 ++ jerry-core/ecma/base/ecma-helpers-string.c | 50 ++++ jerry-core/ecma/base/ecma-helpers-value.c | 124 ++++++++- jerry-core/ecma/base/ecma-helpers.h | 28 ++ jerry-core/ecma/base/ecma-literal-storage.c | 3 + .../builtin-objects/ecma-builtin-global.inc.h | 7 + .../ecma-builtin-helpers-macro-defines.inc.h | 10 + .../ecma-builtin-helpers-macro-undefs.inc.h | 4 + .../builtin-objects/ecma-builtin-helpers.c | 6 +- .../builtin-objects/ecma-builtin-helpers.h | 2 +- ...a-builtin-internal-routines-template.inc.h | 32 +++ .../builtin-objects/ecma-builtin-object.c | 109 +++++--- .../builtin-objects/ecma-builtin-object.inc.h | 3 + .../ecma-builtin-symbol-prototype.c | 98 +++++++ .../ecma-builtin-symbol-prototype.inc.h | 49 ++++ .../builtin-objects/ecma-builtin-symbol.c | 243 ++++++++++++++++++ .../builtin-objects/ecma-builtin-symbol.inc.h | 91 +++++++ .../builtin-objects/ecma-builtins-internal.h | 3 + .../ecma/builtin-objects/ecma-builtins.c | 29 +++ .../ecma/builtin-objects/ecma-builtins.inc.h | 18 ++ jerry-core/ecma/operations/ecma-comparison.c | 14 + jerry-core/ecma/operations/ecma-conversion.c | 185 ++++++++----- jerry-core/ecma/operations/ecma-conversion.h | 1 + .../ecma/operations/ecma-get-put-value.c | 1 + jerry-core/ecma/operations/ecma-objects.c | 174 +++++++------ .../ecma/operations/ecma-symbol-object.c | 186 ++++++++++++++ .../ecma/operations/ecma-symbol-object.h | 53 ++++ jerry-core/jcontext/jcontext.h | 3 + jerry-core/lit/lit-magic-strings.h | 12 + jerry-core/lit/lit-magic-strings.inc.h | 59 ++++- jerry-core/lit/lit-magic-strings.ini | 15 ++ jerry-core/profiles/README.md | 5 +- jerry-core/vm/opcodes.c | 16 +- jerry-core/vm/vm.c | 41 +-- .../es2015/object-get-own-property-symbols.js | 119 +++++++++ tests/jerry/es2015/symbol-key-keyfor.js | 60 +++++ .../symbol-prototype-symbol-toprimitive.js | 34 +++ .../jerry/es2015/symbol-prototype-tostring.js | 34 +++ .../jerry/es2015/symbol-prototype-valueof.js | 34 +++ tests/jerry/es2015/symbol.js | 122 +++++++++ .../{ => es5.1}/regression-test-issue-116.js | 0 43 files changed, 1896 insertions(+), 212 deletions(-) create mode 100644 jerry-core/ecma/builtin-objects/ecma-builtin-symbol-prototype.c create mode 100644 jerry-core/ecma/builtin-objects/ecma-builtin-symbol-prototype.inc.h create mode 100644 jerry-core/ecma/builtin-objects/ecma-builtin-symbol.c create mode 100644 jerry-core/ecma/builtin-objects/ecma-builtin-symbol.inc.h create mode 100644 jerry-core/ecma/operations/ecma-symbol-object.c create mode 100644 jerry-core/ecma/operations/ecma-symbol-object.h create mode 100644 tests/jerry/es2015/object-get-own-property-symbols.js create mode 100644 tests/jerry/es2015/symbol-key-keyfor.js create mode 100644 tests/jerry/es2015/symbol-prototype-symbol-toprimitive.js create mode 100644 tests/jerry/es2015/symbol-prototype-tostring.js create mode 100644 tests/jerry/es2015/symbol-prototype-valueof.js create mode 100644 tests/jerry/es2015/symbol.js rename tests/jerry/{ => es5.1}/regression-test-issue-116.js (100%) diff --git a/jerry-core/config.h b/jerry-core/config.h index f74a31ecc..e5d39eb92 100644 --- a/jerry-core/config.h +++ b/jerry-core/config.h @@ -43,6 +43,7 @@ # define CONFIG_DISABLE_ES2015_MAP_BUILTIN # define CONFIG_DISABLE_ES2015_OBJECT_INITIALIZER # define CONFIG_DISABLE_ES2015_PROMISE_BUILTIN +# define CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN # define CONFIG_DISABLE_ES2015_TEMPLATE_STRINGS # define CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN #endif /* CONFIG_DISABLE_ES2015 */ diff --git a/jerry-core/ecma/base/ecma-gc.c b/jerry-core/ecma/base/ecma-gc.c index c16275671..9eb84b4ea 100644 --- a/jerry-core/ecma/base/ecma-gc.c +++ b/jerry-core/ecma/base/ecma-gc.c @@ -592,6 +592,9 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */ switch (ext_object_p->u.class_prop.class_id) { +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + case LIT_MAGIC_STRING_SYMBOL_UL: +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ case LIT_MAGIC_STRING_STRING_UL: case LIT_MAGIC_STRING_NUMBER_UL: { diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index 375e7d17d..830ab6921 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -73,6 +73,7 @@ typedef enum ECMA_TYPE_STRING = 1, /**< pointer to description of a string */ ECMA_TYPE_FLOAT = 2, /**< pointer to a 64 or 32 bit floating point number */ ECMA_TYPE_OBJECT = 3, /**< pointer to description of an object */ + ECMA_TYPE_SYMBOL = 4, /**< pointer to description of a symbol */ ECMA_TYPE_DIRECT_STRING = 5, /**< directly encoded string values */ ECMA_TYPE_ERROR = 7, /**< pointer to description of an error reference (only supported by C API) */ ECMA_TYPE_POINTER = ECMA_TYPE_ERROR, /**< a generic aligned pointer */ @@ -361,6 +362,9 @@ typedef enum * that are not indices */ ECMA_LIST_ENUMERABLE = (1 << 1), /**< exclude non-enumerable properties */ ECMA_LIST_PROTOTYPE = (1 << 2), /**< list properties from prototype chain */ +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + ECMA_LIST_SYMBOLS = (1 << 3), /**< list symbol properties only */ +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ } ecma_list_properties_options_t; /** @@ -1328,6 +1332,8 @@ typedef enum stored locally in the string's descriptor */ ECMA_STRING_CONTAINER_MAGIC_STRING_EX, /**< the ecma-string is equal to one of external magic strings */ + ECMA_STRING_CONTAINER_SYMBOL, /**< the ecma-string is a symbol */ + ECMA_STRING_LITERAL_NUMBER, /**< a literal number which is used solely by the literal storage * so no string processing function supports this type except * the ecma_deref_ecma_string function. */ @@ -1398,6 +1404,7 @@ typedef struct uint32_t magic_string_ex_id; /**< identifier of an external magic string (lit_magic_string_ex_id_t) */ ecma_value_t lit_number; /**< number (see ECMA_STRING_LITERAL_NUMBER) */ uint32_t common_uint32_field; /**< for zeroing and comparison in some cases */ + ecma_value_t symbol_descriptor; /**< symbol descriptor string-value */ } u; } ecma_string_t; @@ -1535,6 +1542,26 @@ typedef struct } ecma_extended_typedarray_object_t; #endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */ + +/** + * Flag for indicating whether the symbol is a well known symbol + * + * See also: 6.1.5.1 + */ +#define ECMA_GLOBAL_SYMBOL_FLAG 0x01 + +/** + * Bitshift index for indicating whether the symbol is a well known symbol + * + * See also: 6.1.5.1 + */ +#define ECMA_GLOBAL_SYMBOL_SHIFT 1 + +/** + * Bitshift index for the symbol hash property + */ +#define ECMA_SYMBOL_HASH_SHIFT 2 + /** * @} * @} diff --git a/jerry-core/ecma/base/ecma-helpers-string.c b/jerry-core/ecma/base/ecma-helpers-string.c index 41a11120c..59100bd1d 100644 --- a/jerry-core/ecma/base/ecma-helpers-string.c +++ b/jerry-core/ecma/base/ecma-helpers-string.c @@ -198,6 +198,42 @@ ecma_new_ecma_string_from_magic_string_ex_id (lit_magic_string_ex_id_t id) /**< return string_desc_p; } /* ecma_new_ecma_string_from_magic_string_ex_id */ +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN +/** + * Allocate new ecma-string and fill it with reference to the symbol descriptor + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_new_symbol_from_descriptor_string (ecma_value_t string_desc) /**< ecma-string */ +{ + JERRY_ASSERT (!ecma_is_value_symbol (string_desc)); + + ecma_string_t *symbol_p = ecma_alloc_string (); + symbol_p->refs_and_container = ECMA_STRING_REF_ONE | ECMA_STRING_CONTAINER_SYMBOL; + symbol_p->u.symbol_descriptor = string_desc; + symbol_p->hash = (uint16_t) (((uintptr_t) symbol_p) >> ECMA_SYMBOL_HASH_SHIFT); + JERRY_ASSERT ((symbol_p->hash & ECMA_GLOBAL_SYMBOL_FLAG) == 0); + + return symbol_p; +} /* ecma_new_symbol_from_descriptor_string */ + +/** + * Check whether an ecma-string contains an ecma-symbol + * + * @return true - if the ecma-string contains an ecma-symbol + * false - otherwise + */ +bool +ecma_prop_name_is_symbol (ecma_string_t *string_p) /**< ecma-string */ +{ + JERRY_ASSERT (string_p != NULL); + + return (!ECMA_IS_DIRECT_STRING (string_p) + && ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_SYMBOL); +} /* ecma_prop_name_is_symbol */ +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ + /** * Allocate new ecma-string and fill it with characters from the utf8 string * @@ -934,6 +970,13 @@ ecma_deref_ecma_string (ecma_string_t *string_p) /**< ecma-string */ ecma_free_value (string_p->u.lit_number); break; } +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + case ECMA_STRING_CONTAINER_SYMBOL: + { + ecma_free_value (string_p->u.symbol_descriptor); + break; + } +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ default: { JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC @@ -1773,6 +1816,13 @@ ecma_compare_ecma_strings (const ecma_string_t *string1_p, /**< ecma-string */ return false; } +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + if (string1_container == ECMA_STRING_CONTAINER_SYMBOL) + { + return false; + } +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ + if (string1_container >= ECMA_STRING_CONTAINER_UINT32_IN_DESC) { return string1_p->u.common_uint32_field == string2_p->u.common_uint32_field; diff --git a/jerry-core/ecma/base/ecma-helpers-value.c b/jerry-core/ecma/base/ecma-helpers-value.c index 6bb76ed53..e345c00a0 100644 --- a/jerry-core/ecma/base/ecma-helpers-value.c +++ b/jerry-core/ecma/base/ecma-helpers-value.c @@ -311,6 +311,36 @@ ecma_is_value_string (ecma_value_t value) /**< ecma value */ return ((value & (ECMA_VALUE_TYPE_MASK - 0x4)) == ECMA_TYPE_STRING); } /* ecma_is_value_string */ +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN +/** + * Check if the value is symbol. + * + * @return true - if the value contains symbol value, + * false - otherwise + */ +inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE +ecma_is_value_symbol (ecma_value_t value) /**< ecma value */ +{ + return (ecma_get_value_type_field (value) == ECMA_TYPE_SYMBOL); +} /* ecma_is_value_symbol */ +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ + +/** + * Check if the value can be property name. + * + * @return true - if the value can be property name value, + * false - otherwise + */ +inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE +ecma_is_value_prop_name (ecma_value_t value) /**< ecma value */ +{ +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + return ecma_is_value_string (value) || ecma_is_value_symbol (value); +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ + + return ecma_is_value_string (value); +} /* ecma_is_value_prop_name */ + /** * Check if the value is direct ecma-string. * @@ -383,6 +413,7 @@ ecma_check_value_type_is_spec_defined (ecma_value_t value) /**< ecma value */ || ecma_is_value_boolean (value) || ecma_is_value_number (value) || ecma_is_value_string (value) + || ECMA_ASSERT_VALUE_IS_SYMBOL (value) || ecma_is_value_object (value)); } /* ecma_check_value_type_is_spec_defined */ @@ -531,6 +562,9 @@ inline ecma_value_t JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE ecma_make_string_value (const ecma_string_t *ecma_string_p) /**< string to reference in value */ { JERRY_ASSERT (ecma_string_p != NULL); +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + JERRY_ASSERT (!ecma_prop_name_is_symbol ((ecma_string_t *) ecma_string_p)); +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ if ((((uintptr_t) ecma_string_p) & ECMA_VALUE_TYPE_MASK) != 0) { @@ -540,6 +574,42 @@ ecma_make_string_value (const ecma_string_t *ecma_string_p) /**< string to refer return ecma_pointer_to_ecma_value (ecma_string_p) | ECMA_TYPE_STRING; } /* ecma_make_string_value */ +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN +/** + * Symbol value constructor + * + * @return ecma-value representation of the string argument + */ +inline ecma_value_t JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE +ecma_make_symbol_value (const ecma_string_t *ecma_symbol_p) /**< symbol to reference in value */ +{ + JERRY_ASSERT (ecma_symbol_p != NULL); + JERRY_ASSERT (ecma_prop_name_is_symbol ((ecma_string_t *) ecma_symbol_p)); + + return ecma_pointer_to_ecma_value (ecma_symbol_p) | ECMA_TYPE_SYMBOL; +} /* ecma_make_symbol_value */ +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ + +/** + * Property-name value constructor + * + * @return ecma-value representation of a property name argument + */ +inline ecma_value_t JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE +ecma_make_prop_name_value (const ecma_string_t *ecma_prop_name_p) /**< property name to reference in value */ +{ + JERRY_ASSERT (ecma_prop_name_p != NULL); + +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + if (ecma_prop_name_is_symbol ((ecma_string_t *) ecma_prop_name_p)) + { + return ecma_make_symbol_value (ecma_prop_name_p); + } +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ + + return ecma_make_string_value (ecma_prop_name_p); +} /* ecma_make_prop_name_value */ + /** * String value constructor * @@ -660,6 +730,39 @@ ecma_get_string_from_value (ecma_value_t value) /**< ecma value */ return (ecma_string_t *) ecma_get_pointer_from_ecma_value (value); } /* ecma_get_string_from_value */ +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN +/** + * Get pointer to ecma-string from ecma value + * + * @return the string pointer + */ +inline ecma_string_t *JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE +ecma_get_symbol_from_value (ecma_value_t value) /**< ecma value */ +{ + JERRY_ASSERT (ecma_is_value_symbol (value)); + + return (ecma_string_t *) ecma_get_pointer_from_ecma_value (value); +} /* ecma_get_symbol_from_value */ +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ + +/** + * Get pointer to a property name from ecma value + * + * @return the string pointer + */ +inline ecma_string_t *JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE +ecma_get_prop_name_from_value (ecma_value_t value) /**< ecma value */ +{ + JERRY_ASSERT (ecma_is_value_prop_name (value)); + + if ((value & ECMA_VALUE_TYPE_MASK) == ECMA_TYPE_DIRECT_STRING) + { + return (ecma_string_t *) (uintptr_t) value; + } + + return (ecma_string_t *) ecma_get_pointer_from_ecma_value (value); +} /* ecma_get_prop_name_from_value */ + /** * Get pointer to ecma-object from ecma value * @@ -737,6 +840,13 @@ ecma_copy_value (ecma_value_t value) /**< value description */ ecma_ref_ecma_string (ecma_get_string_from_value (value)); return value; } +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + case ECMA_TYPE_SYMBOL: + { + ecma_ref_ecma_string (ecma_get_symbol_from_value (value)); + return value; + } +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ case ECMA_TYPE_OBJECT: { ecma_ref_object (ecma_get_object_from_value (value)); @@ -927,7 +1037,13 @@ ecma_free_value (ecma_value_t value) /**< value description */ ecma_deref_ecma_string (string_p); break; } - +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + case ECMA_TYPE_SYMBOL: + { + ecma_deref_ecma_string (ecma_get_symbol_from_value (value)); + break; + } +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ case ECMA_TYPE_OBJECT: { ecma_deref_object (ecma_get_object_from_value (value)); @@ -1027,6 +1143,12 @@ ecma_get_typeof_lit_id (ecma_value_t value) /**< input ecma value */ { ret_value = LIT_MAGIC_STRING_STRING; } +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + else if (ecma_is_value_symbol (value)) + { + ret_value = LIT_MAGIC_STRING_SYMBOL; + } +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ else { JERRY_ASSERT (ecma_is_value_object (value)); diff --git a/jerry-core/ecma/base/ecma-helpers.h b/jerry-core/ecma/base/ecma-helpers.h index 620033e49..477bac19b 100644 --- a/jerry-core/ecma/base/ecma-helpers.h +++ b/jerry-core/ecma/base/ecma-helpers.h @@ -137,6 +137,18 @@ typedef enum */ #define ECMA_BOOL_TO_BITFIELD(x) ((x) ? 1 : 0) +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN +/** + * JERRY_ASSERT compatible macro for checking whether the given ecma-value is symbol + */ +#define ECMA_ASSERT_VALUE_IS_SYMBOL(value) (ecma_is_value_symbol ((value))) +#else /* CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ +/** + * JERRY_ASSERT compatible macro for checking whether the given ecma-value is symbol + */ +#define ECMA_ASSERT_VALUE_IS_SYMBOL(value) (false) +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ + /* ecma-helpers-value.c */ bool JERRY_ATTR_CONST ecma_is_value_direct (ecma_value_t value); bool JERRY_ATTR_CONST ecma_is_value_simple (ecma_value_t value); @@ -154,6 +166,10 @@ bool JERRY_ATTR_CONST ecma_are_values_integer_numbers (ecma_value_t first_value, bool JERRY_ATTR_CONST ecma_is_value_float_number (ecma_value_t value); bool JERRY_ATTR_CONST ecma_is_value_number (ecma_value_t value); bool JERRY_ATTR_CONST ecma_is_value_string (ecma_value_t value); +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN +bool JERRY_ATTR_CONST ecma_is_value_symbol (ecma_value_t value); +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ +bool JERRY_ATTR_CONST ecma_is_value_prop_name (ecma_value_t value); bool JERRY_ATTR_CONST ecma_is_value_direct_string (ecma_value_t value); bool JERRY_ATTR_CONST ecma_is_value_non_direct_string (ecma_value_t value); bool JERRY_ATTR_CONST ecma_is_value_object (ecma_value_t value); @@ -169,6 +185,10 @@ ecma_value_t ecma_make_number_value (ecma_number_t ecma_number); ecma_value_t ecma_make_int32_value (int32_t int32_number); ecma_value_t ecma_make_uint32_value (uint32_t uint32_number); ecma_value_t JERRY_ATTR_PURE ecma_make_string_value (const ecma_string_t *ecma_string_p); +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN +ecma_value_t JERRY_ATTR_PURE ecma_make_symbol_value (const ecma_string_t *ecma_symbol_p); +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ +ecma_value_t JERRY_ATTR_PURE ecma_make_prop_name_value (const ecma_string_t *ecma_prop_name_p); ecma_value_t JERRY_ATTR_PURE ecma_make_magic_string_value (lit_magic_string_id_t id); ecma_value_t JERRY_ATTR_PURE ecma_make_object_value (const ecma_object_t *object_p); ecma_value_t JERRY_ATTR_PURE ecma_make_error_reference_value (const ecma_error_reference_t *error_ref_p); @@ -177,6 +197,10 @@ ecma_integer_value_t JERRY_ATTR_CONST ecma_get_integer_from_value (ecma_value_t ecma_number_t JERRY_ATTR_PURE ecma_get_float_from_value (ecma_value_t value); ecma_number_t JERRY_ATTR_PURE ecma_get_number_from_value (ecma_value_t value); ecma_string_t JERRY_ATTR_PURE *ecma_get_string_from_value (ecma_value_t value); +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN +ecma_string_t JERRY_ATTR_PURE *ecma_get_symbol_from_value (ecma_value_t value); +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ +ecma_string_t JERRY_ATTR_PURE *ecma_get_prop_name_from_value (ecma_value_t value); ecma_object_t JERRY_ATTR_PURE *ecma_get_object_from_value (ecma_value_t value); ecma_error_reference_t JERRY_ATTR_PURE *ecma_get_error_reference_from_value (ecma_value_t value); void * JERRY_ATTR_PURE ecma_get_pointer_from_value (ecma_value_t value); @@ -194,6 +218,10 @@ void ecma_free_number (ecma_value_t value); lit_magic_string_id_t ecma_get_typeof_lit_id (ecma_value_t value); /* ecma-helpers-string.c */ +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN +ecma_string_t *ecma_new_symbol_from_descriptor_string (ecma_value_t string_desc); +bool ecma_prop_name_is_symbol (ecma_string_t *string_p); +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ ecma_string_t *ecma_new_ecma_string_from_utf8 (const lit_utf8_byte_t *string_p, lit_utf8_size_t string_size); ecma_string_t *ecma_new_ecma_string_from_utf8_converted_to_cesu8 (const lit_utf8_byte_t *string_p, lit_utf8_size_t string_size); diff --git a/jerry-core/ecma/base/ecma-literal-storage.c b/jerry-core/ecma/base/ecma-literal-storage.c index 4262ea9f0..f16e340ba 100644 --- a/jerry-core/ecma/base/ecma-literal-storage.c +++ b/jerry-core/ecma/base/ecma-literal-storage.c @@ -57,6 +57,9 @@ ecma_free_string_list (ecma_lit_storage_item_t *string_list_p) /**< string list void ecma_finalize_lit_storage (void) { +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + ecma_free_string_list (JERRY_CONTEXT (symbol_list_first_p)); +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ ecma_free_string_list (JERRY_CONTEXT (string_list_first_p)); ecma_free_string_list (JERRY_CONTEXT (number_list_first_p)); } /* ecma_finalize_lit_storage */ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-global.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-global.inc.h index 1339e915c..f1ce41c01 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-global.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-global.inc.h @@ -205,6 +205,13 @@ OBJECT_VALUE (LIT_MAGIC_STRING_MAP_UL, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) #endif /* !CONFIG_DISABLE_ES2015_MAP_BUILTIN */ +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN +/* ECMA-262 v6, 19.4.1.1 */ +OBJECT_VALUE (LIT_MAGIC_STRING_SYMBOL_UL, + ECMA_BUILTIN_ID_SYMBOL, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ + /* 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-builtin-helpers-macro-defines.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-macro-defines.inc.h index fef4ea0a2..0b6e07821 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-macro-defines.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-macro-defines.inc.h @@ -25,6 +25,12 @@ #define STRING_VALUE(name, magic_string_id, prop_attributes) #endif /* !STRING_VALUE */ +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN +#ifndef SYMBOL_VALUE +#define SYMBOL_VALUE(name, desc_string_id) +#endif /* !SYMBOL_VALUE */ +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ + #ifndef OBJECT_VALUE #define OBJECT_VALUE(name, obj_builtin_id, prop_attributes) #endif /* !OBJECT_VALUE */ @@ -33,6 +39,10 @@ #define ROUTINE(name, c_function_name, args_number, length_prop_value) #endif /* !ROUTINE */ +#ifndef ROUTINE_CONFIGURABLE_ONLY +#define ROUTINE_CONFIGURABLE_ONLY(name, c_function_name, args_number, length_prop_value) +#endif /* !ROUTINE_CONFIGURABLE_ONLY */ + #ifndef ACCESSOR_READ_WRITE #define ACCESSOR_READ_WRITE(name, c_getter_func_name, c_setter_func_name, prop_attributes) #endif /* !ACCESSOR_READ_WRITE */ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-macro-undefs.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-macro-undefs.inc.h index f2c190622..f96f99164 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-macro-undefs.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-macro-undefs.inc.h @@ -16,7 +16,11 @@ #undef SIMPLE_VALUE #undef NUMBER_VALUE #undef STRING_VALUE +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN +#undef SYMBOL_VALUE +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ #undef OBJECT_VALUE #undef ROUTINE +#undef ROUTINE_CONFIGURABLE_ONLY #undef ACCESSOR_READ_WRITE #undef ACCESSOR_READ_ONLY diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.c b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.c index bccd1aa03..4d22424d8 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.c @@ -187,7 +187,7 @@ ecma_builtin_helper_get_to_locale_string_at_index (ecma_object_t *obj_p, /**< th */ ecma_value_t ecma_builtin_helper_object_get_properties (ecma_object_t *obj_p, /**< object */ - bool only_enumerable_properties) /**< list enumerable properties? */ + uint32_t opts) /**< any combination of ecma_list_properties_options_t */ { JERRY_ASSERT (obj_p != NULL); @@ -197,9 +197,7 @@ ecma_builtin_helper_object_get_properties (ecma_object_t *obj_p, /**< object */ uint32_t index = 0; - ecma_collection_header_t *props_p; - props_p = ecma_op_object_get_property_names (obj_p, - only_enumerable_properties ? ECMA_LIST_ENUMERABLE : ECMA_LIST_NO_OPTS); + ecma_collection_header_t *props_p = ecma_op_object_get_property_names (obj_p, opts); ecma_value_t *ecma_value_p = ecma_collection_iterator_init (props_p); diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.h b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.h index c061e4609..a453dfada 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.h @@ -31,7 +31,7 @@ ecma_builtin_helper_object_to_string (const ecma_value_t this_arg); ecma_value_t ecma_builtin_helper_get_to_locale_string_at_index (ecma_object_t *obj_p, uint32_t index); ecma_value_t -ecma_builtin_helper_object_get_properties (ecma_object_t *obj_p, bool only_enumerable_properties); +ecma_builtin_helper_object_get_properties (ecma_object_t *obj_p, uint32_t opts); ecma_value_t ecma_builtin_helper_array_concat_value (ecma_object_t *obj_p, uint32_t *length_p, ecma_value_t value); uint32_t 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 480f13476..12ba7dc10 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 @@ -43,6 +43,8 @@ const ecma_value_t *arguments_list_p, ecma_length_t arguments_list_len #define ROUTINE(name, c_function_name, args_number, length_prop_value) \ static ecma_value_t c_function_name (ROUTINE_ARG_LIST_ ## args_number); +#define ROUTINE_CONFIGURABLE_ONLY(name, c_function_name, args_number, length_prop_value) \ + static ecma_value_t c_function_name (ROUTINE_ARG_LIST_ ## args_number); #define ACCESSOR_READ_WRITE(name, c_getter_func_name, c_setter_func_name, prop_attributes) \ static ecma_value_t c_getter_func_name (ROUTINE_ARG_LIST_0); \ static ecma_value_t c_setter_func_name (ROUTINE_ARG_LIST_1); @@ -64,6 +66,8 @@ enum PASTE (ECMA_ROUTINE_START_, BUILTIN_UNDERSCORED_ID) = ECMA_BUILTIN_ID__COUNT - 1, #define ROUTINE(name, c_function_name, args_number, length_prop_value) \ ECMA_ROUTINE_ ## name ## c_function_name, +#define ROUTINE_CONFIGURABLE_ONLY(name, c_function_name, args_number, length_prop_value) \ + ECMA_ROUTINE_ ## name ## c_function_name, #define ACCESSOR_READ_WRITE(name, c_getter_func_name, c_setter_func_name, prop_attributes) \ ECMA_ACCESSOR_ ## name ## c_getter_func_name, \ ECMA_ACCESSOR_ ## name ## c_setter_func_name, @@ -87,6 +91,13 @@ const ecma_builtin_property_descriptor_t PROPERTY_DESCRIPTOR_LIST_NAME[] = ECMA_PROPERTY_CONFIGURABLE_WRITABLE, \ ECMA_ROUTINE_VALUE (ECMA_ROUTINE_ ## name ## c_function_name, length_prop_value) \ }, +#define ROUTINE_CONFIGURABLE_ONLY(name, c_function_name, args_number, length_prop_value) \ + { \ + name, \ + ECMA_BUILTIN_PROPERTY_ROUTINE, \ + ECMA_PROPERTY_FLAG_CONFIGURABLE, \ + ECMA_ROUTINE_VALUE (ECMA_ROUTINE_ ## name ## c_function_name, length_prop_value) \ + }, #else /* BUILTIN_CUSTOM_DISPATCH */ #define ROUTINE(name, c_function_name, args_number, length_prop_value) \ { \ @@ -95,6 +106,13 @@ const ecma_builtin_property_descriptor_t PROPERTY_DESCRIPTOR_LIST_NAME[] = ECMA_PROPERTY_CONFIGURABLE_WRITABLE, \ ECMA_ROUTINE_VALUE (c_function_name, length_prop_value) \ }, +#define ROUTINE_CONFIGURABLE_ONLY(name, c_function_name, args_number, length_prop_value) \ + { \ + name, \ + ECMA_BUILTIN_PROPERTY_ROUTINE, \ + ECMA_PROPERTY_FLAG_CONFIGURABLE, \ + ECMA_ROUTINE_VALUE (c_function_name, length_prop_value) \ + }, #endif /* !BUILTIN_CUSTOM_DISPATCH */ #define OBJECT_VALUE(name, obj_builtin_id, prop_attributes) \ { \ @@ -124,6 +142,15 @@ const ecma_builtin_property_descriptor_t PROPERTY_DESCRIPTOR_LIST_NAME[] = prop_attributes, \ magic_string_id \ }, +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN +#define SYMBOL_VALUE(name, desc_string_id) \ + { \ + name, \ + ECMA_BUILTIN_PROPERTY_SYMBOL, \ + ECMA_PROPERTY_FIXED, \ + desc_string_id \ + }, +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ #define ACCESSOR_READ_WRITE(name, c_getter_name, c_setter_name, prop_attributes) \ { \ name, \ @@ -183,6 +210,11 @@ DISPATCH_ROUTINE_ROUTINE_NAME (uint16_t builtin_routine_id, /**< built-in wide r { \ return c_function_name (this_arg_value ROUTINE_ARG_LIST_ ## args_number); \ } +#define ROUTINE_CONFIGURABLE_ONLY(name, c_function_name, args_number, length_prop_value) \ + case ECMA_ROUTINE_ ## name ## c_function_name: \ + { \ + return c_function_name (this_arg_value ROUTINE_ARG_LIST_ ## args_number); \ + } #define ACCESSOR_READ_WRITE(name, c_getter_func_name, c_setter_func_name, prop_attributes) \ case ECMA_ACCESSOR_ ## name ## c_getter_func_name: \ { \ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-object.c b/jerry-core/ecma/builtin-objects/ecma-builtin-object.c index 3729df886..55da22057 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-object.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-object.c @@ -296,12 +296,41 @@ ecma_builtin_object_object_get_own_property_names (ecma_value_t this_arg, /**< ' { ecma_object_t *obj_p = ecma_get_object_from_value (arg); /* 2-5. */ - ret_value = ecma_builtin_helper_object_get_properties (obj_p, false); + ret_value = ecma_builtin_helper_object_get_properties (obj_p, ECMA_LIST_NO_OPTS); } return ret_value; } /* ecma_builtin_object_object_get_own_property_names */ +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN +/** + * The Object object's 'getOwnPropertySymbols' routine + * + * See also: + * ECMA-262 v6, 19.1.2.7 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_object_get_own_property_symbols (ecma_value_t this_arg, /**< 'this' argument */ + ecma_value_t arg) /**< routine's argument */ +{ + JERRY_UNUSED (this_arg); + + if (!ecma_is_value_object (arg)) + { + /* 1. */ + return ecma_raise_type_error (ECMA_ERR_MSG ("Argument is not an object.")); + } + + /* 2 - 5. */ + ecma_object_t *obj_p = ecma_get_object_from_value (arg); + + return ecma_builtin_helper_object_get_properties (obj_p, ECMA_LIST_SYMBOLS); +} /* ecma_builtin_object_object_get_own_property_symbols */ +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ + /** * The Object object's 'seal' routine * @@ -643,7 +672,7 @@ ecma_builtin_object_object_keys (ecma_value_t this_arg, /**< 'this' argument */ { ecma_object_t *obj_p = ecma_get_object_from_value (arg); /* 3-6. */ - ret_value = ecma_builtin_helper_object_get_properties (obj_p, true); + ret_value = ecma_builtin_helper_object_get_properties (obj_p, ECMA_LIST_ENUMERABLE); } return ret_value; @@ -669,19 +698,18 @@ ecma_builtin_object_object_get_own_property_descriptor (ecma_value_t this_arg, / /* 1. */ if (!ecma_is_value_object (arg1)) { - ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Argument is not an object.")); - return ret_value; + return ecma_raise_type_error (ECMA_ERR_MSG ("Argument is not an object.")); + } + + ecma_string_t *name_str_p = ecma_op_to_prop_name (arg2); + + if (JERRY_UNLIKELY (name_str_p == NULL)) + { + return ECMA_VALUE_ERROR; } ecma_object_t *obj_p = ecma_get_object_from_value (arg1); - /* 2. */ - ECMA_TRY_CATCH (name_str_value, - ecma_op_to_string (arg2), - ret_value); - - ecma_string_t *name_str_p = ecma_get_string_from_value (name_str_value); - /* 3. */ ecma_property_descriptor_t prop_desc; @@ -699,7 +727,7 @@ ecma_builtin_object_object_get_own_property_descriptor (ecma_value_t this_arg, / ret_value = ECMA_VALUE_UNDEFINED; } - ECMA_FINALIZE (name_str_value); + ecma_deref_ecma_string (name_str_p); return ret_value; } /* ecma_builtin_object_object_get_own_property_descriptor */ @@ -886,39 +914,38 @@ ecma_builtin_object_object_define_property (ecma_value_t this_arg, /**< 'this' a if (!ecma_is_value_object (arg1)) { - ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Argument is not an object.")); + return ecma_raise_type_error (ECMA_ERR_MSG ("Argument is not an object.")); } - else + + ecma_string_t *name_str_p = ecma_op_to_prop_name (arg2); + + if (JERRY_UNLIKELY (name_str_p == NULL)) { - ecma_object_t *obj_p = ecma_get_object_from_value (arg1); - - ECMA_TRY_CATCH (name_str_value, - ecma_op_to_string (arg2), - ret_value); - - ecma_string_t *name_str_p = ecma_get_string_from_value (name_str_value); - - ecma_property_descriptor_t prop_desc; - - ECMA_TRY_CATCH (conv_result, - ecma_op_to_property_descriptor (arg3, &prop_desc), - ret_value); - - ECMA_TRY_CATCH (define_own_prop_ret, - ecma_op_object_define_own_property (obj_p, - name_str_p, - &prop_desc, - true), - ret_value); - - ret_value = ecma_copy_value (arg1); - - ECMA_FINALIZE (define_own_prop_ret); - ecma_free_property_descriptor (&prop_desc); - ECMA_FINALIZE (conv_result); - ECMA_FINALIZE (name_str_value); + return ECMA_VALUE_ERROR; } + ecma_object_t *obj_p = ecma_get_object_from_value (arg1); + + ecma_property_descriptor_t prop_desc; + + ECMA_TRY_CATCH (conv_result, + ecma_op_to_property_descriptor (arg3, &prop_desc), + ret_value); + + ECMA_TRY_CATCH (define_own_prop_ret, + ecma_op_object_define_own_property (obj_p, + name_str_p, + &prop_desc, + true), + ret_value); + + ret_value = ecma_copy_value (arg1); + + ECMA_FINALIZE (define_own_prop_ret); + ecma_free_property_descriptor (&prop_desc); + ECMA_FINALIZE (conv_result); + ecma_deref_ecma_string (name_str_p); + return ret_value; } /* ecma_builtin_object_object_define_property */ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-object.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-object.inc.h index 03cd56280..c54b47a89 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-object.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-object.inc.h @@ -39,6 +39,9 @@ OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ ROUTINE (LIT_MAGIC_STRING_GET_PROTOTYPE_OF_UL, ecma_builtin_object_object_get_prototype_of, 1, 1) ROUTINE (LIT_MAGIC_STRING_GET_OWN_PROPERTY_NAMES_UL, ecma_builtin_object_object_get_own_property_names, 1, 1) +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN +ROUTINE (LIT_MAGIC_STRING_GET_OWN_PROPERTY_SYMBOLS_UL, ecma_builtin_object_object_get_own_property_symbols, 1, 1) +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ ROUTINE (LIT_MAGIC_STRING_SEAL, ecma_builtin_object_object_seal, 1, 1) ROUTINE (LIT_MAGIC_STRING_FREEZE, ecma_builtin_object_object_freeze, 1, 1) ROUTINE (LIT_MAGIC_STRING_PREVENT_EXTENSIONS_UL, ecma_builtin_object_object_prevent_extensions, 1, 1) diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-symbol-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-symbol-prototype.c new file mode 100644 index 000000000..82eb1cd2c --- /dev/null +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-symbol-prototype.c @@ -0,0 +1,98 @@ +/* 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. + */ + + #include "ecma-alloc.h" + #include "ecma-builtins.h" + #include "ecma-conversion.h" + #include "ecma-exceptions.h" + #include "ecma-gc.h" + #include "ecma-globals.h" + #include "ecma-helpers.h" + #include "ecma-objects.h" + #include "ecma-symbol-object.h" + #include "ecma-try-catch-macro.h" + #include "jrt.h" + +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-symbol-prototype.inc.h" +#define BUILTIN_UNDERSCORED_ID symbol_prototype +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup symbolprototype ECMA Symbol prototype object built-in + * @{ + */ + +/** + * The Symbol.prototype object's 'toString' routine + * + * See also: + * ECMA-262 v6, 19.4.3.2 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_symbol_prototype_object_to_string (ecma_value_t this_arg) /**< this argument */ +{ + return ecma_symbol_to_string_helper (this_arg, true); +} /* ecma_builtin_symbol_prototype_object_to_string */ + +/** + * The Symbol.prototype object's 'valueOf' routine + * + * See also: + * ECMA-262 v6, 19.4.3.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_symbol_prototype_object_value_of (ecma_value_t this_arg) /**< this argument */ +{ + return ecma_symbol_to_string_helper (this_arg, false); +} /* ecma_builtin_symbol_prototype_object_value_of */ + +/** + * The Symbol.prototype object's '@@toPrimitive' routine + * + * See also: + * ECMA-262 v6, 19.4.3.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_symbol_prototype_object_to_primitive (ecma_value_t this_arg) /**< this argument */ +{ + return ecma_builtin_symbol_prototype_object_value_of (this_arg); +} /* ecma_builtin_symbol_prototype_object_to_primitive */ + +/** + * @} + * @} + * @} + */ + +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-symbol-prototype.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-symbol-prototype.inc.h new file mode 100644 index 000000000..86d9ddecd --- /dev/null +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-symbol-prototype.inc.h @@ -0,0 +1,49 @@ +/* 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. + */ + +/* + * Symbol prototype built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + +/* Object properties: + * (property name, object pointer getter) */ + +OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR, + ECMA_BUILTIN_ID_SYMBOL, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE) + +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, + 0, + ECMA_PROPERTY_FLAG_WRITABLE) + +ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ecma_builtin_symbol_prototype_object_to_string, 0, 0) +ROUTINE (LIT_MAGIC_STRING_VALUE_OF_UL, ecma_builtin_symbol_prototype_object_value_of, 0, 0) +ROUTINE_CONFIGURABLE_ONLY (LIT_GLOBAL_SYMBOL_TO_PRIMITIVE, + ecma_builtin_symbol_prototype_object_to_primitive, + 0, + 0) + +/* ECMA-262 v6, 19.4.3.4 */ +STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG, + LIT_MAGIC_STRING_SYMBOL_UL, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.c b/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.c new file mode 100644 index 000000000..41ed2a6bb --- /dev/null +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.c @@ -0,0 +1,243 @@ +/* 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. + */ + + #include "ecma-alloc.h" + #include "ecma-builtins.h" + #include "ecma-conversion.h" + #include "ecma-exceptions.h" + #include "ecma-gc.h" + #include "ecma-globals.h" + #include "ecma-helpers.h" + #include "ecma-objects.h" + #include "ecma-symbol-object.h" + #include "ecma-literal-storage.h" + #include "ecma-try-catch-macro.h" + #include "jcontext.h" + #include "jrt.h" + +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + +#define ECMA_BUILTINS_INTERNAL +#include "ecma-builtins-internal.h" + +#define BUILTIN_INC_HEADER_NAME "ecma-builtin-symbol.inc.h" +#define BUILTIN_UNDERSCORED_ID symbol +#include "ecma-builtin-internal-routines-template.inc.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmabuiltins + * @{ + * + * \addtogroup symbol ECMA Symbol object built-in + * @{ + */ + +/** + * Handle calling [[Call]] of built-in Symbol object. + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_symbol_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */ + ecma_length_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_op_create_symbol (arguments_list_p, arguments_list_len); +} /* ecma_builtin_symbol_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in Symbol object. + * + * Symbol constructor is not intended to be used + * with the new operator or to be subclassed. + * + * See also: + * ECMA-262 v6, 19.4.1 + * @return ecma value + */ +ecma_value_t +ecma_builtin_symbol_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */ + ecma_length_t arguments_list_len) /**< number of arguments */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + return ecma_raise_type_error (ECMA_ERR_MSG ("Symbol is not a constructor.")); +} /* ecma_builtin_symbol_dispatch_construct */ + +/** + * Helper function for Symbol object's 'for' and `keyFor` + * routines common parts + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_symbol_for_helper (ecma_value_t value_to_find) /**< symbol or ecma-string */ +{ + ecma_string_t *string_p; + + bool is_for = ecma_is_value_string (value_to_find); + + if (is_for) + { + string_p = ecma_get_string_from_value (value_to_find); + } + else + { + string_p = ecma_get_symbol_from_value (value_to_find); + } + + ecma_lit_storage_item_t *symbol_list_p = JERRY_CONTEXT (symbol_list_first_p); + jmem_cpointer_t *empty_cpointer_p = NULL; + + while (symbol_list_p != NULL) + { + for (int i = 0; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + { + if (symbol_list_p->values[i] != JMEM_CP_NULL) + { + ecma_string_t *value_p = JMEM_CP_GET_NON_NULL_POINTER (ecma_string_t, + symbol_list_p->values[i]); + + if (is_for) + { + ecma_string_t *symbol_desc_p = ecma_get_symbol_description (value_p); + + if (ecma_compare_ecma_strings (symbol_desc_p, string_p)) + { + /* The current symbol's descriptor matches with the value_to_find, + so the value is no longer needed. */ + ecma_deref_ecma_string (string_p); + return ecma_copy_value (ecma_make_symbol_value (value_p)); + } + } + else + { + if (string_p == value_p) + { + ecma_string_t *symbol_desc_p = ecma_get_symbol_description (string_p); + ecma_ref_ecma_string (symbol_desc_p); + return ecma_make_string_value (symbol_desc_p); + } + } + } + else + { + if (empty_cpointer_p == NULL) + { + empty_cpointer_p = symbol_list_p->values + i; + } + } + } + + symbol_list_p = JMEM_CP_GET_POINTER (ecma_lit_storage_item_t, symbol_list_p->next_cp); + } + + if (!is_for) + { + return ECMA_VALUE_UNDEFINED; + } + + /* There was no matching, sp a new symbol should be added the the global symbol list. The symbol creation requires + an extra reference to the descriptor string, but this reference has already been added. */ + ecma_string_t *new_symbol_p = ecma_new_symbol_from_descriptor_string (value_to_find); + + jmem_cpointer_t result; + JMEM_CP_SET_NON_NULL_POINTER (result, new_symbol_p); + + if (empty_cpointer_p != NULL) + { + *empty_cpointer_p = result; + return ecma_copy_value (ecma_make_symbol_value (new_symbol_p)); + } + + ecma_lit_storage_item_t *new_item_p; + new_item_p = (ecma_lit_storage_item_t *) jmem_pools_alloc (sizeof (ecma_lit_storage_item_t)); + + new_item_p->values[0] = result; + for (int i = 1; i < ECMA_LIT_STORAGE_VALUE_COUNT; i++) + { + new_item_p->values[i] = JMEM_CP_NULL; + } + + JMEM_CP_SET_POINTER (new_item_p->next_cp, JERRY_CONTEXT (symbol_list_first_p)); + JERRY_CONTEXT (symbol_list_first_p) = new_item_p; + + return ecma_copy_value (ecma_make_symbol_value (new_symbol_p)); +} /* ecma_builtin_symbol_for_helper */ + +/** + * The Symbol object's 'for' routine + * + * See also: + * ECMA-262 v6, 19.4.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_symbol_for (ecma_value_t this_arg, /**< this argument */ + ecma_value_t key) /**< key string */ +{ + JERRY_UNUSED (this_arg); + ecma_value_t string_desc = ecma_op_to_string (key); + + /* 1. */ + if (ECMA_IS_VALUE_ERROR (string_desc)) + { + /* 2. */ + return string_desc; + } + /* 4-7. */ + JERRY_ASSERT (ecma_is_value_string (string_desc)); + + return ecma_builtin_symbol_for_helper (string_desc); +} /* ecma_builtin_symbol_for */ + +/** + * The Symbol object's 'keyFor' routine + * + * See also: + * ECMA-262 v6, 19.4.2. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_symbol_key_for (ecma_value_t this_arg, /**< this argument */ + ecma_value_t symbol) /**< symbol */ +{ + JERRY_UNUSED (this_arg); + + /* 1. */ + if (!ecma_is_value_symbol (symbol)) + { + return ecma_raise_type_error (ECMA_ERR_MSG ("The given argument is not a Symbol.")); + } + + /* 2-4. */ + return ecma_builtin_symbol_for_helper (symbol); +} /* ecma_builtin_symbol_key_for */ + +/** + * @} + * @} + * @} + */ + +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.inc.h new file mode 100644 index 000000000..a030f30c4 --- /dev/null +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.inc.h @@ -0,0 +1,91 @@ +/* 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. + */ + +/* + * Symbol built-in description + */ + +#include "ecma-builtin-helpers-macro-defines.inc.h" + +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + +/* Number properties: + * (property name, number value, writable, enumerable, configurable) */ + +/* ECMA-262 v6, 19.4.2 */ +NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, + 0, + ECMA_PROPERTY_FIXED) + +/* Object properties: + * (property name, object pointer getter) */ + +/* ECMA-262 v6, 19.4.2.7 */ +OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, + ECMA_BUILTIN_ID_SYMBOL_PROTOTYPE, + ECMA_PROPERTY_FIXED) + +/* ECMA-262 v6, 19.4.2.2 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_HAS_INSTANCE, + LIT_GLOBAL_SYMBOL_HAS_INSTANCE) + +/* ECMA-262 v6, 19.4.2.3 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_IS_CONCAT_SPREADABLE, + LIT_GLOBAL_SYMBOL_IS_CONCAT_SPREADABLE) + +/* ECMA-262 v6, 19.4.2.4 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_ITERATOR, + LIT_GLOBAL_SYMBOL_ITERATOR) + +/* ECMA-262 v6, 19.4.2.6 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_MATCH, + LIT_GLOBAL_SYMBOL_MATCH) + +/* ECMA-262 v6, 19.4.2.8 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_REPLACE, + LIT_GLOBAL_SYMBOL_REPLACE) + +/* ECMA-262 v6, 19.4.2.9 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_SEARCH, + LIT_GLOBAL_SYMBOL_SEARCH) + +/* ECMA-262 v6, 19.4.2.10 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_SPECIES, + LIT_GLOBAL_SYMBOL_SPECIES) + +/* ECMA-262 v6, 19.4.2.11 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_SPLIT, + LIT_GLOBAL_SYMBOL_SPLIT) + +/* ECMA-262 v6, 19.4.2.12 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_TO_PRIMITIVE, + LIT_GLOBAL_SYMBOL_TO_PRIMITIVE) + +/* ECMA-262 v6, 19.4.2.13 */ +SYMBOL_VALUE (LIT_MAGIC_STRING_TO_STRING_TAG, + LIT_GLOBAL_SYMBOL_TO_STRING_TAG) + +/* ECMA-262 v6, 19.4.2.14 */ +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) */ +ROUTINE (LIT_MAGIC_STRING_FOR, ecma_builtin_symbol_for, 1, 1) +ROUTINE (LIT_MAGIC_STRING_KEY_FOR, ecma_builtin_symbol_key_for, 1, 1) + +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ + +#include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins-internal.h b/jerry-core/ecma/builtin-objects/ecma-builtins-internal.h index 98dca3056..15e480c37 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins-internal.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtins-internal.h @@ -31,6 +31,9 @@ typedef enum ECMA_BUILTIN_PROPERTY_SIMPLE, /**< simple value property */ ECMA_BUILTIN_PROPERTY_NUMBER, /**< number value property */ ECMA_BUILTIN_PROPERTY_STRING, /**< string value property */ +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + ECMA_BUILTIN_PROPERTY_SYMBOL, /**< symbol value property */ +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ ECMA_BUILTIN_PROPERTY_OBJECT, /**< builtin object property */ ECMA_BUILTIN_PROPERTY_ROUTINE, /**< routine property */ ECMA_BUILTIN_PROPERTY_ACCESSOR_READ_WRITE, /**< full accessor property */ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins.c b/jerry-core/ecma/builtin-objects/ecma-builtins.c index 3be7bf0ee..1d941ddc5 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtins.c @@ -653,6 +653,16 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object * lit_magic_string_id_t magic_string_id = ecma_get_string_magic (string_p); +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + if (JERRY_UNLIKELY (ecma_prop_name_is_symbol (string_p))) + { + if (string_p->hash & ECMA_GLOBAL_SYMBOL_FLAG) + { + magic_string_id = (string_p->hash >> ECMA_GLOBAL_SYMBOL_SHIFT); + } + } +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ + if (magic_string_id == LIT_MAGIC_STRING__COUNT) { return NULL; @@ -772,6 +782,25 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object * value = ecma_make_magic_string_value ((lit_magic_string_id_t) curr_property_p->value); break; } +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + case ECMA_BUILTIN_PROPERTY_SYMBOL: + { + lit_magic_string_id_t symbol_desc_id = (lit_magic_string_id_t) curr_property_p->magic_string_id; + + ecma_string_t *symbol_desc_p; + symbol_desc_p = ecma_append_magic_string_to_string (ecma_get_magic_string (LIT_MAGIC_STRING_SYMBOL_DOT_UL), + symbol_desc_id); + + ecma_value_t symbol_desc_value = ecma_make_string_value (symbol_desc_p); + + ecma_string_t *symbol_p = ecma_new_symbol_from_descriptor_string (symbol_desc_value); + lit_magic_string_id_t symbol_id = (lit_magic_string_id_t) curr_property_p->value; + symbol_p->hash = (uint16_t) ((symbol_id << ECMA_GLOBAL_SYMBOL_SHIFT) | ECMA_GLOBAL_SYMBOL_FLAG); + + value = ecma_make_symbol_value (symbol_p); + break; + } +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ case ECMA_BUILTIN_PROPERTY_OBJECT: { ecma_object_t *builtin_object_p = ecma_builtin_get ((ecma_builtin_id_t) curr_property_p->value); diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtins.inc.h index 70561152f..9c6342bdf 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtins.inc.h @@ -441,6 +441,24 @@ BUILTIN_ROUTINE (ECMA_BUILTIN_ID_MAP, #endif /* !CONFIG_DISABLE_ES2015_MAP_BUILTIN */ +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + +/* The Symbol prototype object (ECMA-262 v6, 19.4.2.7) */ +BUILTIN (ECMA_BUILTIN_ID_SYMBOL_PROTOTYPE, + ECMA_OBJECT_TYPE_GENERAL, + ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, + true, + symbol_prototype) + +/* The Symbol routine (ECMA-262 v6, 19.4.2.1) */ +BUILTIN_ROUTINE (ECMA_BUILTIN_ID_SYMBOL, + ECMA_OBJECT_TYPE_FUNCTION, + ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE, + true, + symbol) + +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ + /* The Global object (15.1) */ BUILTIN (ECMA_BUILTIN_ID_GLOBAL, ECMA_OBJECT_TYPE_GENERAL, diff --git a/jerry-core/ecma/operations/ecma-comparison.c b/jerry-core/ecma/operations/ecma-comparison.c index 8ddddfdef..2c9a7b1c6 100644 --- a/jerry-core/ecma/operations/ecma-comparison.c +++ b/jerry-core/ecma/operations/ecma-comparison.c @@ -125,6 +125,13 @@ ecma_op_abstract_equality_compare (ecma_value_t x, /**< first operand */ y = tmp; } +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + if (ecma_is_value_symbol (x)) + { + return ECMA_VALUE_FALSE; + } +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ + if (ecma_is_value_boolean (y)) { if (ecma_is_value_boolean (x)) @@ -141,6 +148,9 @@ ecma_op_abstract_equality_compare (ecma_value_t x, /**< first operand */ if (ecma_is_value_object (x)) { if (ecma_is_value_string (y) +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + || ecma_is_value_symbol (y) +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ || ecma_is_value_number (y)) { /* 9. */ @@ -195,6 +205,10 @@ ecma_op_strict_equality_compare (ecma_value_t x, /**< first operand */ { if (ecma_is_value_direct (x) || ecma_is_value_direct (y) +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + || ecma_is_value_symbol (x) + || ecma_is_value_symbol (y) +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ || ecma_is_value_object (x) || ecma_is_value_object (y)) { diff --git a/jerry-core/ecma/operations/ecma-conversion.c b/jerry-core/ecma/operations/ecma-conversion.c index 4a5dbf5f7..4441f4296 100644 --- a/jerry-core/ecma/operations/ecma-conversion.c +++ b/jerry-core/ecma/operations/ecma-conversion.c @@ -29,6 +29,7 @@ #include "ecma-objects.h" #include "ecma-objects-general.h" #include "ecma-string-object.h" +#include "ecma-symbol-object.h" #include "ecma-try-catch-macro.h" #include "jrt-libc-includes.h" @@ -224,7 +225,7 @@ ecma_op_to_boolean (ecma_value_t value) /**< ecma value */ return !ecma_string_is_empty (str_p); } - JERRY_ASSERT (ecma_is_value_object (value)); + JERRY_ASSERT (ecma_is_value_object (value) || ECMA_ASSERT_VALUE_IS_SYMBOL (value)); return true; } /* ecma_op_to_boolean */ @@ -258,6 +259,12 @@ ecma_op_to_number (ecma_value_t value) /**< ecma value */ ecma_string_t *str_p = ecma_get_string_from_value (value); return ecma_make_number_value (ecma_string_to_number (str_p)); } +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + if (ecma_is_value_symbol (value)) + { + return ecma_raise_type_error (ECMA_ERR_MSG ("Cannot convert a Symbol value to a number.")); + } +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ if (ecma_is_value_object (value)) { @@ -359,6 +366,85 @@ ecma_get_number (ecma_value_t value, /**< ecma value*/ return ECMA_VALUE_EMPTY; } /* ecma_get_number */ +/** + * ToString operation helper function. + * + * See also: + * ECMA-262 v5, 9.8 + * + * @return NULL - if the conversion fails + * ecma-string - otherwise + */ +static ecma_string_t * +ecma_to_op_string_helper (ecma_value_t value) /**< ecma value */ +{ + ecma_check_value_type_is_spec_defined (value); + + if (JERRY_UNLIKELY (ecma_is_value_object (value))) + { + ecma_value_t prim_value = ecma_op_to_primitive (value, ECMA_PREFERRED_TYPE_STRING); + + if (ECMA_IS_VALUE_ERROR (prim_value)) + { + return NULL; + } + + ecma_string_t *ret_string_p = ecma_to_op_string_helper (prim_value); + + ecma_free_value (prim_value); + + return ret_string_p; + } + + if (ecma_is_value_string (value)) + { + ecma_string_t *res_p = ecma_get_string_from_value (value); + ecma_ref_ecma_string (res_p); + return res_p; + } + else if (ecma_is_value_integer_number (value)) + { + ecma_integer_value_t num = ecma_get_integer_from_value (value); + + if (num < 0) + { + return ecma_new_ecma_string_from_number ((ecma_number_t) num); + } + else + { + return ecma_new_ecma_string_from_uint32 ((uint32_t) num); + } + } + else if (ecma_is_value_float_number (value)) + { + ecma_number_t num = ecma_get_float_from_value (value); + return ecma_new_ecma_string_from_number (num); + } + else if (ecma_is_value_undefined (value)) + { + return ecma_get_magic_string (LIT_MAGIC_STRING_UNDEFINED); + } + else if (ecma_is_value_null (value)) + { + return ecma_get_magic_string (LIT_MAGIC_STRING_NULL); + } +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + else if (ecma_is_value_symbol (value)) + { + ecma_raise_type_error (ECMA_ERR_MSG ("Cannot convert a Symbol value to a string.")); + return NULL; + } +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ + JERRY_ASSERT (ecma_is_value_boolean (value)); + + if (ecma_is_value_true (value)) + { + return ecma_get_magic_string (LIT_MAGIC_STRING_TRUE); + } + + return ecma_get_magic_string (LIT_MAGIC_STRING_FALSE); +} /* ecma_to_op_string_helper */ + /** * ToString operation. * @@ -373,73 +459,40 @@ ecma_op_to_string (ecma_value_t value) /**< ecma value */ { ecma_check_value_type_is_spec_defined (value); - if (JERRY_UNLIKELY (ecma_is_value_object (value))) + ecma_string_t *string_p = ecma_to_op_string_helper (value); + + if (JERRY_UNLIKELY (string_p == NULL)) { - ecma_value_t ret_value = ECMA_VALUE_EMPTY; - - ECMA_TRY_CATCH (prim_value, - ecma_op_to_primitive (value, ECMA_PREFERRED_TYPE_STRING), - ret_value); - - ret_value = ecma_op_to_string (prim_value); - - ECMA_FINALIZE (prim_value); - - return ret_value; + /* Note: At this point the error has already been thrown. */ + return ECMA_VALUE_ERROR; } - else - { - ecma_string_t *res_p = NULL; - if (ecma_is_value_string (value)) - { - res_p = ecma_get_string_from_value (value); - ecma_ref_ecma_string (res_p); - } - else if (ecma_is_value_integer_number (value)) - { - ecma_integer_value_t num = ecma_get_integer_from_value (value); - - if (num < 0) - { - res_p = ecma_new_ecma_string_from_number ((ecma_number_t) num); - } - else - { - res_p = ecma_new_ecma_string_from_uint32 ((uint32_t) num); - } - } - else if (ecma_is_value_float_number (value)) - { - ecma_number_t num = ecma_get_float_from_value (value); - res_p = ecma_new_ecma_string_from_number (num); - } - else if (ecma_is_value_undefined (value)) - { - res_p = ecma_get_magic_string (LIT_MAGIC_STRING_UNDEFINED); - } - else if (ecma_is_value_null (value)) - { - res_p = ecma_get_magic_string (LIT_MAGIC_STRING_NULL); - } - else - { - JERRY_ASSERT (ecma_is_value_boolean (value)); - - if (ecma_is_value_true (value)) - { - res_p = ecma_get_magic_string (LIT_MAGIC_STRING_TRUE); - } - else - { - res_p = ecma_get_magic_string (LIT_MAGIC_STRING_FALSE); - } - } - - return ecma_make_string_value (res_p); - } + return ecma_make_string_value (string_p); } /* ecma_op_to_string */ +/** + * ToPropertyName operation. + * + * @return NULL - if the conversion fails + * ecma-string - otherwise + */ +ecma_string_t * +ecma_op_to_prop_name (ecma_value_t value) /**< ecma value */ +{ + ecma_check_value_type_is_spec_defined (value); + +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + if (ecma_is_value_symbol (value)) + { + ecma_string_t *symbol_p = ecma_get_symbol_from_value (value); + ecma_ref_ecma_string (symbol_p); + return symbol_p; + } +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ + + return ecma_to_op_string_helper (value); +} /* ecma_op_to_prop_name */ + /** * ToObject operation. * @@ -466,6 +519,12 @@ ecma_op_to_object (ecma_value_t value) /**< ecma value */ { return ecma_copy_value (value); } +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + else if (ecma_is_value_symbol (value)) + { + return ecma_op_create_symbol_object (value); + } +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ else { if (ecma_is_value_undefined (value) diff --git a/jerry-core/ecma/operations/ecma-conversion.h b/jerry-core/ecma/operations/ecma-conversion.h index ce00ffe6d..6b2fdc48e 100644 --- a/jerry-core/ecma/operations/ecma-conversion.h +++ b/jerry-core/ecma/operations/ecma-conversion.h @@ -44,6 +44,7 @@ bool ecma_op_to_boolean (ecma_value_t value); ecma_value_t ecma_op_to_number (ecma_value_t value); ecma_value_t ecma_get_number (ecma_value_t value, ecma_number_t *number_p); ecma_value_t ecma_op_to_string (ecma_value_t value); +ecma_string_t *ecma_op_to_prop_name (ecma_value_t value); ecma_value_t ecma_op_to_object (ecma_value_t value); ecma_object_t *ecma_op_from_property_descriptor (const ecma_property_descriptor_t *src_prop_desc_p); diff --git a/jerry-core/ecma/operations/ecma-get-put-value.c b/jerry-core/ecma/operations/ecma-get-put-value.c index 4f4604d75..826193bd5 100644 --- a/jerry-core/ecma/operations/ecma-get-put-value.c +++ b/jerry-core/ecma/operations/ecma-get-put-value.c @@ -96,6 +96,7 @@ ecma_op_get_value_object_base (ecma_value_t base_value, /**< base value */ JERRY_ASSERT (ecma_is_value_boolean (base_value) || ecma_is_value_number (base_value) + || ECMA_ASSERT_VALUE_IS_SYMBOL (base_value) || ecma_is_value_string (base_value)); ecma_value_t object_base = ecma_op_to_object (base_value); diff --git a/jerry-core/ecma/operations/ecma-objects.c b/jerry-core/ecma/operations/ecma-objects.c index 5e30fe049..4ede816a8 100644 --- a/jerry-core/ecma/operations/ecma-objects.c +++ b/jerry-core/ecma/operations/ecma-objects.c @@ -1350,6 +1350,9 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ const bool is_enumerable_only = (const bool) (opts & ECMA_LIST_ENUMERABLE); const bool is_array_indices_only = (const bool) (opts & ECMA_LIST_ARRAY_INDICES); const bool is_with_prototype_chain = (const bool) (opts & ECMA_LIST_PROTOTYPE); +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + const bool is_symbols_only = (const bool) (opts & ECMA_LIST_SYMBOLS); +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ const size_t bitmap_row_size = sizeof (uint32_t) * JERRY_BITSINBYTE; const size_t names_hashes_bitmap_size = ECMA_OBJECT_HASH_BITMAP_SIZE / bitmap_row_size; @@ -1367,82 +1370,90 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ ecma_collection_header_t *prop_names_p = ecma_new_values_collection (); - if (obj_is_builtin) +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + if (JERRY_LIKELY (!is_symbols_only)) { - ecma_builtin_list_lazy_property_names (obj_p, - is_enumerable_only, - prop_names_p, - skipped_non_enumerable_p); - } - else - { - switch (type) +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ + + if (obj_is_builtin) { - case ECMA_OBJECT_TYPE_PSEUDO_ARRAY: + ecma_builtin_list_lazy_property_names (obj_p, + is_enumerable_only, + prop_names_p, + skipped_non_enumerable_p); + } + else + { + switch (type) { -#ifndef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN - if (ecma_is_typedarray (ecma_make_object_value (obj_p))) + case ECMA_OBJECT_TYPE_PSEUDO_ARRAY: { - ecma_op_typedarray_list_lazy_property_names (obj_p, prop_names_p); + #ifndef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN + if (ecma_is_typedarray (ecma_make_object_value (obj_p))) + { + ecma_op_typedarray_list_lazy_property_names (obj_p, prop_names_p); + } + #endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */ + break; } -#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */ - break; - } - case ECMA_OBJECT_TYPE_FUNCTION: -#ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION - case ECMA_OBJECT_TYPE_ARROW_FUNCTION: -#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */ - { - ecma_op_function_list_lazy_property_names (obj_p, - is_enumerable_only, - prop_names_p, - skipped_non_enumerable_p); - break; - } - case ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION: - { - ecma_op_external_function_list_lazy_property_names (is_enumerable_only, - prop_names_p, - skipped_non_enumerable_p); - break; - } - case ECMA_OBJECT_TYPE_BOUND_FUNCTION: - { - ecma_op_bound_function_list_lazy_property_names (is_enumerable_only, - prop_names_p, - skipped_non_enumerable_p); - break; - } - case ECMA_OBJECT_TYPE_CLASS: - { - ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; - - if (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_STRING_UL) + case ECMA_OBJECT_TYPE_FUNCTION: + #ifndef CONFIG_DISABLE_ES2015_ARROW_FUNCTION + case ECMA_OBJECT_TYPE_ARROW_FUNCTION: + #endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */ { - ecma_op_string_list_lazy_property_names (obj_p, - is_enumerable_only, - prop_names_p, - skipped_non_enumerable_p); + ecma_op_function_list_lazy_property_names (obj_p, + is_enumerable_only, + prop_names_p, + skipped_non_enumerable_p); + break; } + case ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION: + { + ecma_op_external_function_list_lazy_property_names (is_enumerable_only, + prop_names_p, + skipped_non_enumerable_p); + break; + } + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + { + ecma_op_bound_function_list_lazy_property_names (is_enumerable_only, + prop_names_p, + skipped_non_enumerable_p); + break; + } + case ECMA_OBJECT_TYPE_CLASS: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; - break; - } - case ECMA_OBJECT_TYPE_ARRAY: - { - ecma_op_array_list_lazy_property_names (obj_p, - is_enumerable_only, - prop_names_p, - skipped_non_enumerable_p); - break; - } - default: - { - JERRY_ASSERT (type == ECMA_OBJECT_TYPE_GENERAL); + if (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_STRING_UL) + { + ecma_op_string_list_lazy_property_names (obj_p, + is_enumerable_only, + prop_names_p, + skipped_non_enumerable_p); + } - break; + break; + } + case ECMA_OBJECT_TYPE_ARRAY: + { + ecma_op_array_list_lazy_property_names (obj_p, + is_enumerable_only, + prop_names_p, + skipped_non_enumerable_p); + break; + } + default: + { + JERRY_ASSERT (type == ECMA_OBJECT_TYPE_GENERAL); + + break; + } } } +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN } +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ ecma_value_t *ecma_value_p = ecma_collection_iterator_init (prop_names_p); @@ -1453,6 +1464,12 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ while (ecma_value_p != NULL) { ecma_string_t *name_p = ecma_get_string_from_value (*ecma_value_p); + +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + /* Symbols are never lazy listed */ + JERRY_ASSERT (!ecma_prop_name_is_symbol (name_p)); +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ + ecma_value_p = ecma_collection_iterator_next (ecma_value_p); uint8_t hash = (uint8_t) ecma_string_hash (name_p); @@ -1498,6 +1515,19 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ if (!(is_enumerable_only && !ecma_is_property_enumerable (*property_p))) { +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + /* If is_symbols_only is false and prop_name is symbol + we should skip the current property e.g. for-in. + + Also if is_symbols_only is true and prop_name is not symbol + we should skip the current property e.g. Object.getOwnPropertySymbols. */ + if (JERRY_UNLIKELY (is_symbols_only != ecma_prop_name_is_symbol (name_p))) + { + ecma_deref_ecma_string (name_p); + continue; + } +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ + uint8_t hash = (uint8_t) ecma_string_hash (name_p); uint32_t bitmap_row = (uint32_t) (hash / bitmap_row_size); uint32_t bitmap_column = (uint32_t) (hash % bitmap_row_size); @@ -1510,7 +1540,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ while (ecma_value_p != NULL) { - ecma_string_t *current_name_p = ecma_get_string_from_value (*ecma_value_p); + ecma_string_t *current_name_p = ecma_get_prop_name_from_value (*ecma_value_p); ecma_value_p = ecma_collection_iterator_next (ecma_value_p); if (ecma_compare_ecma_strings (name_p, current_name_p)) @@ -1526,7 +1556,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ own_names_hashes_bitmap[bitmap_row] |= (1u << bitmap_column); ecma_append_to_values_collection (prop_names_p, - ecma_make_string_value (name_p), + ecma_make_prop_name_value (name_p), 0); } } @@ -1535,7 +1565,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ JERRY_ASSERT (is_enumerable_only && !ecma_is_property_enumerable (*property_p)); ecma_append_to_values_collection (skipped_non_enumerable_p, - ecma_make_string_value (name_p), + ecma_make_prop_name_value (name_p), 0); } @@ -1551,7 +1581,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ while (ecma_value_p != NULL) { - ecma_string_t *name_p = ecma_get_string_from_value (*ecma_value_p); + ecma_string_t *name_p = ecma_get_prop_name_from_value (*ecma_value_p); ecma_value_p = ecma_collection_iterator_next (ecma_value_p); uint32_t index = ecma_string_get_array_index (name_p); @@ -1580,7 +1610,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ while (ecma_value_p != NULL) { - ecma_string_t *name_p = ecma_get_string_from_value (*ecma_value_p); + ecma_string_t *name_p = ecma_get_prop_name_from_value (*ecma_value_p); ecma_value_p = ecma_collection_iterator_next (ecma_value_p); uint32_t index = ecma_string_get_array_index (name_p); @@ -1670,7 +1700,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ while (ecma_value_p != NULL) { - ecma_string_t *current_name_p = ecma_get_string_from_value (*ecma_value_p); + ecma_string_t *current_name_p = ecma_get_prop_name_from_value (*ecma_value_p); ecma_value_p = ecma_collection_iterator_next (ecma_value_p); if (ecma_compare_ecma_strings (name_p, current_name_p)) @@ -1687,7 +1717,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ while (ecma_value_p != NULL) { - ecma_string_t *current_name_p = ecma_get_string_from_value (*ecma_value_p); + ecma_string_t *current_name_p = ecma_get_prop_name_from_value (*ecma_value_p); ecma_value_p = ecma_collection_iterator_next (ecma_value_p); if (ecma_compare_ecma_strings (name_p, current_name_p)) @@ -1702,7 +1732,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ { JERRY_ASSERT ((names_hashes_bitmap[bitmap_row] & (1u << bitmap_column)) != 0); - ecma_append_to_values_collection (ret_p, ecma_make_string_value (names_p[i]), 0); + ecma_append_to_values_collection (ret_p, ecma_make_prop_name_value (names_p[i]), 0); } ecma_deref_ecma_string (name_p); diff --git a/jerry-core/ecma/operations/ecma-symbol-object.c b/jerry-core/ecma/operations/ecma-symbol-object.c new file mode 100644 index 000000000..0149e7a32 --- /dev/null +++ b/jerry-core/ecma/operations/ecma-symbol-object.c @@ -0,0 +1,186 @@ +/* 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. + */ + +#include "ecma-alloc.h" +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-objects.h" +#include "ecma-objects-general.h" +#include "ecma-symbol-object.h" + +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmasymbolobject ECMA Symbol object related routines + * @{ + */ + +/** + * Symbol creation operation. + * + * See also: ECMA-262 v6, 6.1.5.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_create_symbol (const ecma_value_t *arguments_list_p, /**< list of arguments */ + ecma_length_t arguments_list_len) /**< length of the arguments' list */ +{ + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + ecma_value_t string_desc; + + /* 1-3. */ + if (arguments_list_len == 0) + { + string_desc = ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + } + else + { + string_desc = ecma_op_to_string (arguments_list_p[0]); + + /* 4. */ + if (ECMA_IS_VALUE_ERROR (string_desc)) + { + return string_desc; + } + + JERRY_ASSERT (ecma_is_value_string (string_desc)); + } + + /* 5. */ + return ecma_make_symbol_value (ecma_new_symbol_from_descriptor_string (string_desc)); +} /* ecma_op_create_symbol */ + +/** + * Symbol object creation operation. + * + * See also: ECMA-262 v6, 19.4.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_create_symbol_object (const ecma_value_t value) /**< symbol value */ +{ + JERRY_ASSERT (ecma_is_value_symbol (value)); + +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_SYMBOL_PROTOTYPE); +#else /* CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ + ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ + + ecma_object_t *object_p = ecma_create_object (prototype_obj_p, + sizeof (ecma_extended_object_t), + ECMA_OBJECT_TYPE_CLASS); + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + ext_object_p->u.class_prop.class_id = LIT_MAGIC_STRING_SYMBOL_UL; + ext_object_p->u.class_prop.u.value = ecma_copy_value (value); + + return ecma_make_object_value (object_p); +} /* ecma_op_create_symbol_object */ + +/** + * Get the symbol descriptor ecma-string from an ecma-symbol + * + * @return pointer to ecma-string descriptor + */ +ecma_string_t * +ecma_get_symbol_description (ecma_string_t *symbol_p) /**< ecma-symbol */ +{ + JERRY_ASSERT (symbol_p != NULL); + JERRY_ASSERT (ecma_prop_name_is_symbol (symbol_p)); + + return ecma_get_string_from_value (symbol_p->u.symbol_descriptor); +} /* ecma_get_symbol_description */ + +/** + * Get the descriptive string of the Symbol. + * + * See also: ECMA-262 v6, 19.4.3.2.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_get_symbol_descriptive_string (ecma_value_t symbol_value) /**< symbol to stringify */ +{ + /* 1. */ + JERRY_ASSERT (ecma_is_value_symbol (symbol_value)); + + /* 2 - 3. */ + ecma_string_t *symbol_p = ecma_get_symbol_from_value (symbol_value); + ecma_string_t *string_desc_p = ecma_get_symbol_description (symbol_p); + + /* 5. */ + ecma_string_t *concat_p = ecma_concat_ecma_strings (ecma_get_magic_string (LIT_MAGIC_STRING_SYMBOL_LEFT_PAREN_UL), + string_desc_p); + + ecma_string_t *final_str_p = ecma_append_magic_string_to_string (concat_p, LIT_MAGIC_STRING_RIGHT_PAREN); + + return ecma_make_string_value (final_str_p); +} /* ecma_get_symbol_descriptive_string */ + +/** + * Helper for Symbol.prototype.{toString, valueOf} routines + * + * See also: 19.4.3.2, 19.4.3.3 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_symbol_to_string_helper (ecma_value_t this_arg, /**< this argument value */ + bool is_to_string) /**< true - perform the 'toString' routine steps + * false - perform the 'valueOf' routine steps */ +{ + if (ecma_is_value_symbol (this_arg)) + { + return is_to_string ? ecma_get_symbol_descriptive_string (this_arg) : ecma_copy_value (this_arg); + } + + if (ecma_is_value_object (this_arg)) + { + ecma_object_t *object_p = ecma_get_object_from_value (this_arg); + + if (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_CLASS) + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + if (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_SYMBOL_UL) + { + return (is_to_string ? ecma_get_symbol_descriptive_string (ext_object_p->u.class_prop.u.value) + : ecma_copy_value (ext_object_p->u.class_prop.u.value)); + } + } + } + + return ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is must be a Symbol.")); +} /* ecma_symbol_to_string_helper */ + +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ + +/** + * @} + * @} + */ diff --git a/jerry-core/ecma/operations/ecma-symbol-object.h b/jerry-core/ecma/operations/ecma-symbol-object.h new file mode 100644 index 000000000..71226d902 --- /dev/null +++ b/jerry-core/ecma/operations/ecma-symbol-object.h @@ -0,0 +1,53 @@ +/* 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. + */ + +#ifndef ECMA_SYMBOL_H +#define ECMA_SYMBOL_H + +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmasymbolobject ECMA Symbol object related routines + * @{ + */ + +ecma_value_t +ecma_op_create_symbol (const ecma_value_t *arguments_list_p, ecma_length_t arguments_list_len); + +ecma_value_t +ecma_op_create_symbol_object (const ecma_value_t value); + +bool +ecma_prop_name_is_symbol (ecma_string_t *string_p); + +ecma_string_t * +ecma_get_symbol_description (ecma_string_t *symbol_p); + +ecma_value_t +ecma_symbol_to_string_helper (ecma_value_t this_arg, bool is_to_string); + +ecma_value_t +ecma_get_symbol_descriptive_string (ecma_value_t symbol_value); + +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ +/** + * @} + * @} + */ + +#endif /* !ECMA_SYMBOL_H */ diff --git a/jerry-core/jcontext/jcontext.h b/jerry-core/jcontext/jcontext.h index baa866b53..7a0dfb1b3 100644 --- a/jerry-core/jcontext/jcontext.h +++ b/jerry-core/jcontext/jcontext.h @@ -97,6 +97,9 @@ struct jerry_context_t 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 */ ecma_lit_storage_item_t *string_list_first_p; /**< first item of the literal string list */ +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + ecma_lit_storage_item_t *symbol_list_first_p; /**< first item of the global symbol list */ +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ ecma_lit_storage_item_t *number_list_first_p; /**< first item of the literal number list */ ecma_object_t *ecma_global_lex_env_p; /**< global lexical environment */ vm_frame_ctx_t *vm_top_context_p; /**< top (current) interpreter context */ diff --git a/jerry-core/lit/lit-magic-strings.h b/jerry-core/lit/lit-magic-strings.h index 1e40636a3..eab6c7069 100644 --- a/jerry-core/lit/lit-magic-strings.h +++ b/jerry-core/lit/lit-magic-strings.h @@ -46,6 +46,18 @@ typedef enum LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_INDEX, /**< [[Index]] property */ LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_VALUE, /**< [[Values]] property */ LIT_INTERNAL_MAGIC_STRING_PROMISE_PROPERTY_REMAINING_ELEMENT, /**< [[RemainingElement]] property */ + /* List of well known symbols */ + LIT_GLOBAL_SYMBOL_HAS_INSTANCE, /**< @@hasInstance well known symbol */ + LIT_GLOBAL_SYMBOL_IS_CONCAT_SPREADABLE, /**< @@isConcatSpreadable well known symbol */ + LIT_GLOBAL_SYMBOL_ITERATOR, /**< @@iterator 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 */ + LIT_GLOBAL_SYMBOL_SPECIES, /**< @@species well known symbol */ + LIT_GLOBAL_SYMBOL_SPLIT, /**< @@split 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_UNSCOPABLES, /**< @@unscopables well known symbol */ 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. */ LIT_INTERNAL_MAGIC_STRING_DELETED = LIT_GC_MARK_REQUIRED_MAGIC_STRING__COUNT, /**< special value for diff --git a/jerry-core/lit/lit-magic-strings.inc.h b/jerry-core/lit/lit-magic-strings.inc.h index 845bddd1f..77e25e4d2 100644 --- a/jerry-core/lit/lit-magic-strings.inc.h +++ b/jerry-core/lit/lit-magic-strings.inc.h @@ -19,6 +19,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING__EMPTY, "") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SPACE_CHAR, " ") +#if !defined (CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_RIGHT_PAREN, ")") +#endif LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_COMMA_CHAR, ",") #if !defined (CONFIG_DISABLE_REGEXP_BUILTIN) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SLASH_CHAR, "/") @@ -55,6 +58,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ALL, "all") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_COS, "cos") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_EXP, "exp") #endif +#if !defined (CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FOR, "for") +#endif LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET, "get") #if !defined (CONFIG_DISABLE_ES2015_MAP_BUILTIN) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_HAS, "has") @@ -187,7 +193,8 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_INDEX, "index") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_INPUT, "input") #endif LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_NAN, "isNaN") -#if !defined (CONFIG_DISABLE_REGEXP_BUILTIN) && !defined (CONFIG_DISABLE_STRING_BUILTIN) +#if !defined (CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN) \ +|| !defined (CONFIG_DISABLE_REGEXP_BUILTIN) && !defined (CONFIG_DISABLE_STRING_BUILTIN) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MATCH, "match") #endif #if !defined (CONFIG_DISABLE_DATE_BUILTIN) \ @@ -205,7 +212,8 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SHIFT, "shift") || !defined (CONFIG_DISABLE_STRING_BUILTIN) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SLICE, "slice") #endif -#if !defined (CONFIG_DISABLE_STRING_BUILTIN) +#if !defined (CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN) \ +|| !defined (CONFIG_DISABLE_STRING_BUILTIN) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SPLIT, "split") #endif LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_VALUE, "value") @@ -216,6 +224,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_NUMBER_UL, "Number") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_OBJECT_UL, "Object") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REGEXP_UL, "RegExp") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_STRING_UL, "String") +#if !defined (CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SYMBOL_UL, "Symbol") +#endif #if !defined (CONFIG_DISABLE_ES2015_BUILTIN) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ASSIGN, "assign") #endif @@ -252,6 +263,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GLOBAL, "global") #if !defined (CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_VIEW_UL, "isView") #endif +#if !defined (CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_KEY_FOR, "keyFor") +#endif LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LENGTH, "length") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_NUMBER, "number") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_OBJECT, "object") @@ -265,7 +279,8 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REDUCE, "reduce") #if !defined (CONFIG_DISABLE_ES2015_PROMISE_BUILTIN) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REJECT, "reject") #endif -#if !defined (CONFIG_DISABLE_REGEXP_BUILTIN) && !defined (CONFIG_DISABLE_STRING_BUILTIN) +#if !defined (CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN) \ +|| !defined (CONFIG_DISABLE_REGEXP_BUILTIN) && !defined (CONFIG_DISABLE_STRING_BUILTIN) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SEARCH, "search") #endif #if !defined (CONFIG_DISABLE_REGEXP_BUILTIN) @@ -278,6 +293,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_STRING, "string") #if !defined (CONFIG_DISABLE_ANNEXB_BUILTIN) && !defined (CONFIG_DISABLE_STRING_BUILTIN) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SUBSTR, "substr") #endif +#if !defined (CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SYMBOL, "symbol") +#endif #if !defined (CONFIG_DISABLE_DATE_BUILTIN) \ || !defined (CONFIG_DISABLE_JSON_BUILTIN) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_JSON_UL, "toJSON") @@ -289,6 +307,10 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PROMISE_UL, "Promise") #if !defined (CONFIG_DISABLE_MATH_BUILTIN) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SQRT1_2_U, "SQRT1_2") #endif +#if !defined (CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SYMBOL_LEFT_PAREN_UL, "Symbol(") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SYMBOL_DOT_UL, "Symbol.") +#endif LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BOOLEAN, "boolean") #if !defined (CONFIG_DISABLE_ANNEXB_BUILTIN) && !defined (CONFIG_DISABLE_REGEXP_BUILTIN) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_COMPILE, "compile") @@ -312,7 +334,8 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_INDEX_OF_UL, "indexOf") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_ARRAY_UL, "isArray") #endif LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_MESSAGE, "message") -#if !defined (CONFIG_DISABLE_REGEXP_BUILTIN) && !defined (CONFIG_DISABLE_STRING_BUILTIN) +#if !defined (CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN) \ +|| !defined (CONFIG_DISABLE_REGEXP_BUILTIN) && !defined (CONFIG_DISABLE_STRING_BUILTIN) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REPLACE, "replace") #endif #if !defined (CONFIG_DISABLE_ES2015_PROMISE_BUILTIN) @@ -329,6 +352,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_TIME_UL, "setTime") #if !defined (CONFIG_DISABLE_ANNEXB_BUILTIN) && !defined (CONFIG_DISABLE_DATE_BUILTIN) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_YEAR_UL, "setYear") #endif +#if !defined (CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SPECIES, "species") +#endif #if !defined (CONFIG_DISABLE_NUMBER_BUILTIN) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_FIXED_UL, "toFixed") #endif @@ -349,6 +375,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_MONTH_UL, "getMonth") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_FINITE, "isFinite") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_FROZEN_UL, "isFrozen") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_SEALED_UL, "isSealed") +#if !defined (CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ITERATOR, "iterator") +#endif LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PARSE_INT, "parseInt") #if !defined (CONFIG_DISABLE_DATE_BUILTIN) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_HOURS_UL, "setHours") @@ -443,6 +472,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_FULL_YEAR_UL, "getFullYear") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UTC_HOURS_UL, "getUTCHours") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UTC_MONTH_UL, "getUTCMonth") #endif +#if !defined (CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_HAS_INSTANCE, "hasInstance") +#endif #if !defined (CONFIG_DISABLE_ARRAY_BUILTIN) \ || !defined (CONFIG_DISABLE_STRING_BUILTIN) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LAST_INDEX_OF_UL, "lastIndexOf") @@ -468,12 +500,19 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_LOWER_CASE_UL, "toLowerCase") #if !defined (CONFIG_DISABLE_NUMBER_BUILTIN) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_PRECISION_UL, "toPrecision") #endif +#if !defined (CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_PRIMITIVE, "toPrimitive") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_STRING_TAG, "toStringTag") +#endif #if !defined (CONFIG_DISABLE_DATE_BUILTIN) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_UTC_STRING_UL, "toUTCString") #endif #if !defined (CONFIG_DISABLE_STRING_BUILTIN) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_UPPER_CASE_UL, "toUpperCase") #endif +#if !defined (CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_UNSCOPABLES, "unscopables") +#endif #if !defined (CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FLOAT32_ARRAY_UL, "Float32Array") #endif @@ -548,12 +587,20 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DECODE_URI_COMPONENT, "decodeURIComponent LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ENCODE_URI_COMPONENT, "encodeURIComponent") #if !defined (CONFIG_DISABLE_DATE_BUILTIN) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UTC_MILLISECONDS_UL, "getUTCMilliseconds") +#endif +#if !defined (CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_CONCAT_SPREADABLE, "isConcatSpreadable") +#endif +#if !defined (CONFIG_DISABLE_DATE_BUILTIN) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UTC_MILLISECONDS_UL, "setUTCMilliseconds") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_LOCALE_DATE_STRING_UL, "toLocaleDateString") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_LOCALE_TIME_STRING_UL, "toLocaleTimeString") #endif LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_OWN_PROPERTY_NAMES_UL, "getOwnPropertyNames") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PROPERTY_IS_ENUMERABLE_UL, "propertyIsEnumerable") +#if !defined (CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN) +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_OWN_PROPERTY_SYMBOLS_UL, "getOwnPropertySymbols") +#endif LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTOR_UL, "getOwnPropertyDescriptor") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING__FUNCTION_TO_STRING, "function(){/* ecmascript */}") @@ -650,7 +697,11 @@ LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (17, LIT_MAGIC_STRING_PREVENT_EXTENSIONS LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (18, LIT_MAGIC_STRING_DECODE_URI_COMPONENT) LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (19, LIT_MAGIC_STRING_GET_OWN_PROPERTY_NAMES_UL) LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (20, LIT_MAGIC_STRING_PROPERTY_IS_ENUMERABLE_UL) +#if !defined (CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN) +LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (21, LIT_MAGIC_STRING_GET_OWN_PROPERTY_SYMBOLS_UL) +#else LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (21, LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTOR_UL) +#endif LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (22, LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTOR_UL) LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (23, LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTOR_UL) LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (24, LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTOR_UL) diff --git a/jerry-core/lit/lit-magic-strings.ini b/jerry-core/lit/lit-magic-strings.ini index f1e458737..9c296bad5 100644 --- a/jerry-core/lit/lit-magic-strings.ini +++ b/jerry-core/lit/lit-magic-strings.ini @@ -24,6 +24,7 @@ LIT_MAGIC_STRING__EMPTY = "" LIT_MAGIC_STRING_SPACE_CHAR = " " +LIT_MAGIC_STRING_RIGHT_PAREN = ")" LIT_MAGIC_STRING_COMMA_CHAR = "," LIT_MAGIC_STRING_SLASH_CHAR = "/" LIT_MAGIC_STRING_COLON_CHAR = ":" @@ -40,6 +41,7 @@ LIT_MAGIC_STRING_ABS = "abs" LIT_MAGIC_STRING_ALL = "all" LIT_MAGIC_STRING_COS = "cos" LIT_MAGIC_STRING_EXP = "exp" +LIT_MAGIC_STRING_FOR = "for" LIT_MAGIC_STRING_GET = "get" LIT_MAGIC_STRING_HAS = "has" LIT_MAGIC_STRING_LOG = "log" @@ -110,6 +112,7 @@ LIT_MAGIC_STRING_NUMBER_UL = "Number" LIT_MAGIC_STRING_OBJECT_UL = "Object" LIT_MAGIC_STRING_REGEXP_UL = "RegExp" LIT_MAGIC_STRING_STRING_UL = "String" +LIT_MAGIC_STRING_SYMBOL_UL = "Symbol" LIT_MAGIC_STRING_ASSIGN = "assign" LIT_MAGIC_STRING_BUFFER = "buffer" LIT_MAGIC_STRING_CALLEE = "callee" @@ -124,6 +127,7 @@ LIT_MAGIC_STRING_FREEZE = "freeze" LIT_MAGIC_STRING_GET_DAY_UL = "getDay" LIT_MAGIC_STRING_GLOBAL = "global" LIT_MAGIC_STRING_IS_VIEW_UL = "isView" +LIT_MAGIC_STRING_KEY_FOR = "keyFor" LIT_MAGIC_STRING_LENGTH = "length" LIT_MAGIC_STRING_NUMBER = "number" LIT_MAGIC_STRING_OBJECT = "object" @@ -134,11 +138,14 @@ LIT_MAGIC_STRING_SEARCH = "search" LIT_MAGIC_STRING_SOURCE = "source" LIT_MAGIC_STRING_SPLICE = "splice" LIT_MAGIC_STRING_STRING = "string" +LIT_MAGIC_STRING_SYMBOL = "symbol" LIT_MAGIC_STRING_SUBSTR = "substr" LIT_MAGIC_STRING_TO_JSON_UL = "toJSON" LIT_MAGIC_STRING_BOOLEAN_UL = "Boolean" LIT_MAGIC_STRING_PROMISE_UL = "Promise" LIT_MAGIC_STRING_SQRT1_2_U = "SQRT1_2" +LIT_MAGIC_STRING_SYMBOL_LEFT_PAREN_UL = "Symbol(" +LIT_MAGIC_STRING_SYMBOL_DOT_UL = "Symbol." LIT_MAGIC_STRING_BOOLEAN = "boolean" LIT_MAGIC_STRING_COMPILE = "compile" LIT_MAGIC_STRING_FOR_EACH_UL = "forEach" @@ -154,6 +161,7 @@ LIT_MAGIC_STRING_REVERSE = "reverse" LIT_MAGIC_STRING_SET_DATE_UL = "setDate" LIT_MAGIC_STRING_SET_TIME_UL = "setTime" LIT_MAGIC_STRING_SET_YEAR_UL = "setYear" +LIT_MAGIC_STRING_SPECIES = "species" LIT_MAGIC_STRING_TO_FIXED_UL = "toFixed" LIT_MAGIC_STRING_UNSHIFT = "unshift" LIT_MAGIC_STRING_VALUE_OF_UL = "valueOf" @@ -166,6 +174,7 @@ LIT_MAGIC_STRING_GET_MONTH_UL = "getMonth" LIT_MAGIC_STRING_IS_FINITE = "isFinite" LIT_MAGIC_STRING_IS_FROZEN_UL = "isFrozen" LIT_MAGIC_STRING_IS_SEALED_UL = "isSealed" +LIT_MAGIC_STRING_ITERATOR = "iterator" LIT_MAGIC_STRING_PARSE_INT = "parseInt" LIT_MAGIC_STRING_SET_HOURS_UL = "setHours" LIT_MAGIC_STRING_SET_MONTH_UL = "setMonth" @@ -216,6 +225,7 @@ LIT_MAGIC_STRING_CONSTRUCTOR = "constructor" LIT_MAGIC_STRING_GET_FULL_YEAR_UL = "getFullYear" LIT_MAGIC_STRING_GET_UTC_HOURS_UL = "getUTCHours" LIT_MAGIC_STRING_GET_UTC_MONTH_UL = "getUTCMonth" +LIT_MAGIC_STRING_HAS_INSTANCE = "hasInstance" LIT_MAGIC_STRING_LAST_INDEX_OF_UL = "lastIndexOf" LIT_MAGIC_STRING_REDUCE_RIGHT_UL = "reduceRight" LIT_MAGIC_STRING_SET_FULL_YEAR_UL = "setFullYear" @@ -225,8 +235,11 @@ LIT_MAGIC_STRING_TO_GMT_STRING_UL = "toGMTString" LIT_MAGIC_STRING_TO_ISO_STRING_UL = "toISOString" LIT_MAGIC_STRING_TO_LOWER_CASE_UL = "toLowerCase" LIT_MAGIC_STRING_TO_PRECISION_UL = "toPrecision" +LIT_MAGIC_STRING_TO_PRIMITIVE = "toPrimitive" +LIT_MAGIC_STRING_TO_STRING_TAG = "toStringTag" LIT_MAGIC_STRING_TO_UTC_STRING_UL = "toUTCString" LIT_MAGIC_STRING_TO_UPPER_CASE_UL = "toUpperCase" +LIT_MAGIC_STRING_UNSCOPABLES = "unscopables" LIT_MAGIC_STRING_FLOAT32_ARRAY_UL = "Float32Array" LIT_MAGIC_STRING_FLOAT64_ARRAY_UL = "Float64Array" LIT_MAGIC_STRING_INVALID_DATE_UL = "Invalid Date" @@ -264,10 +277,12 @@ LIT_MAGIC_STRING_TO_LOCALE_UPPER_CASE_UL = "toLocaleUpperCase" LIT_MAGIC_STRING_DECODE_URI_COMPONENT = "decodeURIComponent" LIT_MAGIC_STRING_ENCODE_URI_COMPONENT = "encodeURIComponent" LIT_MAGIC_STRING_GET_UTC_MILLISECONDS_UL = "getUTCMilliseconds" +LIT_MAGIC_STRING_IS_CONCAT_SPREADABLE = "isConcatSpreadable" LIT_MAGIC_STRING_SET_UTC_MILLISECONDS_UL = "setUTCMilliseconds" LIT_MAGIC_STRING_TO_LOCALE_DATE_STRING_UL = "toLocaleDateString" LIT_MAGIC_STRING_TO_LOCALE_TIME_STRING_UL = "toLocaleTimeString" LIT_MAGIC_STRING_GET_OWN_PROPERTY_NAMES_UL = "getOwnPropertyNames" LIT_MAGIC_STRING_PROPERTY_IS_ENUMERABLE_UL = "propertyIsEnumerable" +LIT_MAGIC_STRING_GET_OWN_PROPERTY_SYMBOLS_UL = "getOwnPropertySymbols" LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTOR_UL = "getOwnPropertyDescriptor" LIT_MAGIC_STRING__FUNCTION_TO_STRING = "function(){/* ecmascript */}" diff --git a/jerry-core/profiles/README.md b/jerry-core/profiles/README.md index 2904206db..0965432dc 100644 --- a/jerry-core/profiles/README.md +++ b/jerry-core/profiles/README.md @@ -36,6 +36,7 @@ CONFIG_DISABLE_ES2015_FUNCTION_PARAMETER_INITIALIZER CONFIG_DISABLE_ES2015_MAP_BUILTIN CONFIG_DISABLE_ES2015_OBJECT_INITIALIZER CONFIG_DISABLE_ES2015_PROMISE_BUILTIN +CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN CONFIG_DISABLE_ES2015_TEMPLATE_STRINGS CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN ``` @@ -96,6 +97,8 @@ In JerryScript all of the features are enabled by default, so an empty profile f Disable the [Map](http://www.ecma-international.org/ecma-262/6.0/#sec-keyed-collection) built-ins. * `CONFIG_DISABLE_ES2015_OBJECT_INITIALIZER`: Disable the [enhanced object initializer](http://www.ecma-international.org/ecma-262/6.0/#sec-object-initializer) language element. +* `CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN`: + Disable the [Symbol](https://www.ecma-international.org/ecma-262/6.0/#sec-symbol-objects) built-in. * `CONFIG_DISABLE_ES2015_PROMISE_BUILTIN`: Disable the [Promise](http://www.ecma-international.org/ecma-262/6.0/#sec-promise-objects) built-in. * `CONFIG_DISABLE_ES2015_TEMPLATE_STRINGS`: @@ -105,4 +108,4 @@ In JerryScript all of the features are enabled by default, so an empty profile f * `CONFIG_DISABLE_ES2015`: Disable all of the implemented [ECMAScript2015 features](http://www.ecma-international.org/ecma-262/6.0/). (equivalent to `CONFIG_DISABLE_ES2015_ARROW_FUNCTION`, `CONFIG_DISABLE_ES2015_BUILTIN`, `CONFIG_DISABLE_ES2015_CLASS`, `CONFIG_DISABLE_ES2015_FUNCTION_PARAMETER_INITIALIZER`, `CONFIG_DISABLE_ES2015_MAP_BUILTIN`, `CONFIG_DISABLE_ES2015_OBJECT_INITIALIZER`, - `CONFIG_DISABLE_ES2015_PROMISE_BUILTIN`, `CONFIG_DISABLE_ES2015_TEMPLATE_STRINGS`, and `CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN`). + `CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN`, `CONFIG_DISABLE_ES2015_PROMISE_BUILTIN`, `CONFIG_DISABLE_ES2015_TEMPLATE_STRINGS`, and `CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN`). diff --git a/jerry-core/vm/opcodes.c b/jerry-core/vm/opcodes.c index eb295ed8e..b64620d63 100644 --- a/jerry-core/vm/opcodes.c +++ b/jerry-core/vm/opcodes.c @@ -162,14 +162,12 @@ vm_op_delete_prop (ecma_value_t object, /**< base object */ } JERRY_ASSERT (check_coercible == ECMA_VALUE_EMPTY); - ecma_value_t str_name_value = ecma_op_to_string (property); - if (ECMA_IS_VALUE_ERROR (str_name_value)) - { - return str_name_value; - } + ecma_string_t *name_string_p = ecma_op_to_prop_name (property); - JERRY_ASSERT (ecma_is_value_string (str_name_value)); - ecma_string_t *name_string_p = ecma_get_string_from_value (str_name_value); + if (JERRY_UNLIKELY (name_string_p == NULL)) + { + return ECMA_VALUE_ERROR; + } ecma_value_t obj_value = ecma_op_to_object (object); /* The ecma_op_check_object_coercible call already checked the op_to_object error cases. */ @@ -180,8 +178,8 @@ vm_op_delete_prop (ecma_value_t object, /**< base object */ ecma_value_t delete_op_ret = ecma_op_object_delete (obj_p, name_string_p, is_strict); JERRY_ASSERT (ecma_is_value_boolean (delete_op_ret) || (is_strict == true && ECMA_IS_VALUE_ERROR (delete_op_ret))); - ecma_free_value (obj_value); - ecma_free_value (str_name_value); + ecma_deref_object (obj_p); + ecma_deref_ecma_string (name_string_p); return delete_op_ret; } /* vm_op_delete_prop */ diff --git a/jerry-core/vm/vm.c b/jerry-core/vm/vm.c index 42e3aa2c2..c3105279d 100644 --- a/jerry-core/vm/vm.c +++ b/jerry-core/vm/vm.c @@ -70,6 +70,13 @@ vm_op_get_value (ecma_value_t object, /**< base object */ property_name_p = ecma_get_string_from_value (property); } +#ifndef CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN + if (ecma_is_value_symbol (property)) + { + property_name_p = ecma_get_symbol_from_value (property); + } +#endif /* !CONFIG_DISABLE_ES2015_SYMBOL_BUILTIN */ + if (property_name_p != NULL) { #ifndef CONFIG_ECMA_LCACHE_DISABLE @@ -101,15 +108,13 @@ vm_op_get_value (ecma_value_t object, /**< base object */ return error_value; } - ecma_value_t prop_to_string_result = ecma_op_to_string (property); + ecma_string_t *property_name_p = ecma_op_to_prop_name (property); - if (ECMA_IS_VALUE_ERROR (prop_to_string_result)) + if (property_name_p == NULL) { - return prop_to_string_result; + return ECMA_VALUE_ERROR; } - ecma_string_t *property_name_p = ecma_get_string_from_value (prop_to_string_result); - ecma_value_t get_value_result = ecma_op_get_value_object_base (object, property_name_p); ecma_deref_ecma_string (property_name_p); @@ -158,22 +163,25 @@ vm_op_set_value (ecma_value_t object, /**< base object */ object = to_object; } - if (!ecma_is_value_string (property)) + ecma_string_t *property_p; + ecma_object_t *object_p = ecma_get_object_from_value (object); + + if (!ecma_is_value_prop_name (property)) { - ecma_value_t to_string = ecma_op_to_string (property); + property_p = ecma_op_to_prop_name (property); ecma_fast_free_value (property); - if (ECMA_IS_VALUE_ERROR (to_string)) + if (JERRY_UNLIKELY (property_p == NULL)) { - ecma_free_value (object); - return to_string; + ecma_deref_object (object_p); + return ECMA_VALUE_ERROR; } - - property = to_string; + } + else + { + property_p = ecma_get_prop_name_from_value (property); } - ecma_object_t *object_p = ecma_get_object_from_value (object); - ecma_string_t *property_p = ecma_get_string_from_value (property); ecma_value_t completion_value = ECMA_VALUE_EMPTY; if (!ecma_is_lexical_environment (object_p)) @@ -191,8 +199,8 @@ vm_op_set_value (ecma_value_t object, /**< base object */ is_strict); } - ecma_free_value (object); - ecma_free_value (property); + ecma_deref_object (object_p); + ecma_deref_ecma_string (property_p); return completion_value; } /* vm_op_set_value */ @@ -1608,6 +1616,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (length_num); ecma_property_value_t *prop_value_p; + prop_value_p = ecma_create_named_data_property (array_obj_p, index_str_p, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, diff --git a/tests/jerry/es2015/object-get-own-property-symbols.js b/tests/jerry/es2015/object-get-own-property-symbols.js new file mode 100644 index 000000000..83848f930 --- /dev/null +++ b/tests/jerry/es2015/object-get-own-property-symbols.js @@ -0,0 +1,119 @@ +/* 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. + */ + +// Test array +var a = Symbol ('a'); +var b = Symbol ('b'); +var c = Symbol ('c'); +var d = Symbol (); + +var arr = [a, b, c, d]; +var props = Object.getOwnPropertySymbols (arr); +// props should not contain: a, b, c, d +assert (props.indexOf ('0') === -1); +assert (props.indexOf ('1') === -1); +assert (props.indexOf ('2') === -1); +assert (props.indexOf ('length') === -1); +assert (props.length === 0); + +// Test object +var obj = {}; +obj[a] = 'a'; +obj[b] = 'b'; +obj[c] = 'c'; +obj[d] = 'd'; +props = Object.getOwnPropertySymbols (obj); +// props should contain: a, b, c, d and the order is not defined! +assert (props.indexOf(a) !== -1); +assert (props.indexOf(b) !== -1); +assert (props.indexOf(c) !== -1); +assert (props.indexOf(d) !== -1); +assert (props.length === 4); + +// Test same descriptions +var fooSymbol1 = Symbol ('foo'); +var fooSymbol2 = Symbol ('foo'); +var fooSymbol3 = Symbol ('foo'); +var fooSymbol4 = Symbol ('foo'); + +var obj = {} +obj[fooSymbol1] = 'foo'; +obj[fooSymbol2] = 'bar'; +obj[fooSymbol3] = 'foobar'; +obj[fooSymbol4] = 'barfoo'; + +props = Object.getOwnPropertySymbols (obj); +assert (props.indexOf (fooSymbol1) !== -1); +assert (props.indexOf (fooSymbol2) !== -1); +assert (props.indexOf (fooSymbol3) !== -1); +assert (props.indexOf (fooSymbol4) !== -1); +assert (props.length === 4); + +var mixed_object = {}; +var foo = Symbol ('foo'); +var bar = Symbol.for ('bar'); + +mixed_object[foo] = 'localSymbol'; +mixed_object[bar] = 'globalSymbol'; +mixed_object['foo'] = 'string'; + +var props = Object.getOwnPropertySymbols (mixed_object); + +assert (typeof props[0] === 'symbol') +assert (props.indexOf(foo) !== -1); +assert (props.indexOf(bar) !== -1); +assert (props.indexOf('foo') === -1); +assert (props.length === 2) + +// Test prototype chain +function Parent() {} +Parent.prototype.inheritedMethod = function() {}; + +function Child() { + this[a] = 5; + this[b] = function() {}; +} +Child.prototype = new Parent; +Child.prototype.prototypeMethod = function() {}; + +props = Object.getOwnPropertySymbols (new Child()); +// props should contain: a, b and the order is not defined! +assert (props.indexOf(a) !== -1); +assert (props.indexOf(b) !== -1); + +assert (props.length === 2); + +// Test non-emumerable symbols +var object = {}; +var foo = Symbol ('foo'); +var foo2 = Symbol ('foo2'); +object[foo] = 'EnumerableSymbolProp'; +Object.defineProperty(object, foo2, { value : 'NonEnumerableSymbolProp' }); + +props = Object.getOwnPropertySymbols (object); + +assert (props.indexOf(foo) !== -1); +assert (props.indexOf(foo2) !== -1); +assert (props.length === 2); +assert (Object.getOwnPropertyDescriptor (object, foo).enumerable === true); +assert (Object.getOwnPropertyDescriptor (object, foo2).enumerable === false); + +// Test non-object argument +try { + Object.getOwnPropertySymbols ('hello'); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} diff --git a/tests/jerry/es2015/symbol-key-keyfor.js b/tests/jerry/es2015/symbol-key-keyfor.js new file mode 100644 index 000000000..7bb96a80e --- /dev/null +++ b/tests/jerry/es2015/symbol-key-keyfor.js @@ -0,0 +1,60 @@ +/* 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. + */ + +try { + Symbol.for (Symbol('foo')); + assert (false); +} catch (e) { + assert (e instanceof TypeError) +} + +var a = Symbol.for ('foo'); +var b = Symbol.for ('foo'); + +assert (a === b); +assert (a == b); + +assert (Symbol.keyFor (a) === 'foo'); +assert (Symbol.keyFor (b) === 'foo'); + +// Test non-string arguments +var c = Symbol.for (5); +var d = Symbol.for (5.58); +var e = Symbol.for ({}); + +assert (Symbol.keyFor (c) === '5'); +assert (Symbol.keyFor (d) === '5.58'); +assert (Symbol.keyFor (e) === '[object Object]'); + +// Test global symbol table +var array = []; +for (var i = 0; i < 15; i++) { + array[i] = Symbol.for ('foo' + i); + + for (var j = 0; j < i; j++) { + assert (array[j] !== array[i]); + } +} + +try { + Symbol.keyFor ('NonSymbolValue'); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} + +for (var i = 0; i < 15; i++) { + assert (Symbol.keyFor (array[i]) === ('foo' + i)); +} diff --git a/tests/jerry/es2015/symbol-prototype-symbol-toprimitive.js b/tests/jerry/es2015/symbol-prototype-symbol-toprimitive.js new file mode 100644 index 000000000..73016b9de --- /dev/null +++ b/tests/jerry/es2015/symbol-prototype-symbol-toprimitive.js @@ -0,0 +1,34 @@ +/* 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. + */ + +try { + Symbol.prototype[Symbol.toPrimitive].call ('NonSymbolValue'); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} + +try { + Symbol.prototype[Symbol.toPrimitive].call ({}); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} + +var foo = Symbol ('foo'); +assert (foo[Symbol.toPrimitive] () === foo); + +var fooObj = Object (foo); +assert (fooObj[Symbol.toPrimitive] () === foo); diff --git a/tests/jerry/es2015/symbol-prototype-tostring.js b/tests/jerry/es2015/symbol-prototype-tostring.js new file mode 100644 index 000000000..bea3cc259 --- /dev/null +++ b/tests/jerry/es2015/symbol-prototype-tostring.js @@ -0,0 +1,34 @@ +/* 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. + */ + +try { + Symbol.prototype.toString.call ('NonSymbolValue'); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} + +try { + Symbol.prototype.toString.call ({}); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} + +var foo = Symbol ('foo'); +assert (foo.toString () === "Symbol(foo)"); + +var fooObj = Object (foo); +assert (fooObj.toString () === "Symbol(foo)"); diff --git a/tests/jerry/es2015/symbol-prototype-valueof.js b/tests/jerry/es2015/symbol-prototype-valueof.js new file mode 100644 index 000000000..216d22836 --- /dev/null +++ b/tests/jerry/es2015/symbol-prototype-valueof.js @@ -0,0 +1,34 @@ +/* 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. + */ + +try { + Symbol.prototype.valueOf.call ('NonSymbolValue'); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} + +try { + Symbol.prototype.valueOf.call ({}); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} + +var foo = Symbol ('foo'); +assert (foo.valueOf () === foo); + +var fooObj = Object (foo); +assert (fooObj.valueOf () === foo); diff --git a/tests/jerry/es2015/symbol.js b/tests/jerry/es2015/symbol.js new file mode 100644 index 000000000..329a7c515 --- /dev/null +++ b/tests/jerry/es2015/symbol.js @@ -0,0 +1,122 @@ +/* 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 a = Symbol ('foo'); +var b = Symbol ('bar'); + +assert (a !== b); +assert (a === a); +assert (typeof a === 'symbol'); +assert (a.toString() == 'Symbol(foo)'); +assert (Object.prototype.toString.call (a) === "[object Symbol]"); +assert (JSON.stringify (a) === undefined); + +var obj = { c : 10, d : 20}; +obj[a] = 'EnumerableSymbolProp'; +assert (obj[a] === 'EnumerableSymbolProp'); + +// Symbol properties are not listed via for in +Object.defineProperty(obj, b, { value : 'NonEnumerableSymbolProp' }); + +var counter = 0; + +for (var v in obj) { + assert (v === 'c' || v === 'd'); + counter++; +} + +assert (counter === 2); + +var keys = Object.keys (obj); +assert (keys.length === 2); +assert (keys[0] === 'c' || keys[0] === 'd'); +assert (keys[1] === 'd' || keys[1] === 'c'); + +var c = Symbol ('bar'); +var obj2 = {}; +obj2[b] = 'foo'; +obj2[c] = 'bar'; + +assert (obj2[b] == 'foo'); +assert (obj2[c] == 'bar'); + +try { + new Date (Symbol ('2018-11-09')); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} + +try { + a + 'append_string'; + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} + +assert (Object (a) == a); +assert (Object (a) !== a); + +// Test built-in symbols +var a = ['hasInstance', + 'isConcatSpreadable', + 'iterator', + 'match', + 'replace', + 'search', + 'species', + 'split', + 'toPrimitive', + 'toStringTag', + 'unscopables']; + +a.forEach (function (e) { + assert (Symbol[e].toString() === ('Symbol(Symbol.' + e +')')); + assert (typeof Symbol[e] === 'symbol'); +}); + +var obj = {}; +Object.defineProperty(obj, a, { 'get' : function () {throw new ReferenceError ('foo'); } }); +Object.defineProperty(obj, b, { value : 5 }); +assert (obj[b] === 5); + +try { + obj[a]; + assert (false); +} catch (e) { + assert (e instanceof ReferenceError); + assert (e.message === 'foo'); +} + +var descriptor = Object.getOwnPropertyDescriptor(obj, b); + +assert (descriptor.configurable === false); +assert (descriptor.enumerable === false); +assert (descriptor.writable === false); +assert (descriptor.value === 5); + +var foo = Symbol ('foo'); +assert (foo[Symbol.toStringTag] === 'Symbol'); + +// Test same descriptions +var symA = Symbol ('foobar'); +var symB = Symbol ('foobar'); +assert (symA !== symB); +assert (symA != symB); + +var obj = { foobar : 55 }; +obj[symA] = 77; +assert (obj["foobar"] !== obj[symA]); +assert (obj["foobar"] != obj[symA]); diff --git a/tests/jerry/regression-test-issue-116.js b/tests/jerry/es5.1/regression-test-issue-116.js similarity index 100% rename from tests/jerry/regression-test-issue-116.js rename to tests/jerry/es5.1/regression-test-issue-116.js