From d838af7df14a949a4069bb3ac1c4244f68ccf0b7 Mon Sep 17 00:00:00 2001 From: Zoltan Herczeg Date: Thu, 16 Sep 2021 08:29:54 +0000 Subject: [PATCH] Support resource name and user value for implicit class constructors JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com --- jerry-core/api/jerry.c | 14 +- jerry-core/ecma/base/ecma-gc.c | 127 ++++--- jerry-core/ecma/base/ecma-globals.h | 30 +- jerry-core/ecma/base/ecma-helpers.c | 144 ++++---- jerry-core/ecma/base/ecma-helpers.h | 3 +- .../ecma/operations/ecma-function-object.c | 312 +++++++++++++----- jerry-core/ecma/operations/ecma-objects.c | 3 +- jerry-core/vm/opcodes.c | 114 ++----- jerry-core/vm/opcodes.h | 4 +- jerry-core/vm/vm.c | 11 +- tests/test262-esnext-excludelist.xml | 3 - tests/unit-core/test-resource-name.c | 21 ++ tests/unit-core/test-script-user-value.c | 8 + 13 files changed, 469 insertions(+), 325 deletions(-) diff --git a/jerry-core/api/jerry.c b/jerry-core/api/jerry.c index e3ae1ebf3a..e53c587dc4 100644 --- a/jerry-core/api/jerry.c +++ b/jerry-core/api/jerry.c @@ -5468,15 +5468,14 @@ jerry_get_resource_name (const jerry_value_t value) /**< jerry api value */ return ecma_copy_value (ecma_get_resource_name (JERRY_CONTEXT (vm_top_context_p)->shared_p->bytecode_header_p)); } - const ecma_compiled_code_t *bytecode_p = ecma_bytecode_get_from_value (value); + ecma_value_t script_value = ecma_script_get_from_value (value); - if (bytecode_p == NULL) + if (script_value == JMEM_CP_NULL) { return ecma_make_magic_string_value (LIT_MAGIC_STRING_RESOURCE_ANON); } - ecma_value_t script_value = ((cbc_uint8_arguments_t *) bytecode_p)->script_value; - cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + const cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); return ecma_copy_value (script_p->resource_name); #else /* !JERRY_RESOURCE_NAME */ @@ -5497,15 +5496,14 @@ jerry_get_resource_name (const jerry_value_t value) /**< jerry api value */ jerry_value_t jerry_get_user_value (const jerry_value_t value) /**< jerry api value */ { - const ecma_compiled_code_t *bytecode_p = ecma_bytecode_get_from_value (value); + ecma_value_t script_value = ecma_script_get_from_value (value); - if (bytecode_p == NULL) + if (script_value == JMEM_CP_NULL) { return ECMA_VALUE_UNDEFINED; } - ecma_value_t script_value = ((cbc_uint8_arguments_t *) bytecode_p)->script_value; - cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + const cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); if (!(script_p->refs_and_type & CBC_SCRIPT_HAS_USER_VALUE)) { diff --git a/jerry-core/ecma/base/ecma-gc.c b/jerry-core/ecma/base/ecma-gc.c index f16a0ce9c5..c4b03008c5 100644 --- a/jerry-core/ecma/base/ecma-gc.c +++ b/jerry-core/ecma/base/ecma-gc.c @@ -421,11 +421,8 @@ ecma_gc_mark_properties (ecma_object_t *object_p, /**< object */ * Mark compiled code. */ static void -ecma_gc_mark_compiled_code (const ecma_compiled_code_t *compiled_code_p) /**< compiled code */ +ecma_gc_mark_compiled_code (ecma_value_t script_value) /**< script value */ { - JERRY_ASSERT (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)); - - ecma_value_t script_value = ((cbc_uint8_arguments_t *) compiled_code_p)->script_value; cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); if (script_p->refs_and_type & CBC_SCRIPT_USER_VALUE_IS_OBJECT) @@ -895,7 +892,9 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */ const ecma_compiled_code_t *compiled_code_p; compiled_code_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, ext_object_p->u.cls.u3.value); - ecma_gc_mark_compiled_code (compiled_code_p); + + JERRY_ASSERT (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)); + ecma_gc_mark_compiled_code (((cbc_uint8_arguments_t *) compiled_code_p)->script_value); break; } #endif /* JERRY_PARSER */ @@ -934,7 +933,10 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */ if (!(module_p->header.u.cls.u2.module_flags & ECMA_MODULE_IS_NATIVE) && module_p->u.compiled_code_p != NULL) { - ecma_gc_mark_compiled_code (module_p->u.compiled_code_p); + const ecma_compiled_code_t *compiled_code_p = module_p->u.compiled_code_p; + + JERRY_ASSERT (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)); + ecma_gc_mark_compiled_code (((cbc_uint8_arguments_t *) compiled_code_p)->script_value); } ecma_module_node_t *node_p = module_p->imports_p; @@ -1095,21 +1097,16 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */ break; } #endif /* JERRY_BUILTIN_PROXY */ - case ECMA_OBJECT_TYPE_BOUND_FUNCTION: - { - ecma_gc_mark_bound_function_object (object_p); - break; - } case ECMA_OBJECT_TYPE_FUNCTION: { ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; ecma_gc_set_object_visited (ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, ext_func_p->u.function.scope_cp)); - const ecma_compiled_code_t *byte_code_p = ecma_op_function_get_compiled_code (ext_func_p); + const ecma_compiled_code_t *compiled_code_p = ecma_op_function_get_compiled_code (ext_func_p); #if JERRY_ESNEXT - if (CBC_FUNCTION_IS_ARROW (byte_code_p->status_flags)) + if (CBC_FUNCTION_IS_ARROW (compiled_code_p->status_flags)) { ecma_arrow_function_t *arrow_func_p = (ecma_arrow_function_t *) object_p; @@ -1126,25 +1123,22 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */ #endif /* JERRY_ESNEXT */ #if JERRY_SNAPSHOT_EXEC - if (JERRY_UNLIKELY (byte_code_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)) + if (JERRY_UNLIKELY (compiled_code_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)) { /* Static snapshot functions have a global realm */ break; } #endif /* JERRY_SNAPSHOT_EXEC */ - ecma_gc_mark_compiled_code (byte_code_p); + JERRY_ASSERT (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)); + ecma_gc_mark_compiled_code (((cbc_uint8_arguments_t *) compiled_code_p)->script_value); break; } -#if JERRY_BUILTIN_REALMS - case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: { - ecma_native_function_t *native_function_p = (ecma_native_function_t *) object_p; - ecma_gc_set_object_visited (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, - native_function_p->realm_value)); + ecma_gc_mark_bound_function_object (object_p); break; } -#endif /* JERRY_BUILTIN_REALMS */ #if JERRY_ESNEXT || JERRY_BUILTIN_REALMS case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: { @@ -1226,6 +1220,22 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */ break; } #endif /* JERRY_ESNEXT || JERRY_BUILTIN_REALMS */ +#if JERRY_ESNEXT + case ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION: + { + ecma_gc_mark_compiled_code (((ecma_extended_object_t *) object_p)->u.constructor_function.script_value); + break; + } +#endif /* JERRY_ESNEXT */ +#if JERRY_BUILTIN_REALMS + case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: + { + ecma_native_function_t *native_function_p = (ecma_native_function_t *) object_p; + ecma_gc_set_object_visited (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, + native_function_p->realm_value)); + break; + } +#endif /* JERRY_BUILTIN_REALMS */ default: { break; @@ -1974,40 +1984,6 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */ #endif /* JERRY_SNAPSHOT_EXEC */ break; } - case ECMA_OBJECT_TYPE_BOUND_FUNCTION: - { - ext_object_size = sizeof (ecma_bound_function_t); - ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) object_p; - - ecma_value_t args_len_or_this = bound_func_p->header.u.bound_function.args_len_or_this; - -#if JERRY_ESNEXT - ecma_free_value (bound_func_p->target_length); -#endif /* JERRY_ESNEXT */ - - if (!ecma_is_value_integer_number (args_len_or_this)) - { - ecma_free_value_if_not_object (args_len_or_this); - break; - } - - ecma_integer_value_t args_length = ecma_get_integer_from_value (args_len_or_this); - ecma_value_t *args_p = (ecma_value_t *) (bound_func_p + 1); - - for (ecma_integer_value_t i = 0; i < args_length; i++) - { - ecma_free_value_if_not_object (args_p[i]); - } - - size_t args_size = ((size_t) args_length) * sizeof (ecma_value_t); - ext_object_size += args_size; - break; - } - case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: - { - ext_object_size = sizeof (ecma_native_function_t); - break; - } case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: { ecma_extended_object_t *extended_func_p = (ecma_extended_object_t *) object_p; @@ -2071,6 +2047,47 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */ #endif /* JERRY_ESNEXT */ break; } + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + { + ext_object_size = sizeof (ecma_bound_function_t); + ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) object_p; + + ecma_value_t args_len_or_this = bound_func_p->header.u.bound_function.args_len_or_this; + +#if JERRY_ESNEXT + ecma_free_value (bound_func_p->target_length); +#endif /* JERRY_ESNEXT */ + + if (!ecma_is_value_integer_number (args_len_or_this)) + { + ecma_free_value_if_not_object (args_len_or_this); + break; + } + + ecma_integer_value_t args_length = ecma_get_integer_from_value (args_len_or_this); + ecma_value_t *args_p = (ecma_value_t *) (bound_func_p + 1); + + for (ecma_integer_value_t i = 0; i < args_length; i++) + { + ecma_free_value_if_not_object (args_p[i]); + } + + size_t args_size = ((size_t) args_length) * sizeof (ecma_value_t); + ext_object_size += args_size; + break; + } +#if JERRY_ESNEXT + case ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION: + { + ecma_script_deref (((ecma_extended_object_t *) object_p)->u.constructor_function.script_value); + break; + } +#endif /* JERRY_ESNEXT */ + case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: + { + ext_object_size = sizeof (ecma_native_function_t); + break; + } default: { JERRY_UNREACHABLE (); diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index 0a7b6187cf..6a9918f4b0 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -715,9 +715,10 @@ typedef enum ECMA_OBJECT_TYPE_PROXY = 6, /**< Proxy object ECMAScript v6 26.2 */ /* Note: these 4 types must be in this order. See IsCallable operation. */ ECMA_OBJECT_TYPE_FUNCTION = 7, /**< Function objects (15.3), created through 13.2 routine */ - ECMA_OBJECT_TYPE_BOUND_FUNCTION = 8, /**< Function objects (15.3), created through 15.3.4.5 routine */ - ECMA_OBJECT_TYPE_NATIVE_FUNCTION = 9, /**< Native function object */ - ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION = 10, /**< Native built-in function object */ + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION = 8, /**< Native built-in function object */ + ECMA_OBJECT_TYPE_BOUND_FUNCTION = 9, /**< Function objects (15.3), created through 15.3.4.5 routine */ + ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION = 10, /**< implicit class constructor function */ + ECMA_OBJECT_TYPE_NATIVE_FUNCTION = 11, /**< Native function object */ ECMA_OBJECT_TYPE__MAX /**< maximum value */ } ecma_object_type_t; @@ -1161,6 +1162,17 @@ typedef struct jmem_cpointer_tag_t target_function; /**< target function */ ecma_value_t args_len_or_this; /**< length of arguments or this value */ } bound_function; + +#if JERRY_ESNEXT + /** + * Description of implicit class constructor function. + */ + struct + { + ecma_value_t script_value; /**< script value */ + uint8_t flags; /**< constructor flags */ + } constructor_function; +#endif /* JERRY_ESNEXT */ } u; } ecma_extended_object_t; @@ -2477,8 +2489,8 @@ typedef struct */ typedef enum { - ECMA_DATE_TZA_NONE = 0, - ECMA_DATE_TZA_SET = 1 << 0, + ECMA_DATE_TZA_NONE = 0, /**< no time-zone adjustment is set */ + ECMA_DATE_TZA_SET = (1 << 0), /**< time-zone adjustment is set */ } ecma_date_object_flags_t; /** @@ -2490,6 +2502,14 @@ typedef struct ecma_number_t date_value; /**< [[DateValue]] internal property */ } ecma_date_object_t; +/** + * Implicit class constructor flags + */ +typedef enum +{ + ECMA_CONSTRUCTOR_FUNCTION_HAS_HERITAGE = (1 << 0), /**< heritage object is present */ +} ecma_constructor_function_flags_t; + #endif /* JERRY_ESNEXT */ /** diff --git a/jerry-core/ecma/base/ecma-helpers.c b/jerry-core/ecma/base/ecma-helpers.c index 4c5dda7d5e..ea43fd3acf 100644 --- a/jerry-core/ecma/base/ecma-helpers.c +++ b/jerry-core/ecma/base/ecma-helpers.c @@ -1406,6 +1406,63 @@ ecma_raise_error_from_error_reference (ecma_value_t value) /**< error reference JERRY_CONTEXT (error_value) = referenced_value; } /* ecma_raise_error_from_error_reference */ +/** + * Decrease the reference counter of a script value. + */ +void +ecma_script_deref (ecma_value_t script_value) /**< script value */ +{ + cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + script_p->refs_and_type -= CBC_SCRIPT_REF_ONE; + + if (script_p->refs_and_type >= CBC_SCRIPT_REF_ONE) + { + return; + } + + size_t script_size = sizeof (cbc_script_t); + uint32_t type = script_p->refs_and_type; + + if (type & CBC_SCRIPT_HAS_USER_VALUE) + { + script_size += sizeof (ecma_value_t); + + if (!(type & CBC_SCRIPT_USER_VALUE_IS_OBJECT)) + { + ecma_value_t user_value = CBC_SCRIPT_GET_USER_VALUE (script_p); + + JERRY_ASSERT (!ecma_is_value_object (user_value)); + ecma_free_value (user_value); + } + } + +#if JERRY_RESOURCE_NAME + ecma_deref_ecma_string (ecma_get_string_from_value (script_p->resource_name)); +#endif /* JERRY_RESOURCE_NAME */ + +#if JERRY_MODULE_SYSTEM + if (type & CBC_SCRIPT_HAS_IMPORT_META) + { + JERRY_ASSERT (!(type & CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS)); + JERRY_ASSERT (ecma_is_value_object (CBC_SCRIPT_GET_IMPORT_META (script_p, type))); + + script_size += sizeof (ecma_value_t); + } +#endif /* JERRY_MODULE_SYSTEM */ + +#if JERRY_FUNCTION_TO_STRING + ecma_deref_ecma_string (ecma_get_string_from_value (script_p->source_code)); + + if (type & CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS) + { + ecma_deref_ecma_string (ecma_get_string_from_value (CBC_SCRIPT_GET_FUNCTION_ARGUMENTS (script_p, type))); + script_size += sizeof (ecma_value_t); + } +#endif /* JERRY_FUNCTION_TO_STRING */ + + jmem_heap_free_block (script_p, script_size); +} /* ecma_script_deref */ + /** * Increase reference counter of Compact * Byte Code or regexp byte code. @@ -1478,53 +1535,7 @@ ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p) /**< byte code pointer */ } } - ecma_value_t script_value = ((cbc_uint8_arguments_t *) bytecode_p)->script_value; - cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); - script_p->refs_and_type -= CBC_SCRIPT_REF_ONE; - - if (script_p->refs_and_type < CBC_SCRIPT_REF_ONE) - { - size_t script_size = sizeof (cbc_script_t); - uint32_t type = script_p->refs_and_type; - - if (type & CBC_SCRIPT_HAS_USER_VALUE) - { - script_size += sizeof (ecma_value_t); - - if (!(type & CBC_SCRIPT_USER_VALUE_IS_OBJECT)) - { - ecma_value_t user_value = CBC_SCRIPT_GET_USER_VALUE (script_p); - - JERRY_ASSERT (!ecma_is_value_object (user_value)); - ecma_free_value (user_value); - } - } - -#if JERRY_RESOURCE_NAME - ecma_deref_ecma_string (ecma_get_string_from_value (script_p->resource_name)); -#endif /* JERRY_RESOURCE_NAME */ - -#if JERRY_MODULE_SYSTEM - if (type & CBC_SCRIPT_HAS_IMPORT_META) - { - JERRY_ASSERT (ecma_is_value_object (CBC_SCRIPT_GET_IMPORT_META (script_p, type))); - - script_size += sizeof (ecma_value_t); - } -#endif /* JERRY_MODULE_SYSTEM */ - -#if JERRY_FUNCTION_TO_STRING - ecma_deref_ecma_string (ecma_get_string_from_value (script_p->source_code)); - - if (type & CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS) - { - ecma_deref_ecma_string (ecma_get_string_from_value (CBC_SCRIPT_GET_FUNCTION_ARGUMENTS (script_p, type))); - script_size += sizeof (ecma_value_t); - } -#endif /* JERRY_FUNCTION_TO_STRING */ - - jmem_heap_free_block (script_p, script_size); - } + ecma_script_deref (((cbc_uint8_arguments_t *) bytecode_p)->script_value); #if JERRY_ESNEXT if (bytecode_p->status_flags & CBC_CODE_FLAGS_HAS_TAGGED_LITERALS) @@ -1597,19 +1608,20 @@ ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p) /**< byte code pointer */ } /* ecma_bytecode_deref */ /** - * Gets the byte code asigned to a script / module / function + * Gets the script data asigned to a script / module / function * - * @return byte code - if available, NULL - otherwise + * @return script data - if available, JMEM_CP_NULL - otherwise */ -const ecma_compiled_code_t * -ecma_bytecode_get_from_value (ecma_value_t value) /**< compiled code */ +ecma_value_t +ecma_script_get_from_value (ecma_value_t value) /**< compiled code */ { if (!ecma_is_value_object (value)) { - return NULL; + return JMEM_CP_NULL; } ecma_object_t *object_p = ecma_get_object_from_value (value); + const ecma_compiled_code_t *bytecode_p = NULL; while (true) { @@ -1621,8 +1633,9 @@ ecma_bytecode_get_from_value (ecma_value_t value) /**< compiled code */ if (ext_object_p->u.cls.type == ECMA_OBJECT_CLASS_SCRIPT) { - return ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, - ext_object_p->u.cls.u3.value); + bytecode_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, + ext_object_p->u.cls.u3.value); + break; } #if JERRY_MODULE_SYSTEM @@ -1632,15 +1645,17 @@ ecma_bytecode_get_from_value (ecma_value_t value) /**< compiled code */ if (!(module_p->header.u.cls.u2.module_flags & ECMA_MODULE_IS_NATIVE)) { - return module_p->u.compiled_code_p; + bytecode_p = module_p->u.compiled_code_p; + break; } } #endif /* JERRY_MODULE_SYSTEM */ - return NULL; + return JMEM_CP_NULL; } case ECMA_OBJECT_TYPE_FUNCTION: { - return ecma_op_function_get_compiled_code ((ecma_extended_object_t *) object_p); + bytecode_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) object_p); + break; } case ECMA_OBJECT_TYPE_BOUND_FUNCTION: { @@ -1648,15 +1663,24 @@ ecma_bytecode_get_from_value (ecma_value_t value) /**< compiled code */ object_p = ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, ext_object_p->u.bound_function.target_function); - break; + continue; + } +#if JERRY_ESNEXT + case ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION: + { + return ((ecma_extended_object_t *) object_p)->u.constructor_function.script_value; } +#endif /* JERRY_ESNEXT */ default: { - return NULL; + return JMEM_CP_NULL; } } + + JERRY_ASSERT (bytecode_p != NULL); + return ((cbc_uint8_arguments_t *) bytecode_p)->script_value; } -} /* ecma_bytecode_get_from_value */ +} /* ecma_script_get_from_value */ /** * Resolve the position of the arguments list start of the compiled code diff --git a/jerry-core/ecma/base/ecma-helpers.h b/jerry-core/ecma/base/ecma-helpers.h index 11a41f101e..2a787f1b32 100644 --- a/jerry-core/ecma/base/ecma-helpers.h +++ b/jerry-core/ecma/base/ecma-helpers.h @@ -531,9 +531,10 @@ ecma_value_t ecma_create_error_reference_from_context (void); ecma_value_t ecma_create_error_object_reference (ecma_object_t *object_p); void ecma_raise_error_from_error_reference (ecma_value_t value); +void ecma_script_deref (ecma_value_t script_value); void ecma_bytecode_ref (ecma_compiled_code_t *bytecode_p); void ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p); -const ecma_compiled_code_t *ecma_bytecode_get_from_value (ecma_value_t value); +ecma_value_t ecma_script_get_from_value (ecma_value_t value); ecma_value_t *ecma_compiled_code_resolve_arguments_start (const ecma_compiled_code_t *bytecode_header_p); #if JERRY_ESNEXT ecma_value_t *ecma_compiled_code_resolve_function_name (const ecma_compiled_code_t *bytecode_header_p); diff --git a/jerry-core/ecma/operations/ecma-function-object.c b/jerry-core/ecma/operations/ecma-function-object.c index eb8dcb07e4..7506397cf6 100644 --- a/jerry-core/ecma/operations/ecma-function-object.c +++ b/jerry-core/ecma/operations/ecma-function-object.c @@ -29,6 +29,7 @@ #include "ecma-proxy-object.h" #include "ecma-symbol-object.h" #include "jcontext.h" +#include "opcodes.h" /** \addtogroup ecma ECMA * @{ @@ -224,7 +225,8 @@ ecma_object_check_constructor (ecma_object_t *obj_p) /**< ecma object */ #endif /* JERRY_BUILTIN_PROXY */ JERRY_ASSERT (type == ECMA_OBJECT_TYPE_NATIVE_FUNCTION - || type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + || type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION + || type == ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION); if (type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION) { @@ -803,7 +805,17 @@ ecma_op_function_get_function_realm (ecma_object_t *func_obj_p) /**< function ob native_function_p->realm_value); } - #if JERRY_BUILTIN_PROXY +#if JERRY_ESNEXT + if (type == ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION) + { + ecma_value_t script_value = ((ecma_extended_object_t *) func_obj_p)->u.constructor_function.script_value; + cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + + return (ecma_global_object_t *) script_p->realm_p; + } +#endif /* JERRY_ESNEXT */ + +#if JERRY_BUILTIN_PROXY if (ECMA_OBJECT_IS_PROXY (func_obj_p)) { ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) func_obj_p; @@ -815,7 +827,7 @@ ecma_op_function_get_function_realm (ecma_object_t *func_obj_p) /**< function ob func_obj_p = ecma_get_object_from_value (proxy_obj_p->target); continue; } - #endif /* JERRY_BUILTIN_PROXY */ +#endif /* JERRY_BUILTIN_PROXY */ JERRY_ASSERT (type == ECMA_OBJECT_TYPE_BOUND_FUNCTION); ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) func_obj_p; @@ -857,8 +869,9 @@ ecma_op_function_has_instance (ecma_object_t *func_obj_p, /**< Function object * } JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION - || ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_NATIVE_FUNCTION || ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION + || ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION + || ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_NATIVE_FUNCTION || ECMA_OBJECT_IS_PROXY (func_obj_p)); ecma_object_t *v_obj_p = ecma_get_object_from_value (value); @@ -1389,6 +1402,12 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */ { result = ecma_op_function_call_native (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len); } +#if JERRY_ESNEXT + else if (JERRY_UNLIKELY (type == ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION)) + { + result = ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_class_constructor_new)); + } +#endif /* JERRY_ESNEXT */ else { result = ecma_op_function_call_bound (func_obj_p, arguments_list_p, arguments_list_len); @@ -1401,6 +1420,118 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */ return result; } /* ecma_op_function_call */ +/** + * [[Construct]] internal method for ECMAScript function objects + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +static ecma_value_t +ecma_op_function_construct_simple (ecma_object_t *func_obj_p, /**< Function object */ + ecma_object_t *new_target_p, /**< new target */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION); + + ecma_object_t *new_this_obj_p = NULL; + ecma_value_t this_arg; + +#if JERRY_ESNEXT + ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) func_obj_p; + + /* 5. */ + if (!ECMA_GET_THIRD_BIT_FROM_POINTER_TAG (ext_func_obj_p->u.function.scope_cp)) + { +#endif /* JERRY_ESNEXT */ + /* 5.a */ + ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (new_target_p, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); + + /* 5.b */ + if (JERRY_UNLIKELY (proto_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + new_this_obj_p = ecma_create_object (proto_p, 0, ECMA_OBJECT_TYPE_GENERAL); + ecma_deref_object (proto_p); + this_arg = ecma_make_object_value (new_this_obj_p); +#if JERRY_ESNEXT + } + else + { + this_arg = ECMA_VALUE_UNDEFINED; + } + + /* 6. */ + ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target_p); + JERRY_CONTEXT (current_new_target_p) = new_target_p; +#endif /* JERRY_ESNEXT */ + + ecma_value_t ret_value = ecma_op_function_call_simple (func_obj_p, this_arg, arguments_list_p, arguments_list_len); + +#if JERRY_ESNEXT + JERRY_CONTEXT (current_new_target_p) = old_new_target_p; +#endif /* JERRY_ESNEXT */ + + /* 13.a */ + if (ECMA_IS_VALUE_ERROR (ret_value) || ecma_is_value_object (ret_value)) + { +#if JERRY_ESNEXT + if (new_this_obj_p != NULL) + { + ecma_deref_object (new_this_obj_p); + } +#else /* !JERRY_ESNEXT */ + ecma_deref_object (new_this_obj_p); +#endif /* JERRY_ESNEXT */ + return ret_value; + } + + /* 13.b */ + ecma_free_value (ret_value); + return this_arg; +} /* ecma_op_function_construct_simple */ + +/** + * [[Construct]] internal method for built-in function objects + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +static ecma_value_t +ecma_op_function_construct_built_in (ecma_object_t *func_obj_p, /**< Function object */ + ecma_object_t *new_target_p, /**< new target */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + JERRY_UNUSED (new_target_p); + + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + +#if JERRY_BUILTIN_REALMS + ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p); + ecma_value_t realm_value = ((ecma_extended_object_t *) func_obj_p)->u.built_in.realm_value; + JERRY_CONTEXT (global_object_p) = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, realm_value); +#endif /* JERRY_BUILTIN_REALMS */ + +#if JERRY_ESNEXT + ecma_object_t *old_new_target = JERRY_CONTEXT (current_new_target_p); + JERRY_CONTEXT (current_new_target_p) = new_target_p; +#endif /* JERRY_ESNEXT */ + + ecma_value_t ret_value = ecma_builtin_dispatch_construct (func_obj_p, arguments_list_p, arguments_list_len); + +#if JERRY_ESNEXT + JERRY_CONTEXT (current_new_target_p) = old_new_target; +#endif /* JERRY_ESNEXT */ + +#if JERRY_BUILTIN_REALMS + JERRY_CONTEXT (global_object_p) = saved_global_object_p; +#endif /* JERRY_BUILTIN_REALMS */ + return ret_value; +} /* ecma_op_function_construct_built_in */ + /** * [[Construct]] internal method for bound function objects * @@ -1437,6 +1568,78 @@ ecma_op_function_construct_bound (ecma_object_t *func_obj_p, /**< Function objec return ret_value; } /* ecma_op_function_construct_bound */ +#if JERRY_ESNEXT + +/** + * [[Construct]] internal method for class implicit constructor objects + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +static ecma_value_t +ecma_op_function_construct_constructor (ecma_object_t *func_obj_p, /**< Function object */ + ecma_object_t *new_target_p, /**< new target */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION); + + ecma_extended_object_t *constructor_object_p = (ecma_extended_object_t *) func_obj_p; + + if (!(constructor_object_p->u.constructor_function.flags & ECMA_CONSTRUCTOR_FUNCTION_HAS_HERITAGE)) + { + ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (new_target_p, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); + + if (JERRY_UNLIKELY (proto_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_object_t *new_this_object_p = ecma_create_object (proto_p, 0, ECMA_OBJECT_TYPE_GENERAL); + ecma_deref_object (proto_p); + + jerry_value_t new_this_value = ecma_make_object_value (new_this_object_p); + jerry_value_t ret_value = opfunc_init_class_fields (func_obj_p, new_this_value); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_deref_object (new_this_object_p); + return ret_value; + } + + return new_this_value; + } + + ecma_value_t super_ctor = ecma_op_function_get_super_constructor (func_obj_p); + + if (ECMA_IS_VALUE_ERROR (super_ctor)) + { + return super_ctor; + } + + ecma_object_t *super_ctor_p = ecma_get_object_from_value (super_ctor); + ecma_value_t result = ecma_op_function_construct (super_ctor_p, + new_target_p, + arguments_list_p, + arguments_list_len); + ecma_deref_object (super_ctor_p); + + if (ecma_is_value_object (result)) + { + ecma_value_t fields_value = opfunc_init_class_fields (func_obj_p, result); + + if (ECMA_IS_VALUE_ERROR (fields_value)) + { + ecma_free_value (result); + return fields_value; + } + } + + return result; +} /* ecma_op_function_construct_constructor */ + +#endif /* JERRY_ESNEXT */ + /** * [[Construct]] internal method for external function objects * @@ -1503,110 +1706,37 @@ ecma_op_function_construct (ecma_object_t *func_obj_p, /**< Function object */ const ecma_object_type_t type = ecma_get_object_type (func_obj_p); -#if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_TYPE_IS_PROXY (type)) + if (JERRY_LIKELY (type == ECMA_OBJECT_TYPE_FUNCTION)) { - return ecma_proxy_object_construct (func_obj_p, - new_target_p, - arguments_list_p, - arguments_list_len); + return ecma_op_function_construct_simple (func_obj_p, new_target_p, arguments_list_p, arguments_list_len); } -#endif /* JERRY_BUILTIN_PROXY */ - if (JERRY_UNLIKELY (type == ECMA_OBJECT_TYPE_BOUND_FUNCTION)) + if (type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION) { - return ecma_op_function_construct_bound (func_obj_p, new_target_p, arguments_list_p, arguments_list_len); + return ecma_op_function_construct_built_in (func_obj_p, new_target_p, arguments_list_p, arguments_list_len); } - if (JERRY_UNLIKELY (type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION)) +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_TYPE_IS_PROXY (type)) { -#if JERRY_BUILTIN_REALMS - ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p); - ecma_value_t realm_value = ((ecma_extended_object_t *) func_obj_p)->u.built_in.realm_value; - JERRY_CONTEXT (global_object_p) = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, realm_value); -#endif /* JERRY_BUILTIN_REALMS */ - -#if JERRY_ESNEXT - ecma_object_t *old_new_target = JERRY_CONTEXT (current_new_target_p); - JERRY_CONTEXT (current_new_target_p) = new_target_p; -#endif /* JERRY_ESNEXT */ - - ecma_value_t ret_value = ecma_builtin_dispatch_construct (func_obj_p, arguments_list_p, arguments_list_len); - -#if JERRY_ESNEXT - JERRY_CONTEXT (current_new_target_p) = old_new_target; -#endif /* JERRY_ESNEXT */ - -#if JERRY_BUILTIN_REALMS - JERRY_CONTEXT (global_object_p) = saved_global_object_p; -#endif /* JERRY_BUILTIN_REALMS */ - return ret_value; + return ecma_proxy_object_construct (func_obj_p, new_target_p, arguments_list_p, arguments_list_len); } +#endif /* JERRY_BUILTIN_PROXY */ - if (JERRY_UNLIKELY (type == ECMA_OBJECT_TYPE_NATIVE_FUNCTION)) + if (JERRY_UNLIKELY (type == ECMA_OBJECT_TYPE_BOUND_FUNCTION)) { - return ecma_op_function_construct_native (func_obj_p, new_target_p, arguments_list_p, arguments_list_len); + return ecma_op_function_construct_bound (func_obj_p, new_target_p, arguments_list_p, arguments_list_len); } - JERRY_ASSERT (type == ECMA_OBJECT_TYPE_FUNCTION); - - ecma_object_t *new_this_obj_p = NULL; - ecma_value_t this_arg; - #if JERRY_ESNEXT - ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) func_obj_p; - - /* 5. */ - if (!ECMA_GET_THIRD_BIT_FROM_POINTER_TAG (ext_func_obj_p->u.function.scope_cp)) + if (type == ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION) { -#endif /* JERRY_ESNEXT */ - /* 5.a */ - ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (new_target_p, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); - - /* 5.b */ - if (JERRY_UNLIKELY (proto_p == NULL)) - { - return ECMA_VALUE_ERROR; - } - - new_this_obj_p = ecma_create_object (proto_p, 0, ECMA_OBJECT_TYPE_GENERAL); - ecma_deref_object (proto_p); - this_arg = ecma_make_object_value (new_this_obj_p); -#if JERRY_ESNEXT + return ecma_op_function_construct_constructor (func_obj_p, new_target_p, arguments_list_p, arguments_list_len); } - else - { - this_arg = ECMA_VALUE_UNDEFINED; - } - - /* 6. */ - ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target_p); - JERRY_CONTEXT (current_new_target_p) = new_target_p; -#endif /* JERRY_ESNEXT */ - - ecma_value_t ret_value = ecma_op_function_call_simple (func_obj_p, this_arg, arguments_list_p, arguments_list_len); - -#if JERRY_ESNEXT - JERRY_CONTEXT (current_new_target_p) = old_new_target_p; -#endif /* JERRY_ESNEXT */ - - /* 13.a */ - if (ECMA_IS_VALUE_ERROR (ret_value) || ecma_is_value_object (ret_value)) - { -#if JERRY_ESNEXT - if (new_this_obj_p != NULL) - { - ecma_deref_object (new_this_obj_p); - } -#else /* !JERRY_ESNEXT */ - ecma_deref_object (new_this_obj_p); #endif /* JERRY_ESNEXT */ - return ret_value; - } - /* 13.b */ - ecma_free_value (ret_value); - return this_arg; + JERRY_ASSERT (type == ECMA_OBJECT_TYPE_NATIVE_FUNCTION); + return ecma_op_function_construct_native (func_obj_p, new_target_p, arguments_list_p, arguments_list_len); } /* ecma_op_function_construct */ /** diff --git a/jerry-core/ecma/operations/ecma-objects.c b/jerry-core/ecma/operations/ecma-objects.c index 8562fe80a4..846631d05a 100644 --- a/jerry-core/ecma/operations/ecma-objects.c +++ b/jerry-core/ecma/operations/ecma-objects.c @@ -2376,7 +2376,8 @@ ecma_object_list_lazy_property_names (ecma_object_t *obj_p, /**< object */ } default: { - JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_GENERAL); + JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_GENERAL + || ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION); break; } } diff --git a/jerry-core/vm/opcodes.c b/jerry-core/vm/opcodes.c index 7767838292..4ad26b1a5d 100644 --- a/jerry-core/vm/opcodes.c +++ b/jerry-core/vm/opcodes.c @@ -914,14 +914,12 @@ opfunc_async_create_and_await (vm_frame_ctx_t *frame_ctx_p, /**< frame context * * ECMA_VALUE_UNDEFINED - otherwise */ ecma_value_t -opfunc_init_class_fields (ecma_value_t class_object, /**< the function itself */ +opfunc_init_class_fields (ecma_object_t *class_object_p, /**< the function itself */ ecma_value_t this_val) /**< this_arg of the function */ { - JERRY_ASSERT (ecma_is_value_object (class_object)); JERRY_ASSERT (ecma_is_value_object (this_val)); ecma_string_t *name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_INIT); - ecma_object_t *class_object_p = ecma_get_object_from_value (class_object); ecma_property_t *property_p = ecma_find_named_property (class_object_p, name_p); if (property_p == NULL) @@ -1048,78 +1046,6 @@ opfunc_add_computed_field (ecma_value_t class_object, /**< class object */ return ECMA_VALUE_UNDEFINED; } /* opfunc_add_computed_field */ -/** - * Implicit class constructor handler when the classHeritage is not present. - * - * See also: ECMAScript v6, 14.5.14.10.b.i - * - * @return ECMA_VALUE_ERROR - if the function was invoked without 'new' - * ECMA_VALUE_UNDEFINED - otherwise - */ -static ecma_value_t -ecma_op_implicit_constructor_handler_cb (const jerry_call_info_t *call_info_p, /**< call information */ - const ecma_value_t args_p[], /**< argument list */ - const uint32_t args_count) /**< argument number */ -{ - JERRY_UNUSED_2 (args_p, args_count); - - if (JERRY_CONTEXT (current_new_target_p) == NULL) - { - return ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_class_constructor_new)); - } - - return opfunc_init_class_fields (call_info_p->function, call_info_p->this_value); -} /* ecma_op_implicit_constructor_handler_cb */ - -/** - * Implicit class constructor handler when the classHeritage is present. - * - * See also: ECMAScript v6, 14.5.14.10.a.i - * - * @return ECMA_VALUE_ERROR - if the operation fails - * result of the super call - otherwise - */ -static ecma_value_t -ecma_op_implicit_constructor_handler_heritage_cb (const jerry_call_info_t *call_info_p, /**< call information */ - const ecma_value_t args_p[], /**< argument list */ - const uint32_t args_count) /**< argument number */ -{ - if (JERRY_CONTEXT (current_new_target_p) == NULL) - { - return ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_class_constructor_new)); - } - - ecma_object_t *func_obj_p = ecma_get_object_from_value (call_info_p->function); - ecma_value_t super_ctor = ecma_op_function_get_super_constructor (func_obj_p); - - if (ECMA_IS_VALUE_ERROR (super_ctor)) - { - return super_ctor; - } - - ecma_object_t *super_ctor_p = ecma_get_object_from_value (super_ctor); - - ecma_value_t result = ecma_op_function_construct (super_ctor_p, - JERRY_CONTEXT (current_new_target_p), - args_p, - args_count); - - if (ecma_is_value_object (result)) - { - ecma_value_t fields_value = opfunc_init_class_fields (call_info_p->function, result); - - if (ECMA_IS_VALUE_ERROR (fields_value)) - { - ecma_free_value (result); - result = ECMA_VALUE_ERROR; - } - } - - ecma_deref_object (super_ctor_p); - - return result; -} /* ecma_op_implicit_constructor_handler_heritage_cb */ - /** * Create implicit class constructor * @@ -1128,40 +1054,42 @@ ecma_op_implicit_constructor_handler_heritage_cb (const jerry_call_info_t *call_ * @return - new external function ecma-object */ ecma_value_t -opfunc_create_implicit_class_constructor (uint8_t opcode) /**< current cbc opcode */ +opfunc_create_implicit_class_constructor (uint8_t opcode, /**< current cbc opcode */ + const ecma_compiled_code_t *bytecode_p) /**< current byte code */ { /* 8. */ - ecma_object_t *function_obj_p = ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE), - sizeof (ecma_native_function_t), - ECMA_OBJECT_TYPE_NATIVE_FUNCTION); + ecma_value_t script_value = ((cbc_uint8_arguments_t *) bytecode_p)->script_value; + cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value); + + if (JERRY_UNLIKELY (script_p->refs_and_type >= CBC_SCRIPT_REF_MAX)) + { + jerry_fatal (ERR_REF_COUNT_LIMIT); + } - ecma_native_function_t *native_function_p = (ecma_native_function_t *) function_obj_p; + ecma_object_t *function_object_p = ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE), + sizeof (ecma_extended_object_t), + ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION); -#if JERRY_BUILTIN_REALMS - ECMA_SET_INTERNAL_VALUE_POINTER (native_function_p->realm_value, - ecma_builtin_get_global ()); -#endif /* JERRY_BUILTIN_REALMS */ + ecma_extended_object_t *constructor_object_p = (ecma_extended_object_t *) function_object_p; + + script_p->refs_and_type += CBC_SCRIPT_REF_ONE; + constructor_object_p->u.constructor_function.script_value = script_value; + constructor_object_p->u.constructor_function.flags = 0; /* 10.a.i */ if (opcode == CBC_EXT_PUSH_IMPLICIT_CONSTRUCTOR_HERITAGE) { - native_function_p->native_handler_cb = ecma_op_implicit_constructor_handler_heritage_cb; - } - /* 10.b.i */ - else - { - native_function_p->native_handler_cb = ecma_op_implicit_constructor_handler_cb; + constructor_object_p->u.constructor_function.flags |= ECMA_CONSTRUCTOR_FUNCTION_HAS_HERITAGE; } ecma_property_value_t *prop_value_p; - prop_value_p = ecma_create_named_data_property (function_obj_p, + prop_value_p = ecma_create_named_data_property (function_object_p, ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), ECMA_PROPERTY_FLAG_CONFIGURABLE, NULL); - prop_value_p->value = ecma_make_uint32_value (0); - return ecma_make_object_value (function_obj_p); + return ecma_make_object_value (function_object_p); } /* opfunc_create_implicit_class_constructor */ /** diff --git a/jerry-core/vm/opcodes.h b/jerry-core/vm/opcodes.h index 0a4fa92be6..a4bfa3a98c 100644 --- a/jerry-core/vm/opcodes.h +++ b/jerry-core/vm/opcodes.h @@ -142,7 +142,7 @@ ecma_value_t opfunc_async_create_and_await (vm_frame_ctx_t *frame_ctx_p, ecma_value_t value, uint16_t extra_flags); ecma_value_t -opfunc_init_class_fields (ecma_value_t class_object, ecma_value_t this_val); +opfunc_init_class_fields (ecma_object_t *class_object_p, ecma_value_t this_val); ecma_value_t opfunc_init_static_class_fields (ecma_value_t function_object, ecma_value_t this_val); @@ -151,7 +151,7 @@ ecma_value_t opfunc_add_computed_field (ecma_value_t class_object, ecma_value_t name); ecma_value_t -opfunc_create_implicit_class_constructor (uint8_t opcode); +opfunc_create_implicit_class_constructor (uint8_t opcode, const ecma_compiled_code_t *bytecode_p); void opfunc_set_home_object (ecma_object_t *func_p, ecma_object_t *parent_env_p); diff --git a/jerry-core/vm/vm.c b/jerry-core/vm/vm.c index dfd1a98efe..3707a96088 100644 --- a/jerry-core/vm/vm.c +++ b/jerry-core/vm/vm.c @@ -620,8 +620,7 @@ vm_super_call (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ if (ecma_is_value_object (completion_value)) { - ecma_value_t current_function = ecma_make_object_value (vm_get_class_function (frame_ctx_p)); - ecma_value_t fields_value = opfunc_init_class_fields (current_function, completion_value); + ecma_value_t fields_value = opfunc_init_class_fields (vm_get_class_function (frame_ctx_p), completion_value); if (ECMA_IS_VALUE_ERROR (fields_value)) { @@ -2065,7 +2064,8 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } case VM_OC_PUSH_IMPLICIT_CTOR: { - *stack_top_p++ = opfunc_create_implicit_class_constructor (opcode); + *stack_top_p++ = opfunc_create_implicit_class_constructor (opcode, + frame_ctx_p->shared_p->bytecode_header_p); continue; } case VM_OC_INIT_CLASS: @@ -2120,8 +2120,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ case VM_OC_RUN_FIELD_INIT: { JERRY_ASSERT (frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_NON_ARROW_FUNC); - result = opfunc_init_class_fields (ecma_make_object_value (frame_ctx_p->shared_p->function_object_p), - frame_ctx_p->this_binding); + result = opfunc_init_class_fields (frame_ctx_p->shared_p->function_object_p, frame_ctx_p->this_binding); if (ECMA_IS_VALUE_ERROR (result)) { @@ -2279,7 +2278,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ ECMA_PROPERTY_FLAG_CONFIGURABLE, NULL); - if (ecma_get_object_type (func_obj_p) != ECMA_OBJECT_TYPE_NATIVE_FUNCTION) + if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION) { ECMA_SET_SECOND_BIT_TO_POINTER_TAG (((ecma_extended_object_t *) func_obj_p)->u.function.scope_cp); } diff --git a/tests/test262-esnext-excludelist.xml b/tests/test262-esnext-excludelist.xml index 6829dc4430..6d14700516 100644 --- a/tests/test262-esnext-excludelist.xml +++ b/tests/test262-esnext-excludelist.xml @@ -2469,7 +2469,6 @@ - @@ -4047,7 +4046,6 @@ - @@ -7952,7 +7950,6 @@ - diff --git a/tests/unit-core/test-resource-name.c b/tests/unit-core/test-resource-name.c index 7e6087b385..2893bcc2c8 100644 --- a/tests/unit-core/test-resource-name.c +++ b/tests/unit-core/test-resource-name.c @@ -214,6 +214,27 @@ main (void) jerry_release_value (parse_options.resource_name); jerry_release_value (program); + const char *source_6 = "(class {})"; + + parse_options.options = JERRY_PARSE_HAS_RESOURCE; + parse_options.resource_name = jerry_create_string ((jerry_char_t *) "demo6.js"); + + program = jerry_parse ((const jerry_char_t *) source_6, + strlen (source_6), + &parse_options); + if (!jerry_value_is_error (program)) + { + resource_value = jerry_get_resource_name (program); + compare_result = jerry_binary_operation (JERRY_BIN_OP_STRICT_EQUAL, resource_value, parse_options.resource_name); + TEST_ASSERT (jerry_value_is_true (compare_result)); + + jerry_release_value (resource_value); + jerry_release_value (compare_result); + } + + jerry_release_value (parse_options.resource_name); + jerry_release_value (program); + jerry_cleanup (); return 0; diff --git a/tests/unit-core/test-script-user-value.c b/tests/unit-core/test-script-user-value.c index 2d04d858ca..67a5bd20cd 100644 --- a/tests/unit-core/test-script-user-value.c +++ b/tests/unit-core/test-script-user-value.c @@ -138,6 +138,14 @@ main (void) parse_options.options = JERRY_PARSE_HAS_USER_VALUE; test_parse_function (source_p, &parse_options, true); + /* There is no test for ESNEXT, using SYMBOL instead. */ + if (jerry_is_feature_enabled (JERRY_FEATURE_SYMBOL)) + { + source_p = TEST_STRING_LITERAL ("(class {})"); + parse_options.options = JERRY_PARSE_HAS_USER_VALUE; + test_parse (source_p, &parse_options, true); + } + source_p = TEST_STRING_LITERAL ("eval('function f() {}')\n" "f"); parse_options.options = JERRY_PARSE_HAS_USER_VALUE;