import {JSCallback, CString} from 'bun:ffi' import {encodeCString, default as lib} from './lib' export class Webview { static #instances = [] static unload() { for (const instance of this.#instances) instance.destroy() lib.close() } #handle #callbacks = {} constructor(debug = false, window) { this.#handle = lib.symbols.webview_create(Number(this.debug = debug), window) } get handle() { return handle } get window() { return lib.symbols.webview_get_window(this.#handle) } set title(title) { lib.symbols.webview_set_title(this.#handle, encodeCString(title)) } set size({width, height, hint}) { lib.symbols.webview_set_size(this.#handle, width, height, hint) } set html(html) { lib.symbols.webview_set_html(this.#handle, encodeCString(html)) } navigate(url) { lib.symbols.webview_navigate(this.#handle, encodeCString(url)) } init(source) { lib.symbols.webview_init(this.#handle, encodeCString(source)) } eval(source) { lib.symbols.webview_eval(this.#handle, encodeCString(source)) } run() { lib.symbols.webview_run(this.#handle) this.destroy() } return(id, status, result = null) { lib.symbols.webview_return(this.#handle, encodeCString(id), status, encodeCString(result)) } dispatch(name, ...arg) { lib.symbols.webview_dispatch(this.#handle, this.#callbacks[name], encodeCString(JSON.stringify(arg))) } destroy() { for (const callback of Object.keys(this.#callbacks)) this.unbind(callback) lib.symbols.webview_terminate(this.#handle) lib.symbols.webview_destroy(this.#handle) this.#handle = null } bindRaw(name, callback, arg) { lib.symbols.webview_bind(this.#handle, encodeCString(name), ( this.#callbacks[name] = new JSCallback((id, req, arg) => callback(new CString(id), new CString(req), arg), { args: ['cstring', 'cstring', 'ptr'] }) ).ptr, arg) } bind(name, callback) { this.bindRaw(name, (id, req) => { try { const result = callback(...JSON.parse(req)) if (result instanceof Promise) result.then(r => this.return(id, 0, JSON.stringify(r))) else this.return(id, 0, JSON.stringify(result)) } catch(error) { this.return(id, 1, error) } }) } unbind(name) { lib.symbols.webview_unbind(this.#handle, encodeCString(name)) this.#callbacks[name]?.close() delete this.#callbacks[name] } }