mirror of
https://github.com/rubyjs/therubyracer
synced 2023-03-27 23:21:42 -04:00
move bare function handling into its own class
This commit is contained in:
parent
41f9e10b25
commit
6fa4389555
5 changed files with 74 additions and 64 deletions
|
@ -6,9 +6,9 @@ module V8
|
|||
require 'v8/v8' #native glue
|
||||
require 'v8/portal'
|
||||
require 'v8/portal/caller'
|
||||
require 'v8/portal/functions'
|
||||
require 'v8/portal/proxies'
|
||||
require 'v8/portal/templates'
|
||||
require 'v8/portal/function'
|
||||
require 'v8/portal/constructor'
|
||||
require 'v8/portal/interceptors'
|
||||
require 'v8/context'
|
||||
|
|
|
@ -6,7 +6,6 @@ module V8
|
|||
def initialize(context, access)
|
||||
@context, @access = context, access
|
||||
@proxies = Proxies.new
|
||||
@functions = Functions.new(self)
|
||||
@templates = Templates.new(self)
|
||||
@interceptors = Interceptors.new(self)
|
||||
@caller = Caller.new(self)
|
||||
|
@ -44,7 +43,7 @@ module V8
|
|||
C::String::NewSymbol(value.to_s)
|
||||
when Proc,Method,UnboundMethod
|
||||
@proxies.rb2js(value) do
|
||||
@functions.to_function(value).function
|
||||
@templates.to_function(value).function
|
||||
end
|
||||
when ::Array
|
||||
C::Array::New(value.length).tap do |a|
|
||||
|
|
46
lib/v8/portal/function.rb
Normal file
46
lib/v8/portal/function.rb
Normal file
|
@ -0,0 +1,46 @@
|
|||
module V8
|
||||
class Portal
|
||||
class Function
|
||||
|
||||
attr_reader :template, :function
|
||||
|
||||
def initialize(portal, code)
|
||||
@portal = portal
|
||||
@template = V8::C::FunctionTemplate::New(code.respond_to?(:call) ? Call.new(portal) : BindAndCall.new(portal), code)
|
||||
end
|
||||
|
||||
def function
|
||||
@template.GetFunction()
|
||||
end
|
||||
|
||||
class Call
|
||||
def initialize(portal)
|
||||
@portal = portal
|
||||
end
|
||||
|
||||
def call(arguments)
|
||||
proc = arguments.Data()
|
||||
rbargs = []
|
||||
for i in 0..arguments.Length() - 1
|
||||
rbargs << @portal.rb(arguments[i])
|
||||
end
|
||||
@portal.caller.invoke(proc, *rbargs)
|
||||
end
|
||||
end
|
||||
|
||||
class BindAndCall < Call
|
||||
def call(arguments)
|
||||
method = arguments.Data()
|
||||
rbargs = []
|
||||
for i in 0..arguments.Length() - 1
|
||||
rbargs << @portal.rb(arguments[i])
|
||||
end
|
||||
this = @portal.rb(arguments.This())
|
||||
@portal.caller.protect do
|
||||
method.bind(this).call(*rbargs)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,60 +0,0 @@
|
|||
module V8
|
||||
class Portal
|
||||
class Functions
|
||||
def initialize(portal)
|
||||
@portal = portal
|
||||
@procs = {}
|
||||
@methods = {}
|
||||
end
|
||||
|
||||
def to_function(code)
|
||||
case code
|
||||
when Method, UnboundMethod
|
||||
#TODO: clear this reference when the C::FunctionTemplate becomes weak.
|
||||
@methods[code.to_s] ||= Template.new(@portal, code.kind_of?(Method) ? :invoke_callable : :invoke_unbound_method, code)
|
||||
else
|
||||
if code.respond_to?(:call)
|
||||
#TODO: clear with reference when the C::FunctionTemplate becomes weak.
|
||||
@procs[code] ||= Template.new(@portal, :invoke_callable, code)
|
||||
else
|
||||
fail "invalid code type: #{code.class}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Template
|
||||
attr_reader :template, :function
|
||||
|
||||
def initialize(portal, impl, code)
|
||||
@portal = portal
|
||||
@template = V8::C::FunctionTemplate::New(method(impl), code)
|
||||
end
|
||||
|
||||
def function
|
||||
@template.GetFunction()
|
||||
end
|
||||
|
||||
def invoke_callable(arguments)
|
||||
proc = arguments.Data()
|
||||
rbargs = []
|
||||
for i in 0..arguments.Length() - 1
|
||||
rbargs << @portal.rb(arguments[i])
|
||||
end
|
||||
@portal.caller.invoke(proc, *rbargs)
|
||||
end
|
||||
|
||||
def invoke_unbound_method(arguments)
|
||||
method = arguments.Data()
|
||||
rbargs = []
|
||||
for i in 0..arguments.Length() - 1
|
||||
rbargs << @portal.rb(arguments[i])
|
||||
end
|
||||
this = @portal.rb(arguments.This())
|
||||
@portal.caller.protect do
|
||||
method.bind(this).call(*rbargs)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -8,6 +8,8 @@ module V8
|
|||
def initialize(portal)
|
||||
@portal = portal
|
||||
@constructors = {}
|
||||
@methods = {}
|
||||
@procs = {}
|
||||
end
|
||||
|
||||
def to_constructor(ruby_class)
|
||||
|
@ -15,12 +17,35 @@ module V8
|
|||
if constructor = @constructors[class_id]
|
||||
return constructor
|
||||
else
|
||||
constructor = @constructors[class_id] = Portal::Constructor.new(self, class_id)
|
||||
constructor = @constructors[class_id] = Constructor.new(self, class_id)
|
||||
ObjectSpace.define_finalizer(ruby_class, bind(@constructors, :delete, class_id))
|
||||
return constructor
|
||||
end
|
||||
end
|
||||
|
||||
def to_function(code)
|
||||
case code
|
||||
when Method, UnboundMethod
|
||||
if fn = @methods[code.to_s]
|
||||
return fn
|
||||
else
|
||||
function = @methods[code.to_s] = Function.new(@portal, code)
|
||||
#TODO: test this weak behavior
|
||||
function.template.MakeWeak(0, bind(@methods, :delete, code.to_s))
|
||||
return function
|
||||
end
|
||||
else
|
||||
if fn = @procs[code]
|
||||
return fn
|
||||
else
|
||||
function = Function.new(@portal, code)
|
||||
#TODO: test this weak behavior
|
||||
function.template.MakeWeak(0, bind(@procs, :delete, code))
|
||||
return function
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def proxies
|
||||
@portal.proxies
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue