* Initializes the loader hooks worker thread with customized asynchronous module loading hooks. * @param {SharedArrayBuffer} lock - The lock used to synchronize communication between the worker and the main thread. * @param {MessagePort} syncCommPort - The message port used for synchronous communi
(lock, syncCommPort, errorHandler)
| 141 | * @returns {Promise<void>} A promise that resolves when the worker thread has been initialized. |
| 142 | */ |
| 143 | async function customizedModuleWorker(lock, syncCommPort, errorHandler) { |
| 144 | let asyncLoaderHooks; |
| 145 | let initializationError; |
| 146 | let hasInitializationError = false; |
| 147 | |
| 148 | { |
| 149 | // If a custom hook is calling `process.exit`, we should wake up the main thread |
| 150 | // so it can detect the exit event. |
| 151 | const { exit } = process; |
| 152 | process.exit = function(code) { |
| 153 | syncCommPort.postMessage(wrapMessage('exit', code ?? process.exitCode)); |
| 154 | AtomicsAdd(lock, WORKER_TO_MAIN_THREAD_NOTIFICATION, 1); |
| 155 | AtomicsNotify(lock, WORKER_TO_MAIN_THREAD_NOTIFICATION); |
| 156 | return ReflectApply(exit, this, arguments); |
| 157 | }; |
| 158 | } |
| 159 | |
| 160 | try { |
| 161 | asyncLoaderHooks = await initializeAsyncLoaderHooksOnLoaderHookWorker(); |
| 162 | } catch (exception) { |
| 163 | // If there was an error while parsing and executing a user loader, for example if because a |
| 164 | // loader contained a syntax error, then we need to send the error to the main thread so it can |
| 165 | // be thrown and printed. |
| 166 | hasInitializationError = true; |
| 167 | initializationError = exception; |
| 168 | } |
| 169 | |
| 170 | syncCommPort.on('message', handleMessage); |
| 171 | |
| 172 | if (hasInitializationError) { |
| 173 | syncCommPort.postMessage(wrapMessage('error', initializationError)); |
| 174 | } else { |
| 175 | syncCommPort.postMessage(wrapMessage('success')); |
| 176 | } |
| 177 | |
| 178 | // We're ready, so unlock the main thread. |
| 179 | AtomicsAdd(lock, WORKER_TO_MAIN_THREAD_NOTIFICATION, 1); |
| 180 | AtomicsNotify(lock, WORKER_TO_MAIN_THREAD_NOTIFICATION); |
| 181 | |
| 182 | let immediate; |
| 183 | /** |
| 184 | * Checks for messages on the syncCommPort and handles them asynchronously. |
| 185 | */ |
| 186 | function checkForMessages() { |
| 187 | immediate = setImmediate(checkForMessages).unref(); |
| 188 | // We need to let the event loop tick a few times to give the main thread a chance to send |
| 189 | // follow-up messages. |
| 190 | const response = receiveMessageOnPort(syncCommPort); |
| 191 | |
| 192 | if (response !== undefined) { |
| 193 | PromisePrototypeThen(handleMessage(response.message), undefined, errorHandler); |
| 194 | } |
| 195 | } |
| 196 | |
| 197 | const unsettledResponsePorts = new SafeSet(); |
| 198 | |
| 199 | process.on('beforeExit', () => { |
| 200 | for (const port of unsettledResponsePorts) { |
no test coverage detected
searching dependent graphs…