mirror of
https://github.com/rubyjs/therubyracer
synced 2023-03-27 23:21:42 -04:00
extract Ruby object access.
This commit is contained in:
parent
2404e0c0f8
commit
1c9694a732
6 changed files with 118 additions and 9 deletions
|
@ -14,6 +14,9 @@ require 'v8/conversion/method'
|
|||
require 'v8/conversion/symbol'
|
||||
require 'v8/conversion/string'
|
||||
require 'v8/conversion'
|
||||
require 'v8/access/names'
|
||||
require 'v8/access/indices'
|
||||
require 'v8/access'
|
||||
require 'v8/context'
|
||||
require 'v8/object'
|
||||
require 'v8/array'
|
4
lib/v8/access.rb
Normal file
4
lib/v8/access.rb
Normal file
|
@ -0,0 +1,4 @@
|
|||
class V8::Access
|
||||
include Names
|
||||
include Indices
|
||||
end
|
40
lib/v8/access/indices.rb
Normal file
40
lib/v8/access/indices.rb
Normal file
|
@ -0,0 +1,40 @@
|
|||
class V8::Access
|
||||
module Indices
|
||||
|
||||
def indices(obj)
|
||||
obj.respond_to?(:length) ? (0..obj.length).to_a : yield
|
||||
end
|
||||
|
||||
def iget(obj, index, &dontintercept)
|
||||
if obj.respond_to?(:[])
|
||||
obj.send(:[], index, &dontintercept)
|
||||
else
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
||||
def iset(obj, index, value, &dontintercept)
|
||||
if obj.respond_to?(:[]=)
|
||||
obj.send(:[]=, index, value, &dontintercept)
|
||||
else
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
||||
def iquery(obj, index, attributes, &dontintercept)
|
||||
if obj.respond_to?(:[])
|
||||
attributes.dont_delete
|
||||
unless obj.respond_to?(:[]=)
|
||||
attributes.read_only
|
||||
end
|
||||
else
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
||||
def idelete(obj, index, &dontintercept)
|
||||
yield
|
||||
end
|
||||
|
||||
end
|
||||
end
|
65
lib/v8/access/names.rb
Normal file
65
lib/v8/access/names.rb
Normal file
|
@ -0,0 +1,65 @@
|
|||
require 'set'
|
||||
class V8::Access
|
||||
module Names
|
||||
def names(obj)
|
||||
accessible_names(obj)
|
||||
end
|
||||
|
||||
def get(obj, name, &dontintercept)
|
||||
methods = accessible_names(obj)
|
||||
if methods.include?(name)
|
||||
method = obj.method(name)
|
||||
method.arity == 0 ? method.call : method
|
||||
elsif obj.respond_to?(:[]) && !special?(name)
|
||||
obj.send(:[], name, &dontintercept)
|
||||
else
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
||||
def set(obj, name, value, &dontintercept)
|
||||
setter = name + "="
|
||||
methods = accessible_names(obj, true)
|
||||
if methods.include?(setter)
|
||||
obj.send(setter, value)
|
||||
elsif obj.respond_to?(:[]=) && !special?(name)
|
||||
obj.send(:[]=, name, value, &dontintercept)
|
||||
else
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
||||
def query(obj, name, attributes, &dontintercept)
|
||||
if obj.respond_to?(name)
|
||||
attributes.dont_delete
|
||||
unless obj.respond_to?(name + "=")
|
||||
attributes.read_only
|
||||
end
|
||||
else
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
||||
def delete(obj, name, &dontintercept)
|
||||
yield
|
||||
end
|
||||
|
||||
def accessible_names(obj, special_methods = false)
|
||||
obj.public_methods(false).map {|m| m.to_s}.to_set.tap do |methods|
|
||||
ancestors = obj.class.ancestors.dup
|
||||
while ancestor = ancestors.shift
|
||||
break if ancestor == ::Object
|
||||
methods.merge(ancestor.public_instance_methods(false).map {|m| m.to_s})
|
||||
end
|
||||
methods.reject!(&special?) unless special_methods
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def special?(name = nil)
|
||||
@special ||= lambda {|m| m == "[]" || m == "[]=" || m =~ /=$/}
|
||||
name.nil? ? @special : @special[name]
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,10 +1,11 @@
|
|||
module V8
|
||||
class Context
|
||||
attr_reader :native, :conversion
|
||||
attr_reader :native, :conversion, :access
|
||||
|
||||
def initialize
|
||||
@native = V8::C::Context::New()
|
||||
@conversion = Conversion.new
|
||||
@access = Access.new
|
||||
end
|
||||
|
||||
def to_ruby(v8_object)
|
||||
|
|
|
@ -15,17 +15,13 @@ class V8::Conversion
|
|||
class Get
|
||||
def self.call(property, info)
|
||||
context = V8::Context.current
|
||||
access = context.access
|
||||
object = info.Data().Value()
|
||||
name = property.Utf8Value()
|
||||
if object.respond_to?(name)
|
||||
if object.method(name).arity == 0
|
||||
context.to_v8 object.send(name)
|
||||
else
|
||||
context.to_v8 object.method(name)
|
||||
end
|
||||
else
|
||||
V8::C::Value::Empty
|
||||
dontintercept = proc do
|
||||
return V8::C::Empty
|
||||
end
|
||||
context.to_v8 access.get(object, name, &dontintercept)
|
||||
rescue Exception => e
|
||||
warn "uncaught exception: #{e.class}: #{e.message} while accessing object property: #{e.backtrace.join('\n')}"
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue