Skip to content

Commit

Permalink
Add JS::Object#apply method to call JS function without receiver
Browse files Browse the repository at this point in the history
This method is similar to `JS::Object#call`, but it is used to call a
function that is not a method of an object.

```ruby
floor = JS.global[:Math][:floor]
floor.apply(3.14) # => 3
JS.global[:Promise].new do |resolve, reject|
  resolve.apply(42)
end.await # => 42
```
  • Loading branch information
kateinoigakukun committed Mar 16, 2024
1 parent f96ff58 commit aee363b
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 0 deletions.
14 changes: 14 additions & 0 deletions packages/gems/js/lib/js.rb
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,20 @@ def respond_to_missing?(sym, include_private)
self[sym].typeof == "function"
end

# Call the receiver (a JavaScript function) with `undefined` as its receiver context.
# This method is similar to JS::Object#call, but it is used to call a function that is not
# a method of an object.
#
# floor = JS.global[:Math][:floor]
# floor.apply(3.14) # => 3
# JS.global[:Promise].new do |resolve, reject|
# resolve.apply(42)
# end.await # => 42
def apply(*args, &block)
args = args + [block] if block
JS.global[:Reflect].call(:apply, self, JS::Undefined, args.to_js)
end

# 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
Expand Down
9 changes: 9 additions & 0 deletions packages/npm-packages/ruby-wasm-wasi/test/unit/test_object.rb
Original file line number Diff line number Diff line change
Expand Up @@ -357,4 +357,13 @@ def test_member_set_with_stress_gc
JS.global[:tmp] = "1"
GC.stress = false
end

def test_apply
object = JS.eval(<<~JS)
return { foo(a, b, c) { return a + b + c; } };
JS
assert_equal 6, object[:foo].apply(1, 2, 3).to_i
floor = JS.global[:Math][:floor]
assert_equal 3, floor.apply(3.14).to_i
end
end

0 comments on commit aee363b

Please sign in to comment.