diff --git a/jerry-core/api/jerry.c b/jerry-core/api/jerry.c index 35f52ab0c..362a13435 100644 --- a/jerry-core/api/jerry.c +++ b/jerry-core/api/jerry.c @@ -3585,7 +3585,7 @@ jerry_get_new_target (void) #if ENABLED (JERRY_ES2015) ecma_object_t *current_new_target = JERRY_CONTEXT (current_new_target); - if (current_new_target == NULL || current_new_target == JERRY_CONTEXT_INVALID_NEW_TARGET) + if (current_new_target == NULL) { return jerry_create_undefined (); } diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index dd85aa5ff..ae207cae2 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -111,13 +111,13 @@ typedef enum ECMA_PARSE_EVAL = (1u << 2), /**< eval is called */ ECMA_PARSE_DIRECT_EVAL = (1u << 3), /**< eval is called directly (ECMA-262 v5, 15.1.2.1.1) */ - /* These three status flags must be in this order. See PARSER_SAVED_FLAGS_OFFSET. */ + /* These 4 status flags must be in this order. See PARSER_SAVED_FLAGS_OFFSET. */ ECMA_PARSE_CLASS_CONSTRUCTOR = (1u << 4), /**< a class constructor is being parsed (this value must be kept in * in sync with PARSER_CLASS_CONSTRUCTOR) */ ECMA_PARSE_ALLOW_SUPER = (1u << 5), /**< allow super property access */ ECMA_PARSE_ALLOW_SUPER_CALL = (1u << 6), /**< allow super constructor call */ + ECMA_PARSE_ALLOW_NEW_TARGET = (1u << 7), /**< allow new.target access */ - ECMA_PARSE_CALLED_FROM_FUNCTION = (1u << 7), /**< a function body is parsed or the code is inside a function */ ECMA_PARSE_GENERATOR_FUNCTION = (1u << 8), /**< generator function is parsed */ /* These flags are internally used by the parser. */ diff --git a/jerry-core/ecma/base/ecma-init-finalize.c b/jerry-core/ecma/base/ecma-init-finalize.c index e0bca19f3..6e67eb22c 100644 --- a/jerry-core/ecma/base/ecma-init-finalize.c +++ b/jerry-core/ecma/base/ecma-init-finalize.c @@ -61,7 +61,7 @@ ecma_init (void) #endif /* ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */ #if ENABLED (JERRY_ES2015) - JERRY_CONTEXT (current_new_target) = JERRY_CONTEXT_INVALID_NEW_TARGET; + JERRY_CONTEXT (current_new_target) = NULL; JERRY_CONTEXT (current_function_obj_p) = NULL; #endif /* ENABLED (JERRY_ES2015) */ } /* ecma_init */ @@ -73,7 +73,7 @@ void ecma_finalize (void) { #if ENABLED (JERRY_ES2015) - JERRY_ASSERT (JERRY_CONTEXT (current_new_target) == JERRY_CONTEXT_INVALID_NEW_TARGET); + JERRY_ASSERT (JERRY_CONTEXT (current_new_target) == NULL); JERRY_ASSERT (JERRY_CONTEXT (current_function_obj_p) == NULL); #endif /* ENABLED (JERRY_ES2015) */ diff --git a/jerry-core/ecma/operations/ecma-eval.c b/jerry-core/ecma/operations/ecma-eval.c index 2759236db..69cc4546e 100644 --- a/jerry-core/ecma/operations/ecma-eval.c +++ b/jerry-core/ecma/operations/ecma-eval.c @@ -99,13 +99,6 @@ ecma_op_eval_chars_buffer (const lit_utf8_byte_t *code_p, /**< code characters b #if ENABLED (JERRY_ES2015) ECMA_CLEAR_LOCAL_PARSE_OPTS (); - - /* If a direct eval is used inside the function the info should be propagated. */ - if (JERRY_CONTEXT (current_new_target) != JERRY_CONTEXT_INVALID_NEW_TARGET - && (JERRY_CONTEXT (status_flags) & ECMA_STATUS_DIRECT_EVAL)) - { - parse_opts |= ECMA_PARSE_CALLED_FROM_FUNCTION; - } #endif /* ENABLED (JERRY_ES2015) */ ecma_value_t parse_status = parser_parse_script (NULL, diff --git a/jerry-core/ecma/operations/ecma-function-object.c b/jerry-core/ecma/operations/ecma-function-object.c index b2bcda531..dadd26ba1 100644 --- a/jerry-core/ecma/operations/ecma-function-object.c +++ b/jerry-core/ecma/operations/ecma-function-object.c @@ -445,11 +445,7 @@ ecma_op_create_arrow_function_object (ecma_object_t *scope_p, /**< function's sc arrow_func_p->this_binding = ecma_copy_value_if_not_object (this_binding); arrow_func_p->new_target = ECMA_VALUE_UNDEFINED; - if (JERRY_CONTEXT (current_new_target) == JERRY_CONTEXT_INVALID_NEW_TARGET) - { - arrow_func_p->new_target = ECMA_VALUE_EMPTY; - } - else if (JERRY_CONTEXT (current_new_target) != NULL) + if (JERRY_CONTEXT (current_new_target) != NULL) { arrow_func_p->new_target = ecma_make_object_value (JERRY_CONTEXT (current_new_target)); } @@ -792,7 +788,7 @@ ecma_op_function_call_simple (ecma_object_t *func_obj_p, /**< Function object */ { JERRY_CONTEXT (current_new_target) = NULL; } - else if (ecma_is_value_object (arrow_func_p->new_target)) + else { JERRY_CONTEXT (current_new_target) = ecma_get_object_from_value (arrow_func_p->new_target); } diff --git a/jerry-core/jcontext/jcontext.h b/jerry-core/jcontext/jcontext.h index 5f3f02ebb..ba3bf376a 100644 --- a/jerry-core/jcontext/jcontext.h +++ b/jerry-core/jcontext/jcontext.h @@ -228,7 +228,6 @@ struct jerry_context_t /** * Allowed values and it's meaning: * * NULL (0x0): the current "new.target" is undefined, that is the execution is inside a normal method. - * * JERRY_CONTEXT_INVALID_NEW_TARGET (0x1): the current "new.target" is invalid, that is outside of a method. * * Any other valid function object pointer: the current "new.target" is valid and it is constructor call. */ ecma_object_t *current_new_target; @@ -237,11 +236,6 @@ struct jerry_context_t #endif /* ENABLED (JERRY_ES2015) */ }; -/** - * Magic constant used to indicate that the current "new.target" is not inside a function. - */ -#define JERRY_CONTEXT_INVALID_NEW_TARGET ((ecma_object_t *) 0x1) - #if ENABLED (JERRY_EXTERNAL_CONTEXT) /* diff --git a/jerry-core/parser/js/js-parser-expr.c b/jerry-core/parser/js/js-parser-expr.c index 1ab724a75..1cac8aff9 100644 --- a/jerry-core/parser/js/js-parser-expr.c +++ b/jerry-core/parser/js/js-parser-expr.c @@ -1439,8 +1439,7 @@ parser_parse_unary_expression (parser_context_t *context_p, /**< context */ /* Check if "new.target" is written here. */ if (scanner_try_scan_new_target (context_p)) { - if (!(context_p->status_flags & PARSER_ALLOW_NEW_TARGET) - && !(context_p->global_status_flags & ECMA_PARSE_CALLED_FROM_FUNCTION)) + if (!(context_p->status_flags & PARSER_ALLOW_NEW_TARGET)) { parser_raise_error (context_p, PARSER_ERR_NEW_TARGET_NOT_ALLOWED); } @@ -1505,7 +1504,7 @@ parser_parse_unary_expression (parser_context_t *context_p, /**< context */ } parser_check_assignment_expr (context_p); - parser_parse_function_expression (context_p, PARSER_IS_ARROW_FUNCTION); + parser_parse_function_expression (context_p, PARSER_IS_FUNCTION | PARSER_IS_ARROW_FUNCTION); return parser_abort_parsing_after_arrow (context_p); } #endif /* ENABLED (JERRY_ES2015) */ @@ -1682,9 +1681,7 @@ parser_parse_unary_expression (parser_context_t *context_p, /**< context */ { if (context_p->status_flags & PARSER_ALLOW_SUPER) { - if (lexer_check_next_characters (context_p, LIT_CHAR_DOT, LIT_CHAR_LEFT_SQUARE) - && ((context_p->status_flags & PARSER_ALLOW_NEW_TARGET) - || (context_p->global_status_flags & ECMA_PARSE_CALLED_FROM_FUNCTION))) + if (lexer_check_next_characters (context_p, LIT_CHAR_DOT, LIT_CHAR_LEFT_SQUARE)) { parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_SUPER); break; @@ -1708,7 +1705,7 @@ parser_parse_unary_expression (parser_context_t *context_p, /**< context */ parser_check_assignment_expr (context_p); context_p->token.type = LEXER_ARROW_LEFT_PAREN; - parser_parse_function_expression (context_p, PARSER_IS_ARROW_FUNCTION); + parser_parse_function_expression (context_p, PARSER_IS_FUNCTION | PARSER_IS_ARROW_FUNCTION); return parser_abort_parsing_after_arrow (context_p); } case LEXER_KEYW_YIELD: @@ -1977,7 +1974,7 @@ parser_process_unary_expression (parser_context_t *context_p, /**< context */ if (is_eval) { #if ENABLED (JERRY_ES2015) - if (context_p->status_flags & (PARSER_ALLOW_SUPER_CALL | PARSER_ALLOW_SUPER)) + if (context_p->status_flags & (PARSER_ALLOW_SUPER_CALL | PARSER_ALLOW_SUPER | PARSER_ALLOW_NEW_TARGET)) { parser_emit_cbc_ext_call (context_p, CBC_EXT_LOCAL_EVAL, diff --git a/jerry-core/parser/js/js-parser-internal.h b/jerry-core/parser/js/js-parser-internal.h index bf63d450c..16c13f406 100644 --- a/jerry-core/parser/js/js-parser-internal.h +++ b/jerry-core/parser/js/js-parser-internal.h @@ -65,26 +65,24 @@ typedef enum PARSER_DISALLOW_YIELD = (1u << 16), /**< throw SyntaxError for yield expression */ PARSER_FUNCTION_HAS_NON_SIMPLE_PARAM = (1u << 17), /**< function has a non simple parameter */ PARSER_FUNCTION_HAS_REST_PARAM = (1u << 18), /**< function has rest parameter */ - /* These three status flags must be in this order. See PARSER_SAVED_FLAGS_OFFSET. */ + /* These 4 status flags must be in this order. See PARSER_SAVED_FLAGS_OFFSET. */ PARSER_CLASS_CONSTRUCTOR = (1u << 19), /**< a class constructor is parsed * Note: PARSER_ALLOW_SUPER must be present */ PARSER_ALLOW_SUPER = (1u << 20), /**< allow super property access */ PARSER_ALLOW_SUPER_CALL = (1u << 21), /**< allow super constructor call * Note: PARSER_CLASS_CONSTRUCTOR must be present */ + PARSER_ALLOW_NEW_TARGET = (1u << 22), /**< allow new.target parsing in the current context */ #endif /* ENABLED (JERRY_ES2015) */ #if ENABLED (JERRY_ES2015_MODULE_SYSTEM) - PARSER_MODULE_DEFAULT_CLASS_OR_FUNC = (1u << 22), /**< parsing a function or class default export */ - PARSER_MODULE_STORE_IDENT = (1u << 23), /**< store identifier of the current export statement */ + PARSER_MODULE_DEFAULT_CLASS_OR_FUNC = (1u << 23), /**< parsing a function or class default export */ + PARSER_MODULE_STORE_IDENT = (1u << 24), /**< store identifier of the current export statement */ #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */ PARSER_HAS_LATE_LIT_INIT = (1u << 30), /**< there are identifier or string literals which construction * is postponed after the local parser data is freed */ #ifndef JERRY_NDEBUG PARSER_SCANNING_SUCCESSFUL = PARSER_HAS_LATE_LIT_INIT, /**< scanning process was successful */ #endif /* !JERRY_NDEBUG */ -#if ENABLED (JERRY_ES2015) - PARSER_ALLOW_NEW_TARGET = PARSER_IS_FUNCTION, /**< allow new.target parsing in the current context */ -#endif /* ENABLED (JERRY_ES2015) */ } parser_general_flags_t; /** @@ -137,7 +135,7 @@ typedef enum * Count of ecma_parse_opts_t class parsing options related bits */ #define PARSER_SAVED_FLAGS_COUNT \ - (JERRY_LOG2 (ECMA_PARSE_ALLOW_SUPER_CALL) - JERRY_LOG2 (ECMA_PARSE_CLASS_CONSTRUCTOR) + 1) + (JERRY_LOG2 (ECMA_PARSE_ALLOW_NEW_TARGET) - JERRY_LOG2 (ECMA_PARSE_CLASS_CONSTRUCTOR) + 1) /** * Mask for get class option bits from ecma_parse_opts_t diff --git a/jerry-core/parser/js/js-parser-statm.c b/jerry-core/parser/js/js-parser-statm.c index 8a8312001..57085650f 100644 --- a/jerry-core/parser/js/js-parser-statm.c +++ b/jerry-core/parser/js/js-parser-statm.c @@ -2901,12 +2901,7 @@ parser_parse_statements (parser_context_t *context_p) /**< context */ case LEXER_KEYW_RETURN: { - uint32_t status_flag = PARSER_IS_FUNCTION; -#if ENABLED (JERRY_ES2015) - status_flag |= PARSER_IS_ARROW_FUNCTION; -#endif /* ENABLED (JERRY_ES2015) */ - - if (!(context_p->status_flags & status_flag)) + if (!(context_p->status_flags & PARSER_IS_FUNCTION)) { parser_raise_error (context_p, PARSER_ERR_INVALID_RETURN); } diff --git a/jerry-core/parser/js/js-parser.c b/jerry-core/parser/js/js-parser.c index 40e574eac..0b55643c5 100644 --- a/jerry-core/parser/js/js-parser.c +++ b/jerry-core/parser/js/js-parser.c @@ -2314,6 +2314,9 @@ parser_parse_function (parser_context_t *context_p, /**< context */ JERRY_ASSERT (status_flags & PARSER_IS_FUNCTION); parser_save_context (context_p, &saved_context); context_p->status_flags |= status_flags; +#if ENABLED (JERRY_ES2015) + context_p->status_flags |= PARSER_ALLOW_NEW_TARGET; +#endif /* ENABLED (JERRY_ES2015) */ #if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) if (context_p->is_show_opcodes) @@ -2408,12 +2411,12 @@ parser_parse_arrow_function (parser_context_t *context_p, /**< context */ parser_saved_context_t saved_context; ecma_compiled_code_t *compiled_code_p; - JERRY_ASSERT (!(status_flags & PARSER_IS_FUNCTION) - && (status_flags & PARSER_IS_ARROW_FUNCTION)); + JERRY_ASSERT (status_flags & PARSER_IS_FUNCTION); + JERRY_ASSERT (status_flags & PARSER_IS_ARROW_FUNCTION); parser_save_context (context_p, &saved_context); context_p->status_flags |= status_flags; #if ENABLED (JERRY_ES2015) - context_p->status_flags |= saved_context.status_flags & (PARSER_IS_FUNCTION + context_p->status_flags |= saved_context.status_flags & (PARSER_ALLOW_NEW_TARGET | PARSER_ALLOW_SUPER | PARSER_ALLOW_SUPER_CALL); #endif /* ENABLED (JERRY_ES2015) */ diff --git a/jerry-core/vm/opcodes.c b/jerry-core/vm/opcodes.c index 94889c559..dde5ce376 100644 --- a/jerry-core/vm/opcodes.c +++ b/jerry-core/vm/opcodes.c @@ -778,7 +778,6 @@ ecma_op_implicit_constructor_handler_cb (const ecma_value_t function_obj, /**< t return ecma_raise_type_error (ECMA_ERR_MSG ("Class constructor cannot be invoked without 'new'.")); } - JERRY_ASSERT (JERRY_CONTEXT (current_new_target) != JERRY_CONTEXT_INVALID_NEW_TARGET); return ECMA_VALUE_UNDEFINED; } /* ecma_op_implicit_constructor_handler_cb */ @@ -803,8 +802,6 @@ ecma_op_implicit_constructor_handler_heritage_cb (const ecma_value_t function_ob return ecma_raise_type_error (ECMA_ERR_MSG ("Class constructor cannot be invoked without 'new'.")); } - JERRY_ASSERT (JERRY_CONTEXT (current_new_target) != JERRY_CONTEXT_INVALID_NEW_TARGET); - ecma_object_t *func_obj_p = ecma_get_object_from_value (function_obj); ecma_value_t super_ctor = ecma_op_function_get_super_constructor (func_obj_p); diff --git a/jerry-core/vm/vm.c b/jerry-core/vm/vm.c index e9e54ab32..cd225078c 100644 --- a/jerry-core/vm/vm.c +++ b/jerry-core/vm/vm.c @@ -1986,7 +1986,6 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } else { - JERRY_ASSERT (new_target_object != JERRY_CONTEXT_INVALID_NEW_TARGET); ecma_ref_object (new_target_object); *stack_top_p++ = ecma_make_object_value (new_target_object); } diff --git a/tests/jerry/es2015/regression-test-issue-3630.js b/tests/jerry/es2015/regression-test-issue-3630.js new file mode 100644 index 000000000..05f6e8b51 --- /dev/null +++ b/tests/jerry/es2015/regression-test-issue-3630.js @@ -0,0 +1,23 @@ +// 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 { + { + class eval {} + eval() + } + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} diff --git a/tests/jerry/es2015/regression-test-issue-3640.js b/tests/jerry/es2015/regression-test-issue-3640.js new file mode 100644 index 000000000..1ac6dadb5 --- /dev/null +++ b/tests/jerry/es2015/regression-test-issue-3640.js @@ -0,0 +1,23 @@ +// 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 B = class {} +eval = class extends B {} + +try { + eval(); + assert (false); +} catch (e) { + assert (e instanceof TypeError); +} diff --git a/tests/jerry/es2015/regression-test-issue-3641.js b/tests/jerry/es2015/regression-test-issue-3641.js new file mode 100644 index 000000000..7f27579d8 --- /dev/null +++ b/tests/jerry/es2015/regression-test-issue-3641.js @@ -0,0 +1,26 @@ +// 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. + +eval = class extends SyntaxError { + constructor() { + super() + } +} + +try { + eval() + assert (false); +} catch (e) { + assert (e instanceof TypeError); +}