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:
parent
9a47fee91f
commit
ca4eff3658
3 changed files with 91 additions and 60 deletions
|
@ -1,6 +1,89 @@
|
|||
require 'set'
|
||||
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
|
||||
def self.call(property, info)
|
||||
name = To.rb(property)
|
||||
|
@ -41,7 +124,7 @@ module V8
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class NamedPropertyEnumerator
|
||||
def self.call(info)
|
||||
obj = To.rb(info.This())
|
||||
|
|
|
@ -4,7 +4,7 @@ module V8
|
|||
class Context
|
||||
attr_reader :native, :scope
|
||||
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.Global().SetHiddenValue(C::String::New("TheRubyRacer::RubyObject"), C::External::New(opts[:with])) if opts[:with]
|
||||
@scope = To.rb(@native.Global())
|
||||
|
|
62
lib/v8/to.rb
62
lib/v8/to.rb
|
@ -19,8 +19,10 @@ module V8
|
|||
case value
|
||||
when V8::Object
|
||||
value.instance_eval {@native}
|
||||
when String, Symbol
|
||||
when String
|
||||
C::String::New(value.to_s)
|
||||
when Symbol
|
||||
C::String::NewSymbol(value.to_s)
|
||||
when Proc,Method
|
||||
template = C::FunctionTemplate::New() do |arguments|
|
||||
rbargs = []
|
||||
|
@ -45,7 +47,7 @@ module V8
|
|||
when ::Time
|
||||
C::Date::New(value)
|
||||
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))
|
||||
end
|
||||
when nil,Numeric,TrueClass,FalseClass, C::Value
|
||||
|
@ -53,7 +55,7 @@ module V8
|
|||
else
|
||||
args = C::Array::New(1)
|
||||
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
|
||||
end
|
||||
end
|
||||
|
@ -67,60 +69,6 @@ module V8
|
|||
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)
|
||||
str.to_s.gsub(/_(\w)/) {$1.upcase}
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue