therubyrhino 1.73.0 → 1.73.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|