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 :
|
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
|
||||||
|
|
||||||
|
|
|
@ -38,24 +38,27 @@ 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
|
||||||
name = access.to_s.chomp('_access')
|
access =
|
||||||
name = name[0, 1].capitalize << name[1..-1]
|
if access && ! access.is_a?(Class) # Scriptable.access = :attribute
|
||||||
name = :"#{name}Access"
|
name = access.to_s.chomp('_access')
|
||||||
if Ruby.const_defined?(name)
|
name = name[0, 1].capitalize << name[1..-1]
|
||||||
Ruby.const_get(name) # e.g. Rhino::Ruby::AttributeAccess
|
name = :"#{name}Access"
|
||||||
else
|
if Ruby.const_defined?(name)
|
||||||
const_get(name) # e.g. Rhino::Ruby::Scriptable::FooAccess
|
Ruby.const_get(name) # e.g. Rhino::Ruby::AttributeAccess
|
||||||
end
|
else
|
||||||
else # nil, false
|
const_get(name) # e.g. Rhino::Ruby::Scriptable::FooAccess
|
||||||
access
|
end
|
||||||
|
else # nil, false, Class
|
||||||
|
access
|
||||||
|
end
|
||||||
|
access.is_a?(Class) ? access.new : access
|
||||||
end
|
end
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.access
|
def self.access
|
||||||
@@access ||= Ruby::DefaultAccess
|
@@access ||= Ruby::DefaultAccess.new
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -87,7 +90,7 @@ module Rhino
|
||||||
def unwrap
|
def unwrap
|
||||||
@ruby
|
@ruby
|
||||||
end
|
end
|
||||||
|
|
||||||
# abstract String Scriptable#getClassName();
|
# abstract String Scriptable#getClassName();
|
||||||
def getClassName
|
def getClassName
|
||||||
@ruby.class.to_s # to_s handles 'nameless' classes as well
|
@ruby.class.to_s # to_s handles 'nameless' classes as well
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue