Skip to content

Commit

Permalink
rename when clashing with imported symbol
Browse files Browse the repository at this point in the history
  • Loading branch information
indutny-signal committed Mar 2, 2022
1 parent 38ff6e1 commit 7257144
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 24 deletions.
6 changes: 3 additions & 3 deletions internal/bundler/snapshots/snapshots_ts.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1083,14 +1083,14 @@ function dec(x) {
}
function fn(x) {
var _a2;
class Foo {
class Foo3 {
[_a2 = arguments[0]]() {
}
}
__decorateClass([
dec(arguments[0])
], Foo.prototype, _a2, 1);
return Foo;
], Foo3.prototype, _a2, 1);
return Foo3;
}

// entry.js
Expand Down
4 changes: 4 additions & 0 deletions internal/js_ast/js_ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -1602,6 +1602,9 @@ const (
// This means the symbol is a normal function that takes a single argument
// and returns that argument.
IsIdentityFunction

// This means that symbol was merged with js_ast.MergeSymbols
WasMerged
)

func (flags SymbolFlags) Has(flag SymbolFlags) bool {
Expand Down Expand Up @@ -2434,6 +2437,7 @@ func MergeSymbols(symbols SymbolMap, old Ref, new Ref) Ref {

oldSymbol.Link = new
newSymbol.MergeContentsWith(oldSymbol)
newSymbol.Flags |= WasMerged
return new
}

Expand Down
41 changes: 29 additions & 12 deletions internal/renamer/renamer.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ func NewNumberRenamer(symbols js_ast.SymbolMap, reservedNames map[string]uint32)
return &NumberRenamer{
symbols: symbols,
names: make([][]string, len(symbols.SymbolsForSource)),
root: numberScope{nameCounts: reservedNames},
root: numberScope{nameCounts: reservedNames, mergedRefs: make(map[string]js_ast.Ref)},
}
}

Expand Down Expand Up @@ -452,7 +452,7 @@ func (r *NumberRenamer) assignName(scope *numberScope, ref js_ast.Ref, shallowLo
}

// Compute a new name
name := scope.findUnusedName(originalName, shallowLookup)
name := scope.findUnusedName(symbol, ref, originalName, shallowLookup)

// Store the new name
if inner == nil {
Expand All @@ -472,7 +472,7 @@ func (r *NumberRenamer) assignName(scope *numberScope, ref js_ast.Ref, shallowLo
}

func (r *NumberRenamer) assignNamesRecursive(scope *js_ast.Scope, sourceIndex uint32, parent *numberScope, sorted *[]int) {
s := &numberScope{parent: parent, nameCounts: make(map[string]uint32)}
s := &numberScope{parent: parent, nameCounts: make(map[string]uint32), mergedRefs: make(map[string]js_ast.Ref)}

// Sort member map keys for determinism, reusing a shared memory buffer
*sorted = (*sorted)[:0]
Expand Down Expand Up @@ -523,6 +523,8 @@ type numberScope struct {
// count here so that subsequent collisions can start counting from where the
// previous collision ended instead of having to start counting from 1.
nameCounts map[string]uint32

mergedRefs map[string]js_ast.Ref
}

type nameUse uint8
Expand All @@ -533,26 +535,38 @@ const (
nameUsedInSameScope
)

func (s *numberScope) findNameUse(name string, shallowLookup bool) nameUse {
func (s *numberScope) findNameUse(ref js_ast.Ref, name string, shallowLookup bool) nameUse {
original := s
depth := 0
for {
if _, ok := s.nameCounts[name]; ok {
if s == original {
return nameUsedInSameScope
if otherRef, ok := s.mergedRefs[name]; ok {
if otherRef.SourceIndex != ref.SourceIndex {
return nameUsed
}
}

if !shallowLookup || depth == 0 {
if _, ok := s.nameCounts[name]; ok {
if s == original {
return nameUsedInSameScope
}
return nameUsed
}
return nameUsed
}

s = s.parent
if s == nil || shallowLookup {
if s == nil {
return nameUnused
}

depth++
}
}

func (s *numberScope) findUnusedName(name string, shallowLookup bool) string {
func (s *numberScope) findUnusedName(symbol *js_ast.Symbol, ref js_ast.Ref, name string, shallowLookup bool) string {
name = js_lexer.ForceValidIdentifier(name)

if use := s.findNameUse(name, shallowLookup); use != nameUnused {
if use := s.findNameUse(ref, name, shallowLookup); use != nameUnused {
// If the name is already in use, generate a new name by appending a number
tries := uint32(1)
if use == nameUsedInSameScope {
Expand All @@ -573,7 +587,7 @@ func (s *numberScope) findUnusedName(name string, shallowLookup bool) string {
name = prefix + strconv.Itoa(int(tries))

// Make sure this new name is unused
if s.findNameUse(name, shallowLookup) == nameUnused {
if s.findNameUse(ref, name, shallowLookup) == nameUnused {
// Store the count so we can start here next time instead of starting
// from 1. This means we avoid O(n^2) behavior.
if use == nameUsedInSameScope {
Expand All @@ -587,6 +601,9 @@ func (s *numberScope) findUnusedName(name string, shallowLookup bool) string {
// Each name starts off with a count of 1 so that the first collision with
// "name" is called "name2"
s.nameCounts[name] = 1
if symbol.Flags.Has(js_ast.WasMerged) {
s.mergedRefs[name] = ref
}
return name
}

Expand Down
31 changes: 22 additions & 9 deletions scripts/end-to-end-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -3162,15 +3162,28 @@
if (first(1) !== 1 || second(1) !== 1) throw 'fail';
`,
'first.js': `
export const outer = function outer(self = outer) {
return self;
}
`,
'second.js': `
export const outer = function outer(self = outer) {
return self;
}
`,
export const outer = function outer(self = outer) {
return self;
}
`,
'second.js': `
export const outer = function outer(self = outer) {
return self;
}
`,
}),
test(['in.js', '--bundle', '--outfile=node.js'], {
'in.js': `
import { num as otherNum } from './first.js';
function sum(num) {
return num + otherNum;
}
if (sum(321) !== 123 + 321) throw 'fail';
`,
'first.js': `
export const num = 123;
`,
}),
);

Expand Down

0 comments on commit 7257144

Please sign in to comment.