1
0
Fork 0
mirror of https://github.com/rubyjs/therubyracer synced 2023-03-27 23:21:42 -04:00

separate Constructors from normal object access

This commit is contained in:
Charles Lowell 2010-06-09 00:32:31 +03:00
parent 9a47fee91f
commit ca4eff3658
3 changed files with 91 additions and 60 deletions

View file

@ -1,6 +1,89 @@
require 'set' require 'set'
module V8 module V8
class Access
def self.[](cls)
@access ||= Access.new
@access[cls]
end
def initialize
@classes = {}
end
def [](cls)
@classes ||= {}
if ref = @classes[cls.object_id]
if ref.weakref_alive?
ref.__getobj__
else
@classes.delete(cls.object_id)
self[cls]
end
else
template(cls).tap do |t|
t.InstanceTemplate().SetNamedPropertyHandler(
NamedPropertyGetter,
NamedPropertySetter,
nil,
nil,
NamedPropertyEnumerator
)
if cls.name && cls.name =~ /(::)?(\w+?)$/
t.SetClassName(C::String::NewSymbol($2))
else
t.SetClassName("Ruby")
end
@classes[cls.object_id] = WeakRef.new(t)
end
end
end
def template(cls)
C::FunctionTemplate::New() do |arguments|
unless arguments.Length() == 1 && arguments[0].kind_of?(C::External)
C::ThrowException(C::Exception::Error(C::String::New("cannot call native constructor from javascript")))
else
arguments.This().tap do |this|
this.SetHiddenValue(C::String::NewSymbol("TheRubyRacer::RubyObject"), arguments[0])
end
end
end
end
def self.rubyobject
@rubyobject ||= C::ObjectTemplate::New().tap do |t|
t.SetNamedPropertyHandler(
NamedPropertyGetter,
NamedPropertySetter,
nil,
nil,
NamedPropertyEnumerator
)
end
end
end
class Constructors < Access
def self.[](cls)
@constructors ||= Constructors.new
@constructors[cls]
end
def template(cls)
t = C::FunctionTemplate::New() do |arguments|
rbargs = []
for i in 0..arguments.Length() - 1
rbargs << To.rb(arguments[i])
end
instance = V8::Function.rubycall(cls.method(:new), *rbargs)
arguments.This().tap do |this|
this.SetHiddenValue(C::String::NewSymbol("TheRubyRacer::RubyObject"), C::External::New(instance))
end
end
t.Inherit(Access[cls])
return t
end
end
class NamedPropertyGetter class NamedPropertyGetter
def self.call(property, info) def self.call(property, info)
name = To.rb(property) name = To.rb(property)

View file

@ -4,7 +4,7 @@ module V8
class Context class Context
attr_reader :native, :scope attr_reader :native, :scope
def initialize(opts = {}) def initialize(opts = {})
@native = opts[:with] ? C::Context::New(To.template) : C::Context::New() @native = opts[:with] ? C::Context::New(Access.rubyobject) : C::Context::New()
@native.enter do @native.enter do
@native.Global().SetHiddenValue(C::String::New("TheRubyRacer::RubyObject"), C::External::New(opts[:with])) if opts[:with] @native.Global().SetHiddenValue(C::String::New("TheRubyRacer::RubyObject"), C::External::New(opts[:with])) if opts[:with]
@scope = To.rb(@native.Global()) @scope = To.rb(@native.Global())

View file

@ -19,8 +19,10 @@ module V8
case value case value
when V8::Object when V8::Object
value.instance_eval {@native} value.instance_eval {@native}
when String, Symbol when String
C::String::New(value.to_s) C::String::New(value.to_s)
when Symbol
C::String::NewSymbol(value.to_s)
when Proc,Method when Proc,Method
template = C::FunctionTemplate::New() do |arguments| template = C::FunctionTemplate::New() do |arguments|
rbargs = [] rbargs = []
@ -45,7 +47,7 @@ module V8
when ::Time when ::Time
C::Date::New(value) C::Date::New(value)
when ::Class when ::Class
To.class_template(value).GetFunction().tap do |f| Constructors[value].GetFunction().tap do |f|
f.SetHiddenValue(C::String::NewSymbol("TheRubyRacer::RubyObject"), C::External::New(value)) f.SetHiddenValue(C::String::NewSymbol("TheRubyRacer::RubyObject"), C::External::New(value))
end end
when nil,Numeric,TrueClass,FalseClass, C::Value when nil,Numeric,TrueClass,FalseClass, C::Value
@ -53,7 +55,7 @@ module V8
else else
args = C::Array::New(1) args = C::Array::New(1)
args.Set(0, C::External::New(value)) args.Set(0, C::External::New(value))
obj = To.class_template(value.class).GetFunction().NewInstance(args) obj = Access[value.class].GetFunction().NewInstance(args)
return obj return obj
end end
end end
@ -67,60 +69,6 @@ module V8
end end
end end
def template
@rubyobject ||= C::ObjectTemplate::New().tap do |t|
t.SetNamedPropertyHandler(
NamedPropertyGetter,
NamedPropertySetter,
nil,
nil,
NamedPropertyEnumerator
)
end
end
def class_template(cls)
@classes ||= {}
if ref = @classes[cls.object_id]
if ref.weakref_alive?
ref.__getobj__
else
@classes.delete(cls.object_id)
self.class_template(cls)
end
else
class_template = C::FunctionTemplate::New() do |arguments|
if arguments.Length() > 0 && arguments[0].kind_of?(C::External)
wrapper = arguments[0]
else
rbargs = []
for i in 0..arguments.Length() - 1
rbargs << To.rb(arguments[i])
end
instance = V8::Function.rubycall(cls.method(:new), *rbargs)
wrapper = C::External::New(instance)
end
arguments.This().tap do |this|
this.SetHiddenValue(C::String::NewSymbol("TheRubyRacer::RubyObject"), wrapper)
end
end
class_template.InstanceTemplate().SetNamedPropertyHandler(
NamedPropertyGetter,
NamedPropertySetter,
nil,
nil,
NamedPropertyEnumerator
)
if cls.name && cls.name =~ /(::)?(\w+?)$/
class_template.SetClassName(C::String::NewSymbol($2))
else
class_template.SetClassName("Ruby")
end
@classes[cls.object_id] = WeakRef.new(class_template)
class_template
end
end
def camel_case(str) def camel_case(str)
str.to_s.gsub(/_(\w)/) {$1.upcase} str.to_s.gsub(/_(\w)/) {$1.upcase}
end end