Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

avoid var declaration overwritten #2085

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 5 additions & 4 deletions internal/js_ast/js_ast.go
Expand Up @@ -1482,10 +1482,11 @@ type Scope struct {
// This will be non-nil if this is a TypeScript "namespace" or "enum"
TSNamespace *TSNamespaceScope

Parent *Scope
Children []*Scope
Members map[string]ScopeMember
Generated []Ref
Parent *Scope
Children []*Scope
Members map[string]ScopeMember
HoistFnRef map[string]*Ref
Generated []Ref

// The location of the "use strict" directive for ExplicitStrictMode
UseStrictLoc logger.Loc
Expand Down
52 changes: 41 additions & 11 deletions internal/js_parser/js_parser.go
Expand Up @@ -910,10 +910,11 @@ func (p *parser) selectLocalKind(kind js_ast.LocalKind) js_ast.LocalKind {
func (p *parser) pushScopeForParsePass(kind js_ast.ScopeKind, loc logger.Loc) int {
parent := p.currentScope
scope := &js_ast.Scope{
Kind: kind,
Parent: parent,
Members: make(map[string]js_ast.ScopeMember),
Label: js_ast.LocRef{Ref: js_ast.InvalidRef},
Kind: kind,
Parent: parent,
Members: make(map[string]js_ast.ScopeMember),
HoistFnRef: make(map[string]*js_ast.Ref),
Label: js_ast.LocRef{Ref: js_ast.InvalidRef},
}
if parent != nil {
parent.Children = append(parent.Children, scope)
Expand Down Expand Up @@ -1107,6 +1108,7 @@ const (
mergeForbidden = iota
mergeReplaceWithNew
mergeOverwriteWithNew
mergeHoist
mergeKeepExisting
mergeBecomePrivateGetSetPair
mergeBecomePrivateStaticGetSetPair
Expand Down Expand Up @@ -1147,14 +1149,12 @@ func (p *parser) canMergeSymbols(scope *js_ast.Scope, existing js_ast.SymbolKind
}
}

// "var foo; var foo;"
// "var foo; function foo() {}"
// "function foo() {} var foo;"
// only top level function can be overwritten
// "function *foo() {} function *foo() {}" but not "{ function *foo() {} function *foo() {} }"
if new.IsHoistedOrFunction() && existing.IsHoistedOrFunction() &&
(scope.Kind == js_ast.ScopeEntry || scope.Kind == js_ast.ScopeFunctionBody ||
(new.IsHoisted() && existing.IsHoisted())) {
return mergeReplaceWithNew
return mergeHoist
}

// "get #foo() {} set #foo() {}"
Expand Down Expand Up @@ -1219,11 +1219,41 @@ func (p *parser) declareSymbol(kind js_ast.SymbolKind, loc logger.Loc, name stri
case mergeReplaceWithNew:
symbol.Link = ref

// If these are both functions, remove the overwritten declaration
if p.options.minifySyntax && kind.IsFunction() && symbol.Kind.IsFunction() {
symbol.Flags |= js_ast.RemoveOverwrittenFunctionDeclaration
case mergeHoist:
if !kind.IsFunction() && !symbol.Kind.IsFunction() {
ref = existing.Ref
break
}

fnRef := p.currentScope.HoistFnRef[name]
if fnRef == nil && symbol.Kind.IsFunction() {
p.currentScope.HoistFnRef[name] = &existing.Ref
fnRef = &existing.Ref
}

if p.options.minifySyntax && fnRef != nil && kind.IsFunction() {
fnSymbol := &p.symbols[fnRef.InnerIndex]
fnSymbol.Flags |= js_ast.RemoveOverwrittenFunctionDeclaration
}

if kind.IsFunction() && symbol.Kind.IsFunction() {
symbol.Link = ref
p.currentScope.HoistFnRef[name] = &ref
break
}

if kind.IsFunction() {
// The past are variables, we encountered the first function
p.currentScope.HoistFnRef[name] = &ref
p.symbols[existing.Ref.InnerIndex].Link = ref

// do not update currentScope.Members
return ref
}

// The past are functions, we encountered the first variable
p.symbols[existing.Ref.InnerIndex].Link = ref

case mergeBecomePrivateGetSetPair:
ref = existing.Ref
symbol.Kind = js_ast.SymbolPrivateGetSetPair
Expand Down
4 changes: 3 additions & 1 deletion internal/js_parser/js_parser_test.go
Expand Up @@ -1357,8 +1357,10 @@ func TestFunction(t *testing.T) {
expectPrintedMangle(t, "function f() {} var f", "function f() {\n}\nvar f;\n")
expectPrintedMangle(t, "var f; function f() { x() } function f() { y() }", "var f;\nfunction f() {\n y();\n}\n")
expectPrintedMangle(t, "function f() { x() } function f() { y() } var f", "function f() {\n y();\n}\nvar f;\n")
expectPrintedMangle(t, "function f() { x() } var f; function f() { y() }", "function f() {\n x();\n}\nvar f;\nfunction f() {\n y();\n}\n")
expectPrintedMangle(t, "function f() { x() } var f; function f() { y() }", "var f;\nfunction f() {\n y();\n}\n")
expectPrintedMangle(t, "export function f() { x() } function f() { y() }", "export function f() {\n x();\n}\nfunction f() {\n y();\n}\n")

expectPrintedMangle(t, "var x = x || {}; console.log(x); var x = x || {};", "var x = x || {};\nconsole.log(x);\nvar x = x || {};\n")
}

func TestClass(t *testing.T) {
Expand Down