Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit b95bb38

Browse files
bfarias-godaddyMylesBorins
authored andcommittedJan 12, 2020
esm: empty ext from pkg type/main doesnt affect format
This ensures files with unknown extensions like foo.bar are not loaded as CJS/ESM when imported as a main entry point and makes sure that those files would maintain the same format even if loaded after the main entrypoint. PR-URL: #31021 Reviewed-By: Guy Bedford <[email protected]>
1 parent a91b735 commit b95bb38

File tree

6 files changed

+95
-10
lines changed

6 files changed

+95
-10
lines changed
 

‎doc/api/esm.md

+6-8
Original file line numberDiff line numberDiff line change
@@ -1160,15 +1160,13 @@ updates.
11601160
In the following algorithms, all subroutine errors are propagated as errors
11611161
of these top-level routines unless stated otherwise.
11621162
1163-
_isMain_ is **true** when resolving the Node.js application entry point.
1164-
11651163
_defaultEnv_ is the conditional environment name priority array,
11661164
`["node", "import"]`.
11671165
11681166
<details>
11691167
<summary>Resolver algorithm specification</summary>
11701168
1171-
**ESM_RESOLVE**(_specifier_, _parentURL_, _isMain_)
1169+
**ESM_RESOLVE**(_specifier_, _parentURL_)
11721170
11731171
> 1. Let _resolvedURL_ be **undefined**.
11741172
> 1. If _specifier_ is a valid URL, then
@@ -1189,7 +1187,7 @@ _defaultEnv_ is the conditional environment name priority array,
11891187
> 1. If the file at _resolvedURL_ does not exist, then
11901188
> 1. Throw a _Module Not Found_ error.
11911189
> 1. Set _resolvedURL_ to the real path of _resolvedURL_.
1192-
> 1. Let _format_ be the result of **ESM_FORMAT**(_resolvedURL_, _isMain_).
1190+
> 1. Let _format_ be the result of **ESM_FORMAT**(_resolvedURL_).
11931191
> 1. Load _resolvedURL_ as module format, _format_.
11941192
11951193
**PACKAGE_RESOLVE**(_packageSpecifier_, _parentURL_)
@@ -1340,20 +1338,20 @@ _defaultEnv_ is the conditional environment name priority array,
13401338
> 1. Return _resolved_.
13411339
> 1. Throw a _Module Not Found_ error.
13421340
1343-
**ESM_FORMAT**(_url_, _isMain_)
1341+
**ESM_FORMAT**(_url_)
13441342
1345-
> 1. Assert: _url_ corresponds to an existing file.
1343+
> 1. Assert: _url_ corresponds to an existing file pathname.
13461344
> 1. Let _pjson_ be the result of **READ_PACKAGE_SCOPE**(_url_).
13471345
> 1. If _url_ ends in _".mjs"_, then
13481346
> 1. Return _"module"_.
13491347
> 1. If _url_ ends in _".cjs"_, then
13501348
> 1. Return _"commonjs"_.
13511349
> 1. If _pjson?.type_ exists and is _"module"_, then
1352-
> 1. If _isMain_ is **true** or _url_ ends in _".js"_, then
1350+
> 1. If _url_ ends in _".js"_ or lacks a file extension, then
13531351
> 1. Return _"module"_.
13541352
> 1. Throw an _Unsupported File Extension_ error.
13551353
> 1. Otherwise,
1356-
> 1. If _isMain_ is **true**, then
1354+
> 1. If _url_ lacks a file extension, then
13571355
> 1. Return _"commonjs"_.
13581356
> 1. Throw an _Unsupported File Extension_ error.
13591357

‎lib/internal/modules/esm/default_resolve.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,12 @@ function resolve(specifier, parentURL) {
104104
}
105105

106106
const ext = extname(url.pathname);
107-
let format = extensionFormatMap[ext];
108-
if (ext === '.js' || (!format && isMain))
107+
let format;
108+
if (ext === '.js' || ext === '') {
109109
format = getPackageType(url.href) === TYPE_MODULE ? 'module' : 'commonjs';
110+
} else {
111+
format = extensionFormatMap[ext];
112+
}
110113
if (!format) {
111114
if (experimentalSpeciferResolution === 'node') {
112115
process.emitWarning(
+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const fixtures = require('../common/fixtures');
5+
const { spawn } = require('child_process');
6+
const assert = require('assert');
7+
8+
{
9+
const entry = fixtures.path(
10+
'/es-modules/package-type-module/extension.unknown'
11+
);
12+
const child = spawn(process.execPath, ['--experimental-modules', entry]);
13+
let stdout = '';
14+
let stderr = '';
15+
child.stderr.setEncoding('utf8');
16+
child.stdout.setEncoding('utf8');
17+
child.stdout.on('data', (data) => {
18+
stdout += data;
19+
});
20+
child.stderr.on('data', (data) => {
21+
stderr += data;
22+
});
23+
child.on('close', common.mustCall((code, signal) => {
24+
assert.strictEqual(code, 1);
25+
assert.strictEqual(signal, null);
26+
assert.strictEqual(stdout, '');
27+
assert.ok(stderr.indexOf('ERR_UNKNOWN_FILE_EXTENSION') !== -1);
28+
}));
29+
}
30+
{
31+
const entry = fixtures.path(
32+
'/es-modules/package-type-module/imports-unknownext.mjs'
33+
);
34+
const child = spawn(process.execPath, ['--experimental-modules', entry]);
35+
let stdout = '';
36+
let stderr = '';
37+
child.stderr.setEncoding('utf8');
38+
child.stdout.setEncoding('utf8');
39+
child.stdout.on('data', (data) => {
40+
stdout += data;
41+
});
42+
child.stderr.on('data', (data) => {
43+
stderr += data;
44+
});
45+
child.on('close', common.mustCall((code, signal) => {
46+
assert.strictEqual(code, 1);
47+
assert.strictEqual(signal, null);
48+
assert.strictEqual(stdout, '');
49+
assert.ok(stderr.indexOf('ERR_UNKNOWN_FILE_EXTENSION') !== -1);
50+
}));
51+
}
52+
{
53+
const entry = fixtures.path('/es-modules/package-type-module/noext-esm');
54+
const child = spawn(process.execPath, ['--experimental-modules', entry]);
55+
let stdout = '';
56+
child.stdout.setEncoding('utf8');
57+
child.stdout.on('data', (data) => {
58+
stdout += data;
59+
});
60+
child.on('close', common.mustCall((code, signal) => {
61+
assert.strictEqual(code, 0);
62+
assert.strictEqual(signal, null);
63+
assert.strictEqual(stdout, 'executed\n');
64+
}));
65+
}
66+
{
67+
const entry = fixtures.path(
68+
'/es-modules/package-type-module/imports-noext.mjs'
69+
);
70+
const child = spawn(process.execPath, ['--experimental-modules', entry]);
71+
let stdout = '';
72+
child.stdout.setEncoding('utf8');
73+
child.stdout.on('data', (data) => {
74+
stdout += data;
75+
});
76+
child.on('close', common.mustCall((code, signal) => {
77+
assert.strictEqual(code, 0);
78+
assert.strictEqual(signal, null);
79+
assert.strictEqual(stdout, 'executed\n');
80+
}));
81+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
throw new Error('NO, NEVER');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import './noext-esm';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import './extension.unknown';

0 commit comments

Comments
 (0)
Please sign in to comment.