141 lines
7.0 KiB
JavaScript
141 lines
7.0 KiB
JavaScript
var I = Object.defineProperty;
|
||
var E = (n) => {
|
||
throw TypeError(n);
|
||
};
|
||
var J = (n, e, s) => e in n ? I(n, e, { enumerable: !0, configurable: !0, writable: !0, value: s }) : n[e] = s;
|
||
var j = (n, e, s) => J(n, typeof e != "symbol" ? e + "" : e, s), D = (n, e, s) => e.has(n) || E("Cannot " + s);
|
||
var c = (n, e, s) => (D(n, e, "read from private field"), s ? s.call(n) : e.get(n)), Q = (n, e, s) => e.has(n) ? E("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(n) : e.set(n, s), S = (n, e, s, i) => (D(n, e, "write to private field"), i ? i.call(n, s) : e.set(n, s), s);
|
||
var P = (n, e, s, i) => ({
|
||
set _(f) {
|
||
S(n, e, f, s);
|
||
},
|
||
get _() {
|
||
return c(n, e, i);
|
||
}
|
||
});
|
||
const T = (n, e) => e.reduce((s, i) => s == null ? void 0 : s[i], n), U = (n) => n !== null && typeof n == "object" && Object.getPrototypeOf(n) === Object.prototype, N = (n) => {
|
||
const e = (i) => U(i) ? Object.fromEntries(Object.entries(i).map(
|
||
([f, u]) => typeof u == "function" ? [f, s(u)] : [f, u]
|
||
)) : i, s = (i) => (...f) => {
|
||
const u = [], x = f.map((h) => typeof h != "function" ? h : (...d) => {
|
||
const t = u.length;
|
||
return u.push({ fn: h, params: d }), `\0${t}\0`;
|
||
}), a = e(i(...x));
|
||
return u.length === 0 ? a : Promise.all(u.map(({ fn: h, params: d }) => h(...d))).then((h) => typeof a == "string" ? a.replace(/\x00(\d+)\x00/g, (d, t) => h[+t]) : Array.isArray(a) ? a.some((t) => typeof t == "string" && /^\x00\d+\x00$/.test(t)) ? a.map((t) => typeof t == "string" && /^\x00\d+\x00$/.test(t) ? h[+t.slice(1, -1)] : t) : u.filter((t, o) => h[o]).map(({ params: t }) => t[0]) : a);
|
||
};
|
||
return U(n) ? Object.fromEntries(Object.entries(n).map(
|
||
([i, f]) => typeof f == "function" ? [i, N(f)] : [i, f]
|
||
)) : (...i) => e(n(...i));
|
||
};
|
||
var A, M, w, y;
|
||
const r = class r {
|
||
/**
|
||
* @param {string|URL} workerUrl Worker 脚本地址
|
||
* @param {WorkerOptions} [options] 传给 new Worker() 的选项,如 { type: 'module' }
|
||
*/
|
||
constructor(e, s = {}) {
|
||
/** 底层 Worker 实例 */
|
||
Q(this, y);
|
||
/**
|
||
* 在 Worker 中执行一段代码字符串,返回其 return 值。
|
||
*
|
||
* @param {string} source 代码字符串,支持 async/await,可使用 Util 访问主线程函数
|
||
* @param {Object} [args] 注入代码的变量(以对象属性形式解构到函数参数中)
|
||
* @param {Object} [fns] 本次任务私有的函数注册,优先级低于 WorkerPipe.fns
|
||
* @param {string} [session] session 标识,相同 session 共享 Worker 侧工作区(this)
|
||
* @returns {Promise<any>}
|
||
*/
|
||
j(this, "exec", (e, s = {}, i = {}, f = "") => new Promise((u, x) => {
|
||
if (!/^(?!\s*(\/\/|\/\*|\*)).*?\S+/m.test(e)) return u();
|
||
const a = P(r, A)._++;
|
||
c(r, M).set(a, i), r.mQueue.set(a, [u, x]), c(this, y).postMessage({ id: a, session: f, category: "eval", method: e, args: s });
|
||
}));
|
||
/** 清除指定 session 的 Worker 侧工作区 */
|
||
j(this, "clear", (e) => c(this, y).postMessage({ session: e, category: "clear" }));
|
||
if (c(r, w)) return c(r, w);
|
||
S(this, y, new Worker(e, s));
|
||
const i = /* @__PURE__ */ new Map(), f = /* @__PURE__ */ new Map();
|
||
let u = 0;
|
||
const x = (t) => {
|
||
const o = crypto.randomUUID();
|
||
return i.set(o, t), setTimeout(() => i.delete(o), 3e4), o;
|
||
};
|
||
r.invokeWorkerFn = (t, o) => new Promise((p, b) => {
|
||
const g = u++;
|
||
f.set(g, [p, b]), c(this, y).postMessage({ category: "invoke_fn", fn_id: t, cb_id: g, args: o });
|
||
});
|
||
const a = (t) => {
|
||
if (!(t !== null && typeof t == "object" && Object.getPrototypeOf(t) === Object.prototype && Object.values(t).some((g) => typeof g == "function"))) return t;
|
||
const p = x(t);
|
||
return { ...Object.fromEntries(Object.entries(t).filter(([, g]) => typeof g != "function")), __chain_id__: p };
|
||
}, h = (t) => t != null && t.__fn_id__ ? new Proxy(function() {
|
||
}, {
|
||
apply: (o, p, b) => r.invokeWorkerFn(t.__fn_id__, b)
|
||
}) : t, d = ({ id: t, task_id: o, method: p, args: b, session: g, chain_id: $ }) => {
|
||
try {
|
||
let m;
|
||
if ($) {
|
||
const l = i.get($);
|
||
if (!l) throw `chain state '${$}' not found or expired`;
|
||
if (m = l[p], typeof m != "function") throw `${p} is not a function in chain state`;
|
||
m = m.bind(l);
|
||
} else {
|
||
const l = p.split("/");
|
||
if (m = T(r.fns, l) || T(c(r, M).get(o), l), typeof m != "function") throw `${p} not found`;
|
||
}
|
||
const F = Reflect.apply(m, void 0, b.map(h));
|
||
if (r.chainableTypes.some((l) => F instanceof l)) {
|
||
const l = x(F);
|
||
c(this, y).postMessage({ id: t, task_id: o, category: "util", method: p, args: b, session: g, data: { __chain_id__: l }, error: null });
|
||
return;
|
||
}
|
||
Promise.resolve(F).then((l) => {
|
||
c(this, y).postMessage({ id: t, task_id: o, category: "util", method: p, args: b, session: g, data: a(l), error: null });
|
||
}).catch((l) => {
|
||
let O;
|
||
try {
|
||
O = JSON.parse(JSON.stringify(l)), typeof O == "object" && !Array.isArray(O) && !Object.keys(O).length && (O = String(l));
|
||
} catch {
|
||
O = String(l);
|
||
}
|
||
c(this, y).postMessage({ id: t, task_id: o, category: "util", method: p, args: b, session: g, data: null, error: O });
|
||
});
|
||
} catch (m) {
|
||
c(this, y).postMessage({ id: t, task_id: o, category: "util", method: p, args: b, session: g, data: null, error: String(m) });
|
||
}
|
||
};
|
||
c(this, y).addEventListener("message", ({ data: t }) => {
|
||
if (t.category === "util")
|
||
d(t);
|
||
else if (t.category === "invoke_fn_result") {
|
||
const o = f.get(t.cb_id);
|
||
if (!o) return;
|
||
f.delete(t.cb_id), t.error !== null ? o[1](t.error) : o[0](t.result);
|
||
} else t.category === "eval" && r.mQueue.has(t.id) && (t.error !== null ? r.mQueue.get(t.id)[1](t.error) : r.mQueue.get(t.id)[0](t.data), c(r, M).delete(t.id), r.mQueue.delete(t.id));
|
||
}, !1), S(r, w, this);
|
||
}
|
||
/** 获取单例,首次调用时传入 Worker URL 和选项 */
|
||
static getInstance(e, s = {}) {
|
||
return c(r, w) || new r(e, s), c(r, w);
|
||
}
|
||
};
|
||
A = new WeakMap(), M = new WeakMap(), w = new WeakMap(), y = new WeakMap(), /** 可供 Worker 侧调用的函数注册表(静态,全局共享) */
|
||
j(r, "fns", {}), /** exec() 任务队列:task_id → [resolve, reject] */
|
||
j(r, "mQueue", /* @__PURE__ */ new Map()), /**
|
||
* 需要通过 chainStore 存储的自定义可链式类型(如 HttpResponse)。
|
||
* instanceof 匹配时,主线程将对象存入 chainStore 而非序列化传输。
|
||
*/
|
||
j(r, "chainableTypes", []), /** 全局递增消息 id,用于 mQueue 匹配 */
|
||
Q(r, A, 0), /** 每个 exec() 任务私有的 fns(第三参数),任务结束后清除 */
|
||
Q(r, M, /* @__PURE__ */ new Map()), /** 单例引用 */
|
||
Q(r, w, null), /**
|
||
* 反向调用 Worker 回调的函数:由构造函数赋值,供 wrapArg 使用。
|
||
* 签名:(fn_id: string, args: any[]) => Promise<any>
|
||
*/
|
||
j(r, "invokeWorkerFn", null);
|
||
let C = r;
|
||
export {
|
||
N as WithCallback,
|
||
C as WorkerPipe
|
||
};
|