Skip to content

Commit

Permalink
Add support for embedded SpiderMonkey via Johnson
Browse files Browse the repository at this point in the history
  • Loading branch information
sstephenson committed Jun 18, 2011
1 parent 2e3ec8e commit b1eb16b
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 1 deletion.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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/)
Expand Down
5 changes: 5 additions & 0 deletions execjs.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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"]
Expand Down
112 changes: 112 additions & 0 deletions lib/execjs/johnson_runtime.rb
Original file line number Diff line number Diff line change
@@ -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
4 changes: 4 additions & 0 deletions lib/execjs/runtimes.rb
Original file line number Diff line number Diff line change
@@ -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"
Expand All @@ -10,6 +11,8 @@ module Runtimes

RubyRhino = RubyRhinoRuntime.new

Johnson = JohnsonRuntime.new

Mustang = MustangRuntime.new

Node = ExternalRuntime.new(
Expand Down Expand Up @@ -70,6 +73,7 @@ def self.runtimes
@runtimes ||= [
RubyRacer,
RubyRhino,
Johnson,
Mustang,
Node,
JavaScriptCore,
Expand Down

0 comments on commit b1eb16b

Please sign in to comment.