From f587a974750104cb558f240a47f8e8d89d7f587f Mon Sep 17 00:00:00 2001 From: Sam Date: Wed, 11 May 2016 18:45:27 +1000 Subject: [PATCH] add MiniRacer runtime support --- Gemfile | 1 + lib/execjs/mini_racer_runtime.rb | 102 +++++++++++++++++++++++++++++++ lib/execjs/runtimes.rb | 4 ++ 3 files changed, 107 insertions(+) create mode 100644 lib/execjs/mini_racer_runtime.rb diff --git a/Gemfile b/Gemfile index 2d5fb79..200b5ae 100644 --- a/Gemfile +++ b/Gemfile @@ -7,4 +7,5 @@ group :test do gem 'therubyracer', platform: :mri gem 'therubyrhino', ">=1.73.3", platform: :jruby gem 'minitest', require: false + gem 'mini_racer', platform: :mri end diff --git a/lib/execjs/mini_racer_runtime.rb b/lib/execjs/mini_racer_runtime.rb new file mode 100644 index 0000000..b8a3bca --- /dev/null +++ b/lib/execjs/mini_racer_runtime.rb @@ -0,0 +1,102 @@ +require "execjs/runtime" + +module ExecJS + class MiniRacerRuntime < Runtime + class Context < Runtime::Context + def initialize(runtime, source = "", options={}) + source = encode(source) + @context = ::MiniRacer::Context.new + translate do + @context.eval(source) + end + end + + def exec(source, options = {}) + source = encode(source) + + if /\S/ =~ source + eval "(function(){#{source}})()" + end + end + + def eval(source, options = {}) + source = encode(source) + + if /\S/ =~ source + translate do + @context.eval("(#{source})") + end + end + end + + def call(identifier, *args) + # TODO optimise generate + eval "#{identifier}.apply(this, #{::JSON.generate(args)})" + end + + private + + def strip_functions!(value) + if Array === value + value.map! do |v| + if MiniRacer::JavaScriptFunction === value + nil + else + strip_functions!(v) + end + end + elsif Hash === value + value.each do |k,v| + if MiniRacer::JavaScriptFunction === v + value.delete k + else + value[k] = strip_functions!(v) + end + end + value + elsif MiniRacer::JavaScriptFunction === value + nil + else + value + end + end + + def translate + begin + strip_functions! yield + rescue MiniRacer::RuntimeError => e + ex = ProgramError.new e.message + if backtrace = e.backtrace + backtrace = backtrace.map { |line| + if line =~ /JavaScript at/ + line.sub("JavaScript at ", "") + .sub("", "(execjs)") + .strip + else + line + end + } + ex.set_backtrace backtrace + end + raise ex + rescue MiniRacer::ParseError => e + ex = RuntimeError.new e.message + ex.set_backtrace(["(execjs):1"] + e.backtrace) + raise ex + end + end + + end + + def name + "mini_racer (V8)" + end + + def available? + require "mini_racer" + true + rescue LoadError + false + end + end +end diff --git a/lib/execjs/runtimes.rb b/lib/execjs/runtimes.rb index d84e02e..52dc3c9 100644 --- a/lib/execjs/runtimes.rb +++ b/lib/execjs/runtimes.rb @@ -4,6 +4,7 @@ require "execjs/duktape_runtime" require "execjs/external_runtime" require "execjs/ruby_racer_runtime" require "execjs/ruby_rhino_runtime" +require "execjs/mini_racer_runtime" module ExecJS module Runtimes @@ -15,6 +16,8 @@ module ExecJS RubyRhino = RubyRhinoRuntime.new + MiniRacer = MiniRacerRuntime.new + Node = ExternalRuntime.new( name: "Node.js (V8)", command: ["nodejs", "node"], @@ -79,6 +82,7 @@ module ExecJS RubyRacer, RubyRhino, Duktape, + MiniRacer, Node, JavaScriptCore, SpiderMonkey,