mirror of
https://github.com/morluto/rea.git
synced 2026-10-26 17:35:11 +00:00
fix(importer): reach package-main selection for trailing-slash directory references (#4219)
* fix(importer): reach package-main selection for trailing-slash directory references
posix.normalize preserves a trailing slash in the specifier, so normalized was sub/ while dirname(match) was sub; the resolvedThroughIndex comparison failed and selectPackageMain never ran for require("./sub/"). Compare against the slash-stripped directory so trailing-slash directory references take the same package-main path as the plain spelling. Boundary rows pair each trailing-slash request with the existing manifest fixtures and are validated against Node's own resolver in the same table.
Fixes #4189
* fix(importer): derive trailing-slash directory identity with path semantics
The lookbehind strip kept a trailing slash when the final component ended in a line terminator (require("./pkg\n/")), so dirname(match) still never matched and the trailing-slash path skipped package-main selection for those directories. Join the normalized path with "." instead: path semantics collapse any trailing slash run regardless of the preceding character, and behave identically to the strip on every other spelling. Boundary fixture gains a newline directory with a package.json, an index and a declared main so the index path (not the no-match branch) exercises the comparison.
Addresses Codex P1 on #4219
* fix(importer): normalize package-main targets with path semantics
---------
Co-authored-by: Hemang Varshney <218273197+hemv-857@users.noreply.github.com>
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2 files changed
+27
-4
No files matched your search
@@ -269,9 +269,9 @@ const selectPackageMain = (
|
||||
// package, and a trailing separator does not make the entry a directory.
|
||||
if (posix.isAbsolute(manifest.main))
|
||||
return { to: posix.normalize(manifest.main), resolution: "unresolved" };
|
||||
const target = posix
|
||||
.normalize(posix.join(packageDirectory, manifest.main))
|
||||
.replace(/(?<=.)\/+$/u, "");
|
||||
// Joining "." strips the trailing separator run with path semantics; a
|
||||
// lookbehind regex kept separators behind line terminators (main "lib\n/").
|
||||
const target = posix.join(posix.join(packageDirectory, manifest.main), ".");
|
||||
// Node would load a declared entry outside the imported root.
|
||||
if (logicalPathEscapesRoot(target))
|
||||
return { to: target, resolution: "unresolved" };
|
||||
@@ -395,9 +395,15 @@ const resolveInternalSpecifier = (
|
||||
return packageMainForDirectory(normalized, context) !== undefined
|
||||
? selectPackageMain(normalized, undefined, context, mode)
|
||||
: { to: normalized, resolution: "unresolved" };
|
||||
// posix.normalize preserves the specifier's trailing slash while
|
||||
// dirname(match) never carries one; derive the directory identity with path
|
||||
// semantics (joining "." collapses trailing slashes, including ones a regex
|
||||
// would keep behind a line terminator) so a trailing-slash reference still
|
||||
// reaches package-main selection the same way the plain spelling does.
|
||||
const directory = posix.join(normalized, ".");
|
||||
const resolvedThroughIndex =
|
||||
posix.basename(match).startsWith("index.") &&
|
||||
posix.dirname(match).normalize("NFC") === normalized.normalize("NFC");
|
||||
posix.dirname(match).normalize("NFC") === directory.normalize("NFC");
|
||||
return resolvedThroughIndex
|
||||
? selectPackageMain(posix.dirname(match), match, context, mode)
|
||||
: { to: match, resolution: "internal" };
|
||||
|
||||
@@ -37,10 +37,14 @@ const prepareReferenceSourceDirectoryFixture =
|
||||
["legacy-order.cjs", "./dep", "dep/index.js"],
|
||||
["bare-index.cjs", "./bare", "bare.js"],
|
||||
["package-main.cjs", "./pkg", "pkg/actual.js"],
|
||||
["package-main-slash-specifier.cjs", "./pkg/", "pkg/actual.js"],
|
||||
["package-main-newline-slash.cjs", "./pkg\n/", "pkg\n/actual.js"],
|
||||
["package-main-no-index.cjs", "./no-index-pkg", "no-index-pkg/actual.js"],
|
||||
["package-main-fallback.cjs", "./stale", "stale/index.js"],
|
||||
["package-main-fallback-slash.cjs", "./stale/", "stale/index.js"],
|
||||
["typed-index-collision.cjs", "./typed", "typed.js"],
|
||||
["package-main-slash.cjs", "./slashed", "slashed/lib.js"],
|
||||
["package-main-manifest-newline-slash.cjs", "./nlpkg/", "nlpkg/lib\n.js"],
|
||||
["json.cjs", "./data", "data.json"],
|
||||
["json-explicit.cjs", "./data.json", "data.json"],
|
||||
["json-before-index.cjs", "./conf", "conf.json"],
|
||||
@@ -70,6 +74,12 @@ const prepareReferenceSourceDirectoryFixture =
|
||||
["bare/index", 'module.exports = "extensionless index";\n'],
|
||||
["only/index", 'module.exports = "extensionless index";\n'],
|
||||
["pkg/package.json", '{"main":"actual.js"}\n'],
|
||||
["pkg\n/package.json", '{"main":"actual.js"}\n'],
|
||||
[
|
||||
"pkg\n/actual.js",
|
||||
'module.exports = "declared main behind line terminator";\n',
|
||||
],
|
||||
["pkg\n/index.js", 'module.exports = "index not selected";\n'],
|
||||
["pkg/actual.js", 'module.exports = "declared main";\n'],
|
||||
["pkg/index.js", 'module.exports = "ignored index";\n'],
|
||||
["no-index-pkg/package.json", '{"main":"actual.js"}\n'],
|
||||
@@ -87,6 +97,13 @@ const prepareReferenceSourceDirectoryFixture =
|
||||
["slashed/lib.js", 'module.exports = "file main";\n'],
|
||||
["slashed/lib/index.js", 'module.exports = "not selected";\n'],
|
||||
["slashed/index.js", 'module.exports = "not selected";\n'],
|
||||
["nlpkg/package.json", '{"main":"lib\\n/"}\n'],
|
||||
[
|
||||
"nlpkg/lib\n.js",
|
||||
'module.exports = "file main behind line terminator";\n',
|
||||
],
|
||||
["nlpkg/lib\n/index.js", 'module.exports = "not selected";\n'],
|
||||
["nlpkg/index.js", 'module.exports = "entry index";\n'],
|
||||
["absolute/package.json", `${JSON.stringify({ main: outside })}\n`],
|
||||
["absolute/index.js", 'module.exports = "not selected";\n'],
|
||||
["data.json", '{"value":1}\n'],
|
||||
|
||||
Reference in new issue
Block a user