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

some oop into access impls

AccessBase as a base class for different implementations
change DefaultAccess and RubyAccess to use AccessBase (but keep backwards compatibility with the "module" way)
This commit is contained in:
kares 2012-04-20 20:24:43 +02:00
parent f292f13686
commit 721c8a4355
6 changed files with 115 additions and 73 deletions

View file

@ -143,7 +143,7 @@ that attempts to mirror only attributes as properties as close as possible:
If you happen to come up with your own access strategy, just set it directly : If you happen to come up with your own access strategy, just set it directly :
Rhino::Ruby::Scriptable.access = FooApp::BarAccess Rhino::Ruby::Scriptable.access = FooApp::BarAccess.instance
=== Safe by default === Safe by default

View file

@ -38,8 +38,10 @@ module Rhino
@@access = nil @@access = nil
def self.access=(access) def self.access=(access)
@@access = access.is_a?(Module) ? access : begin @@access = ( access.respond_to?(:get) && access.respond_to?(:put) ) ? access :
if access # Scriptable.access = :attribute begin
access =
if access && ! access.is_a?(Class) # Scriptable.access = :attribute
name = access.to_s.chomp('_access') name = access.to_s.chomp('_access')
name = name[0, 1].capitalize << name[1..-1] name = name[0, 1].capitalize << name[1..-1]
name = :"#{name}Access" name = :"#{name}Access"
@ -48,14 +50,15 @@ module Rhino
else else
const_get(name) # e.g. Rhino::Ruby::Scriptable::FooAccess const_get(name) # e.g. Rhino::Ruby::Scriptable::FooAccess
end end
else # nil, false else # nil, false, Class
access access
end end
access.is_a?(Class) ? access.new : access
end end
end end
def self.access def self.access
@@access ||= Ruby::DefaultAccess @@access ||= Ruby::DefaultAccess.new
end end
private private

View file

@ -4,5 +4,59 @@ module Rhino
autoload :DefaultAccess, "rhino/ruby/default_access" autoload :DefaultAccess, "rhino/ruby/default_access"
autoload :AttributeAccess, "rhino/ruby/attribute_access" autoload :AttributeAccess, "rhino/ruby/attribute_access"
class AccessBase
def has(object, name, scope)
# try [](name) method :
if object.respond_to?(:'[]') && object.method(:'[]').arity == 1
return true unless object[name].nil?
end
yield
end
def get(object, name, scope)
# try [](name) method :
if object.respond_to?(:'[]') && object.method(:'[]').arity == 1
unless (value = object[name]).nil?
return Rhino.to_javascript(value, scope)
end
end
yield
end
def put(object, name, value)
# try []=(name, value) method :
if object.respond_to?(:'[]=') && object.method(:'[]=').arity == 2
return object[name] = Rhino.to_ruby(value)
end
yield
end
end
module DeprecatedAccess
def has(object, name, scope, &block)
Rhino.warn "[DEPRECATION] `#{self.name}.has` is deprecated, please sub-class #{self.name} instead."
instance.has(object, name, scope, &block)
end
def get(object, name, scope, &block)
Rhino.warn "[DEPRECATION] `#{self.name}.get` is deprecated, please sub-class #{self.name} instead."
instance.get(object, name, scope, &block)
end
def put(object, name, value, &block)
Rhino.warn "[DEPRECATION] `#{self.name}.put` is deprecated, please sub-class #{self.name} instead."
instance.put(object, name, value, &block)
end
private
def instance
@instance ||= self.new
end
end
end end
end end

View file

@ -1,57 +1,41 @@
module Rhino module Rhino
module Ruby module Ruby
module AttributeAccess class AttributeAccess < AccessBase
def self.has(object, name, scope) def has(object, name, scope)
if object.respond_to?(name.to_s) || if object.respond_to?(name.to_s) ||
object.respond_to?(:"#{name}=") # might have a writer but no reader object.respond_to?(:"#{name}=") # might have a writer but no reader
return true return true
end end
# try [](name) method : super
if object.respond_to?(:'[]') && object.method(:'[]').arity == 1
return true if object[name]
end
yield
end end
def self.get(object, name, scope) def get(object, name, scope)
name_sym = name.to_s.to_sym name_sym = name.to_s.to_sym
if object.respond_to?(name_sym) if object.respond_to?(name_sym)
method = object.method(name_sym) method = object.method(name_sym)
if method.arity == 0 && # check if it is an attr_reader if method.arity == 0 && # check if it is an attr_reader
( object.respond_to?(:"#{name}=") || ( object.respond_to?(:"#{name}=") ||
object.instance_variables.find { |var| var.to_sym == :"@#{name}" } ) object.instance_variables.find { |var| var.to_sym == :"@#{name}" } )
begin
return Rhino.to_javascript(method.call, scope) return Rhino.to_javascript(method.call, scope)
rescue => e
raise Rhino::Ruby.wrap_error(e)
end
else else
return Function.wrap(method.unbind) return Function.wrap(method.unbind)
end end
elsif object.respond_to?(:"#{name}=") elsif object.respond_to?(:"#{name}=")
return nil # it does have the property but is non readable return nil # it does have the property but is non readable
end end
# try [](name) method : super
if object.respond_to?(:'[]') && object.method(:'[]').arity == 1
if value = object[name]
return Rhino.to_javascript(value, scope)
end
end
yield
end end
def self.put(object, name, value) def put(object, name, value)
if object.respond_to?(set_name = :"#{name}=") if object.respond_to?(set_name = :"#{name}=")
return object.send(set_name, Rhino.to_ruby(value)) return object.send(set_name, Rhino.to_ruby(value))
end end
# try []=(name, value) method : super
if object.respond_to?(:'[]=') && object.method(:'[]=').arity == 2
return object[name] = Rhino.to_ruby(value)
end
yield
end end
extend DeprecatedAccess # backward compatibility for a while
end end
end end
end end

View file

@ -1,54 +1,38 @@
module Rhino module Rhino
module Ruby module Ruby
module DefaultAccess class DefaultAccess < AccessBase
def self.has(object, name, scope) def has(object, name, scope)
if object.respond_to?(name.to_s) || if object.respond_to?(name.to_s) ||
object.respond_to?("#{name}=") object.respond_to?("#{name}=")
return true return true
end end
# try [](name) method : super
if object.respond_to?(:'[]') && object.method(:'[]').arity == 1
return true if object[name]
end
yield
end end
def self.get(object, name, scope) def get(object, name, scope)
if object.respond_to?(name_s = name.to_s) if object.respond_to?(name_s = name.to_s)
method = object.method(name_s) method = object.method(name_s)
if method.arity == 0 if method.arity == 0
begin
return Rhino.to_javascript(method.call, scope) return Rhino.to_javascript(method.call, scope)
rescue => e
raise Rhino::Ruby.wrap_error(e)
end
else else
return Function.wrap(method.unbind) return Function.wrap(method.unbind)
end end
elsif object.respond_to?("#{name}=") elsif object.respond_to?("#{name}=")
return nil return nil
end end
# try [](name) method : super
if object.respond_to?(:'[]') && object.method(:'[]').arity == 1
if value = object[name]
return Rhino.to_javascript(value, scope)
end
end
yield
end end
def self.put(object, name, value) def put(object, name, value)
if object.respond_to?(set_name = "#{name}=") if object.respond_to?(set_name = "#{name}=")
return object.send(set_name, Rhino.to_ruby(value)) return object.send(set_name, Rhino.to_ruby(value))
end end
# try []=(name, value) method : super
if object.respond_to?(:'[]=') && object.method(:'[]=').arity == 2
return object[name] = Rhino.to_ruby(value)
end
yield
end end
extend DeprecatedAccess # backward compatibility for a while
end end
end end
end end

View file

@ -3,7 +3,7 @@ require File.expand_path('../spec_helper', File.dirname(__FILE__))
describe Rhino::Ruby::AttributeAccess do describe Rhino::Ruby::AttributeAccess do
before(:all) do before(:all) do
Rhino::Ruby::Scriptable.access = Rhino::Ruby::AttributeAccess Rhino::Ruby::Scriptable.access = Rhino::Ruby::AttributeAccess.new
end end
after(:all) do after(:all) do
@ -68,8 +68,8 @@ describe Rhino::Ruby::AttributeAccess do
it "might set access as a symbol" do it "might set access as a symbol" do
prev_access = Rhino::Ruby::Scriptable.access prev_access = Rhino::Ruby::Scriptable.access
attr_access = Rhino::Ruby::AttributeAccess module FooAccess; end # backward compatibility
module FooAccess; end class Foo2Access; end
begin begin
@ -77,19 +77,24 @@ describe Rhino::Ruby::AttributeAccess do
lambda { lambda {
Rhino::Ruby::Scriptable.access = :attribute Rhino::Ruby::Scriptable.access = :attribute
}.should_not raise_error }.should_not raise_error
Rhino::Ruby::Scriptable.access.should == attr_access Rhino::Ruby::Scriptable.access.should be_a Rhino::Ruby::AttributeAccess
Rhino::Ruby::Scriptable.access = nil Rhino::Ruby::Scriptable.access = nil
lambda { lambda {
Rhino::Ruby::Scriptable.access = :attribute_access Rhino::Ruby::Scriptable.access = :attribute_access
}.should_not raise_error }.should_not raise_error
Rhino::Ruby::Scriptable.access.should == attr_access Rhino::Ruby::Scriptable.access.should be_a Rhino::Ruby::AttributeAccess
lambda { lambda {
Rhino::Ruby::Scriptable.access = :foo Rhino::Ruby::Scriptable.access = :foo
}.should_not raise_error }.should_not raise_error
Rhino::Ruby::Scriptable.access.should == FooAccess Rhino::Ruby::Scriptable.access.should == FooAccess
lambda {
Rhino::Ruby::Scriptable.access = :foo2
}.should_not raise_error
Rhino::Ruby::Scriptable.access.should be_a Foo2Access
lambda { lambda {
Rhino::Ruby::Scriptable.access = :bar Rhino::Ruby::Scriptable.access = :bar
}.should raise_error }.should raise_error
@ -99,4 +104,16 @@ describe Rhino::Ruby::AttributeAccess do
end end
end end
it "is backward compatibile with the 'module' way" do
Rhino::Ruby::AttributeAccess.respond_to?(:has).should be true
Rhino::Ruby::AttributeAccess.respond_to?(:get).should be true
Rhino::Ruby::AttributeAccess.respond_to?(:put).should be true
Rhino::Ruby::Scriptable.access = Rhino::Ruby::AttributeAccess
rb_object = Rhino::Ruby::Object.wrap Meh.new
rb_object.get('theMethod0', nil).should be_a(Rhino::Ruby::Function)
rb_object.has('non-existent-method', nil).should be false
end
end end