@@ -6700,6 +6700,7 @@ type parseStmtOpts struct {
67006700 isModuleScope bool
67016701 isNamespaceScope bool
67026702 isExport bool
6703+ isExportDefault bool
67036704 isNameOptional bool // For "export default" pseudo-statements
67046705 isTypeScriptDeclare bool
67056706 isForLoopInit bool
@@ -6839,6 +6840,8 @@ func (p *parser) parseStmt(opts parseStmtOpts) js_ast.Stmt {
68396840 return defaultName
68406841 }
68416842
6843+ // "export default async function() {}"
6844+ // "export default async function foo() {}"
68426845 if p.lexer.IsContextualKeyword("async") {
68436846 asyncRange := p.lexer.Range()
68446847 p.lexer.Next()
@@ -6872,20 +6875,27 @@ func (p *parser) parseStmt(opts parseStmtOpts) js_ast.Stmt {
68726875 DefaultName: defaultName, Value: js_ast.Stmt{Loc: loc, Data: &js_ast.SExpr{Value: expr}}}}
68736876 }
68746877
6875- if p.lexer.Token == js_lexer.TFunction || p.lexer.Token == js_lexer.TClass || p.lexer.IsContextualKeyword("interface") {
6878+ // "export default class {}"
6879+ // "export default class Foo {}"
6880+ // "export default function() {}"
6881+ // "export default function foo() {}"
6882+ // "export default interface Foo {}"
6883+ // "export default interface + 1"
6884+ if p.lexer.Token == js_lexer.TFunction || p.lexer.Token == js_lexer.TClass ||
6885+ (p.options.ts.Parse && p.lexer.IsContextualKeyword("interface")) {
68766886 stmt := p.parseStmt(parseStmtOpts{
68776887 deferredDecorators: opts.deferredDecorators,
68786888 isNameOptional: true,
6889+ isExportDefault: true,
68796890 lexicalDecl: lexicalDeclAllowAll,
68806891 hasNoSideEffectsComment: opts.hasNoSideEffectsComment,
68816892 })
6882- if _, ok := stmt.Data.(*js_ast.STypeScript); ok {
6883- return stmt // This was just a type annotation
6884- }
68856893
68866894 // Use the statement name if present, since it's a better name
68876895 var defaultName ast.LocRef
68886896 switch s := stmt.Data.(type) {
6897+ case *js_ast.STypeScript, *js_ast.SExpr:
6898+ return stmt // Handle the "interface" case above
68896899 case *js_ast.SFunction:
68906900 if s.Fn.Name != nil {
68916901 defaultName = ast.LocRef{Loc: defaultLoc, Ref: s.Fn.Name.Ref}
@@ -6901,7 +6911,6 @@ func (p *parser) parseStmt(opts parseStmtOpts) js_ast.Stmt {
69016911 default:
69026912 panic("Internal error")
69036913 }
6904-
69056914 return js_ast.Stmt{Loc: loc, Data: &js_ast.SExportDefault{DefaultName: defaultName, Value: stmt}}
69066915 }
69076916
@@ -6910,6 +6919,7 @@ func (p *parser) parseStmt(opts parseStmtOpts) js_ast.Stmt {
69106919 expr := p.parseExpr(js_ast.LComma)
69116920
69126921 // "export default abstract class {}"
6922+ // "export default abstract class Foo {}"
69136923 if p.options.ts.Parse && isIdentifier && name == "abstract" && !p.lexer.HasNewlineBefore {
69146924 if _, ok := expr.Data.(*js_ast.EIdentifier); ok && (p.lexer.Token == js_lexer.TClass || opts.deferredDecorators != nil) {
69156925 stmt := p.parseClassStmt(loc, parseStmtOpts{
@@ -7741,18 +7751,18 @@ func (p *parser) parseStmt(opts parseStmtOpts) js_ast.Stmt {
77417751
77427752 default:
77437753 isIdentifier := p.lexer.Token == js_lexer.TIdentifier
7754+ nameRange := p.lexer.Range()
77447755 name := p.lexer.Identifier.String
77457756
77467757 // Parse either an async function, an async expression, or a normal expression
77477758 var expr js_ast.Expr
77487759 if isIdentifier && p.lexer.Raw() == "async" {
7749- asyncRange := p.lexer.Range()
77507760 p.lexer.Next()
77517761 if p.lexer.Token == js_lexer.TFunction && !p.lexer.HasNewlineBefore {
77527762 p.lexer.Next()
7753- return p.parseFnStmt(asyncRange .Loc, opts, true /* isAsync */, asyncRange )
7763+ return p.parseFnStmt(nameRange .Loc, opts, true /* isAsync */, nameRange )
77547764 }
7755- expr = p.parseSuffix(p.parseAsyncPrefixExpr(asyncRange , js_ast.LLowest, 0), js_ast.LLowest, nil, 0)
7765+ expr = p.parseSuffix(p.parseAsyncPrefixExpr(nameRange , js_ast.LLowest, 0), js_ast.LLowest, nil, 0)
77567766 } else {
77577767 var stmt js_ast.Stmt
77587768 expr, stmt, _ = p.parseExprOrLetOrUsingStmt(opts)
@@ -7800,11 +7810,20 @@ func (p *parser) parseStmt(opts parseStmtOpts) js_ast.Stmt {
78007810
78017811 case "interface":
78027812 // "interface Foo {}"
7803- if !p.lexer.HasNewlineBefore {
7813+ // "export default interface Foo {}"
7814+ // "export default interface \n Foo {}"
7815+ if !p.lexer.HasNewlineBefore || opts.isExportDefault {
78047816 p.skipTypeScriptInterfaceStmt(parseStmtOpts{isModuleScope: opts.isModuleScope})
78057817 return js_ast.Stmt{Loc: loc, Data: js_ast.STypeScriptShared}
78067818 }
78077819
7820+ // "interface \n Foo {}"
7821+ // "export interface \n Foo {}"
7822+ if opts.isExport {
7823+ p.log.AddError(&p.tracker, nameRange, "Unexpected \"interface\"")
7824+ panic(js_lexer.LexerPanic{})
7825+ }
7826+
78087827 case "abstract":
78097828 if !p.lexer.HasNewlineBefore && (p.lexer.Token == js_lexer.TClass || opts.deferredDecorators != nil) {
78107829 return p.parseClassStmt(loc, opts)
0 commit comments