diff --git a/lib/execjs/duktape_runtime.rb b/lib/execjs/duktape_runtime.rb index 8ae42a5..7758fdf 100644 --- a/lib/execjs/duktape_runtime.rb +++ b/lib/execjs/duktape_runtime.rb @@ -26,7 +26,8 @@ module ExecJS end def call(identifier, *args) - @ctx.call_prop(identifier.split("."), *args) + @ctx.exec_string("__execjs_duktape_call = #{identifier}", '(execjs)') + @ctx.call_prop("__execjs_duktape_call", *args) rescue Exception => e raise wrap_error(e) end diff --git a/lib/execjs/ruby_racer_runtime.rb b/lib/execjs/ruby_racer_runtime.rb index cf8e1a2..682efd5 100644 --- a/lib/execjs/ruby_racer_runtime.rb +++ b/lib/execjs/ruby_racer_runtime.rb @@ -42,7 +42,7 @@ module ExecJS def call(properties, *args) lock do begin - unbox @v8_context.eval(properties).call(*args) + unbox @v8_context.eval("(#{properties})").call(*args) rescue ::V8::JSError => e raise wrap_error(e) end diff --git a/lib/execjs/runtime.rb b/lib/execjs/runtime.rb index eba424c..822bf5a 100644 --- a/lib/execjs/runtime.rb +++ b/lib/execjs/runtime.rb @@ -9,15 +9,30 @@ module ExecJS def initialize(runtime, source = "", options = {}) end + # Evaluates the +source+ in the context of a function body and returns the + # returned value. + # + # context.exec("return 1") # => 1 + # context.exec("1") # => nil (nothing was returned) def exec(source, options = {}) raise NotImplementedError end + # Evaluates the +source+ as an expression and returns the result. + # + # context.eval("1") # => 1 + # context.eval("return 1") # => Raises SyntaxError def eval(source, options = {}) raise NotImplementedError end - def call(properties, *args) + # Evaluates +source+ as an expression (which should be of type + # +function+), and calls the function with the given arguments. + # The function will be evaluated with the global object as +this+. + # + # context.call("function(a, b) { return a + b }", 1, 1) # => 2 + # context.call("CoffeeScript.compile", "1 + 1") + def call(source, *args) raise NotImplementedError end end diff --git a/test/test_execjs.rb b/test/test_execjs.rb index 0ee411f..81804a1 100644 --- a/test/test_execjs.rb +++ b/test/test_execjs.rb @@ -48,6 +48,34 @@ class TestExecJS < Test assert_equal "bar", context.call("a.b.id", "bar") end + def test_call_with_complex_properties + context = ExecJS.compile("") + assert_equal 2, context.call("function(a, b) { return a + b }", 1, 1) + + context = ExecJS.compile("foo = 1") + assert_equal 2, context.call("(function(bar) { return foo + bar })", 1) + end + + def test_call_with_this + # Known bug: https://github.com/cowboyd/therubyrhino/issues/39 + skip if ExecJS.runtime.is_a?(ExecJS::RubyRhinoRuntime) + + # Make sure that `this` is indeed the global scope + context = ExecJS.compile(<<-EOF) + name = 123; + + function Person(name) { + this.name = name; + } + + Person.prototype.getThis = function() { + return this.name; + } + EOF + + assert_equal 123, context.call("(new Person('Bob')).getThis") + end + def test_context_call_missing_function context = ExecJS.compile("") assert_raises ExecJS::ProgramError do