Skip to content
Browse files

Add support for embedded SpiderMonkey via Johnson

  • Loading branch information...
1 parent 2e3ec8e commit b1eb16bd580bc724197aaa68b2897b82b241eed0 @sstephenson committed Jun 18, 2011
Showing with 124 additions and 1 deletion.
  1. +3 −1 README.md
  2. +5 −0 execjs.gemspec
  3. +112 −0 lib/execjs/johnson_runtime.rb
  4. +4 −0 lib/execjs/runtimes.rb
View
4 README.md
@@ -8,9 +8,11 @@ returns the result to you as a Ruby object.
ExecJS supports these runtimes:
* [therubyracer](https://github.com/cowboyd/therubyracer) - Google V8
- embedded within MRI Ruby
+ embedded within Ruby
* [therubyrhino](https://github.com/cowboyd/therubyrhino) - Mozilla
Rhino embedded within JRuby
+* [Johnson](https://github.com/jbarnette/johnson) - Mozilla
+ SpiderMonkey embedded within Ruby
* [Mustang](https://github.com/nu7hatch/mustang) - Mustang V8
embedded within Ruby
* [Node.js](http://nodejs.org/)
View
5 execjs.gemspec
@@ -13,6 +13,7 @@ Gem::Specification.new do |s|
s.files = [
"lib/execjs.rb",
"lib/execjs/external_runtime.rb",
+ "lib/execjs/johnson_runtime.rb",
"lib/execjs/module.rb",
"lib/execjs/version.rb",
"lib/execjs/mustang_runtime.rb",
@@ -29,7 +30,11 @@ Gem::Specification.new do |s|
]
s.add_dependency "multi_json", "~>1.0"
+ s.add_development_dependency "johnson"
+ s.add_development_dependency "mustang"
s.add_development_dependency "rake"
+ s.add_development_dependency "therubyracer"
+ s.add_development_dependency "therubyrhino"
s.authors = ["Sam Stephenson", "Josh Peek"]
s.email = ["sstephenson@gmail.com", "josh@joshpeek.com"]
View
112 lib/execjs/johnson_runtime.rb
@@ -0,0 +1,112 @@
+module ExecJS
+ class JohnsonRuntime
+ class Context
+ def initialize(source = "")
+ @runtime = Johnson::Runtime.new
+ @runtime.evaluate(source)
+ end
+
+ def exec(source, options = {})
+ souce = source.encode('UTF-8') if source.respond_to?(:encode)
+
+ if /\S/ =~ source
+ eval "(function(){#{source}})()", options
+ end
+ end
+
+ def eval(source, options = {})
+ souce = source.encode('UTF-8') if source.respond_to?(:encode)
+
+ if /\S/ =~ source
+ unbox @runtime.evaluate("(#{source})")
+ end
+ rescue Johnson::Error => e
+ if syntax_error?(e)
+ raise RuntimeError, e.message
+ else
+ raise ProgramError, e.message
+ end
+ end
+
+ def call(properties, *args)
+ unbox @runtime.evaluate(properties).call(*args)
+ rescue Johnson::Error => e
+ if syntax_error?(e)
+ raise RuntimeError, e.message
+ else
+ raise ProgramError, e.message
+ end
+ end
+
+ def unbox(value)
+ case
+ when function?(value)
+ nil
+ when string?(value)
+ value.respond_to?(:force_encoding) ?
+ value.force_encoding('UTF-8') :
+ value
+ when array?(value)
+ value.map { |v| unbox(v) }
+ when object?(value)
+ value.inject({}) do |vs, (k, v)|
+ vs[k] = unbox(v) unless function?(v)
+ vs
+ end
+ else
+ value
+ end
+ end
+
+ private
+ def syntax_error?(error)
+ error.message =~ /^syntax error at /
+ end
+
+ def function?(value)
+ value.respond_to?(:function?) && value.function?
+ end
+
+ def string?(value)
+ value.is_a?(String)
+ end
+
+ def array?(value)
+ array_test.call(value)
+ end
+
+ def object?(value)
+ value.respond_to?(:inject)
+ end
+
+ def array_test
+ @array_test ||= @runtime.evaluate("(function(a) {return a instanceof [].constructor})")
+ end
+ end
+
+ def name
+ "Johnson (SpiderMonkey)"
+ 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.new(source)
+ end
+
+ def available?
+ require "johnson"
+ true
+ rescue LoadError
+ false
+ end
+ end
+end
View
4 lib/execjs/runtimes.rb
@@ -1,5 +1,6 @@
require "execjs/module"
require "execjs/external_runtime"
+require "execjs/johnson_runtime"
require "execjs/mustang_runtime"
require "execjs/ruby_racer_runtime"
require "execjs/ruby_rhino_runtime"
@@ -10,6 +11,8 @@ module Runtimes
RubyRhino = RubyRhinoRuntime.new
+ Johnson = JohnsonRuntime.new
+
Mustang = MustangRuntime.new
Node = ExternalRuntime.new(
@@ -70,6 +73,7 @@ def self.runtimes
@runtimes ||= [
RubyRacer,
RubyRhino,
+ Johnson,
Mustang,
Node,
JavaScriptCore,

0 comments on commit b1eb16b

Please sign in to comment.
Something went wrong with that request. Please try again.