worker-tls
Version:
worker-tls 提供了 动态Worker 功能 和 其它一些 Worker 场景下有用的工具集;让开发者可以像调用对象方法一样动态地调用Worker中的方法,也可以随时地往 Worker 中动态地添加函数 等等。
658 lines (657 loc) • 20.1 kB
JavaScript
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
};