Skip to content

Commit cecc193

Browse files
guybedfordcodebytere
authored andcommitted
module: share CJS/ESM resolver fns, refactoring
PR-URL: #34744 Backport-PR-URL: #35385 Reviewed-By: Jan Krems <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent d9857fd commit cecc193

File tree

8 files changed

+317
-569
lines changed

8 files changed

+317
-569
lines changed

doc/api/esm.md

+115-144
Large diffs are not rendered by default.

doc/api/modules.md

+39-41
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,10 @@ require(X) from module at path Y
161161
b. LOAD_AS_DIRECTORY(Y + X)
162162
c. THROW "not found"
163163
4. If X begins with '#'
164-
a. LOAD_INTERAL_IMPORT(X, Y)
165-
4. LOAD_SELF_REFERENCE(X, Y)
166-
5. LOAD_NODE_MODULES(X, dirname(Y))
167-
6. THROW "not found"
164+
a. LOAD_PACKAGE_IMPORTS(X, dirname(Y))
165+
5. LOAD_PACKAGE_SELF(X, dirname(Y))
166+
6. LOAD_NODE_MODULES(X, dirname(Y))
167+
7. THROW "not found"
168168
169169
LOAD_AS_FILE(X)
170170
1. If X is a file, load X as its file extension format. STOP
@@ -191,7 +191,7 @@ LOAD_AS_DIRECTORY(X)
191191
LOAD_NODE_MODULES(X, START)
192192
1. let DIRS = NODE_MODULES_PATHS(START)
193193
2. for each DIR in DIRS:
194-
a. LOAD_PACKAGE_EXPORTS(DIR, X)
194+
a. LOAD_PACKAGE_EXPORTS(X, DIR)
195195
b. LOAD_AS_FILE(DIR/X)
196196
c. LOAD_AS_DIRECTORY(DIR/X)
197197
@@ -206,47 +206,45 @@ NODE_MODULES_PATHS(START)
206206
d. let I = I - 1
207207
5. return DIRS
208208
209-
LOAD_SELF_REFERENCE(X, START)
210-
1. Find the closest package scope to START.
209+
LOAD_PACKAGE_IMPORTS(X, DIR)
210+
1. Find the closest package scope SCOPE to DIR.
211211
2. If no scope was found, return.
212-
3. If the `package.json` has no "exports", return.
213-
4. If the name in `package.json` is a prefix of X, then
214-
a. Load the remainder of X relative to this package as if it was
215-
loaded via `LOAD_NODE_MODULES` with a name in `package.json`.
212+
3. If the SCOPE/package.json "imports" is null or undefined, return.
213+
4. let MATCH = PACKAGE_IMPORTS_RESOLVE(X, pathToFileURL(SCOPE),
214+
["node", "require"]) defined in the ESM resolver.
215+
5. RESOLVE_ESM_MATCH(MATCH).
216216
217-
LOAD_PACKAGE_EXPORTS(DIR, X)
218-
1. Try to interpret X as a combination of name and subpath where the name
217+
LOAD_PACKAGE_EXPORTS(X, DIR)
218+
1. Try to interpret X as a combination of NAME and SUBPATH where the name
219219
may have a @scope/ prefix and the subpath begins with a slash (`/`).
220-
2. If X does not match this pattern or DIR/name/package.json is not a file,
220+
2. If X does not match this pattern or DIR/NAME/package.json is not a file,
221221
return.
222-
3. Parse DIR/name/package.json, and look for "exports" field.
222+
3. Parse DIR/NAME/package.json, and look for "exports" field.
223223
4. If "exports" is null or undefined, return.
224-
5. If "exports" is an object with some keys starting with "." and some keys
225-
not starting with ".", throw "invalid config".
226-
6. If "exports" is a string, or object with no keys starting with ".", treat
227-
it as having that value as its "." object property.
228-
7. If subpath is "." and "exports" does not have a "." entry, return.
229-
8. Find the longest key in "exports" that the subpath starts with.
230-
9. If no such key can be found, throw "not found".
231-
10. let RESOLVED =
232-
fileURLToPath(PACKAGE_EXPORTS_TARGET_RESOLVE(pathToFileURL(DIR/name),
233-
exports[key], subpath.slice(key.length), ["node", "require"])), as defined
234-
in the ESM resolver.
235-
11. If key ends with "/":
236-
a. LOAD_AS_FILE(RESOLVED)
237-
b. LOAD_AS_DIRECTORY(RESOLVED)
238-
12. Otherwise
239-
a. If RESOLVED is a file, load it as its file extension format. STOP
240-
13. Throw "not found"
241-
242-
LOAD_INTERNAL_IMPORT(X, START)
243-
1. Find the closest package scope to START.
244-
2. If no scope was found or the `package.json` has no "imports", return.
245-
3. let RESOLVED =
246-
fileURLToPath(PACKAGE_INTERNAL_RESOLVE(X, pathToFileURL(START)), as defined
247-
in the ESM resolver.
248-
4. If RESOLVED is not a valid file, throw "not found"
249-
5. Load RESOLVED as its file extension format. STOP
224+
5. let MATCH = PACKAGE_EXPORTS_RESOLVE(pathToFileURL(DIR/NAME), "." + SUBPATH,
225+
`package.json` "exports", ["node", "require"]) defined in the ESM resolver.
226+
6. RESOLVE_ESM_MATCH(MATCH)
227+
228+
LOAD_PACKAGE_SELF(X, DIR)
229+
1. Find the closest package scope SCOPE to DIR.
230+
2. If no scope was found, return.
231+
3. If the SCOPE/package.json "exports" is null or undefined, return.
232+
4. If the SCOPE/package.json "name" is not the first segment of X, return.
233+
5. let MATCH = PACKAGE_EXPORTS_RESOLVE(pathToFileURL(SCOPE),
234+
"." + X.slice("name".length), `package.json` "exports", ["node", "require"])
235+
defined in the ESM resolver.
236+
6. RESOLVE_ESM_MATCH(MATCH)
237+
238+
RESOLVE_ESM_MATCH(MATCH)
239+
1. let { RESOLVED, EXACT } = MATCH
240+
2. let RESOLVED_PATH = fileURLToPath(RESOLVED)
241+
3. If EXACT is true,
242+
a. If the file at RESOLVED_PATH exists, load RESOLVED_PATH as its extension
243+
format. STOP
244+
4. Otherwise, if EXACT is false,
245+
a. LOAD_AS_FILE(RESOLVED_PATH)
246+
b. LOAD_AS_DIRECTORY(RESOLVED_PATH)
247+
5. THROW "not found"
250248
```
251249

252250
## Caching

lib/internal/errors.js

+3-6
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ const {
2727
WeakMap,
2828
} = primordials;
2929

30-
const sep = process.platform === 'win32' ? '\\' : '/';
31-
3230
const messages = new Map();
3331
const codes = {};
3432

@@ -1106,10 +1104,9 @@ E('ERR_INVALID_OPT_VALUE', (name, value) =>
11061104
RangeError);
11071105
E('ERR_INVALID_OPT_VALUE_ENCODING',
11081106
'The value "%s" is invalid for option "encoding"', TypeError);
1109-
E('ERR_INVALID_PACKAGE_CONFIG', (path, message, hasMessage = true) => {
1110-
if (hasMessage)
1111-
return `Invalid package config ${path}${sep}package.json, ${message}`;
1112-
return `Invalid JSON in ${path} imported from ${message}`;
1107+
E('ERR_INVALID_PACKAGE_CONFIG', (path, base, message) => {
1108+
return `Invalid package config ${path}${base ? ` imported from ${base}` :
1109+
''}${message ? `. ${message}` : ''}`;
11131110
}, Error);
11141111
E('ERR_INVALID_PACKAGE_TARGET',
11151112
(pkgPath, key, target, isImport = false, base = undefined) => {

0 commit comments

Comments
 (0)