Class: JS::Object

Inherits:
Object show all
Defined in:
lib/unloosen/utils/js.rb,
lib/unloosen/compat/rubygems.rb

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(sym, *args, &block) ⇒ Object



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/unloosen/utils/js.rb', line 115

def method_missing(sym, *args, &block)
  ret = self[sym]

  case ret.typeof
  when "undefined"
    str = sym.to_s
    if str[-1] == "="
      self[str.chop.to_sym] = args.first
      return args.first
    end

    super
  when "function"
    self.call(sym, *args.map, &block).to_rb
  else
    ret.to_rb
  end
end

Instance Method Details

#awaitObject

Await a JavaScript Promise like ‘await` in JavaScript. This method looks like a synchronous method, but it actually runs asynchronously using fibers. In other words, the next line to the `await` call at Ruby source will be executed after the promise will be resolved. However, it does not block JavaScript event loop, so the next line to the `RubyVM.eval` or `RubyVM.evalAsync` (in the case when no `await` operator before the call expression) at JavaScript source will be executed without waiting for the promise.

The below example shows how the execution order goes. It goes in the order of “step N”

# In JavaScript
const response = vm.evalAsync(`
  puts "step 1"
  JS.global.fetch("https://example.com").await
  puts "step 3"
`) // => Promise
console.log("step 2")
await response
console.log("step 4")

The below examples show typical usage in Ruby

JS.eval("return new Promise((ok) => setTimeout(() => ok(42), 1000))").await # => 42 (after 1 second)
JS.global.fetch("https://example.com").await                                # => [object Response]
JS.eval("return 42").await                                                  # => 42
JS.eval("return new Promise((ok, err) => err(new Error())").await           # => raises JS::Error


175
176
177
178
179
# File 'lib/unloosen/utils/js.rb', line 175

def await
  # Promise.resolve wrap a value or flattens promise-like object and its thenable chain

  promise = JS.global[:Promise].resolve(self)
  JS.promise_scheduler.await(promise)
end

#respond_to_missing?(sym, include_private) ⇒ Boolean

Returns:

  • (Boolean)


134
135
136
137
# File 'lib/unloosen/utils/js.rb', line 134

def respond_to_missing?(sym, include_private)
  return true if super
  self[sym].typeof != "undefined"
end

#to_aObject



28
29
30
31
32
33
34
# File 'lib/unloosen/compat/rubygems.rb', line 28

def to_a
    ary = []
    self[:length].to_i.times do |i|
        ary << self.call(:at, i).to_i
    end
    ary
end

#to_rbObject



139
140
141
142
143
144
145
146
147
148
# File 'lib/unloosen/utils/js.rb', line 139

def to_rb
  case self.typeof
  when "number"
    self.to_f
  when "string"
    self.to_s
  else
    self
  end
end