-
Notifications
You must be signed in to change notification settings - Fork 30.6k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Modules: Specify or infer module type for new vm.Script
#27387
Comments
use vm.SourceTextModule for source text module sources: https://nodejs.org/api/vm.html#vm_class_vm_sourcetextmodule |
Thanks. Is there a mechanism to determine if a module is CJS/ESM? Branching logic will need to introduced to either use |
there is no logic you can use to reliably determine if a string is a module or a script. as such, node doesn't provide anything. however, you can come up with your own logic that fits your needs. for example if you know that your modules will always contain imports or exports you can use acorn or something to parse and check for them. |
I want to follow the same log node uses:
|
Also, trying to get |
@azz you can also return a module namespace object, the result of |
Doesn't seem to be the case? const vm = require('vm');
(async () => {
const esModule = new vm.SourceTextModule(`import fs from 'fs';`, {
url: `file:///script.mjs`,
});
await esModule.link(spec => import(spec));
esModule.instantiate();
await esModule.evaluate();
})().catch(console.error); Results in:
|
yeah i'm sorry, the namespace thing is only for dynamic imports. i don't know of a good solution to this off the top of my head, but you can do something like this for now: import * as fs from 'fs'; // or `const fs = require('fs')`, doesn't really matter
new vm.SourceTextModule(
Object.keys(fs)
.map((x) => `export const ${x} = import.meta.mod.${x};`)
.join('\n'), {
initializeImportMeta(meta) {
meta.mod = fs;
},
}); there are still some things you'll need to take care of, like simulating live bindings. node/lib/internal/bootstrap/loaders.js Lines 233 to 288 in b9f1e57
node/lib/internal/modules/esm/translators.js Lines 90 to 107 in b9f1e57
|
Looks like
Would there be any interest in providing this? Maybe called Basically we want to write something like this: async function importModule(specifier, parentURL, defaultImport) {
return defaultImport(specifier, parentURL);
}
const context = vm.createContext();
if (inputIsModule(filePath)) {
let mod = new vm.Module(code, { filename: filePath, importModule });
await mod.runInContext(context);
} else {
let script = new vm.Script(code, { filename: filePath })
script.runInContext(context);
} |
@azz vm.Script and vm.SourceTextModule are the same "level", its just that you need to do more things to run a module than to run a script. It seems like you want us to expose node's internal module loader, more than a specific vm api, is that right? There are definitely changes we can still make to the SourceTextModule api, that's why it's experimental, but exposing node's internal module loader is kind of no-no territory until we finish designing it.
who is "we" and what is the specific use case here? knowing that will help me provide more useful information. |
Ah sorry, I didn't explicitly mention (there's an issue reference above). The context is that we're trying to determine if Jest can run tests on files that are ES modules without first transpiling them to CJS via Babel. With CJS, Jest intercepts Some relevant files: |
aha, so what you're really looking for is "run node's esm module loader in a new context for jest and also let jest intercept some things" since we haven't actually settled on how our esm module loader works, you should probably wait a bit to start doing this. Either we will expose some sort of "loader" api, or you will need to duplicate our behaviour with the vm api. |
Yes exactly.
Ok no worries, the release of v12 prompted me to see how far I could get with what's already shipped 😄 Thanks for your help 👍 |
Should we open up an issue in https://github.com/nodejs/modules/issues about this (running a module in a EDIT: The merged #29864 looks exciting though, the examples seems to cover what we need in Jest 🙂 |
Is your feature request related to a problem? Please describe.
Consider the following:
When executed with
--experimental-modules
, as of12.0.0
this throws:Describe the solution you'd like
The "input-type" to be inferred from the filename
.mjs
An additional option added to
vm.Script
, calledtype
, which overrides file-based inference.Resolve hooks should be available, e.g.:
Describe alternatives you've considered
Alternatively, an API to determine the
type
/format
of a given file path using the same rules that determine the type ofnode --experimental-modules script.js
. E.g.:This would work for some cases but the resolve hook is more powerful.
The text was updated successfully, but these errors were encountered: