diff --git a/internal/js_parser/js_parser.go b/internal/js_parser/js_parser.go index eaf0504e61c..b74802ddee8 100644 --- a/internal/js_parser/js_parser.go +++ b/internal/js_parser/js_parser.go @@ -5800,15 +5800,16 @@ const ( ) type parseStmtOpts struct { - tsDecorators *deferredTSDecorators - lexicalDecl lexicalDecl - isModuleScope bool - isNamespaceScope bool - isExport bool - isNameOptional bool // For "export default" pseudo-statements - isTypeScriptDeclare bool - isForLoopInit bool - isForAwaitLoopInit bool + tsDecorators *deferredTSDecorators + lexicalDecl lexicalDecl + isModuleScope bool + isNamespaceScope bool + isExport bool + isNameOptional bool // For "export default" pseudo-statements + isTypeScriptDeclare bool + isForLoopInit bool + isForAwaitLoopInit bool + allowDirectivePrologue bool } func (p *parser) parseStmt(opts parseStmtOpts) js_ast.Stmt { @@ -6958,7 +6959,9 @@ func (p *parser) parseFnBody(data fnOrArrowDataParse) js_ast.FnBody { defer p.popScope() p.lexer.Expect(js_lexer.TOpenBrace) - stmts := p.parseStmtsUpTo(js_lexer.TCloseBrace, parseStmtOpts{}) + stmts := p.parseStmtsUpTo(js_lexer.TCloseBrace, parseStmtOpts{ + allowDirectivePrologue: true, + }) p.lexer.Next() p.allowIn = oldAllowIn @@ -6975,7 +6978,7 @@ func (p *parser) parseStmtsUpTo(end js_lexer.T, opts parseStmtOpts) []js_ast.Stm stmts := []js_ast.Stmt{} returnWithoutSemicolonStart := int32(-1) opts.lexicalDecl = lexicalDeclAllowAll - isDirectivePrologue := true + isDirectivePrologue := opts.allowDirectivePrologue for { // Preserve some statement-level comments @@ -14493,7 +14496,10 @@ func Parse(log logger.Log, source logger.Source, options Options) (result js_ast p.fnOrArrowDataParse.isTopLevel = true // Parse the file in the first pass, but do not bind symbols - stmts := p.parseStmtsUpTo(js_lexer.TEndOfFile, parseStmtOpts{isModuleScope: true}) + stmts := p.parseStmtsUpTo(js_lexer.TEndOfFile, parseStmtOpts{ + isModuleScope: true, + allowDirectivePrologue: true, + }) p.prepareForVisitPass() // Strip off a leading "use strict" directive when not bundling diff --git a/internal/js_parser/js_parser_test.go b/internal/js_parser/js_parser_test.go index 308cac94740..961ede1403f 100644 --- a/internal/js_parser/js_parser_test.go +++ b/internal/js_parser/js_parser_test.go @@ -432,6 +432,12 @@ func TestStrictMode(t *testing.T) { expectPrinted(t, "class f {} with (x) y", "class f {\n}\nwith (x)\n y;\n") expectPrinted(t, "with (x) y; class f {}", "with (x)\n y;\nclass f {\n}\n") expectPrinted(t, "`use strict`; with (x) y", "`use strict`;\nwith (x)\n y;\n") + expectPrinted(t, "{ 'use strict'; with (x) y }", "{\n \"use strict\";\n with (x)\n y;\n}\n") + expectPrinted(t, "if (0) { 'use strict'; with (x) y }", "if (0) {\n \"use strict\";\n with (x)\n y;\n}\n") + expectPrinted(t, "while (0) { 'use strict'; with (x) y }", "while (0) {\n \"use strict\";\n with (x)\n y;\n}\n") + expectPrinted(t, "try { 'use strict'; with (x) y } catch {}", "try {\n \"use strict\";\n with (x)\n y;\n} catch {\n}\n") + expectPrinted(t, "try {} catch { 'use strict'; with (x) y }", "try {\n} catch {\n \"use strict\";\n with (x)\n y;\n}\n") + expectPrinted(t, "try {} finally { 'use strict'; with (x) y }", "try {\n} finally {\n \"use strict\";\n with (x)\n y;\n}\n") expectParseError(t, "\"use strict\"; with (x) y", ": ERROR: With statements cannot be used in strict mode\n"+useStrict) expectParseError(t, "function f() { 'use strict'; with (x) y }", ": ERROR: With statements cannot be used in strict mode\n"+useStrict) expectParseError(t, "function f() { 'use strict'; function y() { with (x) y } }", ": ERROR: With statements cannot be used in strict mode\n"+useStrict)