Skip to content

Instantly share code, notes, and snippets.

@citkane
Created December 21, 2024 13:50
Show Gist options
  • Save citkane/b25855b2b99679ae0540e5efedb2b5d0 to your computer and use it in GitHub Desktop.
Save citkane/b25855b2b99679ae0540e5efedb2b5d0 to your computer and use it in GitHub Desktop.
Deno code: Bun FFI `JSCallback` fails when called across threads in the same process
import lib, {
_bindName,
_evalHelloWorld,
_evalString,
dispatchJSCallback,
makeBindCallback,
} from "./lib.ts";
const worker = new Worker(import.meta.resolve("./worker.ts"), { type: "module" });
worker.onmessage = (event) => {
const handle = Deno.UnsafePointer.create(event.data as bigint);
const bindJSCallback = makeBindCallback(handle);
try {
lib.webview_dispatch(handle, dispatchJSCallback.pointer);
lib.webview_bind(handle, _bindName, bindJSCallback.pointer, null);
lib.webview_eval(handle, _evalHelloWorld);
} catch (err) {
console.error("error:", err);
}
setTimeout(() => {
lib.webview_eval(handle, _evalString);
}, 1000);
setTimeout(() => {
lib.webview_terminate(handle);
}, 2000);
};
import { resolve } from "node:path";
const encoder = new TextEncoder();
const libPath = resolve("../libwebview.so");
const { symbols } = Deno.dlopen(libPath, {
webview_create: {
parameters: ["i32", "pointer"],
result: "pointer",
},
webview_set_html: {
parameters: ["pointer", "buffer"],
result: "void",
},
webview_run: {
parameters: ["pointer"],
result: "void",
},
webview_dispatch: {
parameters: ["pointer", "function"],
result: "void",
},
webview_bind: {
parameters: ["pointer", "buffer", "function", "buffer"],
result: "void",
},
webview_eval: {
parameters: ["pointer", "buffer"],
result: "void",
},
webview_return: {
parameters: ["pointer", "pointer", "i32", "buffer"],
result: "void",
},
webview_destroy: {
parameters: ["pointer"],
result: "void",
},
webview_terminate: {
parameters: ["pointer"],
result: "void",
},
});
export default symbols;
export const html = encoder.encode("<html>Worker</html>\0");
export const _bindName = encoder.encode("testBind\0");
export const _evalString = encoder.encode("testBind()\0");
export const _evalHelloWorld = encoder.encode(`console.log("Hello World")\0`);
export const _nullReturn = encoder.encode(`""\0`);
export const dispatchJSCallback = new Deno.UnsafeCallback(
{ parameters: ["pointer"], result: "void" },
(id) => {
console.log("dispatched!");
}
);
export function makeBindCallback(handle: Deno.PointerValue) {
return new Deno.UnsafeCallback(
{ parameters: ["pointer", "pointer", "pointer"], result: "void" },
(id, argsStringPointer, userArgPointer?) => {
console.log("Bind was evaluated!");
symbols.webview_return(handle, id, 0, _nullReturn);
}
);
}
declare const self: Worker;
import lib, { _bindName, dispatchJSCallback, html, makeBindCallback } from "./lib.ts";
const handle = lib.webview_create(1, null);
lib.webview_set_html(handle, html);
postMessage(Deno.UnsafePointer.value(handle));
lib.webview_run(handle);
lib.webview_destroy(handle);
process.exit();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment