From 0a88230ec4714e5f74a5aea75c1dc20ee4d5687d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Ribaudo?= Date: Thu, 17 Jan 2019 23:07:48 +0100 Subject: [PATCH] Disallow async functions as loop bodies (#9314) --- packages/babel-parser/src/parser/statement.js | 20 +++++-- .../invalid-fn-decl-inside-loop}/input.js | 0 .../invalid-fn-decl-inside-loop/options.json | 3 + .../input.js | 1 + .../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 | 55 ------------------- 9 files changed, 27 insertions(+), 62 deletions(-) rename packages/babel-parser/test/fixtures/{es2015/uncategorised/330 => core/categorized/invalid-fn-decl-inside-loop}/input.js (100%) create mode 100644 packages/babel-parser/test/fixtures/core/categorized/invalid-fn-decl-inside-loop/options.json 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 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 0f70b8c3a72b..a02441114085 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; @@ -210,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); } @@ -649,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) { @@ -676,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/es2015/uncategorised/330/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/es2015/uncategorised/330/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/invalid-fn-decl-inside-loop/options.json b/packages/babel-parser/test/fixtures/core/categorized/invalid-fn-decl-inside-loop/options.json new file mode 100644 index 000000000000..c1cad1bfedad --- /dev/null +++ b/packages/babel-parser/test/fixtures/core/categorized/invalid-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/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/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 9995fc248479..061bbac1fe13 100644 --- a/scripts/tests/test262/test262_whitelist.txt +++ b/scripts/tests/test262/test262_whitelist.txt @@ -1616,17 +1616,8 @@ 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) @@ -1642,16 +1633,8 @@ 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/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) @@ -1672,45 +1655,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/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) -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/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) 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) @@ -1850,15 +1803,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/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) \ No newline at end of file