feat(wasm): execute client handlers without requests
req: client_local/001\nreq: client_local/004\nreq: client_local/005\nreq: client_local/009\nreq: client_local/010\nreq: client_local/014\nreq: v1_release/001
This commit is contained in:
Vendored
+1
@@ -54,6 +54,7 @@ export interface HemxRuntime {
|
||||
decodeBatch(buffer: ArrayBuffer): EffectBatch;
|
||||
atomValue(root: Element | ParentNode | null | undefined, id: number): Uint8Array | undefined;
|
||||
decodeAtomState(encoded: string): AtomSnapshot[];
|
||||
registerClientHandler(name: string, handler: () => Uint8Array | Promise<Uint8Array>): void;
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
||||
+29
-2
@@ -18,6 +18,7 @@
|
||||
const sseSources = new WeakMap();
|
||||
const atomStores = new WeakMap();
|
||||
const dragKeys = new WeakMap();
|
||||
const clientHandlers = new Map();
|
||||
|
||||
function roots() {
|
||||
const found = [];
|
||||
@@ -237,6 +238,15 @@
|
||||
});
|
||||
}
|
||||
|
||||
async function runClient(el) {
|
||||
const name = el.getAttribute("data-hemx-client");
|
||||
const handler = clientHandlers.get(name);
|
||||
if (!handler) throw new Error(`unknown client-local hemx handler: ${name}`);
|
||||
const wire = await handler();
|
||||
if (!(wire instanceof Uint8Array)) throw new Error(`client-local hemx handler ${name} returned an invalid effect batch`);
|
||||
applyBatch(wire, rootOf(el));
|
||||
}
|
||||
|
||||
async function send(el, eventName, source = el) {
|
||||
if (el.getAttribute("data-hemx-confirm") && !confirm(el.getAttribute("data-hemx-confirm"))) return;
|
||||
const { form, data, multipart } = formDataFor(el, eventName, source);
|
||||
@@ -671,7 +681,11 @@
|
||||
const direct = closestInRoot(event.target, root, (el) => el.hasAttribute(HID));
|
||||
if (direct && defaultEvent(direct) === "click") {
|
||||
event.preventDefault();
|
||||
schedule(direct, name);
|
||||
if (direct.hasAttribute("data-hemx-client")) {
|
||||
runClient(direct).catch((error) => emit(root, "hemx:client-error", String(error)));
|
||||
} else {
|
||||
schedule(direct, name);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -935,7 +949,20 @@
|
||||
if (root) navigateUrl(location.href, root, "none").catch((error) => emit(root, "hemx:error", String(error)));
|
||||
});
|
||||
|
||||
window.hemx = Object.freeze({ runtimeAbiVersion, roots, rootOf, applyHtml, applyBatch, decodeBatch, atomValue, decodeAtomState });
|
||||
window.hemx = Object.freeze({
|
||||
runtimeAbiVersion,
|
||||
roots,
|
||||
rootOf,
|
||||
applyHtml,
|
||||
applyBatch,
|
||||
decodeBatch,
|
||||
atomValue,
|
||||
decodeAtomState,
|
||||
registerClientHandler(name, handler) {
|
||||
if (!name || typeof handler !== "function") throw new Error("client handler registration requires a name and function");
|
||||
clientHandlers.set(name, handler);
|
||||
},
|
||||
});
|
||||
|
||||
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start);
|
||||
else start();
|
||||
|
||||
Reference in New Issue
Block a user