Files
ff-worker-pipe/main.js
2026-07-16 11:10:09 +08:00

141 lines
7.0 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
};