| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -501,6 +501,7 @@ class HooksProxy { | |||
| 501 | 501 | }, | |
| 502 | 502 | }); | |
| 503 | 503 | this.#worker.unref(); // ! Allows the process to eventually exit. | |
| 504 | + this.#worker.on('exit', process.exit); | ||
| 504 | 505 | } | |
| 505 | 506 | ||
| 506 | 507 | #waitForWorker() { | |
@@ -510,6 +511,7 @@ class HooksProxy { | |||
| 510 | 511 | debug('wait for signal from worker'); | |
| 511 | 512 | AtomicsWait(this.#lock, WORKER_TO_MAIN_THREAD_NOTIFICATION, 0); | |
| 512 | 513 | const response = this.#worker.receiveMessageSync(); | |
| 514 | + if (response.message.status === 'exit') { return; } | ||
| 513 | 515 | const { preloadScripts } = this.#unwrapMessage(response); | |
| 514 | 516 | this.#executePreloadScripts(preloadScripts); | |
| 515 | 517 | } | |
@@ -590,6 +592,8 @@ class HooksProxy { | |||
| 590 | 592 | debug('got sync response from worker', { method, args }); | |
| 591 | 593 | if (response.message.status === 'never-settle') { | |
| 592 | 594 | process.exit(13); | |
| 595 | + } else if (response.message.status === 'exit') { | ||
| 596 | + process.exit(response.message.body); | ||
| 593 | 597 | } | |
| 594 | 598 | return this.#unwrapMessage(response); | |
| 595 | 599 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -66,6 +66,19 @@ async function customizedModuleWorker(lock, syncCommPort, errorHandler) { | |||
| 66 | 66 | let hooks, preloadScripts, initializationError; | |
| 67 | 67 | let hasInitializationError = false; | |
| 68 | 68 | ||
| 69 | + { | ||
| 70 | + // If a custom hook is calling `process.exit`, we should wake up the main thread | ||
| 71 | + // so it can detect the exit event. | ||
| 72 | + const { exit } = process; | ||
| 73 | + process.exit = function(code) { | ||
| 74 | + syncCommPort.postMessage(wrapMessage('exit', code ?? process.exitCode)); | ||
| 75 | + AtomicsAdd(lock, WORKER_TO_MAIN_THREAD_NOTIFICATION, 1); | ||
| 76 | + AtomicsNotify(lock, WORKER_TO_MAIN_THREAD_NOTIFICATION); | ||
| 77 | + return ReflectApply(exit, this, arguments); | ||
| 78 | + }; | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + | ||
| 69 | 82 | try { | |
| 70 | 83 | initializeESM(); | |
| 71 | 84 | const initResult = await initializeHooks(); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -143,4 +143,52 @@ describe('Loader hooks', { concurrency: true }, () => { | |||
| 143 | 143 | assert.strictEqual(code, 0); | |
| 144 | 144 | assert.strictEqual(signal, null); | |
| 145 | 145 | }); | |
| 146 | + | ||
| 147 | + it('should be fine to call `process.exit` from a custom async hook', async () => { | ||
| 148 | + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ | ||
| 149 | + '--no-warnings', | ||
| 150 | + '--experimental-import-meta-resolve', | ||
| 151 | + '--experimental-loader', | ||
| 152 | + 'data:text/javascript,export function load(a,b,next){if(a==="data:exit")process.exit(42);return next(a,b)}', | ||
| 153 | + '--input-type=module', | ||
| 154 | + '--eval', | ||
| 155 | + 'import "data:exit"', | ||
| 156 | + ]); | ||
| 157 | + | ||
| 158 | + assert.strictEqual(stderr, ''); | ||
| 159 | + assert.strictEqual(stdout, ''); | ||
| 160 | + assert.strictEqual(code, 42); | ||
| 161 | + assert.strictEqual(signal, null); | ||
| 162 | + }); | ||
| 163 | + | ||
| 164 | + it('should be fine to call `process.exit` from a custom sync hook', async () => { | ||
| 165 | + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ | ||
| 166 | + '--no-warnings', | ||
| 167 | + '--experimental-import-meta-resolve', | ||
| 168 | + '--experimental-loader', | ||
| 169 | + 'data:text/javascript,export function resolve(a,b,next){if(a==="exit:")process.exit(42);return next(a,b)}', | ||
| 170 | + '--input-type=module', | ||
| 171 | + '--eval', | ||
| 172 | + 'import "data:text/javascript,import.meta.resolve(%22exit:%22)"', | ||
| 173 | + ]); | ||
| 174 | + | ||
| 175 | + assert.strictEqual(stderr, ''); | ||
| 176 | + assert.strictEqual(stdout, ''); | ||
| 177 | + assert.strictEqual(code, 42); | ||
| 178 | + assert.strictEqual(signal, null); | ||
| 179 | + }); | ||
| 180 | + | ||
| 181 | + it('should be fine to call `process.exit` from the loader thread top-level', async () => { | ||
| 182 | + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ | ||
| 183 | + '--no-warnings', | ||
| 184 | + '--experimental-loader', | ||
| 185 | + 'data:text/javascript,process.exit(42)', | ||
| 186 | + fixtures.path('empty.js'), | ||
| 187 | + ]); | ||
| 188 | + | ||
| 189 | + assert.strictEqual(stderr, ''); | ||
| 190 | + assert.strictEqual(stdout, ''); | ||
| 191 | + assert.strictEqual(code, 42); | ||
| 192 | + assert.strictEqual(signal, null); | ||
| 193 | + }); | ||
| 146 | 194 | }); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments