mirror of
https://github.com/rails/execjs
synced 2023-03-27 23:21:20 -04:00
Context
This commit is contained in:
parent
763513d9b1
commit
82773bfbde
6 changed files with 189 additions and 104 deletions
|
@ -18,6 +18,10 @@ module ExecJS
|
|||
runtime.eval(source)
|
||||
end
|
||||
|
||||
def self.compile(source)
|
||||
runtime.compile(source)
|
||||
end
|
||||
|
||||
def self.runtimes
|
||||
Runtimes.runtimes
|
||||
end
|
||||
|
|
|
@ -3,6 +3,56 @@ require "tempfile"
|
|||
|
||||
module ExecJS
|
||||
class ExternalRuntime
|
||||
class Context
|
||||
def initialize(runtime)
|
||||
@runtime = runtime
|
||||
@script = ""
|
||||
end
|
||||
|
||||
def eval(source)
|
||||
if /\S/ =~ source
|
||||
exec("return eval(#{"(#{source})".to_json})")
|
||||
end
|
||||
end
|
||||
|
||||
def exec(source)
|
||||
@script << source
|
||||
@script << "\n"
|
||||
|
||||
compile_to_tempfile(@script) do |file|
|
||||
extract_result(@runtime.exec_runtime(file.path))
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
def compile_to_tempfile(source)
|
||||
tempfile = Tempfile.open("execjs")
|
||||
tempfile.write compile(source)
|
||||
tempfile.close
|
||||
yield tempfile
|
||||
ensure
|
||||
tempfile.close!
|
||||
end
|
||||
|
||||
def compile(source)
|
||||
@runtime.runner_source.dup.tap do |output|
|
||||
output.sub!('#{source}', source)
|
||||
output.sub!('#{json2_source}') do
|
||||
IO.read(ExecJS.root + "/support/json2.js")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def extract_result(output)
|
||||
status, value = output.empty? ? [] : JSON.parse(output)
|
||||
if status == "ok"
|
||||
value
|
||||
else
|
||||
raise ProgramError, value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
attr_reader :name
|
||||
|
||||
def initialize(options)
|
||||
|
@ -15,22 +65,39 @@ module ExecJS
|
|||
@binary = locate_binary
|
||||
end
|
||||
|
||||
def eval(source)
|
||||
if /\S/ =~ source
|
||||
exec("return eval(#{"(#{source})".to_json})")
|
||||
end
|
||||
def exec(source)
|
||||
context = Context.new(self)
|
||||
context.exec(source)
|
||||
end
|
||||
|
||||
def exec(source)
|
||||
compile_to_tempfile(source) do |file|
|
||||
extract_result(exec_runtime(file.path))
|
||||
def eval(source)
|
||||
context = Context.new(self)
|
||||
context.eval(source)
|
||||
end
|
||||
|
||||
def compile(source)
|
||||
context = Context.new(self)
|
||||
context.exec(source)
|
||||
context
|
||||
end
|
||||
|
||||
def available?
|
||||
@binary ? true : false
|
||||
end
|
||||
|
||||
def runner_source
|
||||
@runner_source ||= IO.read(@runner_path)
|
||||
end
|
||||
|
||||
def exec_runtime(filename)
|
||||
output = sh("#{@binary} #{filename} 2>&1")
|
||||
if $?.success?
|
||||
output
|
||||
else
|
||||
raise RuntimeError, output
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
def locate_binary
|
||||
if binary = which(@command)
|
||||
|
@ -55,37 +122,6 @@ module ExecJS
|
|||
end
|
||||
end
|
||||
|
||||
def compile(source)
|
||||
runner_source.dup.tap do |output|
|
||||
output.sub!('#{source}', source)
|
||||
output.sub!('#{json2_source}') do
|
||||
IO.read(ExecJS.root + "/support/json2.js")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def runner_source
|
||||
@runner_source ||= IO.read(@runner_path)
|
||||
end
|
||||
|
||||
def compile_to_tempfile(source)
|
||||
tempfile = Tempfile.open("execjs")
|
||||
tempfile.write compile(source)
|
||||
tempfile.close
|
||||
yield tempfile
|
||||
ensure
|
||||
tempfile.close!
|
||||
end
|
||||
|
||||
def exec_runtime(filename)
|
||||
output = sh("#{@binary} #{filename} 2>&1")
|
||||
if $?.success?
|
||||
output
|
||||
else
|
||||
raise RuntimeError, output
|
||||
end
|
||||
end
|
||||
|
||||
if "".respond_to?(:force_encoding)
|
||||
def sh(command)
|
||||
output, options = nil, {}
|
||||
|
@ -108,14 +144,5 @@ module ExecJS
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
def extract_result(output)
|
||||
status, value = output.empty? ? [] : JSON.parse(output)
|
||||
if status == "ok"
|
||||
value
|
||||
else
|
||||
raise ProgramError, value
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
module ExecJS
|
||||
class RubyRacerRuntime
|
||||
def name
|
||||
"therubyracer (V8)"
|
||||
class Context
|
||||
def initialize
|
||||
@v8_context = ::V8::Context.new
|
||||
end
|
||||
|
||||
def exec(source)
|
||||
|
@ -12,8 +13,7 @@ module ExecJS
|
|||
|
||||
def eval(source)
|
||||
if /\S/ =~ source
|
||||
context = ::V8::Context.new
|
||||
unbox context.eval("(#{source})")
|
||||
unbox @v8_context.eval("(#{source})")
|
||||
end
|
||||
rescue ::V8::JSError => e
|
||||
if e.value["name"] == "SyntaxError"
|
||||
|
@ -23,13 +23,6 @@ module ExecJS
|
|||
end
|
||||
end
|
||||
|
||||
def available?
|
||||
require "v8"
|
||||
true
|
||||
rescue LoadError
|
||||
false
|
||||
end
|
||||
|
||||
def unbox(value)
|
||||
case value
|
||||
when ::V8::Function
|
||||
|
@ -46,4 +39,32 @@ module ExecJS
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
def name
|
||||
"therubyracer (V8)"
|
||||
end
|
||||
|
||||
def exec(source)
|
||||
context = Context.new
|
||||
context.exec(source)
|
||||
end
|
||||
|
||||
def eval(source)
|
||||
context = Context.new
|
||||
context.eval(source)
|
||||
end
|
||||
|
||||
def compile(source)
|
||||
context = Context.new
|
||||
context.exec(source)
|
||||
context
|
||||
end
|
||||
|
||||
def available?
|
||||
require "v8"
|
||||
true
|
||||
rescue LoadError
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
module ExecJS
|
||||
class RubyRhinoRuntime
|
||||
def name
|
||||
"therubyrhino (Rhino)"
|
||||
class Context
|
||||
def initialize
|
||||
@rhino_context = ::Rhino::Context.new
|
||||
end
|
||||
|
||||
def exec(source)
|
||||
|
@ -12,8 +13,7 @@ module ExecJS
|
|||
|
||||
def eval(source)
|
||||
if /\S/ =~ source
|
||||
context = ::Rhino::Context.new
|
||||
unbox context.eval("(#{source})")
|
||||
unbox @rhino_context.eval("(#{source})")
|
||||
end
|
||||
rescue ::Rhino::JavascriptError => e
|
||||
if e.message == "syntax error"
|
||||
|
@ -23,13 +23,6 @@ module ExecJS
|
|||
end
|
||||
end
|
||||
|
||||
def available?
|
||||
require "rhino"
|
||||
true
|
||||
rescue LoadError
|
||||
false
|
||||
end
|
||||
|
||||
def unbox(value)
|
||||
case value
|
||||
when ::Rhino::NativeFunction
|
||||
|
@ -44,4 +37,32 @@ module ExecJS
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
def name
|
||||
"therubyrhino (Rhino)"
|
||||
end
|
||||
|
||||
def exec(source)
|
||||
context = Context.new
|
||||
context.exec(source)
|
||||
end
|
||||
|
||||
def eval(source)
|
||||
context = Context.new
|
||||
context.eval(source)
|
||||
end
|
||||
|
||||
def compile(source)
|
||||
context = Context.new
|
||||
context.exec(source)
|
||||
context
|
||||
end
|
||||
|
||||
def available?
|
||||
require "rhino"
|
||||
true
|
||||
rescue LoadError
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -17,4 +17,10 @@ class TestExecJS < Test::Unit::TestCase
|
|||
runtime = ExecJS::ExternalRuntime.new(:command => "ruby")
|
||||
assert runtime.available?
|
||||
end
|
||||
|
||||
def test_compile
|
||||
context = ExecJS.compile("foo = function() { return \"bar\"; }")
|
||||
assert_equal "bar", context.exec("return foo()")
|
||||
assert_equal "bar", context.eval("foo()")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -29,6 +29,12 @@ module TestRuntime
|
|||
assert_equal "café", @runtime.eval("'café'")
|
||||
end
|
||||
|
||||
def test_compile
|
||||
context = @runtime.compile("foo = function() { return \"bar\"; }")
|
||||
assert_equal "bar", context.exec("return foo()")
|
||||
assert_equal "bar", context.eval("foo()")
|
||||
end
|
||||
|
||||
def test_this_is_global_scope
|
||||
assert_equal true, @runtime.eval("this === (function() {return this})()")
|
||||
assert_equal true, @runtime.exec("return this === (function() {return this})()")
|
||||
|
|
Loading…
Reference in a new issue