Skip to content

Commit 40cecec

Browse files
Bartek Wronaclaude
andcommitted
Replace require() with await import() in EXPORT_ES6 shell/runtime files
When EXPORT_ES6 is enabled, the generated JS used createRequire() to polyfill require(), which breaks bundlers (webpack, Rollup, esbuild) and Electron's renderer process. Since EXPORT_ES6 requires MODULARIZE, the module body is wrapped in an async function where await is valid. - shell.js: Remove createRequire block entirely. Use await import() for worker_threads, fs, path, url, util. Replace __dirname with import.meta.url for path resolution. - shell_minimal.js: Same pattern for worker_threads and fs. Replace __dirname with new URL(..., import.meta.url) for wasm file loading. - runtime_debug.js: Skip local require() for fs/util when EXPORT_ES6, reuse outer-scope variables from shell.js instead. - runtime_common.js: Guard perf_hooks require() with EXPORT_ES6 alternative. - preamble.js: Hoist await import('node:v8') above instantiateSync() for NODE_CODE_CACHING since await can't be used inside sync functions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent bc0f059 commit 40cecec

5 files changed

Lines changed: 49 additions & 11 deletions

File tree

src/preamble.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,13 +549,21 @@ var splitModuleProxyHandler = {
549549
};
550550
#endif
551551

552+
#if NODE_CODE_CACHING && ENVIRONMENT_MAY_BE_NODE && EXPORT_ES6
553+
var nodeV8 = ENVIRONMENT_IS_NODE ? await import('node:v8') : undefined;
554+
#endif
555+
552556
#if SPLIT_MODULE || !WASM_ASYNC_COMPILATION
553557
function instantiateSync(file, info) {
554558
var module;
555559
var binary = getBinarySync(file);
556560
#if NODE_CODE_CACHING
557561
if (ENVIRONMENT_IS_NODE) {
562+
#if EXPORT_ES6
563+
var v8 = nodeV8;
564+
#else
558565
var v8 = require('node:v8');
566+
#endif
559567
// Include the V8 version in the cache name, so that we don't try to
560568
// load cached code from another version, which fails silently (it seems
561569
// to load ok, but we do actually recompile the binary every time).

src/runtime_common.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,11 @@ if (ENVIRONMENT_IS_NODE) {
171171
// depends on it for accurate timing.
172172
// Use `global` rather than `globalThis` here since older versions of node
173173
// don't have `globalThis`.
174+
#if EXPORT_ES6
175+
global.performance ??= (await import('perf_hooks')).performance;
176+
#else
174177
global.performance ??= require('perf_hooks').performance;
178+
#endif
175179
}
176180
#endif
177181

src/runtime_debug.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@ function dbg(...args) {
1515
// See https://github.com/emscripten-core/emscripten/issues/14804
1616
if (ENVIRONMENT_IS_NODE) {
1717
// TODO(sbc): Unify with err/out implementation in shell.sh.
18+
#if !EXPORT_ES6
1819
var fs = require('node:fs');
1920
var utils = require('node:util');
21+
#endif
2022
function stringify(a) {
2123
switch (typeof a) {
2224
case 'object': return utils.inspect(a);

src/shell.js

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -107,18 +107,13 @@ if (ENVIRONMENT_IS_PTHREAD) {
107107
#endif
108108
#endif
109109

110-
#if ENVIRONMENT_MAY_BE_NODE && (EXPORT_ES6 || PTHREADS || WASM_WORKERS)
110+
#if ENVIRONMENT_MAY_BE_NODE && (PTHREADS || WASM_WORKERS)
111111
if (ENVIRONMENT_IS_NODE) {
112112
#if EXPORT_ES6
113-
// When building an ES module `require` is not normally available.
114-
// We need to use `createRequire()` to construct the require()` function.
115-
const { createRequire } = await import('node:module');
116-
/** @suppress{duplicate} */
117-
var require = createRequire(import.meta.url);
118-
#endif
119-
120-
#if PTHREADS || WASM_WORKERS
113+
var worker_threads = await import('node:worker_threads');
114+
#else
121115
var worker_threads = require('node:worker_threads');
116+
#endif
122117
global.Worker = worker_threads.Worker;
123118
ENVIRONMENT_IS_WORKER = !worker_threads.isMainThread;
124119
#if PTHREADS
@@ -129,7 +124,6 @@ if (ENVIRONMENT_IS_NODE) {
129124
#if WASM_WORKERS
130125
ENVIRONMENT_IS_WASM_WORKER = ENVIRONMENT_IS_WORKER && worker_threads.workerData == 'em-ww'
131126
#endif
132-
#endif // PTHREADS || WASM_WORKERS
133127
}
134128
#endif // ENVIRONMENT_MAY_BE_NODE
135129

@@ -200,11 +194,17 @@ if (ENVIRONMENT_IS_NODE) {
200194

201195
// These modules will usually be used on Node.js. Load them eagerly to avoid
202196
// the complexity of lazy-loading.
197+
#if EXPORT_ES6
198+
var fs = await import('node:fs');
199+
#else
203200
var fs = require('node:fs');
201+
#endif
204202

205203
#if EXPORT_ES6
206204
if (_scriptName.startsWith('file:')) {
207-
scriptDirectory = require('node:path').dirname(require('node:url').fileURLToPath(_scriptName)) + '/';
205+
var nodePath = await import('node:path');
206+
var nodeUrl = await import('node:url');
207+
scriptDirectory = nodePath.dirname(nodeUrl.fileURLToPath(_scriptName)) + '/';
208208
}
209209
#else
210210
scriptDirectory = __dirname + '/';
@@ -352,7 +352,11 @@ if (!ENVIRONMENT_IS_AUDIO_WORKLET)
352352
var defaultPrint = console.log.bind(console);
353353
var defaultPrintErr = console.error.bind(console);
354354
if (ENVIRONMENT_IS_NODE) {
355+
#if EXPORT_ES6
356+
var utils = await import('node:util');
357+
#else
355358
var utils = require('node:util');
359+
#endif
356360
var stringify = (a) => typeof a == 'object' ? utils.inspect(a) : a;
357361
defaultPrint = (...args) => fs.writeSync(1, args.map(stringify).join(' ') + '\n');
358362
defaultPrintErr = (...args) => fs.writeSync(2, args.map(stringify).join(' ') + '\n');

src/shell_minimal.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,11 @@ var ENVIRONMENT_IS_WEB = !ENVIRONMENT_IS_NODE;
5555

5656
#if ENVIRONMENT_MAY_BE_NODE && (PTHREADS || WASM_WORKERS)
5757
if (ENVIRONMENT_IS_NODE) {
58+
#if EXPORT_ES6
59+
var worker_threads = await import('node:worker_threads');
60+
#else
5861
var worker_threads = require('node:worker_threads');
62+
#endif
5963
global.Worker = worker_threads.Worker;
6064
}
6165
#endif
@@ -99,7 +103,11 @@ if (ENVIRONMENT_IS_NODE && ENVIRONMENT_IS_SHELL) {
99103
var defaultPrint = console.log.bind(console);
100104
var defaultPrintErr = console.error.bind(console);
101105
if (ENVIRONMENT_IS_NODE) {
106+
#if EXPORT_ES6
107+
var fs = await import('node:fs');
108+
#else
102109
var fs = require('node:fs');
110+
#endif
103111
defaultPrint = (...args) => fs.writeSync(1, args.join(' ') + '\n');
104112
defaultPrintErr = (...args) => fs.writeSync(2, args.join(' ') + '\n');
105113
}
@@ -181,6 +189,17 @@ if (!ENVIRONMENT_IS_PTHREAD) {
181189
// Wasm or Wasm2JS loading:
182190

183191
if (ENVIRONMENT_IS_NODE) {
192+
#if EXPORT_ES6
193+
var fs = await import('node:fs');
194+
#if WASM == 2
195+
if (globalThis.WebAssembly) Module['wasm'] = fs.readFileSync(new URL('{{{ TARGET_BASENAME }}}.wasm', import.meta.url));
196+
else eval(fs.readFileSync(new URL('{{{ TARGET_BASENAME }}}.wasm.js', import.meta.url))+'');
197+
#else
198+
#if !WASM2JS
199+
Module['wasm'] = fs.readFileSync(new URL('{{{ TARGET_BASENAME }}}.wasm', import.meta.url));
200+
#endif
201+
#endif
202+
#else
184203
var fs = require('node:fs');
185204
#if WASM == 2
186205
if (globalThis.WebAssembly) Module['wasm'] = fs.readFileSync(__dirname + '/{{{ TARGET_BASENAME }}}.wasm');
@@ -190,6 +209,7 @@ if (ENVIRONMENT_IS_NODE) {
190209
Module['wasm'] = fs.readFileSync(__dirname + '/{{{ TARGET_BASENAME }}}.wasm');
191210
#endif
192211
#endif
212+
#endif
193213
}
194214
#endif
195215

0 commit comments

Comments
 (0)