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
Cannot use mjs file synchronously in commonJS without await / .then() #33605
How often does it reproduce? Is there a required condition?
Always
What is the expected behavior?
I can load an ESM module from a commonJS file.
What do you see instead?
~/tmp/temp123
$ node broken.cjs
internal/modules/cjs/loader.js:984
throw new ERR_REQUIRE_ESM(filename);
^
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /home/raynos/tmp/temp123/third-party-is-promise.mjs
at Module.load (internal/modules/cjs/loader.js:984:11)
at Function.Module._load (internal/modules/cjs/loader.js:879:14)
at Module.require (internal/modules/cjs/loader.js:1026:19)
at require (internal/modules/cjs/helpers.js:72:18)
at Object.<anonymous> (/home/raynos/tmp/temp123/broken.cjs:1:19)
at Module._compile (internal/modules/cjs/loader.js:1138:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1158:10)
at Module.load (internal/modules/cjs/loader.js:986:32)
at Function.Module._load (internal/modules/cjs/loader.js:879:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12) {
code: 'ERR_REQUIRE_ESM'
}
Additional information
I would like to import an ESM synchronously from a commonJS file.
Node added child_process.execSync() a while ago but that used to not be possible.
It would be really nice if node had some kind of importSync() feature.
I see from a related PR that a function promiseWait exists.
If I can just call require.promiseWait(import('./esm.mjs')) then that would also allow me to get a promise for a ESM module using import and then just blocking wait until the promise resolves.
We don't have to do anything "special" with require we just expose a process.awaitSync(p) function.
And there's a PR at #30891, but it has so many issues that that's why nodejs/modules#454 was opened. It's not clear that the issues raised will be addressable; or in plainer terms, require of ESM might not be possible.
Ok, I would like to importSync or require a ESM module and if it has a top level await you can just throw an exception saying "Some ESM has top level await; not supported"
More realistically, if you're looking for a way to "bottle up" promises and resolve them synchronously, you should look into node-fibers and its use in the framework Meteor. That's at least one example of doing so in a widely used framework that has many production apps. Meteor (at least currently) only supports ESM by transpiling it to CommonJS, however; it's unclear whether it can ever support native ESM along with node-fibers. Based on the discussion in nodejs/modules#454, such a thing might not be possible, or possible without violating spec (which is something that Node can't do).
The ECMAScript spec does actually provide data on if top level await is used: https://tc39.es/proposal-top-level-await/#sec-cyclic-module-records in a new internal [[Async]] slot, however this is set for more than just top level await; all WASM modules have that as true due to their initialization lifecycle as I understand. This internal slot is not currently reflected in V8's public API though to my knowledge. I think we could review this if/when it is exposed as a means to help transitioning.
@Raynos I am not as clear on the reasoning, but they always initialize async in module form. Someone more vested in their design/implementation would be more knowledgable.
so, we're not ever going to have importSync. cjs to esm interop is a problem we'd like to solve but it wouldn't be in this manner, and I think we already have other issues tracking this more generally, so I'm going to close this.
changed the title [-]Cannot use mjs file in commonJS without importSync.[/-][+]Cannot use mjs file synchronously in commonJS without await / .then()[/+]on Jul 20, 2020
Activity
Raynos commentedon May 28, 2020
I see from a related PR that a function
promiseWaitexists.If I can just call
require.promiseWait(import('./esm.mjs'))then that would also allow me to get a promise for a ESM module usingimportand then just blocking wait until the promise resolves.We don't have to do anything "special" with
requirewe just expose aprocess.awaitSync(p)function.bmeck commentedon May 28, 2020
Relevant discussion here nodejs/modules#454
GeoffreyBooth commentedon May 28, 2020
And there's a PR at #30891, but it has so many issues that that's why nodejs/modules#454 was opened. It's not clear that the issues raised will be addressable; or in plainer terms,
requireof ESM might not be possible.ESM code can be loaded into a CommonJS module via
import(). https://nodejs.org/api/esm.html#esm_import_expressionsRaynos commentedon May 28, 2020
Ok, I would like to
importSyncorrequirea ESM module and if it has a top level await you can just throw an exception saying "Some ESM has top level await; not supported"Raynos commentedon May 28, 2020
I've also found a userland solution
There are native modules on npm that implement
awaitSync()as a C++ function.devsnek commentedon May 28, 2020
Those who use
@snek/syncifyare doomed to a life of sadnessGeoffreyBooth commentedon May 28, 2020
More realistically, if you're looking for a way to "bottle up" promises and resolve them synchronously, you should look into
node-fibersand its use in the framework Meteor. That's at least one example of doing so in a widely used framework that has many production apps. Meteor (at least currently) only supports ESM by transpiling it to CommonJS, however; it's unclear whether it can ever support native ESM along withnode-fibers. Based on the discussion in nodejs/modules#454, such a thing might not be possible, or possible without violating spec (which is something that Node can't do).bmeck commentedon May 29, 2020
The ECMAScript spec does actually provide data on if top level await is used: https://tc39.es/proposal-top-level-await/#sec-cyclic-module-records in a new internal
[[Async]]slot, however this is set for more than just top level await; all WASM modules have that astruedue to their initialization lifecycle as I understand. This internal slot is not currently reflected in V8's public API though to my knowledge. I think we could review this if/when it is exposed as a means to help transitioning.Raynos commentedon May 29, 2020
Could you explain more about the limitations of loading a WASM module synchronously ?
I think
require(mjs)andrequire(wasm)are two completely different beasts.I would be fine with a
require(mjs)that fails on transitive dependencies that use Top level await and WASM.The fast majority of the uses cases for ESM is trivial code that doesn't do anything special with top level await or WASM.
bmeck commentedon May 29, 2020
@Raynos I am not as clear on the reasoning, but they always initialize async in module form. Someone more vested in their design/implementation would be more knowledgable.
devsnek commentedon May 29, 2020
wasm esm modules take advantage of off-thread compilation and things of that nature, using wasm's async apis.
[-]Cannot require mjs file.[/-][+]Cannot use mjs file in commonJS without importSync.[/+]Raynos commentedon Jul 20, 2020
I was looking at using ESM again and sharing some ideas on twitter ( https://twitter.com/Raynos/status/1285109697662640130 ).
Having importSync() available would help migrate to ESM without breaking all my commonJS users.
devsnek commentedon Jul 20, 2020
so, we're not ever going to have importSync. cjs to esm interop is a problem we'd like to solve but it wouldn't be in this manner, and I think we already have other issues tracking this more generally, so I'm going to close this.
Raynos commentedon Jul 20, 2020
Could you link to the more general issue for using esm from cjs ? I just did a search and could not find anything.
[-]Cannot use mjs file in commonJS without importSync.[/-][+]Cannot use mjs file synchronously in commonJS without await / .then()[/+]devsnek commentedon Jul 20, 2020
@Raynos nodejs/modules#454
Raynos commentedon Jul 20, 2020
Oh it's not in this repository. And there's this PR which was already referenced ( #30891 )