esm: improve validation of resolved URLs

PR-URL: https://github.com/nodejs/node/pull/41446
Reviewed-By: Bradley Farias <bradley.meck@gmail.com>
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
Reviewed-By: Guy Bedford <guybedford@gmail.com>
This commit is contained in:
Jacob Smith 2022-01-19 06:28:32 +01:00 committed by GitHub
parent b9258e5e81
commit dbc6e39ca7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 14 additions and 14 deletions

View File

@ -29,7 +29,7 @@ const {
ERR_INVALID_RETURN_VALUE,
ERR_UNKNOWN_MODULE_FORMAT
} = require('internal/errors').codes;
const { pathToFileURL, isURLInstance } = require('internal/url');
const { pathToFileURL, isURLInstance, URL } = require('internal/url');
const {
isAnyArrayBuffer,
isArrayBufferView,
@ -558,7 +558,8 @@ class ESMLoader {
format,
);
}
if (typeof url !== 'string') {
if (typeof url !== 'string') { // non-strings can be coerced to a url string
throw new ERR_INVALID_RETURN_PROPERTY_VALUE(
'string',
'loader resolve',
@ -567,6 +568,8 @@ class ESMLoader {
);
}
new URL(url); // Intentionally trigger error if `url` is invalid
return {
format,
url,

View File

@ -4,11 +4,7 @@ import assert from 'assert';
import('../fixtures/es-modules/test-esm-ok.mjs')
.then(assert.fail, (error) => {
expectsError({
code: 'ERR_INVALID_URL',
message: 'Invalid URL'
})(error);
expectsError({ code: 'ERR_INVALID_URL' })(error);
assert.strictEqual(error.input, '../fixtures/es-modules/test-esm-ok.mjs');
})
.then(mustCall());

View File

@ -1,3 +1,4 @@
import { pathToFileURL } from 'node:url';
import count from '../es-modules/stateful.mjs';
@ -24,28 +25,28 @@ export function load(url, context, next) {
format: 'module',
});
if (url === 'esmHook/badReturnVal.mjs') return 'export function returnShouldBeObject() {}';
if (url.endsWith('esmHook/badReturnVal.mjs')) return 'export function returnShouldBeObject() {}';
if (url === 'esmHook/badReturnFormatVal.mjs') return {
if (url.endsWith('esmHook/badReturnFormatVal.mjs')) return {
format: Array(0),
source: '',
}
if (url === 'esmHook/unsupportedReturnFormatVal.mjs') return {
if (url.endsWith('esmHook/unsupportedReturnFormatVal.mjs')) return {
format: 'foo', // Not one of the allowable inputs: no translator named 'foo'
source: '',
}
if (url === 'esmHook/badReturnSourceVal.mjs') return {
if (url.endsWith('esmHook/badReturnSourceVal.mjs')) return {
format: 'module',
source: Array(0),
}
if (url === 'esmHook/preknownFormat.pre') return {
if (url.endsWith('esmHook/preknownFormat.pre')) return {
format: context.format,
source: `const msg = 'hello world'; export default msg;`
};
if (url === 'esmHook/virtual.mjs') return {
if (url.endsWith('esmHook/virtual.mjs')) return {
format: 'module',
source: `export const message = 'Woohoo!'.toUpperCase();`,
};
@ -62,7 +63,7 @@ export function resolve(specifier, context, next) {
if (specifier.startsWith('esmHook')) return {
format,
url: specifier,
url: pathToFileURL(specifier).href,
importAssertions: context.importAssertions,
};