@xylabs/threads 3.5.0 → 3.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/common.js +3 -5
- package/{dist-esm → dist/esm}/common.js +0 -1
- package/{dist-esm → dist/esm}/index.js +0 -1
- package/{dist-esm → dist/esm}/master/get-bundle-url.browser.js +0 -2
- package/{dist-esm → dist/esm}/master/implementation.browser.js +1 -5
- package/{dist-esm → dist/esm}/master/implementation.js +0 -8
- package/{dist-esm → dist/esm}/master/implementation.node.js +1 -27
- package/{dist-esm → dist/esm}/master/index.js +0 -2
- package/{dist-esm → dist/esm}/master/invocation-proxy.js +0 -8
- package/{dist-esm → dist/esm}/master/pool-types.js +0 -1
- package/{dist-esm → dist/esm}/master/pool.js +2 -21
- package/{dist-esm → dist/esm}/master/register.js +0 -1
- package/{dist-esm → dist/esm}/master/spawn.js +0 -13
- package/{dist-esm → dist/esm}/master/thread.js +0 -4
- package/{dist-esm → dist/esm}/observable-promise.js +0 -24
- package/{dist-esm → dist/esm}/observable.js +0 -10
- package/{dist-esm → dist/esm}/ponyfills.js +0 -1
- package/{dist-esm → dist/esm}/promise.js +0 -5
- package/{dist-esm → dist/esm}/transferable.js +0 -2
- package/{dist-esm → dist/esm}/types/master.js +0 -4
- package/{dist-esm → dist/esm}/types/messages.js +0 -4
- package/{dist-esm → dist/esm}/worker/bundle-entry.js +0 -1
- package/{dist-esm → dist/esm}/worker/implementation.browser.js +0 -4
- package/{dist-esm → dist/esm}/worker/implementation.js +0 -5
- package/{dist-esm → dist/esm}/worker/implementation.tiny-worker.js +0 -7
- package/{dist-esm → dist/esm}/worker/implementation.worker_threads.js +0 -1
- package/{dist-esm → dist/esm}/worker/index.js +1 -20
- package/{dist-esm → dist/esm}/worker_threads.js +0 -4
- package/dist/index.js +0 -1
- package/dist/master/get-bundle-url.browser.js +2 -5
- package/dist/master/implementation.browser.js +4 -8
- package/dist/master/implementation.d.ts +0 -2
- package/dist/master/implementation.js +0 -8
- package/dist/master/implementation.node.d.ts +0 -1
- package/dist/master/implementation.node.js +5 -31
- package/dist/master/index.d.ts +0 -2
- package/dist/master/index.js +0 -2
- package/dist/master/invocation-proxy.js +2 -11
- package/dist/master/pool-types.d.ts +0 -14
- package/dist/master/pool-types.js +0 -1
- package/dist/master/pool.d.ts +0 -41
- package/dist/master/pool.js +2 -21
- package/dist/master/register.js +0 -1
- package/dist/master/spawn.d.ts +0 -9
- package/dist/master/spawn.js +1 -15
- package/dist/master/thread.d.ts +2 -6
- package/dist/master/thread.js +0 -4
- package/dist/observable-promise.d.ts +0 -13
- package/dist/observable-promise.js +0 -24
- package/dist/observable.d.ts +0 -9
- package/dist/observable.js +0 -10
- package/dist/ponyfills.js +1 -3
- package/dist/promise.d.ts +0 -4
- package/dist/promise.js +1 -7
- package/dist/serializers.js +2 -2
- package/dist/transferable.d.ts +0 -33
- package/dist/transferable.js +2 -5
- package/dist/types/master.d.ts +0 -14
- package/dist/types/master.js +0 -4
- package/dist/types/messages.js +0 -4
- package/dist/worker/bundle-entry.js +0 -1
- package/dist/worker/implementation.browser.d.ts +1 -2
- package/dist/worker/implementation.browser.js +0 -4
- package/dist/worker/implementation.js +0 -5
- package/dist/worker/implementation.tiny-worker.d.ts +1 -2
- package/dist/worker/implementation.tiny-worker.js +0 -7
- package/dist/worker/implementation.worker_threads.d.ts +1 -1
- package/dist/worker/implementation.worker_threads.js +0 -1
- package/dist/worker/index.d.ts +0 -8
- package/dist/worker/index.js +4 -23
- package/dist/worker_threads.js +1 -5
- package/index.mjs +0 -1
- package/observable.d.ts +0 -1
- package/observable.js +0 -2
- package/observable.mjs +0 -1
- package/package.json +18 -19
- package/register.d.ts +0 -2
- package/register.js +0 -2
- package/register.mjs +0 -1
- package/rollup.config.js +0 -1
- package/src/index.ts +0 -1
- package/src/master/implementation.node.ts +1 -1
- package/src/master/pool.ts +2 -1
- package/src/master/spawn.ts +1 -2
- package/src/observable-promise.ts +1 -0
- package/src/worker/implementation.browser.ts +1 -1
- package/src/worker/implementation.tiny-worker.ts +1 -1
- package/src/worker/implementation.ts +1 -1
- package/src/worker/implementation.worker_threads.ts +1 -1
- package/src/worker/index.ts +2 -2
- package/src/worker_threads.ts +1 -1
- package/test/lib/serialization.ts +1 -1
- package/test/observable-promise.test.ts +0 -1
- package/test/observable.test.ts +1 -1
- package/test/pool.test.ts +3 -2
- package/test/serialization.test.ts +0 -1
- package/test/spawn.chromium.mocha.ts +0 -1
- package/test/spawn.test.ts +2 -3
- package/test/streaming.test.ts +0 -1
- package/test/transferables.test.ts +1 -1
- package/test/workers/arraybuffer-xor.ts +0 -1
- package/test/workers/count-to-five.ts +0 -1
- package/test/workers/counter.ts +0 -1
- package/test/workers/faulty-function.ts +0 -1
- package/test/workers/hello-world.ts +0 -1
- package/test/workers/increment.ts +0 -1
- package/test/workers/minmax.ts +0 -1
- package/test/workers/serialization.ts +1 -1
- package/test-tooling/rollup/app.js +0 -1
- package/test-tooling/rollup/rollup.config.ts +1 -1
- package/test-tooling/rollup/worker.js +2 -2
- package/test-tooling/tsconfig/minimal.ts +1 -1
- package/test-tooling/webpack/addition-worker.ts +0 -1
- package/test-tooling/webpack/app-with-inlined-worker.ts +3 -3
- package/test-tooling/webpack/app.ts +2 -2
- package/test-tooling/webpack/pool-worker.ts +0 -1
- package/test-tooling/webpack/webpack.node.config.js +0 -1
- package/test-tooling/webpack/webpack.web.config.js +0 -1
- package/types/is-observable.d.ts +1 -1
- package/worker.d.ts +0 -1
- package/worker.js +0 -2
- package/worker.mjs +0 -1
- /package/{dist-esm → dist/esm}/serializers.js +0 -0
- /package/{dist-esm → dist/esm}/symbols.js +0 -0
- /package/{dist-esm → dist/esm}/types/worker.js +0 -0
package/dist/common.js
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
|
|
3
|
+
exports.registerSerializer = registerSerializer;
|
|
4
|
+
exports.deserialize = deserialize;
|
|
5
|
+
exports.serialize = serialize;
|
|
5
6
|
const serializers_1 = require("./serializers");
|
|
6
7
|
let registeredSerializer = serializers_1.DefaultSerializer;
|
|
7
8
|
function registerSerializer(serializer) {
|
|
8
9
|
registeredSerializer = (0, serializers_1.extendSerializer)(registeredSerializer, serializer);
|
|
9
10
|
}
|
|
10
|
-
exports.registerSerializer = registerSerializer;
|
|
11
11
|
function deserialize(message) {
|
|
12
12
|
return registeredSerializer.deserialize(message);
|
|
13
13
|
}
|
|
14
|
-
exports.deserialize = deserialize;
|
|
15
14
|
function serialize(input) {
|
|
16
15
|
return registeredSerializer.serialize(input);
|
|
17
16
|
}
|
|
18
|
-
exports.serialize = serialize;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// Source: <https://github.com/parcel-bundler/parcel/blob/master/packages/core/parcel-bundler/src/builtins/bundle-url.js>
|
|
2
1
|
let bundleURL;
|
|
3
2
|
function getBundleURLCached() {
|
|
4
3
|
if (!bundleURL) {
|
|
@@ -7,7 +6,6 @@ function getBundleURLCached() {
|
|
|
7
6
|
return bundleURL;
|
|
8
7
|
}
|
|
9
8
|
function getBundleURL() {
|
|
10
|
-
// Attempt to find the URL of the current script and use that as the base URL
|
|
11
9
|
try {
|
|
12
10
|
throw new Error('getBundleURL failed');
|
|
13
11
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// tslint:disable max-classes-per-file
|
|
2
1
|
import { getBundleURL } from './get-bundle-url.browser';
|
|
3
2
|
export const defaultPoolSize = typeof navigator !== 'undefined' && navigator.hardwareConcurrency ? navigator.hardwareConcurrency : 4;
|
|
4
3
|
const isAbsoluteURL = (value) => /^[A-Za-z][\d+.A-Za-z\-]*:/.test(value);
|
|
@@ -8,8 +7,6 @@ function createSourceBlobURL(code) {
|
|
|
8
7
|
}
|
|
9
8
|
function selectWorkerImplementation() {
|
|
10
9
|
if (typeof Worker === 'undefined') {
|
|
11
|
-
// Might happen on Safari, for instance
|
|
12
|
-
// The idea is to only fail if the constructor is actually used
|
|
13
10
|
return class NoWebWorker {
|
|
14
11
|
constructor() {
|
|
15
12
|
throw new Error("No web worker implementation available. You might have tried to spawn a worker within a worker in a browser that doesn't support workers in workers.");
|
|
@@ -28,8 +25,7 @@ function selectWorkerImplementation() {
|
|
|
28
25
|
}
|
|
29
26
|
}
|
|
30
27
|
if (typeof url === 'string' &&
|
|
31
|
-
isAbsoluteURL(url) &&
|
|
32
|
-
// to circumvent worker CORS restrictions
|
|
28
|
+
isAbsoluteURL(url) &&
|
|
33
29
|
(options?.CORSWorkaround ?? true)) {
|
|
34
30
|
url = createSourceBlobURL(`importScripts(${JSON.stringify(url)});`);
|
|
35
31
|
}
|
|
@@ -1,15 +1,7 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* This file is only a stub to make './implementation' resolve to the right module.
|
|
3
|
-
*/
|
|
4
|
-
// We alias `src/master/implementation` to `src/master/implementation.browser` for web
|
|
5
|
-
// browsers already in the package.json, so if get here, it's safe to pass-through the
|
|
6
|
-
// node implementation
|
|
7
1
|
import * as BrowserImplementation from './implementation.browser';
|
|
8
2
|
import * as NodeImplementation from './implementation.node';
|
|
9
3
|
const runningInNode = typeof process !== 'undefined' && process.arch !== 'browser' && 'pid' in process;
|
|
10
4
|
const implementation = runningInNode ? NodeImplementation : BrowserImplementation;
|
|
11
|
-
/** Default size of pools. Depending on the platform the value might vary from device to device. */
|
|
12
5
|
export const defaultPoolSize = implementation.defaultPoolSize;
|
|
13
6
|
export const getWorkerImplementation = implementation.getWorkerImplementation;
|
|
14
|
-
/** Returns `true` if this code is currently running in a worker. */
|
|
15
7
|
export const isWorkerRuntime = implementation.isWorkerRuntime;
|
|
@@ -1,22 +1,12 @@
|
|
|
1
|
-
/* eslint-disable unicorn/prefer-logical-operator-over-ternary */
|
|
2
|
-
/* eslint-disable unicorn/prefer-regexp-test */
|
|
3
|
-
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
4
|
-
/* eslint-disable unicorn/prefer-add-event-listener */
|
|
5
|
-
/* eslint-disable unicorn/prefer-event-target */
|
|
6
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
7
|
-
/* eslint-disable unicorn/text-encoding-identifier-case */
|
|
8
|
-
/* eslint-disable unicorn/no-process-exit */
|
|
9
|
-
/// <reference lib="dom" />
|
|
10
1
|
import { EventEmitter } from 'node:events';
|
|
11
2
|
import { cpus } from 'node:os';
|
|
12
3
|
import path from 'node:path';
|
|
13
4
|
import { fileURLToPath } from 'node:url';
|
|
14
|
-
import getCallsites from 'callsites';
|
|
5
|
+
import getCallsites from 'callsites-3-1-0';
|
|
15
6
|
let tsNodeAvailable;
|
|
16
7
|
export const defaultPoolSize = cpus().length;
|
|
17
8
|
function detectTsNode() {
|
|
18
9
|
if (typeof __non_webpack_require__ === 'function') {
|
|
19
|
-
// Webpack build: => No ts-node required or possible
|
|
20
10
|
return false;
|
|
21
11
|
}
|
|
22
12
|
if (tsNodeAvailable) {
|
|
@@ -31,7 +21,6 @@ function detectTsNode() {
|
|
|
31
21
|
tsNodeAvailable = false;
|
|
32
22
|
}
|
|
33
23
|
else {
|
|
34
|
-
// Re-throw
|
|
35
24
|
throw error;
|
|
36
25
|
}
|
|
37
26
|
}
|
|
@@ -59,7 +48,6 @@ function rebaseScriptPath(scriptPath, ignoreRegex) {
|
|
|
59
48
|
}
|
|
60
49
|
function resolveScriptPath(scriptPath, baseURL) {
|
|
61
50
|
const makeRelative = (filePath) => {
|
|
62
|
-
// eval() hack is also webpack-related
|
|
63
51
|
return path.isAbsolute(filePath) ? filePath : path.join(baseURL || eval('__dirname'), filePath);
|
|
64
52
|
};
|
|
65
53
|
const workerFilePath = typeof __non_webpack_require__ === 'function' ?
|
|
@@ -68,7 +56,6 @@ function resolveScriptPath(scriptPath, baseURL) {
|
|
|
68
56
|
return workerFilePath;
|
|
69
57
|
}
|
|
70
58
|
function initWorkerThreadsWorker() {
|
|
71
|
-
// Webpack hack
|
|
72
59
|
const NativeWorker = typeof __non_webpack_require__ === 'function' ? __non_webpack_require__('worker_threads').Worker : eval('require')('worker_threads').Worker;
|
|
73
60
|
let allWorkers = [];
|
|
74
61
|
class Worker extends NativeWorker {
|
|
@@ -76,7 +63,6 @@ function initWorkerThreadsWorker() {
|
|
|
76
63
|
constructor(scriptPath, options) {
|
|
77
64
|
const resolvedScriptPath = options && options.fromSource ? null : resolveScriptPath(scriptPath, (options || {})._baseURL);
|
|
78
65
|
if (!resolvedScriptPath) {
|
|
79
|
-
// `options.fromSource` is true
|
|
80
66
|
const sourceCode = scriptPath;
|
|
81
67
|
super(sourceCode, { ...options, eval: true });
|
|
82
68
|
}
|
|
@@ -84,7 +70,6 @@ function initWorkerThreadsWorker() {
|
|
|
84
70
|
super(createTsNodeModule(resolvedScriptPath), { ...options, eval: true });
|
|
85
71
|
}
|
|
86
72
|
else if (/\.asar[/\\]/.test(resolvedScriptPath)) {
|
|
87
|
-
// See <https://github.com/andywer/threads-plugin/issues/17>
|
|
88
73
|
super(resolvedScriptPath.replace(/\.asar([/\\])/, '.asar.unpacked$1'), options);
|
|
89
74
|
}
|
|
90
75
|
else {
|
|
@@ -106,11 +91,9 @@ function initWorkerThreadsWorker() {
|
|
|
106
91
|
}
|
|
107
92
|
}
|
|
108
93
|
const terminateWorkersAndMaster = () => {
|
|
109
|
-
// we should terminate all workers and then gracefully shutdown self process
|
|
110
94
|
Promise.all(allWorkers.map((worker) => worker.terminate())).then(() => process.exit(0), () => process.exit(1));
|
|
111
95
|
allWorkers = [];
|
|
112
96
|
};
|
|
113
|
-
// Take care to not leave orphaned processes behind. See #147.
|
|
114
97
|
process.on('SIGINT', () => terminateWorkersAndMaster());
|
|
115
98
|
process.on('SIGTERM', () => terminateWorkersAndMaster());
|
|
116
99
|
class BlobWorker extends Worker {
|
|
@@ -132,13 +115,10 @@ function initTinyWorker() {
|
|
|
132
115
|
class Worker extends TinyWorker {
|
|
133
116
|
emitter;
|
|
134
117
|
constructor(scriptPath, options) {
|
|
135
|
-
// Need to apply a work-around for Windows or it will choke upon the absolute path
|
|
136
|
-
// (`Error [ERR_INVALID_PROTOCOL]: Protocol 'c:' not supported`)
|
|
137
118
|
const resolvedScriptPath = options && options.fromSource ? null
|
|
138
119
|
: process.platform === 'win32' ? `file:///${resolveScriptPath(scriptPath).replaceAll('\\', '/')}`
|
|
139
120
|
: resolveScriptPath(scriptPath);
|
|
140
121
|
if (!resolvedScriptPath) {
|
|
141
|
-
// `options.fromSource` is true
|
|
142
122
|
const sourceCode = scriptPath;
|
|
143
123
|
super(new Function(sourceCode), [], { esm: true });
|
|
144
124
|
}
|
|
@@ -146,7 +126,6 @@ function initTinyWorker() {
|
|
|
146
126
|
super(new Function(createTsNodeModule(resolveScriptPath(scriptPath))), [], { esm: true });
|
|
147
127
|
}
|
|
148
128
|
else if (/\.asar[/\\]/.test(resolvedScriptPath)) {
|
|
149
|
-
// See <https://github.com/andywer/threads-plugin/issues/17>
|
|
150
129
|
super(resolvedScriptPath.replace(/\.asar([/\\])/, '.asar.unpacked$1'), [], { esm: true });
|
|
151
130
|
}
|
|
152
131
|
else {
|
|
@@ -169,12 +148,9 @@ function initTinyWorker() {
|
|
|
169
148
|
}
|
|
170
149
|
}
|
|
171
150
|
const terminateWorkersAndMaster = () => {
|
|
172
|
-
// we should terminate all workers and then gracefully shutdown self process
|
|
173
151
|
Promise.all(allWorkers.map((worker) => worker.terminate())).then(() => process.exit(0), () => process.exit(1));
|
|
174
152
|
allWorkers = [];
|
|
175
153
|
};
|
|
176
|
-
// Take care to not leave orphaned processes behind
|
|
177
|
-
// See <https://github.com/avoidwork/tiny-worker#faq>
|
|
178
154
|
process.on('SIGINT', () => terminateWorkersAndMaster());
|
|
179
155
|
process.on('SIGTERM', () => terminateWorkersAndMaster());
|
|
180
156
|
class BlobWorker extends Worker {
|
|
@@ -198,7 +174,6 @@ function selectWorkerImplementation() {
|
|
|
198
174
|
return initWorkerThreadsWorker();
|
|
199
175
|
}
|
|
200
176
|
catch {
|
|
201
|
-
// tslint:disable-next-line no-console
|
|
202
177
|
console.debug('Node worker_threads not available. Trying to fall back to tiny-worker polyfill...');
|
|
203
178
|
isTinyWorker = true;
|
|
204
179
|
return initTinyWorker();
|
|
@@ -215,7 +190,6 @@ export function isWorkerRuntime() {
|
|
|
215
190
|
return self !== undefined && self['postMessage'] ? true : false;
|
|
216
191
|
}
|
|
217
192
|
else {
|
|
218
|
-
// Webpack hack
|
|
219
193
|
const isMainThread = typeof __non_webpack_require__ === 'function' ?
|
|
220
194
|
__non_webpack_require__('worker_threads').isMainThread
|
|
221
195
|
: eval('require')('worker_threads').isMainThread;
|
|
@@ -2,8 +2,6 @@ import { getWorkerImplementation } from './implementation';
|
|
|
2
2
|
export { Pool } from './pool';
|
|
3
3
|
export { spawn } from './spawn';
|
|
4
4
|
export { Thread } from './thread';
|
|
5
|
-
/** Separate class to spawn workers from source code blobs or strings. */
|
|
6
5
|
export const BlobWorker = getWorkerImplementation().blob;
|
|
7
|
-
/** Worker implementation. Either web worker or a node.js Worker class. */
|
|
8
6
|
export const Worker = getWorkerImplementation().default;
|
|
9
7
|
export { isWorkerRuntime } from './implementation';
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
/*
|
|
3
|
-
* This source file contains the code for proxying calls in the master thread to calls in the workers
|
|
4
|
-
* by `.postMessage()`-ing.
|
|
5
|
-
*
|
|
6
|
-
* Keep in mind that this code can make or break the program's performance! Need to optimize more…
|
|
7
|
-
*/
|
|
8
1
|
import DebugLogger from 'debug';
|
|
9
2
|
import { multicast, Observable } from 'observable-fns';
|
|
10
3
|
import { deserialize, serialize } from '../common';
|
|
@@ -71,7 +64,6 @@ function createObservableForJob(worker, jobUID) {
|
|
|
71
64
|
}
|
|
72
65
|
function prepareArguments(rawArgs) {
|
|
73
66
|
if (rawArgs.length === 0) {
|
|
74
|
-
// Exit early if possible
|
|
75
67
|
return {
|
|
76
68
|
args: [],
|
|
77
69
|
transferables: [],
|
|
@@ -1,11 +1,3 @@
|
|
|
1
|
-
/* eslint-disable unicorn/no-thenable */
|
|
2
|
-
/* eslint-disable @typescript-eslint/no-floating-promises */
|
|
3
|
-
/* eslint-disable require-await */
|
|
4
|
-
/* eslint-disable @typescript-eslint/member-ordering */
|
|
5
|
-
/* eslint-disable unicorn/no-array-reduce */
|
|
6
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
7
|
-
/* eslint-disable import/export */
|
|
8
|
-
/* eslint-disable @typescript-eslint/no-namespace */
|
|
9
1
|
import DebugLogger from 'debug';
|
|
10
2
|
import { multicast, Observable, Subject } from 'observable-fns';
|
|
11
3
|
import { allSettled } from '../ponyfills';
|
|
@@ -99,7 +91,6 @@ class WorkerPool {
|
|
|
99
91
|
const removeTaskFromWorkersRunningTasks = () => {
|
|
100
92
|
worker.runningTasks = worker.runningTasks.filter((someRunPromise) => someRunPromise !== runPromise);
|
|
101
93
|
};
|
|
102
|
-
// Defer task execution by one tick to give handlers time to subscribe
|
|
103
94
|
await delay(0);
|
|
104
95
|
try {
|
|
105
96
|
await this.runPoolTask(worker, task);
|
|
@@ -167,7 +158,7 @@ class WorkerPool {
|
|
|
167
158
|
subscription.unsubscribe();
|
|
168
159
|
resolve(void 0);
|
|
169
160
|
}
|
|
170
|
-
},
|
|
161
|
+
},
|
|
171
162
|
});
|
|
172
163
|
});
|
|
173
164
|
await allSettled(getCurrentlyRunningTasks());
|
|
@@ -188,7 +179,7 @@ class WorkerPool {
|
|
|
188
179
|
subscription.unsubscribe();
|
|
189
180
|
reject(event.error);
|
|
190
181
|
}
|
|
191
|
-
},
|
|
182
|
+
},
|
|
192
183
|
});
|
|
193
184
|
});
|
|
194
185
|
const errors = await Promise.race([settlementPromise, earlyExitPromise]);
|
|
@@ -210,8 +201,6 @@ class WorkerPool {
|
|
|
210
201
|
const taskID = this.nextTaskID++;
|
|
211
202
|
const taskCompletion = this.taskCompletion(taskID);
|
|
212
203
|
taskCompletion.catch((error) => {
|
|
213
|
-
// Prevent unhandled rejections here as we assume the user will use
|
|
214
|
-
// `pool.completed()`, `pool.settled()` or `task.catch()` to handle errors
|
|
215
204
|
this.debug(`Task #${taskID} errored:`, error);
|
|
216
205
|
});
|
|
217
206
|
const task = {
|
|
@@ -255,19 +244,11 @@ class WorkerPool {
|
|
|
255
244
|
await Promise.all(this.workers.map(async (worker) => Thread.terminate(await worker.init)));
|
|
256
245
|
}
|
|
257
246
|
}
|
|
258
|
-
/**
|
|
259
|
-
* Thread pool constructor. Creates a new pool and spawns its worker threads.
|
|
260
|
-
*/
|
|
261
247
|
function PoolConstructor(spawnWorker, optionsOrSize) {
|
|
262
|
-
// The function exists only so we don't need to use `new` to create a pool (we still can, though).
|
|
263
|
-
// If the Pool is a class or not is an implementation detail that should not concern the user.
|
|
264
248
|
return new WorkerPool(spawnWorker, optionsOrSize);
|
|
265
249
|
}
|
|
266
250
|
;
|
|
267
251
|
PoolConstructor.EventType = PoolEventType;
|
|
268
|
-
/**
|
|
269
|
-
* Thread pool constructor. Creates a new pool and spawns its worker threads.
|
|
270
|
-
*/
|
|
271
252
|
export const Pool = PoolConstructor;
|
|
272
253
|
export { PoolEventType } from './pool-types';
|
|
273
254
|
export { Thread } from './thread';
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-floating-promises */
|
|
2
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
1
|
import DebugLogger from 'debug';
|
|
4
2
|
import { Observable } from 'observable-fns';
|
|
5
3
|
import { deserialize } from '../common';
|
|
@@ -74,7 +72,6 @@ function createTerminator(worker) {
|
|
|
74
72
|
const [termination, resolver] = createPromiseWithResolver();
|
|
75
73
|
const terminate = async () => {
|
|
76
74
|
debugThreadUtils('Terminating worker');
|
|
77
|
-
// Newer versions of worker_threads workers return a promise
|
|
78
75
|
await worker.terminate();
|
|
79
76
|
resolver();
|
|
80
77
|
};
|
|
@@ -84,7 +81,6 @@ function setPrivateThreadProps(raw, worker, workerEvents, terminate) {
|
|
|
84
81
|
const workerErrors = workerEvents
|
|
85
82
|
.filter((event) => event.type === WorkerEventType.internalError)
|
|
86
83
|
.map((errorEvent) => errorEvent.error);
|
|
87
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
88
84
|
return Object.assign(raw, {
|
|
89
85
|
[$errors]: workerErrors,
|
|
90
86
|
[$events]: workerEvents,
|
|
@@ -92,15 +88,6 @@ function setPrivateThreadProps(raw, worker, workerEvents, terminate) {
|
|
|
92
88
|
[$worker]: worker,
|
|
93
89
|
});
|
|
94
90
|
}
|
|
95
|
-
/**
|
|
96
|
-
* Spawn a new thread. Takes a fresh worker instance, wraps it in a thin
|
|
97
|
-
* abstraction layer to provide the transparent API and verifies that
|
|
98
|
-
* the worker has initialized successfully.
|
|
99
|
-
*
|
|
100
|
-
* @param worker Instance of `Worker`. Either a web worker, `worker_threads` worker or `tiny-worker` worker.
|
|
101
|
-
* @param [options]
|
|
102
|
-
* @param [options.timeout] Init message timeout. Default: 10000 or set by environment variable.
|
|
103
|
-
*/
|
|
104
91
|
export async function spawn(worker, options) {
|
|
105
92
|
debugSpawn('Initializing new thread');
|
|
106
93
|
const timeout = options && options.timeout ? options.timeout : initMessageTimeout;
|
|
@@ -2,17 +2,13 @@ import { $errors, $events, $terminate } from '../symbols';
|
|
|
2
2
|
function fail(message) {
|
|
3
3
|
throw new Error(message);
|
|
4
4
|
}
|
|
5
|
-
/** Thread utility functions. Use them to manage or inspect a `spawn()`-ed thread. */
|
|
6
5
|
export const Thread = {
|
|
7
|
-
/** Return an observable that can be used to subscribe to all errors happening in the thread. */
|
|
8
6
|
errors(thread) {
|
|
9
7
|
return thread[$errors] || fail('Error observable not found. Make sure to pass a thread instance as returned by the spawn() promise.');
|
|
10
8
|
},
|
|
11
|
-
/** Return an observable that can be used to subscribe to internal events happening in the thread. Useful for debugging. */
|
|
12
9
|
events(thread) {
|
|
13
10
|
return thread[$events] || fail('Events observable not found. Make sure to pass a thread instance as returned by the spawn() promise.');
|
|
14
11
|
},
|
|
15
|
-
/** Terminate a thread. Remember to terminate every thread when you are done using it. */
|
|
16
12
|
terminate(thread) {
|
|
17
13
|
return thread[$terminate]();
|
|
18
14
|
},
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
/* eslint-disable unicorn/no-thenable */
|
|
2
|
-
/* eslint-disable @typescript-eslint/member-ordering */
|
|
3
|
-
/* eslint-disable @typescript-eslint/no-floating-promises */
|
|
4
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
5
|
-
/* eslint-disable @typescript-eslint/no-this-alias */
|
|
6
|
-
/* eslint-disable unicorn/no-this-assignment */
|
|
7
1
|
import { Observable } from 'observable-fns';
|
|
8
2
|
const doNothing = () => { };
|
|
9
3
|
const returnInput = (input) => input;
|
|
@@ -14,19 +8,6 @@ function fail(error) {
|
|
|
14
8
|
function isThenable(thing) {
|
|
15
9
|
return thing && typeof thing.then === 'function';
|
|
16
10
|
}
|
|
17
|
-
/**
|
|
18
|
-
* Creates a hybrid, combining the APIs of an Observable and a Promise.
|
|
19
|
-
*
|
|
20
|
-
* It is used to proxy async process states when we are initially not sure
|
|
21
|
-
* if that async process will yield values once (-> Promise) or multiple
|
|
22
|
-
* times (-> Observable).
|
|
23
|
-
*
|
|
24
|
-
* Note that the observable promise inherits some of the observable's characteristics:
|
|
25
|
-
* The `init` function will be called *once for every time anyone subscribes to it*.
|
|
26
|
-
*
|
|
27
|
-
* If this is undesired, derive a hot observable from it using `makeHot()` and
|
|
28
|
-
* subscribe to that.
|
|
29
|
-
*/
|
|
30
11
|
export class ObservablePromise extends Observable {
|
|
31
12
|
[Symbol.toStringTag] = '[object ObservablePromise]';
|
|
32
13
|
initHasRun = false;
|
|
@@ -38,7 +19,6 @@ export class ObservablePromise extends Observable {
|
|
|
38
19
|
state = 'pending';
|
|
39
20
|
constructor(init) {
|
|
40
21
|
super((originalObserver) => {
|
|
41
|
-
// tslint:disable-next-line no-this-assignment
|
|
42
22
|
const self = this;
|
|
43
23
|
const observer = {
|
|
44
24
|
...originalObserver,
|
|
@@ -74,16 +54,12 @@ export class ObservablePromise extends Observable {
|
|
|
74
54
|
this.state = 'rejected';
|
|
75
55
|
this.rejection = error;
|
|
76
56
|
for (const onRejected of this.rejectionCallbacks) {
|
|
77
|
-
// Promisifying the call to turn errors into unhandled promise rejections
|
|
78
|
-
// instead of them failing sync and cancelling the iteration
|
|
79
57
|
runDeferred(() => onRejected(error));
|
|
80
58
|
}
|
|
81
59
|
}
|
|
82
60
|
onCompletion() {
|
|
83
61
|
this.state = 'fulfilled';
|
|
84
62
|
for (const onFulfilled of this.fulfillmentCallbacks) {
|
|
85
|
-
// Promisifying the call to turn errors into unhandled promise rejections
|
|
86
|
-
// instead of them failing sync and cancelling the iteration
|
|
87
63
|
runDeferred(() => onFulfilled(this.firstValue));
|
|
88
64
|
}
|
|
89
65
|
}
|
|
@@ -1,15 +1,5 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
1
|
import { Observable } from 'observable-fns';
|
|
3
2
|
const $observers = Symbol('observers');
|
|
4
|
-
/**
|
|
5
|
-
* Observable subject. Implements the Observable interface, but also exposes
|
|
6
|
-
* the `next()`, `error()`, `complete()` methods to initiate observable
|
|
7
|
-
* updates "from the outside".
|
|
8
|
-
*
|
|
9
|
-
* Use `Observable.from(subject)` to derive an observable that proxies all
|
|
10
|
-
* values, errors and the completion raised on this subject, but does not
|
|
11
|
-
* expose the `next()`, `error()`, `complete()` methods.
|
|
12
|
-
*/
|
|
13
3
|
export class Subject extends Observable {
|
|
14
4
|
[$observers];
|
|
15
5
|
constructor() {
|
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
// eslint-disable-next-line unicorn/no-useless-undefined
|
|
2
1
|
const doNothing = () => undefined;
|
|
3
|
-
/**
|
|
4
|
-
* Creates a new promise and exposes its resolver function.
|
|
5
|
-
* Use with care!
|
|
6
|
-
*/
|
|
7
2
|
export function createPromiseWithResolver() {
|
|
8
3
|
let alreadyResolved = false;
|
|
9
4
|
let resolvedTo;
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
1
|
import { $transferable } from './symbols';
|
|
3
2
|
function isTransferable(thing) {
|
|
4
3
|
if (!thing || typeof thing !== 'object')
|
|
5
4
|
return false;
|
|
6
|
-
// Don't check too thoroughly, since the list of transferable things in JS might grow over time
|
|
7
5
|
return true;
|
|
8
6
|
}
|
|
9
7
|
export function isTransferDescriptor(thing) {
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
/// <reference lib="dom" />
|
|
3
|
-
// tslint:disable max-classes-per-file
|
|
4
1
|
import { $errors, $events, $terminate, $worker } from '../symbols';
|
|
5
|
-
/** Event as emitted by worker thread. Subscribe to using `Thread.events(thread)`. */
|
|
6
2
|
export var WorkerEventType;
|
|
7
3
|
(function (WorkerEventType) {
|
|
8
4
|
WorkerEventType["internalError"] = "internalError";
|
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
/////////////////////////////
|
|
2
|
-
// Messages sent by master:
|
|
3
1
|
export var MasterMessageType;
|
|
4
2
|
(function (MasterMessageType) {
|
|
5
3
|
MasterMessageType["cancel"] = "cancel";
|
|
6
4
|
MasterMessageType["run"] = "run";
|
|
7
5
|
})(MasterMessageType || (MasterMessageType = {}));
|
|
8
|
-
////////////////////////////
|
|
9
|
-
// Messages sent by worker:
|
|
10
6
|
export var WorkerMessageType;
|
|
11
7
|
(function (WorkerMessageType) {
|
|
12
8
|
WorkerMessageType["error"] = "error";
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/* eslint-disable import/no-default-export */
|
|
2
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
|
-
/// <reference lib="dom" />
|
|
4
|
-
// tslint:disable no-shadowed-variable
|
|
5
1
|
const isWorkerRuntime = function isWorkerRuntime() {
|
|
6
2
|
const isWindowContext = self !== undefined && typeof Window !== 'undefined' && self instanceof Window;
|
|
7
3
|
return self !== undefined && self['postMessage'] && !isWindowContext ? true : false;
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/* eslint-disable import/no-default-export */
|
|
2
|
-
// tslint:disable no-var-requires
|
|
3
|
-
/*
|
|
4
|
-
* This file is only a stub to make './implementation' resolve to the right module.
|
|
5
|
-
*/
|
|
6
1
|
import WebWorkerImplementation from './implementation.browser';
|
|
7
2
|
import TinyWorkerImplementation from './implementation.tiny-worker';
|
|
8
3
|
import WorkerThreadsImplementation from './implementation.worker_threads';
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/* eslint-disable import/no-default-export */
|
|
2
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
|
-
/// <reference lib="dom" />
|
|
4
|
-
// tslint:disable no-shadowed-variable
|
|
5
1
|
try {
|
|
6
2
|
if (self === undefined) {
|
|
7
3
|
;
|
|
@@ -16,15 +12,12 @@ const isWorkerRuntime = function isWorkerRuntime() {
|
|
|
16
12
|
return self !== undefined && self['postMessage'] ? true : false;
|
|
17
13
|
};
|
|
18
14
|
const postMessageToMaster = function postMessageToMaster(data) {
|
|
19
|
-
// TODO: Warn that Transferables are not supported on first attempt to use feature
|
|
20
15
|
self.postMessage(data);
|
|
21
16
|
};
|
|
22
17
|
let muxingHandlerSetUp = false;
|
|
23
18
|
const messageHandlers = new Set();
|
|
24
19
|
const subscribeToMasterMessages = function subscribeToMasterMessages(onMessage) {
|
|
25
20
|
if (!muxingHandlerSetUp) {
|
|
26
|
-
// We have one multiplexing message handler as tiny-worker's
|
|
27
|
-
// addEventListener() only allows you to set a single message handler
|
|
28
21
|
self.addEventListener('message', ((event) => {
|
|
29
22
|
for (const handler of messageHandlers)
|
|
30
23
|
handler(event.data);
|
|
@@ -1,22 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
|
-
import isSomeObservable from 'is-observable';
|
|
1
|
+
import isSomeObservable from 'is-observable-2-1-0';
|
|
4
2
|
import { deserialize, serialize } from '../common';
|
|
5
3
|
import { isTransferDescriptor } from '../transferable';
|
|
6
4
|
import { MasterMessageType, WorkerMessageType, } from '../types/messages';
|
|
7
5
|
import Implementation from './implementation';
|
|
8
6
|
export { registerSerializer } from '../common';
|
|
9
7
|
export { Transfer } from '../transferable';
|
|
10
|
-
/** Returns `true` if this code is currently running in a worker. */
|
|
11
8
|
export const isWorkerRuntime = Implementation.isWorkerRuntime;
|
|
12
9
|
let exposeCalled = false;
|
|
13
10
|
const activeSubscriptions = new Map();
|
|
14
11
|
const isMasterJobCancelMessage = (thing) => thing && thing.type === MasterMessageType.cancel;
|
|
15
12
|
const isMasterJobRunMessage = (thing) => thing && thing.type === MasterMessageType.run;
|
|
16
|
-
/**
|
|
17
|
-
* There are issues with `is-observable` not recognizing zen-observable's instances.
|
|
18
|
-
* We are using `observable-fns`, but it's based on zen-observable, too.
|
|
19
|
-
*/
|
|
20
13
|
const isObservable = (thing) => isSomeObservable(thing) || isZenObservable(thing);
|
|
21
14
|
function isZenObservable(thing) {
|
|
22
15
|
return thing && typeof thing === 'object' && typeof thing.subscribe === 'function';
|
|
@@ -79,7 +72,6 @@ function postUncaughtErrorMessage(error) {
|
|
|
79
72
|
Implementation.postMessageToMaster(errorMessage);
|
|
80
73
|
}
|
|
81
74
|
catch (subError) {
|
|
82
|
-
// tslint:disable-next-line no-console
|
|
83
75
|
console.error('Not reporting uncaught error back to master thread as it ' + 'occured while reporting an uncaught error already.' + '\nLatest error:', subError, '\nOriginal error:', error);
|
|
84
76
|
}
|
|
85
77
|
}
|
|
@@ -113,13 +105,6 @@ async function runFunction(jobUID, fn, args) {
|
|
|
113
105
|
}
|
|
114
106
|
}
|
|
115
107
|
}
|
|
116
|
-
/**
|
|
117
|
-
* Expose a function or a module (an object whose values are functions)
|
|
118
|
-
* to the main thread. Must be called exactly once in every worker thread
|
|
119
|
-
* to signal its API to the main thread.
|
|
120
|
-
*
|
|
121
|
-
* @param exposed Function or object whose values are functions
|
|
122
|
-
*/
|
|
123
108
|
export function expose(exposed) {
|
|
124
109
|
if (!Implementation.isWorkerRuntime()) {
|
|
125
110
|
throw new Error('expose() called in the master thread.');
|
|
@@ -161,25 +146,21 @@ export function expose(exposed) {
|
|
|
161
146
|
}
|
|
162
147
|
if (typeof self !== 'undefined' && typeof self.addEventListener === 'function' && Implementation.isWorkerRuntime()) {
|
|
163
148
|
self.addEventListener('error', (event) => {
|
|
164
|
-
// Post with some delay, so the master had some time to subscribe to messages
|
|
165
149
|
setTimeout(() => postUncaughtErrorMessage(event.error || event), 250);
|
|
166
150
|
});
|
|
167
151
|
self.addEventListener('unhandledrejection', (event) => {
|
|
168
152
|
const error = event.reason;
|
|
169
153
|
if (error && typeof error.message === 'string') {
|
|
170
|
-
// Post with some delay, so the master had some time to subscribe to messages
|
|
171
154
|
setTimeout(() => postUncaughtErrorMessage(error), 250);
|
|
172
155
|
}
|
|
173
156
|
});
|
|
174
157
|
}
|
|
175
158
|
if (typeof process !== 'undefined' && typeof process.on === 'function' && Implementation.isWorkerRuntime()) {
|
|
176
159
|
process.on('uncaughtException', (error) => {
|
|
177
|
-
// Post with some delay, so the master had some time to subscribe to messages
|
|
178
160
|
setTimeout(() => postUncaughtErrorMessage(error), 250);
|
|
179
161
|
});
|
|
180
162
|
process.on('unhandledRejection', (error) => {
|
|
181
163
|
if (error && typeof error.message === 'string') {
|
|
182
|
-
// Post with some delay, so the master had some time to subscribe to messages
|
|
183
164
|
setTimeout(() => postUncaughtErrorMessage(error), 250);
|
|
184
165
|
}
|
|
185
166
|
});
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/* eslint-disable import/no-default-export */
|
|
2
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
|
-
// Webpack hack
|
|
4
|
-
// tslint:disable no-eval
|
|
5
1
|
let implementation;
|
|
6
2
|
function selectImplementation() {
|
|
7
3
|
return typeof __non_webpack_require__ === 'function' ? __non_webpack_require__('worker_threads') : eval('require')('worker_threads');
|
package/dist/index.js
CHANGED
|
@@ -15,7 +15,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
exports.expose = exports.Transfer = exports.DefaultSerializer = exports.registerSerializer = void 0;
|
|
18
|
-
/* eslint-disable import/no-internal-modules */
|
|
19
18
|
var common_1 = require("./common");
|
|
20
19
|
Object.defineProperty(exports, "registerSerializer", { enumerable: true, get: function () { return common_1.registerSerializer; } });
|
|
21
20
|
__exportStar(require("./master/index"), exports);
|