diff --git a/jerry-core/parser/js/js-scanner-internal.h b/jerry-core/parser/js/js-scanner-internal.h index 28af6d51e..23953e6b4 100644 --- a/jerry-core/parser/js/js-scanner-internal.h +++ b/jerry-core/parser/js/js-scanner-internal.h @@ -218,10 +218,10 @@ typedef enum SCANNER_BINDING_NONE, /**< not a destructuring binding expression */ SCANNER_BINDING_VAR, /**< destructuring var binding */ SCANNER_BINDING_LET, /**< destructuring let binding */ + SCANNER_BINDING_CATCH, /**< destructuring catch binding */ SCANNER_BINDING_CONST, /**< destructuring const binding */ SCANNER_BINDING_ARG, /**< destructuring arg binding */ SCANNER_BINDING_ARROW_ARG, /**< possible destructuring arg binding of an arrow function */ - SCANNER_BINDING_CATCH, /**< destructuring catch binding */ } scanner_binding_type_t; /** diff --git a/jerry-core/parser/js/js-scanner-util.c b/jerry-core/parser/js/js-scanner-util.c index c62b281ff..d8cc36e0d 100644 --- a/jerry-core/parser/js/js-scanner-util.c +++ b/jerry-core/parser/js/js-scanner-util.c @@ -564,14 +564,23 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */ { no_declarations++; -#if !ENABLED (JERRY_ES2015) +#if ENABLED (JERRY_ES2015) + if ((type & (SCANNER_LITERAL_IS_CONST | SCANNER_LITERAL_IS_ARG)) == SCANNER_LITERAL_IS_CONST) + { + JERRY_ASSERT (type & SCANNER_LITERAL_IS_LET); + + /* Catch parameters cannot be functions. */ + literal_p->type = (uint8_t) (type & ~SCANNER_LITERAL_IS_FUNC); + no_declarations--; + } +#else /* !ENABLED (JERRY_ES2015) */ if (type & SCANNER_LITERAL_IS_LOCAL) { /* Catch parameters cannot be functions. */ literal_p->type = (uint8_t) (type & ~SCANNER_LITERAL_IS_FUNC); no_declarations--; } -#endif /* !ENABLED (JERRY_ES2015) */ +#endif /* ENABLED (JERRY_ES2015) */ } intptr_t diff = (intptr_t) (literal_p->char_p - prev_source_p); @@ -617,12 +626,14 @@ scanner_pop_literal_pool (parser_context_t *context_p, /**< context */ #if ENABLED (JERRY_ES2015) extended_type |= SCANNER_LITERAL_IS_USED; + const uint8_t mask = (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_LOCAL); + if ((type & SCANNER_LITERAL_IS_ARG) - || (!(literal_location_p->type & SCANNER_LITERAL_IS_ARG) - && (literal_location_p->type & SCANNER_LITERAL_IS_LOCAL))) + || (literal_location_p->type & mask) == SCANNER_LITERAL_IS_LET + || (literal_location_p->type & mask) == SCANNER_LITERAL_IS_CONST) { /* Clears the SCANNER_LITERAL_IS_VAR and SCANNER_LITERAL_IS_FUNC flags - * for speculative arrow paramters and local (non-var) functions. */ + * for speculative arrow parameters and local (non-var) functions. */ type = 0; } #endif /* ENABLED (JERRY_ES2015) */ diff --git a/jerry-core/parser/js/js-scanner.c b/jerry-core/parser/js/js-scanner.c index 20eeac9ca..a1e4ca0cd 100644 --- a/jerry-core/parser/js/js-scanner.c +++ b/jerry-core/parser/js/js-scanner.c @@ -1397,8 +1397,11 @@ scanner_scan_statement (parser_context_t *context_p, /**< context */ lexer_lit_location_t *literal_p = scanner_add_literal (context_p, scanner_context_p); #if ENABLED (JERRY_ES2015) - if (literal_p->type & SCANNER_LITERAL_IS_LOCAL - && !(literal_p->type & (SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_ARG))) + const uint8_t mask = (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LOCAL); + + if ((literal_p->type & SCANNER_LITERAL_IS_LOCAL) + && (literal_p->type & mask) != (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_DESTRUCTURED_ARG) + && (literal_p->type & mask) != (SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_FUNC_DECLARATION)) { scanner_raise_redeclaration_error (context_p); } @@ -2970,10 +2973,10 @@ scanner_scan_all (parser_context_t *context_p, /**< context */ { JERRY_ASSERT (scanner_context.binding_type == SCANNER_BINDING_VAR || scanner_context.binding_type == SCANNER_BINDING_LET + || scanner_context.binding_type == SCANNER_BINDING_CATCH || scanner_context.binding_type == SCANNER_BINDING_CONST || scanner_context.binding_type == SCANNER_BINDING_ARG - || scanner_context.binding_type == SCANNER_BINDING_ARROW_ARG - || scanner_context.binding_type == SCANNER_BINDING_CATCH); + || scanner_context.binding_type == SCANNER_BINDING_ARROW_ARG); if (type == LEXER_THREE_DOTS) { @@ -3035,14 +3038,13 @@ scanner_scan_all (parser_context_t *context_p, /**< context */ { scanner_detect_invalid_let (context_p, literal_p); - if (scanner_context.binding_type == SCANNER_BINDING_LET) + if (scanner_context.binding_type <= SCANNER_BINDING_CATCH) { + JERRY_ASSERT ((scanner_context.binding_type == SCANNER_BINDING_LET) + || (scanner_context.binding_type == SCANNER_BINDING_CATCH)); + literal_p->type |= SCANNER_LITERAL_IS_LET; } - else if (scanner_context.binding_type == SCANNER_BINDING_CATCH) - { - literal_p->type |= SCANNER_LITERAL_IS_LOCAL; - } else { literal_p->type |= SCANNER_LITERAL_IS_CONST; diff --git a/tests/jerry/es2015/try-catch.js b/tests/jerry/es2015/try-catch.js new file mode 100644 index 000000000..3e18c7743 --- /dev/null +++ b/tests/jerry/es2015/try-catch.js @@ -0,0 +1,130 @@ +/* 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 e = -1 + +function f1() +{ + assert(e === undefined) + try { + throw 0 + } catch (e) { + var e = 1 + assert(e === 1) + } + assert(e === undefined) +} +f1() + +function f2() +{ + assert(e === undefined) + try { + throw 0 + } catch (e) { + { + var e = 2 + assert(e === 2) + } + assert(e === 2) + } + assert(e === undefined) +} +f2() + +function f3() +{ + assert(e === -1) + try { + throw [0] + } catch ([e]) { + { + try { + eval("var e = 2") + assert(false) + } catch (e) { + assert(e instanceof SyntaxError) + } + } + assert(e === 0) + } + assert(e === -1) +} +f3() + +function f4() +{ + assert(e === undefined) + try { + throw 0 + } catch (e) { + { + function e() { return 3 } + assert(e() === 3) + } + assert(e === 0) + } + assert(e() === 3) +} +f4() + +function f5() +{ + assert(e === -1) + try { + throw 0 + } catch (e) { + { + eval("function e() { return 3 } assert(e === 0)") + assert(e === 0) + } + assert(e === 0) + } + assert(e() === 3) +} +f5() + +function f6() +{ + let e = 4; + assert(e === 4) + try { + throw 0 + } catch (e) { + { + function e() { return 5 } + assert(e() === 5) + } + assert(e === 0) + } + assert(e === 4) +} +f6() + +function f7() +{ + let e = 6; + assert(e === 6) + try { + throw 0 + } catch (e) { + { + eval("function e() { return 7 } assert(e() === 7)") + } + assert(e === 0) + } + assert(e === 6) +} +f7() diff --git a/tests/jerry/es2015/try-pattern.js b/tests/jerry/es2015/try-pattern.js index 764f842c0..28b7cc2c0 100644 --- a/tests/jerry/es2015/try-pattern.js +++ b/tests/jerry/es2015/try-pattern.js @@ -28,6 +28,11 @@ check_syntax_error("try {} catch([a] {}"); check_syntax_error("try {} catch([a] = [1]) {}"); check_syntax_error("try {} catch({a} = {a:1}) {}"); check_syntax_error("try {} catch(a,) {}"); +check_syntax_error("try {} catch(a) { function a() {} }"); +check_syntax_error("try {} catch(a) { { function a() {} } function a() {} }"); +check_syntax_error("try {} catch([a]) { var a }"); +check_syntax_error("try {} catch([a]) { { var a } }"); +check_syntax_error("try {} catch([a]) { function a() {} }"); try { throw [1,2]