Module: Dommy::Js::Runtime

Defined in:
lib/dommy/js/runtime.rb

Overview

The Runtime port: the contract a JS engine must satisfy to drive a Dommy DOM. Dommy::Browser and Dommy::Js::ScriptBoot depend on this interface, never on a concrete engine — so a backend (QuickJS today, others later) is a pluggable implementation registered through Dommy::Js.register_runtime.

This module is documentation + a conformance check, not a base class: engines satisfy it by duck typing (no inheritance), and conforms? / assert_conformance! verify the surface so a partial backend fails fast with a clear message instead of an obscure NoMethodError mid-boot.

The contract, as the host layer uses it:

Lifecycle / wiring
install_window(window)        seed the realm's window globals + DOM
install_browser_globals       CSS / fetch / addEventListener / ...
define_host_object(name, obj) expose a Ruby object under a JS global
on_unhandled_rejection { |e } observe uncaught promise rejections
on_log { |entry| }            observe console.* output
dispose                       tear down the realm

Script boot (driven by ScriptBoot)
set_document_ready_state(s)   replay loading/interactive/complete
module_loader = callable      install the ESM resolver Proc
load_script(js)               run a classic inline script
load_script_cached(js, cache_key:)  run external script, cache bytecode
load_module_url(url)          run an ES module by URL

Driving / settling
execute(js)                   run for side effects
evaluate(js)                  run and decode the result
settle                        drain microtasks + due-now timers + rAF
drain_microtasks              drain the microtask queue only

Optional (a backend may omit these; callers must guard with respond_to?): install_wasm_memory_shim opt-in WPT SharedArrayBuffer scaffolding

Constant Summary collapse

REQUIRED_METHODS =

The methods every conforming runtime must respond to.

%i[
  install_window install_browser_globals define_host_object
  on_unhandled_rejection on_log dispose
  set_document_ready_state module_loader= load_script load_script_cached load_module_url
  execute evaluate settle drain_microtasks
].freeze
OPTIONAL_METHODS =

Methods a backend may implement but is not required to. on_callback_error { |e } observe a timer/rAF callback the engine force-killed (runaway loop); recorded, not fatal

%i[install_wasm_memory_shim on_callback_error].freeze

Class Method Summary collapse

Class Method Details

.assert_conformance!(obj) ⇒ Object

Raise unless obj satisfies the contract, naming what is missing.

Raises:

  • (ArgumentError)


64
65
66
67
68
69
70
71
# File 'lib/dommy/js/runtime.rb', line 64

def assert_conformance!(obj)
  missing = missing_methods(obj)
  return obj if missing.empty?

  raise ArgumentError,
    "#{obj.class} is not a conforming Dommy::Js::Runtime " \
    "(missing: #{missing.join(", ")})"
end

.conforms?(obj) ⇒ Boolean

Returns:

  • (Boolean)


61
# File 'lib/dommy/js/runtime.rb', line 61

def conforms?(obj) = missing_methods(obj).empty?

.missing_methods(obj) ⇒ Object

The required methods obj does not respond to (empty when conforming).



57
58
59
# File 'lib/dommy/js/runtime.rb', line 57

def missing_methods(obj)
  REQUIRED_METHODS.reject { |m| obj.respond_to?(m) }
end