Class: Dommy::Worker

Inherits:
Object
  • Object
show all
Includes:
Bridge::Methods, EventTarget
Defined in:
lib/dommy/worker.rb

Overview

Worker — inline-emulated. Dommy does NOT spin up a separate execution context (no JS engine, no Ruby Thread). Instead:

- `new Worker("/path/to/worker.js")` records the URL.
- The script body is not executed. Tests install message
handlers on the worker-side via `worker.__test_on_message__ { ... }`
to simulate behavior.
- `worker.postMessage(data)` queues a microtask that delivers
to the worker-side handler.
- The worker-side handler can call `worker.__test_post_to_main__(data)`
to deliver a message back to the main side's `message` event.

This is enough surface to test "the app correctly posts/receives via Worker" without a real worker runtime.

Spec (real): https://html.spec.whatwg.org/multipage/workers.html

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Bridge::Methods

included

Methods included from EventTarget

#__dommy_dump_event_failure__, #__internal_deliver_event__, #__internal_process_event_handler_return__, #add_event_listener, capture_flag, #deliver_at, #dispatch_event, #event_name_from_on, #invoke_listener_isolated, js_truthy?, #on_handler, #remove_event_listener, #set_on_handler

Constructor Details

#initialize(window, url, _options = nil) ⇒ Worker

Returns a new instance of Worker.



25
26
27
28
29
30
31
# File 'lib/dommy/worker.rb', line 25

def initialize(window, url, _options = nil)
  @window = window
  @url = url.to_s
  @inline_handlers = {}
  @worker_side_handlers = []
  @terminated = false
end

Instance Attribute Details

#urlObject (readonly)

Returns the value of attribute url.



23
24
25
# File 'lib/dommy/worker.rb', line 23

def url
  @url
end

Instance Method Details

#__internal_event_parent__Object



115
116
117
# File 'lib/dommy/worker.rb', line 115

def __internal_event_parent__
  nil
end

#__js_call__(method, args) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/dommy/worker.rb', line 100

def __js_call__(method, args)
  case method
  when "postMessage"
    post_message(args[0])
  when "terminate"
    terminate
  when "addEventListener"
    add_event_listener(args[0], args[1], args[2])
  when "removeEventListener"
    remove_event_listener(args[0], args[1], args[2])
  when "dispatchEvent"
    dispatch_event(args[0])
  end
end

#__js_get__(key) ⇒ Object

--- JS bridge -------------------------------------------------



81
82
83
84
85
86
87
88
# File 'lib/dommy/worker.rb', line 81

def __js_get__(key)
  case key
  when "url"
    @url
  else
    @inline_handlers[inline_event_for(key)]
  end
end

#__js_set__(key, value) ⇒ Object



90
91
92
93
94
95
96
# File 'lib/dommy/worker.rb', line 90

def __js_set__(key, value)
  event = inline_event_for(key)
  return Bridge::UNHANDLED unless event

  set_inline_handler(event, value)
  nil
end

#__test_on_message__(&block) ⇒ Object

Register a callback that runs in the "worker side". Multiple registrations stack.



62
63
64
# File 'lib/dommy/worker.rb', line 62

def __test_on_message__(&block)
  @worker_side_handlers << block
end

#__test_post_to_main__(data) ⇒ Object

Worker-side: deliver a message to the main-side message event.



67
68
69
70
71
72
73
74
75
76
77
# File 'lib/dommy/worker.rb', line 67

def __test_post_to_main__(data)
  cloned = Dommy.structured_clone(data)
  @window.scheduler.set_timeout(
    proc do
      dispatch_event(MessageEvent.new("message", "data" => cloned))
    end,
    0
  )

  nil
end

#post_message(data) ⇒ Object Also known as: postMessage

Main-side: post a message to the worker.



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/dommy/worker.rb', line 34

def post_message(data)
  return if @terminated

  cloned = Dommy.structured_clone(data)
  # The "post message" task source — a task, not a microtask (a real worker
  # delivers across the agent boundary in a later event-loop turn).
  @window.scheduler.set_timeout(
    proc do
      @worker_side_handlers.each { |h| invoke(h, [{"data" => cloned}]) }
    end,
    0
  )

  nil
end

#terminateObject



52
53
54
55
56
# File 'lib/dommy/worker.rb', line 52

def terminate
  @terminated = true
  @worker_side_handlers.clear
  nil
end