Class: Dommy::MessagePort

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

Overview

MessagePort — one end of a MessageChannel. postMessage(value) dispatches a MessageEvent on the entangled port asynchronously.

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) ⇒ MessagePort

Returns a new instance of MessagePort.



39
40
41
42
43
44
45
# File 'lib/dommy/message_channel.rb', line 39

def initialize(window)
  @window = window
  @entangled = nil
  @onmessage = nil
  @started = false
  @pending = []
end

Instance Method Details

#__internal_enqueue__(event) ⇒ Object



92
93
94
# File 'lib/dommy/message_channel.rb', line 92

def __internal_enqueue__(event)
  @pending << event
end

#__internal_entangle__(other) ⇒ Object



47
48
49
# File 'lib/dommy/message_channel.rb', line 47

def __internal_entangle__(other)
  @entangled = other
end

#__internal_event_parent__Object



140
141
142
# File 'lib/dommy/message_channel.rb', line 140

def __internal_event_parent__
  nil
end

#__internal_started?Boolean

Returns:

  • (Boolean)


88
89
90
# File 'lib/dommy/message_channel.rb', line 88

def __internal_started?
  @started || !@inline_message_handler.nil?
end

#__js_call__(method, args) ⇒ Object



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/dommy/message_channel.rb', line 123

def __js_call__(method, args)
  case method
  when "postMessage"
    post_message(args[0])
  when "start"
    start
  when "close"
    close
  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



96
97
98
99
100
101
102
103
# File 'lib/dommy/message_channel.rb', line 96

def __js_get__(key)
  case key
  when "onmessage"
    @onmessage
  else
    Bridge::ABSENT
  end
end

#__js_set__(key, value) ⇒ Object



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/dommy/message_channel.rb', line 105

def __js_set__(key, value)
  case key
  when "onmessage"
    # Setting onmessage implicitly starts the port per spec.
    remove_event_listener("message", @onmessage) if @onmessage
    @onmessage = value
    @inline_message_handler = value
    add_event_listener("message", value) if value
    start if value
  else
    return Bridge::UNHANDLED
  end

  nil
end

#closeObject



83
84
85
86
# File 'lib/dommy/message_channel.rb', line 83

def close
  @entangled = nil
  nil
end

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



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/dommy/message_channel.rb', line 51

def post_message(data)
  port = @entangled
  return unless port

  # The "post message" task source — a task, NOT a microtask, so delivery
  # happens in a later event-loop turn (after the current task's microtask
  # checkpoint), matching browsers.
  @window.scheduler.set_timeout(
    proc do
      evt = MessageEvent.new("message", "data" => Dommy.structured_clone(data))
      if port.__internal_started?
        port.dispatch_event(evt)
      else
        port.__internal_enqueue__(evt)
      end
    end,
    0
  )

  nil
end

#startObject



75
76
77
78
79
80
81
# File 'lib/dommy/message_channel.rb', line 75

def start
  @started = true
  flush = @pending
  @pending = []
  flush.each { |evt| dispatch_event(evt) }
  nil
end