You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Modules: Specify or infer module type for new vm.Script #27387
asyncfunctionresolve(specifier,parentURL,defaultResolve){returndefaultResolve('./script.mjs','file:///');}newvm.Script(`import fs from "fs"`,{loader: { resolve }});
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 of node --experimental-modules script.js. E.g.:
Thanks. Is there a mechanism to determine if a module is CJS/ESM? Branching logic will need to introduced to either use vm.Script or vm.SourceTextModule based on this.
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.
Also, trying to get vm.SourceTextModule working, is there a default implementation for linker in module.link(linker)? How is one supposed to return a vm.Module for a built-in, for example?
constvm=require('vm');(async()=>{constesModule=newvm.SourceTextModule(`import fs from 'fs';`,{url: `file:///script.mjs`,});awaitesModule.link(spec=>import(spec));esModule.instantiate();awaitesModule.evaluate();})().catch(console.error);
Results in:
(node:54937) ExperimentalWarning: The ESM module loader is experimental.
Error [ERR_VM_MODULE_NOT_MODULE]: Provided module is not an instance of Module
at ModuleWrap.<anonymous> (internal/vm/source_text_module.js:190:15)
at processTicksAndRejections (internal/process/task_queues.js:88:5)
at process.runNextTicks [as _tickCallback] (internal/process/task_queues.js:58:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:823:13)
at internal/main/run_main_module.js:17:11
at async Promise.all (index 0)
(node:54937) ExperimentalWarning: vm.SourceTextModule is an experimental feature. This feature could change at any time
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:
Looks like vm.ScriptTextModule is a very low-level API, which is great, but not really what we're after. We want a batteries-included API (like vm.Script) that is effectively running node file.mjs except provides:
Ability to intercept and potentially rewire imports, falling back to a default.
Ability to run the module in a new context. (Doesn't have to be vm.createContext, just need to define the global this.)
Would there be any interest in providing this? Maybe called new vm.Module?
@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.
we want to write something like this
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 require() to implement module mocking, and provides a context so it can install fake timers, globals, etc.
Should we open up an issue in https://github.com/nodejs/modules/issues about this (running a module in a vm.Context) or is it still a bit early for that? I see it's mentioned in the readme over there, but I found no open issues about it.
EDIT: The merged #29864 looks exciting though, the examples seems to cover what we need in Jest 🙂
Activity
devsnek commentedon Apr 24, 2019
use vm.SourceTextModule for source text module sources: https://nodejs.org/api/vm.html#vm_class_vm_sourcetextmodule
azz commentedon Apr 24, 2019
Thanks. Is there a mechanism to determine if a module is CJS/ESM? Branching logic will need to introduced to either use
vm.Scriptorvm.SourceTextModulebased on this.devsnek commentedon Apr 24, 2019
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.
azz commentedon Apr 24, 2019
I want to follow the same log node uses:
.js, readpackage.json#type, default to CJS..mjs, ESM.cjs, CJSazz commentedon Apr 24, 2019
Also, trying to get
vm.SourceTextModuleworking, is there a default implementation forlinkerinmodule.link(linker)? How is one supposed to return avm.Modulefor a built-in, for example?devsnek commentedon Apr 24, 2019
@azz you can also return a module namespace object, the result of
import()azz commentedon Apr 25, 2019
Doesn't seem to be the case?
Results in:
devsnek commentedon Apr 25, 2019
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:
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
azz commentedon Apr 25, 2019
Looks like
vm.ScriptTextModuleis a very low-level API, which is great, but not really what we're after. We want a batteries-included API (likevm.Script) that is effectively runningnode file.mjsexcept provides:vm.createContext, just need to define the globalthis.)Would there be any interest in providing this? Maybe called
new vm.Module?Basically we want to write something like this:
devsnek commentedon Apr 25, 2019
@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.
azz commentedon Apr 25, 2019
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
require()to implement module mocking, and provides a context so it can install fake timers, globals, etc.Some relevant files:
https://github.com/facebook/jest/blob/master/packages/jest-environment-node/src/index.ts
https://github.com/facebook/jest/blob/master/packages/jest-transform/src/ScriptTransformer.ts
devsnek commentedon Apr 25, 2019
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.
azz commentedon Apr 25, 2019
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 👍
SimenB commentedon Jan 17, 2020
Should we open up an issue in https://github.com/nodejs/modules/issues about this (running a module in a
vm.Context) or is it still a bit early for that? I see it's mentioned in the readme over there, but I found no open issues about it.EDIT: The merged #29864 looks exciting though, the examples seems to cover what we need in Jest 🙂