worker.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. "use strict";
  2. import {
  3. isMovable,
  4. kRequestCountField,
  5. kResponseCountField,
  6. kTransferable,
  7. kValue
  8. } from "./chunk-QYFJIXNO.js";
  9. // src/worker.ts
  10. import {
  11. parentPort,
  12. receiveMessageOnPort,
  13. workerData as tinypoolData
  14. } from "worker_threads";
  15. import { pathToFileURL } from "url";
  16. // src/utils.ts
  17. function stdout() {
  18. return console._stdout || process.stdout || void 0;
  19. }
  20. function stderr() {
  21. return console._stderr || process.stderr || void 0;
  22. }
  23. // src/worker.ts
  24. var [tinypoolPrivateData, workerData] = tinypoolData;
  25. process.__tinypool_state__ = {
  26. isWorkerThread: true,
  27. workerData,
  28. workerId: tinypoolPrivateData.workerId
  29. };
  30. var handlerCache = /* @__PURE__ */ new Map();
  31. var useAtomics = process.env.PISCINA_DISABLE_ATOMICS !== "1";
  32. var importESMCached;
  33. function getImportESM() {
  34. if (importESMCached === void 0) {
  35. importESMCached = new Function("specifier", "return import(specifier)");
  36. }
  37. return importESMCached;
  38. }
  39. async function getHandler(filename, name) {
  40. let handler = handlerCache.get(`${filename}/${name}`);
  41. if (handler !== void 0) {
  42. return handler;
  43. }
  44. try {
  45. const handlerModule = await import(filename);
  46. handler = typeof handlerModule.default !== "function" && handlerModule.default || handlerModule;
  47. if (typeof handler !== "function") {
  48. handler = await handler[name];
  49. }
  50. } catch {
  51. }
  52. if (typeof handler !== "function") {
  53. handler = await getImportESM()(pathToFileURL(filename).href);
  54. if (typeof handler !== "function") {
  55. handler = await handler[name];
  56. }
  57. }
  58. if (typeof handler !== "function") {
  59. return null;
  60. }
  61. if (handlerCache.size > 1e3) {
  62. const [[key]] = handlerCache;
  63. handlerCache.delete(key);
  64. }
  65. handlerCache.set(`${filename}/${name}`, handler);
  66. return handler;
  67. }
  68. parentPort.on("message", (message) => {
  69. useAtomics = process.env.PISCINA_DISABLE_ATOMICS === "1" ? false : message.useAtomics;
  70. const { port, sharedBuffer, filename, name } = message;
  71. (async function() {
  72. if (filename !== null) {
  73. await getHandler(filename, name);
  74. }
  75. const readyMessage = { ready: true };
  76. parentPort.postMessage(readyMessage);
  77. port.on("message", onMessage.bind(null, port, sharedBuffer));
  78. atomicsWaitLoop(port, sharedBuffer);
  79. })().catch(throwInNextTick);
  80. });
  81. var currentTasks = 0;
  82. var lastSeenRequestCount = 0;
  83. function atomicsWaitLoop(port, sharedBuffer) {
  84. if (!useAtomics)
  85. return;
  86. while (currentTasks === 0) {
  87. Atomics.wait(sharedBuffer, kRequestCountField, lastSeenRequestCount);
  88. lastSeenRequestCount = Atomics.load(sharedBuffer, kRequestCountField);
  89. let entry;
  90. while ((entry = receiveMessageOnPort(port)) !== void 0) {
  91. onMessage(port, sharedBuffer, entry.message);
  92. }
  93. }
  94. }
  95. function onMessage(port, sharedBuffer, message) {
  96. currentTasks++;
  97. const { taskId, task, filename, name } = message;
  98. (async function() {
  99. let response;
  100. let transferList = [];
  101. try {
  102. const handler = await getHandler(filename, name);
  103. if (handler === null) {
  104. throw new Error(`No handler function exported from ${filename}`);
  105. }
  106. let result = await handler(task);
  107. if (isMovable(result)) {
  108. transferList = transferList.concat(result[kTransferable]);
  109. result = result[kValue];
  110. }
  111. response = {
  112. taskId,
  113. result,
  114. error: null
  115. };
  116. if (stdout()?.writableLength > 0) {
  117. await new Promise((resolve) => process.stdout.write("", resolve));
  118. }
  119. if (stderr()?.writableLength > 0) {
  120. await new Promise((resolve) => process.stderr.write("", resolve));
  121. }
  122. } catch (error) {
  123. response = {
  124. taskId,
  125. result: null,
  126. error
  127. };
  128. }
  129. currentTasks--;
  130. port.postMessage(response, transferList);
  131. Atomics.add(sharedBuffer, kResponseCountField, 1);
  132. atomicsWaitLoop(port, sharedBuffer);
  133. })().catch(throwInNextTick);
  134. }
  135. function throwInNextTick(error) {
  136. process.nextTick(() => {
  137. throw error;
  138. });
  139. }