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/v8' #native glue
|
||||||
require 'v8/portal'
|
require 'v8/portal'
|
||||||
require 'v8/portal/caller'
|
require 'v8/portal/caller'
|
||||||
require 'v8/portal/functions'
|
|
||||||
require 'v8/portal/proxies'
|
require 'v8/portal/proxies'
|
||||||
require 'v8/portal/templates'
|
require 'v8/portal/templates'
|
||||||
|
require 'v8/portal/function'
|
||||||
require 'v8/portal/constructor'
|
require 'v8/portal/constructor'
|
||||||
require 'v8/portal/interceptors'
|
require 'v8/portal/interceptors'
|
||||||
require 'v8/context'
|
require 'v8/context'
|
||||||
|
|
|
@ -6,7 +6,6 @@ module V8
|
||||||
def initialize(context, access)
|
def initialize(context, access)
|
||||||
@context, @access = context, access
|
@context, @access = context, access
|
||||||
@proxies = Proxies.new
|
@proxies = Proxies.new
|
||||||
@functions = Functions.new(self)
|
|
||||||
@templates = Templates.new(self)
|
@templates = Templates.new(self)
|
||||||
@interceptors = Interceptors.new(self)
|
@interceptors = Interceptors.new(self)
|
||||||
@caller = Caller.new(self)
|
@caller = Caller.new(self)
|
||||||
|
@ -44,7 +43,7 @@ module V8
|
||||||
C::String::NewSymbol(value.to_s)
|
C::String::NewSymbol(value.to_s)
|
||||||
when Proc,Method,UnboundMethod
|
when Proc,Method,UnboundMethod
|
||||||
@proxies.rb2js(value) do
|
@proxies.rb2js(value) do
|
||||||
@functions.to_function(value).function
|
@templates.to_function(value).function
|
||||||
end
|
end
|
||||||
when ::Array
|
when ::Array
|
||||||
C::Array::New(value.length).tap do |a|
|
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)
|
def initialize(portal)
|
||||||
@portal = portal
|
@portal = portal
|
||||||
@constructors = {}
|
@constructors = {}
|
||||||
|
@methods = {}
|
||||||
|
@procs = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_constructor(ruby_class)
|
def to_constructor(ruby_class)
|
||||||
|
@ -15,12 +17,35 @@ module V8
|
||||||
if constructor = @constructors[class_id]
|
if constructor = @constructors[class_id]
|
||||||
return constructor
|
return constructor
|
||||||
else
|
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))
|
ObjectSpace.define_finalizer(ruby_class, bind(@constructors, :delete, class_id))
|
||||||
return constructor
|
return constructor
|
||||||
end
|
end
|
||||||
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
|
def proxies
|
||||||
@portal.proxies
|
@portal.proxies
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue