From 3b4c2592817dd1484b2291565d47288b48b51bf8 Mon Sep 17 00:00:00 2001 From: Robert Fancsik Date: Fri, 29 May 2020 14:28:52 +0200 Subject: [PATCH] Add support for builtin/builtin routine 'name' property (#3810) JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu --- jerry-core/ecma/base/ecma-globals.h | 12 + .../builtin-objects/ecma-builtin-array.inc.h | 6 + .../ecma-builtin-arraybuffer.inc.h | 4 + .../ecma-builtin-boolean.inc.h | 6 + .../builtin-objects/ecma-builtin-date.inc.h | 6 + .../builtin-objects/ecma-builtin-error.inc.h | 6 + .../ecma-builtin-evalerror.inc.h | 6 + .../ecma-builtin-function-prototype.c | 14 +- .../ecma-builtin-function-prototype.inc.h | 6 + .../ecma-builtin-function.inc.h | 6 + .../builtin-objects/ecma-builtin-number.inc.h | 3 + .../builtin-objects/ecma-builtin-object.inc.h | 6 + .../ecma-builtin-promise.inc.h | 4 + .../builtin-objects/ecma-builtin-proxy.inc.h | 4 + .../ecma-builtin-rangeerror.inc.h | 6 + .../ecma-builtin-referenceerror.inc.h | 6 + .../builtin-objects/ecma-builtin-regexp.inc.h | 4 + .../builtin-objects/ecma-builtin-string.inc.h | 6 + .../builtin-objects/ecma-builtin-symbol.inc.h | 4 + .../ecma-builtin-syntaxerror.inc.h | 6 + .../ecma-builtin-typeerror.inc.h | 6 + .../ecma-builtin-urierror.inc.h | 6 + .../ecma/builtin-objects/ecma-builtins.c | 92 +++++- .../ecma/operations/ecma-function-object.c | 4 +- .../ecma/operations/ecma-function-object.h | 2 +- jerry-core/lit/lit-magic-strings.h | 5 + jerry-core/vm/vm.c | 4 +- tests/jerry/es2015/function-name.js | 287 ++++++++++++++++++ tests/test262-es6-excludelist.xml | 97 ------ 29 files changed, 512 insertions(+), 112 deletions(-) create mode 100644 tests/jerry/es2015/function-name.js diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index 82b4897558..476eaabd42 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -818,6 +818,18 @@ typedef struct } u; } ecma_built_in_props_t; +/** + * Builtin routine function object status flags + */ +typedef enum +{ + ECMA_BUILTIN_ROUTINE_NO_OPTS = 0, /**< No options are provided */ + ECMA_BUILTIN_ROUTINE_LENGTH_INITIALIZED = (1u << 0), /**< 'length' property has been initialized */ + ECMA_BUILTIN_ROUTINE_NAME_INITIALIZED = (1u << 1), /**< 'name' property has been initialized */ + ECMA_BUILTIN_ROUTINE_GETTER = (1u << 2), /**< this routine is getter */ + ECMA_BUILTIN_ROUTINE_SETTER = (1u << 3), /**< this routine is setter */ +} ecma_builtin_routine_flags_t; + /** * Start position of bit set size in length_and_bitset_size field. */ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-array.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-array.inc.h index ff1df5f02c..f9cc9a4b4e 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-array.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-array.inc.h @@ -36,6 +36,12 @@ NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) +#if ENABLED (JERRY_ES2015) +STRING_VALUE (LIT_MAGIC_STRING_NAME, + LIT_MAGIC_STRING_ARRAY_UL, + ECMA_PROPERTY_FLAG_CONFIGURABLE) +#endif /* ENABLED (JERRY_ES2015) */ + /* Routine properties: * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ ROUTINE (LIT_MAGIC_STRING_IS_ARRAY_UL, ecma_builtin_array_object_is_array, 1, 1) diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer.inc.h index a3b162f399..f76e7298dc 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer.inc.h @@ -35,6 +35,10 @@ OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_ARRAYBUFFER_PROTOTYPE, ECMA_PROPERTY_FIXED) +STRING_VALUE (LIT_MAGIC_STRING_NAME, + LIT_MAGIC_STRING_ARRAY_BUFFER_UL, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + /* 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-boolean.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-boolean.inc.h index dd5132b925..5b4c756b65 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-boolean.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-boolean.inc.h @@ -36,6 +36,12 @@ NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) +#if ENABLED (JERRY_ES2015) +STRING_VALUE (LIT_MAGIC_STRING_NAME, + LIT_MAGIC_STRING_BOOLEAN_UL, + ECMA_PROPERTY_FLAG_CONFIGURABLE) +#endif /* ENABLED (JERRY_ES2015) */ + #endif /* ENABLED (JERRY_BUILTIN_BOOLEAN) */ #include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-date.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-date.inc.h index f805b77946..715fb446e6 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-date.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-date.inc.h @@ -34,6 +34,12 @@ ROUTINE (LIT_MAGIC_STRING_PARSE, ecma_builtin_date_parse, 1, 1) ROUTINE (LIT_MAGIC_STRING_UTC_U, ecma_builtin_date_utc, NON_FIXED, 7) ROUTINE (LIT_MAGIC_STRING_NOW, ecma_builtin_date_now, 0, 0) +#if ENABLED (JERRY_ES2015) +STRING_VALUE (LIT_MAGIC_STRING_NAME, + LIT_MAGIC_STRING_DATE_UL, + ECMA_PROPERTY_FLAG_CONFIGURABLE) +#endif /* ENABLED (JERRY_ES2015) */ + #endif /* ENABLED (JERRY_BUILTIN_DATE) */ #include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-error.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-error.inc.h index e965de4973..854a687ffd 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-error.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-error.inc.h @@ -34,4 +34,10 @@ OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_ERROR_PROTOTYPE, ECMA_PROPERTY_FIXED) +#if ENABLED (JERRY_ES2015) +STRING_VALUE (LIT_MAGIC_STRING_NAME, + LIT_MAGIC_STRING_ERROR_UL, + ECMA_PROPERTY_FLAG_CONFIGURABLE) +#endif /* ENABLED (JERRY_ES2015) */ + #include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror.inc.h index f2fd2682af..ceeb2e1d35 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-evalerror.inc.h @@ -36,6 +36,12 @@ OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_EVAL_ERROR_PROTOTYPE, ECMA_PROPERTY_FIXED) +#if ENABLED (JERRY_ES2015) +STRING_VALUE (LIT_MAGIC_STRING_NAME, + LIT_MAGIC_STRING_EVAL_ERROR_UL, + ECMA_PROPERTY_FLAG_CONFIGURABLE) +#endif /* ENABLED (JERRY_ES2015) */ + #endif /* ENABLED (JERRY_BUILTIN_ERRORS) */ #include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.c index 1dc7d06204..94636b05f9 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.c @@ -348,15 +348,21 @@ ecma_builtin_function_prototype_object_bind (ecma_object_t *this_arg_obj_p , /** return name_value; } - if (!ecma_is_value_string (name_value)) + ecma_string_t *name_p; + + if (ecma_is_value_string (name_value)) + { + name_p = ecma_get_string_from_value (name_value); + } + else { ecma_free_value (name_value); - name_value = ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + name_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); } - ecma_value_t bound_function_name = ecma_op_function_form_name (name_value, "bound ", 6); + ecma_value_t bound_function_name = ecma_op_function_form_name (name_p, "bound ", 6); - ecma_free_value (name_value); + ecma_deref_ecma_string (name_p); ecma_property_value_t *name_prop_value_p; name_prop_value_p = ecma_create_named_data_property (function_p, diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.inc.h index 94f0e8704f..e59b047b94 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.inc.h @@ -34,6 +34,12 @@ NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 0, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) +#if ENABLED (JERRY_ES2015) +STRING_VALUE (LIT_MAGIC_STRING_NAME, + LIT_MAGIC_STRING__EMPTY, + ECMA_PROPERTY_FLAG_CONFIGURABLE) +#endif /* ENABLED (JERRY_ES2015) */ + /* Routine properties: * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ECMA_FUNCTION_PROTOTYPE_TO_STRING, 0, 0) diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-function.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-function.inc.h index ede2661583..597af8e525 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-function.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-function.inc.h @@ -34,4 +34,10 @@ NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 1, ECMA_PROPERTY_FLAG_DEFAULT_LENGTH) +#if ENABLED (JERRY_ES2015) +STRING_VALUE (LIT_MAGIC_STRING_NAME, + LIT_MAGIC_STRING_FUNCTION_UL, + ECMA_PROPERTY_FLAG_CONFIGURABLE) +#endif /* ENABLED (JERRY_ES2015) */ + #include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-number.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-number.inc.h index 1119135593..73dbc8a711 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-number.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-number.inc.h @@ -70,6 +70,9 @@ NUMBER_VALUE (LIT_MAGIC_STRING_MIN_SAFE_INTEGER_U, ECMA_BUILTIN_NUMBER_MIN_SAFE_INTEGER, ECMA_PROPERTY_FIXED) +STRING_VALUE (LIT_MAGIC_STRING_NAME, + LIT_MAGIC_STRING_NUMBER_UL, + ECMA_PROPERTY_FLAG_CONFIGURABLE) #endif /* ENABLED (JERRY_ES2015) */ /* Object properties: 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 fde4c7eca7..63f6d346cb 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-object.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-object.inc.h @@ -34,6 +34,12 @@ OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE, ECMA_PROPERTY_FIXED) +#if ENABLED (JERRY_ES2015) +STRING_VALUE (LIT_MAGIC_STRING_NAME, + LIT_MAGIC_STRING_OBJECT_UL, + ECMA_PROPERTY_FLAG_CONFIGURABLE) +#endif /* ENABLED (JERRY_ES2015) */ + /* Routine properties: * (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_OBJECT_ROUTINE_GET_PROTOTYPE_OF, 1, 1) diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-promise.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-promise.inc.h index 117e50bfdc..5c55c7f3fb 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-promise.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-promise.inc.h @@ -35,6 +35,10 @@ OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_PROMISE_PROTOTYPE, ECMA_PROPERTY_FIXED) +STRING_VALUE (LIT_MAGIC_STRING_NAME, + LIT_MAGIC_STRING_PROMISE_UL, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + /* Routine properties: * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ ROUTINE (LIT_MAGIC_STRING_REJECT, ecma_builtin_promise_reject, 1, 1) diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-proxy.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-proxy.inc.h index cfe4be575f..dc4b616545 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-proxy.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-proxy.inc.h @@ -28,6 +28,10 @@ NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 2, ECMA_PROPERTY_FLAG_CONFIGURABLE) +STRING_VALUE (LIT_MAGIC_STRING_NAME, + LIT_MAGIC_STRING_PROXY_UL, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + /* 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-rangeerror.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror.inc.h index f29b82507a..d2fd0dba59 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-rangeerror.inc.h @@ -36,6 +36,12 @@ OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_RANGE_ERROR_PROTOTYPE, ECMA_PROPERTY_FIXED) +#if ENABLED (JERRY_ES2015) +STRING_VALUE (LIT_MAGIC_STRING_NAME, + LIT_MAGIC_STRING_RANGE_ERROR_UL, + ECMA_PROPERTY_FLAG_CONFIGURABLE) +#endif /* ENABLED (JERRY_ES2015) */ + #endif /* ENABLED (JERRY_BUILTIN_ERRORS) */ #include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror.inc.h index ff0638f3cf..2fdd1e4535 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-referenceerror.inc.h @@ -36,6 +36,12 @@ OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_REFERENCE_ERROR_PROTOTYPE, ECMA_PROPERTY_FIXED) +#if ENABLED (JERRY_ES2015) +STRING_VALUE (LIT_MAGIC_STRING_NAME, + LIT_MAGIC_STRING_REFERENCE_ERROR_UL, + ECMA_PROPERTY_FLAG_CONFIGURABLE) +#endif /* ENABLED (JERRY_ES2015) */ + #endif /* ENABLED (JERRY_BUILTIN_ERRORS) */ #include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-regexp.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-regexp.inc.h index bbc0be6c48..0c01f06a92 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-regexp.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-regexp.inc.h @@ -31,6 +31,10 @@ OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_PROPERTY_FIXED) #if ENABLED (JERRY_ES2015) +STRING_VALUE (LIT_MAGIC_STRING_NAME, + LIT_MAGIC_STRING_REGEXP_UL, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + /* ECMA-262 v6, 21.2.4.2 */ ACCESSOR_READ_ONLY (LIT_GLOBAL_SYMBOL_SPECIES, ecma_builtin_regexp_species_get, diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-string.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-string.inc.h index d3e8d88bc7..1250e1c23a 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-string.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-string.inc.h @@ -36,6 +36,12 @@ OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_STRING_PROTOTYPE, ECMA_PROPERTY_FIXED) +#if ENABLED (JERRY_ES2015) +STRING_VALUE (LIT_MAGIC_STRING_NAME, + LIT_MAGIC_STRING_STRING_UL, + ECMA_PROPERTY_FLAG_CONFIGURABLE) +#endif /* ENABLED (JERRY_ES2015) */ + /* Routine properties: * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ ROUTINE (LIT_MAGIC_STRING_FROM_CHAR_CODE_UL, ecma_builtin_string_object_from_char_code, NON_FIXED, 1) diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.inc.h index cb932b1cbf..b27bbcf95a 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-symbol.inc.h @@ -29,6 +29,10 @@ NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, 0, ECMA_PROPERTY_FLAG_CONFIGURABLE) +STRING_VALUE (LIT_MAGIC_STRING_NAME, + LIT_MAGIC_STRING_STRING_UL, + ECMA_PROPERTY_FLAG_CONFIGURABLE) + /* Object properties: * (property name, object pointer getter) */ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror.inc.h index 848b1bcd31..ed1bd4ccf8 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-syntaxerror.inc.h @@ -36,6 +36,12 @@ OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_SYNTAX_ERROR_PROTOTYPE, ECMA_PROPERTY_FIXED) +#if ENABLED (JERRY_ES2015) +STRING_VALUE (LIT_MAGIC_STRING_NAME, + LIT_MAGIC_STRING_SYNTAX_ERROR_UL, + ECMA_PROPERTY_FLAG_CONFIGURABLE) +#endif /* ENABLED (JERRY_ES2015) */ + #endif /* ENABLED (JERRY_BUILTIN_ERRORS) */ #include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror.inc.h index 5c5b42a25e..0d352c2aa9 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-typeerror.inc.h @@ -36,6 +36,12 @@ OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_TYPE_ERROR_PROTOTYPE, ECMA_PROPERTY_FIXED) +#if ENABLED (JERRY_ES2015) +STRING_VALUE (LIT_MAGIC_STRING_NAME, + LIT_MAGIC_STRING_SYNTAX_ERROR_UL, + ECMA_PROPERTY_FLAG_CONFIGURABLE) +#endif /* ENABLED (JERRY_ES2015) */ + #endif /* ENABLED (JERRY_BUILTIN_ERRORS) */ #include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-urierror.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-urierror.inc.h index 84845b6d7f..2dc7296cb9 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-urierror.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-urierror.inc.h @@ -36,6 +36,12 @@ OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE, ECMA_BUILTIN_ID_URI_ERROR_PROTOTYPE, ECMA_PROPERTY_FIXED) +#if ENABLED (JERRY_ES2015) +STRING_VALUE (LIT_MAGIC_STRING_NAME, + LIT_MAGIC_STRING_URI_ERROR_UL, + ECMA_PROPERTY_FLAG_CONFIGURABLE) +#endif /* ENABLED (JERRY_ES2015) */ + #endif /* ENABLED (JERRY_BUILTIN_ERRORS) */ #include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins.c b/jerry-core/ecma/builtin-objects/ecma-builtins.c index 21b26cd4a2..0468e8d25f 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtins.c @@ -19,6 +19,7 @@ #include "ecma-gc.h" #include "ecma-globals.h" #include "ecma-helpers.h" +#include "ecma-function-object.h" #include "ecma-objects.h" #include "jcontext.h" #include "jrt-bit-fields.h" @@ -556,6 +557,7 @@ ecma_builtin_make_function_object_for_routine (ecma_builtin_id_t builtin_id, /** uint16_t routine_id, /**< builtin-wide identifier of the built-in * object's routine property */ uint16_t name_id, /**< magic string id of 'name' property */ + uint16_t flags, /**< see also: ecma_builtin_routine_flags */ uint8_t length_prop_value) /**< value of 'length' property */ { JERRY_ASSERT (length_prop_value < (1 << ECMA_BUILT_IN_BITSET_SHIFT)); @@ -576,7 +578,7 @@ ecma_builtin_make_function_object_for_routine (ecma_builtin_id_t builtin_id, /** ext_func_obj_p->u.built_in.id = (uint8_t) builtin_id; ext_func_obj_p->u.built_in.routine_id = routine_id; ext_func_obj_p->u.built_in.u.builtin_routine.name = name_id; - ext_func_obj_p->u.built_in.u.builtin_routine.bitset = 0; + ext_func_obj_p->u.built_in.u.builtin_routine.bitset = flags; ext_func_obj_p->u.built_in.length_and_bitset_size = length_prop_value; @@ -594,7 +596,11 @@ ecma_builtin_make_function_object_for_getter_accessor (ecma_builtin_id_t builtin * object's routine property */ uint16_t name_id) /**< magic string id of 'name' property */ { - return ecma_builtin_make_function_object_for_routine (builtin_id, routine_id, name_id, 0); + return ecma_builtin_make_function_object_for_routine (builtin_id, + routine_id, + name_id, + ECMA_BUILTIN_ROUTINE_GETTER, + 0); } /* ecma_builtin_make_function_object_for_getter_accessor */ /** @@ -608,7 +614,11 @@ ecma_builtin_make_function_object_for_setter_accessor (ecma_builtin_id_t builtin * object's routine property */ uint16_t name_id) /**< magic string id of 'name' property */ { - return ecma_builtin_make_function_object_for_routine (builtin_id, routine_id, name_id, 1); + return ecma_builtin_make_function_object_for_routine (builtin_id, + routine_id, + name_id, + ECMA_BUILTIN_ROUTINE_SETTER, + 1); } /* ecma_builtin_make_function_object_for_setter_accessor */ /** @@ -638,14 +648,14 @@ ecma_builtin_routine_try_to_instantiate_property (ecma_object_t *object_p, /**< ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; #if ENABLED (JERRY_ES2015) uint16_t *bitset_p = &ext_func_p->u.built_in.u.builtin_routine.bitset; - if (*bitset_p & (1u << 0)) + if (*bitset_p & ECMA_BUILTIN_ROUTINE_LENGTH_INITIALIZED) { /* length property was already instantiated */ return NULL; } /* We mark that the property was lazily instantiated, * as it is configurable and so can be deleted (ECMA-262 v6, 19.2.4.1) */ - *bitset_p |= (1u << 0); + *bitset_p |= ECMA_BUILTIN_ROUTINE_LENGTH_INITIALIZED; ecma_property_value_t *len_prop_value_p = ecma_create_named_data_property (object_p, string_p, ECMA_PROPERTY_FLAG_CONFIGURABLE, @@ -667,6 +677,70 @@ ecma_builtin_routine_try_to_instantiate_property (ecma_object_t *object_p, /**< return len_prop_p; } +#if ENABLED (JERRY_ES2015) + /* + * Lazy instantiation of 'name' property + */ + if (ecma_compare_ecma_string_to_magic_id (string_p, LIT_MAGIC_STRING_NAME)) + { + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; + uint16_t *bitset_p = &ext_func_p->u.built_in.u.builtin_routine.bitset; + + if (*bitset_p & ECMA_BUILTIN_ROUTINE_NAME_INITIALIZED) + { + /* name property was already instantiated */ + return NULL; + } + + /* We mark that the property was lazily instantiated */ + *bitset_p |= ECMA_BUILTIN_ROUTINE_NAME_INITIALIZED; + ecma_property_t *name_prop_p; + ecma_property_value_t *name_prop_value_p = ecma_create_named_data_property (object_p, + string_p, + ECMA_PROPERTY_FLAG_CONFIGURABLE, + &name_prop_p); + + ecma_string_t *name_p; + lit_magic_string_id_t name_id = ext_func_p->u.built_in.u.builtin_routine.name; + + if (JERRY_UNLIKELY (name_id > LIT_NON_INTERNAL_MAGIC_STRING__COUNT)) + { + /* Note: Whenever new intrinsic routine is being added this mapping should be updated as well! */ + if (JERRY_UNLIKELY (name_id == LIT_INTERNAL_MAGIC_STRING_ARRAY_PROTOTYPE_VALUES)) + { + name_p = ecma_get_magic_string (LIT_MAGIC_STRING_VALUES); + } + else + { + JERRY_ASSERT (LIT_IS_GLOBAL_SYMBOL (name_id)); + name_p = ecma_op_get_global_symbol (name_id); + } + } + else + { + name_p = ecma_get_magic_string (name_id); + } + + char *prefix_p = NULL; + lit_utf8_size_t prefix_size = 0; + + if (*bitset_p & (ECMA_BUILTIN_ROUTINE_GETTER | ECMA_BUILTIN_ROUTINE_SETTER)) + { + prefix_size = 4; + prefix_p = (*bitset_p & ECMA_BUILTIN_ROUTINE_GETTER) ? "get " : "set "; + } + + name_prop_value_p->value = ecma_op_function_form_name (name_p, prefix_p, prefix_size); + + if (JERRY_UNLIKELY (name_id > LIT_NON_INTERNAL_MAGIC_STRING__COUNT)) + { + ecma_deref_ecma_string (name_p); + } + + return name_prop_p; + } +#endif /* ENABLED (JERRY_ES2015) */ + return NULL; } /* ecma_builtin_routine_try_to_instantiate_property */ @@ -870,6 +944,7 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object * func_obj_p = ecma_builtin_make_function_object_for_routine (builtin_id, ECMA_GET_ROUTINE_ID (curr_property_p->value), curr_property_p->magic_string_id, + ECMA_BUILTIN_ROUTINE_NO_OPTS, ECMA_GET_ROUTINE_LENGTH (curr_property_p->value)); value = ecma_make_object_value (func_obj_p); break; @@ -967,11 +1042,16 @@ ecma_builtin_routine_list_lazy_property_names (ecma_object_t *object_p, /**< a b { #if ENABLED (JERRY_ES2015) ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; - if (!(ext_func_p->u.built_in.u.builtin_routine.bitset & (1u << 0))) + if (!(ext_func_p->u.built_in.u.builtin_routine.bitset & ECMA_BUILTIN_ROUTINE_LENGTH_INITIALIZED)) { /* Unintialized 'length' property is non-enumerable (ECMA-262 v6, 19.2.4.1) */ ecma_collection_push_back (for_non_enumerable_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); } + if (!(ext_func_p->u.built_in.u.builtin_routine.bitset & ECMA_BUILTIN_ROUTINE_NAME_INITIALIZED)) + { + /* Unintialized 'name' property is non-enumerable (ECMA-262 v6, 19.2.4.2) */ + ecma_collection_push_back (for_non_enumerable_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_NAME)); + } #else /* !ENABLED (JERRY_ES2015) */ /* 'length' property is non-enumerable (ECMA-262 v5, 15) */ ecma_collection_push_back (for_non_enumerable_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); diff --git a/jerry-core/ecma/operations/ecma-function-object.c b/jerry-core/ecma/operations/ecma-function-object.c index bb817697ac..53778ace5a 100644 --- a/jerry-core/ecma/operations/ecma-function-object.c +++ b/jerry-core/ecma/operations/ecma-function-object.c @@ -60,12 +60,10 @@ ecma_op_resource_name (const ecma_compiled_code_t *bytecode_header_p) * @return resource name as ecma-string */ ecma_value_t -ecma_op_function_form_name (ecma_value_t prop_name, /**< property name */ +ecma_op_function_form_name (ecma_string_t *prop_name_p, /**< property name */ char *prefix_p, /**< prefix */ lit_utf8_size_t prefix_size) /**< prefix length */ { - ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (prop_name); - /* 4. */ if (ecma_prop_name_is_symbol (prop_name_p)) { diff --git a/jerry-core/ecma/operations/ecma-function-object.h b/jerry-core/ecma/operations/ecma-function-object.h index 262fabf9bd..c10489eb67 100644 --- a/jerry-core/ecma/operations/ecma-function-object.h +++ b/jerry-core/ecma/operations/ecma-function-object.h @@ -32,7 +32,7 @@ ecma_value_t ecma_op_resource_name (const ecma_compiled_code_t *bytecode_header_ #endif /* ENABLED (JERRY_RESOURCE_NAME) */ #if ENABLED (JERRY_ES2015) -ecma_value_t ecma_op_function_form_name (ecma_value_t prop_name, char *prefix_p, lit_utf8_size_t prefix_size); +ecma_value_t ecma_op_function_form_name (ecma_string_t *prop_name_p, char *prefix_p, lit_utf8_size_t prefix_size); #endif /* ENABLED (JERRY_ES2015) */ bool ecma_op_is_callable (ecma_value_t value); diff --git a/jerry-core/lit/lit-magic-strings.h b/jerry-core/lit/lit-magic-strings.h index 1ab61aa28d..ff3a84ad79 100644 --- a/jerry-core/lit/lit-magic-strings.h +++ b/jerry-core/lit/lit-magic-strings.h @@ -75,6 +75,11 @@ typedef enum LIT_MAGIC_STRING__COUNT /**< number of magic strings */ } lit_magic_string_id_t; +/** + * Checks whether the given id corresponds to a global symbol + */ +#define LIT_IS_GLOBAL_SYMBOL(id) ((id) >= LIT_GLOBAL_SYMBOL_HAS_INSTANCE && (id) <= LIT_GLOBAL_SYMBOL_UNSCOPABLES) + /** * Identifiers of implementation-defined external magic string constants */ diff --git a/jerry-core/vm/vm.c b/jerry-core/vm/vm.c index ea57a7f62e..ee6b8863fe 100644 --- a/jerry-core/vm/vm.c +++ b/jerry-core/vm/vm.c @@ -1883,7 +1883,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ ECMA_SET_SECOND_BIT_TO_POINTER_TAG (((ecma_extended_object_t *) func_obj_p)->u.function.scope_cp); } - value_p->value = ecma_op_function_form_name (left_value, prefix_p, prefix_size); + value_p->value = ecma_op_function_form_name (ecma_get_prop_name_from_value (left_value), + prefix_p, + prefix_size); ecma_free_value (left_value); continue; } diff --git a/tests/jerry/es2015/function-name.js b/tests/jerry/es2015/function-name.js new file mode 100644 index 0000000000..6243372f32 --- /dev/null +++ b/tests/jerry/es2015/function-name.js @@ -0,0 +1,287 @@ +// 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. + +function assertNameExists(func) { + assert(func.hasOwnProperty('name') === true); +} +function assertNameNotExists(func) { + assert(func.hasOwnProperty('name') === false); + assert(Function.prototype.name === ''); + assert(func.name === ''); +} + +function assertConfigurableOnlyMethod(func) { + let desc = Object.getOwnPropertyDescriptor(func, 'name'); + assert(desc.configurable === true); + assert(desc.writable === false); + assert(desc.enumerable === false); + + delete func.name; + assertNameNotExists(func); + + Object.defineProperty(func, 'name', {value: 'newName', configurable: true}); + assert (Object.getOwnPropertyDescriptor(func, 'name').value === 'newName'); + assertNameExists(func); + + delete func.name; + assertNameNotExists(func); + Object.defineProperty(func, 'name', desc); +} + +function assertConfigurableOnlyAccessor(func, name, method) { + let accessor = Object.getOwnPropertyDescriptor(func, name)[method]; + assertConfigurableOnlyMethod(accessor); +} + +function assertMethodName(func, name, functionName = name) { + assertNameExists(func); + assertConfigurableOnlyMethod(func) + assert(Object.getOwnPropertyDescriptor(func, 'name').value === functionName) +} + +function assertGetterName(obj, name, functionName = name) { + assertConfigurableOnlyAccessor(obj, name, 'get'); + assert(Object.getOwnPropertyDescriptor(obj, name).get['name'] === 'get ' + functionName) +} + +function assertSetterName(obj, name, functionName = name) { + assertConfigurableOnlyAccessor(obj, name, 'set'); + assert(Object.getOwnPropertyDescriptor(obj, name).set['name'] === 'set ' + functionName) +} + +var func1 = function () {}; +assertMethodName(func1, 'func1'); + +var func2 = function bar() {}; +assertMethodName(func2, 'bar'); + +var func3 = (function () {}).prototype.constructor; +assert(typeof func3 === 'function'); +assertNameNotExists(func3); + +var func4; +func4 = function () {} +assertMethodName(func4, 'func4'); + +var func5; +func5 = function bar () {} +assertMethodName(func5, 'bar'); + +var func6; +(func6) = function () {} +assertNameNotExists(func6); + +var func7; +(func7) = function bar () {} +assertMethodName(func7, 'bar'); + +let emptySymbolMethod = Symbol(); +let namedSymbolMethod = Symbol('foo'); +let emptySymbolGetter = Symbol(); +let namedSymbolGetter = Symbol('foo'); +let emptySymbolSetter = Symbol(); +let namedSymbolSetter = Symbol('foo'); + +var o = { + func1() {}, + func2: function () {}, + func3: function bar() {}, + func4: () => {}, + func5: class {}, + func6: class A {}, + func7: class name { static name () {} }, + ['func' + '8']() {}, + ['func' + '9']: function () {}, + ['func' + '10']: function bar() {}, + ['func' + '11']: () => {}, + ['func' + '12']: class {}, + ['func' + '13']: class A {}, + ['func' + '14']: class name { static name () {} }, + get func15() {}, + get ['func' + '16']() {}, + set func17(a) {}, + set ['func' + '18'](a) {}, + [emptySymbolMethod]() {}, + [namedSymbolMethod]() {}, + get [emptySymbolGetter]() {}, + get [namedSymbolGetter]() {}, + set [emptySymbolSetter](a) {}, + set [namedSymbolSetter](a) {}, +} + +assertMethodName(o.func1, 'func1'); +assertMethodName(o.func2, 'func2'); +assertMethodName(o.func3, 'bar'); +assertMethodName(o.func4, 'func4'); +assertMethodName(o.func5, 'func5'); +assertMethodName(o.func6, 'A'); +assert(typeof o.func7 === 'function'); + +assertMethodName(o.func8, 'func8'); +assertMethodName(o.func9, 'func9'); +assertMethodName(o.func10, 'bar'); +assertMethodName(o.func11, 'func11'); +assertMethodName(o.func12, 'func12'); +assertMethodName(o.func13, 'A'); +assert(typeof o.func14 === 'function'); + +assertGetterName(o, 'func15'); +assertGetterName(o, 'func16'); +assertSetterName(o, 'func17'); +assertSetterName(o, 'func17'); + +assertMethodName(o[emptySymbolMethod], ''); +assertMethodName(o[namedSymbolMethod], '[foo]'); +assertGetterName(o, emptySymbolGetter, ''); +assertGetterName(o, namedSymbolGetter, '[foo]'); +assertSetterName(o, emptySymbolSetter, ''); +assertSetterName(o, namedSymbolSetter, '[foo]'); + +class A { + constructor () {} + func1() {} + get func2() {} + set func3(a) {} + + static func4() {} + static get func5() {} + static set func6(a) {} + + ['func' + '7']() {} + get ['func' + '8']() {} + set ['func' + '9'](a) {} + + static ['func' + '10']() {} + static get ['func' + '11']() {} + static set ['func' + '12'](a) {} + + [emptySymbolMethod]() {} + [namedSymbolMethod]() {} + get [emptySymbolGetter]() {} + get [namedSymbolGetter]() {} + set [emptySymbolSetter](a) {} + set [namedSymbolSetter](a) {} + + static [emptySymbolMethod]() {} + static [namedSymbolMethod]() {} + static get [emptySymbolGetter]() {} + static get [namedSymbolGetter]() {} + static set [emptySymbolSetter](a) {} + static set [namedSymbolSetter](a) {} +} + +assertMethodName(A.prototype.func1, 'func1'); +assertGetterName(A.prototype, 'func2'); +assertSetterName(A.prototype, 'func3'); + +assertMethodName(A.func4, 'func4'); +assertGetterName(A, 'func5'); +assertSetterName(A, 'func6'); + +assertMethodName(A.prototype.func7, 'func7'); +assertGetterName(A.prototype, 'func8'); +assertSetterName(A.prototype, 'func9'); + +assertMethodName(A.func10, 'func10'); +assertGetterName(A, 'func11'); +assertSetterName(A, 'func12'); + +assertMethodName(A[emptySymbolMethod], ''); +assertMethodName(A[namedSymbolMethod], '[foo]'); +assertGetterName(A, emptySymbolGetter, ''); +assertGetterName(A, namedSymbolGetter, '[foo]'); +assertSetterName(A, emptySymbolSetter, ''); +assertSetterName(A, namedSymbolSetter, '[foo]'); + +assertMethodName(A.prototype[emptySymbolMethod], ''); +assertMethodName(A.prototype[namedSymbolMethod], '[foo]'); +assertGetterName(A.prototype, emptySymbolGetter, ''); +assertGetterName(A.prototype, namedSymbolGetter, '[foo]'); +assertSetterName(A.prototype, emptySymbolSetter, ''); +assertSetterName(A.prototype, namedSymbolSetter, '[foo]'); + +class B { + func1() {} + get func2() {} + set func3(a) {} + + static func4() {} + static get func5() {} + static set func6(a) {} + + ['func' + '7']() {} + get ['func' + '8']() {} + set ['func' + '9'](a) {} + + static ['func' + '10']() {} + static get ['func' + '11']() {} + static set ['func' + '12'](a) {} + + [emptySymbolMethod]() {} + [namedSymbolMethod]() {} + get [emptySymbolGetter]() {} + get [namedSymbolGetter]() {} + set [emptySymbolSetter](a) {} + set [namedSymbolSetter](a) {} + + static [emptySymbolMethod]() {} + static [namedSymbolMethod]() {} + static get [emptySymbolGetter]() {} + static get [namedSymbolGetter]() {} + static set [emptySymbolSetter](a) {} + static set [namedSymbolSetter](a) {} +} + +assertMethodName(B.prototype.func1, 'func1'); +assertGetterName(B.prototype, 'func2'); +assertSetterName(B.prototype, 'func3'); + +assertMethodName(B.func4, 'func4'); +assertGetterName(B, 'func5'); +assertSetterName(B, 'func6'); + +assertMethodName(B.prototype.func7, 'func7'); +assertGetterName(B.prototype, 'func8'); +assertSetterName(B.prototype, 'func9'); + +assertMethodName(B.func10, 'func10'); +assertGetterName(B, 'func11'); +assertSetterName(B, 'func12'); + +assertMethodName(B[emptySymbolMethod], ''); +assertMethodName(B[namedSymbolMethod], '[foo]'); +assertGetterName(B, emptySymbolGetter, ''); +assertGetterName(B, namedSymbolGetter, '[foo]'); +assertSetterName(B, emptySymbolSetter, ''); +assertSetterName(B, namedSymbolSetter, '[foo]'); + +assertMethodName(B.prototype[emptySymbolMethod], ''); +assertMethodName(B.prototype[namedSymbolMethod], '[foo]'); +assertGetterName(B.prototype, emptySymbolGetter, ''); +assertGetterName(B.prototype, namedSymbolGetter, '[foo]'); +assertSetterName(B.prototype, emptySymbolSetter, ''); +assertSetterName(B.prototype, namedSymbolSetter, '[foo]'); + +let names = ['push', 'pop', 'reduce', 'reduceRight']; + +for (let n of names) { + assert(Array.prototype[n].name === n); +} + +assert(Array.prototype[Symbol.iterator].name === 'values'); +assert(Array.prototype.values.name === 'values'); +assert(Object.getOwnPropertyDescriptor(Array, Symbol.species).get.name === 'get [Symbol.species]'); +assert(Object.getOwnPropertyDescriptor(String.prototype, Symbol.iterator).value.name === '[Symbol.iterator]'); +assert(Object.getOwnPropertyDescriptor(Object.prototype, '__proto__').get.name === 'get __proto__'); +assert(Object.getOwnPropertyDescriptor(Object.prototype, '__proto__').set.name === 'set __proto__'); diff --git a/tests/test262-es6-excludelist.xml b/tests/test262-es6-excludelist.xml index 6f30071221..26482f647e 100644 --- a/tests/test262-es6-excludelist.xml +++ b/tests/test262-es6-excludelist.xml @@ -1,6 +1,5 @@ - @@ -15,17 +14,6 @@ - - - - - - - - - - - @@ -41,44 +29,24 @@ - - - - - - - - - - - - - - - - - - - - @@ -124,9 +92,6 @@ - - - @@ -135,57 +100,28 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -198,11 +134,9 @@ - - @@ -210,27 +144,10 @@ - - - - - - - - - - - - - - - - - @@ -240,30 +157,17 @@ - - - - - - - - - - - - - @@ -459,7 +363,6 @@ -