@loaders.gl/worker-utils 4.0.0-beta.2 → 4.0.0-beta.4
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/index.cjs +989 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/{esm/lib → lib}/async-queue/async-queue.js +3 -4
- package/dist/lib/async-queue/async-queue.js.map +1 -0
- package/dist/lib/env-utils/assert.js.map +1 -0
- package/dist/lib/env-utils/globals.js.map +1 -0
- package/dist/{esm/lib → lib}/env-utils/version.js +2 -2
- package/dist/lib/env-utils/version.js.map +1 -0
- package/dist/{esm/lib → lib}/library-utils/library-utils.js +11 -10
- package/dist/lib/library-utils/library-utils.js.map +1 -0
- package/dist/lib/node/require-utils.node.d.ts.map +1 -1
- package/dist/{esm/lib → lib}/node/require-utils.node.js +6 -5
- package/dist/lib/node/require-utils.node.js.map +1 -0
- package/dist/lib/node/worker_threads-browser.d.ts.map +1 -1
- package/dist/lib/node/worker_threads-browser.js.map +1 -0
- package/dist/lib/node/worker_threads.js.map +1 -0
- package/dist/{esm/lib → lib}/process-utils/child-process-proxy.js +12 -13
- package/dist/lib/process-utils/child-process-proxy.js.map +1 -0
- package/dist/lib/process-utils/process-utils.js.map +1 -0
- package/dist/{esm/lib → lib}/worker-api/create-worker.js +2 -2
- package/dist/lib/worker-api/create-worker.js.map +1 -0
- package/dist/lib/worker-api/get-worker-url.js +30 -0
- package/dist/lib/worker-api/get-worker-url.js.map +1 -0
- package/dist/{esm/lib → lib}/worker-api/process-on-worker.js +4 -4
- package/dist/lib/worker-api/process-on-worker.js.map +1 -0
- package/dist/{esm/lib → lib}/worker-api/validate-worker-version.js +2 -2
- package/dist/lib/worker-api/validate-worker-version.js.map +1 -0
- package/dist/{esm/lib → lib}/worker-farm/worker-body.js +1 -1
- package/dist/lib/worker-farm/worker-body.js.map +1 -0
- package/dist/{esm/lib → lib}/worker-farm/worker-farm.js +5 -6
- package/dist/lib/worker-farm/worker-farm.js.map +1 -0
- package/dist/{esm/lib → lib}/worker-farm/worker-job.js +7 -8
- package/dist/lib/worker-farm/worker-job.js.map +1 -0
- package/dist/lib/worker-farm/worker-pool.d.ts.map +1 -1
- package/dist/{esm/lib → lib}/worker-farm/worker-pool.js +18 -17
- package/dist/lib/worker-farm/worker-pool.js.map +1 -0
- package/dist/{esm/lib → lib}/worker-farm/worker-thread.js +17 -18
- package/dist/lib/worker-farm/worker-thread.js.map +1 -0
- package/dist/{esm/lib → lib}/worker-utils/get-loadable-worker-url.js +8 -2
- package/dist/lib/worker-utils/get-loadable-worker-url.js.map +1 -0
- package/dist/lib/worker-utils/get-transfer-list.js.map +1 -0
- package/dist/lib/worker-utils/remove-nontransferable-options.js.map +1 -0
- package/dist/null-worker-node.js +22 -2
- package/dist/null-worker-node.js.map +2 -2
- package/dist/null-worker.js +24 -2
- package/dist/null-worker.js.map +2 -2
- package/dist/types.js.map +1 -0
- package/dist/workers/null-worker.js +5 -0
- package/dist/workers/null-worker.js.map +1 -0
- package/package.json +12 -6
- package/src/lib/library-utils/library-utils.ts +10 -3
- package/src/lib/node/require-utils.node.ts +4 -2
- package/src/lib/node/worker_threads-browser.ts +0 -1
- package/src/lib/worker-farm/worker-pool.ts +3 -0
- package/dist/es5/index.js +0 -148
- package/dist/es5/index.js.map +0 -1
- package/dist/es5/lib/async-queue/async-queue.js +0 -100
- package/dist/es5/lib/async-queue/async-queue.js.map +0 -1
- package/dist/es5/lib/env-utils/assert.js +0 -12
- package/dist/es5/lib/env-utils/assert.js.map +0 -1
- package/dist/es5/lib/env-utils/globals.js +0 -32
- package/dist/es5/lib/env-utils/globals.js.map +0 -1
- package/dist/es5/lib/env-utils/version.js +0 -24
- package/dist/es5/lib/env-utils/version.js.map +0 -1
- package/dist/es5/lib/library-utils/library-utils.js +0 -217
- package/dist/es5/lib/library-utils/library-utils.js.map +0 -1
- package/dist/es5/lib/node/require-utils.node.js +0 -138
- package/dist/es5/lib/node/require-utils.node.js.map +0 -1
- package/dist/es5/lib/node/worker_threads-browser.js +0 -23
- package/dist/es5/lib/node/worker_threads-browser.js.map +0 -1
- package/dist/es5/lib/node/worker_threads.js +0 -27
- package/dist/es5/lib/node/worker_threads.js.map +0 -1
- package/dist/es5/lib/process-utils/child-process-proxy.js +0 -195
- package/dist/es5/lib/process-utils/child-process-proxy.js.map +0 -1
- package/dist/es5/lib/process-utils/process-utils.js +0 -33
- package/dist/es5/lib/process-utils/process-utils.js.map +0 -1
- package/dist/es5/lib/worker-api/create-worker.js +0 -166
- package/dist/es5/lib/worker-api/create-worker.js.map +0 -1
- package/dist/es5/lib/worker-api/get-worker-url.js +0 -37
- package/dist/es5/lib/worker-api/get-worker-url.js.map +0 -1
- package/dist/es5/lib/worker-api/process-on-worker.js +0 -137
- package/dist/es5/lib/worker-api/process-on-worker.js.map +0 -1
- package/dist/es5/lib/worker-api/validate-worker-version.js +0 -25
- package/dist/es5/lib/worker-api/validate-worker-version.js.map +0 -1
- package/dist/es5/lib/worker-farm/worker-body.js +0 -109
- package/dist/es5/lib/worker-farm/worker-body.js.map +0 -1
- package/dist/es5/lib/worker-farm/worker-farm.js +0 -113
- package/dist/es5/lib/worker-farm/worker-farm.js.map +0 -1
- package/dist/es5/lib/worker-farm/worker-job.js +0 -56
- package/dist/es5/lib/worker-farm/worker-job.js.map +0 -1
- package/dist/es5/lib/worker-farm/worker-pool.js +0 -211
- package/dist/es5/lib/worker-farm/worker-pool.js.map +0 -1
- package/dist/es5/lib/worker-farm/worker-thread.js +0 -136
- package/dist/es5/lib/worker-farm/worker-thread.js.map +0 -1
- package/dist/es5/lib/worker-utils/get-loadable-worker-url.js +0 -41
- package/dist/es5/lib/worker-utils/get-loadable-worker-url.js.map +0 -1
- package/dist/es5/lib/worker-utils/get-transfer-list.js +0 -59
- package/dist/es5/lib/worker-utils/get-transfer-list.js.map +0 -1
- package/dist/es5/lib/worker-utils/remove-nontransferable-options.js +0 -25
- package/dist/es5/lib/worker-utils/remove-nontransferable-options.js.map +0 -1
- package/dist/es5/types.js +0 -2
- package/dist/es5/types.js.map +0 -1
- package/dist/es5/workers/null-worker.js +0 -23
- package/dist/es5/workers/null-worker.js.map +0 -1
- package/dist/esm/index.js +0 -26
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/lib/async-queue/async-queue.js.map +0 -1
- package/dist/esm/lib/env-utils/assert.js.map +0 -1
- package/dist/esm/lib/env-utils/globals.js.map +0 -1
- package/dist/esm/lib/env-utils/version.js.map +0 -1
- package/dist/esm/lib/library-utils/library-utils.js.map +0 -1
- package/dist/esm/lib/node/require-utils.node.js.map +0 -1
- package/dist/esm/lib/node/worker_threads-browser.js.map +0 -1
- package/dist/esm/lib/node/worker_threads.js.map +0 -1
- package/dist/esm/lib/process-utils/child-process-proxy.js.map +0 -1
- package/dist/esm/lib/process-utils/process-utils.js.map +0 -1
- package/dist/esm/lib/worker-api/create-worker.js.map +0 -1
- package/dist/esm/lib/worker-api/get-worker-url.js +0 -30
- package/dist/esm/lib/worker-api/get-worker-url.js.map +0 -1
- package/dist/esm/lib/worker-api/process-on-worker.js.map +0 -1
- package/dist/esm/lib/worker-api/validate-worker-version.js.map +0 -1
- package/dist/esm/lib/worker-farm/worker-body.js.map +0 -1
- package/dist/esm/lib/worker-farm/worker-farm.js.map +0 -1
- package/dist/esm/lib/worker-farm/worker-job.js.map +0 -1
- package/dist/esm/lib/worker-farm/worker-pool.js.map +0 -1
- package/dist/esm/lib/worker-farm/worker-thread.js.map +0 -1
- package/dist/esm/lib/worker-utils/get-loadable-worker-url.js.map +0 -1
- package/dist/esm/lib/worker-utils/get-transfer-list.js.map +0 -1
- package/dist/esm/lib/worker-utils/remove-nontransferable-options.js.map +0 -1
- package/dist/esm/types.js.map +0 -1
- package/dist/esm/workers/null-worker.js +0 -5
- package/dist/esm/workers/null-worker.js.map +0 -1
- /package/dist/{esm/lib → lib}/env-utils/assert.js +0 -0
- /package/dist/{esm/lib → lib}/env-utils/globals.js +0 -0
- /package/dist/{esm/lib → lib}/node/worker_threads-browser.js +0 -0
- /package/dist/{esm/lib → lib}/node/worker_threads.js +0 -0
- /package/dist/{esm/lib → lib}/process-utils/process-utils.js +0 -0
- /package/dist/{esm/lib → lib}/worker-utils/get-transfer-list.js +0 -0
- /package/dist/{esm/lib → lib}/worker-utils/remove-nontransferable-options.js +0 -0
- /package/dist/{esm/types.js → types.js} +0 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,989 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
9
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
10
|
+
};
|
|
11
|
+
var __export = (target, all) => {
|
|
12
|
+
for (var name in all)
|
|
13
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
14
|
+
};
|
|
15
|
+
var __copyProps = (to, from, except, desc) => {
|
|
16
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
17
|
+
for (let key of __getOwnPropNames(from))
|
|
18
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
19
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
20
|
+
}
|
|
21
|
+
return to;
|
|
22
|
+
};
|
|
23
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
24
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
25
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
26
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
27
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
28
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
29
|
+
mod
|
|
30
|
+
));
|
|
31
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
32
|
+
|
|
33
|
+
// (disabled):src/lib/node/require-utils.node
|
|
34
|
+
var require_require_utils = __commonJS({
|
|
35
|
+
"(disabled):src/lib/node/require-utils.node"() {
|
|
36
|
+
"use strict";
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// (disabled):src/lib/process-utils/child-process-proxy
|
|
41
|
+
var require_child_process_proxy = __commonJS({
|
|
42
|
+
"(disabled):src/lib/process-utils/child-process-proxy"() {
|
|
43
|
+
"use strict";
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// src/index.ts
|
|
48
|
+
var src_exports = {};
|
|
49
|
+
__export(src_exports, {
|
|
50
|
+
AsyncQueue: () => AsyncQueue,
|
|
51
|
+
ChildProcessProxy: () => import_child_process_proxy.default,
|
|
52
|
+
NullWorker: () => NullWorker,
|
|
53
|
+
WorkerBody: () => WorkerBody,
|
|
54
|
+
WorkerFarm: () => WorkerFarm,
|
|
55
|
+
WorkerJob: () => WorkerJob,
|
|
56
|
+
WorkerPool: () => WorkerPool,
|
|
57
|
+
WorkerThread: () => WorkerThread,
|
|
58
|
+
assert: () => assert,
|
|
59
|
+
canProcessOnWorker: () => canProcessOnWorker,
|
|
60
|
+
createWorker: () => createWorker,
|
|
61
|
+
getLibraryUrl: () => getLibraryUrl,
|
|
62
|
+
getTransferList: () => getTransferList,
|
|
63
|
+
getTransferListForWriter: () => getTransferListForWriter,
|
|
64
|
+
getWorkerURL: () => getWorkerURL,
|
|
65
|
+
isBrowser: () => isBrowser,
|
|
66
|
+
isWorker: () => isWorker,
|
|
67
|
+
loadLibrary: () => loadLibrary,
|
|
68
|
+
processOnWorker: () => processOnWorker,
|
|
69
|
+
validateWorkerVersion: () => validateWorkerVersion
|
|
70
|
+
});
|
|
71
|
+
module.exports = __toCommonJS(src_exports);
|
|
72
|
+
|
|
73
|
+
// src/lib/env-utils/version.ts
|
|
74
|
+
var NPM_TAG = "beta";
|
|
75
|
+
function getVersion() {
|
|
76
|
+
var _a;
|
|
77
|
+
if (!((_a = globalThis._loadersgl_) == null ? void 0 : _a.version)) {
|
|
78
|
+
globalThis._loadersgl_ = globalThis._loadersgl_ || {};
|
|
79
|
+
if (typeof __VERSION__ === "undefined") {
|
|
80
|
+
console.error(
|
|
81
|
+
"loaders.gl: The __VERSION__ variable is not injected using babel plugin. Latest unstable workers would be fetched from the CDN."
|
|
82
|
+
);
|
|
83
|
+
globalThis._loadersgl_.version = NPM_TAG;
|
|
84
|
+
} else {
|
|
85
|
+
globalThis._loadersgl_.version = __VERSION__;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return globalThis._loadersgl_.version;
|
|
89
|
+
}
|
|
90
|
+
var VERSION = getVersion();
|
|
91
|
+
|
|
92
|
+
// src/lib/env-utils/assert.ts
|
|
93
|
+
function assert(condition, message) {
|
|
94
|
+
if (!condition) {
|
|
95
|
+
throw new Error(message || "loaders.gl assertion failed.");
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// src/lib/env-utils/globals.ts
|
|
100
|
+
var globals = {
|
|
101
|
+
self: typeof self !== "undefined" && self,
|
|
102
|
+
window: typeof window !== "undefined" && window,
|
|
103
|
+
global: typeof global !== "undefined" && global,
|
|
104
|
+
document: typeof document !== "undefined" && document
|
|
105
|
+
};
|
|
106
|
+
var self_ = globals.self || globals.window || globals.global || {};
|
|
107
|
+
var window_ = globals.window || globals.self || globals.global || {};
|
|
108
|
+
var global_ = globals.global || globals.self || globals.window || {};
|
|
109
|
+
var document_ = globals.document || {};
|
|
110
|
+
var isBrowser = (
|
|
111
|
+
// @ts-ignore process.browser
|
|
112
|
+
typeof process !== "object" || String(process) !== "[object process]" || process.browser
|
|
113
|
+
);
|
|
114
|
+
var isWorker = typeof importScripts === "function";
|
|
115
|
+
var isMobile = typeof window !== "undefined" && typeof window.orientation !== "undefined";
|
|
116
|
+
var matches = typeof process !== "undefined" && process.version && /v([0-9]*)/.exec(process.version);
|
|
117
|
+
var nodeVersion = matches && parseFloat(matches[1]) || 0;
|
|
118
|
+
|
|
119
|
+
// src/lib/worker-farm/worker-job.ts
|
|
120
|
+
var WorkerJob = class {
|
|
121
|
+
constructor(jobName, workerThread) {
|
|
122
|
+
this.isRunning = true;
|
|
123
|
+
this._resolve = () => {
|
|
124
|
+
};
|
|
125
|
+
this._reject = () => {
|
|
126
|
+
};
|
|
127
|
+
this.name = jobName;
|
|
128
|
+
this.workerThread = workerThread;
|
|
129
|
+
this.result = new Promise((resolve, reject) => {
|
|
130
|
+
this._resolve = resolve;
|
|
131
|
+
this._reject = reject;
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Send a message to the job's worker thread
|
|
136
|
+
* @param data any data structure, ideally consisting mostly of transferrable objects
|
|
137
|
+
*/
|
|
138
|
+
postMessage(type, payload) {
|
|
139
|
+
this.workerThread.postMessage({
|
|
140
|
+
source: "loaders.gl",
|
|
141
|
+
// Lets worker ignore unrelated messages
|
|
142
|
+
type,
|
|
143
|
+
payload
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Call to resolve the `result` Promise with the supplied value
|
|
148
|
+
*/
|
|
149
|
+
done(value) {
|
|
150
|
+
assert(this.isRunning);
|
|
151
|
+
this.isRunning = false;
|
|
152
|
+
this._resolve(value);
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Call to reject the `result` Promise with the supplied error
|
|
156
|
+
*/
|
|
157
|
+
error(error) {
|
|
158
|
+
assert(this.isRunning);
|
|
159
|
+
this.isRunning = false;
|
|
160
|
+
this._reject(error);
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
// src/lib/node/worker_threads-browser.ts
|
|
165
|
+
var Worker2 = class {
|
|
166
|
+
terminate() {
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
// src/lib/worker-utils/get-loadable-worker-url.ts
|
|
171
|
+
var workerURLCache = /* @__PURE__ */ new Map();
|
|
172
|
+
function getLoadableWorkerURL(props) {
|
|
173
|
+
assert(props.source && !props.url || !props.source && props.url);
|
|
174
|
+
let workerURL = workerURLCache.get(props.source || props.url);
|
|
175
|
+
if (!workerURL) {
|
|
176
|
+
if (props.url) {
|
|
177
|
+
workerURL = getLoadableWorkerURLFromURL(props.url);
|
|
178
|
+
workerURLCache.set(props.url, workerURL);
|
|
179
|
+
}
|
|
180
|
+
if (props.source) {
|
|
181
|
+
workerURL = getLoadableWorkerURLFromSource(props.source);
|
|
182
|
+
workerURLCache.set(props.source, workerURL);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
assert(workerURL);
|
|
186
|
+
return workerURL;
|
|
187
|
+
}
|
|
188
|
+
function getLoadableWorkerURLFromURL(url) {
|
|
189
|
+
if (!url.startsWith("http")) {
|
|
190
|
+
return url;
|
|
191
|
+
}
|
|
192
|
+
const workerSource = buildScriptSource(url);
|
|
193
|
+
return getLoadableWorkerURLFromSource(workerSource);
|
|
194
|
+
}
|
|
195
|
+
function getLoadableWorkerURLFromSource(workerSource) {
|
|
196
|
+
const blob = new Blob([workerSource], { type: "application/javascript" });
|
|
197
|
+
return URL.createObjectURL(blob);
|
|
198
|
+
}
|
|
199
|
+
function buildScriptSource(workerUrl) {
|
|
200
|
+
return `try {
|
|
201
|
+
importScripts('${workerUrl}');
|
|
202
|
+
} catch (error) {
|
|
203
|
+
console.error(error);
|
|
204
|
+
throw error;
|
|
205
|
+
}`;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// src/lib/worker-utils/get-transfer-list.ts
|
|
209
|
+
function getTransferList(object, recursive = true, transfers) {
|
|
210
|
+
const transfersSet = transfers || /* @__PURE__ */ new Set();
|
|
211
|
+
if (!object) {
|
|
212
|
+
} else if (isTransferable(object)) {
|
|
213
|
+
transfersSet.add(object);
|
|
214
|
+
} else if (isTransferable(object.buffer)) {
|
|
215
|
+
transfersSet.add(object.buffer);
|
|
216
|
+
} else if (ArrayBuffer.isView(object)) {
|
|
217
|
+
} else if (recursive && typeof object === "object") {
|
|
218
|
+
for (const key in object) {
|
|
219
|
+
getTransferList(object[key], recursive, transfersSet);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return transfers === void 0 ? Array.from(transfersSet) : [];
|
|
223
|
+
}
|
|
224
|
+
function isTransferable(object) {
|
|
225
|
+
if (!object) {
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
if (object instanceof ArrayBuffer) {
|
|
229
|
+
return true;
|
|
230
|
+
}
|
|
231
|
+
if (typeof MessagePort !== "undefined" && object instanceof MessagePort) {
|
|
232
|
+
return true;
|
|
233
|
+
}
|
|
234
|
+
if (typeof ImageBitmap !== "undefined" && object instanceof ImageBitmap) {
|
|
235
|
+
return true;
|
|
236
|
+
}
|
|
237
|
+
if (typeof OffscreenCanvas !== "undefined" && object instanceof OffscreenCanvas) {
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
function getTransferListForWriter(object) {
|
|
243
|
+
if (object === null) {
|
|
244
|
+
return {};
|
|
245
|
+
}
|
|
246
|
+
const clone = Object.assign({}, object);
|
|
247
|
+
Object.keys(clone).forEach((key) => {
|
|
248
|
+
if (typeof object[key] === "object" && !ArrayBuffer.isView(object[key]) && !(object[key] instanceof Array)) {
|
|
249
|
+
clone[key] = getTransferListForWriter(object[key]);
|
|
250
|
+
} else if (typeof clone[key] === "function" || clone[key] instanceof RegExp) {
|
|
251
|
+
clone[key] = {};
|
|
252
|
+
} else {
|
|
253
|
+
clone[key] = object[key];
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
return clone;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// src/lib/worker-farm/worker-thread.ts
|
|
260
|
+
var NOOP = () => {
|
|
261
|
+
};
|
|
262
|
+
var WorkerThread = class {
|
|
263
|
+
constructor(props) {
|
|
264
|
+
this.terminated = false;
|
|
265
|
+
this._loadableURL = "";
|
|
266
|
+
const { name, source, url } = props;
|
|
267
|
+
assert(source || url);
|
|
268
|
+
this.name = name;
|
|
269
|
+
this.source = source;
|
|
270
|
+
this.url = url;
|
|
271
|
+
this.onMessage = NOOP;
|
|
272
|
+
this.onError = (error) => console.log(error);
|
|
273
|
+
this.worker = isBrowser ? this._createBrowserWorker() : this._createNodeWorker();
|
|
274
|
+
}
|
|
275
|
+
/** Checks if workers are supported on this platform */
|
|
276
|
+
static isSupported() {
|
|
277
|
+
return typeof Worker !== "undefined" && isBrowser || typeof Worker2 !== "undefined" && !isBrowser;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Terminate this worker thread
|
|
281
|
+
* @note Can free up significant memory
|
|
282
|
+
*/
|
|
283
|
+
destroy() {
|
|
284
|
+
this.onMessage = NOOP;
|
|
285
|
+
this.onError = NOOP;
|
|
286
|
+
this.worker.terminate();
|
|
287
|
+
this.terminated = true;
|
|
288
|
+
}
|
|
289
|
+
get isRunning() {
|
|
290
|
+
return Boolean(this.onMessage);
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Send a message to this worker thread
|
|
294
|
+
* @param data any data structure, ideally consisting mostly of transferrable objects
|
|
295
|
+
* @param transferList If not supplied, calculated automatically by traversing data
|
|
296
|
+
*/
|
|
297
|
+
postMessage(data, transferList) {
|
|
298
|
+
transferList = transferList || getTransferList(data);
|
|
299
|
+
this.worker.postMessage(data, transferList);
|
|
300
|
+
}
|
|
301
|
+
// PRIVATE
|
|
302
|
+
/**
|
|
303
|
+
* Generate a standard Error from an ErrorEvent
|
|
304
|
+
* @param event
|
|
305
|
+
*/
|
|
306
|
+
_getErrorFromErrorEvent(event) {
|
|
307
|
+
let message = "Failed to load ";
|
|
308
|
+
message += `worker ${this.name} from ${this.url}. `;
|
|
309
|
+
if (event.message) {
|
|
310
|
+
message += `${event.message} in `;
|
|
311
|
+
}
|
|
312
|
+
if (event.lineno) {
|
|
313
|
+
message += `:${event.lineno}:${event.colno}`;
|
|
314
|
+
}
|
|
315
|
+
return new Error(message);
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Creates a worker thread on the browser
|
|
319
|
+
*/
|
|
320
|
+
_createBrowserWorker() {
|
|
321
|
+
this._loadableURL = getLoadableWorkerURL({ source: this.source, url: this.url });
|
|
322
|
+
const worker = new Worker(this._loadableURL, { name: this.name });
|
|
323
|
+
worker.onmessage = (event) => {
|
|
324
|
+
if (!event.data) {
|
|
325
|
+
this.onError(new Error("No data received"));
|
|
326
|
+
} else {
|
|
327
|
+
this.onMessage(event.data);
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
worker.onerror = (error) => {
|
|
331
|
+
this.onError(this._getErrorFromErrorEvent(error));
|
|
332
|
+
this.terminated = true;
|
|
333
|
+
};
|
|
334
|
+
worker.onmessageerror = (event) => console.error(event);
|
|
335
|
+
return worker;
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Creates a worker thread in node.js
|
|
339
|
+
* @todo https://nodejs.org/api/async_hooks.html#async-resource-worker-pool
|
|
340
|
+
*/
|
|
341
|
+
_createNodeWorker() {
|
|
342
|
+
let worker;
|
|
343
|
+
if (this.url) {
|
|
344
|
+
const absolute = this.url.includes(":/") || this.url.startsWith("/");
|
|
345
|
+
const url = absolute ? this.url : `./${this.url}`;
|
|
346
|
+
worker = new Worker2(url, { eval: false });
|
|
347
|
+
} else if (this.source) {
|
|
348
|
+
worker = new Worker2(this.source, { eval: true });
|
|
349
|
+
} else {
|
|
350
|
+
throw new Error("no worker");
|
|
351
|
+
}
|
|
352
|
+
worker.on("message", (data) => {
|
|
353
|
+
this.onMessage(data);
|
|
354
|
+
});
|
|
355
|
+
worker.on("error", (error) => {
|
|
356
|
+
this.onError(error);
|
|
357
|
+
});
|
|
358
|
+
worker.on("exit", (code) => {
|
|
359
|
+
});
|
|
360
|
+
return worker;
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
// src/lib/worker-farm/worker-pool.ts
|
|
365
|
+
var WorkerPool = class {
|
|
366
|
+
/**
|
|
367
|
+
* @param processor - worker function
|
|
368
|
+
* @param maxConcurrency - max count of workers
|
|
369
|
+
*/
|
|
370
|
+
constructor(props) {
|
|
371
|
+
this.name = "unnamed";
|
|
372
|
+
this.maxConcurrency = 1;
|
|
373
|
+
this.maxMobileConcurrency = 1;
|
|
374
|
+
this.onDebug = () => {
|
|
375
|
+
};
|
|
376
|
+
this.reuseWorkers = true;
|
|
377
|
+
this.props = {};
|
|
378
|
+
this.jobQueue = [];
|
|
379
|
+
this.idleQueue = [];
|
|
380
|
+
this.count = 0;
|
|
381
|
+
this.isDestroyed = false;
|
|
382
|
+
this.source = props.source;
|
|
383
|
+
this.url = props.url;
|
|
384
|
+
this.setProps(props);
|
|
385
|
+
}
|
|
386
|
+
/** Checks if workers are supported on this platform */
|
|
387
|
+
static isSupported() {
|
|
388
|
+
return WorkerThread.isSupported();
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Terminates all workers in the pool
|
|
392
|
+
* @note Can free up significant memory
|
|
393
|
+
*/
|
|
394
|
+
destroy() {
|
|
395
|
+
this.idleQueue.forEach((worker) => worker.destroy());
|
|
396
|
+
this.isDestroyed = true;
|
|
397
|
+
}
|
|
398
|
+
setProps(props) {
|
|
399
|
+
this.props = { ...this.props, ...props };
|
|
400
|
+
if (props.name !== void 0) {
|
|
401
|
+
this.name = props.name;
|
|
402
|
+
}
|
|
403
|
+
if (props.maxConcurrency !== void 0) {
|
|
404
|
+
this.maxConcurrency = props.maxConcurrency;
|
|
405
|
+
}
|
|
406
|
+
if (props.maxMobileConcurrency !== void 0) {
|
|
407
|
+
this.maxMobileConcurrency = props.maxMobileConcurrency;
|
|
408
|
+
}
|
|
409
|
+
if (props.reuseWorkers !== void 0) {
|
|
410
|
+
this.reuseWorkers = props.reuseWorkers;
|
|
411
|
+
}
|
|
412
|
+
if (props.onDebug !== void 0) {
|
|
413
|
+
this.onDebug = props.onDebug;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
async startJob(name, onMessage2 = (job, type, data) => job.done(data), onError = (job, error) => job.error(error)) {
|
|
417
|
+
const startPromise = new Promise((onStart) => {
|
|
418
|
+
this.jobQueue.push({ name, onMessage: onMessage2, onError, onStart });
|
|
419
|
+
return this;
|
|
420
|
+
});
|
|
421
|
+
this._startQueuedJob();
|
|
422
|
+
return await startPromise;
|
|
423
|
+
}
|
|
424
|
+
// PRIVATE
|
|
425
|
+
/**
|
|
426
|
+
* Starts first queued job if worker is available or can be created
|
|
427
|
+
* Called when job is started and whenever a worker returns to the idleQueue
|
|
428
|
+
*/
|
|
429
|
+
async _startQueuedJob() {
|
|
430
|
+
if (!this.jobQueue.length) {
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
const workerThread = this._getAvailableWorker();
|
|
434
|
+
if (!workerThread) {
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
const queuedJob = this.jobQueue.shift();
|
|
438
|
+
if (queuedJob) {
|
|
439
|
+
this.onDebug({
|
|
440
|
+
message: "Starting job",
|
|
441
|
+
name: queuedJob.name,
|
|
442
|
+
workerThread,
|
|
443
|
+
backlog: this.jobQueue.length
|
|
444
|
+
});
|
|
445
|
+
const job = new WorkerJob(queuedJob.name, workerThread);
|
|
446
|
+
workerThread.onMessage = (data) => queuedJob.onMessage(job, data.type, data.payload);
|
|
447
|
+
workerThread.onError = (error) => queuedJob.onError(job, error);
|
|
448
|
+
queuedJob.onStart(job);
|
|
449
|
+
try {
|
|
450
|
+
await job.result;
|
|
451
|
+
} catch (error) {
|
|
452
|
+
console.error(`Worker exception: ${error}`);
|
|
453
|
+
} finally {
|
|
454
|
+
this.returnWorkerToQueue(workerThread);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Returns a worker to the idle queue
|
|
460
|
+
* Destroys the worker if
|
|
461
|
+
* - pool is destroyed
|
|
462
|
+
* - if this pool doesn't reuse workers
|
|
463
|
+
* - if maxConcurrency has been lowered
|
|
464
|
+
* @param worker
|
|
465
|
+
*/
|
|
466
|
+
returnWorkerToQueue(worker) {
|
|
467
|
+
const shouldDestroyWorker = (
|
|
468
|
+
// Workers on Node.js prevent the process from exiting.
|
|
469
|
+
// Until we figure out how to close them before exit, we always destroy them
|
|
470
|
+
!isBrowser || // If the pool is destroyed, there is no reason to keep the worker around
|
|
471
|
+
this.isDestroyed || // If the app has disabled worker reuse, any completed workers should be destroyed
|
|
472
|
+
!this.reuseWorkers || // If concurrency has been lowered, this worker might be surplus to requirements
|
|
473
|
+
this.count > this._getMaxConcurrency()
|
|
474
|
+
);
|
|
475
|
+
if (shouldDestroyWorker) {
|
|
476
|
+
worker.destroy();
|
|
477
|
+
this.count--;
|
|
478
|
+
} else {
|
|
479
|
+
this.idleQueue.push(worker);
|
|
480
|
+
}
|
|
481
|
+
if (!this.isDestroyed) {
|
|
482
|
+
this._startQueuedJob();
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Returns idle worker or creates new worker if maxConcurrency has not been reached
|
|
487
|
+
*/
|
|
488
|
+
_getAvailableWorker() {
|
|
489
|
+
if (this.idleQueue.length > 0) {
|
|
490
|
+
return this.idleQueue.shift() || null;
|
|
491
|
+
}
|
|
492
|
+
if (this.count < this._getMaxConcurrency()) {
|
|
493
|
+
this.count++;
|
|
494
|
+
const name = `${this.name.toLowerCase()} (#${this.count} of ${this.maxConcurrency})`;
|
|
495
|
+
return new WorkerThread({ name, source: this.source, url: this.url });
|
|
496
|
+
}
|
|
497
|
+
return null;
|
|
498
|
+
}
|
|
499
|
+
_getMaxConcurrency() {
|
|
500
|
+
return isMobile ? this.maxMobileConcurrency : this.maxConcurrency;
|
|
501
|
+
}
|
|
502
|
+
};
|
|
503
|
+
|
|
504
|
+
// src/lib/worker-farm/worker-farm.ts
|
|
505
|
+
var DEFAULT_PROPS = {
|
|
506
|
+
maxConcurrency: 3,
|
|
507
|
+
maxMobileConcurrency: 1,
|
|
508
|
+
reuseWorkers: true,
|
|
509
|
+
onDebug: () => {
|
|
510
|
+
}
|
|
511
|
+
};
|
|
512
|
+
var WorkerFarm = class {
|
|
513
|
+
/** get global instance with WorkerFarm.getWorkerFarm() */
|
|
514
|
+
constructor(props) {
|
|
515
|
+
this.workerPools = /* @__PURE__ */ new Map();
|
|
516
|
+
this.props = { ...DEFAULT_PROPS };
|
|
517
|
+
this.setProps(props);
|
|
518
|
+
this.workerPools = /* @__PURE__ */ new Map();
|
|
519
|
+
}
|
|
520
|
+
/** Checks if workers are supported on this platform */
|
|
521
|
+
static isSupported() {
|
|
522
|
+
return WorkerThread.isSupported();
|
|
523
|
+
}
|
|
524
|
+
/** Get the singleton instance of the global worker farm */
|
|
525
|
+
static getWorkerFarm(props = {}) {
|
|
526
|
+
WorkerFarm._workerFarm = WorkerFarm._workerFarm || new WorkerFarm({});
|
|
527
|
+
WorkerFarm._workerFarm.setProps(props);
|
|
528
|
+
return WorkerFarm._workerFarm;
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* Terminate all workers in the farm
|
|
532
|
+
* @note Can free up significant memory
|
|
533
|
+
*/
|
|
534
|
+
destroy() {
|
|
535
|
+
for (const workerPool of this.workerPools.values()) {
|
|
536
|
+
workerPool.destroy();
|
|
537
|
+
}
|
|
538
|
+
this.workerPools = /* @__PURE__ */ new Map();
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* Set props used when initializing worker pools
|
|
542
|
+
* @param props
|
|
543
|
+
*/
|
|
544
|
+
setProps(props) {
|
|
545
|
+
this.props = { ...this.props, ...props };
|
|
546
|
+
for (const workerPool of this.workerPools.values()) {
|
|
547
|
+
workerPool.setProps(this._getWorkerPoolProps());
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* Returns a worker pool for the specified worker
|
|
552
|
+
* @param options - only used first time for a specific worker name
|
|
553
|
+
* @param options.name - the name of the worker - used to identify worker pool
|
|
554
|
+
* @param options.url -
|
|
555
|
+
* @param options.source -
|
|
556
|
+
* @example
|
|
557
|
+
* const job = WorkerFarm.getWorkerFarm().getWorkerPool({name, url}).startJob(...);
|
|
558
|
+
*/
|
|
559
|
+
getWorkerPool(options2) {
|
|
560
|
+
const { name, source, url } = options2;
|
|
561
|
+
let workerPool = this.workerPools.get(name);
|
|
562
|
+
if (!workerPool) {
|
|
563
|
+
workerPool = new WorkerPool({
|
|
564
|
+
name,
|
|
565
|
+
source,
|
|
566
|
+
url
|
|
567
|
+
});
|
|
568
|
+
workerPool.setProps(this._getWorkerPoolProps());
|
|
569
|
+
this.workerPools.set(name, workerPool);
|
|
570
|
+
}
|
|
571
|
+
return workerPool;
|
|
572
|
+
}
|
|
573
|
+
_getWorkerPoolProps() {
|
|
574
|
+
return {
|
|
575
|
+
maxConcurrency: this.props.maxConcurrency,
|
|
576
|
+
maxMobileConcurrency: this.props.maxMobileConcurrency,
|
|
577
|
+
reuseWorkers: this.props.reuseWorkers,
|
|
578
|
+
onDebug: this.props.onDebug
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
};
|
|
582
|
+
|
|
583
|
+
// src/lib/worker-farm/worker-body.ts
|
|
584
|
+
function getParentPort() {
|
|
585
|
+
let parentPort;
|
|
586
|
+
try {
|
|
587
|
+
eval("globalThis.parentPort = require('worker_threads').parentPort");
|
|
588
|
+
parentPort = globalThis.parentPort;
|
|
589
|
+
} catch {
|
|
590
|
+
}
|
|
591
|
+
return parentPort;
|
|
592
|
+
}
|
|
593
|
+
var onMessageWrapperMap = /* @__PURE__ */ new Map();
|
|
594
|
+
var WorkerBody = class {
|
|
595
|
+
/** Check that we are actually in a worker thread */
|
|
596
|
+
static inWorkerThread() {
|
|
597
|
+
return typeof self !== "undefined" || Boolean(getParentPort());
|
|
598
|
+
}
|
|
599
|
+
/*
|
|
600
|
+
* (type: WorkerMessageType, payload: WorkerMessagePayload) => any
|
|
601
|
+
*/
|
|
602
|
+
static set onmessage(onMessage2) {
|
|
603
|
+
function handleMessage(message) {
|
|
604
|
+
const parentPort3 = getParentPort();
|
|
605
|
+
const { type, payload } = parentPort3 ? message : message.data;
|
|
606
|
+
onMessage2(type, payload);
|
|
607
|
+
}
|
|
608
|
+
const parentPort2 = getParentPort();
|
|
609
|
+
if (parentPort2) {
|
|
610
|
+
parentPort2.on("message", handleMessage);
|
|
611
|
+
parentPort2.on("exit", () => console.debug("Node worker closing"));
|
|
612
|
+
} else {
|
|
613
|
+
globalThis.onmessage = handleMessage;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
static addEventListener(onMessage2) {
|
|
617
|
+
let onMessageWrapper = onMessageWrapperMap.get(onMessage2);
|
|
618
|
+
if (!onMessageWrapper) {
|
|
619
|
+
onMessageWrapper = (message) => {
|
|
620
|
+
if (!isKnownMessage(message)) {
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
623
|
+
const parentPort3 = getParentPort();
|
|
624
|
+
const { type, payload } = parentPort3 ? message : message.data;
|
|
625
|
+
onMessage2(type, payload);
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
const parentPort2 = getParentPort();
|
|
629
|
+
if (parentPort2) {
|
|
630
|
+
console.error("not implemented");
|
|
631
|
+
} else {
|
|
632
|
+
globalThis.addEventListener("message", onMessageWrapper);
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
static removeEventListener(onMessage2) {
|
|
636
|
+
const onMessageWrapper = onMessageWrapperMap.get(onMessage2);
|
|
637
|
+
onMessageWrapperMap.delete(onMessage2);
|
|
638
|
+
const parentPort2 = getParentPort();
|
|
639
|
+
if (parentPort2) {
|
|
640
|
+
console.error("not implemented");
|
|
641
|
+
} else {
|
|
642
|
+
globalThis.removeEventListener("message", onMessageWrapper);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
/**
|
|
646
|
+
* Send a message from a worker to creating thread (main thread)
|
|
647
|
+
* @param type
|
|
648
|
+
* @param payload
|
|
649
|
+
*/
|
|
650
|
+
static postMessage(type, payload) {
|
|
651
|
+
const data = { source: "loaders.gl", type, payload };
|
|
652
|
+
const transferList = getTransferList(payload);
|
|
653
|
+
const parentPort2 = getParentPort();
|
|
654
|
+
if (parentPort2) {
|
|
655
|
+
parentPort2.postMessage(data, transferList);
|
|
656
|
+
} else {
|
|
657
|
+
globalThis.postMessage(data, transferList);
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
};
|
|
661
|
+
function isKnownMessage(message) {
|
|
662
|
+
const { type, data } = message;
|
|
663
|
+
return type === "message" && data && typeof data.source === "string" && data.source.startsWith("loaders.gl");
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
// src/lib/worker-api/get-worker-url.ts
|
|
667
|
+
function getWorkerName(worker) {
|
|
668
|
+
const warning = worker.version !== VERSION ? ` (worker-utils@${VERSION})` : "";
|
|
669
|
+
return `${worker.name}@${worker.version}${warning}`;
|
|
670
|
+
}
|
|
671
|
+
function getWorkerURL(worker, options2 = {}) {
|
|
672
|
+
const workerOptions = options2[worker.id] || {};
|
|
673
|
+
const workerFile = isBrowser ? `${worker.id}-worker.js` : `${worker.id}-worker-node.js`;
|
|
674
|
+
let url = workerOptions.workerUrl;
|
|
675
|
+
if (!url && worker.id === "compression") {
|
|
676
|
+
url = options2.workerUrl;
|
|
677
|
+
}
|
|
678
|
+
if (options2._workerType === "test") {
|
|
679
|
+
url = `modules/${worker.module}/dist/${workerFile}`;
|
|
680
|
+
}
|
|
681
|
+
if (!url) {
|
|
682
|
+
let version = worker.version;
|
|
683
|
+
if (version === "latest") {
|
|
684
|
+
version = NPM_TAG;
|
|
685
|
+
}
|
|
686
|
+
const versionTag = version ? `@${version}` : "";
|
|
687
|
+
url = `https://unpkg.com/@loaders.gl/${worker.module}${versionTag}/dist/${workerFile}`;
|
|
688
|
+
}
|
|
689
|
+
assert(url);
|
|
690
|
+
return url;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
// src/lib/worker-api/process-on-worker.ts
|
|
694
|
+
function canProcessOnWorker(worker, options2) {
|
|
695
|
+
if (!WorkerFarm.isSupported()) {
|
|
696
|
+
return false;
|
|
697
|
+
}
|
|
698
|
+
return worker.worker && (options2 == null ? void 0 : options2.worker);
|
|
699
|
+
}
|
|
700
|
+
async function processOnWorker(worker, data, options2 = {}, context = {}) {
|
|
701
|
+
const name = getWorkerName(worker);
|
|
702
|
+
const workerFarm = WorkerFarm.getWorkerFarm(options2);
|
|
703
|
+
const { source } = options2;
|
|
704
|
+
const workerPoolProps = { name, source };
|
|
705
|
+
if (!source) {
|
|
706
|
+
workerPoolProps.url = getWorkerURL(worker, options2);
|
|
707
|
+
}
|
|
708
|
+
const workerPool = workerFarm.getWorkerPool(workerPoolProps);
|
|
709
|
+
const jobName = options2.jobName || worker.name;
|
|
710
|
+
const job = await workerPool.startJob(
|
|
711
|
+
jobName,
|
|
712
|
+
// eslint-disable-next-line
|
|
713
|
+
onMessage.bind(null, context)
|
|
714
|
+
);
|
|
715
|
+
const transferableOptions = getTransferListForWriter(options2);
|
|
716
|
+
job.postMessage("process", { input: data, options: transferableOptions });
|
|
717
|
+
const result = await job.result;
|
|
718
|
+
return result.result;
|
|
719
|
+
}
|
|
720
|
+
async function onMessage(context, job, type, payload) {
|
|
721
|
+
switch (type) {
|
|
722
|
+
case "done":
|
|
723
|
+
job.done(payload);
|
|
724
|
+
break;
|
|
725
|
+
case "error":
|
|
726
|
+
job.error(new Error(payload.error));
|
|
727
|
+
break;
|
|
728
|
+
case "process":
|
|
729
|
+
const { id, input, options: options2 } = payload;
|
|
730
|
+
try {
|
|
731
|
+
if (!context.process) {
|
|
732
|
+
job.postMessage("error", { id, error: "Worker not set up to process on main thread" });
|
|
733
|
+
return;
|
|
734
|
+
}
|
|
735
|
+
const result = await context.process(input, options2);
|
|
736
|
+
job.postMessage("done", { id, result });
|
|
737
|
+
} catch (error) {
|
|
738
|
+
const message = error instanceof Error ? error.message : "unknown error";
|
|
739
|
+
job.postMessage("error", { id, error: message });
|
|
740
|
+
}
|
|
741
|
+
break;
|
|
742
|
+
default:
|
|
743
|
+
console.warn(`process-on-worker: unknown message ${type}`);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
// src/lib/async-queue/async-queue.ts
|
|
748
|
+
var AsyncQueue = class {
|
|
749
|
+
constructor() {
|
|
750
|
+
this._values = [];
|
|
751
|
+
this._settlers = [];
|
|
752
|
+
this._closed = false;
|
|
753
|
+
}
|
|
754
|
+
/** Return an async iterator for this queue */
|
|
755
|
+
[Symbol.asyncIterator]() {
|
|
756
|
+
return this;
|
|
757
|
+
}
|
|
758
|
+
/** Push a new value - the async iterator will yield a promise resolved to this value */
|
|
759
|
+
push(value) {
|
|
760
|
+
return this.enqueue(value);
|
|
761
|
+
}
|
|
762
|
+
/**
|
|
763
|
+
* Push a new value - the async iterator will yield a promise resolved to this value
|
|
764
|
+
* Add an error - the async iterator will yield a promise rejected with this value
|
|
765
|
+
*/
|
|
766
|
+
enqueue(value) {
|
|
767
|
+
if (this._closed) {
|
|
768
|
+
throw new Error("Closed");
|
|
769
|
+
}
|
|
770
|
+
if (this._settlers.length > 0) {
|
|
771
|
+
if (this._values.length > 0) {
|
|
772
|
+
throw new Error("Illegal internal state");
|
|
773
|
+
}
|
|
774
|
+
const settler = this._settlers.shift();
|
|
775
|
+
if (value instanceof Error) {
|
|
776
|
+
settler.reject(value);
|
|
777
|
+
} else {
|
|
778
|
+
settler.resolve({ value });
|
|
779
|
+
}
|
|
780
|
+
} else {
|
|
781
|
+
this._values.push(value);
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
/** Indicate that we not waiting for more values - The async iterator will be done */
|
|
785
|
+
close() {
|
|
786
|
+
while (this._settlers.length > 0) {
|
|
787
|
+
const settler = this._settlers.shift();
|
|
788
|
+
settler.resolve({ done: true });
|
|
789
|
+
}
|
|
790
|
+
this._closed = true;
|
|
791
|
+
}
|
|
792
|
+
// ITERATOR IMPLEMENTATION
|
|
793
|
+
/** @returns a Promise for an IteratorResult */
|
|
794
|
+
next() {
|
|
795
|
+
if (this._values.length > 0) {
|
|
796
|
+
const value = this._values.shift();
|
|
797
|
+
if (value instanceof Error) {
|
|
798
|
+
return Promise.reject(value);
|
|
799
|
+
}
|
|
800
|
+
return Promise.resolve({ done: false, value });
|
|
801
|
+
}
|
|
802
|
+
if (this._closed) {
|
|
803
|
+
if (this._settlers.length > 0) {
|
|
804
|
+
throw new Error("Illegal internal state");
|
|
805
|
+
}
|
|
806
|
+
return Promise.resolve({ done: true, value: void 0 });
|
|
807
|
+
}
|
|
808
|
+
return new Promise((resolve, reject) => {
|
|
809
|
+
this._settlers.push({ resolve, reject });
|
|
810
|
+
});
|
|
811
|
+
}
|
|
812
|
+
};
|
|
813
|
+
|
|
814
|
+
// src/lib/worker-api/create-worker.ts
|
|
815
|
+
var requestId = 0;
|
|
816
|
+
var inputBatches;
|
|
817
|
+
var options;
|
|
818
|
+
function createWorker(process2, processInBatches) {
|
|
819
|
+
if (!WorkerBody.inWorkerThread()) {
|
|
820
|
+
return;
|
|
821
|
+
}
|
|
822
|
+
const context = {
|
|
823
|
+
process: processOnMainThread
|
|
824
|
+
};
|
|
825
|
+
WorkerBody.onmessage = async (type, payload) => {
|
|
826
|
+
try {
|
|
827
|
+
switch (type) {
|
|
828
|
+
case "process":
|
|
829
|
+
if (!process2) {
|
|
830
|
+
throw new Error("Worker does not support atomic processing");
|
|
831
|
+
}
|
|
832
|
+
const result = await process2(payload.input, payload.options || {}, context);
|
|
833
|
+
WorkerBody.postMessage("done", { result });
|
|
834
|
+
break;
|
|
835
|
+
case "process-in-batches":
|
|
836
|
+
if (!processInBatches) {
|
|
837
|
+
throw new Error("Worker does not support batched processing");
|
|
838
|
+
}
|
|
839
|
+
inputBatches = new AsyncQueue();
|
|
840
|
+
options = payload.options || {};
|
|
841
|
+
const resultIterator = processInBatches(inputBatches, options, context);
|
|
842
|
+
for await (const batch of resultIterator) {
|
|
843
|
+
WorkerBody.postMessage("output-batch", { result: batch });
|
|
844
|
+
}
|
|
845
|
+
WorkerBody.postMessage("done", {});
|
|
846
|
+
break;
|
|
847
|
+
case "input-batch":
|
|
848
|
+
inputBatches.push(payload.input);
|
|
849
|
+
break;
|
|
850
|
+
case "input-done":
|
|
851
|
+
inputBatches.close();
|
|
852
|
+
break;
|
|
853
|
+
default:
|
|
854
|
+
}
|
|
855
|
+
} catch (error) {
|
|
856
|
+
const message = error instanceof Error ? error.message : "";
|
|
857
|
+
WorkerBody.postMessage("error", { error: message });
|
|
858
|
+
}
|
|
859
|
+
};
|
|
860
|
+
}
|
|
861
|
+
function processOnMainThread(arrayBuffer, options2 = {}) {
|
|
862
|
+
return new Promise((resolve, reject) => {
|
|
863
|
+
const id = requestId++;
|
|
864
|
+
const onMessage2 = (type, payload2) => {
|
|
865
|
+
if (payload2.id !== id) {
|
|
866
|
+
return;
|
|
867
|
+
}
|
|
868
|
+
switch (type) {
|
|
869
|
+
case "done":
|
|
870
|
+
WorkerBody.removeEventListener(onMessage2);
|
|
871
|
+
resolve(payload2.result);
|
|
872
|
+
break;
|
|
873
|
+
case "error":
|
|
874
|
+
WorkerBody.removeEventListener(onMessage2);
|
|
875
|
+
reject(payload2.error);
|
|
876
|
+
break;
|
|
877
|
+
default:
|
|
878
|
+
}
|
|
879
|
+
};
|
|
880
|
+
WorkerBody.addEventListener(onMessage2);
|
|
881
|
+
const payload = { id, input: arrayBuffer, options: options2 };
|
|
882
|
+
WorkerBody.postMessage("process", payload);
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
// src/lib/worker-api/validate-worker-version.ts
|
|
887
|
+
function validateWorkerVersion(worker, coreVersion = VERSION) {
|
|
888
|
+
assert(worker, "no worker provided");
|
|
889
|
+
const workerVersion = worker.version;
|
|
890
|
+
if (!coreVersion || !workerVersion) {
|
|
891
|
+
return false;
|
|
892
|
+
}
|
|
893
|
+
return true;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
// src/lib/library-utils/library-utils.ts
|
|
897
|
+
var node = __toESM(require_require_utils(), 1);
|
|
898
|
+
var loadLibraryPromises = {};
|
|
899
|
+
async function loadLibrary(libraryUrl, moduleName = null, options2 = {}, libraryName = null) {
|
|
900
|
+
if (moduleName) {
|
|
901
|
+
libraryUrl = getLibraryUrl(libraryUrl, moduleName, options2, libraryName);
|
|
902
|
+
}
|
|
903
|
+
loadLibraryPromises[libraryUrl] = // eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
904
|
+
loadLibraryPromises[libraryUrl] || loadLibraryFromFile(libraryUrl);
|
|
905
|
+
return await loadLibraryPromises[libraryUrl];
|
|
906
|
+
}
|
|
907
|
+
function getLibraryUrl(library, moduleName, options2 = {}, libraryName = null) {
|
|
908
|
+
if (!options2.useLocalLibraries && library.startsWith("http")) {
|
|
909
|
+
return library;
|
|
910
|
+
}
|
|
911
|
+
libraryName = libraryName || library;
|
|
912
|
+
const modules = options2.modules || {};
|
|
913
|
+
if (modules[libraryName]) {
|
|
914
|
+
return modules[libraryName];
|
|
915
|
+
}
|
|
916
|
+
if (!isBrowser) {
|
|
917
|
+
return `modules/${moduleName}/dist/libs/${libraryName}`;
|
|
918
|
+
}
|
|
919
|
+
if (options2.CDN) {
|
|
920
|
+
assert(options2.CDN.startsWith("http"));
|
|
921
|
+
return `${options2.CDN}/${moduleName}@${VERSION}/dist/libs/${libraryName}`;
|
|
922
|
+
}
|
|
923
|
+
if (isWorker) {
|
|
924
|
+
return `../src/libs/${libraryName}`;
|
|
925
|
+
}
|
|
926
|
+
return `modules/${moduleName}/src/libs/${libraryName}`;
|
|
927
|
+
}
|
|
928
|
+
async function loadLibraryFromFile(libraryUrl) {
|
|
929
|
+
if (libraryUrl.endsWith("wasm")) {
|
|
930
|
+
return await loadAsArrayBuffer(libraryUrl);
|
|
931
|
+
}
|
|
932
|
+
if (!isBrowser) {
|
|
933
|
+
try {
|
|
934
|
+
return node && void 0 && await (void 0)(libraryUrl);
|
|
935
|
+
} catch (error) {
|
|
936
|
+
console.error(error);
|
|
937
|
+
return null;
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
if (isWorker) {
|
|
941
|
+
return importScripts(libraryUrl);
|
|
942
|
+
}
|
|
943
|
+
const scriptSource = await loadAsText(libraryUrl);
|
|
944
|
+
return loadLibraryFromString(scriptSource, libraryUrl);
|
|
945
|
+
}
|
|
946
|
+
function loadLibraryFromString(scriptSource, id) {
|
|
947
|
+
if (!isBrowser) {
|
|
948
|
+
return void 0 && (void 0)(scriptSource, id);
|
|
949
|
+
}
|
|
950
|
+
if (isWorker) {
|
|
951
|
+
eval.call(globalThis, scriptSource);
|
|
952
|
+
return null;
|
|
953
|
+
}
|
|
954
|
+
const script = document.createElement("script");
|
|
955
|
+
script.id = id;
|
|
956
|
+
try {
|
|
957
|
+
script.appendChild(document.createTextNode(scriptSource));
|
|
958
|
+
} catch (e) {
|
|
959
|
+
script.text = scriptSource;
|
|
960
|
+
}
|
|
961
|
+
document.body.appendChild(script);
|
|
962
|
+
return null;
|
|
963
|
+
}
|
|
964
|
+
async function loadAsArrayBuffer(url) {
|
|
965
|
+
if (!void 0 || url.startsWith("http")) {
|
|
966
|
+
const response = await fetch(url);
|
|
967
|
+
return await response.arrayBuffer();
|
|
968
|
+
}
|
|
969
|
+
return await (void 0)(url);
|
|
970
|
+
}
|
|
971
|
+
async function loadAsText(url) {
|
|
972
|
+
if (!void 0 || url.startsWith("http")) {
|
|
973
|
+
const response = await fetch(url);
|
|
974
|
+
return await response.text();
|
|
975
|
+
}
|
|
976
|
+
return await (void 0)(url);
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
// src/index.ts
|
|
980
|
+
var import_child_process_proxy = __toESM(require_child_process_proxy(), 1);
|
|
981
|
+
var NullWorker = {
|
|
982
|
+
id: "null",
|
|
983
|
+
name: "null",
|
|
984
|
+
module: "worker-utils",
|
|
985
|
+
version: VERSION,
|
|
986
|
+
options: {
|
|
987
|
+
null: {}
|
|
988
|
+
}
|
|
989
|
+
};
|