This commit is contained in:
iqudoo
2026-06-17 12:50:02 +08:00
parent d574f08faf
commit c2476b9f85
14 changed files with 1338 additions and 53 deletions

View File

@@ -50,6 +50,7 @@ function isEmbedMessage(data) {
let embedHostInstalled = false;
let embedChildInstalled = false;
const pendingInvokes = Object.create(null);
const pendingCallbackInvokes = Object.create(null);
const childCallbackFns = Object.create(null);
function cloneArgsReplacingFunctions(val, registry, seen) {
@@ -93,16 +94,21 @@ function hydrateEmbedParams(params, messageSource, targetOrigin) {
const cbId = val.__IScanEmbedCb__;
return function embedCbProxy() {
const args = Array.prototype.slice.call(arguments);
messageSource.postMessage(
{
source: EMBED_SOURCE,
v: EMBED_V,
kind: "callback",
cbId,
args,
},
targetOrigin
);
const callbackInvokeId = createUUID();
return new Promise((resolve, reject) => {
pendingCallbackInvokes[callbackInvokeId] = { resolve, reject };
messageSource.postMessage(
{
source: EMBED_SOURCE,
v: EMBED_V,
kind: "callback",
cbId,
callbackInvokeId,
args,
},
targetOrigin
);
});
};
}
if (val === null || typeof val !== "object") {
@@ -262,9 +268,35 @@ function embedChildOnMessage(ev) {
}
if (data.kind === "callback") {
const fn = childCallbackFns[data.cbId];
if (typeof fn === "function") {
fn.apply(null, data.args || []);
const replyCallbackResult = (ok, result, error) => {
if (!data.callbackInvokeId || !ev.source) {
return;
}
ev.source.postMessage(
{
source: EMBED_SOURCE,
v: EMBED_V,
kind: "callbackResult",
callbackInvokeId: data.callbackInvokeId,
ok,
result: ok ? result : undefined,
error: ok ? undefined : error,
},
ev.origin
);
};
if (typeof fn !== "function") {
replyCallbackResult(false, null, "[IScan embed]: callback not found");
return;
}
Promise.resolve(fn.apply(null, data.args || []))
.then((result) => {
replyCallbackResult(true, result);
})
.catch((err) => {
replyCallbackResult(false, null, String((err && err.message) || err));
});
return;
}
}
@@ -390,6 +422,19 @@ export function installEmbedHost(lib) {
}
return;
}
if (data.kind === "callbackResult") {
const pending = pendingCallbackInvokes[data.callbackInvokeId];
if (!pending) {
return;
}
delete pendingCallbackInvokes[data.callbackInvokeId];
if (data.ok) {
pending.resolve(data.result);
} else {
pending.reject(new Error(data.error || "[IScan embed]: callback failed"));
}
return;
}
if (data.kind !== "invoke") {
return;
}