therubyrhino 1.73.0 → 1.73.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/rhino.rb +27 -9
- data/lib/rhino/context.rb +127 -100
- data/lib/rhino/deprecations.rb +52 -0
- data/lib/rhino/error.rb +44 -0
- data/lib/rhino/object.rb +10 -1
- data/lib/rhino/rhino_ext.rb +237 -0
- data/lib/rhino/ruby.rb +225 -0
- data/lib/rhino/ruby/access.rb +8 -0
- data/lib/rhino/ruby/attribute_access.rb +55 -0
- data/lib/rhino/ruby/default_access.rb +54 -0
- data/lib/rhino/version.rb +1 -1
- data/lib/rhino/wormhole.rb +63 -57
- data/spec/rhino/access_spec.rb +69 -0
- data/spec/rhino/context_spec.rb +24 -10
- data/spec/rhino/deprecations_spec.rb +41 -0
- data/spec/rhino/error_spec.rb +38 -0
- data/spec/rhino/rhino_ext_spec.rb +234 -0
- data/spec/rhino/ruby_spec.rb +390 -0
- data/spec/rhino/wormhole_spec.rb +99 -78
- data/spec/spec_helper.rb +1 -0
- data/therubyrhino.gemspec +1 -0
- metadata +26 -8
- data/lib/rhino/java.rb +0 -24
- data/lib/rhino/native_function.rb +0 -29
- data/lib/rhino/native_object.rb +0 -71
- data/lib/rhino/ruby_function.rb +0 -14
- data/lib/rhino/ruby_object.rb +0 -71
data/lib/rhino.rb
CHANGED
@@ -1,11 +1,29 @@
|
|
1
|
+
require 'java'
|
2
|
+
|
3
|
+
require 'rhino/rhino-1.7R3.jar'
|
1
4
|
|
2
5
|
module Rhino
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
end
|
6
|
+
|
7
|
+
# This module contains all the native Rhino objects implemented in Java
|
8
|
+
# e.g. Rhino::JS::NativeObject # => org.mozilla.javascript.NativeObject
|
9
|
+
module JS
|
10
|
+
include_package "org.mozilla.javascript"
|
11
|
+
|
12
|
+
module Regexp
|
13
|
+
include_package "org.mozilla.javascript.regexp"
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'rhino/wormhole'
|
21
|
+
Rhino.extend Rhino::To
|
22
|
+
|
23
|
+
require 'rhino/object'
|
24
|
+
require 'rhino/context'
|
25
|
+
require 'rhino/error'
|
26
|
+
require 'rhino/rhino_ext'
|
27
|
+
require 'rhino/ruby'
|
28
|
+
require 'rhino/ruby/access'
|
29
|
+
require 'rhino/deprecations'
|
data/lib/rhino/context.rb
CHANGED
@@ -2,40 +2,38 @@ require 'stringio'
|
|
2
2
|
|
3
3
|
module Rhino
|
4
4
|
|
5
|
-
# ==Overview
|
6
|
-
# All Javascript must be executed in a context which represents the execution environment in
|
7
|
-
# which scripts will run. The environment consists of the standard javascript objects
|
8
|
-
# and functions like Object, String, Array, etc... as well as any objects or functions which
|
9
|
-
# have been defined in it. e.g.
|
10
|
-
#
|
11
|
-
# Context.open do |cxt|
|
12
|
-
# cxt['num'] = 5
|
13
|
-
# cxt.eval('num + 5') #=> 10
|
14
|
-
# end
|
15
|
-
#
|
16
|
-
# == Multiple Contexts.
|
17
|
-
# The same object may appear in any number of contexts, but only one context may be executing javascript code
|
18
|
-
# in any given thread. If a new context is opened in a thread in which a context is already opened, the second
|
19
|
-
# context will "mask" the old context e.g.
|
20
|
-
#
|
21
|
-
# six = 6
|
22
|
-
# Context.open do |cxt|
|
23
|
-
# cxt['num'] = 5
|
24
|
-
# cxt.eval('num') # => 5
|
25
|
-
# Context.open do |cxt|
|
26
|
-
# cxt['num'] = 10
|
27
|
-
# cxt.eval('num') # => 10
|
28
|
-
# cxt.eval('++num') # => 11
|
29
|
-
# end
|
30
|
-
# cxt.eval('num') # => 5
|
31
|
-
# end
|
32
|
-
#
|
33
|
-
# == Notes
|
34
|
-
# While there are many similarities between Rhino::Context and Java::org.mozilla.javascript.Context, they are not
|
35
|
-
# the same thing and should not be confused.
|
36
|
-
|
5
|
+
# ==Overview
|
6
|
+
# All Javascript must be executed in a context which represents the execution environment in
|
7
|
+
# which scripts will run. The environment consists of the standard javascript objects
|
8
|
+
# and functions like Object, String, Array, etc... as well as any objects or functions which
|
9
|
+
# have been defined in it. e.g.
|
10
|
+
#
|
11
|
+
# Context.open do |cxt|
|
12
|
+
# cxt['num'] = 5
|
13
|
+
# cxt.eval('num + 5') #=> 10
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# == Multiple Contexts.
|
17
|
+
# The same object may appear in any number of contexts, but only one context may be executing javascript code
|
18
|
+
# in any given thread. If a new context is opened in a thread in which a context is already opened, the second
|
19
|
+
# context will "mask" the old context e.g.
|
20
|
+
#
|
21
|
+
# six = 6
|
22
|
+
# Context.open do |cxt|
|
23
|
+
# cxt['num'] = 5
|
24
|
+
# cxt.eval('num') # => 5
|
25
|
+
# Context.open do |cxt|
|
26
|
+
# cxt['num'] = 10
|
27
|
+
# cxt.eval('num') # => 10
|
28
|
+
# cxt.eval('++num') # => 11
|
29
|
+
# end
|
30
|
+
# cxt.eval('num') # => 5
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# == Notes
|
34
|
+
# While there are many similarities between Rhino::Context and Java::org.mozilla.javascript.Context, they are not
|
35
|
+
# the same thing and should not be confused.
|
37
36
|
class Context
|
38
|
-
attr_reader :scope
|
39
37
|
|
40
38
|
class << self
|
41
39
|
|
@@ -51,37 +49,40 @@ module Rhino
|
|
51
49
|
|
52
50
|
end
|
53
51
|
|
52
|
+
attr_reader :scope
|
53
|
+
|
54
54
|
# Create a new javascript environment for executing javascript and ruby code.
|
55
55
|
# * <tt>:sealed</tt> - if this is true, then the standard objects such as Object, Function, Array will not be able to be modified
|
56
56
|
# * <tt>:with</tt> - use this ruby object as the root scope for all javascript that is evaluated
|
57
57
|
# * <tt>:java</tt> - if true, java packages will be accessible from within javascript
|
58
58
|
def initialize(options = {}) #:nodoc:
|
59
|
-
ContextFactory.new
|
60
|
-
|
61
|
-
@
|
59
|
+
@factory = ContextFactory.new
|
60
|
+
@factory.call do |context|
|
61
|
+
@native = context
|
62
|
+
@global = @native.initStandardObjects(nil, options[:sealed] == true)
|
62
63
|
if with = options[:with]
|
63
|
-
@scope =
|
64
|
-
@scope.setParentScope(@global
|
64
|
+
@scope = Rhino.to_javascript(with)
|
65
|
+
@scope.setParentScope(@global)
|
65
66
|
else
|
66
67
|
@scope = @global
|
67
68
|
end
|
68
69
|
unless options[:java]
|
69
70
|
for package in ["Packages", "java", "javax", "org", "com", "edu", "net"]
|
70
|
-
@global.
|
71
|
+
@global.delete(package)
|
71
72
|
end
|
72
73
|
end
|
73
74
|
end
|
74
75
|
end
|
75
76
|
|
76
77
|
# Read a value from the global scope of this context
|
77
|
-
def [](
|
78
|
-
@scope[
|
78
|
+
def [](key)
|
79
|
+
@scope[key]
|
79
80
|
end
|
80
81
|
|
81
82
|
# Set a value in the global scope of this context. This value will be visible to all the
|
82
83
|
# javascript that is executed in this context.
|
83
|
-
def []=(
|
84
|
-
@scope[
|
84
|
+
def []=(key, val)
|
85
|
+
@scope[key] = val
|
85
86
|
end
|
86
87
|
|
87
88
|
# Evaluate a string of javascript in this context:
|
@@ -89,23 +90,18 @@ module Rhino
|
|
89
90
|
# * <tt>source_name</tt> - associated name for this source code. Mainly useful for backtraces.
|
90
91
|
# * <tt>line_number</tt> - associate this number with the first line of executing source. Mainly useful for backtraces
|
91
92
|
def eval(source, source_name = "<eval>", line_number = 1)
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
else
|
98
|
-
result = @native.evaluateString(scope, source.to_s, source_name, line_number, nil)
|
99
|
-
end
|
100
|
-
To.ruby result
|
101
|
-
rescue J::RhinoException => e
|
102
|
-
raise Rhino::JavascriptError, e
|
93
|
+
open do
|
94
|
+
if IO === source || StringIO === source
|
95
|
+
result = @native.evaluateReader(@scope, IOReader.new(source), source_name, line_number, nil)
|
96
|
+
else
|
97
|
+
result = @native.evaluateString(@scope, source.to_s, source_name, line_number, nil)
|
103
98
|
end
|
99
|
+
Rhino.to_ruby(result)
|
104
100
|
end
|
105
101
|
end
|
106
|
-
|
102
|
+
|
107
103
|
def evaluate(*args) # :nodoc:
|
108
|
-
|
104
|
+
eval(*args) # an alias
|
109
105
|
end
|
110
106
|
|
111
107
|
# Read the contents of <tt>filename</tt> and evaluate it as javascript. Returns the result of evaluating the
|
@@ -125,56 +121,102 @@ module Rhino
|
|
125
121
|
# If this instruction limit is exceeded, then a Rhino::RunawayScriptError
|
126
122
|
# will be raised
|
127
123
|
def instruction_limit=(limit)
|
128
|
-
@native.setInstructionObserverThreshold(limit)
|
129
|
-
@
|
124
|
+
@native.setInstructionObserverThreshold(limit)
|
125
|
+
@factory.instruction_limit = limit
|
130
126
|
end
|
131
127
|
|
128
|
+
def optimization_level
|
129
|
+
@native.getOptimizationLevel
|
130
|
+
end
|
131
|
+
|
132
132
|
# Set the optimization level that this context will use. This is sometimes necessary
|
133
133
|
# in Rhino, if the bytecode size of the compiled javascript exceeds the 64KB limit.
|
134
134
|
# By using the -1 optimization level, you tell Rhino to run in interpretative mode,
|
135
135
|
# taking a hit to performance but escaping the Java bytecode limit.
|
136
136
|
def optimization_level=(level)
|
137
|
-
@native.
|
137
|
+
if @native.class.isValidOptimizationLevel(level)
|
138
|
+
@native.setOptimizationLevel(level)
|
139
|
+
level
|
140
|
+
else
|
141
|
+
@native.setOptimizationLevel(0)
|
142
|
+
nil
|
143
|
+
end
|
138
144
|
end
|
139
145
|
|
140
|
-
#
|
141
|
-
#
|
142
|
-
def
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
end if block_given?
|
146
|
+
# Get the JS interpreter version.
|
147
|
+
# Returns a number e.g. 1.7, nil if unknown and 0 for default.
|
148
|
+
def version
|
149
|
+
case const_value = @native.getLanguageVersion
|
150
|
+
when -1 then nil # VERSION_UNKNOWN
|
151
|
+
when 0 then 0 # VERSION_DEFAULT
|
152
|
+
else const_value / 100.0 # VERSION_1_1 (1.1 = 110 / 100)
|
153
|
+
end
|
149
154
|
end
|
150
|
-
|
155
|
+
|
156
|
+
# Sets interpreter mode a.k.a. JS language version e.g. 1.7 (if supported).
|
157
|
+
def version=(version)
|
158
|
+
const = version.to_s.gsub('.', '_').upcase
|
159
|
+
const = "VERSION_#{const}" if const[0, 7] != 'VERSION'
|
160
|
+
js_context = @native.class # Context
|
161
|
+
if js_context.constants.include?(const)
|
162
|
+
const_value = js_context.const_get(const)
|
163
|
+
@native.setLanguageVersion(const_value)
|
164
|
+
const_value
|
165
|
+
else
|
166
|
+
@native.setLanguageVersion(js_context::VERSION_DEFAULT)
|
167
|
+
nil
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# Enter this context for operations.
|
172
|
+
# Some methods such as eval() will fail unless this context is open !
|
173
|
+
def open(&block)
|
174
|
+
do_open(&block)
|
175
|
+
rescue JS::RhinoException => e
|
176
|
+
raise Rhino::JSError.new(e)
|
177
|
+
end
|
178
|
+
|
179
|
+
private
|
180
|
+
|
181
|
+
def do_open
|
182
|
+
begin
|
183
|
+
@factory.enterContext(@native)
|
184
|
+
yield self
|
185
|
+
ensure
|
186
|
+
JS::Context.exit
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
151
190
|
end
|
152
191
|
|
153
|
-
class IOReader < java.io.Reader
|
192
|
+
class IOReader < java.io.Reader # :nodoc:
|
154
193
|
|
155
194
|
def initialize(io)
|
156
195
|
@io = io
|
157
196
|
end
|
158
197
|
|
159
|
-
|
198
|
+
# implement int Reader#read(char[] buffer, int offset, int length)
|
199
|
+
def read(buffer, offset, length)
|
200
|
+
str = nil
|
160
201
|
begin
|
161
202
|
str = @io.read(length)
|
162
|
-
if str.nil?
|
163
|
-
return -1
|
164
|
-
else
|
165
|
-
jstring = java.lang.String.new(str)
|
166
|
-
for i in 0 .. jstring.length - 1
|
167
|
-
charbuffer[i + offset] = jstring.charAt(i)
|
168
|
-
end
|
169
|
-
return jstring.length
|
170
|
-
end
|
171
203
|
rescue StandardError => e
|
172
|
-
raise java.io.IOException.new
|
204
|
+
raise java.io.IOException.new("failed reading from ruby IO object")
|
205
|
+
end
|
206
|
+
if str.nil?
|
207
|
+
return -1
|
208
|
+
else
|
209
|
+
jstr = str.to_java
|
210
|
+
for i in 0 .. jstr.length - 1
|
211
|
+
buffer[i + offset] = jstr.charAt(i)
|
212
|
+
end
|
213
|
+
return jstr.length
|
173
214
|
end
|
174
215
|
end
|
216
|
+
|
175
217
|
end
|
176
218
|
|
177
|
-
class ContextFactory <
|
219
|
+
class ContextFactory < JS::ContextFactory # :nodoc:
|
178
220
|
|
179
221
|
def observeInstructionCount(cxt, count)
|
180
222
|
raise RunawayScriptError, "script exceeded allowable instruction count" if count > @limit
|
@@ -183,28 +225,13 @@ module Rhino
|
|
183
225
|
def instruction_limit=(count)
|
184
226
|
@limit = count
|
185
227
|
end
|
228
|
+
|
186
229
|
end
|
187
230
|
|
188
231
|
class ContextError < StandardError # :nodoc:
|
189
|
-
|
190
232
|
end
|
191
233
|
|
192
|
-
class
|
193
|
-
def initialize(native)
|
194
|
-
@native = native
|
195
|
-
end
|
196
|
-
|
197
|
-
def message
|
198
|
-
@native.cause.details
|
199
|
-
end
|
200
|
-
|
201
|
-
def javascript_backtrace
|
202
|
-
@native.getScriptStackTrace()
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
JSError = JavascriptError
|
207
|
-
|
208
|
-
class RunawayScriptError < StandardError # :nodoc:
|
234
|
+
class RunawayScriptError < ContextError # :nodoc:
|
209
235
|
end
|
236
|
+
|
210
237
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
|
2
|
+
module Rhino
|
3
|
+
|
4
|
+
@@stub_class = Class.new(Object)
|
5
|
+
|
6
|
+
def self.const_missing(name)
|
7
|
+
case name.to_s
|
8
|
+
when 'J' then
|
9
|
+
warn "[DEPRECATION] `Rhino::J` is deprecated, use `Rhino::JS` instead."
|
10
|
+
return JS
|
11
|
+
when 'JavascriptError' then
|
12
|
+
warn "[DEPRECATION] `Rhino::JavascriptError` is deprecated, use `Rhino::JSError` instead."
|
13
|
+
return JSError
|
14
|
+
when 'NativeObject' then
|
15
|
+
warn "[DEPRECATION] `Rhino::NativeObject` is no longer used, returning a stub."
|
16
|
+
return @@stub_class
|
17
|
+
when 'NativeFunction' then
|
18
|
+
warn "[DEPRECATION] `Rhino::NativeFunction` is no longer used, returning a stub."
|
19
|
+
return @@stub_class
|
20
|
+
else super
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
@@warnings = {}
|
25
|
+
|
26
|
+
def self.warn(msg)
|
27
|
+
# only print out deprecation warnings once
|
28
|
+
if msg[0, 13] == '[DEPRECATION]'
|
29
|
+
return nil if @@warnings[msg]
|
30
|
+
@@warnings[msg] = true
|
31
|
+
end
|
32
|
+
super # Kernel.warn
|
33
|
+
end
|
34
|
+
|
35
|
+
module To
|
36
|
+
|
37
|
+
extend self
|
38
|
+
|
39
|
+
# @deprecated use {#to_ruby} instead
|
40
|
+
def self.ruby(object)
|
41
|
+
Rhino.warn "[DEPRECATION] `Rhino::To.ruby` is deprecated, use `Rhino.to_ruby` instead."
|
42
|
+
to_ruby(object)
|
43
|
+
end
|
44
|
+
|
45
|
+
# @deprecated use {#to_javascript} instead
|
46
|
+
def self.javascript(object, scope = nil)
|
47
|
+
Rhino.warn "[DEPRECATION] `Rhino::To.javascript` is deprecated, use `Rhino.to_javascript` instead."
|
48
|
+
to_javascript(object, scope)
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
data/lib/rhino/error.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
|
2
|
+
module Rhino
|
3
|
+
|
4
|
+
class JSError < StandardError
|
5
|
+
|
6
|
+
def initialize(native)
|
7
|
+
@native = native # NativeException wrapping a Java Throwable
|
8
|
+
end
|
9
|
+
|
10
|
+
def message
|
11
|
+
cause ? cause.details : @native.to_s
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_s
|
15
|
+
super
|
16
|
+
end
|
17
|
+
|
18
|
+
# most likely a Rhino::JS::JavaScriptException
|
19
|
+
def cause
|
20
|
+
@native.respond_to?(:cause) ? @native.cause : nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def unwrap
|
24
|
+
return @unwrap if defined?(@unwrap)
|
25
|
+
cause = self.cause
|
26
|
+
if cause && cause.is_a?(JS::WrappedException)
|
27
|
+
e = cause.getWrappedException
|
28
|
+
if e && e.is_a?(Java::OrgJrubyExceptions::RaiseException)
|
29
|
+
@unwrap = e.getException
|
30
|
+
else
|
31
|
+
@unwrap = e
|
32
|
+
end
|
33
|
+
else
|
34
|
+
@unwrap = nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def javascript_backtrace
|
39
|
+
cause.is_a?(JS::RhinoException) ? cause.getScriptStackTrace : nil
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|