Class: Dommy::Worker

Inherits:
Object
  • Object
show all
Includes:
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.__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.__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): html.spec.whatwg.org/multipage/workers.html

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from EventTarget

#__deliver_event__, #add_event_listener, #dispatch_event, #invoke_listener, #remove_event_listener

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

#__event_parent__Object



107
108
109
# File 'lib/dommy/worker.rb', line 107

def __event_parent__
  nil
end

#__js_call__(method, args) ⇒ Object



92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/dommy/worker.rb', line 92

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])
  when "dispatchEvent"
    dispatch_event(args[0])
  end
end

#__js_get__(key) ⇒ Object

— JS bridge ————————————————-



77
78
79
80
81
82
83
84
# File 'lib/dommy/worker.rb', line 77

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

#__js_set__(key, value) ⇒ Object



86
87
88
89
90
# File 'lib/dommy/worker.rb', line 86

def __js_set__(key, value)
  event = inline_event_for(key)
  set_inline_handler(event, value) if event
  nil
end

#__on_message__(&block) ⇒ Object

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



59
60
61
# File 'lib/dommy/worker.rb', line 59

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

#__post_to_main__(data) ⇒ Object

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



64
65
66
67
68
69
70
71
72
73
# File 'lib/dommy/worker.rb', line 64

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

  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
# File 'lib/dommy/worker.rb', line 34

def post_message(data)
  return if @terminated

  cloned = Dommy.structured_clone(data)
  @window.scheduler.queue_microtask(
    proc do
      @worker_side_handlers.each { |h| invoke(h, [{"data" => cloned}]) }
    end
  )

  nil
end

#terminateObject



49
50
51
52
53
# File 'lib/dommy/worker.rb', line 49

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