Skip to content

Commit 3707d00

Browse files
committed
loader: use default loader as cascaded loader in the in loader worker
Use the default loader as the cascaded loader in the loader worker. Otherwise we spawn loader workers in the loader workers indefinitely.
1 parent 9b6f7f0 commit 3707d00

File tree

7 files changed

+53
-10
lines changed

7 files changed

+53
-10
lines changed

lib/internal/main/worker_thread.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,12 @@ port.on('message', (message) => {
133133
if (manifestSrc) {
134134
require('internal/process/policy').setup(manifestSrc, manifestURL);
135135
}
136-
setupUserModules();
136+
let isLoaderWorker = false;
137+
if (doEval === 'internal' &&
138+
filename === require('internal/modules/esm/utils').loaderWorkerId) {
139+
isLoaderWorker = true;
140+
}
141+
setupUserModules(isLoaderWorker);
137142

138143
if (!hasStdin)
139144
process.stdin.push(null);

lib/internal/modules/esm/hooks.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ const {
5252
} = require('internal/modules/esm/resolve');
5353
const {
5454
getDefaultConditions,
55+
loaderWorkerId,
5556
} = require('internal/modules/esm/utils');
5657
const { deserializeError } = require('internal/error_serdes');
5758
const {
@@ -494,7 +495,7 @@ class HooksProxy {
494495
const lock = new SharedArrayBuffer(SHARED_MEMORY_BYTE_LENGTH);
495496
this.#lock = new Int32Array(lock);
496497

497-
this.#worker = new InternalWorker('internal/modules/esm/worker', {
498+
this.#worker = new InternalWorker(loaderWorkerId, {
498499
stderr: false,
499500
stdin: false,
500501
stdout: false,

lib/internal/modules/esm/loader.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,8 @@ let emittedExperimentalWarning = false;
411411
* @returns {DefaultModuleLoader | CustomizedModuleLoader}
412412
*/
413413
function createModuleLoader(useCustomLoadersIfPresent = true) {
414-
if (useCustomLoadersIfPresent) {
414+
if (useCustomLoadersIfPresent &&
415+
!require('internal/modules/esm/utils').isLoaderWorker()) {
415416
const userLoaderPaths = getOptionValue('--experimental-loader');
416417
if (userLoaderPaths.length > 0) {
417418
if (!emittedExperimentalWarning) {

lib/internal/modules/esm/utils.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,22 @@ async function importModuleDynamicallyCallback(wrap, specifier, assertions) {
9191
throw new ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING();
9292
}
9393

94-
function initializeESM() {
94+
// This is configured during pre-execution. Specifically it's set to true for
95+
// the loader worker in internal/main/worker_thread.js.
96+
let _isLoaderWorker = false;
97+
function initializeESM(isLoaderWorker = false) {
98+
_isLoaderWorker = isLoaderWorker;
9599
initializeDefaultConditions();
96100
// Setup per-isolate callbacks that locate data or callbacks that we keep
97101
// track of for different ESM modules.
98102
setInitializeImportMetaObjectCallback(initializeImportMetaObject);
99103
setImportModuleDynamicallyCallback(importModuleDynamicallyCallback);
100104
}
101105

106+
function isLoaderWorker() {
107+
return _isLoaderWorker;
108+
}
109+
102110
async function initializeHooks() {
103111
const customLoaderPaths = getOptionValue('--experimental-loader');
104112

@@ -165,4 +173,6 @@ module.exports = {
165173
initializeHooks,
166174
getDefaultConditions,
167175
getConditionsSet,
176+
loaderWorkerId: 'internal/modules/esm/worker',
177+
isLoaderWorker,
168178
};

lib/internal/modules/esm/worker.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const { receiveMessageOnPort } = require('internal/worker/io');
2929
const {
3030
WORKER_TO_MAIN_THREAD_NOTIFICATION,
3131
} = require('internal/modules/esm/shared_constants');
32-
const { initializeESM, initializeHooks } = require('internal/modules/esm/utils');
32+
const { initializeHooks } = require('internal/modules/esm/utils');
3333

3434

3535
function transferArrayBuffer(hasError, source) {
@@ -67,7 +67,6 @@ async function customizedModuleWorker(lock, syncCommPort, errorHandler) {
6767
let hasInitializationError = false;
6868

6969
try {
70-
initializeESM();
7170
const initResult = await initializeHooks();
7271
hooks = initResult.hooks;
7372
preloadScripts = initResult.preloadScripts;

lib/internal/process/pre_execution.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,9 @@ function prepareExecution(options) {
119119
}
120120
}
121121

122-
function setupUserModules() {
122+
function setupUserModules(isLoaderWorker = false) {
123123
initializeCJSLoader();
124-
initializeESMLoader();
124+
initializeESMLoader(isLoaderWorker);
125125
const CJSLoader = require('internal/modules/cjs/loader');
126126
assert(!CJSLoader.hasLoadedAnyUserCJSModule);
127127
loadPreloadModules();
@@ -600,9 +600,9 @@ function initializeCJSLoader() {
600600
initializeCJS();
601601
}
602602

603-
function initializeESMLoader() {
603+
function initializeESMLoader(isLoaderWorker) {
604604
const { initializeESM } = require('internal/modules/esm/utils');
605-
initializeESM();
605+
initializeESM(isLoaderWorker);
606606

607607
// Patch the vm module when --experimental-vm-modules is on.
608608
// Please update the comments in vm.js when this block changes.

test/es-module/test-loader-worker.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
'use strict';
2+
3+
require('../common');
4+
const { spawnSync } = require('child_process');
5+
const tmpdir = require('../common/tmpdir');
6+
const assert = require('assert');
7+
const { execPath } = require('process');
8+
const { writeFileSync } = require('fs');
9+
const { join } = require('path');
10+
11+
tmpdir.refresh();
12+
writeFileSync(join(tmpdir.path, 'hello.cjs'), 'console.log("hello")', 'utf8');
13+
writeFileSync(join(tmpdir.path, 'loader.mjs'), 'import "./hello.cjs"', 'utf8');
14+
writeFileSync(join(tmpdir.path, 'main.cjs'), 'setTimeout(() => {}, 1000)', 'utf8');
15+
16+
const child = spawnSync(execPath, ['--experimental-loader', './loader.mjs', 'main.cjs'], {
17+
cwd: tmpdir.path
18+
});
19+
20+
const stdout = child.stdout.toString().trim();
21+
const stderr = child.stderr.toString().trim();
22+
const hellos = [...stdout.matchAll(/hello/g)];
23+
const warnings = [...stderr.matchAll(/ExperimentalWarning: Custom ESM Loaders/g)];
24+
25+
assert.strictEqual(child.status, 0);
26+
assert.strictEqual(hellos.length, 1);
27+
assert.strictEqual(warnings.length, 1);

0 commit comments

Comments
 (0)