Skip to content

Commit

Permalink
reuse default name in export default class
Browse files Browse the repository at this point in the history
  • Loading branch information
evanw committed Apr 4, 2022
1 parent 494e2dc commit e09acfc
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 76 deletions.
84 changes: 42 additions & 42 deletions internal/bundler/snapshots/snapshots_lower.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1525,36 +1525,36 @@ var foo4_default = class extends x {
};

// bar1.js
var _default = class extends x {
var _bar1_default = class extends x {
};
var default2 = _default;
__publicField(default2, "bar1", () => __async(_default, null, function* () {
return __superStaticGet(_default, "foo").call(this, "bar1");
var bar1_default = _bar1_default;
__publicField(bar1_default, "bar1", () => __async(_bar1_default, null, function* () {
return __superStaticGet(_bar1_default, "foo").call(this, "bar1");
}));

// bar2.js
var _default2 = class extends x {
var _bar2_default = class extends x {
};
var default2 = _default2;
__publicField(default2, "bar2", () => __async(_default2, null, function* () {
return () => __superStaticGet(_default2, "foo").call(this, "bar2");
var bar2_default = _bar2_default;
__publicField(bar2_default, "bar2", () => __async(_bar2_default, null, function* () {
return () => __superStaticGet(_bar2_default, "foo").call(this, "bar2");
}));

// bar3.js
var _default3 = class extends x {
var _bar3_default = class extends x {
};
var default2 = _default3;
__publicField(default2, "bar3", () => () => __async(_default3, null, function* () {
return __superStaticGet(_default3, "foo").call(this, "bar3");
var bar3_default = _bar3_default;
__publicField(bar3_default, "bar3", () => () => __async(_bar3_default, null, function* () {
return __superStaticGet(_bar3_default, "foo").call(this, "bar3");
}));

// bar4.js
var _default4 = class extends x {
var _bar4_default = class extends x {
};
var default2 = _default4;
__publicField(default2, "bar4", () => __async(_default4, null, function* () {
return () => __async(_default4, null, function* () {
return __superStaticGet(_default4, "foo").call(this, "bar4");
var bar4_default = _bar4_default;
__publicField(bar4_default, "bar4", () => __async(_bar4_default, null, function* () {
return () => __async(_bar4_default, null, function* () {
return __superStaticGet(_bar4_default, "foo").call(this, "bar4");
});
}));

Expand Down Expand Up @@ -1591,10 +1591,10 @@ var outer_default = function() {
});
}();
export {
_default as bar1,
_default2 as bar2,
_default3 as bar3,
_default4 as bar4,
bar1_default as bar1,
bar2_default as bar2,
bar3_default as bar3,
bar4_default as bar4,
baz1_default as baz1,
baz2_default as baz2,
foo1_default as foo1,
Expand Down Expand Up @@ -1657,36 +1657,36 @@ var foo4_default = class extends x {
};

// bar1.js
var _default = class extends x {
var _bar1_default = class extends x {
};
var default2 = _default;
__publicField(default2, "bar1", () => __async(_default, null, function* () {
return __superStaticSet(_default, "foo", "bar1");
var bar1_default = _bar1_default;
__publicField(bar1_default, "bar1", () => __async(_bar1_default, null, function* () {
return __superStaticSet(_bar1_default, "foo", "bar1");
}));

// bar2.js
var _default2 = class extends x {
var _bar2_default = class extends x {
};
var default2 = _default2;
__publicField(default2, "bar2", () => __async(_default2, null, function* () {
return () => __superStaticSet(_default2, "foo", "bar2");
var bar2_default = _bar2_default;
__publicField(bar2_default, "bar2", () => __async(_bar2_default, null, function* () {
return () => __superStaticSet(_bar2_default, "foo", "bar2");
}));

// bar3.js
var _default3 = class extends x {
var _bar3_default = class extends x {
};
var default2 = _default3;
__publicField(default2, "bar3", () => () => __async(_default3, null, function* () {
return __superStaticSet(_default3, "foo", "bar3");
var bar3_default = _bar3_default;
__publicField(bar3_default, "bar3", () => () => __async(_bar3_default, null, function* () {
return __superStaticSet(_bar3_default, "foo", "bar3");
}));

// bar4.js
var _default4 = class extends x {
var _bar4_default = class extends x {
};
var default2 = _default4;
__publicField(default2, "bar4", () => __async(_default4, null, function* () {
return () => __async(_default4, null, function* () {
return __superStaticSet(_default4, "foo", "bar4");
var bar4_default = _bar4_default;
__publicField(bar4_default, "bar4", () => __async(_bar4_default, null, function* () {
return () => __async(_bar4_default, null, function* () {
return __superStaticSet(_bar4_default, "foo", "bar4");
});
}));

Expand Down Expand Up @@ -1723,10 +1723,10 @@ var outer_default = function() {
});
}();
export {
_default as bar1,
_default2 as bar2,
_default3 as bar3,
_default4 as bar4,
bar1_default as bar1,
bar2_default as bar2,
bar3_default as bar3,
bar4_default as bar4,
baz1_default as baz1,
baz2_default as baz2,
foo1_default as foo1,
Expand Down
62 changes: 35 additions & 27 deletions internal/js_parser/js_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -5876,7 +5876,8 @@ func (p *parser) parseStmt(opts parseStmtOpts) js_ast.Stmt {

// The default name is lazily generated only if no other name is present
createDefaultName := func() js_ast.LocRef {
defaultName := js_ast.LocRef{Loc: defaultLoc, Ref: p.newSymbol(js_ast.SymbolOther, p.source.IdentifierName+"_default")}
// This must be named "default" for when "--keep-names" is active
defaultName := js_ast.LocRef{Loc: defaultLoc, Ref: p.newSymbol(js_ast.SymbolOther, "default")}
p.currentScope.Generated = append(p.currentScope.Generated, defaultName.Ref)
return defaultName
}
Expand Down Expand Up @@ -8980,6 +8981,8 @@ func (p *parser) visitAndAppendStmt(stmts []js_ast.Stmt, stmt js_ast.Stmt) []js_
}
}

stmts = append(stmts, stmt)

case *js_ast.SFunction:
// If we need to preserve the name but there is no name, generate a name
var name string
Expand All @@ -9001,19 +9004,26 @@ func (p *parser) visitAndAppendStmt(stmts []js_ast.Stmt, stmt js_ast.Stmt) []js_
stmts = append(stmts, p.keepStmtSymbolName(s2.Fn.Name.Loc, s2.Fn.Name.Ref, name))
}

return stmts

case *js_ast.SClass:
result := p.visitClass(s.Value.Loc, &s2.Class, true /* isDefaultExport */)
result := p.visitClass(s.Value.Loc, &s2.Class, s.DefaultName.Ref)

// Lower class field syntax for browsers that don't support it
classStmts, _ := p.lowerClass(stmt, js_ast.Expr{}, result)
return append(stmts, classStmts...)

stmts = append(stmts, classStmts...)

default:
panic("Internal error")
}

// Use a more friendly name than "default" now that "--keep-names" has
// been applied and has made sure to enforce the name "default"
if p.symbols[s.DefaultName.Ref.InnerIndex].OriginalName == "default" {
p.symbols[s.DefaultName.Ref.InnerIndex].OriginalName = p.source.IdentifierName + "_default"
}

return stmts

case *js_ast.SExportEquals:
// "module.exports = value"
stmts = append(stmts, js_ast.AssignStmt(
Expand Down Expand Up @@ -9580,7 +9590,7 @@ func (p *parser) visitAndAppendStmt(stmts []js_ast.Stmt, stmt js_ast.Stmt) []js_
return stmts

case *js_ast.SClass:
result := p.visitClass(stmt.Loc, &s.Class, false /* isDefaultExport */)
result := p.visitClass(stmt.Loc, &s.Class, js_ast.InvalidRef)

// Remove the export flag inside a namespace
wasExportInsideNamespace := s.IsExport && p.enclosingNamespaceArgRef != nil
Expand Down Expand Up @@ -10105,7 +10115,7 @@ type visitClassResult struct {
superCtorRef js_ast.Ref
}

func (p *parser) visitClass(nameScopeLoc logger.Loc, class *js_ast.Class, isDefaultExport bool) (result visitClassResult) {
func (p *parser) visitClass(nameScopeLoc logger.Loc, class *js_ast.Class, defaultNameRef js_ast.Ref) (result visitClassResult) {
tsDecoratorScope := p.currentScope
class.TSDecorators = p.visitTSDecorators(class.TSDecorators, tsDecoratorScope)

Expand Down Expand Up @@ -10182,32 +10192,25 @@ func (p *parser) visitClass(nameScopeLoc logger.Loc, class *js_ast.Class, isDefa
oldSuperCtorRef := p.superCtorRef
p.superCtorRef = result.superCtorRef

var classNameRef js_ast.Ref
if class.Name != nil {
classNameRef = class.Name.Ref
} else {
// Generate a name if one doesn't already exist. This is necessary for
// handling "this" in static class property initializers.
name := "this"
if isDefaultExport {
name = "default" // This is important for "--keep-names"
}
classNameRef = p.newSymbol(js_ast.SymbolOther, name)
}

// Insert a shadowing name that spans the whole class, which matches
// JavaScript's semantics. The class body (and extends clause) "captures" the
// original value of the name. This matters for class statements because the
// symbol can be re-assigned to something else later. The captured values
// must be the original value of the name, not the re-assigned value.
// Use "const" for this symbol to match JavaScript run-time semantics. You
// are not allowed to assign to this symbol (it throws a TypeError).
name := p.symbols[classNameRef.InnerIndex].OriginalName
result.shadowRef = p.newSymbol(js_ast.SymbolConst, "_"+name)
p.recordDeclaredSymbol(result.shadowRef)
if class.Name != nil {
name := p.symbols[class.Name.Ref.InnerIndex].OriginalName
result.shadowRef = p.newSymbol(js_ast.SymbolConst, "_"+name)
p.currentScope.Members[name] = js_ast.ScopeMember{Loc: class.Name.Loc, Ref: result.shadowRef}
} else {
name := "_this"
if defaultNameRef != js_ast.InvalidRef {
name = "_" + p.source.IdentifierName + "_default"
}
result.shadowRef = p.newSymbol(js_ast.SymbolConst, name)
}
p.recordDeclaredSymbol(result.shadowRef)

if class.ExtendsOrNil.Data != nil {
class.ExtendsOrNil = p.visitExpr(class.ExtendsOrNil)
Expand Down Expand Up @@ -10377,10 +10380,15 @@ func (p *parser) visitClass(nameScopeLoc logger.Loc, class *js_ast.Class, isDefa
} else if class.Name == nil {
// If there was originally no class name but something inside needed one
// (e.g. there was a static property initializer that referenced "this"),
// store our generated name so the class expression ends up with a name.
// populate the class name. If this is an "export default class" statement,
// use the existing default name so that things will work as expected if
// this is turned into a regular class statement later on.
classNameRef := defaultNameRef
if classNameRef == js_ast.InvalidRef {
classNameRef = p.newSymbol(js_ast.SymbolOther, "this")
p.recordDeclaredSymbol(classNameRef)
}
class.Name = &js_ast.LocRef{Loc: nameScopeLoc, Ref: classNameRef}
p.currentScope.Generated = append(p.currentScope.Generated, classNameRef)
p.recordDeclaredSymbol(classNameRef)
}

return
Expand Down Expand Up @@ -13508,7 +13516,7 @@ func (p *parser) visitExprInOut(expr js_ast.Expr, in exprIn) (js_ast.Expr, exprO
}

case *js_ast.EClass:
result := p.visitClass(expr.Loc, &e.Class, false /* isDefaultExport */)
result := p.visitClass(expr.Loc, &e.Class, js_ast.InvalidRef)

// Lower class field syntax for browsers that don't support it
_, expr = p.lowerClass(js_ast.Stmt{}, expr, result)
Expand Down
8 changes: 1 addition & 7 deletions internal/js_parser/js_parser_lower.go
Original file line number Diff line number Diff line change
Expand Up @@ -2061,13 +2061,6 @@ func (p *parser) lowerClass(stmt js_ast.Stmt, expr js_ast.Expr, result visitClas
class = &s2.Class
defaultName = s.DefaultName
kind = classKindExportDefaultStmt

// The shadowing name inside the class expression should be the same as
// the default export name
if result.shadowRef != js_ast.InvalidRef {
p.mergeSymbols(result.shadowRef, defaultName.Ref)
}

if class.Name != nil {
nameToKeep = p.symbols[class.Name.Ref.InnerIndex].OriginalName
} else {
Expand Down Expand Up @@ -2691,6 +2684,7 @@ func (p *parser) lowerClass(stmt js_ast.Stmt, expr js_ast.Expr, result visitClas
ValueOrNil: init,
}},
}})
p.recordUsage(nameRef)
} else {
switch kind {
case classKindStmt:
Expand Down

0 comments on commit e09acfc

Please sign in to comment.