1
0
Fork 0
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:
kares 2012-04-21 19:56:05 +02:00
parent eeb32308db
commit 112c1afa50
4 changed files with 82 additions and 38 deletions

View file

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

View file

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

View file

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

View file

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