threadsx 2.0.0
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/LICENSE +21 -0
- package/README.md +164 -0
- package/dist/common.d.ts +4 -0
- package/dist/common.js +16 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +26 -0
- package/dist/master/get-bundle-url.browser.d.ts +3 -0
- package/dist/master/get-bundle-url.browser.js +28 -0
- package/dist/master/implementation.browser.d.ts +4 -0
- package/dist/master/implementation.browser.js +72 -0
- package/dist/master/implementation.d.ts +6 -0
- package/dist/master/implementation.js +51 -0
- package/dist/master/implementation.node.d.ts +4 -0
- package/dist/master/implementation.node.js +196 -0
- package/dist/master/index.d.ts +14 -0
- package/dist/master/index.js +15 -0
- package/dist/master/invocation-proxy.d.ts +3 -0
- package/dist/master/invocation-proxy.js +128 -0
- package/dist/master/pool-types.d.ts +65 -0
- package/dist/master/pool-types.js +15 -0
- package/dist/master/pool.d.ts +89 -0
- package/dist/master/pool.js +290 -0
- package/dist/master/register.d.ts +1 -0
- package/dist/master/register.js +9 -0
- package/dist/master/spawn.d.ts +20 -0
- package/dist/master/spawn.js +159 -0
- package/dist/master/thread.d.ts +12 -0
- package/dist/master/thread.js +22 -0
- package/dist/observable-promise.d.ts +38 -0
- package/dist/observable-promise.js +150 -0
- package/dist/observable.d.ts +19 -0
- package/dist/observable.js +40 -0
- package/dist/ponyfills.d.ts +8 -0
- package/dist/ponyfills.js +21 -0
- package/dist/promise.d.ts +5 -0
- package/dist/promise.js +27 -0
- package/dist/serializers.d.ts +16 -0
- package/dist/serializers.js +51 -0
- package/dist/symbols.d.ts +5 -0
- package/dist/symbols.js +8 -0
- package/dist/transferable.d.ts +42 -0
- package/dist/transferable.js +26 -0
- package/dist/types/master.d.ts +98 -0
- package/dist/types/master.js +12 -0
- package/dist/types/messages.d.ts +62 -0
- package/dist/types/messages.js +20 -0
- package/dist/types/worker.d.ts +11 -0
- package/dist/types/worker.js +2 -0
- package/dist/worker/bundle-entry.d.ts +1 -0
- package/dist/worker/bundle-entry.js +24 -0
- package/dist/worker/implementation.browser.d.ts +6 -0
- package/dist/worker/implementation.browser.js +25 -0
- package/dist/worker/implementation.d.ts +3 -0
- package/dist/worker/implementation.js +18 -0
- package/dist/worker/implementation.worker_threads.d.ts +8 -0
- package/dist/worker/implementation.worker_threads.js +42 -0
- package/dist/worker/index.d.ts +13 -0
- package/dist/worker/index.js +224 -0
- package/dist/worker_threads.d.ts +8 -0
- package/dist/worker_threads.js +16 -0
- package/dist-esm/common.js +11 -0
- package/dist-esm/index.js +5 -0
- package/dist-esm/master/get-bundle-url.browser.js +25 -0
- package/dist-esm/master/implementation.browser.js +67 -0
- package/dist-esm/master/implementation.js +15 -0
- package/dist-esm/master/implementation.node.js +155 -0
- package/dist-esm/master/index.js +9 -0
- package/dist-esm/master/invocation-proxy.js +121 -0
- package/dist-esm/master/pool-types.js +12 -0
- package/dist-esm/master/pool.js +283 -0
- package/dist-esm/master/register.js +7 -0
- package/dist-esm/master/spawn.js +153 -0
- package/dist-esm/master/thread.js +19 -0
- package/dist-esm/observable-promise.js +146 -0
- package/dist-esm/observable.js +36 -0
- package/dist-esm/ponyfills.js +18 -0
- package/dist-esm/promise.js +24 -0
- package/dist-esm/serializers.js +47 -0
- package/dist-esm/symbols.js +5 -0
- package/dist-esm/transferable.js +22 -0
- package/dist-esm/types/master.js +9 -0
- package/dist-esm/types/messages.js +17 -0
- package/dist-esm/types/worker.js +1 -0
- package/dist-esm/worker/bundle-entry.js +8 -0
- package/dist-esm/worker/implementation.browser.js +23 -0
- package/dist-esm/worker/implementation.js +13 -0
- package/dist-esm/worker/implementation.worker_threads.js +37 -0
- package/dist-esm/worker/index.js +215 -0
- package/dist-esm/worker_threads.js +13 -0
- package/index.mjs +4 -0
- package/observable.mjs +1 -0
- package/package.json +168 -0
- package/register.mjs +2 -0
- package/worker.mjs +1 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import DebugLogger from "debug";
|
|
11
|
+
import { Observable } from "observable-fns";
|
|
12
|
+
import { deserialize } from "../common";
|
|
13
|
+
import { createPromiseWithResolver } from "../promise";
|
|
14
|
+
import { $errors, $events, $terminate, $worker } from "../symbols";
|
|
15
|
+
import { WorkerEventType } from "../types/master";
|
|
16
|
+
import { createProxyFunction, createProxyModule } from "./invocation-proxy";
|
|
17
|
+
const debugMessages = DebugLogger("threads:master:messages");
|
|
18
|
+
const debugSpawn = DebugLogger("threads:master:spawn");
|
|
19
|
+
const debugThreadUtils = DebugLogger("threads:master:thread-utils");
|
|
20
|
+
const isInitMessage = (data) => data && data.type === "init";
|
|
21
|
+
const isUncaughtErrorMessage = (data) => data && data.type === "uncaughtError";
|
|
22
|
+
const initMessageTimeout = typeof process !== "undefined" && typeof process.env !== "undefined" && process.env.THREADS_WORKER_INIT_TIMEOUT
|
|
23
|
+
? Number.parseInt(process.env.THREADS_WORKER_INIT_TIMEOUT, 10)
|
|
24
|
+
: 10000;
|
|
25
|
+
function withTimeout(promise, timeoutInMs, errorMessage) {
|
|
26
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
27
|
+
let timeoutHandle;
|
|
28
|
+
const timeout = new Promise((resolve, reject) => {
|
|
29
|
+
timeoutHandle = setTimeout(() => reject(Error(errorMessage)), timeoutInMs);
|
|
30
|
+
});
|
|
31
|
+
try {
|
|
32
|
+
return yield Promise.race([
|
|
33
|
+
promise,
|
|
34
|
+
timeout
|
|
35
|
+
]);
|
|
36
|
+
}
|
|
37
|
+
finally {
|
|
38
|
+
// Always clear the timer, even when `promise` rejects. Otherwise a pending
|
|
39
|
+
// timeout keeps the event loop alive until it fires (which on a failed
|
|
40
|
+
// spawn showed up as ava "failed to exit" on slower runners).
|
|
41
|
+
clearTimeout(timeoutHandle);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function receiveInitMessage(worker) {
|
|
46
|
+
return new Promise((resolve, reject) => {
|
|
47
|
+
const messageHandler = ((event) => {
|
|
48
|
+
debugMessages("Message from worker before finishing initialization:", event.data);
|
|
49
|
+
if (isInitMessage(event.data)) {
|
|
50
|
+
worker.removeEventListener("message", messageHandler);
|
|
51
|
+
resolve(event.data);
|
|
52
|
+
}
|
|
53
|
+
else if (isUncaughtErrorMessage(event.data)) {
|
|
54
|
+
worker.removeEventListener("message", messageHandler);
|
|
55
|
+
reject(deserialize(event.data.error));
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
worker.addEventListener("message", messageHandler);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
function createEventObservable(worker, workerTermination) {
|
|
62
|
+
return new Observable(observer => {
|
|
63
|
+
const messageHandler = ((messageEvent) => {
|
|
64
|
+
const workerEvent = {
|
|
65
|
+
type: WorkerEventType.message,
|
|
66
|
+
data: messageEvent.data
|
|
67
|
+
};
|
|
68
|
+
observer.next(workerEvent);
|
|
69
|
+
});
|
|
70
|
+
const rejectionHandler = ((errorEvent) => {
|
|
71
|
+
debugThreadUtils("Unhandled promise rejection event in thread:", errorEvent);
|
|
72
|
+
const workerEvent = {
|
|
73
|
+
type: WorkerEventType.internalError,
|
|
74
|
+
error: Error(errorEvent.reason)
|
|
75
|
+
};
|
|
76
|
+
observer.next(workerEvent);
|
|
77
|
+
});
|
|
78
|
+
worker.addEventListener("message", messageHandler);
|
|
79
|
+
worker.addEventListener("unhandledrejection", rejectionHandler);
|
|
80
|
+
workerTermination.then(() => {
|
|
81
|
+
const terminationEvent = {
|
|
82
|
+
type: WorkerEventType.termination
|
|
83
|
+
};
|
|
84
|
+
worker.removeEventListener("message", messageHandler);
|
|
85
|
+
worker.removeEventListener("unhandledrejection", rejectionHandler);
|
|
86
|
+
observer.next(terminationEvent);
|
|
87
|
+
observer.complete();
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
function createTerminator(worker) {
|
|
92
|
+
const [termination, resolver] = createPromiseWithResolver();
|
|
93
|
+
const terminate = () => __awaiter(this, void 0, void 0, function* () {
|
|
94
|
+
debugThreadUtils("Terminating worker");
|
|
95
|
+
// Newer versions of worker_threads workers return a promise
|
|
96
|
+
yield worker.terminate();
|
|
97
|
+
resolver();
|
|
98
|
+
});
|
|
99
|
+
return { terminate, termination };
|
|
100
|
+
}
|
|
101
|
+
function setPrivateThreadProps(raw, worker, workerEvents, terminate) {
|
|
102
|
+
const workerErrors = workerEvents
|
|
103
|
+
.filter(event => event.type === WorkerEventType.internalError)
|
|
104
|
+
.map(errorEvent => errorEvent.error);
|
|
105
|
+
return Object.assign(raw, {
|
|
106
|
+
[$errors]: workerErrors,
|
|
107
|
+
[$events]: workerEvents,
|
|
108
|
+
[$terminate]: terminate,
|
|
109
|
+
[$worker]: worker
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Spawn a new thread. Takes a fresh worker instance, wraps it in a thin
|
|
114
|
+
* abstraction layer to provide the transparent API and verifies that
|
|
115
|
+
* the worker has initialized successfully.
|
|
116
|
+
*
|
|
117
|
+
* @param worker Instance of `Worker`. Either a web worker or a `worker_threads` worker.
|
|
118
|
+
* @param [options]
|
|
119
|
+
* @param [options.timeout] Init message timeout. Default: 10000 or set by environment variable.
|
|
120
|
+
*/
|
|
121
|
+
export function spawn(worker, options) {
|
|
122
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
123
|
+
var _a, _b;
|
|
124
|
+
debugSpawn("Initializing new thread");
|
|
125
|
+
const timeout = options && options.timeout ? options.timeout : initMessageTimeout;
|
|
126
|
+
let initMessage;
|
|
127
|
+
try {
|
|
128
|
+
initMessage = yield withTimeout(receiveInitMessage(worker), timeout, `Timeout: Did not receive an init message from worker after ${timeout}ms. Make sure the worker calls expose().`);
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
// The worker failed to initialise (e.g. it threw before calling expose(),
|
|
132
|
+
// or never sent an init message). Tear it down so it does not leak a live
|
|
133
|
+
// worker handle and keep the process from exiting.
|
|
134
|
+
yield Promise.resolve((_b = (_a = worker).terminate) === null || _b === void 0 ? void 0 : _b.call(_a)).catch(() => undefined);
|
|
135
|
+
throw error;
|
|
136
|
+
}
|
|
137
|
+
const exposed = initMessage.exposed;
|
|
138
|
+
const { termination, terminate } = createTerminator(worker);
|
|
139
|
+
const events = createEventObservable(worker, termination);
|
|
140
|
+
if (exposed.type === "function") {
|
|
141
|
+
const proxy = createProxyFunction(worker);
|
|
142
|
+
return setPrivateThreadProps(proxy, worker, events, terminate);
|
|
143
|
+
}
|
|
144
|
+
else if (exposed.type === "module") {
|
|
145
|
+
const proxy = createProxyModule(worker, exposed.methods);
|
|
146
|
+
return setPrivateThreadProps(proxy, worker, events, terminate);
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
const type = exposed.type;
|
|
150
|
+
throw Error(`Worker init message states unexpected type of expose(): ${type}`);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { $errors, $events, $terminate } from "../symbols";
|
|
2
|
+
function fail(message) {
|
|
3
|
+
throw Error(message);
|
|
4
|
+
}
|
|
5
|
+
/** Thread utility functions. Use them to manage or inspect a `spawn()`-ed thread. */
|
|
6
|
+
export const Thread = {
|
|
7
|
+
/** Return an observable that can be used to subscribe to all errors happening in the thread. */
|
|
8
|
+
errors(thread) {
|
|
9
|
+
return thread[$errors] || fail("Error observable not found. Make sure to pass a thread instance as returned by the spawn() promise.");
|
|
10
|
+
},
|
|
11
|
+
/** Return an observable that can be used to subscribe to internal events happening in the thread. Useful for debugging. */
|
|
12
|
+
events(thread) {
|
|
13
|
+
return thread[$events] || fail("Events observable not found. Make sure to pass a thread instance as returned by the spawn() promise.");
|
|
14
|
+
},
|
|
15
|
+
/** Terminate a thread. Remember to terminate every thread when you are done using it. */
|
|
16
|
+
terminate(thread) {
|
|
17
|
+
return thread[$terminate]();
|
|
18
|
+
}
|
|
19
|
+
};
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
var _a;
|
|
2
|
+
import { Observable } from "observable-fns";
|
|
3
|
+
const doNothing = () => undefined;
|
|
4
|
+
const returnInput = (input) => input;
|
|
5
|
+
const runDeferred = (fn) => Promise.resolve().then(fn);
|
|
6
|
+
function fail(error) {
|
|
7
|
+
throw error;
|
|
8
|
+
}
|
|
9
|
+
function isThenable(thing) {
|
|
10
|
+
return thing && typeof thing.then === "function";
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Creates a hybrid, combining the APIs of an Observable and a Promise.
|
|
14
|
+
*
|
|
15
|
+
* It is used to proxy async process states when we are initially not sure
|
|
16
|
+
* if that async process will yield values once (-> Promise) or multiple
|
|
17
|
+
* times (-> Observable).
|
|
18
|
+
*
|
|
19
|
+
* Note that the observable promise inherits some of the observable's characteristics:
|
|
20
|
+
* The `init` function will be called *once for every time anyone subscribes to it*.
|
|
21
|
+
*
|
|
22
|
+
* If this is undesired, derive a hot observable from it using `makeHot()` and
|
|
23
|
+
* subscribe to that.
|
|
24
|
+
*/
|
|
25
|
+
export class ObservablePromise extends Observable {
|
|
26
|
+
constructor(init) {
|
|
27
|
+
super((originalObserver) => {
|
|
28
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
29
|
+
const self = this;
|
|
30
|
+
const observer = Object.assign(Object.assign({}, originalObserver), { complete() {
|
|
31
|
+
originalObserver.complete();
|
|
32
|
+
self.onCompletion();
|
|
33
|
+
},
|
|
34
|
+
error(error) {
|
|
35
|
+
originalObserver.error(error);
|
|
36
|
+
self.onError(error);
|
|
37
|
+
},
|
|
38
|
+
next(value) {
|
|
39
|
+
originalObserver.next(value);
|
|
40
|
+
self.onNext(value);
|
|
41
|
+
} });
|
|
42
|
+
try {
|
|
43
|
+
this.initHasRun = true;
|
|
44
|
+
return init(observer);
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
observer.error(error);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
this.initHasRun = false;
|
|
51
|
+
this.fulfillmentCallbacks = [];
|
|
52
|
+
this.rejectionCallbacks = [];
|
|
53
|
+
this.firstValueSet = false;
|
|
54
|
+
this.state = "pending";
|
|
55
|
+
this[_a] = "[object ObservablePromise]";
|
|
56
|
+
}
|
|
57
|
+
onNext(value) {
|
|
58
|
+
if (!this.firstValueSet) {
|
|
59
|
+
this.firstValue = value;
|
|
60
|
+
this.firstValueSet = true;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
onError(error) {
|
|
64
|
+
this.state = "rejected";
|
|
65
|
+
this.rejection = error;
|
|
66
|
+
for (const onRejected of this.rejectionCallbacks) {
|
|
67
|
+
// Promisifying the call to turn errors into unhandled promise rejections
|
|
68
|
+
// instead of them failing sync and cancelling the iteration
|
|
69
|
+
runDeferred(() => onRejected(error));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
onCompletion() {
|
|
73
|
+
this.state = "fulfilled";
|
|
74
|
+
for (const onFulfilled of this.fulfillmentCallbacks) {
|
|
75
|
+
// Promisifying the call to turn errors into unhandled promise rejections
|
|
76
|
+
// instead of them failing sync and cancelling the iteration
|
|
77
|
+
runDeferred(() => onFulfilled(this.firstValue));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
then(onFulfilledRaw, onRejectedRaw) {
|
|
81
|
+
const onFulfilled = onFulfilledRaw || returnInput;
|
|
82
|
+
const onRejected = onRejectedRaw || fail;
|
|
83
|
+
let onRejectedCalled = false;
|
|
84
|
+
return new Promise((resolve, reject) => {
|
|
85
|
+
const rejectionCallback = (error) => {
|
|
86
|
+
if (onRejectedCalled)
|
|
87
|
+
return;
|
|
88
|
+
onRejectedCalled = true;
|
|
89
|
+
try {
|
|
90
|
+
resolve(onRejected(error));
|
|
91
|
+
}
|
|
92
|
+
catch (anotherError) {
|
|
93
|
+
reject(anotherError);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
const fulfillmentCallback = (value) => {
|
|
97
|
+
try {
|
|
98
|
+
resolve(onFulfilled(value));
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
rejectionCallback(error);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
if (!this.initHasRun) {
|
|
105
|
+
this.subscribe({ error: rejectionCallback });
|
|
106
|
+
}
|
|
107
|
+
if (this.state === "fulfilled") {
|
|
108
|
+
return resolve(onFulfilled(this.firstValue));
|
|
109
|
+
}
|
|
110
|
+
if (this.state === "rejected") {
|
|
111
|
+
onRejectedCalled = true;
|
|
112
|
+
return resolve(onRejected(this.rejection));
|
|
113
|
+
}
|
|
114
|
+
this.fulfillmentCallbacks.push(fulfillmentCallback);
|
|
115
|
+
this.rejectionCallbacks.push(rejectionCallback);
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
catch(onRejected) {
|
|
119
|
+
return this.then(undefined, onRejected);
|
|
120
|
+
}
|
|
121
|
+
finally(onCompleted) {
|
|
122
|
+
const handler = onCompleted || doNothing;
|
|
123
|
+
return this.then((value) => {
|
|
124
|
+
handler();
|
|
125
|
+
return value;
|
|
126
|
+
}, () => handler());
|
|
127
|
+
}
|
|
128
|
+
static from(thing) {
|
|
129
|
+
if (isThenable(thing)) {
|
|
130
|
+
return new ObservablePromise(observer => {
|
|
131
|
+
const onFulfilled = (value) => {
|
|
132
|
+
observer.next(value);
|
|
133
|
+
observer.complete();
|
|
134
|
+
};
|
|
135
|
+
const onRejected = (error) => {
|
|
136
|
+
observer.error(error);
|
|
137
|
+
};
|
|
138
|
+
thing.then(onFulfilled, onRejected);
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
return super.from(thing);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
_a = Symbol.toStringTag;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Observable } from "observable-fns";
|
|
2
|
+
export { Observable };
|
|
3
|
+
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
|
+
export class Subject extends Observable {
|
|
14
|
+
constructor() {
|
|
15
|
+
super(observer => {
|
|
16
|
+
this[$observers] = [
|
|
17
|
+
...(this[$observers] || []),
|
|
18
|
+
observer
|
|
19
|
+
];
|
|
20
|
+
const unsubscribe = () => {
|
|
21
|
+
this[$observers] = this[$observers].filter(someObserver => someObserver !== observer);
|
|
22
|
+
};
|
|
23
|
+
return unsubscribe;
|
|
24
|
+
});
|
|
25
|
+
this[$observers] = [];
|
|
26
|
+
}
|
|
27
|
+
complete() {
|
|
28
|
+
this[$observers].forEach(observer => observer.complete());
|
|
29
|
+
}
|
|
30
|
+
error(error) {
|
|
31
|
+
this[$observers].forEach(observer => observer.error(error));
|
|
32
|
+
}
|
|
33
|
+
next(value) {
|
|
34
|
+
this[$observers].forEach(observer => observer.next(value));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Based on <https://github.com/es-shims/Promise.allSettled/blob/master/implementation.js>
|
|
2
|
+
export function allSettled(values) {
|
|
3
|
+
return Promise.all(values.map(item => {
|
|
4
|
+
const onFulfill = (value) => {
|
|
5
|
+
return { status: 'fulfilled', value };
|
|
6
|
+
};
|
|
7
|
+
const onReject = (reason) => {
|
|
8
|
+
return { status: 'rejected', reason };
|
|
9
|
+
};
|
|
10
|
+
const itemPromise = Promise.resolve(item);
|
|
11
|
+
try {
|
|
12
|
+
return itemPromise.then(onFulfill, onReject);
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
return Promise.reject(error);
|
|
16
|
+
}
|
|
17
|
+
}));
|
|
18
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const doNothing = () => undefined;
|
|
2
|
+
/**
|
|
3
|
+
* Creates a new promise and exposes its resolver function.
|
|
4
|
+
* Use with care!
|
|
5
|
+
*/
|
|
6
|
+
export function createPromiseWithResolver() {
|
|
7
|
+
let alreadyResolved = false;
|
|
8
|
+
let resolvedTo;
|
|
9
|
+
let resolver = doNothing;
|
|
10
|
+
const promise = new Promise(resolve => {
|
|
11
|
+
if (alreadyResolved) {
|
|
12
|
+
resolve(resolvedTo);
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
resolver = resolve;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
const exposedResolver = (value) => {
|
|
19
|
+
alreadyResolved = true;
|
|
20
|
+
resolvedTo = value;
|
|
21
|
+
resolver(resolvedTo);
|
|
22
|
+
};
|
|
23
|
+
return [promise, exposedResolver];
|
|
24
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export function extendSerializer(extend, implementation) {
|
|
2
|
+
const fallbackDeserializer = extend.deserialize.bind(extend);
|
|
3
|
+
const fallbackSerializer = extend.serialize.bind(extend);
|
|
4
|
+
return {
|
|
5
|
+
deserialize(message) {
|
|
6
|
+
return implementation.deserialize(message, fallbackDeserializer);
|
|
7
|
+
},
|
|
8
|
+
serialize(input) {
|
|
9
|
+
return implementation.serialize(input, fallbackSerializer);
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
const DefaultErrorSerializer = {
|
|
14
|
+
deserialize(message) {
|
|
15
|
+
return Object.assign(Error(message.message), {
|
|
16
|
+
name: message.name,
|
|
17
|
+
stack: message.stack
|
|
18
|
+
});
|
|
19
|
+
},
|
|
20
|
+
serialize(error) {
|
|
21
|
+
return {
|
|
22
|
+
__error_marker: "$$error",
|
|
23
|
+
message: error.message,
|
|
24
|
+
name: error.name,
|
|
25
|
+
stack: error.stack
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
const isSerializedError = (thing) => thing && typeof thing === "object" && "__error_marker" in thing && thing.__error_marker === "$$error";
|
|
30
|
+
export const DefaultSerializer = {
|
|
31
|
+
deserialize(message) {
|
|
32
|
+
if (isSerializedError(message)) {
|
|
33
|
+
return DefaultErrorSerializer.deserialize(message);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
return message;
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
serialize(input) {
|
|
40
|
+
if (input instanceof Error) {
|
|
41
|
+
return DefaultErrorSerializer.serialize(input);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
return input;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { $transferable } from "./symbols";
|
|
2
|
+
function isTransferable(thing) {
|
|
3
|
+
if (!thing || typeof thing !== "object")
|
|
4
|
+
return false;
|
|
5
|
+
// Don't check too thoroughly, since the list of transferable things in JS might grow over time
|
|
6
|
+
return true;
|
|
7
|
+
}
|
|
8
|
+
export function isTransferDescriptor(thing) {
|
|
9
|
+
return thing && typeof thing === "object" && thing[$transferable];
|
|
10
|
+
}
|
|
11
|
+
export function Transfer(payload, transferables) {
|
|
12
|
+
if (!transferables) {
|
|
13
|
+
if (!isTransferable(payload))
|
|
14
|
+
throw Error();
|
|
15
|
+
transferables = [payload];
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
[$transferable]: true,
|
|
19
|
+
send: payload,
|
|
20
|
+
transferables
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/// <reference lib="dom" />
|
|
2
|
+
import { $errors, $events, $terminate, $worker } from "../symbols";
|
|
3
|
+
/** Event as emitted by worker thread. Subscribe to using `Thread.events(thread)`. */
|
|
4
|
+
export var WorkerEventType;
|
|
5
|
+
(function (WorkerEventType) {
|
|
6
|
+
WorkerEventType["internalError"] = "internalError";
|
|
7
|
+
WorkerEventType["message"] = "message";
|
|
8
|
+
WorkerEventType["termination"] = "termination";
|
|
9
|
+
})(WorkerEventType || (WorkerEventType = {}));
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/////////////////////////////
|
|
2
|
+
// Messages sent by master:
|
|
3
|
+
export var MasterMessageType;
|
|
4
|
+
(function (MasterMessageType) {
|
|
5
|
+
MasterMessageType["cancel"] = "cancel";
|
|
6
|
+
MasterMessageType["run"] = "run";
|
|
7
|
+
})(MasterMessageType || (MasterMessageType = {}));
|
|
8
|
+
////////////////////////////
|
|
9
|
+
// Messages sent by worker:
|
|
10
|
+
export var WorkerMessageType;
|
|
11
|
+
(function (WorkerMessageType) {
|
|
12
|
+
WorkerMessageType["error"] = "error";
|
|
13
|
+
WorkerMessageType["init"] = "init";
|
|
14
|
+
WorkerMessageType["result"] = "result";
|
|
15
|
+
WorkerMessageType["running"] = "running";
|
|
16
|
+
WorkerMessageType["uncaughtError"] = "uncaughtError";
|
|
17
|
+
})(WorkerMessageType || (WorkerMessageType = {}));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/// <reference lib="dom" />
|
|
2
|
+
const isWorkerRuntime = function isWorkerRuntime() {
|
|
3
|
+
const isWindowContext = typeof self !== "undefined" && typeof Window !== "undefined" && self instanceof Window;
|
|
4
|
+
return typeof self !== "undefined" && typeof self.postMessage === "function" && !isWindowContext;
|
|
5
|
+
};
|
|
6
|
+
const postMessageToMaster = function postMessageToMaster(data, transferList) {
|
|
7
|
+
self.postMessage(data, transferList);
|
|
8
|
+
};
|
|
9
|
+
const subscribeToMasterMessages = function subscribeToMasterMessages(onMessage) {
|
|
10
|
+
const messageHandler = (messageEvent) => {
|
|
11
|
+
onMessage(messageEvent.data);
|
|
12
|
+
};
|
|
13
|
+
const unsubscribe = () => {
|
|
14
|
+
self.removeEventListener("message", messageHandler);
|
|
15
|
+
};
|
|
16
|
+
self.addEventListener("message", messageHandler);
|
|
17
|
+
return unsubscribe;
|
|
18
|
+
};
|
|
19
|
+
export default {
|
|
20
|
+
isWorkerRuntime,
|
|
21
|
+
postMessageToMaster,
|
|
22
|
+
subscribeToMasterMessages
|
|
23
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is only a stub to make './implementation' resolve to the right module.
|
|
3
|
+
*/
|
|
4
|
+
import WebWorkerImplementation from "./implementation.browser";
|
|
5
|
+
import WorkerThreadsImplementation from "./implementation.worker_threads";
|
|
6
|
+
const runningInNode = typeof process !== 'undefined' && process.arch !== 'browser' && 'pid' in process;
|
|
7
|
+
function selectNodeImplementation() {
|
|
8
|
+
WorkerThreadsImplementation.testImplementation();
|
|
9
|
+
return WorkerThreadsImplementation;
|
|
10
|
+
}
|
|
11
|
+
export default runningInNode
|
|
12
|
+
? selectNodeImplementation()
|
|
13
|
+
: WebWorkerImplementation;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import WorkerThreads from "../worker_threads";
|
|
2
|
+
function assertMessagePort(port) {
|
|
3
|
+
if (!port) {
|
|
4
|
+
throw Error("Invariant violation: MessagePort to parent is not available.");
|
|
5
|
+
}
|
|
6
|
+
return port;
|
|
7
|
+
}
|
|
8
|
+
const isWorkerRuntime = function isWorkerRuntime() {
|
|
9
|
+
return !WorkerThreads().isMainThread;
|
|
10
|
+
};
|
|
11
|
+
const postMessageToMaster = function postMessageToMaster(data, transferList) {
|
|
12
|
+
assertMessagePort(WorkerThreads().parentPort).postMessage(data, transferList);
|
|
13
|
+
};
|
|
14
|
+
const subscribeToMasterMessages = function subscribeToMasterMessages(onMessage) {
|
|
15
|
+
const parentPort = WorkerThreads().parentPort;
|
|
16
|
+
if (!parentPort) {
|
|
17
|
+
throw Error("Invariant violation: MessagePort to parent is not available.");
|
|
18
|
+
}
|
|
19
|
+
const messageHandler = (message) => {
|
|
20
|
+
onMessage(message);
|
|
21
|
+
};
|
|
22
|
+
const unsubscribe = () => {
|
|
23
|
+
assertMessagePort(parentPort).off("message", messageHandler);
|
|
24
|
+
};
|
|
25
|
+
assertMessagePort(parentPort).on("message", messageHandler);
|
|
26
|
+
return unsubscribe;
|
|
27
|
+
};
|
|
28
|
+
function testImplementation() {
|
|
29
|
+
// Will throw if `worker_threads` are not available
|
|
30
|
+
WorkerThreads();
|
|
31
|
+
}
|
|
32
|
+
export default {
|
|
33
|
+
isWorkerRuntime,
|
|
34
|
+
postMessageToMaster,
|
|
35
|
+
subscribeToMasterMessages,
|
|
36
|
+
testImplementation
|
|
37
|
+
};
|