Class: RustyRacer::ExecJSRuntime::Context

Inherits:
ExecJS::Runtime::Context
  • Object
show all
Defined in:
lib/rusty_racer/execjs.rb

Constant Summary collapse

LOCATION =

‘filename` for every JS run, so a thrown error’s stack (which rusty_racer surfaces as the Ruby backtrace) reads “(execjs):line:col” — ExecJS’s test suite asserts the backtrace mentions “(execjs):”.

'(execjs)'

Instance Method Summary collapse

Constructor Details

#initialize(_runtime, source = '', _options = {}) ⇒ Context

Returns a new instance of Context.



32
33
34
35
36
37
38
39
40
41
# File 'lib/rusty_racer/execjs.rb', line 32

def initialize(_runtime, source = '', _options = {})
  @isolate = RustyRacer::Isolate.new
  @context = @isolate.context
  # ExecJS guarantees a bare global (no browser/Node ambient): V8 installs a
  # default `console`, so drop it to match the contract (consumers attach
  # their own if needed), exactly as the mini_racer runtime does.
  @context.eval('delete globalThis.console')
  source = encode(source)
  translate { @context.eval(source, filename: LOCATION) } if /\S/.match?(source)
end

Instance Method Details

#call(identifier, *args) ⇒ Object

Evaluate ‘identifier` to a function and call it with the global object as `this` and the (JSON-marshalled) args. `identifier` is arbitrary JS — a name path (“a.b.fn”), a member expression, or a function literal — so it is applied rather than looked up. The newline guards a trailing comment as in eval/exec.



71
72
73
# File 'lib/rusty_racer/execjs.rb', line 71

def call(identifier, *args)
  eval("(#{encode(identifier)}\n).apply(this, #{JSON.generate(args)})")
end

#eval(source, _options = {}) ⇒ Object

Evaluate an expression and return its (JSON-projected) value. Blank source is nil. The expression is parenthesised so a leading ‘{` reads as an object literal (and a trailing `//` comment can’t swallow the closing parens — hence the newline), then routed through JSON.stringify for ExecJS semantics.



56
57
58
59
60
61
62
63
64
# File 'lib/rusty_racer/execjs.rb', line 56

def eval(source, _options = {})
  source = encode(source)
  return unless /\S/.match?(source)

  json = translate { @context.eval("JSON.stringify((#{source}\n))", filename: LOCATION) }
  # JSON.stringify yields `undefined` (-> nil here) for a function/undefined
  # result; otherwise a JSON string to parse back.
  json.nil? ? nil : JSON.parse(json)
end

#exec(source, _options = {}) ⇒ Object

Run statements in a function body and return what they ‘return` (nil when nothing is returned), per ExecJS. The trailing newline before `}` ends any `//` line comment the source closes with, so it can’t eat the wrapper.



46
47
48
49
# File 'lib/rusty_racer/execjs.rb', line 46

def exec(source, _options = {})
  source = encode(source)
  eval("(function(){#{source}\n})()") if /\S/.match?(source)
end