Class: Dommy::Scheduler
- Inherits:
-
Object
- Object
- Dommy::Scheduler
- Defined in:
- lib/dommy/scheduler.rb
Overview
Deterministic host-side scheduler for timers, rAF, and microtasks. Time advances only when the host explicitly calls ‘advance_time`.
Defined Under Namespace
Classes: Timer
Constant Summary collapse
- FRAME_MS =
16- IDLE_DEADLINE =
requestIdleCallback has no real idle period here; the callback always sees a fixed budget and didTimeout: false.
{"timeRemaining" => 50.0, "didTimeout" => false}.freeze
Instance Attribute Summary collapse
-
#native_microtask_scheduler ⇒ Object
An optional hook (set by a JS runtime) that enqueues a microtask onto the engine’s NATIVE promise-job queue.
-
#now_ms ⇒ Object
readonly
Returns the value of attribute now_ms.
Instance Method Summary collapse
- #advance_time(delta_ms) ⇒ Object
- #cancel_animation_frame(id) ⇒ Object
- #cancel_idle_callback(id) ⇒ Object
- #clear_interval(id) ⇒ Object
- #clear_timeout(id) ⇒ Object
- #drain_microtasks ⇒ Object
- #drain_timers(advance: 0) ⇒ Object
-
#initialize ⇒ Scheduler
constructor
A new instance of Scheduler.
-
#next_due_timer_at ⇒ Object
Public accessor for eval-time auto-drain: keep advancing the clock until no timers remain (or a safety budget runs out).
- #queue_microtask(callback) ⇒ Object
- #request_animation_frame(callback) ⇒ Object
-
#request_idle_callback(callback, timeout = 0) ⇒ Object
WHATWG requestIdleCallback — modeled as a deferred timer that hands the callback an IdleDeadline-shaped Hash.
- #set_interval(callback, interval_ms) ⇒ Object
- #set_timeout(callback, delay_ms) ⇒ Object
Constructor Details
#initialize ⇒ Scheduler
Returns a new instance of Scheduler.
15 16 17 18 19 20 21 |
# File 'lib/dommy/scheduler.rb', line 15 def initialize @now_ms = 0 @next_id = 1 @timers = {} @microtasks = [] @native_microtask_scheduler = nil end |
Instance Attribute Details
#native_microtask_scheduler ⇒ Object
An optional hook (set by a JS runtime) that enqueues a microtask onto the engine’s NATIVE promise-job queue. When present, ‘queue_microtask` routes through it so host-side microtasks (e.g. MutationObserver delivery) interleave FIFO with JS `await`/Promise reactions instead of draining on a separate pass. Absent in vanilla CRuby use (falls back to `@microtasks`).
30 31 32 |
# File 'lib/dommy/scheduler.rb', line 30 def native_microtask_scheduler @native_microtask_scheduler end |
#now_ms ⇒ Object (readonly)
Returns the value of attribute now_ms.
23 24 25 |
# File 'lib/dommy/scheduler.rb', line 23 def now_ms @now_ms end |
Instance Method Details
#advance_time(delta_ms) ⇒ Object
88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/dommy/scheduler.rb', line 88 def advance_time(delta_ms) target = @now_ms + [delta_ms.to_i, 0].max while next_due_timer_at && next_due_timer_at <= target @now_ms = next_due_timer_at run_due_timers drain_microtasks end @now_ms = target drain_microtasks nil end |
#cancel_animation_frame(id) ⇒ Object
56 57 58 |
# File 'lib/dommy/scheduler.rb', line 56 def cancel_animation_frame(id) cancel_timer(id) end |
#cancel_idle_callback(id) ⇒ Object
66 67 68 |
# File 'lib/dommy/scheduler.rb', line 66 def cancel_idle_callback(id) cancel_timer(id) end |
#clear_interval(id) ⇒ Object
45 46 47 |
# File 'lib/dommy/scheduler.rb', line 45 def clear_interval(id) cancel_timer(id) end |
#clear_timeout(id) ⇒ Object
36 37 38 |
# File 'lib/dommy/scheduler.rb', line 36 def clear_timeout(id) cancel_timer(id) end |
#drain_microtasks ⇒ Object
79 80 81 82 83 84 85 86 |
# File 'lib/dommy/scheduler.rb', line 79 def drain_microtasks until @microtasks.empty? callback = @microtasks.shift CallableInvoker.invoke(callback, @now_ms) end nil end |
#drain_timers(advance: 0) ⇒ Object
101 102 103 |
# File 'lib/dommy/scheduler.rb', line 101 def drain_timers(advance: 0) advance_time(advance) end |
#next_due_timer_at ⇒ Object
Public accessor for eval-time auto-drain: keep advancing the clock until no timers remain (or a safety budget runs out).
107 108 109 |
# File 'lib/dommy/scheduler.rb', line 107 def next_due_timer_at @timers.values.select(&:active).map(&:due_at).min end |
#queue_microtask(callback) ⇒ Object
70 71 72 73 74 75 76 77 |
# File 'lib/dommy/scheduler.rb', line 70 def queue_microtask(callback) if @native_microtask_scheduler @native_microtask_scheduler.call(callback) else @microtasks << callback end nil end |
#request_animation_frame(callback) ⇒ Object
49 50 51 52 53 54 |
# File 'lib/dommy/scheduler.rb', line 49 def request_animation_frame(callback) frames = ((@now_ms / FRAME_MS) + 1) * FRAME_MS id = next_id @timers[id] = Timer.new(id, :raf, callback, frames, nil, true) id end |
#request_idle_callback(callback, timeout = 0) ⇒ Object
WHATWG requestIdleCallback — modeled as a deferred timer that hands the callback an IdleDeadline-shaped Hash. No real idle period in dommy.
62 63 64 |
# File 'lib/dommy/scheduler.rb', line 62 def request_idle_callback(callback, timeout = 0) register_timer(:idle, callback, timeout.to_i, nil) end |
#set_interval(callback, interval_ms) ⇒ Object
40 41 42 43 |
# File 'lib/dommy/scheduler.rb', line 40 def set_interval(callback, interval_ms) ms = [interval_ms.to_i, 0].max register_timer(:interval, callback, ms, ms) end |
#set_timeout(callback, delay_ms) ⇒ Object
32 33 34 |
# File 'lib/dommy/scheduler.rb', line 32 def set_timeout(callback, delay_ms) register_timer(:timeout, callback, delay_ms.to_i, nil) end |