Repository: nodejs/node
File: lib/internal/modules/esm/worker.js (JavaScript)

Code before:
      AtomicsNotify(operationLock, WORKER_TO_MAIN_THREAD_NOTIFICATION);
    }
    unsettledResponsePorts.clear();

    AtomicsAdd(lock, WORKER_TO_MAIN_THREAD_NOTIFICATION, 1);
    AtomicsNotify(lock, WORKER_TO_MAIN_THREAD_NOTIFICATION);

    // Attach back the event handler.
    syncCommPort.on('message', handleMessage);
    // Also check synchronously for a message, in case it's already there.
    clearImmediate(immediate);
    checkForMessages();
    // We don't need the sync check after this tick, as we already have added the event handler.
    clearImmediate(immediate);
    // Add some work for next tick so the worker cannot exit.
    setImmediate(() => {});
  });

  const allThreadRegisteredHandlerPorts = [];
  /**
   * @callback registerHandler
   * @param {MessagePort} toWorkerThread - Upon Worker creation a message channel between the new Worker
   * and the Hooks thread is being initialized. This is the MessagePort that the Hooks thread will use post
   * messages to the worker. The other MessagePort is passed to the new Worker itself via LOAD_SCRIPT message
   */
  function registerHandler(toWorkerThread) {
    toWorkerThread.on('message', handleMessage);
    ArrayPrototypePush(allThreadRegisteredHandlerPorts, toWorkerThread);
  }

  function getMessageHandler(method) {
    if (method === '#registerWorkerClient') {
      return registerHandler;
    }
    return hooks[method];
  }

  /**
   * Handles incoming messages from the main thread or other workers.
   * @param {object} options - The options object.
   * @param {string} options.method - The name of the hook.
   * @param {Array} options.args - The arguments to pass to the method.
   * @param {MessagePort} options.port - The message port to use for communication.
   * @param {Int32Array} options.lock - The shared memory where the caller expects to get awaken.
   */
  async function handleMessage({ method, args, port, lock: msgLock }) {
    // Each potential exception needs to be caught individually so that the correct error is sent to
    // the main thread.
    let hasError = false;
    let shouldRemoveGlobalErrorHandler = false;
    assert(typeof getMessageHandler(method) === 'function');

Review comment (suggestion):
Is there no unregister needed if a worker ends?
My feeling is that `allThreadRegisteredHandlerPorts` just grows.

Code after:
      AtomicsAdd(operationLock, WORKER_TO_MAIN_THREAD_NOTIFICATION, 1);
      AtomicsNotify(operationLock, WORKER_TO_MAIN_THREAD_NOTIFICATION);
    }
    unsettledResponsePorts.clear();

    AtomicsAdd(lock, WORKER_TO_MAIN_THREAD_NOTIFICATION, 1);
    AtomicsNotify(lock, WORKER_TO_MAIN_THREAD_NOTIFICATION);

    // Attach back the event handler.
    syncCommPort.on('message', handleMessage);
    // Also check synchronously for a message, in case it's already there.
    clearImmediate(immediate);
    checkForMessages();
    // We don't need the sync check after this tick, as we already have added the event handler.
    clearImmediate(immediate);
    // Add some work for next tick so the worker cannot exit.
    setImmediate(() => {});
  });

  let allThreadRegisteredHandlerPorts = [];
  /**
   * @callback registerHandler
   * @param {MessagePort} toWorkerThread - Upon Worker creation a message channel between the new Worker
   * and the Hooks thread is being initialized. This is the MessagePort that the Hooks thread will use post
   * messages to the worker. The other MessagePort is passed to the new Worker itself via LOAD_SCRIPT message
   */
  function registerHandler(toWorkerThread, registeredThreadId) {
    toWorkerThread.on('message', handleMessage);
    ArrayPrototypePush(allThreadRegisteredHandlerPorts, { port: toWorkerThread, registeredThreadId });
  }

  /**
   * @callback registerHandler
   * @param {number} unregisteredThreadId - the thread id of the worker thread that is being unregistered
   * from the Hooks Thread
   */
  function unregisterHandler(unregisteredThreadId) {
    allThreadRegisteredHandlerPorts = ArrayPrototypeFilter(
      allThreadRegisteredHandlerPorts, (el) => el.registeredThreadId !== unregisteredThreadId);
  }

  function getMessageHandler(method) {
    if (method === '#registerWorkerClient') {
      return registerHandler;
    }
    if (method === '#unregisterWorkerClient') {
      return unregisterHandler;
    }
    return hooks[method];
  }