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'
|
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)
|
||||||
|
|
|
@ -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())
|
||||||
|
|
62
lib/v8/to.rb
62
lib/v8/to.rb
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue