Skip to content

Commit

Permalink
add more info to exports errors in package.json
Browse files Browse the repository at this point in the history
  • Loading branch information
evanw committed Jan 11, 2023
1 parent d751dfb commit 9cc2b84
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 12 deletions.
10 changes: 5 additions & 5 deletions internal/bundler_tests/bundler_packagejson_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1362,7 +1362,7 @@ func TestPackageJsonExportsErrorInvalidPackageTarget(t *testing.T) {
{ "exports": { ".": "invalid" } }
`,
"/Users/user/project/node_modules/pkg2/package.json": `
{ "exports": { ".": "../pkg3" } }
{ "exports": { ".": "./../pkg3" } }
`,
"/Users/user/project/node_modules/pkg3/package.json": `
{ "exports": { ".": "./node_modules/pkg" } }
Expand All @@ -1374,13 +1374,13 @@ func TestPackageJsonExportsErrorInvalidPackageTarget(t *testing.T) {
AbsOutputFile: "/Users/user/project/out.js",
},
expectedScanLog: `Users/user/project/src/entry.js: ERROR: Could not resolve "pkg1"
Users/user/project/node_modules/pkg1/package.json: NOTE: The package target "invalid" is invalid:
Users/user/project/node_modules/pkg1/package.json: NOTE: The package target "invalid" is invalid because it doesn't start with "./":
NOTE: You can mark the path "pkg1" as external to exclude it from the bundle, which will remove this error.
Users/user/project/src/entry.js: ERROR: Could not resolve "pkg2"
Users/user/project/node_modules/pkg2/package.json: NOTE: The package target "../pkg3" is invalid:
Users/user/project/node_modules/pkg2/package.json: NOTE: The package target "./../pkg3" is invalid because it contains invalid segment "..":
NOTE: You can mark the path "pkg2" as external to exclude it from the bundle, which will remove this error.
Users/user/project/src/entry.js: ERROR: Could not resolve "pkg3"
Users/user/project/node_modules/pkg3/package.json: NOTE: The package target "./node_modules/pkg" is invalid:
Users/user/project/node_modules/pkg3/package.json: NOTE: The package target "./node_modules/pkg" is invalid because it contains invalid segment "node_modules":
NOTE: You can mark the path "pkg3" as external to exclude it from the bundle, which will remove this error.
`,
})
Expand Down Expand Up @@ -1853,7 +1853,7 @@ func TestPackageJsonExportsErrorMissingTrailingSlash(t *testing.T) {
AbsOutputFile: "/Users/user/project/out.js",
},
expectedScanLog: `Users/user/project/src/entry.js: ERROR: Could not resolve "pkg1/foo/bar"
Users/user/project/node_modules/pkg1/package.json: NOTE: The module specifier "./test" is invalid:
Users/user/project/node_modules/pkg1/package.json: NOTE: The module specifier "./test" is invalid because it doesn't end in "/":
NOTE: You can mark the path "pkg1/foo/bar" as external to exclude it from the bundle, which will remove this error.
`,
})
Expand Down
26 changes: 21 additions & 5 deletions internal/resolver/package_json.go
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,10 @@ func (status pjStatus) isUndefined() bool {
}

type pjDebug struct {
// If the status is "pjStatusInvalidPackageTarget" or "pjStatusInvalidModuleSpecifier",
// then this is the reason. It always starts with " because".
invalidBecause string

// If the status is "pjStatusUndefinedNoConditionsMatch", this is the set of
// conditions that didn't match, in the order that they were found in the file.
// This information is used for error messages.
Expand Down Expand Up @@ -1018,9 +1022,12 @@ func (r resolverQuery) esmPackageTargetResolve(
// does not end with "/", throw an Invalid Module Specifier error.
if !pattern && subpath != "" && !strings.HasSuffix(target.strData, "/") {
if r.debugLogs != nil {
r.debugLogs.addNote(fmt.Sprintf("The target %q is invalid because it doesn't end \"/\"", target.strData))
r.debugLogs.addNote(fmt.Sprintf("The target %q is invalid because it doesn't end in \"/\"", target.strData))
}
return target.strData, pjStatusInvalidModuleSpecifier, pjDebug{
token: target.firstToken,
invalidBecause: " because it doesn't end in \"/\"",
}
return target.strData, pjStatusInvalidModuleSpecifier, pjDebug{token: target.firstToken}
}

// If target does not start with "./", then...
Expand All @@ -1042,7 +1049,10 @@ func (r resolverQuery) esmPackageTargetResolve(
if r.debugLogs != nil {
r.debugLogs.addNote(fmt.Sprintf("The target %q is invalid because it doesn't start with \"./\"", target.strData))
}
return target.strData, pjStatusInvalidPackageTarget, pjDebug{token: target.firstToken}
return target.strData, pjStatusInvalidPackageTarget, pjDebug{
token: target.firstToken,
invalidBecause: " because it doesn't start with \"./\"",
}
}

// If target split on "/" or "\" contains any ".", ".." or "node_modules"
Expand All @@ -1051,7 +1061,10 @@ func (r resolverQuery) esmPackageTargetResolve(
if r.debugLogs != nil {
r.debugLogs.addNote(fmt.Sprintf("The target %q is invalid because it contains invalid segment %q", target.strData, invalidSegment))
}
return target.strData, pjStatusInvalidPackageTarget, pjDebug{token: target.firstToken}
return target.strData, pjStatusInvalidPackageTarget, pjDebug{
token: target.firstToken,
invalidBecause: fmt.Sprintf(" because it contains invalid segment %q", invalidSegment),
}
}

// Let resolvedTarget be the URL resolution of the concatenation of packageURL and target.
Expand All @@ -1063,7 +1076,10 @@ func (r resolverQuery) esmPackageTargetResolve(
if r.debugLogs != nil {
r.debugLogs.addNote(fmt.Sprintf("The path %q is invalid because it contains invalid segment %q", subpath, invalidSegment))
}
return subpath, pjStatusInvalidModuleSpecifier, pjDebug{token: target.firstToken}
return subpath, pjStatusInvalidModuleSpecifier, pjDebug{
token: target.firstToken,
invalidBecause: fmt.Sprintf(" because it contains invalid segment %q", invalidSegment),
}
}

if pattern {
Expand Down
4 changes: 2 additions & 2 deletions internal/resolver/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -2326,14 +2326,14 @@ func (r resolverQuery) finalizeImportsExportsResult(
switch status {
case pjStatusInvalidModuleSpecifier:
r.debugMeta.notes = []logger.MsgData{tracker.MsgData(debug.token,
fmt.Sprintf("The module specifier %q is invalid:", resolvedPath))}
fmt.Sprintf("The module specifier %q is invalid%s:", resolvedPath, debug.invalidBecause))}

case pjStatusInvalidPackageConfiguration:
r.debugMeta.notes = []logger.MsgData{tracker.MsgData(debug.token,
"The package configuration has an invalid value here:")}

case pjStatusInvalidPackageTarget:
why := fmt.Sprintf("The package target %q is invalid:", resolvedPath)
why := fmt.Sprintf("The package target %q is invalid%s:", resolvedPath, debug.invalidBecause)
if resolvedPath == "" {
// "PACKAGE_TARGET_RESOLVE" is specified to throw an "Invalid
// Package Target" error for what is actually an invalid package
Expand Down

0 comments on commit 9cc2b84

Please sign in to comment.