module JS

JavaScript interoperations module

The JS module provides a way to interact with JavaScript from Ruby.

Example

require 'js'
JS.eval("return 1 + 2") # => 3
JS.global[:document].write("Hello, world!")
div = JS.global[:document].createElement("div")
div[:innerText] = "click me"
body = JS.global[:document][:body]
if body[:classList].contains?("main")
  body.appendChild(div)
end
div.addEventListener("click") do |event|
  puts event          # => # [object MouseEvent]
  puts event[:detail] # => 1
  div[:innerText] = "clicked!"
end

If you are using ‘ruby.wasm` without `stdlib` you will not have `addEventListener` and other specialized functions defined. You can still acomplish many of the same things using `call` instead.

Example

require 'js'
JS.eval("return 1 + 2") # => 3
JS.global[:document].call(:write, "Hello, world!")
div = JS.global[:document].call(:createElement, "div")
div[:innerText] = "click me"
if body[:classList].call(:contains, "main") == JS::True
  body.appendChild(div)
end
div.call(:addEventListener, "click") do |event|
  puts event          # => # [object MouseEvent]
  puts event[:detail] # => 1
  div[:innerText] = "clicked!"
end

Constants

False
Null
True

A boolean value in JavaScript is always a JS::Object instance from Ruby’s point of view. If we use the boolean value returned by a JavaScript function as the condition for an if expression in Ruby, the if expression will always be true.

Bad Example

searchParams = JS.global[:URLSearchParams].new(JS.global[:location][:search])
if searchParams.has('phrase')
  # Always pass through here.
  ...
else
  ...
end

Therefore, the JS::True constant is used to determine if the JavaScript function return value is true or false.

Good Example

if searchParams.has('phrase') == JS::True
  ...
end
Undefined
VERSION

Public Class Methods

eval(code) → JS::Object click to toggle source

Evaluates the given JavaScript code, returning the result as a JS::Object.

p JS.eval("return 1 + 1").to_i                             # => 2
p JS.eval("return new Object()").is_a?(JS.global[:Object]) # => true
static VALUE _rb_js_eval_js(VALUE _, VALUE code_str) {
  rb_js_abi_host_string_t abi_str;
  rstring_to_abi_string(code_str, &abi_str);
  rb_js_abi_host_js_abi_result_t ret;
  rb_js_abi_host_eval_js(&abi_str, &ret);
  raise_js_error_if_failure(&ret);
  return jsvalue_s_new(ret.val.success);
}
global → JS::Object click to toggle source

Returns globalThis JavaScript object.

p JS.global
p JS.global[:document]
static VALUE _rb_js_global_this(VALUE _) {
  return jsvalue_s_new(rb_js_abi_host_global_this());
}
is_a?(js_obj, js_class) → true or false click to toggle source

Returns true if js_class is the instance of js_obj, otherwise returns false. Comparison is done using the instanceof in JavaScript.

p JS.is_a?(JS.global, JS.global[:Object]) #=> true
p JS.is_a?(JS.global, Object)             #=> false
static VALUE _rb_js_is_kind_of(VALUE klass, VALUE obj, VALUE c) {
  if (!IS_JSVALUE(obj)) {
    return Qfalse;
  }
  struct jsvalue *val = DATA_PTR(obj);
  VALUE js_klass_v = _rb_js_try_convert(klass, c);
  struct jsvalue *js_klass = DATA_PTR(js_klass_v);
  return RBOOL(rb_js_abi_host_instance_of(val->abi, js_klass->abi));
}
promise_scheduler() click to toggle source
# File packages/gems/js/lib/js.rb, line 101
def self.promise_scheduler
  @promise_scheduler
end
try_convert(obj) → JS::Object or nil click to toggle source

Try to convert the given object to a JS::Object using to_js method. Returns nil if the object cannot be converted.

p JS.try_convert(1)                           # => JS::Object
p JS.try_convert("foo")                       # => JS::Object
p JS.try_convert(Object.new)                  # => nil
p JS.try_convert(JS::Object.wrap(Object.new)) # => JS::Object
VALUE _rb_js_try_convert(VALUE klass, VALUE obj) {
  if (_rb_js_is_js(klass, obj)) {
    return obj;
  } else if (rb_respond_to(obj, i_to_js)) {
    return rb_funcallv(obj, i_to_js, 0, NULL);
  } else {
    return Qnil;
  }
}