Class: Dommy::Js::Quickjs::WasmBridge
- Inherits:
-
Object
- Object
- Dommy::Js::Quickjs::WasmBridge
- Defined in:
- lib/dommy/js/quickjs/wasm_bridge.rb
Overview
Handle-oriented JS access for a wasm guest (e.g. mruby-in-wasm under wasmtime-rb). Distinct from the Proxy-based HostBridge: instead of exposing Ruby DOM objects to JS as proxies, this lets a guest treat any JS value as an opaque integer ref it can get/set/call/new on — the shape the guest’s ‘js_*` bridge imports need.
The JS half lives in host_runtime.js (the ‘wasm*` functions on `__rbHost`); this is the thin Ruby facade over them. Every non-primitive JS value crosses as a `JSValue` (an opaque ref into the VM); primitives cross as plain Ruby values. Callbacks the guest registers become JS functions (also refs) that route back through `__rbWasmInvoke`.
Defined Under Namespace
Classes: JSValue
Instance Method Summary collapse
-
#apply(fn, this_arg, args) ⇒ Object
Apply a function ref directly (optionally with an explicit ‘this`).
- #call(recv, method, args) ⇒ Object
- #construct(ctor, args) ⇒ Object
-
#eval_js(src) ⇒ Object
Evaluate real JS source in global scope; returns the (packed) result.
- #get(recv, prop) ⇒ Object
-
#global_ref ⇒ Object
A ref to the VM’s globalThis — the guest’s ‘js_global`.
-
#initialize(backend) ⇒ WasmBridge
constructor
A new instance of WasmBridge.
- #instance_of?(value, ctor) ⇒ Boolean
- #js_null?(value) ⇒ Boolean
-
#make_callback(invoke_id) ⇒ Object
Make a JS function (returned as a ref) that calls back into the guest with the given invoke-id when invoked.
-
#on_invoke(&block) ⇒ Object
Install the dispatcher JS callbacks route back through.
-
#pack(value) ⇒ Object
Ruby value -> wasm-tagged JS value.
- #release(value) ⇒ Object
- #set(recv, prop, value) ⇒ Object
- #strict_equal(a, b) ⇒ Object
- #to_string(value) ⇒ Object
- #typeof(value) ⇒ Object
-
#unpack(value) ⇒ Object
wasm-tagged JS value -> Ruby value (JSValue for refs).
Constructor Details
#initialize(backend) ⇒ WasmBridge
Returns a new instance of WasmBridge.
26 27 28 |
# File 'lib/dommy/js/quickjs/wasm_bridge.rb', line 26 def initialize(backend) @backend = backend end |
Instance Method Details
#apply(fn, this_arg, args) ⇒ Object
Apply a function ref directly (optionally with an explicit ‘this`).
64 65 66 67 |
# File 'lib/dommy/js/quickjs/wasm_bridge.rb', line 64 def apply(fn, this_arg, args) this_ref = this_arg.nil? ? nil : ref_of(this_arg) unpack(@backend.call_js("__rbHost.wasmApply", ref_of(fn), this_ref, args.map { |a| pack(a) })) end |
#call(recv, method, args) ⇒ Object
59 60 61 |
# File 'lib/dommy/js/quickjs/wasm_bridge.rb', line 59 def call(recv, method, args) unpack(@backend.call_js("__rbHost.wasmCall", ref_of(recv), method.to_s, args.map { |a| pack(a) })) end |
#construct(ctor, args) ⇒ Object
69 70 71 |
# File 'lib/dommy/js/quickjs/wasm_bridge.rb', line 69 def construct(ctor, args) unpack(@backend.call_js("__rbHost.wasmNew", ref_of(ctor), args.map { |a| pack(a) })) end |
#eval_js(src) ⇒ Object
Evaluate real JS source in global scope; returns the (packed) result.
46 47 48 |
# File 'lib/dommy/js/quickjs/wasm_bridge.rb', line 46 def eval_js(src) unpack(@backend.call_js("__rbHost.wasmEval", src.to_s)) end |
#get(recv, prop) ⇒ Object
50 51 52 |
# File 'lib/dommy/js/quickjs/wasm_bridge.rb', line 50 def get(recv, prop) unpack(@backend.call_js("__rbHost.wasmGet", ref_of(recv), prop.to_s)) end |
#global_ref ⇒ Object
A ref to the VM’s globalThis — the guest’s ‘js_global`.
41 42 43 |
# File 'lib/dommy/js/quickjs/wasm_bridge.rb', line 41 def global_ref unpack(@backend.call_js("__rbHost.wasmGlobalRef")) end |
#instance_of?(value, ctor) ⇒ Boolean
91 92 93 |
# File 'lib/dommy/js/quickjs/wasm_bridge.rb', line 91 def instance_of?(value, ctor) @backend.call_js("__rbHost.wasmInstanceof", ref_of(value), ref_of(ctor)) end |
#js_null?(value) ⇒ Boolean
85 86 87 88 89 |
# File 'lib/dommy/js/quickjs/wasm_bridge.rb', line 85 def js_null?(value) return value.nil? unless value.is_a?(JSValue) @backend.call_js("__rbHost.wasmIsNull", value.ref) end |
#make_callback(invoke_id) ⇒ Object
Make a JS function (returned as a ref) that calls back into the guest with the given invoke-id when invoked.
97 98 99 |
# File 'lib/dommy/js/quickjs/wasm_bridge.rb', line 97 def make_callback(invoke_id) unpack(@backend.call_js("__rbHost.wasmMakeCallback", invoke_id.to_i)) end |
#on_invoke(&block) ⇒ Object
Install the dispatcher JS callbacks route back through. The block receives (invoke_id, packed_args) and must return a packed result (the same tagged shape #pack produces). Called once by the embedder.
33 34 35 36 37 38 |
# File 'lib/dommy/js/quickjs/wasm_bridge.rb', line 33 def on_invoke(&block) @backend.define_host_function("__rbWasmInvoke") do |invoke_id, args| block.call(invoke_id.to_i, args) end self end |
#pack(value) ⇒ Object
Ruby value -> wasm-tagged JS value. Public so the embedder’s #on_invoke dispatcher can pack the values it hands back into JS.
108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/dommy/js/quickjs/wasm_bridge.rb', line 108 def pack(value) case value when JSValue then {"__rb_js_ref" => value.ref} when nil, true, false, Integer, Float, String then value when Symbol then value.to_s when Array then value.map { |e| pack(e) } when Hash then value.each_with_object({}) { |(k, v), h| h[k.to_s] = pack(v) } else raise ArgumentError, "cannot pack #{value.class} for the wasm JS bridge" end end |
#release(value) ⇒ Object
101 102 103 104 |
# File 'lib/dommy/js/quickjs/wasm_bridge.rb', line 101 def release(value) @backend.call_js("__rbHost.wasmReleaseRef", value.ref) if value.is_a?(JSValue) nil end |
#set(recv, prop, value) ⇒ Object
54 55 56 57 |
# File 'lib/dommy/js/quickjs/wasm_bridge.rb', line 54 def set(recv, prop, value) @backend.call_js("__rbHost.wasmSet", ref_of(recv), prop.to_s, pack(value)) nil end |
#strict_equal(a, b) ⇒ Object
81 82 83 |
# File 'lib/dommy/js/quickjs/wasm_bridge.rb', line 81 def strict_equal(a, b) @backend.call_js("__rbHost.wasmStrictEqual", ref_of(a), ref_of(b)) end |
#to_string(value) ⇒ Object
77 78 79 |
# File 'lib/dommy/js/quickjs/wasm_bridge.rb', line 77 def to_string(value) @backend.call_js("__rbHost.wasmToString", ref_of(value)) end |
#typeof(value) ⇒ Object
73 74 75 |
# File 'lib/dommy/js/quickjs/wasm_bridge.rb', line 73 def typeof(value) @backend.call_js("__rbHost.wasmTypeof", ref_of(value)) end |
#unpack(value) ⇒ Object
wasm-tagged JS value -> Ruby value (JSValue for refs). Public for the same reason as #pack.
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/dommy/js/quickjs/wasm_bridge.rb', line 122 def unpack(value) case value when Hash if value.key?("__rb_js_ref") JSValue.new(value["__rb_js_ref"]) elsif value.key?("__rb_undefined") nil elsif value.key?("__rb_bytes") value["__rb_bytes"] elsif value.key?("__rb_arraybuffer") value["__rb_arraybuffer"] else value.each_with_object({}) { |(k, v), h| h[k] = unpack(v) } end when Array then value.map { |e| unpack(e) } else value end end |