1
0
Fork 0
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:
Charles Lowell 2012-06-11 11:49:04 -05:00
parent 2404e0c0f8
commit 1c9694a732
6 changed files with 118 additions and 9 deletions

View file

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

@ -0,0 +1,4 @@
class V8::Access
include Names
include Indices
end

40
lib/v8/access/indices.rb Normal file
View 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
View 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

View file

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

View file

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