Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 5b4db8e

Browse filesBrowse files
guybedfordMylesBorins
authored andcommitted
module: conditional exports import condition
PR-URL: #30799 Reviewed-By: Jan Krems <jan.krems@gmail.com> Reviewed-By: Myles Borins <myles.borins@gmail.com>
1 parent 15d48f9 commit 5b4db8e
Copy full SHA for 5b4db8e

File tree

Expand file treeCollapse file tree

11 files changed

+67
-30
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

11 files changed

+67
-30
lines changed
Open diff view settings
Collapse file

‎doc/api/esm.md‎

Copy file name to clipboardExpand all lines: doc/api/esm.md
+28-21Lines changed: 28 additions & 21 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -335,8 +335,8 @@ Node.js and the browser can be written:
335335
"main": "./index.js",
336336
"exports": {
337337
"./feature": {
338-
"browser": "./feature-browser.js",
339-
"default": "./feature-default.js"
338+
"import": "./feature-default.js",
339+
"browser": "./feature-browser.js"
340340
}
341341
}
342342
}
@@ -347,16 +347,24 @@ will be used as the final fallback.
347347

348348
The conditions supported in Node.js are matched in the following order:
349349

350-
1. `"require"` - matched when the package is loaded via `require()`.
351-
_This is currently only supported behind the
352-
`--experimental-conditional-exports` flag._
353-
2. `"node"` - matched for any Node.js environment. Can be a CommonJS or ES
350+
1. `"node"` - matched for any Node.js environment. Can be a CommonJS or ES
354351
module file. _This is currently only supported behind the
355-
`--experimental-conditional-exports` flag._
356-
3. `"default"` - the generic fallback that will always match if no other
352+
`--experimental-conditional-exports` flag._
353+
2. `"require"` - matched when the package is loaded via `require()`.
354+
_This is currently only supported behind the
355+
`--experimental-conditional-exports` flag._
356+
3. `"import"` - matched when the package is loaded via `import` or
357+
`import()`. Can be any module format, this field does not set the type
358+
interpretation. _This is currently only supported behind the
359+
`--experimental-conditional-exports` flag._
360+
4. `"default"` - the generic fallback that will always match if no other
357361
more specific condition is matched first. Can be a CommonJS or ES module
358362
file.
359363

364+
> Setting any of the above flagged conditions for a published package is not
365+
> recommended until they are unflagged to avoid breaking changes to packages in
366+
> future.
367+
360368
Using the `"require"` condition it is possible to define a package that will
361369
have a different exported value for CommonJS and ES modules, which can be a
362370
hazard in that it can result in having two separate instances of the same
@@ -400,8 +408,8 @@ from exports subpaths.
400408
{
401409
"exports": {
402410
".": {
403-
"require": "./main.cjs",
404-
"default": "./main.js"
411+
"import": "./main.js",
412+
"require": "./main.cjs"
405413
}
406414
}
407415
}
@@ -413,8 +421,8 @@ can be written:
413421
```js
414422
{
415423
"exports": {
416-
"require": "./main.cjs",
417-
"default": "./main.js"
424+
"import": "./main.js",
425+
"require": "./main.cjs"
418426
}
419427
}
420428
```
@@ -428,8 +436,8 @@ thrown:
428436
// Throws on resolution!
429437
"exports": {
430438
"./feature": "./lib/feature.js",
431-
"require": "./main.cjs",
432-
"default": "./main.js"
439+
"import": "./main.js",
440+
"require": "./main.cjs"
433441
}
434442
}
435443
```
@@ -514,9 +522,8 @@ ES module wrapper is used for `import` and the CommonJS entry point for
514522
`require`.
515523

516524
> Note: While `--experimental-conditional-exports` is flagged, a package
517-
> using this pattern will throw when loaded via `require()` in modern
518-
> Node.js, unless package consumers use the `--experimental-conditional-exports`
519-
> flag.
525+
> using this pattern will throw when loaded unless package consumers use the
526+
> `--experimental-conditional-exports` flag.
520527
521528
<!-- eslint-skip -->
522529
```js
@@ -526,7 +533,7 @@ ES module wrapper is used for `import` and the CommonJS entry point for
526533
"main": "./index.cjs",
527534
"exports": {
528535
"require": "./index.cjs",
529-
"default": "./wrapper.mjs"
536+
"import": "./wrapper.mjs"
530537
}
531538
}
532539
```
@@ -611,8 +618,8 @@ CommonJS and ES module entry points directly (requires
611618
"type": "module",
612619
"main": "./index.cjs",
613620
"exports": {
614-
"require": "./index.cjs",
615-
"default": "./index.mjs"
621+
"import": "./index.mjs",
622+
"require": "./index.cjs"
616623
}
617624
}
618625
```
@@ -1152,7 +1159,7 @@ of these top-level routines unless stated otherwise.
11521159
_isMain_ is **true** when resolving the Node.js application entry point.
11531160
11541161
_defaultEnv_ is the conditional environment name priority array,
1155-
`["node", "default"]`.
1162+
`["node", "import"]`.
11561163
11571164
<details>
11581165
<summary>Resolver algorithm specification</summary>
Collapse file

‎doc/api/modules.md‎

Copy file name to clipboardExpand all lines: doc/api/modules.md
+2-1Lines changed: 2 additions & 1 deletion
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,8 @@ RESOLVE_BARE_SPECIFIER(DIR, X)
241241
g. If no such key can be found, throw "not found".
242242
h. let RESOLVED_URL =
243243
PACKAGE_EXPORTS_TARGET_RESOLVE(pathToFileURL(DIR/name), exports[key],
244-
subpath.slice(key.length)), as defined in the ESM resolver.
244+
subpath.slice(key.length), ["node", "require"]), as defined in the ESM
245+
resolver.
245246
i. return fileURLToPath(RESOLVED_URL)
246247
3. return DIR/X
247248
```
Collapse file

‎lib/internal/modules/cjs/loader.js‎

Copy file name to clipboardExpand all lines: lib/internal/modules/cjs/loader.js
+4-4Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -574,9 +574,9 @@ function resolveExportsTarget(pkgPath, target, subpath, basePath, mappingKey) {
574574
}
575575
} else if (typeof target === 'object' && target !== null) {
576576
if (experimentalConditionalExports &&
577-
ObjectPrototype.hasOwnProperty(target, 'require')) {
577+
ObjectPrototype.hasOwnProperty(target, 'node')) {
578578
try {
579-
const result = resolveExportsTarget(pkgPath, target.require, subpath,
579+
const result = resolveExportsTarget(pkgPath, target.node, subpath,
580580
basePath, mappingKey);
581581
emitExperimentalWarning('Conditional exports');
582582
return result;
@@ -585,9 +585,9 @@ function resolveExportsTarget(pkgPath, target, subpath, basePath, mappingKey) {
585585
}
586586
}
587587
if (experimentalConditionalExports &&
588-
ObjectPrototype.hasOwnProperty(target, 'node')) {
588+
ObjectPrototype.hasOwnProperty(target, 'require')) {
589589
try {
590-
const result = resolveExportsTarget(pkgPath, target.node, subpath,
590+
const result = resolveExportsTarget(pkgPath, target.require, subpath,
591591
basePath, mappingKey);
592592
emitExperimentalWarning('Conditional exports');
593593
return result;
Collapse file

‎src/env.h‎

Copy file name to clipboardExpand all lines: src/env.h
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ constexpr size_t kFsStatsBufferLength =
255255
V(hostmaster_string, "hostmaster") \
256256
V(http_1_1_string, "http/1.1") \
257257
V(ignore_string, "ignore") \
258+
V(import_string, "import") \
258259
V(infoaccess_string, "infoAccess") \
259260
V(inherit_string, "inherit") \
260261
V(input_string, "input") \
Collapse file

‎src/module_wrap.cc‎

Copy file name to clipboardExpand all lines: src/module_wrap.cc
+11Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -967,6 +967,17 @@ Maybe<URL> ResolveExportsTarget(Environment* env,
967967
return resolved;
968968
}
969969
}
970+
if (env->options()->experimental_conditional_exports &&
971+
target_obj->HasOwnProperty(context, env->import_string()).FromJust()) {
972+
matched = true;
973+
conditionalTarget =
974+
target_obj->Get(context, env->import_string()).ToLocalChecked();
975+
Maybe<URL> resolved = ResolveExportsTarget(env, pjson_url,
976+
conditionalTarget, subpath, pkg_subpath, base, false);
977+
if (!resolved.IsNothing()) {
978+
return resolved;
979+
}
980+
}
970981
if (target_obj->HasOwnProperty(context, env->default_string()).FromJust()) {
971982
matched = true;
972983
conditionalTarget =
Collapse file

‎test/es-module/test-esm-exports.mjs‎

Copy file name to clipboardExpand all lines: test/es-module/test-esm-exports.mjs
+11-2Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import fromInside from '../fixtures/node_modules/pkgexports/lib/hole.js';
3232
['pkgexports-sugar', { default: 'main' }],
3333
// Conditional object exports sugar
3434
['pkgexports-sugar2', isRequire ? { default: 'not-exported' } :
35-
{ default: 'main' }]
35+
{ default: 'main' }],
3636
]);
3737

3838
for (const [validSpecifier, expected] of validSpecifiers) {
@@ -52,7 +52,7 @@ import fromInside from '../fixtures/node_modules/pkgexports/lib/hole.js';
5252
['pkgexports-number/hidden.js', './hidden.js'],
5353
// Sugar cases still encapsulate
5454
['pkgexports-sugar/not-exported.js', './not-exported.js'],
55-
['pkgexports-sugar2/not-exported.js', './not-exported.js']
55+
['pkgexports-sugar2/not-exported.js', './not-exported.js'],
5656
]);
5757

5858
const invalidExports = new Map([
@@ -98,6 +98,15 @@ import fromInside from '../fixtures/node_modules/pkgexports/lib/hole.js';
9898
}));
9999
}
100100

101+
// Conditional export, even with no match, should still be used instead
102+
// of falling back to main
103+
if (isRequire) {
104+
loadFixture('pkgexports-main').catch(mustCall((err) => {
105+
strictEqual(err.code, 'MODULE_NOT_FOUND');
106+
assertStartsWith(err.message, 'No valid export');
107+
}));
108+
}
109+
101110
// Covering out bases - not a file is still not a file after dir mapping.
102111
loadFixture('pkgexports/sub/not-a-file.js').catch(mustCall((err) => {
103112
strictEqual(err.code, (isRequire ? '' : 'ERR_') + 'MODULE_NOT_FOUND');
Collapse file

‎test/fixtures/node_modules/pkgexports-main/main.cjs‎

Copy file name to clipboardExpand all lines: test/fixtures/node_modules/pkgexports-main/main.cjs
+1Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Collapse file

‎test/fixtures/node_modules/pkgexports-main/module.mjs‎

Copy file name to clipboardExpand all lines: test/fixtures/node_modules/pkgexports-main/module.mjs
+1Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Collapse file

‎test/fixtures/node_modules/pkgexports-main/package.json‎

Copy file name to clipboardExpand all lines: test/fixtures/node_modules/pkgexports-main/package.json
+6Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Collapse file

‎test/fixtures/node_modules/pkgexports-sugar-fail/package.json‎

Copy file name to clipboardExpand all lines: test/fixtures/node_modules/pkgexports-sugar-fail/package.json
+1-1Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.