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:
parent
f292f13686
commit
721c8a4355
6 changed files with 115 additions and 73 deletions
|
@ -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 :
|
||||
|
||||
Rhino::Ruby::Scriptable.access = FooApp::BarAccess
|
||||
Rhino::Ruby::Scriptable.access = FooApp::BarAccess.instance
|
||||
|
||||
=== Safe by default
|
||||
|
||||
|
|
|
@ -38,24 +38,27 @@ module Rhino
|
|||
@@access = nil
|
||||
|
||||
def self.access=(access)
|
||||
@@access = access.is_a?(Module) ? access : begin
|
||||
if access # Scriptable.access = :attribute
|
||||
name = access.to_s.chomp('_access')
|
||||
name = name[0, 1].capitalize << name[1..-1]
|
||||
name = :"#{name}Access"
|
||||
if Ruby.const_defined?(name)
|
||||
Ruby.const_get(name) # e.g. Rhino::Ruby::AttributeAccess
|
||||
else
|
||||
const_get(name) # e.g. Rhino::Ruby::Scriptable::FooAccess
|
||||
end
|
||||
else # nil, false
|
||||
access
|
||||
@@access = ( access.respond_to?(:get) && access.respond_to?(:put) ) ? access :
|
||||
begin
|
||||
access =
|
||||
if access && ! access.is_a?(Class) # Scriptable.access = :attribute
|
||||
name = access.to_s.chomp('_access')
|
||||
name = name[0, 1].capitalize << name[1..-1]
|
||||
name = :"#{name}Access"
|
||||
if Ruby.const_defined?(name)
|
||||
Ruby.const_get(name) # e.g. Rhino::Ruby::AttributeAccess
|
||||
else
|
||||
const_get(name) # e.g. Rhino::Ruby::Scriptable::FooAccess
|
||||
end
|
||||
else # nil, false, Class
|
||||
access
|
||||
end
|
||||
access.is_a?(Class) ? access.new : access
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.access
|
||||
@@access ||= Ruby::DefaultAccess
|
||||
@@access ||= Ruby::DefaultAccess.new
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -4,5 +4,59 @@ module Rhino
|
|||
autoload :DefaultAccess, "rhino/ruby/default_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
|
|
@ -1,57 +1,41 @@
|
|||
module Rhino
|
||||
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) ||
|
||||
object.respond_to?(:"#{name}=") # might have a writer but no reader
|
||||
return true
|
||||
end
|
||||
# try [](name) method :
|
||||
if object.respond_to?(:'[]') && object.method(:'[]').arity == 1
|
||||
return true if object[name]
|
||||
end
|
||||
yield
|
||||
super
|
||||
end
|
||||
|
||||
def self.get(object, name, scope)
|
||||
def get(object, name, scope)
|
||||
name_sym = name.to_s.to_sym
|
||||
if object.respond_to?(name_sym)
|
||||
method = object.method(name_sym)
|
||||
if method.arity == 0 && # check if it is an attr_reader
|
||||
( object.respond_to?(:"#{name}=") ||
|
||||
object.instance_variables.find { |var| var.to_sym == :"@#{name}" } )
|
||||
begin
|
||||
return Rhino.to_javascript(method.call, scope)
|
||||
rescue => e
|
||||
raise Rhino::Ruby.wrap_error(e)
|
||||
end
|
||||
return Rhino.to_javascript(method.call, scope)
|
||||
else
|
||||
return Function.wrap(method.unbind)
|
||||
end
|
||||
elsif object.respond_to?(:"#{name}=")
|
||||
return nil # it does have the property but is non readable
|
||||
end
|
||||
# try [](name) method :
|
||||
if object.respond_to?(:'[]') && object.method(:'[]').arity == 1
|
||||
if value = object[name]
|
||||
return Rhino.to_javascript(value, scope)
|
||||
end
|
||||
end
|
||||
yield
|
||||
super
|
||||
end
|
||||
|
||||
def self.put(object, name, value)
|
||||
def put(object, name, value)
|
||||
if object.respond_to?(set_name = :"#{name}=")
|
||||
return object.send(set_name, Rhino.to_ruby(value))
|
||||
end
|
||||
# try []=(name, value) method :
|
||||
if object.respond_to?(:'[]=') && object.method(:'[]=').arity == 2
|
||||
return object[name] = Rhino.to_ruby(value)
|
||||
end
|
||||
yield
|
||||
super
|
||||
end
|
||||
|
||||
extend DeprecatedAccess # backward compatibility for a while
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,54 +1,38 @@
|
|||
module Rhino
|
||||
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) ||
|
||||
object.respond_to?("#{name}=")
|
||||
return true
|
||||
end
|
||||
# try [](name) method :
|
||||
if object.respond_to?(:'[]') && object.method(:'[]').arity == 1
|
||||
return true if object[name]
|
||||
end
|
||||
yield
|
||||
super
|
||||
end
|
||||
|
||||
def self.get(object, name, scope)
|
||||
def get(object, name, scope)
|
||||
if object.respond_to?(name_s = name.to_s)
|
||||
method = object.method(name_s)
|
||||
if method.arity == 0
|
||||
begin
|
||||
return Rhino.to_javascript(method.call, scope)
|
||||
rescue => e
|
||||
raise Rhino::Ruby.wrap_error(e)
|
||||
end
|
||||
return Rhino.to_javascript(method.call, scope)
|
||||
else
|
||||
return Function.wrap(method.unbind)
|
||||
end
|
||||
elsif object.respond_to?("#{name}=")
|
||||
return nil
|
||||
end
|
||||
# try [](name) method :
|
||||
if object.respond_to?(:'[]') && object.method(:'[]').arity == 1
|
||||
if value = object[name]
|
||||
return Rhino.to_javascript(value, scope)
|
||||
end
|
||||
end
|
||||
yield
|
||||
super
|
||||
end
|
||||
|
||||
def self.put(object, name, value)
|
||||
def put(object, name, value)
|
||||
if object.respond_to?(set_name = "#{name}=")
|
||||
return object.send(set_name, Rhino.to_ruby(value))
|
||||
end
|
||||
# try []=(name, value) method :
|
||||
if object.respond_to?(:'[]=') && object.method(:'[]=').arity == 2
|
||||
return object[name] = Rhino.to_ruby(value)
|
||||
end
|
||||
yield
|
||||
super
|
||||
end
|
||||
|
||||
extend DeprecatedAccess # backward compatibility for a while
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -3,7 +3,7 @@ require File.expand_path('../spec_helper', File.dirname(__FILE__))
|
|||
describe Rhino::Ruby::AttributeAccess do
|
||||
|
||||
before(:all) do
|
||||
Rhino::Ruby::Scriptable.access = Rhino::Ruby::AttributeAccess
|
||||
Rhino::Ruby::Scriptable.access = Rhino::Ruby::AttributeAccess.new
|
||||
end
|
||||
|
||||
after(:all) do
|
||||
|
@ -68,8 +68,8 @@ describe Rhino::Ruby::AttributeAccess do
|
|||
|
||||
it "might set access as a symbol" do
|
||||
prev_access = Rhino::Ruby::Scriptable.access
|
||||
attr_access = Rhino::Ruby::AttributeAccess
|
||||
module FooAccess; end
|
||||
module FooAccess; end # backward compatibility
|
||||
class Foo2Access; end
|
||||
|
||||
begin
|
||||
|
||||
|
@ -77,19 +77,24 @@ describe Rhino::Ruby::AttributeAccess do
|
|||
lambda {
|
||||
Rhino::Ruby::Scriptable.access = :attribute
|
||||
}.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
|
||||
lambda {
|
||||
Rhino::Ruby::Scriptable.access = :attribute_access
|
||||
}.should_not raise_error
|
||||
Rhino::Ruby::Scriptable.access.should == attr_access
|
||||
Rhino::Ruby::Scriptable.access.should be_a Rhino::Ruby::AttributeAccess
|
||||
|
||||
lambda {
|
||||
Rhino::Ruby::Scriptable.access = :foo
|
||||
}.should_not raise_error
|
||||
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 {
|
||||
Rhino::Ruby::Scriptable.access = :bar
|
||||
}.should raise_error
|
||||
|
@ -99,4 +104,16 @@ describe Rhino::Ruby::AttributeAccess do
|
|||
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
|
||||
|
|
Loading…
Reference in a new issue