From a7d91de5879301219e84d713c4d6291b9f345031 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Fri, 11 Jan 2019 13:41:34 +0100 Subject: [PATCH 1/2] Disallow async functions as loop body --- packages/babel-parser/src/parser/statement.js | 15 +++++++- .../categorized/fn-decl-inside-loop}/input.js | 0 .../fn-decl-inside-loop/options.json | 3 ++ .../es2015/uncategorised/330/options.json | 3 -- .../invalid-inside-loop/input.js | 1 + .../invalid-inside-loop/options.json | 3 ++ scripts/tests/test262/test262_whitelist.txt | 38 ------------------- 7 files changed, 20 insertions(+), 43 deletions(-) rename packages/babel-parser/test/fixtures/{es2015/uncategorised/330 => core/categorized/fn-decl-inside-loop}/input.js (100%) create mode 100644 packages/babel-parser/test/fixtures/core/categorized/fn-decl-inside-loop/options.json delete mode 100644 packages/babel-parser/test/fixtures/es2015/uncategorised/330/options.json create mode 100644 packages/babel-parser/test/fixtures/es2017/async-functions/invalid-inside-loop/input.js create mode 100644 packages/babel-parser/test/fixtures/es2017/async-functions/invalid-inside-loop/options.json diff --git a/packages/babel-parser/src/parser/statement.js b/packages/babel-parser/src/parser/statement.js index 553da03d6167..5659b5418c67 100644 --- a/packages/babel-parser/src/parser/statement.js +++ b/packages/babel-parser/src/parser/statement.js @@ -106,7 +106,12 @@ export default class StatementParser extends ExpressionParser { return this.parseForStatement(node); case tt._function: if (this.lookahead().type === tt.dot) break; - if (!declaration) this.unexpected(); + if (!declaration) { + this.raise( + this.state.start, + "Function declaration not allowed in this context", + ); + } return this.parseFunctionStatement(node); case tt._class: @@ -189,7 +194,13 @@ export default class StatementParser extends ExpressionParser { const state = this.state.clone(); this.next(); if (this.match(tt._function) && !this.canInsertSemicolon()) { - this.expect(tt._function); + if (!declaration) { + this.raise( + this.state.lastTokStart, + "Function declaration not allowed in this context", + ); + } + this.next(); return this.parseFunction(node, true, false, true); } else { this.state = state; diff --git a/packages/babel-parser/test/fixtures/es2015/uncategorised/330/input.js b/packages/babel-parser/test/fixtures/core/categorized/fn-decl-inside-loop/input.js similarity index 100% rename from packages/babel-parser/test/fixtures/es2015/uncategorised/330/input.js rename to packages/babel-parser/test/fixtures/core/categorized/fn-decl-inside-loop/input.js diff --git a/packages/babel-parser/test/fixtures/core/categorized/fn-decl-inside-loop/options.json b/packages/babel-parser/test/fixtures/core/categorized/fn-decl-inside-loop/options.json new file mode 100644 index 000000000000..c1cad1bfedad --- /dev/null +++ b/packages/babel-parser/test/fixtures/core/categorized/fn-decl-inside-loop/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Function declaration not allowed in this context (1:10)" +} diff --git a/packages/babel-parser/test/fixtures/es2015/uncategorised/330/options.json b/packages/babel-parser/test/fixtures/es2015/uncategorised/330/options.json deleted file mode 100644 index 89bfc2d73f8a..000000000000 --- a/packages/babel-parser/test/fixtures/es2015/uncategorised/330/options.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "throws": "Unexpected token (1:10)" -} diff --git a/packages/babel-parser/test/fixtures/es2017/async-functions/invalid-inside-loop/input.js b/packages/babel-parser/test/fixtures/es2017/async-functions/invalid-inside-loop/input.js new file mode 100644 index 000000000000..c519d6ea261a --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2017/async-functions/invalid-inside-loop/input.js @@ -0,0 +1 @@ +while (1) async function foo(){} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/es2017/async-functions/invalid-inside-loop/options.json b/packages/babel-parser/test/fixtures/es2017/async-functions/invalid-inside-loop/options.json new file mode 100644 index 000000000000..c1cad1bfedad --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2017/async-functions/invalid-inside-loop/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Function declaration not allowed in this context (1:10)" +} diff --git a/scripts/tests/test262/test262_whitelist.txt b/scripts/tests/test262/test262_whitelist.txt index e0b544e95216..fcd61a08940a 100644 --- a/scripts/tests/test262/test262_whitelist.txt +++ b/scripts/tests/test262/test262_whitelist.txt @@ -1697,17 +1697,9 @@ language/statements/class/syntax/early-errors/class-definition-evaluation-block- language/statements/class/syntax/early-errors/class-definition-evaluation-scriptbody-duplicate-binding.js(default) language/statements/class/syntax/early-errors/class-definition-evaluation-scriptbody-duplicate-binding.js(strict mode) language/statements/const/redeclaration-error-from-within-strict-mode-function-const.js(default) -language/statements/do-while/decl-async-fun.js(default) -language/statements/do-while/decl-async-fun.js(strict mode) -language/statements/do-while/decl-async-gen.js(default) -language/statements/do-while/decl-async-gen.js(strict mode) language/statements/do-while/labelled-fn-stmt.js(default) language/statements/for-await-of/let-block-with-newline.js(default) language/statements/for-await-of/let-identifier-with-newline.js(default) -language/statements/for-in/decl-async-fun.js(default) -language/statements/for-in/decl-async-fun.js(strict mode) -language/statements/for-in/decl-async-gen.js(default) -language/statements/for-in/decl-async-gen.js(strict mode) language/statements/for-in/dstr/array-rest-before-elision.js(default) language/statements/for-in/dstr/array-rest-before-elision.js(strict mode) language/statements/for-in/dstr/array-rest-elision-invalid.js(default) @@ -1729,10 +1721,6 @@ language/statements/for-in/labelled-fn-stmt-lhs.js(default) language/statements/for-in/labelled-fn-stmt-var.js(default) language/statements/for-in/let-block-with-newline.js(default) language/statements/for-in/let-identifier-with-newline.js(default) -language/statements/for-of/decl-async-fun.js(default) -language/statements/for-of/decl-async-fun.js(strict mode) -language/statements/for-of/decl-async-gen.js(default) -language/statements/for-of/decl-async-gen.js(strict mode) language/statements/for-of/dstr/array-rest-before-elision.js(default) language/statements/for-of/dstr/array-rest-before-elision.js(strict mode) language/statements/for-of/dstr/array-rest-elision-invalid.js(default) @@ -1759,10 +1747,6 @@ language/statements/for-of/labelled-fn-stmt-lhs.js(default) language/statements/for-of/labelled-fn-stmt-var.js(default) language/statements/for-of/let-block-with-newline.js(default) language/statements/for-of/let-identifier-with-newline.js(default) -language/statements/for/decl-async-fun.js(default) -language/statements/for/decl-async-fun.js(strict mode) -language/statements/for/decl-async-gen.js(default) -language/statements/for/decl-async-gen.js(strict mode) language/statements/for/head-let-bound-names-in-stmt.js(default) language/statements/for/head-let-bound-names-in-stmt.js(strict mode) language/statements/for/head-lhs-let.js(default) @@ -1773,22 +1757,6 @@ language/statements/for/let-block-with-newline.js(default) language/statements/for/let-identifier-with-newline.js(default) language/statements/function/dflt-params-duplicates.js(default) language/statements/generators/dflt-params-duplicates.js(default) -language/statements/if/if-async-fun-else-async-fun.js(default) -language/statements/if/if-async-fun-else-async-fun.js(strict mode) -language/statements/if/if-async-fun-else-stmt.js(default) -language/statements/if/if-async-fun-else-stmt.js(strict mode) -language/statements/if/if-async-fun-no-else.js(default) -language/statements/if/if-async-fun-no-else.js(strict mode) -language/statements/if/if-async-gen-else-async-gen.js(default) -language/statements/if/if-async-gen-else-async-gen.js(strict mode) -language/statements/if/if-async-gen-else-stmt.js(default) -language/statements/if/if-async-gen-else-stmt.js(strict mode) -language/statements/if/if-async-gen-no-else.js(default) -language/statements/if/if-async-gen-no-else.js(strict mode) -language/statements/if/if-stmt-else-async-fun.js(default) -language/statements/if/if-stmt-else-async-fun.js(strict mode) -language/statements/if/if-stmt-else-async-gen.js(default) -language/statements/if/if-stmt-else-async-gen.js(strict mode) language/statements/if/labelled-fn-stmt-first.js(default) language/statements/if/labelled-fn-stmt-lone.js(default) language/statements/if/labelled-fn-stmt-second.js(default) @@ -1931,15 +1899,9 @@ language/statements/try/early-catch-lex.js(default) language/statements/try/early-catch-lex.js(strict mode) language/statements/try/early-catch-var.js(default) language/statements/try/early-catch-var.js(strict mode) -language/statements/while/decl-async-fun.js(default) -language/statements/while/decl-async-fun.js(strict mode) -language/statements/while/decl-async-gen.js(default) -language/statements/while/decl-async-gen.js(strict mode) language/statements/while/labelled-fn-stmt.js(default) language/statements/while/let-block-with-newline.js(default) language/statements/while/let-identifier-with-newline.js(default) -language/statements/with/decl-async-fun.js(default) -language/statements/with/decl-async-gen.js(default) language/statements/with/labelled-fn-stmt.js(default) language/statements/with/let-block-with-newline.js(default) language/statements/with/let-identifier-with-newline.js(default) From 7b0acf70521aa8b8153a1ef52db8a6e3c5a65796 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Fri, 11 Jan 2019 13:48:30 +0100 Subject: [PATCH 2/2] Disallow labeled functions in loop bodies --- packages/babel-parser/src/parser/statement.js | 5 +++-- .../input.js | 0 .../options.json | 0 .../input.js | 1 + .../options.json | 3 +++ scripts/tests/test262/test262_whitelist.txt | 17 ----------------- 6 files changed, 7 insertions(+), 19 deletions(-) rename packages/babel-parser/test/fixtures/core/categorized/{fn-decl-inside-loop => invalid-fn-decl-inside-loop}/input.js (100%) rename packages/babel-parser/test/fixtures/core/categorized/{fn-decl-inside-loop => invalid-fn-decl-inside-loop}/options.json (100%) create mode 100644 packages/babel-parser/test/fixtures/core/categorized/invalid-fn-decl-labeled-inside-loop/input.js create mode 100644 packages/babel-parser/test/fixtures/core/categorized/invalid-fn-decl-labeled-inside-loop/options.json diff --git a/packages/babel-parser/src/parser/statement.js b/packages/babel-parser/src/parser/statement.js index 5659b5418c67..1eea3ed4392f 100644 --- a/packages/babel-parser/src/parser/statement.js +++ b/packages/babel-parser/src/parser/statement.js @@ -221,7 +221,7 @@ export default class StatementParser extends ExpressionParser { expr.type === "Identifier" && this.eat(tt.colon) ) { - return this.parseLabeledStatement(node, maybeName, expr); + return this.parseLabeledStatement(node, maybeName, expr, declaration); } else { return this.parseExpressionStatement(node, expr); } @@ -660,6 +660,7 @@ export default class StatementParser extends ExpressionParser { node: N.LabeledStatement, maybeName: string, expr: N.Identifier, + declaration: boolean, ): N.LabeledStatement { for (const label of this.state.labels) { if (label.name === maybeName) { @@ -687,7 +688,7 @@ export default class StatementParser extends ExpressionParser { kind: kind, statementStart: this.state.start, }); - node.body = this.parseStatement(true); + node.body = this.parseStatement(declaration); if ( node.body.type == "ClassDeclaration" || diff --git a/packages/babel-parser/test/fixtures/core/categorized/fn-decl-inside-loop/input.js b/packages/babel-parser/test/fixtures/core/categorized/invalid-fn-decl-inside-loop/input.js similarity index 100% rename from packages/babel-parser/test/fixtures/core/categorized/fn-decl-inside-loop/input.js rename to packages/babel-parser/test/fixtures/core/categorized/invalid-fn-decl-inside-loop/input.js diff --git a/packages/babel-parser/test/fixtures/core/categorized/fn-decl-inside-loop/options.json b/packages/babel-parser/test/fixtures/core/categorized/invalid-fn-decl-inside-loop/options.json similarity index 100% rename from packages/babel-parser/test/fixtures/core/categorized/fn-decl-inside-loop/options.json rename to packages/babel-parser/test/fixtures/core/categorized/invalid-fn-decl-inside-loop/options.json diff --git a/packages/babel-parser/test/fixtures/core/categorized/invalid-fn-decl-labeled-inside-loop/input.js b/packages/babel-parser/test/fixtures/core/categorized/invalid-fn-decl-labeled-inside-loop/input.js new file mode 100644 index 000000000000..241ddc1cde1c --- /dev/null +++ b/packages/babel-parser/test/fixtures/core/categorized/invalid-fn-decl-labeled-inside-loop/input.js @@ -0,0 +1 @@ +while (1) foo: bar: function foo(){} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/core/categorized/invalid-fn-decl-labeled-inside-loop/options.json b/packages/babel-parser/test/fixtures/core/categorized/invalid-fn-decl-labeled-inside-loop/options.json new file mode 100644 index 000000000000..1397e6a76220 --- /dev/null +++ b/packages/babel-parser/test/fixtures/core/categorized/invalid-fn-decl-labeled-inside-loop/options.json @@ -0,0 +1,3 @@ +{ + "throws": "Function declaration not allowed in this context (1:20)" +} diff --git a/scripts/tests/test262/test262_whitelist.txt b/scripts/tests/test262/test262_whitelist.txt index fcd61a08940a..7c8254c29028 100644 --- a/scripts/tests/test262/test262_whitelist.txt +++ b/scripts/tests/test262/test262_whitelist.txt @@ -1697,7 +1697,6 @@ language/statements/class/syntax/early-errors/class-definition-evaluation-block- language/statements/class/syntax/early-errors/class-definition-evaluation-scriptbody-duplicate-binding.js(default) language/statements/class/syntax/early-errors/class-definition-evaluation-scriptbody-duplicate-binding.js(strict mode) language/statements/const/redeclaration-error-from-within-strict-mode-function-const.js(default) -language/statements/do-while/labelled-fn-stmt.js(default) language/statements/for-await-of/let-block-with-newline.js(default) language/statements/for-await-of/let-identifier-with-newline.js(default) language/statements/for-in/dstr/array-rest-before-elision.js(default) @@ -1715,10 +1714,6 @@ language/statements/for-in/head-let-bound-names-in-stmt.js(strict mode) language/statements/for-in/head-lhs-let.js(default) language/statements/for-in/head-var-bound-names-let.js(default) language/statements/for-in/identifier-let-allowed-as-lefthandside-expression-not-strict.js(default) -language/statements/for-in/labelled-fn-stmt-const.js(default) -language/statements/for-in/labelled-fn-stmt-let.js(default) -language/statements/for-in/labelled-fn-stmt-lhs.js(default) -language/statements/for-in/labelled-fn-stmt-var.js(default) language/statements/for-in/let-block-with-newline.js(default) language/statements/for-in/let-identifier-with-newline.js(default) language/statements/for-of/dstr/array-rest-before-elision.js(default) @@ -1741,25 +1736,15 @@ language/statements/for-of/head-let-bound-names-in-stmt.js(strict mode) language/statements/for-of/head-var-bound-names-let.js(default) language/statements/for-of/head-var-no-expr.js(default) language/statements/for-of/head-var-no-expr.js(strict mode) -language/statements/for-of/labelled-fn-stmt-const.js(default) -language/statements/for-of/labelled-fn-stmt-let.js(default) -language/statements/for-of/labelled-fn-stmt-lhs.js(default) -language/statements/for-of/labelled-fn-stmt-var.js(default) language/statements/for-of/let-block-with-newline.js(default) language/statements/for-of/let-identifier-with-newline.js(default) language/statements/for/head-let-bound-names-in-stmt.js(default) language/statements/for/head-let-bound-names-in-stmt.js(strict mode) language/statements/for/head-lhs-let.js(default) -language/statements/for/labelled-fn-stmt-expr.js(default) -language/statements/for/labelled-fn-stmt-let.js(default) -language/statements/for/labelled-fn-stmt-var.js(default) language/statements/for/let-block-with-newline.js(default) language/statements/for/let-identifier-with-newline.js(default) language/statements/function/dflt-params-duplicates.js(default) language/statements/generators/dflt-params-duplicates.js(default) -language/statements/if/labelled-fn-stmt-first.js(default) -language/statements/if/labelled-fn-stmt-lone.js(default) -language/statements/if/labelled-fn-stmt-second.js(default) language/statements/if/let-block-with-newline.js(default) language/statements/if/let-identifier-with-newline.js(default) language/statements/labeled/let-block-with-newline.js(default) @@ -1899,9 +1884,7 @@ language/statements/try/early-catch-lex.js(default) language/statements/try/early-catch-lex.js(strict mode) language/statements/try/early-catch-var.js(default) language/statements/try/early-catch-var.js(strict mode) -language/statements/while/labelled-fn-stmt.js(default) language/statements/while/let-block-with-newline.js(default) language/statements/while/let-identifier-with-newline.js(default) -language/statements/with/labelled-fn-stmt.js(default) language/statements/with/let-block-with-newline.js(default) language/statements/with/let-identifier-with-newline.js(default)