Skip to content

Commit

Permalink
special-case "index" in name-from-path
Browse files Browse the repository at this point in the history
  • Loading branch information
evanw committed Jun 14, 2020
1 parent 1a891e8 commit b6e98c3
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 52 deletions.
52 changes: 46 additions & 6 deletions internal/ast/ast.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package ast

import (
"path"
"strings"
)

Expand Down Expand Up @@ -1259,12 +1258,53 @@ func MergeSymbols(symbols SymbolMap, old Ref, new Ref) Ref {
return new
}

func GenerateNonUniqueNameFromPath(text string) string {
// This has a custom implementation instead of using "filepath.Base" because it
// should work the same on Unix and Windows. These names end up in the generated
// output and the generated output should not depend on the OS.
func platformIndependentPathDirAndBaseWithoutExt(path string) (string, string) {
dir := ""
for {
i := strings.LastIndexAny(path, "/\\")
if i < 0 {
break
}
if i+1 != len(path) {
dir = path[:i]
path = path[i+1:]
break
}
path = path[:i]
}
if dot := strings.LastIndexByte(path, '.'); dot >= 0 {
path = path[:dot]
}
return dir, path
}

// For readability, the names of certain automatically-generated symbols are
// derived from the file name. For example, instead of the CommonJS wrapper for
// a file being called something like "require273" it can be called something
// like "require_react" instead. This function generates the part of these
// identifiers that's specific to the file path. It can take both an absolute
// path (OS-specific) and a path in the source code (OS-independent).
//
// Note that these generated names do not at all relate to the correctness of
// the code as far as avoiding symbol name collisions. These names still go
// through the renaming logic that all other symbols go through to avoid name
// collisions.
func GenerateNonUniqueNameFromPath(path string) string {
// Get the file name without the extension
base := path.Base(text)
lastDot := strings.LastIndexByte(base, '.')
if lastDot >= 0 {
base = base[:lastDot]
dir, base := platformIndependentPathDirAndBaseWithoutExt(path)

// If the name is "index", use the directory name instead. This is because
// many packages in npm use the file name "index.js" because it triggers
// node's implicit module resolution rules that allows you to import it by
// just naming the directory.
if base == "index" {
_, dirBase := platformIndependentPathDirAndBaseWithoutExt(dir)
if dirBase != "" {
base = dirBase
}
}

// Convert it to an ASCII identifier
Expand Down
23 changes: 23 additions & 0 deletions internal/ast/ast_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package ast

import "testing"

func assertEqual(t *testing.T, a interface{}, b interface{}) {
if a != b {
t.Fatalf("%s != %s", a, b)
}
}

func TestGenerateNonUniqueNameFromPath(t *testing.T) {
assertEqual(t, GenerateNonUniqueNameFromPath("<stdin>"), "stdin")
assertEqual(t, GenerateNonUniqueNameFromPath("foo/bar"), "bar")
assertEqual(t, GenerateNonUniqueNameFromPath("foo/bar.js"), "bar")
assertEqual(t, GenerateNonUniqueNameFromPath("foo/bar.min.js"), "bar_min")
assertEqual(t, GenerateNonUniqueNameFromPath("trailing//slashes//"), "slashes")
assertEqual(t, GenerateNonUniqueNameFromPath("path/with/spaces in name.js"), "spaces_in_name")
assertEqual(t, GenerateNonUniqueNameFromPath("path\\on\\windows.js"), "windows")
assertEqual(t, GenerateNonUniqueNameFromPath("node_modules/demo-pkg/index.js"), "demo_pkg")
assertEqual(t, GenerateNonUniqueNameFromPath("node_modules\\demo-pkg\\index.js"), "demo_pkg")
assertEqual(t, GenerateNonUniqueNameFromPath("123_invalid_identifier.js"), "invalid_identifier")
assertEqual(t, GenerateNonUniqueNameFromPath("emoji 🍕 name.js"), "emoji_name")
}
30 changes: 15 additions & 15 deletions internal/bundler/bundler_dce_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,13 @@ func TestPackageJsonSideEffectsFalseKeepNamedImportCommonJS(t *testing.T) {
},
expected: map[string]string{
"/out.js": `// /Users/user/project/node_modules/demo-pkg/index.js
var require_index = __commonJS((exports) => {
var require_demo_pkg = __commonJS((exports) => {
exports.foo = 123;
console.log("hello");
});
// /Users/user/project/src/entry.js
const demo_pkg = __toModule(require_index());
const demo_pkg = __toModule(require_demo_pkg());
console.log(demo_pkg.foo);
`,
},
Expand Down Expand Up @@ -110,15 +110,15 @@ func TestPackageJsonSideEffectsFalseKeepStarImportES6(t *testing.T) {
},
expected: map[string]string{
"/out.js": `// /Users/user/project/node_modules/demo-pkg/index.js
const index_exports = {};
__export(index_exports, {
const demo_pkg_exports = {};
__export(demo_pkg_exports, {
foo: () => foo
});
const foo = 123;
console.log("hello");
// /Users/user/project/src/entry.js
console.log(index_exports);
console.log(demo_pkg_exports);
`,
},
})
Expand Down Expand Up @@ -151,13 +151,13 @@ func TestPackageJsonSideEffectsFalseKeepStarImportCommonJS(t *testing.T) {
},
expected: map[string]string{
"/out.js": `// /Users/user/project/node_modules/demo-pkg/index.js
var require_index = __commonJS((exports) => {
var require_demo_pkg = __commonJS((exports) => {
exports.foo = 123;
console.log("hello");
});
// /Users/user/project/src/entry.js
const ns = __toModule(require_index());
const ns = __toModule(require_demo_pkg());
console.log(ns);
`,
},
Expand Down Expand Up @@ -227,13 +227,13 @@ func TestPackageJsonSideEffectsTrueKeepCommonJS(t *testing.T) {
},
expected: map[string]string{
"/out.js": `// /Users/user/project/node_modules/demo-pkg/index.js
var require_index = __commonJS((exports) => {
var require_demo_pkg = __commonJS((exports) => {
exports.foo = 123;
console.log("hello");
});
// /Users/user/project/src/entry.js
const demo_pkg = __toModule(require_index());
const demo_pkg = __toModule(require_demo_pkg());
console.log("unused import");
`,
},
Expand Down Expand Up @@ -268,7 +268,7 @@ func TestPackageJsonSideEffectsFalseKeepBareImportAndRequireES6(t *testing.T) {
},
expected: map[string]string{
"/out.js": `// /Users/user/project/node_modules/demo-pkg/index.js
var require_index = __commonJS((exports) => {
var require_demo_pkg = __commonJS((exports) => {
__export(exports, {
foo: () => foo
});
Expand All @@ -277,7 +277,7 @@ var require_index = __commonJS((exports) => {
});
// /Users/user/project/src/entry.js
require_index();
require_demo_pkg();
console.log("unused import");
`,
},
Expand Down Expand Up @@ -312,13 +312,13 @@ func TestPackageJsonSideEffectsFalseKeepBareImportAndRequireCommonJS(t *testing.
},
expected: map[string]string{
"/out.js": `// /Users/user/project/node_modules/demo-pkg/index.js
var require_index = __commonJS((exports) => {
var require_demo_pkg = __commonJS((exports) => {
exports.foo = 123;
console.log("hello");
});
// /Users/user/project/src/entry.js
require_index();
require_demo_pkg();
console.log("unused import");
`,
},
Expand Down Expand Up @@ -651,10 +651,10 @@ func TestPackageJsonSideEffectsKeepExportDefaultExpr(t *testing.T) {
},
expected: map[string]string{
"/out.js": `// /Users/user/project/node_modules/demo-pkg/index.js
const index_default = exprWithSideEffects();
const demo_pkg_default = exprWithSideEffects();
// /Users/user/project/src/entry.js
console.log(index_default);
console.log(demo_pkg_default);
`,
},
})
Expand Down
6 changes: 3 additions & 3 deletions internal/bundler/bundler_importstar_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1974,13 +1974,13 @@ const foo = () => "hi there";
// /folders/child/index.js
// /folders/index.js
const index_exports = {};
__export(index_exports, {
const folders_exports = {};
__export(folders_exports, {
foo: () => foo
});
// /entry.js
console.log(JSON.stringify(index_exports));
console.log(JSON.stringify(folders_exports));
`,
},
})
Expand Down
Loading

0 comments on commit b6e98c3

Please sign in to comment.