Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 89 additions & 7 deletions internal/bundler_tests/bundler_packagejson_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2416,27 +2416,109 @@ NOTE: You can mark the path "#" as external to exclude it from the bundle, which
})
}

func TestPackageJsonImportsErrorStartsWithHashSlash(t *testing.T) {
// Tests for new Node.js behavior: https://github.com/nodejs/node/pull/60864
// The #/ prefix is now allowed in subpath imports when there's a matching pattern

func TestPackageJsonImportsHashSlashWithWildcard(t *testing.T) {
packagejson_suite.expectBundled(t, bundled{
files: map[string]string{
"/Users/user/project/src/entry.js": `
import '#/foo'
import '#/foo.js'
import '#/bar/baz.js'
`,
"/Users/user/project/src/package.json": `
{
"imports": {}
"imports": {
"#/*": "./src/*"
}
}
`,
"/Users/user/project/src/src/foo.js": `console.log('foo.js')`,
"/Users/user/project/src/src/bar/baz.js": `console.log('bar/baz.js')`,
},
entryPaths: []string{"/Users/user/project/src/entry.js"},
options: config.Options{
Mode: config.ModeBundle,
AbsOutputFile: "/Users/user/project/out.js",
},
})
}

func TestPackageJsonImportsHashSlashExactMatch(t *testing.T) {
packagejson_suite.expectBundled(t, bundled{
files: map[string]string{
"/Users/user/project/src/entry.js": `
import '#/'
import '#/utils'
`,
"/Users/user/project/src/package.json": `
{
"imports": {
"#/": "./index.js",
"#/utils": "./utils.js"
}
}
`,
"/Users/user/project/src/index.js": `console.log('index.js')`,
"/Users/user/project/src/utils.js": `console.log('utils.js')`,
},
entryPaths: []string{"/Users/user/project/src/entry.js"},
options: config.Options{
Mode: config.ModeBundle,
AbsOutputFile: "/Users/user/project/out.js",
},
})
}

func TestPackageJsonImportsHashSlashWithConditions(t *testing.T) {
packagejson_suite.expectBundled(t, bundled{
files: map[string]string{
"/Users/user/project/src/entry.js": `
import '#/lib'
`,
"/Users/user/project/src/package.json": `
{
"imports": {
"#/*": {
"import": "./esm/*.js",
"require": "./cjs/*.js"
}
}
}
`,
"/Users/user/project/src/esm/lib.js": `console.log('esm/lib.js')`,
"/Users/user/project/src/cjs/lib.js": `console.log('cjs/lib.js')`,
},
entryPaths: []string{"/Users/user/project/src/entry.js"},
options: config.Options{
Mode: config.ModeBundle,
AbsOutputFile: "/Users/user/project/out.js",
},
})
}

func TestPackageJsonImportsHashSlashSymmetricWithExports(t *testing.T) {
// Common pattern: symmetric imports/exports for root-relative imports
packagejson_suite.expectBundled(t, bundled{
files: map[string]string{
"/Users/user/project/src/entry.js": `
import '#/components/button.js'
import '#/utils/format.js'
`,
"/Users/user/project/src/package.json": `
{
"exports": { "./*": "./src/*" },
"imports": { "#/*": "./src/*" }
}
`,
"/Users/user/project/src/src/components/button.js": `console.log('button.js')`,
"/Users/user/project/src/src/utils/format.js": `console.log('format.js')`,
},
entryPaths: []string{"/Users/user/project/src/entry.js"},
options: config.Options{
Mode: config.ModeBundle,
AbsOutputFile: "/Users/user/project/out.js",
},
expectedScanLog: `Users/user/project/src/entry.js: ERROR: Could not resolve "#/foo"
Users/user/project/src/package.json: NOTE: This "imports" map was ignored because the module specifier "#/foo" is invalid:
NOTE: You can mark the path "#/foo" as external to exclude it from the bundle, which will remove this error and leave the unresolved path in the bundle.
`,
})
}

Expand Down
33 changes: 33 additions & 0 deletions internal/bundler_tests/snapshots/snapshots_packagejson.txt
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,39 @@ console.log("c.js");
// Users/user/project/src/node_modules/pkg/some-slash/d.js
console.log("d.js");

================================================================================
TestPackageJsonImportsHashSlashExactMatch
---------- /Users/user/project/out.js ----------
// Users/user/project/src/index.js
console.log("index.js");

// Users/user/project/src/utils.js
console.log("utils.js");

================================================================================
TestPackageJsonImportsHashSlashSymmetricWithExports
---------- /Users/user/project/out.js ----------
// Users/user/project/src/src/components/button.js
console.log("button.js");

// Users/user/project/src/src/utils/format.js
console.log("format.js");

================================================================================
TestPackageJsonImportsHashSlashWithConditions
---------- /Users/user/project/out.js ----------
// Users/user/project/src/esm/lib.js
console.log("esm/lib.js");

================================================================================
TestPackageJsonImportsHashSlashWithWildcard
---------- /Users/user/project/out.js ----------
// Users/user/project/src/src/foo.js
console.log("foo.js");

// Users/user/project/src/src/bar/baz.js
console.log("bar/baz.js");

================================================================================
TestPackageJsonMain
---------- /Users/user/project/out.js ----------
Expand Down
6 changes: 3 additions & 3 deletions internal/resolver/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -2255,10 +2255,10 @@ func (r resolverQuery) loadPackageImports(importPath string, dirInfoPackageJSON
}

// Filter out invalid module specifiers now where we have more information for
// a better error message instead of later when we're inside the algorithm
if importPath == "#" || strings.HasPrefix(importPath, "#/") {
// a better error message instead of later when we're inside the algorithm.
if importPath == "#" {
if r.debugLogs != nil {
r.debugLogs.addNote(fmt.Sprintf("The path %q must not equal \"#\" and must not start with \"#/\".", importPath))
r.debugLogs.addNote(fmt.Sprintf("The path %q must not equal \"#\".", importPath))
}
tracker := logger.MakeLineColumnTracker(&packageJSON.source)
r.debugMeta.notes = append(r.debugMeta.notes, tracker.MsgData(packageJSON.importsMap.root.firstToken,
Expand Down
Loading