lib/proxy_pac_rb/runtimes/rubyracer.rb
# frozen_string_literal: true
module ProxyPacRb
# Ruby Racer Runtime
class RubyRacerRuntime < Runtime
# Context
class Context < Runtime::Context
def initialize(_runtime, source = '', _environment = nil)
source = encode(source)
lock do
self.context = ::V8::Context.new
context.eval(source)
end
end
def exec(source, options = {})
source = encode(source)
# rubocop:disable Security/Eval
eval "(function(){#{source}})()", options if /\S/ =~ source
# rubocop:enable Security/Eval
end
def eval(source, _options = {})
source = encode(source)
return nil unless /\S/ =~ source
lock do
begin
unbox context.eval("(#{source})")
rescue ::V8::JSError => e
if e.value['name'] == 'SyntaxError'
raise e.value.to_s
else
raise ProgramError, e.value.to_s
end
end
end
end
def call(properties, *args)
lock do
begin
unbox context.eval(properties).call(*args)
rescue ::V8::JSError => e
if e.value['name'] == 'SyntaxError'
raise e.value.to_s
else
raise ProgramError, e.value.to_s
end
end
end
end
def unbox(value)
case value
when ::V8::Function
nil
when ::V8::Array
value.map { |v| unbox(v) }
when ::V8::Object
# rubocop:disable Style/EachWithObject
value.reduce({}) do |vs, (k, v)|
vs[k] = unbox(v) unless v.is_a?(::V8::Function)
vs
end
# rubocop:enable Style/EachWithObject
when String
if value.respond_to?(:force_encoding)
value.force_encoding('UTF-8')
else
value
end
else
value
end
end
private
def lock
result = nil
exception = nil
V8::C::Locker() do
begin
result = yield
rescue => e
exception = e
end
end
if exception
raise exception
else
result
end
end
end
def name
'therubyracer (V8)'
end
def available?
require 'v8'
true
rescue LoadError
false
end
end
end