UNPKG

10.5 kBJavaScriptView Raw
1"use strict";
2/// <reference lib="dom" />
3// tslint:disable function-constructor no-eval no-duplicate-super max-classes-per-file
4var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
5 if (k2 === undefined) k2 = k;
6 Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
7}) : (function(o, m, k, k2) {
8 if (k2 === undefined) k2 = k;
9 o[k2] = m[k];
10}));
11var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
12 Object.defineProperty(o, "default", { enumerable: true, value: v });
13}) : function(o, v) {
14 o["default"] = v;
15});
16var __importStar = (this && this.__importStar) || function (mod) {
17 if (mod && mod.__esModule) return mod;
18 var result = {};
19 if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
20 __setModuleDefault(result, mod);
21 return result;
22};
23var __importDefault = (this && this.__importDefault) || function (mod) {
24 return (mod && mod.__esModule) ? mod : { "default": mod };
25};
26Object.defineProperty(exports, "__esModule", { value: true });
27exports.isWorkerRuntime = exports.getWorkerImplementation = exports.defaultPoolSize = void 0;
28const callsites_1 = __importDefault(require("callsites"));
29const events_1 = require("events");
30const os_1 = require("os");
31const path = __importStar(require("path"));
32const url_1 = require("url");
33let tsNodeAvailable;
34exports.defaultPoolSize = os_1.cpus().length;
35function detectTsNode() {
36 if (typeof __non_webpack_require__ === "function") {
37 // Webpack build: => No ts-node required or possible
38 return false;
39 }
40 if (tsNodeAvailable) {
41 return tsNodeAvailable;
42 }
43 try {
44 eval("require").resolve("ts-node");
45 tsNodeAvailable = true;
46 }
47 catch (error) {
48 if (error && error.code === "MODULE_NOT_FOUND") {
49 tsNodeAvailable = false;
50 }
51 else {
52 // Re-throw
53 throw error;
54 }
55 }
56 return tsNodeAvailable;
57}
58function createTsNodeModule(scriptPath) {
59 const content = `
60 require("ts-node/register/transpile-only");
61 require(${JSON.stringify(scriptPath)});
62 `;
63 return content;
64}
65function rebaseScriptPath(scriptPath, ignoreRegex) {
66 const parentCallSite = callsites_1.default().find((callsite) => {
67 const filename = callsite.getFileName();
68 return Boolean(filename &&
69 !filename.match(ignoreRegex) &&
70 !filename.match(/[\/\\]master[\/\\]implementation/) &&
71 !filename.match(/^internal\/process/));
72 });
73 const rawCallerPath = parentCallSite ? parentCallSite.getFileName() : null;
74 let callerPath = rawCallerPath ? rawCallerPath : null;
75 if (callerPath && callerPath.startsWith('file:')) {
76 callerPath = url_1.fileURLToPath(callerPath);
77 }
78 const rebasedScriptPath = callerPath ? path.join(path.dirname(callerPath), scriptPath) : scriptPath;
79 return rebasedScriptPath;
80}
81function resolveScriptPath(scriptPath, baseURL) {
82 const makeRelative = (filePath) => {
83 // eval() hack is also webpack-related
84 return path.isAbsolute(filePath) ? filePath : path.join(baseURL || eval("__dirname"), filePath);
85 };
86 const workerFilePath = typeof __non_webpack_require__ === "function"
87 ? __non_webpack_require__.resolve(makeRelative(scriptPath))
88 : eval("require").resolve(makeRelative(rebaseScriptPath(scriptPath, /[\/\\]worker_threads[\/\\]/)));
89 return workerFilePath;
90}
91function initWorkerThreadsWorker() {
92 // Webpack hack
93 const NativeWorker = typeof __non_webpack_require__ === "function"
94 ? __non_webpack_require__("worker_threads").Worker
95 : eval("require")("worker_threads").Worker;
96 let allWorkers = [];
97 class Worker extends NativeWorker {
98 constructor(scriptPath, options) {
99 const resolvedScriptPath = options && options.fromSource
100 ? null
101 : resolveScriptPath(scriptPath, (options || {})._baseURL);
102 if (!resolvedScriptPath) {
103 // `options.fromSource` is true
104 const sourceCode = scriptPath;
105 super(sourceCode, Object.assign(Object.assign({}, options), { eval: true }));
106 }
107 else if (resolvedScriptPath.match(/\.tsx?$/i) && detectTsNode()) {
108 super(createTsNodeModule(resolvedScriptPath), Object.assign(Object.assign({}, options), { eval: true }));
109 }
110 else if (resolvedScriptPath.match(/\.asar[\/\\]/)) {
111 // See <https://github.com/andywer/threads-plugin/issues/17>
112 super(resolvedScriptPath.replace(/\.asar([\/\\])/, ".asar.unpacked$1"), options);
113 }
114 else {
115 super(resolvedScriptPath, options);
116 }
117 this.mappedEventListeners = new WeakMap();
118 allWorkers.push(this);
119 }
120 addEventListener(eventName, rawListener) {
121 const listener = (message) => {
122 rawListener({ data: message });
123 };
124 this.mappedEventListeners.set(rawListener, listener);
125 this.on(eventName, listener);
126 }
127 removeEventListener(eventName, rawListener) {
128 const listener = this.mappedEventListeners.get(rawListener) || rawListener;
129 this.off(eventName, listener);
130 }
131 }
132 const terminateWorkersAndMaster = () => {
133 // we should terminate all workers and then gracefully shutdown self process
134 Promise.all(allWorkers.map(worker => worker.terminate())).then(() => process.exit(0), () => process.exit(1));
135 allWorkers = [];
136 };
137 // Take care to not leave orphaned processes behind. See #147.
138 process.on("SIGINT", () => terminateWorkersAndMaster());
139 process.on("SIGTERM", () => terminateWorkersAndMaster());
140 class BlobWorker extends Worker {
141 constructor(blob, options) {
142 super(Buffer.from(blob).toString("utf-8"), Object.assign(Object.assign({}, options), { fromSource: true }));
143 }
144 static fromText(source, options) {
145 return new Worker(source, Object.assign(Object.assign({}, options), { fromSource: true }));
146 }
147 }
148 return {
149 blob: BlobWorker,
150 default: Worker
151 };
152}
153function initTinyWorker() {
154 const TinyWorker = require("tiny-worker");
155 let allWorkers = [];
156 class Worker extends TinyWorker {
157 constructor(scriptPath, options) {
158 // Need to apply a work-around for Windows or it will choke upon the absolute path
159 // (`Error [ERR_INVALID_PROTOCOL]: Protocol 'c:' not supported`)
160 const resolvedScriptPath = options && options.fromSource
161 ? null
162 : process.platform === "win32"
163 ? `file:///${resolveScriptPath(scriptPath).replace(/\\/g, "/")}`
164 : resolveScriptPath(scriptPath);
165 if (!resolvedScriptPath) {
166 // `options.fromSource` is true
167 const sourceCode = scriptPath;
168 super(new Function(sourceCode), [], { esm: true });
169 }
170 else if (resolvedScriptPath.match(/\.tsx?$/i) && detectTsNode()) {
171 super(new Function(createTsNodeModule(resolveScriptPath(scriptPath))), [], { esm: true });
172 }
173 else if (resolvedScriptPath.match(/\.asar[\/\\]/)) {
174 // See <https://github.com/andywer/threads-plugin/issues/17>
175 super(resolvedScriptPath.replace(/\.asar([\/\\])/, ".asar.unpacked$1"), [], { esm: true });
176 }
177 else {
178 super(resolvedScriptPath, [], { esm: true });
179 }
180 allWorkers.push(this);
181 this.emitter = new events_1.EventEmitter();
182 this.onerror = (error) => this.emitter.emit("error", error);
183 this.onmessage = (message) => this.emitter.emit("message", message);
184 }
185 addEventListener(eventName, listener) {
186 this.emitter.addListener(eventName, listener);
187 }
188 removeEventListener(eventName, listener) {
189 this.emitter.removeListener(eventName, listener);
190 }
191 terminate() {
192 allWorkers = allWorkers.filter(worker => worker !== this);
193 return super.terminate();
194 }
195 }
196 const terminateWorkersAndMaster = () => {
197 // we should terminate all workers and then gracefully shutdown self process
198 Promise.all(allWorkers.map(worker => worker.terminate())).then(() => process.exit(0), () => process.exit(1));
199 allWorkers = [];
200 };
201 // Take care to not leave orphaned processes behind
202 // See <https://github.com/avoidwork/tiny-worker#faq>
203 process.on("SIGINT", () => terminateWorkersAndMaster());
204 process.on("SIGTERM", () => terminateWorkersAndMaster());
205 class BlobWorker extends Worker {
206 constructor(blob, options) {
207 super(Buffer.from(blob).toString("utf-8"), Object.assign(Object.assign({}, options), { fromSource: true }));
208 }
209 static fromText(source, options) {
210 return new Worker(source, Object.assign(Object.assign({}, options), { fromSource: true }));
211 }
212 }
213 return {
214 blob: BlobWorker,
215 default: Worker
216 };
217}
218let implementation;
219let isTinyWorker;
220function selectWorkerImplementation() {
221 try {
222 isTinyWorker = false;
223 return initWorkerThreadsWorker();
224 }
225 catch (error) {
226 // tslint:disable-next-line no-console
227 console.debug("Node worker_threads not available. Trying to fall back to tiny-worker polyfill...");
228 isTinyWorker = true;
229 return initTinyWorker();
230 }
231}
232function getWorkerImplementation() {
233 if (!implementation) {
234 implementation = selectWorkerImplementation();
235 }
236 return implementation;
237}
238exports.getWorkerImplementation = getWorkerImplementation;
239function isWorkerRuntime() {
240 if (isTinyWorker) {
241 return typeof self !== "undefined" && self.postMessage ? true : false;
242 }
243 else {
244 // Webpack hack
245 const isMainThread = typeof __non_webpack_require__ === "function"
246 ? __non_webpack_require__("worker_threads").isMainThread
247 : eval("require")("worker_threads").isMainThread;
248 return !isMainThread;
249 }
250}
251exports.isWorkerRuntime = isWorkerRuntime;