Class: Dommy::AbortSignal
- Inherits:
-
Object
- Object
- Dommy::AbortSignal
- Includes:
- EventTarget
- Defined in:
- lib/dommy/event.rb
Overview
‘AbortController` + `AbortSignal` subset. Signal fires an “abort” event and flips `[:aborted]` to true when the controller’s ‘abort()` is called; otherwise it stays inert.
Class Method Summary collapse
-
.abort(reason = nil) ⇒ Object
Spec: ‘AbortSignal.abort(reason?)` returns a fresh, pre-aborted signal.
-
.any(signals) ⇒ Object
Spec: ‘AbortSignal.any([sig, …])` returns a composite signal that aborts as soon as any of the inputs aborts.
-
.timeout(ms, scheduler: nil) ⇒ Object
Spec: ‘AbortSignal.timeout(ms)` returns a signal that aborts itself after `ms` milliseconds with a `TimeoutError` reason.
Instance Method Summary collapse
- #__js_call__(method, args) ⇒ Object
- #__js_get__(key) ⇒ Object
- #__js_set__(_key, _value) ⇒ Object
- #__mark_aborted__(reason = nil) ⇒ Object
-
#__schedule_thread_timeout__(ms, reason) ⇒ Object
Background-thread timeout used by ‘AbortSignal.timeout` when no scheduler is provided.
- #aborted? ⇒ Boolean
-
#initialize ⇒ AbortSignal
constructor
A new instance of AbortSignal.
- #reason ⇒ Object
-
#throw_if_aborted ⇒ Object
(also: #throwIfAborted)
Spec: throws ‘signal.reason` if aborted, otherwise no-op.
Methods included from EventTarget
#__deliver_event__, #add_event_listener, #dispatch_event, #invoke_listener, #remove_event_listener
Constructor Details
#initialize ⇒ AbortSignal
Returns a new instance of AbortSignal.
497 498 499 500 |
# File 'lib/dommy/event.rb', line 497 def initialize @aborted = false @reason = nil end |
Class Method Details
.abort(reason = nil) ⇒ Object
Spec: ‘AbortSignal.abort(reason?)` returns a fresh, pre-aborted signal. Convenient for APIs that need an already-cancelled token.
454 455 456 457 458 |
# File 'lib/dommy/event.rb', line 454 def self.abort(reason = nil) signal = new signal.__mark_aborted__(reason) signal end |
.any(signals) ⇒ Object
Spec: ‘AbortSignal.any([sig, …])` returns a composite signal that aborts as soon as any of the inputs aborts. If any input is already aborted, the returned signal is pre-aborted with that input’s reason.
481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 |
# File 'lib/dommy/event.rb', line 481 def self.any(signals) composite = new list = Array(signals).select { |s| s.is_a?(AbortSignal) } already = list.find(&:aborted?) if already composite.__mark_aborted__(already.reason) return composite end list.each do |sig| sig.add_event_listener("abort", proc { composite.__mark_aborted__(sig.reason) }) end composite end |
.timeout(ms, scheduler: nil) ⇒ Object
Spec: ‘AbortSignal.timeout(ms)` returns a signal that aborts itself after `ms` milliseconds with a `TimeoutError` reason. Without a Window/scheduler we fall back to a Thread-based timer so the signal works in vanilla CRuby; embedders that want microtask integration can pass a window via `schedule_via`.
465 466 467 468 469 470 471 472 473 474 475 |
# File 'lib/dommy/event.rb', line 465 def self.timeout(ms, scheduler: nil) signal = new reason = DOMException::TimeoutError.new("operation timed out") if scheduler scheduler.set_timeout(proc { signal.__mark_aborted__(reason) }, ms.to_i) else signal.__schedule_thread_timeout__(ms.to_i, reason) end signal end |
Instance Method Details
#__js_call__(method, args) ⇒ Object
545 546 547 548 549 550 551 552 553 554 555 556 |
# File 'lib/dommy/event.rb', line 545 def __js_call__(method, args) case method when "addEventListener" add_event_listener(args[0], args[1], args[2]) when "removeEventListener" remove_event_listener(args[0], args[1]) when "dispatchEvent" dispatch_event(args[0]) when "throwIfAborted" throw_if_aborted end end |
#__js_get__(key) ⇒ Object
532 533 534 535 536 537 538 539 |
# File 'lib/dommy/event.rb', line 532 def __js_get__(key) case key when "aborted" @aborted when "reason" @reason end end |
#__js_set__(_key, _value) ⇒ Object
541 542 543 |
# File 'lib/dommy/event.rb', line 541 def __js_set__(_key, _value) nil end |
#__mark_aborted__(reason = nil) ⇒ Object
558 559 560 561 562 563 564 |
# File 'lib/dommy/event.rb', line 558 def __mark_aborted__(reason = nil) return if @aborted @aborted = true @reason = reason dispatch_event(Event.new("abort", "bubbles" => false, "cancelable" => false)) end |
#__schedule_thread_timeout__(ms, reason) ⇒ Object
Background-thread timeout used by ‘AbortSignal.timeout` when no scheduler is provided. Kept package-private; tests can also drive the abort manually via `mark_aborted`.
505 506 507 508 509 510 511 512 |
# File 'lib/dommy/event.rb', line 505 def __schedule_thread_timeout__(ms, reason) Thread.new do sleep(ms.to_f / 1000.0) __mark_aborted__(reason) end nil end |
#aborted? ⇒ Boolean
514 515 516 |
# File 'lib/dommy/event.rb', line 514 def aborted? @aborted end |
#reason ⇒ Object
518 519 520 |
# File 'lib/dommy/event.rb', line 518 def reason @reason end |
#throw_if_aborted ⇒ Object Also known as: throwIfAborted
Spec: throws ‘signal.reason` if aborted, otherwise no-op. Used by consumer code that polls before doing async work.
524 525 526 527 528 |
# File 'lib/dommy/event.rb', line 524 def throw_if_aborted return unless @aborted raise @reason.is_a?(Exception) ? @reason : RuntimeError.new(@reason.to_s) end |