diff --git a/packages/babel-parser/src/parser/statement.js b/packages/babel-parser/src/parser/statement.js index 794667bb35d8..32ad1a30d28b 100644 --- a/packages/babel-parser/src/parser/statement.js +++ b/packages/babel-parser/src/parser/statement.js @@ -850,10 +850,11 @@ export default class StatementParser extends ExpressionParser { afterBlockParse?: (hasStrictModeDirective: boolean) => void, ): void { const octalPositions = []; + const oldStrict = this.state.strict; + let hasStrictModeDirective = false; let parsedNonDirective = false; - let oldStrict = null; - while (!this.eat(end)) { + while (!this.match(end)) { // Track octal literals that occur before a "use strict" directive. if (!parsedNonDirective && this.state.octalPositions.length) { octalPositions.push(...this.state.octalPositions); @@ -865,8 +866,8 @@ export default class StatementParser extends ExpressionParser { const directive = this.stmtToDirective(stmt); directives.push(directive); - if (oldStrict === null && directive.value.value === "use strict") { - oldStrict = this.state.strict; + if (!hasStrictModeDirective && directive.value.value === "use strict") { + hasStrictModeDirective = true; this.setStrict(true); } @@ -887,15 +888,14 @@ export default class StatementParser extends ExpressionParser { } if (afterBlockParse) { - afterBlockParse.call( - this, - /* hasStrictModeDirective */ oldStrict !== null, - ); + afterBlockParse.call(this, hasStrictModeDirective); } - if (oldStrict === false) { + if (!oldStrict) { this.setStrict(false); } + + this.next(); } // Parse a regular `for` loop. The disambiguation code in @@ -1156,7 +1156,7 @@ export default class StatementParser extends ExpressionParser { this.parseClassId(node, isStatement, optionalId); this.parseClassSuper(node); - node.body = this.parseClassBody(!!node.superClass); + node.body = this.parseClassBody(!!node.superClass, oldStrict); this.state.strict = oldStrict; @@ -1183,7 +1183,10 @@ export default class StatementParser extends ExpressionParser { ); } - parseClassBody(constructorAllowsSuper: boolean): N.ClassBody { + parseClassBody( + constructorAllowsSuper: boolean, + oldStrict?: boolean, + ): N.ClassBody { this.classScope.enter(); const state = { hadConstructor: false }; @@ -1197,7 +1200,7 @@ export default class StatementParser extends ExpressionParser { // contexts within the class body. They are permitted in test expressions, // outside of the class body. this.withTopicForbiddingContext(() => { - while (!this.eat(tt.braceR)) { + while (!this.match(tt.braceR)) { if (this.eat(tt.semi)) { if (decorators.length > 0) { throw this.raise(this.state.lastTokEnd, Errors.DecoratorSemicolon); @@ -1231,6 +1234,12 @@ export default class StatementParser extends ExpressionParser { } }); + if (!oldStrict) { + this.state.strict = false; + } + + this.next(); + if (decorators.length) { throw this.raise(this.state.start, Errors.TrailingDecorator); } diff --git a/packages/babel-parser/test/fixtures/es2015/regression/11183/input.js b/packages/babel-parser/test/fixtures/es2015/regression/11183/input.js new file mode 100644 index 000000000000..a64bdeee0804 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/regression/11183/input.js @@ -0,0 +1,5 @@ +class X {} +05 + +function x() { 'use strict' } +05 diff --git a/packages/babel-parser/test/fixtures/es2015/regression/11183/options.json b/packages/babel-parser/test/fixtures/es2015/regression/11183/options.json new file mode 100644 index 000000000000..b412ffe6712f --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/regression/11183/options.json @@ -0,0 +1,3 @@ +{ + "sourceType": "script" +} diff --git a/packages/babel-parser/test/fixtures/es2015/regression/11183/output.json b/packages/babel-parser/test/fixtures/es2015/regression/11183/output.json new file mode 100644 index 000000000000..ea1e5e19d850 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2015/regression/11183/output.json @@ -0,0 +1,242 @@ +{ + "type": "File", + "start": 0, + "end": 47, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 2 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 47, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 5, + "column": 2 + } + }, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ClassDeclaration", + "start": 0, + "end": 10, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 10 + } + }, + "id": { + "type": "Identifier", + "start": 6, + "end": 7, + "loc": { + "start": { + "line": 1, + "column": 6 + }, + "end": { + "line": 1, + "column": 7 + }, + "identifierName": "X" + }, + "name": "X" + }, + "superClass": null, + "body": { + "type": "ClassBody", + "start": 8, + "end": 10, + "loc": { + "start": { + "line": 1, + "column": 8 + }, + "end": { + "line": 1, + "column": 10 + } + }, + "body": [] + } + }, + { + "type": "ExpressionStatement", + "start": 11, + "end": 13, + "loc": { + "start": { + "line": 2, + "column": 0 + }, + "end": { + "line": 2, + "column": 2 + } + }, + "expression": { + "type": "NumericLiteral", + "start": 11, + "end": 13, + "loc": { + "start": { + "line": 2, + "column": 0 + }, + "end": { + "line": 2, + "column": 2 + } + }, + "extra": { + "rawValue": 5, + "raw": "05" + }, + "value": 5 + } + }, + { + "type": "FunctionDeclaration", + "start": 15, + "end": 44, + "loc": { + "start": { + "line": 4, + "column": 0 + }, + "end": { + "line": 4, + "column": 29 + } + }, + "id": { + "type": "Identifier", + "start": 24, + "end": 25, + "loc": { + "start": { + "line": 4, + "column": 9 + }, + "end": { + "line": 4, + "column": 10 + }, + "identifierName": "x" + }, + "name": "x" + }, + "generator": false, + "async": false, + "params": [], + "body": { + "type": "BlockStatement", + "start": 28, + "end": 44, + "loc": { + "start": { + "line": 4, + "column": 13 + }, + "end": { + "line": 4, + "column": 29 + } + }, + "body": [], + "directives": [ + { + "type": "Directive", + "start": 30, + "end": 42, + "loc": { + "start": { + "line": 4, + "column": 15 + }, + "end": { + "line": 4, + "column": 27 + } + }, + "value": { + "type": "DirectiveLiteral", + "start": 30, + "end": 42, + "loc": { + "start": { + "line": 4, + "column": 15 + }, + "end": { + "line": 4, + "column": 27 + } + }, + "value": "use strict", + "extra": { + "raw": "'use strict'", + "rawValue": "use strict" + } + } + } + ] + } + }, + { + "type": "ExpressionStatement", + "start": 45, + "end": 47, + "loc": { + "start": { + "line": 5, + "column": 0 + }, + "end": { + "line": 5, + "column": 2 + } + }, + "expression": { + "type": "NumericLiteral", + "start": 45, + "end": 47, + "loc": { + "start": { + "line": 5, + "column": 0 + }, + "end": { + "line": 5, + "column": 2 + } + }, + "extra": { + "rawValue": 5, + "raw": "05" + }, + "value": 5 + } + } + ], + "directives": [] + } +} \ No newline at end of file