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

170 lines
4.6 KiB
Ruby

# The base class for all JavaScript objects.
class Java::OrgMozillaJavascript::ScriptableObject
include_package "org.mozilla.javascript"
# get a property from this javascript object, where +k+ is a string or symbol
# corresponding to the property name e.g.
#
# jsobject = Context.open do |cxt|
# cxt.eval('({foo: 'bar', 'Take me to': 'a funky town'})')
# end
# jsobject[:foo] # => 'bar'
# jsobject['foo'] # => 'bar'
# jsobject['Take me to'] # => 'a funky town'
#
def [](name)
Rhino.to_ruby ScriptableObject.getProperty(self, name.to_s)
end
# set a property on the javascript object, where +k+ is a string or symbol corresponding
# to the property name, and +v+ is the value to set. e.g.
#
# jsobject = eval_js "new Object()"
# jsobject['foo'] = 'bar'
# Context.open(:with => jsobject) do |cxt|
# cxt.eval('foo') # => 'bar'
# end
#
def []=(key, value)
scope = self
ScriptableObject.putProperty(self, key.to_s, Rhino.to_javascript(value, scope))
end
# enumerate the key value pairs contained in this javascript object. e.g.
#
# eval_js("{foo: 'bar', baz: 'bang'}").each do |key,value|
# puts "#{key} -> #{value} "
# end
#
# outputs foo -> bar baz -> bang
#
def each
each_raw { |key, val| yield key, Rhino.to_ruby(val) }
end
def each_key
each_raw { |key, val| yield key }
end
def each_value
each_raw { |key, val| yield Rhino.to_ruby(val) }
end
def each_raw
for id in getAllIds do
yield id, get(id, self)
end
end
def keys
keys = []
each_key { |key| keys << key }
keys
end
def values
vals = []
each_value { |val| vals << val }
vals
end
# Converts the native object to a hash. This isn't really a stretch since it's
# pretty much a hash in the first place.
def to_h
hash = {}
each do |key, val|
hash[key] = val.is_a?(ScriptableObject) ? val.to_h : val
end
hash
end
# Convert this javascript object into a json string.
def to_json(*args)
to_h.to_json(*args)
end
# Delegate methods to JS object if possible when called from Ruby.
def method_missing(name, *args)
s_name = name.to_s
if s_name[-1, 1] == '=' && args.size == 1 # writer -> JS put
self[ s_name[0...-1] ] = args[0]
else
property = ScriptableObject.getProperty(self, s_name)
if property && property != Scriptable::NOT_FOUND
if property.is_a?(Rhino::JS::Function)
begin
context = Rhino::JS::Context.enter
js_args = Rhino.args_to_javascript(args, self) # scope == self
Rhino.to_ruby property.call(context, self, s_name, js_args)
ensure
Rhino::JS::Context.exit
end
else
if args.size > 0
raise ArgumentError, "can't #{name}(#{args.join(', ')}) as '#{name}' is a property"
end
Rhino.to_ruby property
end
else
super
end
end
end
end
class Java::OrgMozillaJavascript::NativeObject
include_package "org.mozilla.javascript"
def [](name)
value = Rhino.to_ruby(ScriptableObject.getProperty(self, s_name = name.to_s))
# handle { '5': 5 }.keys() ... [ 5 ] not [ '5' ] !
if value.nil? && (i_name = s_name.to_i) != 0
value = Rhino.to_ruby(ScriptableObject.getProperty(self, i_name))
end
value
end
# re-implement unsupported Map#put
def []=(key, value)
scope = self
ScriptableObject.putProperty(self, key.to_s, Rhino.to_javascript(value, scope))
end
end
# The base class for all JavaScript function objects.
class Java::OrgMozillaJavascript::BaseFunction
alias_method :__call__, :call # Rhino's Function#call(a1, a2, a3, a4)
# make JavaScript functions callable Ruby style e.g. `fn.call('42')`
def call(*args)
context = Rhino::JS::Context.enter
scope = getParentScope || context.initStandardObjects
__call__(context, scope, scope, Rhino.args_to_javascript(args, scope))
ensure
Rhino::JS::Context.exit
end
# use JavaScript functions constructors from Ruby as `fn.new`
def new(*args)
context = Rhino::JS::Context.enter
scope = getParentScope || context.initStandardObjects
construct(context, scope, Rhino.args_to_javascript(args, scope))
ensure
Rhino::JS::Context.exit
end
def methodcall(this, *args)
context = Rhino::JS::Context.enter
scope = getParentScope || context.initStandardObjects
__call__(context, scope, Rhino.to_javascript(this), Rhino.args_to_javascript(args, scope))
ensure
Rhino::JS::Context.exit
end
end