Description
- Version: 12.10.0
- Platform: Windows Server 2019
- Subsystem: url
An error occurs after creating the custom-loader.mjs
containing the dummy loader code as directed by the documentation, an x.js
file, and running the following command in PowerShell.
node --experimental-modules --loader ./custom-loader.mjs x.js
By the way, this command diverges from the one provided in the documentation to be used on Windows as NODE_OPTIONS='--experimental-modules --loader ./custom-loader.mjs' node x.js
fails in PowerShell.
(node:1364) ExperimentalWarning: The ESM module loader is experimental.
(node:1364) ExperimentalWarning: --loader is an experimental feature. This feature could change at any time
internal/modules/cjs/loader.js:992
internalBinding('errors').triggerUncaughtException(
^
TypeError [ERR_INVALID_URL]: Invalid URL: /C:/Users/Administrator/source/repos/esm/x.js
at onParseError (internal/url.js:243:9)
at new URL (internal/url.js:319:5)
at resolve (file:///C:/Users/Administrator/source/repos/esm/custom-loader.mjs:23:20)
at Loader.resolve (internal/modules/esm/loader.js:73:33)
at Loader.getModuleJob (internal/modules/esm/loader.js:152:40)
at Loader.import (internal/modules/esm/loader.js:136:28)
at internal/modules/cjs/loader.js:989:27 {
input: '/C:/Users/Administrator/source/repos/esm/x.js'
}
The x.js
file certainly exists. It turns out that there is a Windows-specific error where a leading forward slash causes this example to break. I was able to resolve this by adding:
specifier = cleanPath(specifier);
specifier = url.pathToFileURL(specifier).href;
prior to (from the dummy loader code):
const resolved = new URL(specifier, parentModuleURL);
and including the following function:
/**
* Path sanitizer that removes a leading slash if followed by Windows drive sepcifier.
* @param {string} specifier URL path to a file
* @returns {string} Cleaned specifier URL path to a file
*/
function cleanPath(specifier) {
const specifierDir = path.parse(specifier).dir;
if (
specifierDir.length >= 3 &&
specifierDir.charAt(0) == '/' &&
specifierDir.charAt(1).toUpperCase() !=
specifierDir.charAt(1).toLowerCase() && // Check if alphabetic
specifierDir.charAt(2) == ':'
) {
specifier = specifier.substring(1);
}
return specifier;
}
P.S. This also needs import url from 'url';
added to the top of custom-loader.mjs
.