-
Notifications
You must be signed in to change notification settings - Fork 29.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ES Module loading with abolute path fails on windows #31710
Comments
You'd need to write |
As per node.js documentation: The specifier of an import statement is the string after the from keyword, e.g. 'path' in import { sep } from 'path'. Specifiers are also used in export from statements, and as the argument to an import() expression. There are four types of specifiers:
Bare specifiers, and the bare specifier portion of deep import specifiers, are strings; but everything else in a specifier is a URL. Only file: and data: URLs are supported. A specifier like 'https://example.com/app.js' may be supported by browsers but it is not supported in Node.js. Specifiers may not begin with / or //. These are reserved for potential future use. The root of the current volume may be referenced via file:///. |
@kiranpwr1260 thanks! It works on mac os though. Maybe not the same way you posted, but it works according to expectation. On macos, if you do this:
I expected the same to be true on windows, hence the issue report :) Thanks @devsnek as well! |
Yeah, I think this is either a bug on macos & linux or windows. Mac and Linux (alpine docker image, to be precise): $ echo 'export default "hello!";' > file.mjs
$ node -e 'import(require.resolve("./file.mjs")).then(console.log, console.error)'
(node:28) ExperimentalWarning: The ESM module loader is experimental.
[Module] { default: 'hello!' } Windows: $ echo 'export default "hello!";' > file.mjs
$ node -e 'import(require.resolve("./file.mjs")).then(console.log, console.error)'
(node:3036) ExperimentalWarning: The ESM module loader is experimental.
Error [ERR_UNSUPPORTED_ESM_URL_SCHEME]: Only file and data URLs are supported by the default ESM loader
at Loader.defaultResolve [as _resolve] (internal/modules/esm/resolve.js:33:11)
at Loader.resolve (internal/modules/esm/loader.js:85:40)
at Loader.getModuleJob (internal/modules/esm/loader.js:188:40)
at Loader.import (internal/modules/esm/loader.js:163:28)
at importModuleDynamically (internal/modules/cjs/loader.js:1094:27)
at exports.importModuleDynamicallyCallback (internal/process/esm_loader.js:37:14)
at Object.<anonymous> (C:\Users\IEUser\script.js:1:16)
at Module._compile (internal/modules/cjs/loader.js:1151:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1171:10)
at Module.load (internal/modules/cjs/loader.js:1000:32) {
code: 'ERR_UNSUPPORTED_ESM_URL_SCHEME'
} With |
the issue is that |
From a user perspective it's really weird that absolute paths work for some OSes, but not all. Would it make sense to throw on absolute paths without |
you should use https://nodejs.org/api/url.html#url_url_pathtofileurl_path |
Yeah, I've changed to use that in Jest now, but it's still odd to me that it behaves differently across OSes, even though Maybe the error message could include something about passing the file path provided through |
This is because URL {
scheme: "c:",
host: null,
path: "/path/to/module.js",
} And Node doesn’t know how to deal with a URL with a scheme of What you want is URL {
scheme: "file:",
host: "",
path: "/C:/path/to/module.js",
} |
Yeah, I understand why it happens, I just disagree with the behavior that absolute paths are treated differently between platforms, and would prefer it to just accept either relative paths or absolute paths that has the That ship might have sailed though 🙂 |
@SimenB it doesn't accept paths, it accept urls. like i said, the correct thing to do if you have a path is to use pathToFileURL. |
Absolute paths (either unix or windows style) aren't valid URLs, though. $ node -p 'new URL("/Users/user/file.js").href'
internal/url.js:243
throw new ERR_INVALID_URL(input);
^
TypeError [ERR_INVALID_URL]: Invalid URL: /Users/user/file.js (same behavior in Chrome) I 100% agree with passing the path through |
So to summarize and clarify, ESM importing right now works like this:
This issue report is about the inconsistency regarding "absolute paths". For my money, I would love to have absolute paths work on windows as well. It only makes sense that a function to include other files can actually handle paths. At least when running in a node.js environment. I understand the difficulties differentiating between a windows absolute path and an url, since the drive letter could be confused with a URL scheme. And single-letter schemes seem to be valid according to this RFC: https://tools.ietf.org/html/rfc3986#section-3.1 . But I think it's safe to assume that introducing single-letter URL schemes in a world where windows exists is not likely to happen |
@SimenB they aren't valid absolute urls, but they are valid as relative urls (https://url.spec.whatwg.org/#path-absolute-url-string), which is why they're accepted in I'm not sure how we could detect the intent of someone when they typed it, since that's all that separates an absolute path from a relative path absolute url string. |
Aha, gotcha! Didn't think about the case when it's a $ node -p 'new URL("/Users/user/file.js", "http://example.com/some/path").href'
http://example.com/Users/user/file.js So what essentially happens is I think this should be highlighted in the docs somewhere, although I'm not entirely sure where. |
adding something to the docs seems reasonable to me. |
As discussed, this behaviour is by design. A docs PR to help clarify further would be very welcome. |
Update es module documentation in accordance to nodejs#31710 by providing a gotcha for windows users
Explains that absolute specifiers and absolute paths are not the same, and mentions what to do about it. Refs: nodejs#31710
For windows file path, `C:\` prefix are not supported as they get confused with a regular URI. The fix is to write the file path with `file://` protocol. Fixes: KaotoIO#98 Related issue: nodejs/node#31710
For windows file path, `C:\` prefix are not supported as they get confused with a regular URI. The fix is to write the file path with `file://` protocol. Fixes: #98 Related issue: nodejs/node#31710
It would be nice to be able to load an absolute path... in this case I don't have a way to set the current working directory, and |
What steps will reproduce the bug?
C:\prog\node\genast
(as expected!)
It errors out with:
internal/modules/run_main.js:54
internalBinding('errors').triggerUncaughtException(
^
Error [ERR_UNSUPPORTED_ESM_URL_SCHEME]: Only file and data URLs are supported by the default ESM loader
at Loader.defaultResolve [as _resolve] (internal/modules/esm/resolve.js:33:11)
at Loader.resolve (internal/modules/esm/loader.js:85:40)
at Loader.getModuleJob (internal/modules/esm/loader.js:188:40)
at ModuleWrap. (internal/modules/esm/module_job.js:42:40)
at link (internal/modules/esm/module_job.js:41:36) {
code: 'ERR_UNSUPPORTED_ESM_URL_SCHEME'
}
Using forward- och backward slashes doesn't make a difference.
How often does it reproduce? Is there a required condition?
100%
What is the expected behavior?
Absolute includes should work the same as relative
What do you see instead?
Additional information
The same issue is seen with both static ES imports and dynamic ES imports.
The text was updated successfully, but these errors were encountered: