Class: Dommy::Rack::SessionRuntime
- Inherits:
-
Object
- Object
- Dommy::Rack::SessionRuntime
- Defined in:
- lib/dommy/rack/session_runtime.rb
Overview
Binds a JS runtime to a Session: each HTML document the session loads gets
its own JS realm (window globals, listeners, timers), its <script> tags
boot, and window.fetch / external scripts resolve through the session's
Rack app (shared cookie jar). Subscribes to the session's
on_document_loaded seam so VM lifetime follows page loads.
The JS engine is pluggable: realms are built through
Dommy::Js.build_runtime, so any registered backend (QuickJS via
dommy-js-quickjs, others later) drives the session. This is the engine
behind Dommy::Rack::Session.new(app, javascript: true) and the Capybara
driver's JS support — one realm manager, two front ends.
Constant Summary collapse
- PUMP_SLICE_MS =
50
Instance Attribute Summary collapse
-
#console ⇒ Object
readonly
current_documentyields the document execute/evaluate should target (the session's current document by default; the Capybara driver passes its own frame-aware accessor). -
#js_errors ⇒ Object
readonly
current_documentyields the document execute/evaluate should target (the session's current document by default; the Capybara driver passes its own frame-aware accessor).
Instance Method Summary collapse
-
#advance_time(ms) ⇒ Object
Advance the current realm's virtual clock, running timers that come due, then drain.
- #current_runtime ⇒ Object
- #dispose ⇒ Object
-
#drain ⇒ Object
Drain the current realm's microtasks (used as an interaction's settle point: a Ruby-dispatched event ran JS handlers; flush their promises).
- #evaluate(js) ⇒ Object
- #execute(js) ⇒ Object
-
#initialize(session, ¤t_document) ⇒ SessionRuntime
constructor
A new instance of SessionRuntime.
-
#on_console(&block) ⇒ Object
Observation seams a Trace (or other host) subscribes to.
- #on_document(&block) ⇒ Object
- #on_js_error(&block) ⇒ Object
- #on_script(&block) ⇒ Object
-
#pump ⇒ Object
Advance virtual time a slice and drain across EVERY live realm, so a timer in any window (top or frame) progresses while a poller waits.
-
#runtime_for(doc) ⇒ Object
The realm VM for one document, built lazily and cached by identity so a frame switch keeps each realm's JS state instead of rebuilding it.
-
#settle ⇒ Object
Settle work ready at the current virtual time (microtasks + due-now timers + rAF) for the current document's realm.
Constructor Details
#initialize(session, ¤t_document) ⇒ SessionRuntime
Returns a new instance of SessionRuntime.
26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/dommy/rack/session_runtime.rb', line 26 def initialize(session, ¤t_document) @session = session @current_document = current_document || -> { session.document } @runtimes = {}.compare_by_identity @js_errors = [] @console = [] @console_listeners = [] @js_error_listeners = [] @script_listeners = [] @document_listeners = [] session.on_document_loaded { |window| on_page_load(window) } end |
Instance Attribute Details
#console ⇒ Object (readonly)
current_document yields the document execute/evaluate should target
(the session's current document by default; the Capybara driver passes
its own frame-aware accessor).
Uncaught JS errors and unhandled promise rejections collected across
every realm (a host can fail a test when non-empty), and console output.
24 25 26 |
# File 'lib/dommy/rack/session_runtime.rb', line 24 def console @console end |
#js_errors ⇒ Object (readonly)
current_document yields the document execute/evaluate should target
(the session's current document by default; the Capybara driver passes
its own frame-aware accessor).
Uncaught JS errors and unhandled promise rejections collected across
every realm (a host can fail a test when non-empty), and console output.
24 25 26 |
# File 'lib/dommy/rack/session_runtime.rb', line 24 def js_errors @js_errors end |
Instance Method Details
#advance_time(ms) ⇒ Object
Advance the current realm's virtual clock, running timers that come due, then drain.
61 62 63 64 65 |
# File 'lib/dommy/rack/session_runtime.rb', line 61 def advance_time(ms) scheduler_of(@current_document.call)&.advance_time(ms) current_runtime.drain_microtasks self end |
#current_runtime ⇒ Object
90 91 92 |
# File 'lib/dommy/rack/session_runtime.rb', line 90 def current_runtime runtime_for(@current_document.call) end |
#dispose ⇒ Object
94 95 96 |
# File 'lib/dommy/rack/session_runtime.rb', line 94 def dispose dispose_all end |
#drain ⇒ Object
Drain the current realm's microtasks (used as an interaction's settle point: a Ruby-dispatched event ran JS handlers; flush their promises).
69 70 71 72 |
# File 'lib/dommy/rack/session_runtime.rb', line 69 def drain current_runtime.drain_microtasks self end |
#evaluate(js) ⇒ Object
50 |
# File 'lib/dommy/rack/session_runtime.rb', line 50 def evaluate(js) = current_runtime.evaluate(js) |
#execute(js) ⇒ Object
49 |
# File 'lib/dommy/rack/session_runtime.rb', line 49 def execute(js) = current_runtime.execute(js) |
#on_console(&block) ⇒ Object
Observation seams a Trace (or other host) subscribes to. console output,
JS errors, and script-boot results are realm-internal — they surface
here, not on the Session — so the runtime fans them out. on_document
fires before a freshly loaded page's scripts boot (see on_page_load), so
a :document marker is ordered ahead of that page's :script entries.
44 |
# File 'lib/dommy/rack/session_runtime.rb', line 44 def on_console(&block) = @console_listeners << block |
#on_document(&block) ⇒ Object
47 |
# File 'lib/dommy/rack/session_runtime.rb', line 47 def on_document(&block) = @document_listeners << block |
#on_js_error(&block) ⇒ Object
45 |
# File 'lib/dommy/rack/session_runtime.rb', line 45 def on_js_error(&block) = @js_error_listeners << block |
#on_script(&block) ⇒ Object
46 |
# File 'lib/dommy/rack/session_runtime.rb', line 46 def on_script(&block) = @script_listeners << block |
#pump ⇒ Object
Advance virtual time a slice and drain across EVERY live realm, so a timer in any window (top or frame) progresses while a poller waits. Snapshot iteration: a fired timer may navigate and replace the map.
77 78 79 80 81 82 |
# File 'lib/dommy/rack/session_runtime.rb', line 77 def pump @runtimes.to_a.each do |doc, runtime| scheduler_of(doc)&.advance_time(PUMP_SLICE_MS) runtime.drain_microtasks end end |
#runtime_for(doc) ⇒ Object
The realm VM for one document, built lazily and cached by identity so a frame switch keeps each realm's JS state instead of rebuilding it.
86 87 88 |
# File 'lib/dommy/rack/session_runtime.rb', line 86 def runtime_for(doc) @runtimes[doc] ||= build_runtime(doc) end |
#settle ⇒ Object
Settle work ready at the current virtual time (microtasks + due-now timers + rAF) for the current document's realm.
54 55 56 57 |
# File 'lib/dommy/rack/session_runtime.rb', line 54 def settle current_runtime.settle self end |