Permalink
Browse files

Context

  • Loading branch information...
1 parent 763513d commit 82773bfbde4fbdcd3e03c4f4d3e2635eaec20a3a @josh josh committed Feb 11, 2011
Showing with 188 additions and 103 deletions.
  1. +4 −0 lib/execjs.rb
  2. +74 −47 lib/execjs/external_runtime.rb
  3. +50 −29 lib/execjs/ruby_racer_runtime.rb
  4. +48 −27 lib/execjs/ruby_rhino_runtime.rb
  5. +6 −0 test/test_execjs.rb
  6. +6 −0 test/test_runtimes.rb
View
4 lib/execjs.rb
@@ -18,6 +18,10 @@ def self.eval(source)
runtime.eval(source)
end
+ def self.compile(source)
+ runtime.compile(source)
+ end
+
def self.runtimes
Runtimes.runtimes
end
View
121 lib/execjs/external_runtime.rb
@@ -3,6 +3,56 @@
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 @@ def initialize(options)
@binary = locate_binary
end
+ def exec(source)
+ context = Context.new(self)
+ context.exec(source)
+ end
+
def eval(source)
- if /\S/ =~ source
- exec("return eval(#{"(#{source})".to_json})")
- end
+ context = Context.new(self)
+ context.eval(source)
end
- def exec(source)
- compile_to_tempfile(source) do |file|
- extract_result(exec_runtime(file.path))
- 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 @@ def which(command)
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 @@ def sh(command)
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
View
79 lib/execjs/ruby_racer_runtime.rb
@@ -1,26 +1,63 @@
module ExecJS
class RubyRacerRuntime
+ class Context
+ def initialize
+ @v8_context = ::V8::Context.new
+ end
+
+ def exec(source)
+ if /\S/ =~ source
+ eval "(function(){#{source}})()"
+ end
+ end
+
+ def eval(source)
+ if /\S/ =~ source
+ unbox @v8_context.eval("(#{source})")
+ end
+ rescue ::V8::JSError => e
+ if e.value["name"] == "SyntaxError"
+ raise RuntimeError, e
+ else
+ raise ProgramError, e
+ end
+ end
+
+ def unbox(value)
+ case value
+ when ::V8::Function
+ nil
+ when ::V8::Array
+ value.map { |v| unbox(v) }
+ when ::V8::Object
+ value.inject({}) do |vs, (k, v)|
+ vs[k] = unbox(v) unless v.is_a?(::V8::Function)
+ vs
+ end
+ else
+ value
+ end
+ end
+ end
+
def name
"therubyracer (V8)"
end
def exec(source)
- if /\S/ =~ source
- eval "(function(){#{source}})()"
- end
+ context = Context.new
+ context.exec(source)
end
def eval(source)
- if /\S/ =~ source
- context = ::V8::Context.new
- unbox context.eval("(#{source})")
- end
- rescue ::V8::JSError => e
- if e.value["name"] == "SyntaxError"
- raise RuntimeError, e
- else
- raise ProgramError, e
- end
+ context = Context.new
+ context.eval(source)
+ end
+
+ def compile(source)
+ context = Context.new
+ context.exec(source)
+ context
end
def available?
@@ -29,21 +66,5 @@ def available?
rescue LoadError
false
end
-
- def unbox(value)
- case value
- when ::V8::Function
- nil
- when ::V8::Array
- value.map { |v| unbox(v) }
- when ::V8::Object
- value.inject({}) do |vs, (k, v)|
- vs[k] = unbox(v) unless v.is_a?(::V8::Function)
- vs
- end
- else
- value
- end
- end
end
end
View
75 lib/execjs/ruby_rhino_runtime.rb
@@ -1,26 +1,61 @@
module ExecJS
class RubyRhinoRuntime
+ class Context
+ def initialize
+ @rhino_context = ::Rhino::Context.new
+ end
+
+ def exec(source)
+ if /\S/ =~ source
+ eval "(function(){#{source}})()"
+ end
+ end
+
+ def eval(source)
+ if /\S/ =~ source
+ unbox @rhino_context.eval("(#{source})")
+ end
+ rescue ::Rhino::JavascriptError => e
+ if e.message == "syntax error"
+ raise RuntimeError, e
+ else
+ raise ProgramError, e
+ end
+ end
+
+ def unbox(value)
+ case value
+ when ::Rhino::NativeFunction
+ nil
+ when ::Rhino::NativeObject
+ value.inject({}) do |vs, (k, v)|
+ vs[k] = unbox(v) unless v.is_a?(::Rhino::NativeFunction)
+ vs
+ end
+ else
+ value
+ end
+ end
+ end
+
def name
"therubyrhino (Rhino)"
end
def exec(source)
- if /\S/ =~ source
- eval "(function(){#{source}})()"
- end
+ context = Context.new
+ context.exec(source)
end
def eval(source)
- if /\S/ =~ source
- context = ::Rhino::Context.new
- unbox context.eval("(#{source})")
- end
- rescue ::Rhino::JavascriptError => e
- if e.message == "syntax error"
- raise RuntimeError, e
- else
- raise ProgramError, e
- end
+ context = Context.new
+ context.eval(source)
+ end
+
+ def compile(source)
+ context = Context.new
+ context.exec(source)
+ context
end
def available?
@@ -29,19 +64,5 @@ def available?
rescue LoadError
false
end
-
- def unbox(value)
- case value
- when ::Rhino::NativeFunction
- nil
- when ::Rhino::NativeObject
- value.inject({}) do |vs, (k, v)|
- vs[k] = unbox(v) unless v.is_a?(::Rhino::NativeFunction)
- vs
- end
- else
- value
- end
- end
end
end
View
6 test/test_execjs.rb
@@ -17,4 +17,10 @@ def test_runtime_available
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
View
6 test/test_runtimes.rb
@@ -29,6 +29,12 @@ def test_eval
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})()")

0 comments on commit 82773bf

Please sign in to comment.