mirror of
https://github.com/zebrajr/node.git
synced 2026-01-15 12:15:26 +00:00
Revert "esm: convert resolve hook to synchronous"
This reverts commit 90b634a5a5.
PR-URL: https://github.com/nodejs/node/pull/43526
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
Reviewed-By: Guy Bedford <guybedford@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Mohammed Keyvanzadeh <mohammadkeyvanzade94@gmail.com>
This commit is contained in:
@@ -324,9 +324,6 @@ added:
|
||||
- v13.9.0
|
||||
- v12.16.2
|
||||
changes:
|
||||
- version: REPLACEME
|
||||
pr-url: https://github.com/nodejs/node/pull/43363
|
||||
description: Convert from asynchronous to synchronous.
|
||||
- version:
|
||||
- v16.2.0
|
||||
- v14.18.0
|
||||
@@ -342,19 +339,15 @@ command flag enabled.
|
||||
* `specifier` {string} The module specifier to resolve relative to `parent`.
|
||||
* `parent` {string|URL} The absolute parent module URL to resolve from. If none
|
||||
is specified, the value of `import.meta.url` is used as the default.
|
||||
* Returns: {string}
|
||||
* Returns: {Promise}
|
||||
|
||||
Provides a module-relative resolution function scoped to each module, returning
|
||||
the URL string. In alignment with browser behavior, this now returns
|
||||
synchronously.
|
||||
|
||||
> **Caveat** This can result in synchronous file-system operations, which
|
||||
> can impact performance similarly to `require.resolve`.
|
||||
the URL string.
|
||||
|
||||
<!-- eslint-skip -->
|
||||
|
||||
```js
|
||||
const dependencyAsset = import.meta.resolve('component-lib/asset.css');
|
||||
const dependencyAsset = await import.meta.resolve('component-lib/asset.css');
|
||||
```
|
||||
|
||||
`import.meta.resolve` also accepts a second argument which is the parent module
|
||||
@@ -363,11 +356,11 @@ from which to resolve from:
|
||||
<!-- eslint-skip -->
|
||||
|
||||
```js
|
||||
import.meta.resolve('./dep', import.meta.url);
|
||||
await import.meta.resolve('./dep', import.meta.url);
|
||||
```
|
||||
|
||||
This function is synchronous because the ES module resolver in Node.js is
|
||||
synchronous.
|
||||
This function is asynchronous because the ES module resolver in Node.js is
|
||||
allowed to be asynchronous.
|
||||
|
||||
## Interoperability with CommonJS
|
||||
|
||||
@@ -738,9 +731,6 @@ prevent unintentional breaks in the chain.
|
||||
|
||||
<!-- YAML
|
||||
changes:
|
||||
- version: REPLACEME
|
||||
pr-url: https://github.com/nodejs/node/pull/43363
|
||||
description: Convert hook from asynchronous to synchronous.
|
||||
- version: REPLACEME
|
||||
pr-url: https://github.com/nodejs/node/pull/42623
|
||||
description: Add support for chaining resolve hooks. Each hook must either
|
||||
@@ -774,9 +764,6 @@ changes:
|
||||
terminate the chain of `resolve` hooks. **Default:** `false`
|
||||
* `url` {string} The absolute URL to which this input resolves
|
||||
|
||||
> **Caveat** A resolve hook can contain synchronous file-system operations
|
||||
> (as `defaultResolveHook()` does), which can impact performance.
|
||||
|
||||
The `resolve` hook chain is responsible for resolving file URL for a given
|
||||
module specifier and parent URL, and optionally its format (such as `'module'`)
|
||||
as a hint to the `load` hook. If a format is specified, the `load` hook is
|
||||
@@ -803,7 +790,7 @@ Node.js module specifier resolution behavior_ when calling `defaultResolve`, the
|
||||
`context.conditions` array originally passed into the `resolve` hook.
|
||||
|
||||
```js
|
||||
export function resolve(specifier, context, nextResolve) {
|
||||
export async function resolve(specifier, context, nextResolve) {
|
||||
const { parentURL = null } = context;
|
||||
|
||||
if (Math.random() > 0.5) { // Some condition.
|
||||
@@ -1102,7 +1089,7 @@ const baseURL = pathToFileURL(`${cwd()}/`).href;
|
||||
// CoffeeScript files end in .coffee, .litcoffee, or .coffee.md.
|
||||
const extensionsRegex = /\.coffee$|\.litcoffee$|\.coffee\.md$/;
|
||||
|
||||
export function resolve(specifier, context, nextResolve) {
|
||||
export async function resolve(specifier, context, nextResolve) {
|
||||
if (extensionsRegex.test(specifier)) {
|
||||
const { parentURL = baseURL } = context;
|
||||
|
||||
|
||||
@@ -3,23 +3,21 @@
|
||||
const { getOptionValue } = require('internal/options');
|
||||
const experimentalImportMetaResolve =
|
||||
getOptionValue('--experimental-import-meta-resolve');
|
||||
const {
|
||||
PromisePrototypeThen,
|
||||
PromiseReject,
|
||||
} = primordials;
|
||||
const asyncESM = require('internal/process/esm_loader');
|
||||
|
||||
function createImportMetaResolve(defaultParentUrl) {
|
||||
return function resolve(specifier, parentUrl = defaultParentUrl) {
|
||||
let url;
|
||||
|
||||
try {
|
||||
({ url } = asyncESM.esmLoader.resolve(specifier, parentUrl));
|
||||
} catch (error) {
|
||||
if (error.code === 'ERR_UNSUPPORTED_DIR_IMPORT') {
|
||||
({ url } = error);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
return url;
|
||||
return async function resolve(specifier, parentUrl = defaultParentUrl) {
|
||||
return PromisePrototypeThen(
|
||||
asyncESM.esmLoader.resolve(specifier, parentUrl),
|
||||
({ url }) => url,
|
||||
(error) => (
|
||||
error.code === 'ERR_UNSUPPORTED_DIR_IMPORT' ?
|
||||
error.url : PromiseReject(error))
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -15,8 +15,6 @@ const {
|
||||
ObjectDefineProperty,
|
||||
ObjectSetPrototypeOf,
|
||||
PromiseAll,
|
||||
PromiseResolve,
|
||||
PromisePrototypeThen,
|
||||
ReflectApply,
|
||||
RegExpPrototypeExec,
|
||||
SafeArrayIterator,
|
||||
@@ -111,14 +109,12 @@ let emittedSpecifierResolutionWarning = false;
|
||||
* position in the hook chain.
|
||||
* @param {string} meta.hookName The kind of hook the chain is (ex 'resolve')
|
||||
* @param {boolean} meta.shortCircuited Whether a hook signaled a short-circuit.
|
||||
* @param {object} validators A wrapper function
|
||||
* @param {(hookErrIdentifier, hookArgs) => void} validate A wrapper function
|
||||
* containing all validation of a custom loader hook's intermediary output. Any
|
||||
* validation within MUST throw.
|
||||
* @param {(hookErrIdentifier, hookArgs) => void} validators.validateArgs
|
||||
* @param {(hookErrIdentifier, output) => void} validators.validateOutput
|
||||
* @returns {function next<HookName>(...hookArgs)} The next hook in the chain.
|
||||
*/
|
||||
function nextHookFactory(chain, meta, { validateArgs, validateOutput }) {
|
||||
function nextHookFactory(chain, meta, validate) {
|
||||
// First, prepare the current
|
||||
const { hookName } = meta;
|
||||
const {
|
||||
@@ -141,7 +137,7 @@ function nextHookFactory(chain, meta, { validateArgs, validateOutput }) {
|
||||
// factory generates the next link in the chain.
|
||||
meta.hookIndex--;
|
||||
|
||||
nextNextHook = nextHookFactory(chain, meta, { validateArgs, validateOutput });
|
||||
nextNextHook = nextHookFactory(chain, meta, validate);
|
||||
} else {
|
||||
// eslint-disable-next-line func-name-matching
|
||||
nextNextHook = function chainAdvancedTooFar() {
|
||||
@@ -152,36 +148,21 @@ function nextHookFactory(chain, meta, { validateArgs, validateOutput }) {
|
||||
}
|
||||
|
||||
return ObjectDefineProperty(
|
||||
(...args) => {
|
||||
async (...args) => {
|
||||
// Update only when hook is invoked to avoid fingering the wrong filePath
|
||||
meta.hookErrIdentifier = `${hookFilePath} '${hookName}'`;
|
||||
|
||||
validateArgs(`${meta.hookErrIdentifier} hook's ${nextHookName}()`, args);
|
||||
|
||||
const outputErrIdentifier = `${chain[generatedHookIndex].url} '${hookName}' hook's ${nextHookName}()`;
|
||||
validate(`${meta.hookErrIdentifier} hook's ${nextHookName}()`, args);
|
||||
|
||||
// Set when next<HookName> is actually called, not just generated.
|
||||
if (generatedHookIndex === 0) { meta.chainFinished = true; }
|
||||
|
||||
ArrayPrototypePush(args, nextNextHook);
|
||||
const output = ReflectApply(hook, undefined, args);
|
||||
const output = await ReflectApply(hook, undefined, args);
|
||||
|
||||
validateOutput(outputErrIdentifier, output);
|
||||
if (output?.shortCircuit === true) { meta.shortCircuited = true; }
|
||||
return output;
|
||||
|
||||
function checkShortCircuited(output) {
|
||||
if (output?.shortCircuit === true) { meta.shortCircuited = true; }
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
if (meta.isChainAsync) {
|
||||
return PromisePrototypeThen(
|
||||
PromiseResolve(output),
|
||||
checkShortCircuited,
|
||||
);
|
||||
}
|
||||
|
||||
return checkShortCircuited(output);
|
||||
},
|
||||
'name',
|
||||
{ __proto__: null, value: nextHookName },
|
||||
@@ -440,11 +421,8 @@ class ESMLoader {
|
||||
);
|
||||
}
|
||||
|
||||
const { format, url } = this.resolve(
|
||||
specifier,
|
||||
parentURL,
|
||||
importAssertionsForResolve,
|
||||
);
|
||||
const { format, url } =
|
||||
await this.resolve(specifier, parentURL, importAssertionsForResolve);
|
||||
|
||||
let job = this.moduleMap.get(url, importAssertions.type);
|
||||
|
||||
@@ -579,11 +557,10 @@ class ESMLoader {
|
||||
hookErrIdentifier: '',
|
||||
hookIndex: chain.length - 1,
|
||||
hookName: 'load',
|
||||
isChainAsync: true,
|
||||
shortCircuited: false,
|
||||
};
|
||||
|
||||
const validateArgs = (hookErrIdentifier, { 0: nextUrl, 1: ctx }) => {
|
||||
const validate = (hookErrIdentifier, { 0: nextUrl, 1: ctx }) => {
|
||||
if (typeof nextUrl !== 'string') {
|
||||
// non-strings can be coerced to a url string
|
||||
// validateString() throws a less-specific error
|
||||
@@ -609,22 +586,19 @@ class ESMLoader {
|
||||
|
||||
validateObject(ctx, `${hookErrIdentifier} context`);
|
||||
};
|
||||
const validateOutput = (hookErrIdentifier, output) => {
|
||||
if (typeof output !== 'object') { // [2]
|
||||
throw new ERR_INVALID_RETURN_VALUE(
|
||||
'an object',
|
||||
hookErrIdentifier,
|
||||
output,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const nextLoad = nextHookFactory(chain, meta, { validateArgs, validateOutput });
|
||||
const nextLoad = nextHookFactory(chain, meta, validate);
|
||||
|
||||
const loaded = await nextLoad(url, context);
|
||||
const { hookErrIdentifier } = meta; // Retrieve the value after all settled
|
||||
|
||||
validateOutput(hookErrIdentifier, loaded);
|
||||
if (typeof loaded !== 'object') { // [2]
|
||||
throw new ERR_INVALID_RETURN_VALUE(
|
||||
'an object',
|
||||
hookErrIdentifier,
|
||||
loaded,
|
||||
);
|
||||
}
|
||||
|
||||
if (loaded?.shortCircuit === true) { meta.shortCircuited = true; }
|
||||
|
||||
@@ -804,7 +778,7 @@ class ESMLoader {
|
||||
* statement or expression.
|
||||
* @returns {{ format: string, url: URL['href'] }}
|
||||
*/
|
||||
resolve(
|
||||
async resolve(
|
||||
originalSpecifier,
|
||||
parentURL,
|
||||
importAssertions = ObjectCreate(null)
|
||||
@@ -828,16 +802,16 @@ class ESMLoader {
|
||||
hookErrIdentifier: '',
|
||||
hookIndex: chain.length - 1,
|
||||
hookName: 'resolve',
|
||||
isChainAsync: false,
|
||||
shortCircuited: false,
|
||||
};
|
||||
|
||||
const context = {
|
||||
conditions: DEFAULT_CONDITIONS,
|
||||
importAssertions,
|
||||
parentURL,
|
||||
};
|
||||
const validate = (hookErrIdentifier, { 0: suppliedSpecifier, 1: ctx }) => {
|
||||
|
||||
const validateArgs = (hookErrIdentifier, { 0: suppliedSpecifier, 1: ctx }) => {
|
||||
validateString(
|
||||
suppliedSpecifier,
|
||||
`${hookErrIdentifier} specifier`,
|
||||
@@ -845,26 +819,19 @@ class ESMLoader {
|
||||
|
||||
validateObject(ctx, `${hookErrIdentifier} context`);
|
||||
};
|
||||
const validateOutput = (hookErrIdentifier, output) => {
|
||||
if (
|
||||
typeof output !== 'object' || // [2]
|
||||
output === null ||
|
||||
(output.url == null && typeof output.then === 'function')
|
||||
) {
|
||||
throw new ERR_INVALID_RETURN_VALUE(
|
||||
'an object',
|
||||
hookErrIdentifier,
|
||||
output,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const nextResolve = nextHookFactory(chain, meta, { validateArgs, validateOutput });
|
||||
const nextResolve = nextHookFactory(chain, meta, validate);
|
||||
|
||||
const resolution = nextResolve(originalSpecifier, context);
|
||||
const resolution = await nextResolve(originalSpecifier, context);
|
||||
const { hookErrIdentifier } = meta; // Retrieve the value after all settled
|
||||
|
||||
validateOutput(hookErrIdentifier, resolution);
|
||||
if (typeof resolution !== 'object') { // [2]
|
||||
throw new ERR_INVALID_RETURN_VALUE(
|
||||
'an object',
|
||||
hookErrIdentifier,
|
||||
resolution,
|
||||
);
|
||||
}
|
||||
|
||||
if (resolution?.shortCircuit === true) { meta.shortCircuited = true; }
|
||||
|
||||
|
||||
@@ -1081,7 +1081,7 @@ function throwIfUnsupportedURLScheme(parsed, experimentalNetworkImports) {
|
||||
}
|
||||
}
|
||||
|
||||
function defaultResolve(specifier, context = {}) {
|
||||
async function defaultResolve(specifier, context = {}) {
|
||||
let { parentURL, conditions } = context;
|
||||
if (parentURL && policy?.manifest) {
|
||||
const redirects = policy.manifest.getDependencyMapper(parentURL);
|
||||
@@ -1227,11 +1227,11 @@ const {
|
||||
|
||||
if (policy) {
|
||||
const $defaultResolve = defaultResolve;
|
||||
module.exports.defaultResolve = function defaultResolve(
|
||||
module.exports.defaultResolve = async function defaultResolve(
|
||||
specifier,
|
||||
context
|
||||
) {
|
||||
const ret = $defaultResolve(specifier, context);
|
||||
const ret = await $defaultResolve(specifier, context, $defaultResolve);
|
||||
// This is a preflight check to avoid data exfiltration by query params etc.
|
||||
policy.manifest.mightAllow(ret.url, () =>
|
||||
new ERR_MANIFEST_DEPENDENCY_MISSING(
|
||||
|
||||
@@ -1,49 +1,37 @@
|
||||
// Flags: --experimental-import-meta-resolve
|
||||
import '../common/index.mjs';
|
||||
import { mustCall } from '../common/index.mjs';
|
||||
import assert from 'assert';
|
||||
|
||||
const dirname = import.meta.url.slice(0, import.meta.url.lastIndexOf('/') + 1);
|
||||
const fixtures = dirname.slice(0, dirname.lastIndexOf('/', dirname.length - 2) +
|
||||
1) + 'fixtures/';
|
||||
|
||||
assert.strictEqual(
|
||||
import.meta.resolve('./test-esm-import-meta.mjs'),
|
||||
dirname + 'test-esm-import-meta.mjs',
|
||||
);
|
||||
|
||||
assert.throws(
|
||||
() => import.meta.resolve('./notfound.mjs'),
|
||||
{ code: 'ERR_MODULE_NOT_FOUND' },
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
import.meta.resolve('../fixtures/empty-with-bom.txt'),
|
||||
fixtures + 'empty-with-bom.txt',
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
import.meta.resolve('../fixtures/'),
|
||||
fixtures,
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
import.meta.resolve('../fixtures/', import.meta.url),
|
||||
fixtures,
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
import.meta.resolve('../fixtures/', new URL(import.meta.url)),
|
||||
fixtures,
|
||||
);
|
||||
|
||||
[[], {}, Symbol(), 0, 1, 1n, 1.1, () => {}, true, false].forEach((arg) => {
|
||||
assert.throws(
|
||||
() => import.meta.resolve('../fixtures/', arg),
|
||||
{ code: 'ERR_INVALID_ARG_TYPE' },
|
||||
(async () => {
|
||||
assert.strictEqual(await import.meta.resolve('./test-esm-import-meta.mjs'),
|
||||
dirname + 'test-esm-import-meta.mjs');
|
||||
try {
|
||||
await import.meta.resolve('./notfound.mjs');
|
||||
assert.fail();
|
||||
} catch (e) {
|
||||
assert.strictEqual(e.code, 'ERR_MODULE_NOT_FOUND');
|
||||
}
|
||||
assert.strictEqual(
|
||||
await import.meta.resolve('../fixtures/empty-with-bom.txt'),
|
||||
fixtures + 'empty-with-bom.txt');
|
||||
assert.strictEqual(await import.meta.resolve('../fixtures/'), fixtures);
|
||||
assert.strictEqual(
|
||||
await import.meta.resolve('../fixtures/', import.meta.url),
|
||||
fixtures);
|
||||
assert.strictEqual(
|
||||
await import.meta.resolve('../fixtures/', new URL(import.meta.url)),
|
||||
fixtures);
|
||||
await Promise.all(
|
||||
[[], {}, Symbol(), 0, 1, 1n, 1.1, () => {}, true, false].map((arg) =>
|
||||
assert.rejects(import.meta.resolve('../fixtures/', arg), {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
})
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
assert.strictEqual(
|
||||
import.meta.resolve('baz/', fixtures),
|
||||
fixtures + 'node_modules/baz/',
|
||||
);
|
||||
assert.strictEqual(await import.meta.resolve('baz/', fixtures),
|
||||
fixtures + 'node_modules/baz/');
|
||||
})().then(mustCall());
|
||||
|
||||
@@ -165,32 +165,6 @@ const commonArgs = [
|
||||
assert.strictEqual(status, 0);
|
||||
}
|
||||
|
||||
{ // Verify error thrown for an async resolve hook
|
||||
const { status, stderr } = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-42.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-async-fn.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
|
||||
assert.match(stderr, /ERR_INVALID_RETURN_VALUE/);
|
||||
assert.match(stderr, /Promise/);
|
||||
assert.match(stderr, /loader-resolve-async-fn\.mjs/);
|
||||
assert.match(stderr, /'resolve'/);
|
||||
// Cannot expect stdout to be empty because detecting whether a hook has
|
||||
// returned a promise requires the hook to be executed
|
||||
assert.strictEqual(status, 1);
|
||||
}
|
||||
|
||||
{ // Verify error thrown for incomplete resolve chain, citing errant loader & hook
|
||||
const { status, stderr, stdout } = spawnSync(
|
||||
process.execPath,
|
||||
|
||||
@@ -10,8 +10,8 @@ const {
|
||||
defaultResolve: resolve
|
||||
} = require('internal/modules/esm/resolve');
|
||||
|
||||
assert.throws(
|
||||
() => resolve('target'),
|
||||
assert.rejects(
|
||||
resolve('target'),
|
||||
{
|
||||
code: 'ERR_MODULE_NOT_FOUND',
|
||||
name: 'Error',
|
||||
|
||||
@@ -41,10 +41,10 @@ try {
|
||||
[ '/es-modules/package-type-commonjs/index.js', 'commonjs' ],
|
||||
[ '/es-modules/package-without-type/index.js', 'commonjs' ],
|
||||
[ '/es-modules/package-without-pjson/index.js', 'commonjs' ],
|
||||
].forEach((testVariant) => {
|
||||
].forEach(async (testVariant) => {
|
||||
const [ testScript, expectedType ] = testVariant;
|
||||
const resolvedPath = path.resolve(fixtures.path(testScript));
|
||||
const resolveResult = resolve(url.pathToFileURL(resolvedPath));
|
||||
const resolveResult = await resolve(url.pathToFileURL(resolvedPath));
|
||||
assert.strictEqual(resolveResult.format, expectedType);
|
||||
});
|
||||
|
||||
@@ -59,7 +59,7 @@ try {
|
||||
[ 'test-module-mainmjs', 'mjs', 'module', 'module'],
|
||||
[ 'test-module-cjs', 'js', 'commonjs', 'commonjs'],
|
||||
[ 'test-module-ne', 'js', undefined, 'commonjs'],
|
||||
].forEach((testVariant) => {
|
||||
].forEach(async (testVariant) => {
|
||||
const [ moduleName,
|
||||
moduleExtenstion,
|
||||
moduleType,
|
||||
@@ -89,7 +89,7 @@ try {
|
||||
fs.writeFileSync(script,
|
||||
'export function esm-resolve-tester() {return 42}');
|
||||
|
||||
const resolveResult = resolve(`${moduleName}`);
|
||||
const resolveResult = await resolve(`${moduleName}`);
|
||||
assert.strictEqual(resolveResult.format, expectedResolvedType);
|
||||
|
||||
fs.rmSync(nmDir, { recursive: true, force: true });
|
||||
@@ -102,7 +102,7 @@ try {
|
||||
}
|
||||
};
|
||||
|
||||
function testDualPackageWithJsMainScriptAndModuleType() {
|
||||
async function testDualPackageWithJsMainScriptAndModuleType() {
|
||||
// Create a dummy dual package
|
||||
//
|
||||
/**
|
||||
@@ -172,7 +172,7 @@ try {
|
||||
);
|
||||
|
||||
// test the resolve
|
||||
const resolveResult = resolve(`${moduleName}`);
|
||||
const resolveResult = await resolve(`${moduleName}`);
|
||||
assert.strictEqual(resolveResult.format, 'module');
|
||||
assert.ok(resolveResult.url.includes('my-dual-package/es/index.js'));
|
||||
}
|
||||
@@ -192,7 +192,7 @@ try {
|
||||
[ 'hmod', 'index.js', 'imp.js', 'commonjs', 'module', 'module', '#Key'],
|
||||
[ 'qhmod', 'index.js', 'imp.js', 'commonjs', 'module', 'module', '?k=v#h'],
|
||||
[ 'ts-mod-com', 'index.js', 'imp.ts', 'module', 'commonjs', undefined],
|
||||
].forEach((testVariant) => {
|
||||
].forEach(async (testVariant) => {
|
||||
const [
|
||||
moduleName,
|
||||
mainRequireScript,
|
||||
@@ -240,7 +240,7 @@ try {
|
||||
);
|
||||
|
||||
// test the resolve
|
||||
const resolveResult = resolve(`${moduleName}`);
|
||||
const resolveResult = await resolve(`${moduleName}`);
|
||||
assert.strictEqual(resolveResult.format, expectedResolvedFormat);
|
||||
assert.ok(resolveResult.url.endsWith(`${moduleName}/subdir/${mainImportScript}${mainSuffix}`));
|
||||
});
|
||||
|
||||
@@ -13,8 +13,8 @@ export function globalPreload() {
|
||||
`;
|
||||
}
|
||||
|
||||
export function resolve(specifier, context, next) {
|
||||
const def = next(specifier, context);
|
||||
export async function resolve(specifier, context, next) {
|
||||
const def = await next(specifier, context);
|
||||
|
||||
if (def.url.startsWith('node:')) {
|
||||
return {
|
||||
|
||||
@@ -6,8 +6,8 @@ export async function load(url, context, next) {
|
||||
return next(url, context, next);
|
||||
}
|
||||
|
||||
export function resolve(specifier, context, next) {
|
||||
const nextResult = next(specifier, context);
|
||||
export async function resolve(specifier, context, next) {
|
||||
const nextResult = await next(specifier, context);
|
||||
const { format } = nextResult;
|
||||
|
||||
if (format === 'module' || specifier.endsWith('.mjs')) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export function resolve(specifier, { parentURL, importAssertions }, defaultResolve) {
|
||||
export async function resolve(specifier, { parentURL, importAssertions }, defaultResolve) {
|
||||
if (parentURL && specifier === '../fixtures/es-modules/test-esm-ok.mjs') {
|
||||
return {
|
||||
shortCircuit: true,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export function resolve(specifier, { parentURL, importAssertions }, nextResolve) {
|
||||
export async function resolve(specifier, { parentURL, importAssertions }, defaultResolve) {
|
||||
if (parentURL && specifier === '../fixtures/es-modules/test-esm-ok.mjs') {
|
||||
return {
|
||||
shortCircuit: true,
|
||||
@@ -6,5 +6,5 @@ export function resolve(specifier, { parentURL, importAssertions }, nextResolve)
|
||||
importAssertions,
|
||||
};
|
||||
}
|
||||
return nextResolve(specifier, {parentURL, importAssertions});
|
||||
return defaultResolve(specifier, {parentURL, importAssertions}, defaultResolve);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export function resolve(specifier, context, next) {
|
||||
export async function resolve(specifier, context, next) {
|
||||
console.log('resolve 42'); // This log is deliberate
|
||||
console.log('next<HookName>:', next.name); // This log is deliberate
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
export async function resolve(specifier, context, next) {
|
||||
return next(specifier, context);
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
export function resolve(specifier, context, next) {
|
||||
export async function resolve(specifier, context, next) {
|
||||
return next(specifier, []);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export function resolve(specifier, context, next) {
|
||||
export async function resolve(specifier, context, next) {
|
||||
return next([], context);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export function resolve(specifier, context, next) {
|
||||
export async function resolve(specifier, context, next) {
|
||||
console.log('resolve foo'); // This log is deliberate
|
||||
return next('file:///foo.mjs', context);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export function resolve() {
|
||||
export async function resolve() {
|
||||
return {
|
||||
url: 'file:///incomplete-resolve-chain.js',
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export function resolve(specifier, context, next) {
|
||||
const { url: first } = next(specifier, context);
|
||||
const { url: second } = next(specifier, context);
|
||||
export async function resolve(specifier, context, next) {
|
||||
const { url: first } = await next(specifier, context);
|
||||
const { url: second } = await next(specifier, context);
|
||||
|
||||
return {
|
||||
format: 'module',
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
export function resolve(url, context, next) {
|
||||
export async function resolve(url, context, next) {
|
||||
const {
|
||||
format,
|
||||
url: nextUrl,
|
||||
} = next(url, context);
|
||||
} = await next(url, context);
|
||||
|
||||
return {
|
||||
format,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export function resolve(specifier, context, next) {
|
||||
export async function resolve(specifier, context, next) {
|
||||
return next(specifier, {
|
||||
...context,
|
||||
foo: 'bar',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export function resolve(specifier, context, next) {
|
||||
export async function resolve(specifier, context, next) {
|
||||
console.log('resolve passthru'); // This log is deliberate
|
||||
return next(specifier, context);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export function resolve(specifier, context, next) {
|
||||
export async function resolve(specifier, context, next) {
|
||||
console.log(context.foo); // This log is deliberate
|
||||
return next(specifier, context);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export function resolve(specifier) {
|
||||
export async function resolve(specifier) {
|
||||
return {
|
||||
shortCircuit: true,
|
||||
url: specifier,
|
||||
|
||||
@@ -5,7 +5,7 @@ import { createRequire } from '../../common/index.mjs';
|
||||
const require = createRequire(import.meta.url);
|
||||
const dep = require('./loader-dep.js');
|
||||
|
||||
export function resolve(specifier, { parentURL, importAssertions }, nextResolve) {
|
||||
export function resolve(specifier, { parentURL, importAssertions }, defaultResolve) {
|
||||
assert.strictEqual(dep.format, 'module');
|
||||
return nextResolve(specifier, { parentURL, importAssertions });
|
||||
return defaultResolve(specifier, { parentURL, importAssertions }, defaultResolve);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ok, deepStrictEqual } from 'assert';
|
||||
|
||||
export function resolve(specifier, context, nextResolve) {
|
||||
export async function resolve(specifier, context, defaultResolve) {
|
||||
ok(Array.isArray(context.conditions), 'loader receives conditions array');
|
||||
|
||||
deepStrictEqual([...context.conditions].sort(), [
|
||||
@@ -9,7 +9,7 @@ export function resolve(specifier, context, nextResolve) {
|
||||
'node-addons',
|
||||
]);
|
||||
|
||||
return nextResolve(specifier, {
|
||||
return defaultResolve(specifier, {
|
||||
...context,
|
||||
conditions: ['custom-condition', ...context.conditions],
|
||||
});
|
||||
|
||||
@@ -3,9 +3,9 @@ import {createRequire} from '../../common/index.mjs';
|
||||
const require = createRequire(import.meta.url);
|
||||
const dep = require('./loader-dep.js');
|
||||
|
||||
export function resolve(specifier, { parentURL, importAssertions }, nextResolve) {
|
||||
export async function resolve(specifier, { parentURL, importAssertions }, defaultResolve) {
|
||||
return {
|
||||
url: (nextResolve(specifier, { parentURL, importAssertions })).url,
|
||||
url: (await defaultResolve(specifier, { parentURL, importAssertions }, defaultResolve)).url,
|
||||
format: dep.format
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
export function resolve(specifier, { parentURL }, nextResolve) {
|
||||
export function resolve(specifier, { parentURL }, defaultResolve) {
|
||||
if (specifier === 'test') {
|
||||
return {
|
||||
url: 'file://'
|
||||
};
|
||||
}
|
||||
return nextResolve(specifier, {parentURL});
|
||||
return defaultResolve(specifier, {parentURL}, defaultResolve);
|
||||
}
|
||||
|
||||
export function getFormat(url, context, defaultGetFormat) {
|
||||
|
||||
@@ -168,7 +168,7 @@ export function globalPreload({port}) {
|
||||
|
||||
|
||||
// Rewrites node: loading to mock-facade: so that it can be intercepted
|
||||
export function resolve(specifier, context, nextResolve) {
|
||||
export async function resolve(specifier, context, defaultResolve) {
|
||||
if (specifier === 'node:mock') {
|
||||
return {
|
||||
shortCircuit: true,
|
||||
@@ -176,7 +176,7 @@ export function resolve(specifier, context, nextResolve) {
|
||||
};
|
||||
}
|
||||
doDrainPort();
|
||||
const def = nextResolve(specifier, context);
|
||||
const def = await defaultResolve(specifier, context);
|
||||
if (context.parentURL?.startsWith('mock-facade:')) {
|
||||
// Do nothing, let it get the "real" module
|
||||
} else if (mockedModuleExports.has(def.url)) {
|
||||
|
||||
@@ -3,13 +3,13 @@ import assert from 'assert';
|
||||
// a loader that asserts that the defaultResolve will throw "not found"
|
||||
// (skipping the top-level main of course)
|
||||
let mainLoad = true;
|
||||
export function resolve(specifier, { parentURL, importAssertions }, nextResolve) {
|
||||
export async function resolve(specifier, { parentURL, importAssertions }, defaultResolve) {
|
||||
if (mainLoad) {
|
||||
mainLoad = false;
|
||||
return nextResolve(specifier, {parentURL, importAssertions});
|
||||
return defaultResolve(specifier, {parentURL, importAssertions}, defaultResolve);
|
||||
}
|
||||
try {
|
||||
nextResolve(specifier, {parentURL, importAssertions});
|
||||
await defaultResolve(specifier, {parentURL, importAssertions}, defaultResolve);
|
||||
}
|
||||
catch (e) {
|
||||
assert.strictEqual(e.code, 'ERR_MODULE_NOT_FOUND');
|
||||
|
||||
Reference in New Issue
Block a user