Skip to content

Commit 3743406

Browse files
JakobJingleheimerdanielleadams
authored andcommitted
esm: consolidate ESM loader hooks
doc: update ESM hook examples esm: fix unsafe primordial doc: fix ESM example linting esm: allow source of type ArrayBuffer doc: update ESM hook changelog to include resolve format esm: allow all ArrayBuffers and TypedArrays for load hook source doc: tidy code & API docs doc: convert ESM source table header from Title Case to Sentence case doc: add detailed explanation for getPackageType esm: add caveat that ESMLoader::import() must NOT be renamed esm: tidy code declaration of getFormat protocolHandlers doc: correct ESM doc link (bad conflict resolution) doc: update ESM hook limitation for CJS esm: tweak preload description doc: update ESM getPackageType() example explanation PR-URL: #37468 Reviewed-By: Antoine du Hamel <[email protected]> Reviewed-By: Guy Bedford <[email protected]> Reviewed-By: Bradley Farias <[email protected]> Reviewed-By: Geoffrey Booth <[email protected]>
1 parent 1ef2cf8 commit 3743406

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+971
-545
lines changed

doc/api/esm.md

+163-149
Large diffs are not rendered by default.

lib/internal/modules/cjs/loader.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -981,14 +981,14 @@ Module.prototype.load = function(filename) {
981981
Module._extensions[extension](this, filename);
982982
this.loaded = true;
983983

984-
const ESMLoader = asyncESM.ESMLoader;
984+
const esmLoader = asyncESM.esmLoader;
985985
// Create module entry at load time to snapshot exports correctly
986986
const exports = this.exports;
987987
// Preemptively cache
988988
if ((module?.module === undefined ||
989989
module.module.getStatus() < kEvaluated) &&
990-
!ESMLoader.cjsCache.has(this))
991-
ESMLoader.cjsCache.set(this, exports);
990+
!esmLoader.cjsCache.has(this))
991+
esmLoader.cjsCache.set(this, exports);
992992
};
993993

994994

@@ -1022,7 +1022,7 @@ function wrapSafe(filename, content, cjsModuleInstance) {
10221022
lineOffset: 0,
10231023
displayErrors: true,
10241024
importModuleDynamically: async (specifier) => {
1025-
const loader = asyncESM.ESMLoader;
1025+
const loader = asyncESM.esmLoader;
10261026
return loader.import(specifier, normalizeReferrerURL(filename));
10271027
},
10281028
});
@@ -1037,7 +1037,7 @@ function wrapSafe(filename, content, cjsModuleInstance) {
10371037
], {
10381038
filename,
10391039
importModuleDynamically(specifier) {
1040-
const loader = asyncESM.ESMLoader;
1040+
const loader = asyncESM.esmLoader;
10411041
return loader.import(specifier, normalizeReferrerURL(filename));
10421042
},
10431043
});

lib/internal/modules/esm/get_format.js

+23-13
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
'use strict';
22
const {
3+
ObjectAssign,
4+
ObjectCreate,
5+
ObjectPrototypeHasOwnProperty,
36
RegExpPrototypeExec,
4-
StringPrototypeStartsWith,
57
} = primordials;
68
const { extname } = require('path');
79
const { getOptionValue } = require('internal/options');
@@ -36,26 +38,25 @@ if (experimentalWasmModules)
3638
if (experimentalJsonModules)
3739
extensionFormatMap['.json'] = legacyExtensionFormatMap['.json'] = 'json';
3840

39-
function defaultGetFormat(url, context, defaultGetFormatUnused) {
40-
if (StringPrototypeStartsWith(url, 'node:')) {
41-
return { format: 'builtin' };
42-
}
43-
const parsed = new URL(url);
44-
if (parsed.protocol === 'data:') {
41+
const protocolHandlers = ObjectAssign(ObjectCreate(null), {
42+
'data:'(parsed) {
4543
const { 1: mime } = RegExpPrototypeExec(
4644
/^([^/]+\/[^;,]+)(?:[^,]*?)(;base64)?,/,
4745
parsed.pathname,
48-
) || [ , null ];
46+
) || [, null];
4947
const format = ({
5048
'__proto__': null,
5149
'text/javascript': 'module',
5250
'application/json': experimentalJsonModules ? 'json' : null,
5351
'application/wasm': experimentalWasmModules ? 'wasm' : null
5452
})[mime] || null;
55-
return { format };
56-
} else if (parsed.protocol === 'file:') {
53+
54+
return format;
55+
},
56+
'file:'(parsed, url) {
5757
const ext = extname(parsed.pathname);
5858
let format;
59+
5960
if (ext === '.js') {
6061
format = getPackageType(parsed.href) === 'module' ? 'module' : 'commonjs';
6162
} else {
@@ -71,9 +72,18 @@ function defaultGetFormat(url, context, defaultGetFormatUnused) {
7172
throw new ERR_UNKNOWN_FILE_EXTENSION(ext, fileURLToPath(url));
7273
}
7374
}
74-
return { format: format || null };
75-
}
76-
return { format: null };
75+
76+
return format || null;
77+
},
78+
'node:'() { return 'builtin'; },
79+
});
80+
81+
function defaultGetFormat(url, context) {
82+
const parsed = new URL(url);
83+
84+
return ObjectPrototypeHasOwnProperty(protocolHandlers, parsed.protocol) ?
85+
protocolHandlers[parsed.protocol](parsed, url) :
86+
null;
7787
}
7888

7989
module.exports = {

lib/internal/modules/esm/get_source.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,6 @@ async function defaultGetSource(url, { format } = {}, defaultGetSource) {
4040
if (policy?.manifest) {
4141
policy.manifest.assertIntegrity(parsed, source);
4242
}
43-
return { source };
43+
return source;
4444
}
4545
exports.defaultGetSource = defaultGetSource;

lib/internal/modules/esm/load.js

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
'use strict';
2+
3+
const { defaultGetFormat } = require('internal/modules/esm/get_format');
4+
const { defaultGetSource } = require('internal/modules/esm/get_source');
5+
const { translators } = require('internal/modules/esm/translators');
6+
7+
async function defaultLoad(url, context) {
8+
let {
9+
format,
10+
source,
11+
} = context;
12+
13+
if (!translators.has(format)) format = defaultGetFormat(url);
14+
15+
if (
16+
format === 'builtin' ||
17+
format === 'commonjs'
18+
) {
19+
source = null;
20+
} else if (source == null) {
21+
source = await defaultGetSource(url, { format });
22+
}
23+
24+
return {
25+
format,
26+
source,
27+
};
28+
}
29+
30+
module.exports = {
31+
defaultLoad,
32+
};

0 commit comments

Comments
 (0)