Upload Kmake

This commit is contained in:
Gorochu
2026-05-26 23:36:42 -07:00
parent ba051b2f74
commit 555ec72358
41615 changed files with 13344630 additions and 1 deletions

496
lib/internal/worker/io.js Normal file
View File

@ -0,0 +1,496 @@
'use strict';
const {
Array,
FunctionPrototypeBind,
FunctionPrototypeCall,
ObjectAssign,
ObjectCreate,
ObjectDefineProperties,
ObjectDefineProperty,
ObjectGetOwnPropertyDescriptors,
ObjectGetPrototypeOf,
ObjectSetPrototypeOf,
ObjectValues,
ReflectApply,
Symbol,
SymbolFor,
} = primordials;
const {
assignFunctionName,
kEnumerableProperty,
setOwnProperty,
} = require('internal/util');
const {
handle_onclose: handleOnCloseSymbol,
oninit: onInitSymbol,
no_message_symbol: noMessageSymbol,
} = internalBinding('symbols');
const {
privateSymbols: {
transfer_mode_private_symbol,
},
constants: {
kCloneable,
},
} = internalBinding('util');
const {
MessagePort,
MessageChannel,
broadcastChannel,
drainMessagePort,
moveMessagePortToContext,
receiveMessageOnPort: receiveMessageOnPort_,
stopMessagePort,
DOMException,
} = internalBinding('messaging');
const {
getEnvMessagePort,
} = internalBinding('worker');
const { Readable, Writable } = require('stream');
const {
Event,
EventTarget,
NodeEventTarget,
defineEventHandler,
initNodeEventTarget,
kCreateEvent,
kNewListener,
kRemoveListener,
} = require('internal/event_target');
const { inspect } = require('internal/util/inspect');
const {
codes: {
ERR_INVALID_THIS,
ERR_MISSING_ARGS,
},
} = require('internal/errors');
const kHandle = Symbol('kHandle');
const kIncrementsPortRef = Symbol('kIncrementsPortRef');
const kName = Symbol('kName');
const kOnMessage = Symbol('kOnMessage');
const kOnMessageError = Symbol('kOnMessageError');
const kPort = Symbol('kPort');
const kWaitingStreams = Symbol('kWaitingStreams');
const kWritableCallback = Symbol('kWritableCallback');
const kStartedReading = Symbol('kStartedReading');
const kStdioWantsMoreDataCallback = Symbol('kStdioWantsMoreDataCallback');
const kCurrentlyReceivingPorts =
SymbolFor('nodejs.internal.kCurrentlyReceivingPorts');
const kType = Symbol('kType');
const messageTypes = {
UP_AND_RUNNING: 'upAndRunning',
COULD_NOT_SERIALIZE_ERROR: 'couldNotSerializeError',
ERROR_MESSAGE: 'errorMessage',
STDIO_PAYLOAD: 'stdioPayload',
STDIO_WANTS_MORE_DATA: 'stdioWantsMoreData',
LOAD_SCRIPT: 'loadScript',
};
// createFastMessageEvent skips webidl argument validation when the arguments
// passed are known to be valid.
let fastCreateMessageEvent;
function lazyMessageEvent(type, init) {
fastCreateMessageEvent ??= require('internal/deps/undici/undici').createFastMessageEvent;
return fastCreateMessageEvent(type, init);
}
// We have to mess with the MessagePort prototype a bit, so that a) we can make
// it inherit from NodeEventTarget, even though it is a C++ class, and b) we do
// not provide methods that are not present in the Browser and not documented
// on our side (e.g. stopMessagePort).
const messagePortPrototypePropertyDescriptors = ObjectGetOwnPropertyDescriptors(MessagePort.prototype);
const propertiesValues = ObjectValues(messagePortPrototypePropertyDescriptors);
for (let i = 0; i < propertiesValues.length; i++) {
// We want to use null-prototype objects to not rely on globally mutable
// %Object.prototype%.
ObjectSetPrototypeOf(propertiesValues[i], null);
}
// Save a copy of the original set of methods as a shallow clone.
const MessagePortPrototype = ObjectCreate(
ObjectGetPrototypeOf(MessagePort.prototype),
messagePortPrototypePropertyDescriptors);
// Set up the new inheritance chain.
ObjectSetPrototypeOf(MessagePort, NodeEventTarget);
ObjectSetPrototypeOf(MessagePort.prototype, NodeEventTarget.prototype);
// Copy methods that are inherited from HandleWrap, because
// changing the prototype of MessagePort.prototype implicitly removed them.
MessagePort.prototype.ref = MessagePortPrototype.ref;
MessagePort.prototype.unref = MessagePortPrototype.unref;
MessagePort.prototype.hasRef = function hasRef() {
return !!FunctionPrototypeCall(MessagePortPrototype.hasRef, this);
};
const originalCreateEvent = EventTarget.prototype[kCreateEvent];
ObjectDefineProperty(
MessagePort.prototype,
kCreateEvent,
{
__proto__: null,
value: assignFunctionName(kCreateEvent, function(data, type) {
if (type !== 'message' && type !== 'messageerror') {
return ReflectApply(originalCreateEvent, this, arguments);
}
const ports = this[kCurrentlyReceivingPorts];
this[kCurrentlyReceivingPorts] = undefined;
return lazyMessageEvent(type, { data, ports });
}),
configurable: false,
writable: false,
enumerable: false,
});
// This is called from inside the `MessagePort` constructor.
function oninit() {
initNodeEventTarget(this);
setupPortReferencing(this, this, 'message');
this[kCurrentlyReceivingPorts] = undefined;
}
defineEventHandler(MessagePort.prototype, 'message');
defineEventHandler(MessagePort.prototype, 'messageerror');
ObjectDefineProperty(MessagePort.prototype, onInitSymbol, {
__proto__: null,
enumerable: true,
writable: false,
value: oninit,
});
class MessagePortCloseEvent extends Event {
constructor() {
super('close');
}
}
// This is called after the underlying `uv_async_t` has been closed.
function onclose() {
this.dispatchEvent(new MessagePortCloseEvent());
}
ObjectDefineProperty(MessagePort.prototype, handleOnCloseSymbol, {
__proto__: null,
enumerable: false,
writable: false,
value: onclose,
});
MessagePort.prototype.close = function close(cb) {
if (typeof cb === 'function')
this.once('close', cb);
FunctionPrototypeCall(MessagePortPrototype.close, this);
};
ObjectDefineProperty(MessagePort.prototype, inspect.custom, {
__proto__: null,
enumerable: false,
writable: false,
value: function inspect() { // eslint-disable-line func-name-matching
let ref;
try {
// This may throw when `this` does not refer to a native object,
// e.g. when accessing the prototype directly.
ref = FunctionPrototypeCall(MessagePortPrototype.hasRef, this);
} catch { return this; }
return ObjectAssign({ __proto__: MessagePort.prototype },
ref === undefined ? {
active: false,
} : {
active: true,
refed: ref,
},
this);
},
});
function setupPortReferencing(port, eventEmitter, eventName) {
// Keep track of whether there are any workerMessage listeners:
// If there are some, ref() the channel so it keeps the event loop alive.
// If there are none or all are removed, unref() the channel so the worker
// can shutdown gracefully.
port.unref();
eventEmitter.on('newListener', function(name) {
if (name === eventName) newListener(eventEmitter.listenerCount(name));
});
eventEmitter.on('removeListener', function(name) {
if (name === eventName) removeListener(eventEmitter.listenerCount(name));
});
const origNewListener = eventEmitter[kNewListener];
setOwnProperty(eventEmitter, kNewListener, function(size, type, ...args) {
if (type === eventName) newListener(size - 1);
return ReflectApply(origNewListener, this, arguments);
});
const origRemoveListener = eventEmitter[kRemoveListener];
setOwnProperty(eventEmitter, kRemoveListener, function(size, type, ...args) {
if (type === eventName) removeListener(size);
return ReflectApply(origRemoveListener, this, arguments);
});
function newListener(size) {
if (size === 0) {
port.ref();
FunctionPrototypeCall(MessagePortPrototype.start, port);
}
}
function removeListener(size) {
if (size === 0) {
stopMessagePort(port);
port.unref();
}
}
}
class ReadableWorkerStdio extends Readable {
constructor(port, name) {
super();
this[kPort] = port;
this[kName] = name;
this[kIncrementsPortRef] = true;
this[kStartedReading] = false;
this.on('end', () => {
if (this[kStartedReading] && this[kIncrementsPortRef]) {
if (--this[kPort][kWaitingStreams] === 0)
this[kPort].unref();
}
});
}
_read() {
if (!this[kStartedReading] && this[kIncrementsPortRef]) {
this[kStartedReading] = true;
if (this[kPort][kWaitingStreams]++ === 0)
this[kPort].ref();
}
this[kPort].postMessage({
type: messageTypes.STDIO_WANTS_MORE_DATA,
stream: this[kName],
});
}
}
class WritableWorkerStdio extends Writable {
constructor(port, name) {
super({ decodeStrings: false });
this[kPort] = port;
this[kName] = name;
this[kWritableCallback] = null;
}
_writev(chunks, cb) {
const toSend = new Array(chunks.length);
// We avoid .map() because it's a hot path
for (let i = 0; i < chunks.length; i++) {
const { chunk, encoding } = chunks[i];
toSend[i] = { chunk, encoding };
}
this[kPort].postMessage({
type: messageTypes.STDIO_PAYLOAD,
stream: this[kName],
chunks: toSend,
});
if (process._exiting) {
cb();
} else {
// Only one writev happens at any given time,
// so we can safely overwrite the callback.
this[kWritableCallback] = cb;
if (this[kPort][kWaitingStreams]++ === 0)
this[kPort].ref();
}
}
_final(cb) {
this[kPort].postMessage({
type: messageTypes.STDIO_PAYLOAD,
stream: this[kName],
chunks: [ { chunk: null, encoding: '' } ],
});
cb();
}
[kStdioWantsMoreDataCallback]() {
const cb = this[kWritableCallback];
if (cb) {
this[kWritableCallback] = null;
cb();
if (--this[kPort][kWaitingStreams] === 0)
this[kPort].unref();
}
}
}
function createWorkerStdio() {
const port = getEnvMessagePort();
port[kWaitingStreams] = 0;
return {
stdin: new ReadableWorkerStdio(port, 'stdin'),
stdout: new WritableWorkerStdio(port, 'stdout'),
stderr: new WritableWorkerStdio(port, 'stderr'),
};
}
function receiveMessageOnPort(port) {
const message = receiveMessageOnPort_(port?.[kHandle] ?? port);
if (message === noMessageSymbol) return undefined;
return { message };
}
function onMessageEvent(type, data) {
this.dispatchEvent(lazyMessageEvent(type, { data }));
}
function isBroadcastChannel(value) {
return value?.[kType] === 'BroadcastChannel';
}
class BroadcastChannel extends EventTarget {
/**
* @param {string} name
*/
constructor(name) {
if (arguments.length === 0)
throw new ERR_MISSING_ARGS('name');
super();
this[kType] = 'BroadcastChannel';
this[kName] = `${name}`;
this[kHandle] = broadcastChannel(this[kName]);
this[kOnMessage] = FunctionPrototypeBind(onMessageEvent, this, 'message');
this[kOnMessageError] =
FunctionPrototypeBind(onMessageEvent, this, 'messageerror');
this[kHandle].on('message', this[kOnMessage]);
this[kHandle].on('messageerror', this[kOnMessageError]);
}
[inspect.custom](depth, options) {
if (!isBroadcastChannel(this))
throw new ERR_INVALID_THIS('BroadcastChannel');
if (depth < 0)
return 'BroadcastChannel';
const opts = {
...options,
depth: options.depth == null ? null : options.depth - 1,
};
return `BroadcastChannel ${inspect({
name: this[kName],
active: this[kHandle] !== undefined,
}, opts)}`;
}
/**
* @type {string}
*/
get name() {
if (!isBroadcastChannel(this))
throw new ERR_INVALID_THIS('BroadcastChannel');
return this[kName];
}
/**
* @returns {void}
*/
close() {
if (!isBroadcastChannel(this))
throw new ERR_INVALID_THIS('BroadcastChannel');
if (this[kHandle] === undefined)
return;
this[kHandle].off('message', this[kOnMessage]);
this[kHandle].off('messageerror', this[kOnMessageError]);
this[kOnMessage] = undefined;
this[kOnMessageError] = undefined;
this[kHandle].close();
this[kHandle] = undefined;
}
/**
*
* @param {any} message
* @returns {void}
*/
postMessage(message) {
if (!isBroadcastChannel(this))
throw new ERR_INVALID_THIS('BroadcastChannel');
if (arguments.length === 0)
throw new ERR_MISSING_ARGS('message');
if (this[kHandle] === undefined)
throw new DOMException('BroadcastChannel is closed.', 'InvalidStateError');
if (this[kHandle].postMessage(message) === undefined)
throw new DOMException('Message could not be posted.');
}
// The ref() method is Node.js specific and not part of the standard
// BroadcastChannel API definition. Typically we shouldn't extend Web
// Platform APIs with Node.js specific methods but ref and unref
// are a bit special.
/**
* @returns {BroadcastChannel}
*/
ref() {
if (!isBroadcastChannel(this))
throw new ERR_INVALID_THIS('BroadcastChannel');
if (this[kHandle])
this[kHandle].ref();
return this;
}
// The unref() method is Node.js specific and not part of the standard
// BroadcastChannel API definition. Typically we shouldn't extend Web
// Platform APIs with Node.js specific methods but ref and unref
// are a bit special.
/**
* @returns {BroadcastChannel}
*/
unref() {
if (!isBroadcastChannel(this))
throw new ERR_INVALID_THIS('BroadcastChannel');
if (this[kHandle])
this[kHandle].unref();
return this;
}
}
ObjectDefineProperties(BroadcastChannel.prototype, {
name: kEnumerableProperty,
close: kEnumerableProperty,
postMessage: kEnumerableProperty,
});
defineEventHandler(BroadcastChannel.prototype, 'message');
defineEventHandler(BroadcastChannel.prototype, 'messageerror');
function markAsUncloneable(obj) {
if ((typeof obj !== 'object' && typeof obj !== 'function') || obj === null) {
return;
}
obj[transfer_mode_private_symbol] &= ~kCloneable;
}
module.exports = {
drainMessagePort,
messageTypes,
kPort,
kIncrementsPortRef,
kWaitingStreams,
kStdioWantsMoreDataCallback,
markAsUncloneable,
moveMessagePortToContext,
MessagePort,
MessageChannel,
receiveMessageOnPort,
setupPortReferencing,
ReadableWorkerStdio,
WritableWorkerStdio,
createWorkerStdio,
BroadcastChannel,
};

View File

@ -0,0 +1,138 @@
'use strict';
const {
Error,
StringPrototypeSplit,
} = primordials;
const {
codes: {
ERR_MISSING_ARGS,
},
} = require('internal/errors');
const webidl = require('internal/webidl');
const {
messaging_deserialize_symbol,
messaging_transfer_symbol,
messaging_clone_symbol,
messaging_transfer_list_symbol,
} = internalBinding('symbols');
const {
setDeserializerCreateObjectFunction,
structuredClone: nativeStructuredClone,
} = internalBinding('messaging');
const {
privateSymbols: {
transfer_mode_private_symbol,
},
constants: {
kDisallowCloneAndTransfer,
kTransferable,
kCloneable,
},
} = internalBinding('util');
function setup() {
// Register the handler that will be used when deserializing JS-based objects
// from .postMessage() calls. The format of `deserializeInfo` is generally
// 'module:Constructor', e.g. 'internal/fs/promises:FileHandle'.
setDeserializerCreateObjectFunction((deserializeInfo) => {
const { 0: module, 1: ctor } = StringPrototypeSplit(deserializeInfo, ':', 2);
const Ctor = require(module)[ctor];
if (typeof Ctor !== 'function' ||
typeof Ctor.prototype[messaging_deserialize_symbol] !== 'function') {
// Not one of the official errors because one should not be able to get
// here without messing with Node.js internals.
// eslint-disable-next-line no-restricted-syntax
throw new Error(`Unknown deserialize spec ${deserializeInfo}`);
}
return new Ctor();
});
}
/**
* Mark an object as being transferable or customized cloneable in
* `.postMessage()`.
* This should only applied to host objects like Web API interfaces, Node.js'
* built-in objects.
* Objects marked as cloneable and transferable should implement the method
* `@@kClone` and `@@kTransfer` respectively. Method `@@kDeserialize` is
* required to deserialize the data to a new instance.
*
* Example implementation of a cloneable interface (assuming its located in
* `internal/my_interface.js`):
*
* ```
* class MyInterface {
* constructor(...args) {
* markTransferMode(this, true);
* this.args = args;
* }
* [kDeserialize](data) {
* this.args = data.args;
* }
* [kClone]() {
* return {
* data: { args: this.args },
* deserializeInfo: 'internal/my_interface:MyInterface',
* }
* }
* }
*
* module.exports = {
* MyInterface,
* };
* ```
* @param {object} obj Host objects that can be either cloned or transferred.
* @param {boolean} [cloneable] if the object can be cloned and `@@kClone` is
* implemented.
* @param {boolean} [transferable] if the object can be transferred and
* `@@kTransfer` is implemented.
*/
function markTransferMode(obj, cloneable = false, transferable = false) {
if ((typeof obj !== 'object' && typeof obj !== 'function') || obj === null)
return; // This object is a primitive and therefore already untransferable.
let mode = kDisallowCloneAndTransfer;
if (cloneable) mode |= kCloneable;
if (transferable) mode |= kTransferable;
obj[transfer_mode_private_symbol] = mode;
}
webidl.converters.StructuredSerializeOptions = webidl
.createDictionaryConverter(
[
{
key: 'transfer',
converter: webidl.converters['sequence<object>'],
defaultValue: () => [],
},
],
);
function structuredClone(value, options) {
if (arguments.length === 0) {
throw new ERR_MISSING_ARGS('The value argument must be specified');
}
const idlOptions = webidl.converters.StructuredSerializeOptions(
options,
{
__proto__: null,
prefix: "Failed to execute 'structuredClone'",
context: 'Options',
},
);
const serializedData = nativeStructuredClone(value, idlOptions);
return serializedData;
}
module.exports = {
markTransferMode,
setup,
structuredClone,
kClone: messaging_clone_symbol,
kDeserialize: messaging_deserialize_symbol,
kTransfer: messaging_transfer_symbol,
kTransferList: messaging_transfer_list_symbol,
};

View File

@ -0,0 +1,242 @@
'use strict';
const {
AtomicsNotify,
AtomicsStore,
AtomicsWaitAsync,
Int32Array,
SafeMap,
globalThis,
} = primordials;
const {
SharedArrayBuffer,
} = globalThis;
const {
isMainThread,
threadId: currentThreadId,
} = internalBinding('worker');
const {
codes: {
ERR_WORKER_MESSAGING_ERRORED,
ERR_WORKER_MESSAGING_FAILED,
ERR_WORKER_MESSAGING_SAME_THREAD,
ERR_WORKER_MESSAGING_TIMEOUT,
},
} = require('internal/errors');
const { MessageChannel } = require('internal/worker/io');
const { validateNumber } = require('internal/validators');
const messageTypes = {
REGISTER_MAIN_THREAD_PORT: 'registerMainThreadPort',
UNREGISTER_MAIN_THREAD_PORT: 'unregisterMainThreadPort',
SEND_MESSAGE_TO_WORKER: 'sendMessageToWorker',
RECEIVE_MESSAGE_FROM_WORKER: 'receiveMessageFromWorker',
};
// This is only populated by main thread and always empty in other threads
const threadsPorts = new SafeMap();
// This is only populated in child threads and always undefined in main thread
let mainThreadPort;
// SharedArrayBuffer must always be Int32, so it's * 4.
// We need one for the operation status (performing / performed) and one for the result (success / failure).
const WORKER_MESSAGING_SHARED_DATA = 2 * 4;
const WORKER_MESSAGING_STATUS_INDEX = 0;
const WORKER_MESSAGING_RESULT_INDEX = 1;
// Response codes
const WORKER_MESSAGING_RESULT_DELIVERED = 0;
const WORKER_MESSAGING_RESULT_NO_LISTENERS = 1;
const WORKER_MESSAGING_RESULT_LISTENER_ERROR = 2;
// This event handler is always executed on the main thread only
function handleMessageFromThread(message) {
switch (message.type) {
case messageTypes.REGISTER_MAIN_THREAD_PORT:
{
const { threadId, port } = message;
// Register the port
threadsPorts.set(threadId, port);
// Handle messages on this port
// When a new thread wants to register a children
// this take care of doing that.
// This way any thread can be linked to the main one.
port.on('message', handleMessageFromThread);
// Never block the thread on this port
port.unref();
}
break;
case messageTypes.UNREGISTER_MAIN_THREAD_PORT:
threadsPorts.get(message.threadId).close();
threadsPorts.delete(message.threadId);
break;
case messageTypes.SEND_MESSAGE_TO_WORKER:
{
// Send the message to the target thread
const { source, destination, value, transferList, memory } = message;
sendMessageToWorker(source, destination, value, transferList, memory);
}
break;
}
}
function handleMessageFromMainThread(message) {
switch (message.type) {
case messageTypes.RECEIVE_MESSAGE_FROM_WORKER:
receiveMessageFromWorker(message.source, message.value, message.memory);
break;
}
}
function sendMessageToWorker(source, destination, value, transferList, memory) {
// We are on the main thread, we can directly process the message
if (destination === 0) {
receiveMessageFromWorker(source, value, memory);
return;
}
// Search the port to the target thread
const port = threadsPorts.get(destination);
if (!port) {
const status = new Int32Array(memory);
AtomicsStore(status, WORKER_MESSAGING_RESULT_INDEX, WORKER_MESSAGING_RESULT_NO_LISTENERS);
AtomicsStore(status, WORKER_MESSAGING_STATUS_INDEX, 1);
AtomicsNotify(status, WORKER_MESSAGING_STATUS_INDEX, 1);
return;
}
port.postMessage(
{
type: messageTypes.RECEIVE_MESSAGE_FROM_WORKER,
source,
destination,
value,
memory,
},
transferList,
);
}
function receiveMessageFromWorker(source, value, memory) {
let response = WORKER_MESSAGING_RESULT_NO_LISTENERS;
try {
if (process.emit('workerMessage', value, source)) {
response = WORKER_MESSAGING_RESULT_DELIVERED;
}
} catch {
response = WORKER_MESSAGING_RESULT_LISTENER_ERROR;
}
// Populate the result
const status = new Int32Array(memory);
AtomicsStore(status, WORKER_MESSAGING_RESULT_INDEX, response);
AtomicsStore(status, WORKER_MESSAGING_STATUS_INDEX, 1);
AtomicsNotify(status, WORKER_MESSAGING_STATUS_INDEX, 1);
}
function createMainThreadPort(threadId) {
// Create a channel that links the new thread to the main thread
const {
port1: mainThreadPortToMain,
port2: mainThreadPortToThread,
} = new MessageChannel();
const registrationMessage = {
type: messageTypes.REGISTER_MAIN_THREAD_PORT,
threadId,
port: mainThreadPortToMain,
};
if (isMainThread) {
handleMessageFromThread(registrationMessage);
} else {
mainThreadPort.postMessage(registrationMessage, [mainThreadPortToMain]);
}
return mainThreadPortToThread;
}
function destroyMainThreadPort(threadId) {
const unregistrationMessage = {
type: messageTypes.UNREGISTER_MAIN_THREAD_PORT,
threadId,
};
if (isMainThread) {
handleMessageFromThread(unregistrationMessage);
} else {
mainThreadPort.postMessage(unregistrationMessage);
}
}
function setupMainThreadPort(port) {
mainThreadPort = port;
mainThreadPort.on('message', handleMessageFromMainThread);
// Never block the process on this port
mainThreadPort.unref();
}
async function postMessageToThread(threadId, value, transferList, timeout) {
if (typeof transferList === 'number' && typeof timeout === 'undefined') {
timeout = transferList;
transferList = [];
}
if (typeof timeout !== 'undefined') {
validateNumber(timeout, 'timeout', 0);
}
if (threadId === currentThreadId) {
throw new ERR_WORKER_MESSAGING_SAME_THREAD();
}
const memory = new SharedArrayBuffer(WORKER_MESSAGING_SHARED_DATA);
const status = new Int32Array(memory);
const promise = AtomicsWaitAsync(status, WORKER_MESSAGING_STATUS_INDEX, 0, timeout).value;
const message = {
type: messageTypes.SEND_MESSAGE_TO_WORKER,
source: currentThreadId,
destination: threadId,
value,
memory,
transferList,
};
if (isMainThread) {
handleMessageFromThread(message);
} else {
mainThreadPort.postMessage(message, transferList);
}
// Wait for the response
const response = await promise;
if (response === 'timed-out') {
throw new ERR_WORKER_MESSAGING_TIMEOUT();
} else if (status[WORKER_MESSAGING_RESULT_INDEX] === WORKER_MESSAGING_RESULT_NO_LISTENERS) {
throw new ERR_WORKER_MESSAGING_FAILED();
} else if (status[WORKER_MESSAGING_RESULT_INDEX] === WORKER_MESSAGING_RESULT_LISTENER_ERROR) {
throw new ERR_WORKER_MESSAGING_ERRORED();
}
}
module.exports = {
createMainThreadPort,
destroyMainThreadPort,
setupMainThreadPort,
postMessageToThread,
};