1
0
Fork 0
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:
Charles Lowell 2011-04-26 23:39:32 -05:00
parent 41f9e10b25
commit 6fa4389555
5 changed files with 74 additions and 64 deletions

View file

@ -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'

View file

@ -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
View 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

View file

@ -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

View file

@ -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