Skip to content

Commit 5dafa6b

Browse files
authored
Prefix Node.js built-in imports with node: (emscripten-core#26079)
To ensure compatibility with Deno which requires explicit identification of built-in Node.js modules. When targeting Node.js versions older than 16 (e.g. `-sMIN_NODE_VERSION=150000`), the `node:` prefix is removed using a custom Babel plugin.
1 parent 3b81189 commit 5dafa6b

68 files changed

Lines changed: 277 additions & 209 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.circleci/config.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -890,6 +890,8 @@ jobs:
890890
core0.test_hello_world
891891
core0.test_hello_argc_pthreads
892892
core2.test_pthread_create
893+
other.test_esm
894+
other.test_esm_pthreads
893895
"
894896
test-deno:
895897
executor: linux-python
@@ -908,6 +910,8 @@ jobs:
908910
core0.test_hello_world
909911
core0.test_hello_argc_pthreads
910912
core2.test_pthread_create
913+
other.test_esm
914+
other.test_esm_pthreads
911915
"
912916
test-jsc:
913917
executor: linux-python
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/**
2+
* @license
3+
* Copyright 2026 The Emscripten Authors
4+
* SPDX-License-Identifier: MIT
5+
*/
6+
7+
// A babel plugin to remove the leading `node:` prefix from all imports.
8+
9+
export default function ({ types: t, targets }) {
10+
// Skip this plugin for Node.js >= 16
11+
if (+targets().node.split('.')[0] >= 16) {
12+
return {};
13+
}
14+
15+
return {
16+
name: 'strip-node-prefix',
17+
visitor: {
18+
// e.g. `import fs from 'node:fs'`
19+
ImportDeclaration({ node }) {
20+
if (node.source.value.startsWith('node:')) {
21+
node.source.value = node.source.value.slice(5);
22+
}
23+
},
24+
25+
// e.g. `await import('node:fs')`
26+
// Note: only here for reference, it's mangled with EMSCRIPTEN$AWAIT$IMPORT below.
27+
ImportExpression({ node }) {
28+
if (t.isStringLiteral(node.source) && node.source.value.startsWith('node:')) {
29+
node.source.value = node.source.value.slice(5);
30+
}
31+
},
32+
33+
// e.g. `require('node:fs')` or EMSCRIPTEN$AWAIT$IMPORT('node:fs')
34+
CallExpression({ node }) {
35+
if (
36+
(t.isIdentifier(node.callee, { name: 'require' }) ||
37+
// Special placeholder for `await import`
38+
// FIXME: Remove after PR https://github.com/emscripten-core/emscripten/pull/23730 is landed.
39+
t.isIdentifier(node.callee, { name: 'EMSCRIPTEN$AWAIT$IMPORT' })) &&
40+
t.isStringLiteral(node.arguments[0]) &&
41+
node.arguments[0].value.startsWith('node:')
42+
) {
43+
node.arguments[0].value = node.arguments[0].value.slice(5);
44+
}
45+
},
46+
},
47+
};
48+
}

src/lib/libatomic.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ addToLibrary({
161161

162162
emscripten_num_logical_cores: () =>
163163
#if ENVIRONMENT_MAY_BE_NODE
164-
ENVIRONMENT_IS_NODE ? require('os').cpus().length :
164+
ENVIRONMENT_IS_NODE ? require('node:os').cpus().length :
165165
#endif
166166
navigator['hardwareConcurrency'],
167167
});

src/lib/libcore.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ addToLibrary({
351351
var cmdstr = UTF8ToString(command);
352352
if (!cmdstr.length) return 0; // this is what glibc seems to do (shell works test?)
353353

354-
var cp = require('child_process');
354+
var cp = require('node:child_process');
355355
var ret = cp.spawnSync(cmdstr, [], {shell:true, stdio:'inherit'});
356356

357357
var _W_EXITCODE = (ret, sig) => ((ret) << 8 | (sig));

src/lib/libembind_gen.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -922,7 +922,7 @@ var LibraryEmbind = {
922922
const printer = new TsPrinter(moduleDefinitions);
923923
#endif
924924
const output = printer.print();
925-
var fs = require('fs');
925+
var fs = require('node:fs');
926926
fs.writeFileSync(process.argv[2], output + '\n');
927927
},
928928

src/lib/libnodepath.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
// operations. Hence, using `nodePath` should be safe here.
1313

1414
addToLibrary({
15-
$nodePath: "require('path')",
15+
$nodePath: "require('node:path')",
1616
$PATH__deps: ['$nodePath'],
1717
$PATH: `{
1818
isAbs: nodePath.isAbsolute,

src/lib/libwasi.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,7 @@ var WasiLibrary = {
571571
#if ENVIRONMENT_MAY_BE_NODE && MIN_NODE_VERSION < 190000
572572
// This block is not needed on v19+ since crypto.getRandomValues is builtin
573573
if (ENVIRONMENT_IS_NODE) {
574-
var nodeCrypto = require('crypto');
574+
var nodeCrypto = require('node:crypto');
575575
return (view) => nodeCrypto.randomFillSync(view);
576576
}
577577
#endif // ENVIRONMENT_MAY_BE_NODE

src/lib/libwasm_worker.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ if (ENVIRONMENT_IS_WASM_WORKER
286286

287287
emscripten_navigator_hardware_concurrency: () => {
288288
#if ENVIRONMENT_MAY_BE_NODE
289-
if (ENVIRONMENT_IS_NODE) return require('os').cpus().length;
289+
if (ENVIRONMENT_IS_NODE) return require('node:os').cpus().length;
290290
#endif
291291
return navigator['hardwareConcurrency'];
292292
},

src/parseTools.mjs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1140,19 +1140,19 @@ function nodePthreadDetection() {
11401140
// Under node we detect that we are running in a pthread by checking the
11411141
// workerData property.
11421142
if (EXPORT_ES6) {
1143-
return "(await import('worker_threads')).workerData === 'em-pthread'";
1143+
return "(await import('node:worker_threads')).workerData === 'em-pthread'";
11441144
} else {
1145-
return "require('worker_threads').workerData === 'em-pthread'";
1145+
return "require('node:worker_threads').workerData === 'em-pthread'";
11461146
}
11471147
}
11481148

11491149
function nodeWWDetection() {
11501150
// Under node we detect that we are running in a wasm worker by checking the
11511151
// workerData property.
11521152
if (EXPORT_ES6) {
1153-
return "(await import('worker_threads')).workerData === 'em-ww'";
1153+
return "(await import('node:worker_threads')).workerData === 'em-ww'";
11541154
} else {
1155-
return "require('worker_threads').workerData === 'em-ww'";
1155+
return "require('node:worker_threads').workerData === 'em-ww'";
11561156
}
11571157
}
11581158

src/postamble.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ if (ENVIRONMENT_IS_NODE
322322
#endif
323323
)
324324
{
325-
const url = await import('url');
325+
const url = await import('node:url');
326326
const isMainModule = url.pathToFileURL(process.argv[1]).href === import.meta.url;
327327
if (isMainModule) await init();
328328
}

0 commit comments

Comments
 (0)