UNPKG

worker-tls

Version:

worker-tls 提供了 动态Worker 功能 和 其它一些 Worker 场景下有用的工具集;让开发者可以像调用对象方法一样动态地调用Worker中的方法,也可以随时地往 Worker 中动态地添加函数 等等。

658 lines (657 loc) 20.1 kB
var _ = Object.defineProperty; var G = (s, t, e) => t in s ? _(s, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : s[t] = e; var b = (s, t, e) => G(s, typeof t != "symbol" ? t + "" : t, e); import { isObject as N, getExactTypeOf as z } from "type-tls"; import { M as q, i as K } from "./dynamicWorkerAPI-NH-1-_70.js"; const W = `(function(){"use strict";function n(){const r=globalThis.currentWorkerType;if(r)return r;let e=globalThis.SharedWorkerGlobalScope;return typeof e=="function"&&globalThis instanceof e?globalThis.currentWorkerType="SharedWorker":(e=globalThis.DedicatedWorkerGlobalScope,typeof e=="function"&&globalThis instanceof e?globalThis.currentWorkerType="DedicatedWorker":(e=globalThis.Window,typeof e=="function"&&globalThis instanceof e?globalThis.currentWorkerType="Window":globalThis.currentWorkerType="unknown"))}function t(r){switch(n()){case"SharedWorker":{globalThis.addEventListener("connect",function(e){for(const o of e.ports)o.addEventListener("message",r),o.start()});break}default:globalThis.addEventListener("message",r)}}globalThis.listenMessage||(globalThis.listenMessage=t)})(); `, Z = '(function(){"use strict";function b(t){var e=t;return t!=null&&(e=t.constructor,e==null&&(e=typeof t)),e}var u=(t=>(t.equal="equal",t.intersect="intersect",t.intersectEqual="intersectEqual",t))(u||{});(t=>{function e(r){let s;switch(r){case"equal":s=(o,n)=>o===n;case"intersect":s=(o,n)=>o&n;default:s=(o,n)=>(o&n)===o}return s}t.getEqualFun=e})(u||(u={}));function d(){const t=globalThis.currentWorkerType;if(t)return t;let e=globalThis.SharedWorkerGlobalScope;return typeof e=="function"&&globalThis instanceof e?globalThis.currentWorkerType="SharedWorker":(e=globalThis.DedicatedWorkerGlobalScope,typeof e=="function"&&globalThis instanceof e?globalThis.currentWorkerType="DedicatedWorker":(e=globalThis.Window,typeof e=="function"&&globalThis instanceof e?globalThis.currentWorkerType="Window":globalThis.currentWorkerType="unknown"))}function h(t,e,r){const s=/(^\\s*(async\\s+)?function\\s*(\\s|\\*)\\s*)[A-Za-z_$]+[\\w$]*(\\s*\\()/,o=/^[A-Za-z_$]+[\\w$]*$/,n=s.test(t),a=e&&o.test(e);if(n&&a&&(t=t.replace(s,`$1${e}$4`)),!n&&a)var i=`var ${e} = ${t} ; return ${e}`;else i=`return (${t})`;return new Function(i)()}function f(t){const{name:e,args:r,this:s}=t,o=s??globalThis,n=globalThis[e];return typeof n=="function"?n.apply(o,r):r||s?{error:"函数不存在",state:"结束"}:{data:n,state:"结束"}}function g(t){const e=b(t);if(e==="object"||e===Object){const{transfer:r,targetOrigin:s}=t;return"data"in t||"error"in t||Array.isArray(r)||typeof s=="string"}return!1}function c(t,e){const{data:r,...s}=g(t)?t:{data:t},o={...e,...s};if(r instanceof ReadableStream){const n=new WritableStream({write:function(a,i){return c(a,{...o,state:"进行中"})},close:function(a){l(void 0,{state:"结束",...o})},abort:function(a){l(void 0,{state:"结束",...o,error:a})}});return r.pipeTo(n)}return r instanceof Promise?r.then(function(n){c(n,{state:"结束",...o})},function(n){l(void 0,{...o,error:n,state:"结束"})}):l(r,{state:"结束",...o})}function l(t,e){const{port:r,...s}=e,{transfer:o,targetOrigin:n,...a}=g(t)?{...s,...t}:{...s,data:t};a.state==null&&(a.state="结束");const i={transfer:o,targetOrigin:n};return(r??globalThis).postMessage(a,i)}function T(t){const e=t.data,r=t.currentTarget;if(e){const s=f(e);c(s,{execId:e.id,port:r})}}function p(t,e){const r=h(t,e);return e=e??r.name,globalThis[e]=r,!0}function y(t){return delete globalThis[t]}Object.assign(globalThis,{execCMD:f,messageListener:T,setCMD:p,removeCMD:y,sendMessage:c}),d(),listenMessage(T)})();\n', T = "event"; function A(s, t) { t = t ?? s.name; const e = s.toString(); return `globalThis['${t}'] = ${e};`; } function D(s, t) { const e = typeof s == "string" ? s : s.toString(); t = t ?? []; const n = t.map(function(r) { return N(r) ? JSON.stringify(r) : r; }), o = n.length > 0 ? `,${n.join(",")}` : ""; return `(${e}).call(this${o});`; } function I(s, t) { return s.name ? A(s) : D(s, t); } function P(s) { return `globalThis.listenMessage(${typeof s == "string" ? s : s.toString()});`; } function H(s) { const e = s.map(function(o) { return `${o}.call(this,${T});`; }).join(` `), n = `function(${T}){${e}}`; return P(n); } function J(s) { const e = s.map(function(o) { return D(o, [T]); }).join(` `), n = `function(${T}){${e}}`; return P(n); } function w(s, t) { const e = new Blob(s, { type: "text/javascript", ...t }); return URL.createObjectURL(e); } function ne(s, t) { const e = s.map((n) => typeof n == "function" ? ` ${I(n, t)} ` : n); return w(e); } function $(s) { return s.name || s.fun ? [s] : Object.entries(s).map(function([t, e]) { return { name: t, fun: e }; }); } function v(s, t) { const { code: e, named: n, iife: o, message: r } = s, i = [], c = [], a = o || [], f = [], l = [], m = Array.isArray(e) ? e : e ? [e] : []; for (const u of m) { const g = z(u); if (g === Object || g === "object") { const x = $(u); i.push(...x); } else c.push(u); } const y = Array.isArray(n) ? n : n ? [n] : []; for (const u of y) if (typeof u == "function") i.push({ fun: u }); else { const g = $(u); i.push(...g); } const p = Array.isArray(r) ? r : r ? [r] : []; for (const u of p) switch (typeof u) { case "string": { l.push(u); break; } case "function": { f.push(u); break; } default: { const { name: g, fun: x } = u; x ? f.push(x) : g && l.push(g); } } const h = i.map(function({ name: u, fun: g }) { return `${A(g, u)} `; }), d = c.map(function(u) { return typeof u == "function" ? `${I(u)} ` : u; }), M = a.map(function(u) { return `${D(u)} `; }), S = [], F = J(f); S.push(`${F} `); const B = H(l); return S.push(`${B} `), [...t ? [] : [`${W} `], ...h, ...d, ...M, ...S]; } function re(s, t) { const e = v(s, t); return w(e); } function E(s, t) { const e = s ? v(s, !1) : []; return t || e.unshift(W, Z), w(e); } function R(s) { return s && Array.isArray(s.args) && Array.isArray(s.transfer); } const k = class k { constructor(t) { b(this, "id", ++k.instanceCount); /** * 执行命令的计数 * * @remarks * 用于给每次执行命令时生成 id */ b(this, "execCount", 0); if (t) for (const e of Object.keys(t)) this.setCMDToSelf(e); } /** * 消息端口 */ get port() { return this.getPort(this.worker); } /** * 获取 Worker 和 对应的 消息端口 */ get workerAndPort() { const t = this.worker; return [t, this.getPort(t)]; } /** * 获取消息端口 * @param worker * @returns */ getPort(t) { return t.port || t; } /** * 执行已开始 * @remarks * 开始执行 */ execStarted(t, e) { ++t.executingCount; } /** * 执行已开始 * @remarks * 开始执行 */ execEnded(t) { --t.executingCount; } /** * 获取本次执行的执行 id * @param cmdName * @returns */ getExecId(t) { return t = t ?? "匿名", `${t}_${this.execCount}`; } /** * 根据调用信息生成调用记录数据 * @param exec - 调用信息 * @returns */ getExecRecord(t) { return { id: this.getExecId(t.name), ...t }; } /** * 监听响应 * @param id * @returns */ listenResponse(t, e) { const n = new AbortController(), o = n.signal; let r = null; const i = this.getPort(e); return new Promise((c, a) => { i.addEventListener( "message", (l) => { const m = l.data, { execId: y, state: p, error: h, data: d } = m; if (t !== y) return; if (r) { if (p === q.End) { n.abort(), h && r.error(h), d !== void 0 && r.enqueue(d), r.close(), this.execEnded(e); return; } if (h) { r.error(h); return; } r.enqueue(d); return; } if (h) { a(h), n.abort(); return; } if (p === q.End) { n.abort(), c(d), this.execEnded(e); return; } const M = new ReadableStream({ start: (S) => { r = S, h && r.error(h), r.enqueue(d); } }); c(M); }, { signal: o } ); const f = (l) => { if (n.abort(), r) { r.error(l), r.close(), this.execEnded(e); return; } a(l); }; e.addEventListener("error", f, { signal: o }), i.addEventListener("messageerror", f, { signal: o }); }).catch((c) => { throw this.execEnded(e), c; }); } /** * 执行 worker 中的命令 * * @remarks * 当 worker 中成功执行,且 this 上没有对应的成员时,则会自动新增对应的成员方法 * * @param exec - 命令信息 * @param transfer - 传递给 Worker 的可传递对象。这些对象的所有权将被转移给 Worker,而发当前环境将不再保有所有权。 * @returns */ execCMD(t, e) { ++this.execCount; const n = this.getExecRecord(t), [o, r] = this.workerAndPort; this.execStarted(o, n); const i = this.listenResponse(n.id, o); r.postMessage(n, e); const c = t.name; return c in this ? i : i.then((a) => (this.setCMDToSelf(c), a)); } /** * 往自身上添加命令成员 * @remarks * 会给实例自身上添加一个执行命令的快捷命令 * * @param name * @param isProperty - 添加到实例自身的快捷命令是否作为属性;如果是 true,则会在实例自身上生成快捷属性 */ setCMDToSelf(t, e) { const n = (...r) => { const i = r[0]; let c; return r.length === 1 && R(i) && (c = i.transfer, r = i.args), this.execCMD({ name: t, args: r.length > 0 ? r : void 0 }, c); }; return Reflect.defineProperty(this, t, { configurable: !0, enumerable: !0, ...e ? { get: n } : { value: n, writable: !0 } }); } }; /** * 实例的计数 * * @remarks * 用于给每次调用生成 id */ b(k, "instanceCount", 0); let C = k; function j(s) { const { url: t, name: e } = s; return new Worker(t, { name: e }); } class Q extends C { constructor(e, n) { super(e == null ? void 0 : e.named); /** * Worker 的实例 */ b(this, "worker"); const { id: o } = this; let r = (typeof n == "string" ? n : n == null ? void 0 : n.name) || `DynamicWorker/${o}`, i = e; if (!K(e)) { const c = typeof e == "string", { getWorker: a, noDep: f } = n || {}, l = c ? e : E(e, f); i = (a || j)({ url: l, name: r, clientId: o, id: o }), c || URL.revokeObjectURL(l); } i.executingCount = 0, i.name = r, i.id = i.clientId = o, this.worker = i; } /** * 正在执行中的任务数 */ get executingCount() { return this.worker.executingCount; } /** * 设置命令 * @remarks * 会在Worker中添加一条命令,并且也会在实例自身上添加一个快捷命令(快捷方法 或 快捷属性) * * @param cmd * @param name - 命令的命名;默认会取 `cmd.name` 作为名字;当 cmd 是字符串时,name 是必须的 * @param isProperty - 添加到实例自身的快捷命令是否作为属性;如果是 true,则会在实例自身上生成快捷属性 * @returns */ setCMD(e, n, o) { const r = n || e.name; if (!r) return Promise.reject("没有函数的名字"); const i = typeof e == "function" ? e.toString() : e; return this.execCMD({ name: "setCMD", args: [i, r] }).then((c) => (c && this.setCMDToSelf(r, o), c)); } /** * 移除命令 * @remarks * 会将 Worker 中的命令 和 自己实例上的对应快捷方法都给移除 * @param name * @returns */ removeCMD(e) { return this.execCMD({ name: "removeCMD", args: [e] }).then((n) => (n && Reflect.deleteProperty(this, e), n)); } } class V { constructor(t, e) { b(this, "_queue", []); this.comparer = t, e && (this.queue = e); } /** * 队列 * @remarks * 保存所有的元素 */ get queue() { return this._queue; } set queue(t) { this._queue = t, this.sort(); } /** * 第一个元素 */ get first() { return this.queue[0]; } /** * 最后一个元素 */ get last() { return this.queue.at(-1); } /** * 添加元素 * @param items * @returns 返回item最终的索引 */ add(t) { const { queue: e } = this; let n = e.indexOf(t); return n === -1 && (n = e.push(t) - 1), this.sortItemForIndex(n); } /** * 添加元素 * @param items */ addItems(t) { for (const e of t) this.add(e); } /** * 删除元素 * @param items * @returns 返回item删除前所在的索引 */ delete(t) { const { queue: e } = this, n = e.indexOf(t); return n === -1 && e.splice(n, 1), n; } /** * 删除元素 * @param items */ deleteItems(t) { const { queue: e } = this; for (const n of t) { const o = e.indexOf(n); o === -1 && e.splice(o, 1); } } /** * 对队列中的所有元素重新排序 */ sort() { this.queue.sort(this.comparer); } /** * 排序 item * @param item * @returns 如果item 不在队列中,返回 false;否则返回 true */ sortItem(t) { const e = this.queue.indexOf(t); return e === -1 ? e : this.sortItemForIndex(e); } /** * 前向排序 * @param item * @returns 返回item最终的索引 */ forwardSort(t) { const e = this.queue.indexOf(t); return e < 1 ? e : this.forwardSortForIndex(e); } /** * 后向排序 * @param item * @returns 返回item最终的索引 */ backwardSort(t) { const e = this.queue.indexOf(t); return e === -1 ? e : this.backwardSortForIndex(e); } /** * 排序 item * @param index * @returns 返回item最终的索引 */ sortItemForIndex(t) { const { queue: e, comparer: n } = this, o = e[t], r = t - 1; if (r >= 0 && n(e[r], o) > 0) return this.forwardSort(o); const i = t + 1, c = e.length; return i < c && n(o, e[i]) > 0 ? this.backwardSort(o) : t; } /** * 前向排序 * @param index * @returns 返回item最终的索引 */ forwardSortForIndex(t) { const { queue: e, comparer: n } = this, o = e[t]; for (; t > 0; ) { const r = t - 1, i = e[r]; if (n(i, o) > 0) e[r] = o, e[t] = i, t = r; else break; } return t; } /** * 后向排序 * @param index * @returns 返回item最终的索引 */ backwardSortForIndex(t) { const { queue: e, comparer: n } = this, o = e[t], r = e.length - 1; for (; t < r; ) { const i = t + 1, c = e[i]; if (n(o, c) > 0) e[i] = o, e[t] = c, t = i; else break; } return t; } } function X(s, t) { return s.executingCount - t.executingCount; } class Y extends C { /** * * @param workerNum - Worker池 中 workder 的个数 * @param codeOrUrl - code 选项 或 url * @param workerOptions - Worker 相关的选项 */ constructor(e, n, o) { const r = typeof n == "string"; super(n == null ? void 0 : n.named); /** * Worker 队列 */ b(this, "queue", new V(X)); const i = r ? n : E(n), { getWorker: c, name: a } = o || {}, f = this.id, l = a || `DynamicWorkerPool/${f}`, m = c || j, y = []; for (let p = 1; p <= e; p++) { const h = `${l}/${p}`, d = m({ url: i, name: h, clientId: f, id: p }); d.executingCount = 0, d.name = h, d.clientId = f, d.id = p, y.push(d); } r || URL.revokeObjectURL(i), this.queue.queue = y; } get worker() { return this.queue.first; } get executingCount() { return this.queue.queue.reduce((e, n) => e + n.executingCount, 0); } execStarted(e, n) { super.execStarted(e, n), this.queue.backwardSort(e); } execEnded(e) { super.execEnded(e), this.queue.forwardSort(e); } /** * 在指定 worker 中的执行命令 * * @remarks * 当 worker 中成功执行,且 this 上没有对应的成员时,则会自动新增对应的成员方法 * * @param exec - 命令信息 * @param transfer - 传递给 Worker 的可传递对象。这些对象的所有权将被转移给 Worker,而发当前环境将不再保有所有权。 * @returns */ execCMDOnWorker(e, n, o) { ++this.execCount; const r = this.getExecRecord(n), i = this.getPort(e); this.execStarted(e, r), i.postMessage(r, o); const c = this.listenResponse(r.id, e), a = n.name; return a in this ? c : c.then((f) => (this.setCMDToSelf(a), f)); } /** * 在所有 worker 中的执行命令 * * @remarks * 当 worker 中成功执行,且 this 上没有对应的成员时,则会自动新增对应的成员方法 * * @param exec - 命令信息 * @param transfer - 传递给 Worker 的可传递对象。这些对象的所有权将被转移给 Worker,而发当前环境将不再保有所有权。 * @returns */ allExecCMD(e, n) { const o = [], r = [...this.queue.queue]; for (const a of r) { ++this.execCount; const f = this.getExecRecord(e), l = this.getPort(a); this.execStarted(a, f), l.postMessage(f, n); const m = this.listenResponse(f.id, a); o.push(m); } const i = Promise.all(o), c = e.name; return c in this ? i : i.then((a) => (this.setCMDToSelf(c), a)); } /** * 设置命令 * @remarks * 会在Worker中添加一条命令,并且也会在实例自身上添加一个快捷命令(快捷方法 或 快捷属性) * * @param cmd * @param name - 命令的命名;默认会取 `cmd.name` 作为名字;当 cmd 是字符串时,name 是必须的 * @param isProperty - 添加到实例自身的快捷命令是否作为属性;如果是 true,则会在实例自身上生成快捷属性 * @returns */ setCMD(e, n, o) { const r = n || e.name; if (!r) return Promise.reject("没有函数的名字"); const i = typeof e == "function" ? e.toString() : e; return this.allExecCMD({ name: "setCMD", args: [i, r] }).then((c) => (c && this.setCMDToSelf(r, o), c)); } /** * 移除命令 * @remarks * 会将 Worker 中的命令 和 自己实例上的对应快捷方法都给移除 * @param name * @returns */ removeCMD(e) { return this.allExecCMD({ name: "removeCMD", args: [e] }).then((n) => (n && Reflect.deleteProperty(this, e), n)); } } function L(s) { return new Proxy(s, { get: function(t, e, n) { const o = t[e]; return typeof o == "function" ? o.bind(t) : o || function(...r) { const i = r[0]; let c; return r.length === 1 && R(i) && (c = i.transfer, r = i.args), t.execCMD({ name: e, args: r.length > 0 ? r : void 0 }, c); }; }, set: function(t, e, n, o) { return t.setCMD(n, e, typeof n != "function"); }, deleteProperty: function(t, e) { return t.removeCMD(e); }, has: function(t, e) { return e in t; }, ownKeys: function(t) { return Reflect.ownKeys(t); } }); } function se(s, t) { const e = new Q(s, t); return L(e); } function oe(s, t, e) { const n = new Y(s, t, e); return L(n); } export { Q as DynamicWorker, Y as DynamicWorkerPool, V as SortQueue, C as WorkerClient, v as createBlobParts, se as createDynamicWorker, oe as createDynamicWorkerPool, E as createDynamicWorkerURL, ne as createObjectURLByCodes, w as createObjectURLByContents, L as createWorkerClientProxy, re as createWorkerURL, Z as dynamicWorkerCodeString, j as getWorker_Default, R as isCallOptions, W as listenMessages_Dep, X as workerPriorityComparator };