web-worker-helper
Advanced tools
Comparing version 0.0.3 to 0.0.4-beta.0
@@ -1,2 +0,2 @@ | ||
export declare const version = "0.0.3"; | ||
export { default as version } from './version'; | ||
import type { WorkerObject } from './types'; | ||
@@ -3,0 +3,0 @@ export type { WorkerObject, WorkerOptions, WorkerMessage, WorkerMessageType, WorkerMessageData, WorkerMessagePayload, } from './types'; |
@@ -1,2 +0,2 @@ | ||
export var version = '0.0.3'; | ||
export { default as version } from './version'; | ||
// GENERAL UTILS | ||
@@ -3,0 +3,0 @@ export { assert } from './utils/env-utils/assert'; |
/** | ||
* Worker 配置项 | ||
*/ | ||
export declare type WorkerOptions = { | ||
export type WorkerOptions = { | ||
CDN?: string; | ||
@@ -13,12 +13,12 @@ worker?: boolean; | ||
}; | ||
export declare type WorkerContext = { | ||
export type WorkerContext = { | ||
process?: Process; | ||
processInBatches?: ProcessInBatches; | ||
}; | ||
export declare type Process = (data: any, options?: Record<string, any>, context?: WorkerContext) => any; | ||
export declare type ProcessInBatches = (iterator: AsyncIterable<any> | Iterable<any>, options?: Record<string, any>, context?: WorkerContext) => AsyncIterable<any>; | ||
export type Process = (data: any, options?: Record<string, any>, context?: WorkerContext) => any; | ||
export type ProcessInBatches = (iterator: AsyncIterable<any> | Iterable<any>, options?: Record<string, any>, context?: WorkerContext) => AsyncIterable<any>; | ||
/** | ||
* worker 类型定义, worker 描述对象 | ||
*/ | ||
export declare type WorkerObject = { | ||
export type WorkerObject = { | ||
id: string; | ||
@@ -32,4 +32,4 @@ name: string; | ||
}; | ||
export declare type WorkerMessageType = 'process' | 'done' | 'error' | 'process-in-batches' | 'input-batch' | 'input-done' | 'output-batch'; | ||
export declare type WorkerMessagePayload = { | ||
export type WorkerMessageType = 'process' | 'done' | 'error' | 'process-in-batches' | 'input-batch' | 'input-done' | 'output-batch'; | ||
export type WorkerMessagePayload = { | ||
id?: number; | ||
@@ -41,3 +41,3 @@ options?: Record<string, any>; | ||
}; | ||
export declare type WorkerMessageData = { | ||
export type WorkerMessageData = { | ||
source: string; | ||
@@ -47,5 +47,5 @@ type: WorkerMessageType; | ||
}; | ||
export declare type WorkerMessage = { | ||
export type WorkerMessage = { | ||
type: string; | ||
data: WorkerMessageData; | ||
}; |
@@ -16,3 +16,3 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
while (g && (g = 0, op[0] && (_ = 0)), _) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
@@ -57,6 +57,6 @@ if (y = 0, t) op = [op[0] & 2, t.value]; | ||
*/ | ||
export function loadLibrary(libraryUrl, moduleName, options) { | ||
if (moduleName === void 0) { moduleName = null; } | ||
if (options === void 0) { options = {}; } | ||
return __awaiter(this, void 0, void 0, function () { | ||
export function loadLibrary(libraryUrl_1) { | ||
return __awaiter(this, arguments, void 0, function (libraryUrl, moduleName, options) { | ||
if (moduleName === void 0) { moduleName = null; } | ||
if (options === void 0) { options = {}; } | ||
return __generator(this, function (_a) { | ||
@@ -90,9 +90,9 @@ switch (_a.label) { | ||
assert(options.CDN.startsWith('http')); | ||
return options.CDN + "/" + moduleName + "/dist/libs/" + library; | ||
return "".concat(options.CDN, "/").concat(moduleName, "/dist/libs/").concat(library); | ||
} | ||
// TODO - loading inside workers requires paths relative to worker script location... | ||
if (isWorker) { | ||
return "../src/libs/" + library; | ||
return "../src/libs/".concat(library); | ||
} | ||
return "modules/" + moduleName + "/src/libs/" + library; | ||
return "modules/".concat(moduleName, "/src/libs/").concat(library); | ||
} | ||
@@ -99,0 +99,0 @@ function loadLibraryFromFile(libraryUrl) { |
@@ -63,3 +63,3 @@ import { assert } from '../env-utils/assert'; | ||
function buildScriptSource(workerUrl) { | ||
return "try {\n importScripts('" + workerUrl + "');\n} catch (error) {\n console.error(error);\n throw error;\n}"; | ||
return "try {\n importScripts('".concat(workerUrl, "');\n} catch (error) {\n console.error(error);\n throw error;\n}"); | ||
} |
import type { WorkerContext, Process, ProcessInBatches } from '../types'; | ||
export declare type ProcessOnMainThread = (data: any, options?: Record<string, any>, context?: WorkerContext) => any; | ||
export type ProcessOnMainThread = (data: any, options?: Record<string, any>, context?: WorkerContext) => any; | ||
/** | ||
@@ -4,0 +4,0 @@ * Set up a WebWorkerGlobalScope to talk with the main thread |
@@ -16,3 +16,3 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
while (g && (g = 0, op[0] && (_ = 0)), _) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
@@ -65,8 +65,8 @@ if (y = 0, t) op = [op[0] & 2, t.value]; | ||
WorkerBody.onmessage = function (type, payload) { return __awaiter(_this, void 0, void 0, function () { | ||
var _a, result, resultIterator, resultIterator_1, resultIterator_1_1, batch, e_1_1, error_1, message; | ||
var e_1, _b; | ||
return __generator(this, function (_c) { | ||
switch (_c.label) { | ||
var _a, result, resultIterator, _b, resultIterator_1, resultIterator_1_1, batch, e_1_1, error_1, message; | ||
var _c, e_1, _d, _e; | ||
return __generator(this, function (_f) { | ||
switch (_f.label) { | ||
case 0: | ||
_c.trys.push([0, 19, , 20]); | ||
_f.trys.push([0, 19, , 20]); | ||
_a = type; | ||
@@ -86,3 +86,3 @@ switch (_a) { | ||
case 2: | ||
result = _c.sent(); | ||
result = _f.sent(); | ||
WorkerBody.postMessage('done', { result: result }); | ||
@@ -97,26 +97,30 @@ return [3 /*break*/, 18]; | ||
resultIterator = processInBatches(inputBatches, options, context); | ||
_c.label = 4; | ||
_f.label = 4; | ||
case 4: | ||
_c.trys.push([4, 9, 10, 15]); | ||
resultIterator_1 = __asyncValues(resultIterator); | ||
_c.label = 5; | ||
_f.trys.push([4, 9, 10, 15]); | ||
_b = true, resultIterator_1 = __asyncValues(resultIterator); | ||
_f.label = 5; | ||
case 5: return [4 /*yield*/, resultIterator_1.next()]; | ||
case 6: | ||
if (!(resultIterator_1_1 = _c.sent(), !resultIterator_1_1.done)) return [3 /*break*/, 8]; | ||
batch = resultIterator_1_1.value; | ||
if (!(resultIterator_1_1 = _f.sent(), _c = resultIterator_1_1.done, !_c)) return [3 /*break*/, 8]; | ||
_e = resultIterator_1_1.value; | ||
_b = false; | ||
batch = _e; | ||
WorkerBody.postMessage('output-batch', { result: batch }); | ||
_c.label = 7; | ||
case 7: return [3 /*break*/, 5]; | ||
_f.label = 7; | ||
case 7: | ||
_b = true; | ||
return [3 /*break*/, 5]; | ||
case 8: return [3 /*break*/, 15]; | ||
case 9: | ||
e_1_1 = _c.sent(); | ||
e_1_1 = _f.sent(); | ||
e_1 = { error: e_1_1 }; | ||
return [3 /*break*/, 15]; | ||
case 10: | ||
_c.trys.push([10, , 13, 14]); | ||
if (!(resultIterator_1_1 && !resultIterator_1_1.done && (_b = resultIterator_1.return))) return [3 /*break*/, 12]; | ||
return [4 /*yield*/, _b.call(resultIterator_1)]; | ||
_f.trys.push([10, , 13, 14]); | ||
if (!(!_b && !_c && (_d = resultIterator_1.return))) return [3 /*break*/, 12]; | ||
return [4 /*yield*/, _d.call(resultIterator_1)]; | ||
case 11: | ||
_c.sent(); | ||
_c.label = 12; | ||
_f.sent(); | ||
_f.label = 12; | ||
case 12: return [3 /*break*/, 14]; | ||
@@ -138,3 +142,3 @@ case 13: | ||
case 19: | ||
error_1 = _c.sent(); | ||
error_1 = _f.sent(); | ||
message = error_1 instanceof Error ? error_1.message : ''; | ||
@@ -141,0 +145,0 @@ WorkerBody.postMessage('error', { error: message }); |
@@ -6,3 +6,3 @@ import { assert } from '../utils/env-utils/assert'; | ||
export function getWorkerName(worker) { | ||
return "" + worker.name; | ||
return "".concat(worker.name); | ||
} | ||
@@ -19,11 +19,11 @@ /** | ||
var workerOptions = options[worker.id] || {}; | ||
var workerFileName = worker.name + ".worker.js"; | ||
var workerFileName = "".concat(worker.name, ".worker.js"); | ||
var url = workerOptions.workerUrl; | ||
// If URL is test | ||
if (options._workerType === 'test') { | ||
url = worker.module + "/dist/" + workerFileName; | ||
url = "".concat(worker.module, "/dist/").concat(workerFileName); | ||
} | ||
// If url override is not provided, generate a URL to published version on npm CDN unpkg.com | ||
if (!url) { | ||
url = "https://unpkg.com/" + worker.module + "/dist/" + workerFileName; | ||
url = "https://unpkg.com/".concat(worker.module, "/dist/").concat(workerFileName); | ||
} | ||
@@ -30,0 +30,0 @@ assert(url); |
import type { WorkerObject, WorkerOptions, WorkerContext } from '../types'; | ||
declare type ProcessOnWorkerOptions = WorkerOptions & { | ||
type ProcessOnWorkerOptions = WorkerOptions & { | ||
jobName?: string; | ||
@@ -4,0 +4,0 @@ [key: string]: any; |
@@ -16,3 +16,3 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
while (g && (g = 0, op[0] && (_ = 0)), _) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
@@ -57,7 +57,7 @@ if (y = 0, t) op = [op[0] & 2, t.value]; | ||
*/ | ||
export function processOnWorker(worker, data, options, context) { | ||
if (options === void 0) { options = {}; } | ||
if (context === void 0) { context = {}; } | ||
return __awaiter(this, void 0, void 0, function () { | ||
export function processOnWorker(worker_1, data_1) { | ||
return __awaiter(this, arguments, void 0, function (worker, data, options, context) { | ||
var name, url, workerFarm, workerPool, jobName, job, transferableOptions, result; | ||
if (options === void 0) { options = {}; } | ||
if (context === void 0) { context = {}; } | ||
return __generator(this, function (_a) { | ||
@@ -131,3 +131,3 @@ switch (_a.label) { | ||
case 8: | ||
console.warn("process-on-worker: unknown message " + type); | ||
console.warn("process-on-worker: unknown message ".concat(type)); | ||
_b.label = 9; | ||
@@ -134,0 +134,0 @@ case 9: return [2 /*return*/]; |
import WorkerPool from './worker-pool'; | ||
export declare type WorkerFarmProps = { | ||
export type WorkerFarmProps = { | ||
maxConcurrency?: number; | ||
@@ -4,0 +4,0 @@ maxMobileConcurrency?: number; |
@@ -24,3 +24,3 @@ import { assert } from '../utils/env-utils/assert'; | ||
this.workerThread.postMessage({ | ||
source: 'Main thread', | ||
source: 'Main thread', // Lets worker ignore unrelated messages | ||
type: type, | ||
@@ -27,0 +27,0 @@ payload: payload, |
@@ -5,3 +5,3 @@ import type { WorkerMessageType, WorkerMessagePayload } from '../types'; | ||
/** WorkerPool onDebug Callback Parameters */ | ||
declare type OnDebugParameters = { | ||
type OnDebugParameters = { | ||
message: string; | ||
@@ -13,3 +13,3 @@ name: string; | ||
/** WorkerPool Properties */ | ||
export declare type WorkerPoolProps = { | ||
export type WorkerPoolProps = { | ||
name?: string; | ||
@@ -24,4 +24,4 @@ source?: string; | ||
/** Private helper types */ | ||
declare type OnMessage = (job: WorkerJob, type: WorkerMessageType, payload: WorkerMessagePayload) => void; | ||
declare type OnError = (job: WorkerJob, error: Error) => void; | ||
type OnMessage = (job: WorkerJob, type: WorkerMessageType, payload: WorkerMessagePayload) => void; | ||
type OnError = (job: WorkerJob, error: Error) => void; | ||
/** | ||
@@ -28,0 +28,0 @@ * Process multiple data messages with small pool of identical workers |
@@ -27,3 +27,3 @@ var __assign = (this && this.__assign) || function () { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
while (g && (g = 0, op[0] && (_ = 0)), _) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
@@ -98,8 +98,8 @@ if (y = 0, t) op = [op[0] & 2, t.value]; | ||
}; | ||
WorkerPool.prototype.startJob = function (name, onMessage, onError) { | ||
if (onMessage === void 0) { onMessage = function (job, type, data) { return job.done(data); }; } | ||
if (onError === void 0) { onError = function (job, error) { return job.error(error); }; } | ||
return __awaiter(this, void 0, void 0, function () { | ||
WorkerPool.prototype.startJob = function (name_1) { | ||
return __awaiter(this, arguments, void 0, function (name, onMessage, onError) { | ||
var startPromise; | ||
var _this = this; | ||
if (onMessage === void 0) { onMessage = function (job, type, data) { return job.done(data); }; } | ||
if (onError === void 0) { onError = function (job, error) { return job.error(error); }; } | ||
return __generator(this, function (_a) { | ||
@@ -197,3 +197,3 @@ switch (_a.label) { | ||
this.count++; | ||
var name_1 = this.name.toLowerCase() + " (#" + this.count + " of " + this.maxConcurrency + ")"; | ||
var name_1 = "".concat(this.name.toLowerCase(), " (#").concat(this.count, " of ").concat(this.maxConcurrency, ")"); | ||
return new WorkerThread({ name: name_1, source: this.source, url: this.url }); | ||
@@ -200,0 +200,0 @@ } |
@@ -1,2 +0,2 @@ | ||
export declare type WorkerThreadProps = { | ||
export type WorkerThreadProps = { | ||
name: string; | ||
@@ -3,0 +3,0 @@ source?: string; |
@@ -60,5 +60,5 @@ import { assert } from '../utils/env-utils/assert'; | ||
var message = 'Failed to load '; | ||
message += "worker " + this.name + " from " + this.url + ". "; | ||
message += "worker ".concat(this.name, " from ").concat(this.url, ". "); | ||
if (event.message) { | ||
message += event.message + " in "; | ||
message += "".concat(event.message, " in "); | ||
} | ||
@@ -68,3 +68,3 @@ // const hasFilename = event.filename && !event.filename.startsWith('blob:'); | ||
if (event.lineno) { | ||
message += ":" + event.lineno + ":" + event.colno; | ||
message += ":".concat(event.lineno, ":").concat(event.colno); | ||
} | ||
@@ -93,3 +93,3 @@ return new Error(message); | ||
}; | ||
worker.onmessageerror = function (event) { return console.error("worker " + _this.name + ", message error: " + event); }; | ||
worker.onmessageerror = function (event) { return console.error("worker ".concat(_this.name, ", message error: ").concat(event)); }; | ||
return worker; | ||
@@ -96,0 +96,0 @@ }; |
@@ -16,3 +16,3 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
while (g && (g = 0, op[0] && (_ = 0)), _) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
@@ -19,0 +19,0 @@ if (y = 0, t) op = [op[0] & 2, t.value]; |
@@ -1,2 +0,2 @@ | ||
export declare const version = "0.0.3"; | ||
export { default as version } from './version'; | ||
import type { WorkerObject } from './types'; | ||
@@ -3,0 +3,0 @@ export type { WorkerObject, WorkerOptions, WorkerMessage, WorkerMessageType, WorkerMessageData, WorkerMessagePayload, } from './types'; |
@@ -7,3 +7,4 @@ "use strict"; | ||
exports.NullWorker = exports.AsyncQueue = exports.loadLibrary = exports.getLibraryUrl = exports.getTransferList = exports.getWorkerURL = exports.createWorker = exports.canProcessOnWorker = exports.processOnWorker = exports.WorkerBody = exports.WorkerPool = exports.WorkerFarm = exports.WorkerThread = exports.WorkerJob = exports.isWorker = exports.assert = exports.version = void 0; | ||
exports.version = '0.0.3'; | ||
var version_1 = require("./version"); | ||
Object.defineProperty(exports, "version", { enumerable: true, get: function () { return __importDefault(version_1).default; } }); | ||
// GENERAL UTILS | ||
@@ -10,0 +11,0 @@ var assert_1 = require("./utils/env-utils/assert"); |
/** | ||
* Worker 配置项 | ||
*/ | ||
export declare type WorkerOptions = { | ||
export type WorkerOptions = { | ||
CDN?: string; | ||
@@ -13,12 +13,12 @@ worker?: boolean; | ||
}; | ||
export declare type WorkerContext = { | ||
export type WorkerContext = { | ||
process?: Process; | ||
processInBatches?: ProcessInBatches; | ||
}; | ||
export declare type Process = (data: any, options?: Record<string, any>, context?: WorkerContext) => any; | ||
export declare type ProcessInBatches = (iterator: AsyncIterable<any> | Iterable<any>, options?: Record<string, any>, context?: WorkerContext) => AsyncIterable<any>; | ||
export type Process = (data: any, options?: Record<string, any>, context?: WorkerContext) => any; | ||
export type ProcessInBatches = (iterator: AsyncIterable<any> | Iterable<any>, options?: Record<string, any>, context?: WorkerContext) => AsyncIterable<any>; | ||
/** | ||
* worker 类型定义, worker 描述对象 | ||
*/ | ||
export declare type WorkerObject = { | ||
export type WorkerObject = { | ||
id: string; | ||
@@ -32,4 +32,4 @@ name: string; | ||
}; | ||
export declare type WorkerMessageType = 'process' | 'done' | 'error' | 'process-in-batches' | 'input-batch' | 'input-done' | 'output-batch'; | ||
export declare type WorkerMessagePayload = { | ||
export type WorkerMessageType = 'process' | 'done' | 'error' | 'process-in-batches' | 'input-batch' | 'input-done' | 'output-batch'; | ||
export type WorkerMessagePayload = { | ||
id?: number; | ||
@@ -41,3 +41,3 @@ options?: Record<string, any>; | ||
}; | ||
export declare type WorkerMessageData = { | ||
export type WorkerMessageData = { | ||
source: string; | ||
@@ -47,5 +47,5 @@ type: WorkerMessageType; | ||
}; | ||
export declare type WorkerMessage = { | ||
export type WorkerMessage = { | ||
type: string; | ||
data: WorkerMessageData; | ||
}; |
@@ -17,3 +17,3 @@ "use strict"; | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
while (g && (g = 0, op[0] && (_ = 0)), _) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
@@ -60,6 +60,6 @@ if (y = 0, t) op = [op[0] & 2, t.value]; | ||
*/ | ||
function loadLibrary(libraryUrl, moduleName, options) { | ||
if (moduleName === void 0) { moduleName = null; } | ||
if (options === void 0) { options = {}; } | ||
return __awaiter(this, void 0, void 0, function () { | ||
function loadLibrary(libraryUrl_1) { | ||
return __awaiter(this, arguments, void 0, function (libraryUrl, moduleName, options) { | ||
if (moduleName === void 0) { moduleName = null; } | ||
if (options === void 0) { options = {}; } | ||
return __generator(this, function (_a) { | ||
@@ -94,9 +94,9 @@ switch (_a.label) { | ||
(0, assert_1.assert)(options.CDN.startsWith('http')); | ||
return options.CDN + "/" + moduleName + "/dist/libs/" + library; | ||
return "".concat(options.CDN, "/").concat(moduleName, "/dist/libs/").concat(library); | ||
} | ||
// TODO - loading inside workers requires paths relative to worker script location... | ||
if (globals_1.isWorker) { | ||
return "../src/libs/" + library; | ||
return "../src/libs/".concat(library); | ||
} | ||
return "modules/" + moduleName + "/src/libs/" + library; | ||
return "modules/".concat(moduleName, "/src/libs/").concat(library); | ||
} | ||
@@ -103,0 +103,0 @@ exports.getLibraryUrl = getLibraryUrl; |
@@ -67,3 +67,3 @@ "use strict"; | ||
function buildScriptSource(workerUrl) { | ||
return "try {\n importScripts('" + workerUrl + "');\n} catch (error) {\n console.error(error);\n throw error;\n}"; | ||
return "try {\n importScripts('".concat(workerUrl, "');\n} catch (error) {\n console.error(error);\n throw error;\n}"); | ||
} |
import type { WorkerContext, Process, ProcessInBatches } from '../types'; | ||
export declare type ProcessOnMainThread = (data: any, options?: Record<string, any>, context?: WorkerContext) => any; | ||
export type ProcessOnMainThread = (data: any, options?: Record<string, any>, context?: WorkerContext) => any; | ||
/** | ||
@@ -4,0 +4,0 @@ * Set up a WebWorkerGlobalScope to talk with the main thread |
@@ -17,3 +17,3 @@ "use strict"; | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
while (g && (g = 0, op[0] && (_ = 0)), _) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
@@ -71,8 +71,8 @@ if (y = 0, t) op = [op[0] & 2, t.value]; | ||
worker_body_1.default.onmessage = function (type, payload) { return __awaiter(_this, void 0, void 0, function () { | ||
var _a, result, resultIterator, resultIterator_1, resultIterator_1_1, batch, e_1_1, error_1, message; | ||
var e_1, _b; | ||
return __generator(this, function (_c) { | ||
switch (_c.label) { | ||
var _a, result, resultIterator, _b, resultIterator_1, resultIterator_1_1, batch, e_1_1, error_1, message; | ||
var _c, e_1, _d, _e; | ||
return __generator(this, function (_f) { | ||
switch (_f.label) { | ||
case 0: | ||
_c.trys.push([0, 19, , 20]); | ||
_f.trys.push([0, 19, , 20]); | ||
_a = type; | ||
@@ -92,3 +92,3 @@ switch (_a) { | ||
case 2: | ||
result = _c.sent(); | ||
result = _f.sent(); | ||
worker_body_1.default.postMessage('done', { result: result }); | ||
@@ -103,26 +103,30 @@ return [3 /*break*/, 18]; | ||
resultIterator = processInBatches(inputBatches, options, context); | ||
_c.label = 4; | ||
_f.label = 4; | ||
case 4: | ||
_c.trys.push([4, 9, 10, 15]); | ||
resultIterator_1 = __asyncValues(resultIterator); | ||
_c.label = 5; | ||
_f.trys.push([4, 9, 10, 15]); | ||
_b = true, resultIterator_1 = __asyncValues(resultIterator); | ||
_f.label = 5; | ||
case 5: return [4 /*yield*/, resultIterator_1.next()]; | ||
case 6: | ||
if (!(resultIterator_1_1 = _c.sent(), !resultIterator_1_1.done)) return [3 /*break*/, 8]; | ||
batch = resultIterator_1_1.value; | ||
if (!(resultIterator_1_1 = _f.sent(), _c = resultIterator_1_1.done, !_c)) return [3 /*break*/, 8]; | ||
_e = resultIterator_1_1.value; | ||
_b = false; | ||
batch = _e; | ||
worker_body_1.default.postMessage('output-batch', { result: batch }); | ||
_c.label = 7; | ||
case 7: return [3 /*break*/, 5]; | ||
_f.label = 7; | ||
case 7: | ||
_b = true; | ||
return [3 /*break*/, 5]; | ||
case 8: return [3 /*break*/, 15]; | ||
case 9: | ||
e_1_1 = _c.sent(); | ||
e_1_1 = _f.sent(); | ||
e_1 = { error: e_1_1 }; | ||
return [3 /*break*/, 15]; | ||
case 10: | ||
_c.trys.push([10, , 13, 14]); | ||
if (!(resultIterator_1_1 && !resultIterator_1_1.done && (_b = resultIterator_1.return))) return [3 /*break*/, 12]; | ||
return [4 /*yield*/, _b.call(resultIterator_1)]; | ||
_f.trys.push([10, , 13, 14]); | ||
if (!(!_b && !_c && (_d = resultIterator_1.return))) return [3 /*break*/, 12]; | ||
return [4 /*yield*/, _d.call(resultIterator_1)]; | ||
case 11: | ||
_c.sent(); | ||
_c.label = 12; | ||
_f.sent(); | ||
_f.label = 12; | ||
case 12: return [3 /*break*/, 14]; | ||
@@ -144,3 +148,3 @@ case 13: | ||
case 19: | ||
error_1 = _c.sent(); | ||
error_1 = _f.sent(); | ||
message = error_1 instanceof Error ? error_1.message : ''; | ||
@@ -147,0 +151,0 @@ worker_body_1.default.postMessage('error', { error: message }); |
@@ -9,3 +9,3 @@ "use strict"; | ||
function getWorkerName(worker) { | ||
return "" + worker.name; | ||
return "".concat(worker.name); | ||
} | ||
@@ -23,11 +23,11 @@ exports.getWorkerName = getWorkerName; | ||
var workerOptions = options[worker.id] || {}; | ||
var workerFileName = worker.name + ".worker.js"; | ||
var workerFileName = "".concat(worker.name, ".worker.js"); | ||
var url = workerOptions.workerUrl; | ||
// If URL is test | ||
if (options._workerType === 'test') { | ||
url = worker.module + "/dist/" + workerFileName; | ||
url = "".concat(worker.module, "/dist/").concat(workerFileName); | ||
} | ||
// If url override is not provided, generate a URL to published version on npm CDN unpkg.com | ||
if (!url) { | ||
url = "https://unpkg.com/" + worker.module + "/dist/" + workerFileName; | ||
url = "https://unpkg.com/".concat(worker.module, "/dist/").concat(workerFileName); | ||
} | ||
@@ -34,0 +34,0 @@ (0, assert_1.assert)(url); |
import type { WorkerObject, WorkerOptions, WorkerContext } from '../types'; | ||
declare type ProcessOnWorkerOptions = WorkerOptions & { | ||
type ProcessOnWorkerOptions = WorkerOptions & { | ||
jobName?: string; | ||
@@ -4,0 +4,0 @@ [key: string]: any; |
@@ -17,3 +17,3 @@ "use strict"; | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
while (g && (g = 0, op[0] && (_ = 0)), _) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
@@ -64,7 +64,7 @@ if (y = 0, t) op = [op[0] & 2, t.value]; | ||
*/ | ||
function processOnWorker(worker, data, options, context) { | ||
if (options === void 0) { options = {}; } | ||
if (context === void 0) { context = {}; } | ||
return __awaiter(this, void 0, void 0, function () { | ||
function processOnWorker(worker_1, data_1) { | ||
return __awaiter(this, arguments, void 0, function (worker, data, options, context) { | ||
var name, url, workerFarm, workerPool, jobName, job, transferableOptions, result; | ||
if (options === void 0) { options = {}; } | ||
if (context === void 0) { context = {}; } | ||
return __generator(this, function (_a) { | ||
@@ -139,3 +139,3 @@ switch (_a.label) { | ||
case 8: | ||
console.warn("process-on-worker: unknown message " + type); | ||
console.warn("process-on-worker: unknown message ".concat(type)); | ||
_b.label = 9; | ||
@@ -142,0 +142,0 @@ case 9: return [2 /*return*/]; |
import WorkerPool from './worker-pool'; | ||
export declare type WorkerFarmProps = { | ||
export type WorkerFarmProps = { | ||
maxConcurrency?: number; | ||
@@ -4,0 +4,0 @@ maxMobileConcurrency?: number; |
@@ -26,3 +26,3 @@ "use strict"; | ||
this.workerThread.postMessage({ | ||
source: 'Main thread', | ||
source: 'Main thread', // Lets worker ignore unrelated messages | ||
type: type, | ||
@@ -29,0 +29,0 @@ payload: payload, |
@@ -5,3 +5,3 @@ import type { WorkerMessageType, WorkerMessagePayload } from '../types'; | ||
/** WorkerPool onDebug Callback Parameters */ | ||
declare type OnDebugParameters = { | ||
type OnDebugParameters = { | ||
message: string; | ||
@@ -13,3 +13,3 @@ name: string; | ||
/** WorkerPool Properties */ | ||
export declare type WorkerPoolProps = { | ||
export type WorkerPoolProps = { | ||
name?: string; | ||
@@ -24,4 +24,4 @@ source?: string; | ||
/** Private helper types */ | ||
declare type OnMessage = (job: WorkerJob, type: WorkerMessageType, payload: WorkerMessagePayload) => void; | ||
declare type OnError = (job: WorkerJob, error: Error) => void; | ||
type OnMessage = (job: WorkerJob, type: WorkerMessageType, payload: WorkerMessagePayload) => void; | ||
type OnError = (job: WorkerJob, error: Error) => void; | ||
/** | ||
@@ -28,0 +28,0 @@ * Process multiple data messages with small pool of identical workers |
@@ -28,3 +28,3 @@ "use strict"; | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
while (g && (g = 0, op[0] && (_ = 0)), _) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
@@ -103,8 +103,8 @@ if (y = 0, t) op = [op[0] & 2, t.value]; | ||
}; | ||
WorkerPool.prototype.startJob = function (name, onMessage, onError) { | ||
if (onMessage === void 0) { onMessage = function (job, type, data) { return job.done(data); }; } | ||
if (onError === void 0) { onError = function (job, error) { return job.error(error); }; } | ||
return __awaiter(this, void 0, void 0, function () { | ||
WorkerPool.prototype.startJob = function (name_1) { | ||
return __awaiter(this, arguments, void 0, function (name, onMessage, onError) { | ||
var startPromise; | ||
var _this = this; | ||
if (onMessage === void 0) { onMessage = function (job, type, data) { return job.done(data); }; } | ||
if (onError === void 0) { onError = function (job, error) { return job.error(error); }; } | ||
return __generator(this, function (_a) { | ||
@@ -202,3 +202,3 @@ switch (_a.label) { | ||
this.count++; | ||
var name_1 = this.name.toLowerCase() + " (#" + this.count + " of " + this.maxConcurrency + ")"; | ||
var name_1 = "".concat(this.name.toLowerCase(), " (#").concat(this.count, " of ").concat(this.maxConcurrency, ")"); | ||
return new worker_thread_1.default({ name: name_1, source: this.source, url: this.url }); | ||
@@ -205,0 +205,0 @@ } |
@@ -1,2 +0,2 @@ | ||
export declare type WorkerThreadProps = { | ||
export type WorkerThreadProps = { | ||
name: string; | ||
@@ -3,0 +3,0 @@ source?: string; |
@@ -62,5 +62,5 @@ "use strict"; | ||
var message = 'Failed to load '; | ||
message += "worker " + this.name + " from " + this.url + ". "; | ||
message += "worker ".concat(this.name, " from ").concat(this.url, ". "); | ||
if (event.message) { | ||
message += event.message + " in "; | ||
message += "".concat(event.message, " in "); | ||
} | ||
@@ -70,3 +70,3 @@ // const hasFilename = event.filename && !event.filename.startsWith('blob:'); | ||
if (event.lineno) { | ||
message += ":" + event.lineno + ":" + event.colno; | ||
message += ":".concat(event.lineno, ":").concat(event.colno); | ||
} | ||
@@ -95,3 +95,3 @@ return new Error(message); | ||
}; | ||
worker.onmessageerror = function (event) { return console.error("worker " + _this.name + ", message error: " + event); }; | ||
worker.onmessageerror = function (event) { return console.error("worker ".concat(_this.name, ", message error: ").concat(event)); }; | ||
return worker; | ||
@@ -98,0 +98,0 @@ }; |
@@ -17,3 +17,3 @@ "use strict"; | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
while (g && (g = 0, op[0] && (_ = 0)), _) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
@@ -20,0 +20,0 @@ if (y = 0, t) op = [op[0] & 2, t.value]; |
(function () { | ||
'use strict'; | ||
/****************************************************************************** | ||
Copyright (c) Microsoft Corporation. | ||
Permission to use, copy, modify, and/or distribute this software for any | ||
purpose with or without fee is hereby granted. | ||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH | ||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY | ||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, | ||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM | ||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR | ||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | ||
PERFORMANCE OF THIS SOFTWARE. | ||
***************************************************************************** */ | ||
/* global Reflect, Promise, SuppressedError, Symbol */ | ||
function __awaiter(thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
} | ||
function __generator(thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (g && (g = 0, op[0] && (_ = 0)), _) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
} | ||
function __values(o) { | ||
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; | ||
if (m) return m.call(o); | ||
if (o && typeof o.length === "number") return { | ||
next: function () { | ||
if (o && i >= o.length) o = void 0; | ||
return { value: o && o[i++], done: !o }; | ||
} | ||
}; | ||
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); | ||
} | ||
function __asyncValues(o) { | ||
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); | ||
var m = o[Symbol.asyncIterator], i; | ||
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); | ||
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } | ||
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } | ||
} | ||
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { | ||
var e = new Error(message); | ||
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; | ||
}; | ||
// From https://github.com/rauschma/async-iter-demo/tree/master/src under MIT license | ||
@@ -18,7 +98,4 @@ // http://2ality.com/2016/10/asynchronous-iteration.html | ||
*/ | ||
class AsyncQueue { | ||
_values; | ||
_settlers; | ||
_closed; | ||
constructor() { | ||
var AsyncQueue = /** @class */ (function () { | ||
function AsyncQueue() { | ||
this._values = []; // enqueues > dequeues | ||
@@ -29,9 +106,9 @@ this._settlers = []; // dequeues > enqueues | ||
/** Return an async iterator for this queue */ | ||
[Symbol.asyncIterator]() { | ||
AsyncQueue.prototype[Symbol.asyncIterator] = function () { | ||
return this; | ||
} | ||
}; | ||
/** Push a new value - the async iterator will yield a promise resolved to this value */ | ||
push(value) { | ||
AsyncQueue.prototype.push = function (value) { | ||
return this.enqueue(value); | ||
} | ||
}; | ||
/** | ||
@@ -41,3 +118,3 @@ * Push a new value - the async iterator will yield a promise resolved to this value | ||
*/ | ||
enqueue(value) { | ||
AsyncQueue.prototype.enqueue = function (value) { | ||
if (this._closed) { | ||
@@ -50,3 +127,3 @@ throw new Error('Closed'); | ||
} | ||
const settler = this._settlers.shift(); | ||
var settler = this._settlers.shift(); | ||
if (value instanceof Error) { | ||
@@ -56,3 +133,3 @@ settler.reject(value); | ||
else { | ||
settler.resolve({ value }); | ||
settler.resolve({ value: value }); | ||
} | ||
@@ -63,21 +140,22 @@ } | ||
} | ||
} | ||
}; | ||
/** Indicate that we not waiting for more values - The async iterator will be done */ | ||
close() { | ||
AsyncQueue.prototype.close = function () { | ||
while (this._settlers.length > 0) { | ||
const settler = this._settlers.shift(); | ||
var settler = this._settlers.shift(); | ||
settler.resolve({ done: true }); | ||
} | ||
this._closed = true; | ||
} | ||
}; | ||
// ITERATOR IMPLEMENTATION | ||
/** @returns a Promise for an IteratorResult */ | ||
next() { | ||
AsyncQueue.prototype.next = function () { | ||
var _this = this; | ||
// If values in queue, yield the first value | ||
if (this._values.length > 0) { | ||
const value = this._values.shift(); | ||
var value = this._values.shift(); | ||
if (value instanceof Error) { | ||
return Promise.reject(value); | ||
} | ||
return Promise.resolve({ done: false, value }); | ||
return Promise.resolve({ done: false, value: value }); | ||
} | ||
@@ -92,7 +170,8 @@ // If queue is closed, the iterator is done | ||
// Yield a promise that waits for new values to be enqueued | ||
return new Promise((resolve, reject) => { | ||
this._settlers.push({ resolve, reject }); | ||
return new Promise(function (resolve, reject) { | ||
_this._settlers.push({ resolve: resolve, reject: reject }); | ||
}); | ||
} | ||
} | ||
}; | ||
return AsyncQueue; | ||
}()); | ||
@@ -109,5 +188,6 @@ // NOTE - there is a copy of this function is both in core and loader-utils | ||
*/ | ||
function getTransferList(object, recursive = true, transfers) { | ||
function getTransferList(object, recursive, transfers) { | ||
if (recursive === void 0) { recursive = true; } | ||
// Make sure that items in the transfer list is unique | ||
const transfersSet = transfers || new Set(); | ||
var transfersSet = transfers || new Set(); | ||
if (!object) ; | ||
@@ -123,3 +203,3 @@ else if (isTransferable(object)) { | ||
else if (recursive && typeof object === 'object') { | ||
for (const key in object) { | ||
for (var key in object) { | ||
// Avoid perf hit - only go one level deep | ||
@@ -155,24 +235,30 @@ getTransferList(object[key], recursive, transfersSet); | ||
const onMessageWrapperMap = new Map(); | ||
var onMessageWrapperMap = new Map(); | ||
/** | ||
* Type safe wrapper for worker code | ||
*/ | ||
class WorkerBody { | ||
/* | ||
* (type: WorkerMessageType, payload: WorkerMessagePayload) => any | ||
*/ | ||
static set onmessage(onMessage) { | ||
self.onmessage = (message) => { | ||
if (!isKnownMessage(message)) { | ||
return; | ||
} | ||
// Confusingly the message itself also has a 'type' field which is always set to 'message' | ||
const { type, payload } = message.data; | ||
onMessage(type, payload); | ||
}; | ||
var WorkerBody = /** @class */ (function () { | ||
function WorkerBody() { | ||
} | ||
static addEventListener(onMessage) { | ||
let onMessageWrapper = onMessageWrapperMap.get(onMessage); | ||
Object.defineProperty(WorkerBody, "onmessage", { | ||
/* | ||
* (type: WorkerMessageType, payload: WorkerMessagePayload) => any | ||
*/ | ||
set: function (onMessage) { | ||
self.onmessage = function (message) { | ||
if (!isKnownMessage(message)) { | ||
return; | ||
} | ||
// Confusingly the message itself also has a 'type' field which is always set to 'message' | ||
var _a = message.data, type = _a.type, payload = _a.payload; | ||
onMessage(type, payload); | ||
}; | ||
}, | ||
enumerable: false, | ||
configurable: true | ||
}); | ||
WorkerBody.addEventListener = function (onMessage) { | ||
var onMessageWrapper = onMessageWrapperMap.get(onMessage); | ||
if (!onMessageWrapper) { | ||
onMessageWrapper = (message) => { | ||
onMessageWrapper = function (message) { | ||
if (!isKnownMessage(message)) { | ||
@@ -182,3 +268,3 @@ return; | ||
// Confusingly the message itself also has a 'type' field which is always set to 'message' | ||
const { type, payload } = message.data; | ||
var _a = message.data, type = _a.type, payload = _a.payload; | ||
onMessage(type, payload); | ||
@@ -188,8 +274,8 @@ }; | ||
self.addEventListener('message', onMessageWrapper); | ||
} | ||
static removeEventListener(onMessage) { | ||
const onMessageWrapper = onMessageWrapperMap.get(onMessage); | ||
}; | ||
WorkerBody.removeEventListener = function (onMessage) { | ||
var onMessageWrapper = onMessageWrapperMap.get(onMessage); | ||
onMessageWrapperMap.delete(onMessage); | ||
self.removeEventListener('message', onMessageWrapper); | ||
} | ||
}; | ||
/** | ||
@@ -201,6 +287,6 @@ * Send a message from a worker to creating thread (main thread) | ||
*/ | ||
static postMessage(type, payload) { | ||
WorkerBody.postMessage = function (type, payload) { | ||
if (self) { | ||
const data = { source: 'Worker thread', type, payload }; | ||
const transferList = getTransferList(payload); | ||
var data = { source: 'Worker thread', type: type, payload: payload }; | ||
var transferList = getTransferList(payload); | ||
// TODO: targetOrigin, transferList | ||
@@ -211,7 +297,8 @@ // eslint-disable-next-line @typescript-eslint/ban-ts-comment | ||
} | ||
} | ||
} | ||
}; | ||
return WorkerBody; | ||
}()); | ||
// Filter out noise messages sent to workers | ||
function isKnownMessage(message) { | ||
const { type, data } = message; | ||
var type = message.type, data = message.data; | ||
return type === 'message' && data && typeof data.source === 'string' && data.source === 'Main thread'; | ||
@@ -221,6 +308,6 @@ } | ||
/** Counter for jobs */ | ||
let requestId = 0; | ||
var requestId = 0; | ||
// 异步队列 | ||
let inputBatches; | ||
let options; | ||
var inputBatches; | ||
var options; | ||
/** | ||
@@ -230,2 +317,3 @@ * Set up a WebWorkerGlobalScope to talk with the main thread | ||
function createWorker(process, processInBatches) { | ||
var _this = this; | ||
// 检查是否在 worker 线程中 | ||
@@ -235,17 +323,30 @@ if (typeof self === 'undefined') { | ||
} | ||
const context = { | ||
var context = { | ||
process: processOnMainThread, | ||
}; | ||
WorkerBody.onmessage = async (type, payload) => { | ||
try { | ||
switch (type) { | ||
case 'process': | ||
WorkerBody.onmessage = function (type, payload) { return __awaiter(_this, void 0, void 0, function () { | ||
var _a, result, resultIterator, _b, resultIterator_1, resultIterator_1_1, batch, e_1_1, error_1, message; | ||
var _c, e_1, _d, _e; | ||
return __generator(this, function (_f) { | ||
switch (_f.label) { | ||
case 0: | ||
_f.trys.push([0, 19, , 20]); | ||
_a = type; | ||
switch (_a) { | ||
case 'process': return [3 /*break*/, 1]; | ||
case 'process-in-batches': return [3 /*break*/, 3]; | ||
case 'input-batch': return [3 /*break*/, 16]; | ||
case 'input-done': return [3 /*break*/, 17]; | ||
} | ||
return [3 /*break*/, 18]; | ||
case 1: | ||
if (!process) { | ||
throw new Error('Worker does not support atomic processing'); | ||
} | ||
// eslint-disable-next-line no-case-declarations | ||
const result = await process(payload.input, payload.options || {}, context); | ||
WorkerBody.postMessage('done', { result }); | ||
break; | ||
case 'process-in-batches': | ||
return [4 /*yield*/, process(payload.input, payload.options || {}, context)]; | ||
case 2: | ||
result = _f.sent(); | ||
WorkerBody.postMessage('done', { result: result }); | ||
return [3 /*break*/, 18]; | ||
case 3: | ||
if (!processInBatches) { | ||
@@ -256,30 +357,63 @@ throw new Error('Worker does not support batched processing'); | ||
options = payload.options || {}; | ||
// eslint-disable-next-line no-case-declarations | ||
const resultIterator = processInBatches(inputBatches, options, context); | ||
for await (const batch of resultIterator) { | ||
WorkerBody.postMessage('output-batch', { result: batch }); | ||
} | ||
resultIterator = processInBatches(inputBatches, options, context); | ||
_f.label = 4; | ||
case 4: | ||
_f.trys.push([4, 9, 10, 15]); | ||
_b = true, resultIterator_1 = __asyncValues(resultIterator); | ||
_f.label = 5; | ||
case 5: return [4 /*yield*/, resultIterator_1.next()]; | ||
case 6: | ||
if (!(resultIterator_1_1 = _f.sent(), _c = resultIterator_1_1.done, !_c)) return [3 /*break*/, 8]; | ||
_e = resultIterator_1_1.value; | ||
_b = false; | ||
batch = _e; | ||
WorkerBody.postMessage('output-batch', { result: batch }); | ||
_f.label = 7; | ||
case 7: | ||
_b = true; | ||
return [3 /*break*/, 5]; | ||
case 8: return [3 /*break*/, 15]; | ||
case 9: | ||
e_1_1 = _f.sent(); | ||
e_1 = { error: e_1_1 }; | ||
return [3 /*break*/, 15]; | ||
case 10: | ||
_f.trys.push([10, , 13, 14]); | ||
if (!(!_b && !_c && (_d = resultIterator_1.return))) return [3 /*break*/, 12]; | ||
return [4 /*yield*/, _d.call(resultIterator_1)]; | ||
case 11: | ||
_f.sent(); | ||
_f.label = 12; | ||
case 12: return [3 /*break*/, 14]; | ||
case 13: | ||
if (e_1) throw e_1.error; | ||
return [7 /*endfinally*/]; | ||
case 14: return [7 /*endfinally*/]; | ||
case 15: | ||
WorkerBody.postMessage('done', {}); | ||
break; | ||
case 'input-batch': | ||
return [3 /*break*/, 18]; | ||
case 16: | ||
inputBatches.push(payload.input); | ||
break; | ||
case 'input-done': | ||
return [3 /*break*/, 18]; | ||
case 17: | ||
inputBatches.close(); | ||
break; | ||
default: | ||
return [3 /*break*/, 18]; | ||
case 18: return [3 /*break*/, 20]; | ||
case 19: | ||
error_1 = _f.sent(); | ||
message = error_1 instanceof Error ? error_1.message : ''; | ||
WorkerBody.postMessage('error', { error: message }); | ||
return [3 /*break*/, 20]; | ||
case 20: return [2 /*return*/]; | ||
} | ||
} | ||
catch (error) { | ||
const message = error instanceof Error ? error.message : ''; | ||
WorkerBody.postMessage('error', { error: message }); | ||
} | ||
}; | ||
}); | ||
}); }; | ||
} | ||
function processOnMainThread(arrayBuffer, options = {}) { | ||
return new Promise((resolve, reject) => { | ||
const id = requestId++; | ||
function processOnMainThread(arrayBuffer, options) { | ||
if (options === void 0) { options = {}; } | ||
return new Promise(function (resolve, reject) { | ||
var id = requestId++; | ||
/** | ||
*/ | ||
const onMessage = (type, payload) => { | ||
var onMessage = function (type, payload) { | ||
if (payload.id !== id) { | ||
@@ -303,3 +437,3 @@ // not ours | ||
// Ask the main thread to decode data | ||
const payload = { id, input: arrayBuffer, options }; | ||
var payload = { id: id, input: arrayBuffer, options: options }; | ||
WorkerBody.postMessage('process', payload); | ||
@@ -309,7 +443,9 @@ }); | ||
createWorker(async (data, options) => { | ||
return data; | ||
}); | ||
createWorker(function (data, options) { return __awaiter(void 0, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
return [2 /*return*/, data]; | ||
}); | ||
}); }); | ||
})(); | ||
//# sourceMappingURL=null.worker.js.map |
@@ -7,2 +7,4 @@ (function (global, factory) { | ||
var version = '0.0.4-beta.0'; | ||
// Replacement for the external assert method to reduce bundle size | ||
@@ -21,3 +23,3 @@ // Note: We don't use the second "message" argument in calling code, | ||
/* eslint-disable no-restricted-globals */ | ||
const globals = { | ||
var globals = { | ||
self: typeof self !== 'undefined' && self, | ||
@@ -27,7 +29,7 @@ window: typeof window !== 'undefined' && window, | ||
}; | ||
const global_ = globals.self || globals.window || {}; | ||
var global_ = globals.self || globals.window || {}; | ||
/** true if running on a worker thread */ | ||
const isWorker = typeof importScripts === 'function'; | ||
var isWorker = typeof importScripts === 'function'; | ||
/** true if running on a mobile device */ | ||
const isMobile = typeof window !== 'undefined' && typeof window.orientation !== 'undefined'; | ||
var isMobile = typeof window !== 'undefined' && typeof window.orientation !== 'undefined'; | ||
@@ -37,19 +39,13 @@ /** | ||
*/ | ||
class WorkerJob { | ||
name; | ||
workerThread; | ||
isRunning; | ||
/** Promise that resolves when Job is done */ | ||
result; | ||
resolve; | ||
reject; | ||
constructor(jobName, workerThread) { | ||
var WorkerJob = /** @class */ (function () { | ||
function WorkerJob(jobName, workerThread) { | ||
var _this = this; | ||
this.name = jobName; | ||
this.workerThread = workerThread; | ||
this.isRunning = true; | ||
this.resolve = () => { }; | ||
this.reject = () => { }; | ||
this.result = new Promise((resolve, reject) => { | ||
this.resolve = resolve; | ||
this.reject = reject; | ||
this.resolve = function () { }; | ||
this.reject = function () { }; | ||
this.result = new Promise(function (resolve, reject) { | ||
_this.resolve = resolve; | ||
_this.reject = reject; | ||
}); | ||
@@ -61,28 +57,29 @@ } | ||
*/ | ||
postMessage(type, payload) { | ||
WorkerJob.prototype.postMessage = function (type, payload) { | ||
this.workerThread.postMessage({ | ||
source: 'Main thread', | ||
type, | ||
payload, | ||
source: 'Main thread', // Lets worker ignore unrelated messages | ||
type: type, | ||
payload: payload, | ||
}); | ||
} | ||
}; | ||
/** | ||
* Call to resolve the `result` Promise with the supplied value | ||
*/ | ||
done(value) { | ||
WorkerJob.prototype.done = function (value) { | ||
assert(this.isRunning, 'WorkerJob isRunning false.'); | ||
this.isRunning = false; | ||
this.resolve(value); | ||
} | ||
}; | ||
/** | ||
* Call to reject the `result` Promise with the supplied error | ||
*/ | ||
error(error) { | ||
WorkerJob.prototype.error = function (error) { | ||
assert(this.isRunning, 'WorkerJob isRunning false.'); | ||
this.isRunning = false; | ||
this.reject(error); | ||
} | ||
} | ||
}; | ||
return WorkerJob; | ||
}()); | ||
const workerURLCache = new Map(); | ||
var workerURLCache = new Map(); | ||
/** | ||
@@ -99,3 +96,3 @@ * Creates a loadable URL from worker source or URL | ||
assert((props.source && !props.url) || (!props.source && props.url)); // Either source or url must be defined | ||
let workerURL = workerURLCache.get(props.source || props.url); | ||
var workerURL = workerURLCache.get(props.source || props.url); | ||
if (!workerURL) { | ||
@@ -126,3 +123,3 @@ // Differentiate worker urls from worker source code | ||
// A remote script, we need to use `importScripts` to load from different origin | ||
const workerSource = buildScriptSource(url); | ||
var workerSource = buildScriptSource(url); | ||
return getLoadableWorkerURLFromSource(workerSource); | ||
@@ -138,3 +135,3 @@ } | ||
// const blob = webworkify(workerSource, {bare: true}); | ||
const blob = new Blob([workerSource], { type: 'application/javascript' }); | ||
var blob = new Blob([workerSource], { type: 'application/javascript' }); | ||
return URL.createObjectURL(blob); | ||
@@ -151,9 +148,3 @@ } | ||
function buildScriptSource(workerUrl) { | ||
return `\ | ||
try { | ||
importScripts('${workerUrl}'); | ||
} catch (error) { | ||
console.error(error); | ||
throw error; | ||
}`; | ||
return "try {\n importScripts('".concat(workerUrl, "');\n} catch (error) {\n console.error(error);\n throw error;\n}"); | ||
} | ||
@@ -171,5 +162,6 @@ | ||
*/ | ||
function getTransferList(object, recursive = true, transfers) { | ||
function getTransferList(object, recursive, transfers) { | ||
if (recursive === void 0) { recursive = true; } | ||
// Make sure that items in the transfer list is unique | ||
const transfersSet = transfers || new Set(); | ||
var transfersSet = transfers || new Set(); | ||
if (!object) ; | ||
@@ -185,3 +177,3 @@ else if (isTransferable(object)) { | ||
else if (recursive && typeof object === 'object') { | ||
for (const key in object) { | ||
for (var key in object) { | ||
// Avoid perf hit - only go one level deep | ||
@@ -217,17 +209,11 @@ getTransferList(object[key], recursive, transfersSet); | ||
const NOOP = () => { }; | ||
var NOOP = function () { }; | ||
/** | ||
* Represents one worker thread | ||
*/ | ||
class WorkerThread { | ||
name; | ||
source; | ||
url; | ||
terminated = false; | ||
worker; | ||
onMessage; | ||
onError; | ||
loadableURL = ''; | ||
constructor(props) { | ||
const { name, source, url } = props; | ||
var WorkerThread = /** @class */ (function () { | ||
function WorkerThread(props) { | ||
this.terminated = false; | ||
this.loadableURL = ''; | ||
var name = props.name, source = props.source, url = props.url; | ||
assert(source || url); // Either source or url must be defined | ||
@@ -238,8 +224,8 @@ this.name = name; | ||
this.onMessage = NOOP; | ||
this.onError = (error) => console.log(error); | ||
this.onError = function (error) { return console.log(error); }; | ||
this.worker = this.createBrowserWorker(); | ||
} | ||
static isSupported() { | ||
WorkerThread.isSupported = function () { | ||
return typeof Worker !== 'undefined'; | ||
} | ||
}; | ||
/** | ||
@@ -249,3 +235,3 @@ * Terminate this worker thread | ||
*/ | ||
destroy() { | ||
WorkerThread.prototype.destroy = function () { | ||
this.onMessage = NOOP; | ||
@@ -255,7 +241,11 @@ this.onError = NOOP; | ||
this.terminated = true; | ||
} | ||
get isRunning() { | ||
// TODO: isRunning | ||
return Boolean(this.onMessage); | ||
} | ||
}; | ||
Object.defineProperty(WorkerThread.prototype, "isRunning", { | ||
get: function () { | ||
// TODO: isRunning | ||
return Boolean(this.onMessage); | ||
}, | ||
enumerable: false, | ||
configurable: true | ||
}); | ||
/** | ||
@@ -266,6 +256,6 @@ * Send a message to this worker thread | ||
*/ | ||
postMessage(data, transferList) { | ||
WorkerThread.prototype.postMessage = function (data, transferList) { | ||
transferList = transferList || getTransferList(data); | ||
this.worker.postMessage(data, transferList); | ||
} | ||
}; | ||
/** | ||
@@ -275,10 +265,10 @@ * Generate a standard Error from an ErrorEvent | ||
*/ | ||
getErrorFromErrorEvent(event) { | ||
WorkerThread.prototype.getErrorFromErrorEvent = function (event) { | ||
// Note Error object does not have the expected fields if loading failed completely | ||
// https://developer.mozilla.org/en-US/docs/Web/API/Worker#Event_handlers | ||
// https://developer.mozilla.org/en-US/docs/Web/API/ErrorEvent | ||
let message = 'Failed to load '; | ||
message += `worker ${this.name} from ${this.url}. `; | ||
var message = 'Failed to load '; | ||
message += "worker ".concat(this.name, " from ").concat(this.url, ". "); | ||
if (event.message) { | ||
message += `${event.message} in `; | ||
message += "".concat(event.message, " in "); | ||
} | ||
@@ -288,47 +278,138 @@ // const hasFilename = event.filename && !event.filename.startsWith('blob:'); | ||
if (event.lineno) { | ||
message += `:${event.lineno}:${event.colno}`; | ||
message += ":".concat(event.lineno, ":").concat(event.colno); | ||
} | ||
return new Error(message); | ||
} | ||
}; | ||
/** | ||
* Creates a worker thread on the browser | ||
*/ | ||
createBrowserWorker() { | ||
WorkerThread.prototype.createBrowserWorker = function () { | ||
var _this = this; | ||
this.loadableURL = getLoadableWorkerURL({ source: this.source, url: this.url }); | ||
const worker = new Worker(this.loadableURL, { name: this.name }); | ||
worker.onmessage = (event) => { | ||
var worker = new Worker(this.loadableURL, { name: this.name }); | ||
worker.onmessage = function (event) { | ||
if (!event.data) { | ||
this.onError(new Error('No data received')); | ||
_this.onError(new Error('No data received')); | ||
} | ||
else { | ||
this.onMessage(event.data); | ||
_this.onMessage(event.data); | ||
} | ||
}; | ||
// This callback represents an uncaught exception in the worker thread | ||
worker.onerror = (error) => { | ||
this.onError(this.getErrorFromErrorEvent(error)); | ||
this.terminated = true; | ||
worker.onerror = function (error) { | ||
_this.onError(_this.getErrorFromErrorEvent(error)); | ||
_this.terminated = true; | ||
}; | ||
worker.onmessageerror = (event) => console.error(`worker ${this.name}, message error: ${event}`); | ||
worker.onmessageerror = function (event) { return console.error("worker ".concat(_this.name, ", message error: ").concat(event)); }; | ||
return worker; | ||
}; | ||
return WorkerThread; | ||
}()); | ||
/****************************************************************************** | ||
Copyright (c) Microsoft Corporation. | ||
Permission to use, copy, modify, and/or distribute this software for any | ||
purpose with or without fee is hereby granted. | ||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH | ||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY | ||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, | ||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM | ||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR | ||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | ||
PERFORMANCE OF THIS SOFTWARE. | ||
***************************************************************************** */ | ||
/* global Reflect, Promise, SuppressedError, Symbol */ | ||
var __assign = function() { | ||
__assign = Object.assign || function __assign(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; | ||
} | ||
return t; | ||
}; | ||
return __assign.apply(this, arguments); | ||
}; | ||
function __awaiter(thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
} | ||
function __generator(thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (g && (g = 0, op[0] && (_ = 0)), _) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
} | ||
function __values(o) { | ||
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; | ||
if (m) return m.call(o); | ||
if (o && typeof o.length === "number") return { | ||
next: function () { | ||
if (o && i >= o.length) o = void 0; | ||
return { value: o && o[i++], done: !o }; | ||
} | ||
}; | ||
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); | ||
} | ||
function __asyncValues(o) { | ||
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); | ||
var m = o[Symbol.asyncIterator], i; | ||
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); | ||
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } | ||
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } | ||
} | ||
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { | ||
var e = new Error(message); | ||
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; | ||
}; | ||
/** | ||
* Process multiple data messages with small pool of identical workers | ||
*/ | ||
class WorkerPool { | ||
name = 'unnamed'; | ||
source; | ||
url; | ||
maxConcurrency = 1; | ||
maxMobileConcurrency = 1; | ||
onDebug = () => { }; | ||
reuseWorkers = true; | ||
props = {}; | ||
jobQueue = []; | ||
idleQueue = []; | ||
count = 0; | ||
isDestroyed = false; | ||
constructor(props) { | ||
var WorkerPool = /** @class */ (function () { | ||
function WorkerPool(props) { | ||
this.name = 'unnamed'; | ||
this.maxConcurrency = 1; | ||
this.maxMobileConcurrency = 1; | ||
this.onDebug = function () { }; | ||
this.reuseWorkers = true; | ||
this.props = {}; | ||
this.jobQueue = []; | ||
this.idleQueue = []; | ||
this.count = 0; | ||
this.isDestroyed = false; | ||
this.source = props.source; | ||
@@ -342,9 +423,9 @@ this.url = props.url; | ||
*/ | ||
destroy() { | ||
WorkerPool.prototype.destroy = function () { | ||
// Destroy idle workers, active Workers will be destroyed on completion | ||
this.idleQueue.forEach((worker) => worker.destroy()); | ||
this.idleQueue.forEach(function (worker) { return worker.destroy(); }); | ||
this.isDestroyed = true; | ||
} | ||
setProps(props) { | ||
this.props = { ...this.props, ...props }; | ||
}; | ||
WorkerPool.prototype.setProps = function (props) { | ||
this.props = __assign(__assign({}, this.props), props); | ||
if (props.name !== undefined) { | ||
@@ -365,13 +446,24 @@ this.name = props.name; | ||
} | ||
} | ||
async startJob(name, onMessage = (job, type, data) => job.done(data), onError = (job, error) => job.error(error)) { | ||
// Promise resolves when thread starts working on this job | ||
const startPromise = new Promise((onStart) => { | ||
// Promise resolves when thread completes or fails working on this job | ||
this.jobQueue.push({ name, onMessage, onError, onStart }); | ||
return this; | ||
}; | ||
WorkerPool.prototype.startJob = function (name_1) { | ||
return __awaiter(this, arguments, void 0, function (name, onMessage, onError) { | ||
var startPromise; | ||
var _this = this; | ||
if (onMessage === void 0) { onMessage = function (job, type, data) { return job.done(data); }; } | ||
if (onError === void 0) { onError = function (job, error) { return job.error(error); }; } | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
startPromise = new Promise(function (onStart) { | ||
// Promise resolves when thread completes or fails working on this job | ||
_this.jobQueue.push({ name: name, onMessage: onMessage, onError: onError, onStart: onStart }); | ||
return _this; | ||
}); | ||
this.startQueuedJob(); | ||
return [4 /*yield*/, startPromise]; | ||
case 1: return [2 /*return*/, _a.sent()]; | ||
} | ||
}); | ||
}); | ||
this.startQueuedJob(); | ||
return await startPromise; | ||
} | ||
}; | ||
/** | ||
@@ -381,35 +473,44 @@ * Starts first queued job if worker is available or can be created | ||
*/ | ||
async startQueuedJob() { | ||
if (!this.jobQueue.length) { | ||
return; | ||
} | ||
const workerThread = this.getAvailableWorker(); | ||
if (!workerThread) { | ||
return; | ||
} | ||
// We have a worker, dequeue and start the job | ||
const queuedJob = this.jobQueue.shift(); | ||
if (queuedJob) { | ||
this.onDebug({ | ||
message: 'Starting job', | ||
name: queuedJob.name, | ||
backlog: this.jobQueue.length, | ||
workerThread, | ||
WorkerPool.prototype.startQueuedJob = function () { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var workerThread, queuedJob, job_1; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
if (!this.jobQueue.length) { | ||
return [2 /*return*/]; | ||
} | ||
workerThread = this.getAvailableWorker(); | ||
if (!workerThread) { | ||
return [2 /*return*/]; | ||
} | ||
queuedJob = this.jobQueue.shift(); | ||
if (!queuedJob) return [3 /*break*/, 4]; | ||
this.onDebug({ | ||
message: 'Starting job', | ||
name: queuedJob.name, | ||
backlog: this.jobQueue.length, | ||
workerThread: workerThread, | ||
}); | ||
job_1 = new WorkerJob(queuedJob.name, workerThread); | ||
// Set the worker thread's message handlers | ||
workerThread.onMessage = function (data) { return queuedJob.onMessage(job_1, data.type, data.payload); }; | ||
workerThread.onError = function (error) { return queuedJob.onError(job_1, error); }; | ||
// Resolve the start promise so that the app can start sending messages to worker | ||
queuedJob.onStart(job_1); | ||
_a.label = 1; | ||
case 1: | ||
_a.trys.push([1, , 3, 4]); | ||
return [4 /*yield*/, job_1.result]; | ||
case 2: | ||
_a.sent(); | ||
return [3 /*break*/, 4]; | ||
case 3: | ||
this.returnWorkerToQueue(workerThread); | ||
return [7 /*endfinally*/]; | ||
case 4: return [2 /*return*/]; | ||
} | ||
}); | ||
// Create a worker job to let the app access thread and manage job completion | ||
const job = new WorkerJob(queuedJob.name, workerThread); | ||
// Set the worker thread's message handlers | ||
workerThread.onMessage = (data) => queuedJob.onMessage(job, data.type, data.payload); | ||
workerThread.onError = (error) => queuedJob.onError(job, error); | ||
// Resolve the start promise so that the app can start sending messages to worker | ||
queuedJob.onStart(job); | ||
// Wait for the app to signal that the job is complete, then return worker to queue | ||
try { | ||
await job.result; | ||
} | ||
finally { | ||
this.returnWorkerToQueue(workerThread); | ||
} | ||
} | ||
} | ||
}); | ||
}; | ||
/** | ||
@@ -422,4 +523,4 @@ * Returns a worker to the idle queue | ||
*/ | ||
returnWorkerToQueue(worker) { | ||
const shouldDestroyWorker = this.isDestroyed || !this.reuseWorkers || this.count > this.getMaxConcurrency(); | ||
WorkerPool.prototype.returnWorkerToQueue = function (worker) { | ||
var shouldDestroyWorker = this.isDestroyed || !this.reuseWorkers || this.count > this.getMaxConcurrency(); | ||
if (shouldDestroyWorker) { | ||
@@ -435,7 +536,7 @@ worker.destroy(); | ||
} | ||
} | ||
}; | ||
/** | ||
* Returns idle worker or creates new worker if maxConcurrency has not been reached | ||
*/ | ||
getAvailableWorker() { | ||
WorkerPool.prototype.getAvailableWorker = function () { | ||
// If a worker has completed and returned to the queue, it can be used | ||
@@ -448,17 +549,18 @@ if (this.idleQueue.length > 0) { | ||
this.count++; | ||
const name = `${this.name.toLowerCase()} (#${this.count} of ${this.maxConcurrency})`; | ||
return new WorkerThread({ name, source: this.source, url: this.url }); | ||
var name_1 = "".concat(this.name.toLowerCase(), " (#").concat(this.count, " of ").concat(this.maxConcurrency, ")"); | ||
return new WorkerThread({ name: name_1, source: this.source, url: this.url }); | ||
} | ||
// No worker available, have to wait | ||
return null; | ||
} | ||
getMaxConcurrency() { | ||
}; | ||
WorkerPool.prototype.getMaxConcurrency = function () { | ||
return isMobile ? this.maxMobileConcurrency : this.maxConcurrency; | ||
} | ||
} | ||
}; | ||
return WorkerPool; | ||
}()); | ||
const DEFAULT_PROPS = { | ||
var DEFAULT_PROPS = { | ||
maxConcurrency: 3, | ||
maxMobileConcurrency: 1, | ||
onDebug: () => { }, | ||
onDebug: function () { }, | ||
reuseWorkers: true, | ||
@@ -469,23 +571,21 @@ }; | ||
*/ | ||
class WorkerFarm { | ||
props; | ||
workerPools = new Map(); | ||
// singleton | ||
static workerFarm; | ||
var WorkerFarm = /** @class */ (function () { | ||
/** get global instance with WorkerFarm.getWorkerFarm() */ | ||
function WorkerFarm(props) { | ||
this.workerPools = new Map(); | ||
this.props = __assign({}, DEFAULT_PROPS); | ||
this.setProps(props); | ||
this.workerPools = new Map(); | ||
} | ||
/** Check if Workers are supported */ | ||
static isSupported() { | ||
WorkerFarm.isSupported = function () { | ||
return WorkerThread.isSupported(); | ||
} | ||
}; | ||
/** Get the singleton instance of the global worker farm */ | ||
static getWorkerFarm(props = {}) { | ||
WorkerFarm.getWorkerFarm = function (props) { | ||
if (props === void 0) { props = {}; } | ||
WorkerFarm.workerFarm = WorkerFarm.workerFarm || new WorkerFarm({}); | ||
WorkerFarm.workerFarm.setProps(props); | ||
return WorkerFarm.workerFarm; | ||
} | ||
/** get global instance with WorkerFarm.getWorkerFarm() */ | ||
constructor(props) { | ||
this.props = { ...DEFAULT_PROPS }; | ||
this.setProps(props); | ||
this.workerPools = new Map(); | ||
} | ||
}; | ||
/** | ||
@@ -495,7 +595,18 @@ * Terminate all workers in the farm | ||
*/ | ||
destroy() { | ||
for (const workerPool of this.workerPools.values()) { | ||
workerPool.destroy(); | ||
WorkerFarm.prototype.destroy = function () { | ||
var e_1, _a; | ||
try { | ||
for (var _b = __values(this.workerPools.values()), _c = _b.next(); !_c.done; _c = _b.next()) { | ||
var workerPool = _c.value; | ||
workerPool.destroy(); | ||
} | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (_c && !_c.done && (_a = _b.return)) _a.call(_b); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
}; | ||
/** | ||
@@ -505,9 +616,20 @@ * Set props used when initializing worker pools | ||
*/ | ||
setProps(props) { | ||
this.props = { ...this.props, ...props }; | ||
// Update worker pool props | ||
for (const workerPool of this.workerPools.values()) { | ||
workerPool.setProps(this.getWorkerPoolProps()); | ||
WorkerFarm.prototype.setProps = function (props) { | ||
var e_2, _a; | ||
this.props = __assign(__assign({}, this.props), props); | ||
try { | ||
// Update worker pool props | ||
for (var _b = __values(this.workerPools.values()), _c = _b.next(); !_c.done; _c = _b.next()) { | ||
var workerPool = _c.value; | ||
workerPool.setProps(this.getWorkerPoolProps()); | ||
} | ||
} | ||
} | ||
catch (e_2_1) { e_2 = { error: e_2_1 }; } | ||
finally { | ||
try { | ||
if (_c && !_c.done && (_a = _b.return)) _a.call(_b); | ||
} | ||
finally { if (e_2) throw e_2.error; } | ||
} | ||
}; | ||
/** | ||
@@ -522,10 +644,10 @@ * Returns a worker pool for the specified worker | ||
*/ | ||
getWorkerPool(options) { | ||
const { name, source, url } = options; | ||
let workerPool = this.workerPools.get(name); | ||
WorkerFarm.prototype.getWorkerPool = function (options) { | ||
var name = options.name, source = options.source, url = options.url; | ||
var workerPool = this.workerPools.get(name); | ||
if (!workerPool) { | ||
workerPool = new WorkerPool({ | ||
name, | ||
source, | ||
url, | ||
name: name, | ||
source: source, | ||
url: url, | ||
}); | ||
@@ -536,4 +658,4 @@ workerPool.setProps(this.getWorkerPoolProps()); | ||
return workerPool; | ||
} | ||
getWorkerPoolProps() { | ||
}; | ||
WorkerFarm.prototype.getWorkerPoolProps = function () { | ||
return { | ||
@@ -545,27 +667,34 @@ maxConcurrency: this.props.maxConcurrency, | ||
}; | ||
} | ||
} | ||
}; | ||
return WorkerFarm; | ||
}()); | ||
const onMessageWrapperMap = new Map(); | ||
var onMessageWrapperMap = new Map(); | ||
/** | ||
* Type safe wrapper for worker code | ||
*/ | ||
class WorkerBody { | ||
/* | ||
* (type: WorkerMessageType, payload: WorkerMessagePayload) => any | ||
*/ | ||
static set onmessage(onMessage) { | ||
self.onmessage = (message) => { | ||
if (!isKnownMessage(message)) { | ||
return; | ||
} | ||
// Confusingly the message itself also has a 'type' field which is always set to 'message' | ||
const { type, payload } = message.data; | ||
onMessage(type, payload); | ||
}; | ||
var WorkerBody = /** @class */ (function () { | ||
function WorkerBody() { | ||
} | ||
static addEventListener(onMessage) { | ||
let onMessageWrapper = onMessageWrapperMap.get(onMessage); | ||
Object.defineProperty(WorkerBody, "onmessage", { | ||
/* | ||
* (type: WorkerMessageType, payload: WorkerMessagePayload) => any | ||
*/ | ||
set: function (onMessage) { | ||
self.onmessage = function (message) { | ||
if (!isKnownMessage(message)) { | ||
return; | ||
} | ||
// Confusingly the message itself also has a 'type' field which is always set to 'message' | ||
var _a = message.data, type = _a.type, payload = _a.payload; | ||
onMessage(type, payload); | ||
}; | ||
}, | ||
enumerable: false, | ||
configurable: true | ||
}); | ||
WorkerBody.addEventListener = function (onMessage) { | ||
var onMessageWrapper = onMessageWrapperMap.get(onMessage); | ||
if (!onMessageWrapper) { | ||
onMessageWrapper = (message) => { | ||
onMessageWrapper = function (message) { | ||
if (!isKnownMessage(message)) { | ||
@@ -575,3 +704,3 @@ return; | ||
// Confusingly the message itself also has a 'type' field which is always set to 'message' | ||
const { type, payload } = message.data; | ||
var _a = message.data, type = _a.type, payload = _a.payload; | ||
onMessage(type, payload); | ||
@@ -581,8 +710,8 @@ }; | ||
self.addEventListener('message', onMessageWrapper); | ||
} | ||
static removeEventListener(onMessage) { | ||
const onMessageWrapper = onMessageWrapperMap.get(onMessage); | ||
}; | ||
WorkerBody.removeEventListener = function (onMessage) { | ||
var onMessageWrapper = onMessageWrapperMap.get(onMessage); | ||
onMessageWrapperMap.delete(onMessage); | ||
self.removeEventListener('message', onMessageWrapper); | ||
} | ||
}; | ||
/** | ||
@@ -594,6 +723,6 @@ * Send a message from a worker to creating thread (main thread) | ||
*/ | ||
static postMessage(type, payload) { | ||
WorkerBody.postMessage = function (type, payload) { | ||
if (self) { | ||
const data = { source: 'Worker thread', type, payload }; | ||
const transferList = getTransferList(payload); | ||
var data = { source: 'Worker thread', type: type, payload: payload }; | ||
var transferList = getTransferList(payload); | ||
// TODO: targetOrigin, transferList | ||
@@ -604,7 +733,8 @@ // eslint-disable-next-line @typescript-eslint/ban-ts-comment | ||
} | ||
} | ||
} | ||
}; | ||
return WorkerBody; | ||
}()); | ||
// Filter out noise messages sent to workers | ||
function isKnownMessage(message) { | ||
const { type, data } = message; | ||
var type = message.type, data = message.data; | ||
return type === 'message' && data && typeof data.source === 'string' && data.source === 'Main thread'; | ||
@@ -624,4 +754,4 @@ } | ||
function stringifyJSON(v) { | ||
const cache = new Set(); | ||
return JSON.stringify(v, (key, value) => { | ||
var cache = new Set(); | ||
return JSON.stringify(v, function (key, value) { | ||
if (typeof value === 'object' && value !== null) { | ||
@@ -650,3 +780,3 @@ if (cache.has(value)) { | ||
function getWorkerName(worker) { | ||
return `${worker.name}`; | ||
return "".concat(worker.name); | ||
} | ||
@@ -660,13 +790,14 @@ /** | ||
*/ | ||
function getWorkerURL(worker, options = {}) { | ||
const workerOptions = options[worker.id] || {}; | ||
const workerFileName = `${worker.name}.worker.js`; | ||
let url = workerOptions.workerUrl; | ||
function getWorkerURL(worker, options) { | ||
if (options === void 0) { options = {}; } | ||
var workerOptions = options[worker.id] || {}; | ||
var workerFileName = "".concat(worker.name, ".worker.js"); | ||
var url = workerOptions.workerUrl; | ||
// If URL is test | ||
if (options._workerType === 'test') { | ||
url = `${worker.module}/dist/${workerFileName}`; | ||
url = "".concat(worker.module, "/dist/").concat(workerFileName); | ||
} | ||
// If url override is not provided, generate a URL to published version on npm CDN unpkg.com | ||
if (!url) { | ||
url = `https://unpkg.com/${worker.module}/dist/${workerFileName}`; | ||
url = "https://unpkg.com/".concat(worker.module, "/dist/").concat(workerFileName); | ||
} | ||
@@ -687,3 +818,3 @@ assert(url); | ||
} | ||
return worker.worker && options?.worker; | ||
return worker.worker && (options === null || options === void 0 ? void 0 : options.worker); | ||
} | ||
@@ -694,14 +825,27 @@ /** | ||
*/ | ||
async function processOnWorker(worker, data, options = {}, context = {}) { | ||
const name = getWorkerName(worker); | ||
const url = getWorkerURL(worker, options); | ||
const workerFarm = WorkerFarm.getWorkerFarm(options); | ||
const workerPool = workerFarm.getWorkerPool({ name, url }); | ||
const jobName = options.jobName || worker.name; | ||
const job = await workerPool.startJob(jobName, onMessage.bind(null, context)); | ||
// Kick off the processing in the worker | ||
const transferableOptions = removeNontransferableOptions(options); | ||
job.postMessage('process', { input: data, options: transferableOptions }); | ||
const result = await job.result; | ||
return result.result; | ||
function processOnWorker(worker_1, data_1) { | ||
return __awaiter(this, arguments, void 0, function (worker, data, options, context) { | ||
var name, url, workerFarm, workerPool, jobName, job, transferableOptions, result; | ||
if (options === void 0) { options = {}; } | ||
if (context === void 0) { context = {}; } | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
name = getWorkerName(worker); | ||
url = getWorkerURL(worker, options); | ||
workerFarm = WorkerFarm.getWorkerFarm(options); | ||
workerPool = workerFarm.getWorkerPool({ name: name, url: url }); | ||
jobName = options.jobName || worker.name; | ||
return [4 /*yield*/, workerPool.startJob(jobName, onMessage.bind(null, context))]; | ||
case 1: | ||
job = _a.sent(); | ||
transferableOptions = removeNontransferableOptions(options); | ||
job.postMessage('process', { input: data, options: transferableOptions }); | ||
return [4 /*yield*/, job.result]; | ||
case 2: | ||
result = _a.sent(); | ||
return [2 /*return*/, result.result]; | ||
} | ||
}); | ||
}); | ||
} | ||
@@ -713,32 +857,50 @@ /** | ||
*/ | ||
async function onMessage(context, job, type, payload) { | ||
switch (type) { | ||
case 'done': | ||
// Worker is done | ||
job.done(payload); | ||
break; | ||
case 'error': | ||
// Worker encountered an error | ||
job.error(new Error(payload.error)); | ||
break; | ||
case 'process': | ||
// Worker is asking for us (main thread) to process something | ||
// eslint-disable-next-line no-case-declarations | ||
const { id, input, options } = payload; | ||
try { | ||
if (!context.process) { | ||
job.postMessage('error', { id, error: 'Worker not set up to process on main thread' }); | ||
return; | ||
} | ||
const result = await context.process(input, options); | ||
job.postMessage('done', { id, result }); | ||
function onMessage(context, job, type, payload) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var _a, id, input, options, result, error_1, message; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
_a = type; | ||
switch (_a) { | ||
case 'done': return [3 /*break*/, 1]; | ||
case 'error': return [3 /*break*/, 2]; | ||
case 'process': return [3 /*break*/, 3]; | ||
} | ||
return [3 /*break*/, 8]; | ||
case 1: | ||
// Worker is done | ||
job.done(payload); | ||
return [3 /*break*/, 9]; | ||
case 2: | ||
// Worker encountered an error | ||
job.error(new Error(payload.error)); | ||
return [3 /*break*/, 9]; | ||
case 3: | ||
id = payload.id, input = payload.input, options = payload.options; | ||
_b.label = 4; | ||
case 4: | ||
_b.trys.push([4, 6, , 7]); | ||
if (!context.process) { | ||
job.postMessage('error', { id: id, error: 'Worker not set up to process on main thread' }); | ||
return [2 /*return*/]; | ||
} | ||
return [4 /*yield*/, context.process(input, options)]; | ||
case 5: | ||
result = _b.sent(); | ||
job.postMessage('done', { id: id, result: result }); | ||
return [3 /*break*/, 7]; | ||
case 6: | ||
error_1 = _b.sent(); | ||
message = error_1 instanceof Error ? error_1.message : 'unknown error'; | ||
job.postMessage('error', { id: id, error: message }); | ||
return [3 /*break*/, 7]; | ||
case 7: return [3 /*break*/, 9]; | ||
case 8: | ||
console.warn("process-on-worker: unknown message ".concat(type)); | ||
_b.label = 9; | ||
case 9: return [2 /*return*/]; | ||
} | ||
catch (error) { | ||
const message = error instanceof Error ? error.message : 'unknown error'; | ||
job.postMessage('error', { id, error: message }); | ||
} | ||
break; | ||
default: | ||
console.warn(`process-on-worker: unknown message ${type}`); | ||
} | ||
}); | ||
}); | ||
} | ||
@@ -760,7 +922,4 @@ | ||
*/ | ||
class AsyncQueue { | ||
_values; | ||
_settlers; | ||
_closed; | ||
constructor() { | ||
var AsyncQueue = /** @class */ (function () { | ||
function AsyncQueue() { | ||
this._values = []; // enqueues > dequeues | ||
@@ -771,9 +930,9 @@ this._settlers = []; // dequeues > enqueues | ||
/** Return an async iterator for this queue */ | ||
[Symbol.asyncIterator]() { | ||
AsyncQueue.prototype[Symbol.asyncIterator] = function () { | ||
return this; | ||
} | ||
}; | ||
/** Push a new value - the async iterator will yield a promise resolved to this value */ | ||
push(value) { | ||
AsyncQueue.prototype.push = function (value) { | ||
return this.enqueue(value); | ||
} | ||
}; | ||
/** | ||
@@ -783,3 +942,3 @@ * Push a new value - the async iterator will yield a promise resolved to this value | ||
*/ | ||
enqueue(value) { | ||
AsyncQueue.prototype.enqueue = function (value) { | ||
if (this._closed) { | ||
@@ -792,3 +951,3 @@ throw new Error('Closed'); | ||
} | ||
const settler = this._settlers.shift(); | ||
var settler = this._settlers.shift(); | ||
if (value instanceof Error) { | ||
@@ -798,3 +957,3 @@ settler.reject(value); | ||
else { | ||
settler.resolve({ value }); | ||
settler.resolve({ value: value }); | ||
} | ||
@@ -805,21 +964,22 @@ } | ||
} | ||
} | ||
}; | ||
/** Indicate that we not waiting for more values - The async iterator will be done */ | ||
close() { | ||
AsyncQueue.prototype.close = function () { | ||
while (this._settlers.length > 0) { | ||
const settler = this._settlers.shift(); | ||
var settler = this._settlers.shift(); | ||
settler.resolve({ done: true }); | ||
} | ||
this._closed = true; | ||
} | ||
}; | ||
// ITERATOR IMPLEMENTATION | ||
/** @returns a Promise for an IteratorResult */ | ||
next() { | ||
AsyncQueue.prototype.next = function () { | ||
var _this = this; | ||
// If values in queue, yield the first value | ||
if (this._values.length > 0) { | ||
const value = this._values.shift(); | ||
var value = this._values.shift(); | ||
if (value instanceof Error) { | ||
return Promise.reject(value); | ||
} | ||
return Promise.resolve({ done: false, value }); | ||
return Promise.resolve({ done: false, value: value }); | ||
} | ||
@@ -834,13 +994,14 @@ // If queue is closed, the iterator is done | ||
// Yield a promise that waits for new values to be enqueued | ||
return new Promise((resolve, reject) => { | ||
this._settlers.push({ resolve, reject }); | ||
return new Promise(function (resolve, reject) { | ||
_this._settlers.push({ resolve: resolve, reject: reject }); | ||
}); | ||
} | ||
} | ||
}; | ||
return AsyncQueue; | ||
}()); | ||
/** Counter for jobs */ | ||
let requestId = 0; | ||
var requestId = 0; | ||
// 异步队列 | ||
let inputBatches; | ||
let options; | ||
var inputBatches; | ||
var options; | ||
/** | ||
@@ -850,2 +1011,3 @@ * Set up a WebWorkerGlobalScope to talk with the main thread | ||
function createWorker(process, processInBatches) { | ||
var _this = this; | ||
// 检查是否在 worker 线程中 | ||
@@ -855,17 +1017,30 @@ if (typeof self === 'undefined') { | ||
} | ||
const context = { | ||
var context = { | ||
process: processOnMainThread, | ||
}; | ||
WorkerBody.onmessage = async (type, payload) => { | ||
try { | ||
switch (type) { | ||
case 'process': | ||
WorkerBody.onmessage = function (type, payload) { return __awaiter(_this, void 0, void 0, function () { | ||
var _a, result, resultIterator, _b, resultIterator_1, resultIterator_1_1, batch, e_1_1, error_1, message; | ||
var _c, e_1, _d, _e; | ||
return __generator(this, function (_f) { | ||
switch (_f.label) { | ||
case 0: | ||
_f.trys.push([0, 19, , 20]); | ||
_a = type; | ||
switch (_a) { | ||
case 'process': return [3 /*break*/, 1]; | ||
case 'process-in-batches': return [3 /*break*/, 3]; | ||
case 'input-batch': return [3 /*break*/, 16]; | ||
case 'input-done': return [3 /*break*/, 17]; | ||
} | ||
return [3 /*break*/, 18]; | ||
case 1: | ||
if (!process) { | ||
throw new Error('Worker does not support atomic processing'); | ||
} | ||
// eslint-disable-next-line no-case-declarations | ||
const result = await process(payload.input, payload.options || {}, context); | ||
WorkerBody.postMessage('done', { result }); | ||
break; | ||
case 'process-in-batches': | ||
return [4 /*yield*/, process(payload.input, payload.options || {}, context)]; | ||
case 2: | ||
result = _f.sent(); | ||
WorkerBody.postMessage('done', { result: result }); | ||
return [3 /*break*/, 18]; | ||
case 3: | ||
if (!processInBatches) { | ||
@@ -876,30 +1051,63 @@ throw new Error('Worker does not support batched processing'); | ||
options = payload.options || {}; | ||
// eslint-disable-next-line no-case-declarations | ||
const resultIterator = processInBatches(inputBatches, options, context); | ||
for await (const batch of resultIterator) { | ||
WorkerBody.postMessage('output-batch', { result: batch }); | ||
} | ||
resultIterator = processInBatches(inputBatches, options, context); | ||
_f.label = 4; | ||
case 4: | ||
_f.trys.push([4, 9, 10, 15]); | ||
_b = true, resultIterator_1 = __asyncValues(resultIterator); | ||
_f.label = 5; | ||
case 5: return [4 /*yield*/, resultIterator_1.next()]; | ||
case 6: | ||
if (!(resultIterator_1_1 = _f.sent(), _c = resultIterator_1_1.done, !_c)) return [3 /*break*/, 8]; | ||
_e = resultIterator_1_1.value; | ||
_b = false; | ||
batch = _e; | ||
WorkerBody.postMessage('output-batch', { result: batch }); | ||
_f.label = 7; | ||
case 7: | ||
_b = true; | ||
return [3 /*break*/, 5]; | ||
case 8: return [3 /*break*/, 15]; | ||
case 9: | ||
e_1_1 = _f.sent(); | ||
e_1 = { error: e_1_1 }; | ||
return [3 /*break*/, 15]; | ||
case 10: | ||
_f.trys.push([10, , 13, 14]); | ||
if (!(!_b && !_c && (_d = resultIterator_1.return))) return [3 /*break*/, 12]; | ||
return [4 /*yield*/, _d.call(resultIterator_1)]; | ||
case 11: | ||
_f.sent(); | ||
_f.label = 12; | ||
case 12: return [3 /*break*/, 14]; | ||
case 13: | ||
if (e_1) throw e_1.error; | ||
return [7 /*endfinally*/]; | ||
case 14: return [7 /*endfinally*/]; | ||
case 15: | ||
WorkerBody.postMessage('done', {}); | ||
break; | ||
case 'input-batch': | ||
return [3 /*break*/, 18]; | ||
case 16: | ||
inputBatches.push(payload.input); | ||
break; | ||
case 'input-done': | ||
return [3 /*break*/, 18]; | ||
case 17: | ||
inputBatches.close(); | ||
break; | ||
default: | ||
return [3 /*break*/, 18]; | ||
case 18: return [3 /*break*/, 20]; | ||
case 19: | ||
error_1 = _f.sent(); | ||
message = error_1 instanceof Error ? error_1.message : ''; | ||
WorkerBody.postMessage('error', { error: message }); | ||
return [3 /*break*/, 20]; | ||
case 20: return [2 /*return*/]; | ||
} | ||
} | ||
catch (error) { | ||
const message = error instanceof Error ? error.message : ''; | ||
WorkerBody.postMessage('error', { error: message }); | ||
} | ||
}; | ||
}); | ||
}); }; | ||
} | ||
function processOnMainThread(arrayBuffer, options = {}) { | ||
return new Promise((resolve, reject) => { | ||
const id = requestId++; | ||
function processOnMainThread(arrayBuffer, options) { | ||
if (options === void 0) { options = {}; } | ||
return new Promise(function (resolve, reject) { | ||
var id = requestId++; | ||
/** | ||
*/ | ||
const onMessage = (type, payload) => { | ||
var onMessage = function (type, payload) { | ||
if (payload.id !== id) { | ||
@@ -923,3 +1131,3 @@ // not ours | ||
// Ask the main thread to decode data | ||
const payload = { id, input: arrayBuffer, options }; | ||
var payload = { id: id, input: arrayBuffer, options: options }; | ||
WorkerBody.postMessage('process', payload); | ||
@@ -929,4 +1137,3 @@ }); | ||
/* global importScripts */ | ||
const loadLibraryPromises = {}; // promises | ||
var loadLibraryPromises = {}; // promises | ||
/** | ||
@@ -947,9 +1154,19 @@ * Dynamically loads a library ("module") | ||
*/ | ||
async function loadLibrary(libraryUrl, moduleName = null, options = {}) { | ||
if (moduleName) { | ||
libraryUrl = getLibraryUrl(libraryUrl, moduleName, options); | ||
} | ||
// Ensure libraries are only loaded once | ||
loadLibraryPromises[libraryUrl] = loadLibraryPromises[libraryUrl] || loadLibraryFromFile(libraryUrl); | ||
return await loadLibraryPromises[libraryUrl]; | ||
function loadLibrary(libraryUrl_1) { | ||
return __awaiter(this, arguments, void 0, function (libraryUrl, moduleName, options) { | ||
if (moduleName === void 0) { moduleName = null; } | ||
if (options === void 0) { options = {}; } | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
if (moduleName) { | ||
libraryUrl = getLibraryUrl(libraryUrl, moduleName, options); | ||
} | ||
// Ensure libraries are only loaded once | ||
loadLibraryPromises[libraryUrl] = loadLibraryPromises[libraryUrl] || loadLibraryFromFile(libraryUrl); | ||
return [4 /*yield*/, loadLibraryPromises[libraryUrl]]; | ||
case 1: return [2 /*return*/, _a.sent()]; | ||
} | ||
}); | ||
}); | ||
} | ||
@@ -963,3 +1180,3 @@ // TODO - sort out how to resolve paths for main/worker and dev/prod | ||
// Allow application to import and supply libraries through `options.modules` | ||
const modules = options.modules || {}; | ||
var modules = options.modules || {}; | ||
if (modules[library]) { | ||
@@ -971,25 +1188,36 @@ return modules[library]; | ||
assert(options.CDN.startsWith('http')); | ||
return `${options.CDN}/${moduleName}/dist/libs/${library}`; | ||
return "".concat(options.CDN, "/").concat(moduleName, "/dist/libs/").concat(library); | ||
} | ||
// TODO - loading inside workers requires paths relative to worker script location... | ||
if (isWorker) { | ||
return `../src/libs/${library}`; | ||
return "../src/libs/".concat(library); | ||
} | ||
return `modules/${moduleName}/src/libs/${library}`; | ||
return "modules/".concat(moduleName, "/src/libs/").concat(library); | ||
} | ||
async function loadLibraryFromFile(libraryUrl) { | ||
if (libraryUrl.endsWith('wasm')) { | ||
const response = await fetch(libraryUrl); | ||
return await response.arrayBuffer(); | ||
} | ||
if (isWorker) { | ||
return importScripts(libraryUrl); | ||
} | ||
// TODO - fix - should be more secure than string parsing since observes CORS | ||
// if (isBrowser) { | ||
// return await loadScriptFromFile(libraryUrl); | ||
// } | ||
const response = await fetch(libraryUrl); | ||
const scriptSource = await response.text(); | ||
return loadLibraryFromString(scriptSource, libraryUrl); | ||
function loadLibraryFromFile(libraryUrl) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var response_1, response, scriptSource; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
if (!libraryUrl.endsWith('wasm')) return [3 /*break*/, 3]; | ||
return [4 /*yield*/, fetch(libraryUrl)]; | ||
case 1: | ||
response_1 = _a.sent(); | ||
return [4 /*yield*/, response_1.arrayBuffer()]; | ||
case 2: return [2 /*return*/, _a.sent()]; | ||
case 3: | ||
if (isWorker) { | ||
return [2 /*return*/, importScripts(libraryUrl)]; | ||
} | ||
return [4 /*yield*/, fetch(libraryUrl)]; | ||
case 4: | ||
response = _a.sent(); | ||
return [4 /*yield*/, response.text()]; | ||
case 5: | ||
scriptSource = _a.sent(); | ||
return [2 /*return*/, loadLibraryFromString(scriptSource, libraryUrl)]; | ||
} | ||
}); | ||
}); | ||
} | ||
@@ -1020,3 +1248,3 @@ /* | ||
} | ||
const script = document.createElement('script'); | ||
var script = document.createElement('script'); | ||
script.id = id; | ||
@@ -1048,6 +1276,5 @@ // most browsers like a separate text node but some throw an error. The second method covers those. | ||
const version = '0.0.3'; | ||
// WORKER OBJECTS | ||
/** A null worker to test that worker processing is functional */ | ||
const NullWorker = { | ||
var NullWorker = { | ||
id: 'null', | ||
@@ -1077,5 +1304,3 @@ name: 'null', | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
})); | ||
//# sourceMappingURL=web-worker-helper.js.map |
{ | ||
"name": "web-worker-helper", | ||
"version": "0.0.3", | ||
"version": "0.0.4-beta.0", | ||
"description": "Utilities for running tasks on worker threads", | ||
@@ -25,17 +25,7 @@ "license": "MIT", | ||
], | ||
"scripts": { | ||
"prepare": "husky install", | ||
"lint": "eslint src __tests__ --ext .js,.ts", | ||
"lint-fix": "eslint src __tests__ --ext .js,.ts --fix", | ||
"prettier": "prettier src __tests__ -c -w", | ||
"typedoc": "typedoc", | ||
"clean": "rimraf dist", | ||
"build": "npm run clean && npm run build:cjs && npm run build:esm && npm run build:umd", | ||
"build:cjs": "tsc -p tsconfig.json --target ES5 --module CommonJS --outDir dist/lib", | ||
"build:esm": "tsc -p tsconfig.json --target ES5 --module ESNext --outDir dist/esm", | ||
"build:umd": "rollup -c scripts/rollup.config.ts" | ||
}, | ||
"dependencies": {}, | ||
"devDependencies": { | ||
"@rollup/plugin-typescript": "^8.3.0", | ||
"@changesets/changelog-github": "^0.5.0", | ||
"@changesets/cli": "^2.27.1", | ||
"@rollup/plugin-terser": "^0.4.4", | ||
"@rollup/plugin-typescript": "^11.1.6", | ||
"@typescript-eslint/eslint-plugin": "^5.0.0", | ||
@@ -50,9 +40,27 @@ "@typescript-eslint/parser": "^5.0.0", | ||
"rimraf": "^3.0.2", | ||
"rollup": "^2.66.0", | ||
"rollup-plugin-terser": "^7.0.2", | ||
"rollup": "^4.14.0", | ||
"tape": "^5.3.1", | ||
"tape-promise": "^4.0.0", | ||
"typedoc": "^0.22.5", | ||
"typescript": "^4.4.3" | ||
"tslib": "^2.6.2", | ||
"typedoc": "^0.25.12", | ||
"typescript": "^5.4.4" | ||
}, | ||
"engines": { | ||
"node": ">=18", | ||
"pnpm": ">=8" | ||
}, | ||
"scripts": { | ||
"lint": "eslint src __tests__ --ext .js,.ts", | ||
"lint-fix": "eslint src __tests__ --ext .js,.ts --fix", | ||
"prettier": "prettier src __tests__ -c -w", | ||
"typedoc": "typedoc", | ||
"clean": "rimraf dist", | ||
"build": "pnpm clean && pnpm run '/^build:.*/'", | ||
"build:cjs": "tsc -p tsconfig.json --declaration --module CommonJS --outDir dist/lib", | ||
"build:esm": "tsc -p tsconfig.json --declaration --module ESNext --outDir dist/esm", | ||
"build:umd": "rollup -c scripts/rollup.config.mjs", | ||
"changeset": "changeset add", | ||
"publish-version": "changeset version && node scripts/sync-version.mjs", | ||
"publish-package": "pnpm build && changeset publish" | ||
} | ||
} | ||
} |
@@ -1,2 +0,2 @@ | ||
export const version = '0.0.3'; | ||
export { default as version } from './version'; | ||
@@ -3,0 +3,0 @@ import type { WorkerObject } from './types'; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
410160
101
6487
19
9