mirror of
https://github.com/rubyjs/therubyrhino
synced 2023-03-27 23:21:34 -04:00
do not access internal JS names from Ruby + exclude [] & []= methods (RedJS 0.4 compatibility)
This commit is contained in:
parent
eeb32308db
commit
112c1afa50
4 changed files with 82 additions and 38 deletions
2
Gemfile
2
Gemfile
|
@ -2,4 +2,4 @@ source :rubygems
|
|||
|
||||
gemspec
|
||||
|
||||
gem 'redjs', :git => 'git://github.com/cowboyd/redjs.git', :tag => "0.3.0", :group => :test
|
||||
gem 'redjs', :git => 'git://github.com/cowboyd/redjs.git', :branch => "0.4", :group => :test
|
||||
|
|
|
@ -5,38 +5,7 @@ module Rhino
|
|||
# shared JS::Scriptable implementation
|
||||
module Scriptable
|
||||
|
||||
# override Object Scriptable#get(String name, Scriptable start);
|
||||
# override Object Scriptable#get(int index, Scriptable start);
|
||||
def get(name, start)
|
||||
access.get(unwrap, name, self) { super }
|
||||
end
|
||||
|
||||
# override boolean Scriptable#has(String name, Scriptable start);
|
||||
# override boolean Scriptable#has(int index, Scriptable start);
|
||||
def has(name, start)
|
||||
access.has(unwrap, name, self) { super }
|
||||
end
|
||||
|
||||
# override void Scriptable#put(String name, Scriptable start, Object value);
|
||||
# override void Scriptable#put(int index, Scriptable start, Object value);
|
||||
def put(name, start, value)
|
||||
access.put(unwrap, name, value) { super }
|
||||
end
|
||||
|
||||
# override Object[] Scriptable#getIds();
|
||||
def getIds
|
||||
ids = []
|
||||
unwrap.public_methods(false).each do |name|
|
||||
name = name[0...-1] if name[-1, 1] == '=' # 'foo=' ... 'foo'
|
||||
name = name.to_s.to_java # java.lang.String
|
||||
ids << name unless ids.include?(name)
|
||||
end
|
||||
super.each { |id| ids.unshift(id) }
|
||||
ids.to_java
|
||||
end
|
||||
|
||||
@@access = nil
|
||||
|
||||
def self.access=(access)
|
||||
@@access = ( access.respond_to?(:get) && access.respond_to?(:put) ) ? access :
|
||||
begin
|
||||
|
@ -61,11 +30,61 @@ module Rhino
|
|||
@@access ||= Ruby::DefaultAccess.new
|
||||
end
|
||||
|
||||
# override Object Scriptable#get(String name, Scriptable start);
|
||||
# override Object Scriptable#get(int index, Scriptable start);
|
||||
def get(name, start)
|
||||
return nil if exclude?(name)
|
||||
access.get(unwrap, name, self) { super }
|
||||
end
|
||||
|
||||
# override boolean Scriptable#has(String name, Scriptable start);
|
||||
# override boolean Scriptable#has(int index, Scriptable start);
|
||||
def has(name, start)
|
||||
return nil if exclude?(name)
|
||||
access.has(unwrap, name, self) { super }
|
||||
end
|
||||
|
||||
# override void Scriptable#put(String name, Scriptable start, Object value);
|
||||
# override void Scriptable#put(int index, Scriptable start, Object value);
|
||||
def put(name, start, value)
|
||||
return nil if exclude?(name)
|
||||
access.put(unwrap, name, value) { super }
|
||||
end
|
||||
|
||||
# override Object[] Scriptable#getIds();
|
||||
def getIds
|
||||
ids = []
|
||||
unwrap.public_methods(false).each do |name|
|
||||
next unless name = convert(name)
|
||||
name = name.to_s.to_java # java.lang.String
|
||||
ids << name unless ids.include?(name)
|
||||
end
|
||||
super.each { |id| ids.unshift(id) }
|
||||
ids.to_java
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def access
|
||||
Scriptable.access
|
||||
def convert(name)
|
||||
if exclude?(name)
|
||||
nil
|
||||
elsif name[-1, 1] == '='
|
||||
name[0...-1]
|
||||
else
|
||||
name
|
||||
end
|
||||
end
|
||||
|
||||
FETCH = '[]'.freeze
|
||||
STORE = '[]='.freeze
|
||||
|
||||
def exclude?(name)
|
||||
name == FETCH || name == STORE
|
||||
end
|
||||
|
||||
def access
|
||||
Scriptable.access
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -9,8 +9,10 @@ module Rhino
|
|||
def has(object, name, scope)
|
||||
# try [](name) method :
|
||||
if object.respond_to?(:'[]') && object.method(:'[]').arity == 1
|
||||
value = object.[](name) { return true }
|
||||
return true unless value.nil?
|
||||
unless internal?(name)
|
||||
value = object.[](name) { return true }
|
||||
return true unless value.nil?
|
||||
end
|
||||
end
|
||||
yield
|
||||
end
|
||||
|
@ -22,7 +24,7 @@ module Rhino
|
|||
object[name]
|
||||
rescue LocalJumpError
|
||||
nil
|
||||
end
|
||||
end unless internal?(name)
|
||||
return Rhino.to_javascript(value, scope) unless value.nil?
|
||||
end
|
||||
yield
|
||||
|
@ -35,11 +37,20 @@ module Rhino
|
|||
begin
|
||||
return object[name] = rb_value
|
||||
rescue LocalJumpError
|
||||
end
|
||||
end unless internal?(name)
|
||||
end
|
||||
yield
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
UNDERSCORES = '__'.freeze
|
||||
|
||||
def internal?(name) # e.g. '__iterator__', '__proto__'
|
||||
name.is_a?(String) &&
|
||||
name[0..1] == UNDERSCORES && name[-2..-1] == UNDERSCORES
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
module DeprecatedAccess
|
||||
|
|
|
@ -8,4 +8,18 @@ describe Rhino::Context do
|
|||
|
||||
it_behaves_like 'RedJS::Context'
|
||||
|
||||
it "keeps objects iterable when property accessor is provided" do
|
||||
klass = Class.new do
|
||||
def [](name); name; end
|
||||
attr_accessor :foo
|
||||
def bar=(bar); bar; end
|
||||
end
|
||||
|
||||
RedJS::Context.new do |cxt|
|
||||
cxt['o'] = klass.new
|
||||
cxt.eval('a = new Array(); for (var i in o) a.push(i);')
|
||||
cxt['a'].length.should == 2 # [ 'foo', 'bar' ]
|
||||
end
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in a new issue