diff --git a/lib/rhino.rb b/lib/rhino.rb
index 7c43dcd..783a29a 100644
--- a/lib/rhino.rb
+++ b/lib/rhino.rb
@@ -22,6 +22,7 @@ Rhino.extend Rhino::To
require 'rhino/object'
require 'rhino/context'
+require 'rhino/error'
require 'rhino/rhino_ext'
require 'rhino/ruby_object'
require 'rhino/ruby_function'
diff --git a/lib/rhino/context.rb b/lib/rhino/context.rb
index 6279e3f..fa558e7 100644
--- a/lib/rhino/context.rb
+++ b/lib/rhino/context.rb
@@ -90,23 +90,18 @@ module Rhino
# * source_name - associated name for this source code. Mainly useful for backtraces.
# * line_number - associate this number with the first line of executing source. Mainly useful for backtraces
def eval(source, source_name = "", line_number = 1)
- self.open do
- begin
- scope = Rhino.to_javascript(@scope)
- if IO === source || StringIO === source
- result = @native.evaluateReader(scope, IOReader.new(source), source_name, line_number, nil)
- else
- result = @native.evaluateString(scope, source.to_s, source_name, line_number, nil)
- end
- Rhino.to_ruby(result)
- rescue JS::RhinoException => e
- raise JavascriptError, e
+ open do
+ if IO === source || StringIO === source
+ result = @native.evaluateReader(@scope, IOReader.new(source), source_name, line_number, nil)
+ else
+ result = @native.evaluateString(@scope, source.to_s, source_name, line_number, nil)
end
+ Rhino.to_ruby(result)
end
end
-
+
def evaluate(*args) # :nodoc:
- self.eval(*args)
+ eval(*args) # an alias
end
# Read the contents of filename and evaluate it as javascript. Returns the result of evaluating the
@@ -163,40 +158,50 @@ module Rhino
end
end
- # Enter this context for operations. Some methods such as eval() will
- # fail unless this context is open
- def open
- begin
- @factory.enterContext(@native)
- yield self
- ensure
- JS::Context.exit()
- end if block_given?
+ # Enter this context for operations.
+ # Some methods such as eval() will fail unless this context is open !
+ def open(&block)
+ do_open(&block)
+ rescue JS::RhinoException => e
+ raise Rhino::JSError.new(e)
end
-
+
+ private
+
+ def do_open
+ begin
+ @factory.enterContext(@native)
+ yield self
+ ensure
+ JS::Context.exit
+ end
+ end
+
end
- class IOReader < java.io.Reader #:nodoc:
+ class IOReader < java.io.Reader # :nodoc:
def initialize(io)
@io = io
end
- def read(charbuffer, offset, length)
+ # implement int Reader#read(char[] buffer, int offset, int length)
+ def read(buffer, offset, length)
+ str = nil
begin
str = @io.read(length)
- if str.nil?
- return -1
- else
- jstring = java.lang.String.new(str)
- for i in 0 .. jstring.length - 1
- charbuffer[i + offset] = jstring.charAt(i)
- end
- return jstring.length
- end
rescue StandardError => e
raise java.io.IOException.new, "Failed reading from ruby IO object"
end
+ if str.nil?
+ return -1
+ else
+ jstr = str.to_java
+ for i in 0 .. jstr.length - 1
+ buffer[i + offset] = jstr.charAt(i)
+ end
+ return jstr.length
+ end
end
end
@@ -216,23 +221,7 @@ module Rhino
class ContextError < StandardError # :nodoc:
end
- class JavascriptError < StandardError # :nodoc:
- def initialize(native)
- @native = native
- end
-
- def message
- @native.cause.details
- end
-
- def javascript_backtrace
- @native.getScriptStackTrace()
- end
- end
-
- JSError = JavascriptError
-
- class RunawayScriptError < StandardError # :nodoc:
+ class RunawayScriptError < ContextError # :nodoc:
end
end
diff --git a/lib/rhino/deprecations.rb b/lib/rhino/deprecations.rb
index 209e5e9..65592d8 100644
--- a/lib/rhino/deprecations.rb
+++ b/lib/rhino/deprecations.rb
@@ -8,6 +8,9 @@ module Rhino
when 'J' then
warn "[DEPRECATION] `Rhino::J` is deprecated, use `Rhino::JS` instead."
return JS
+ when 'JavascriptError' then
+ warn "[DEPRECATION] `Rhino::JavascriptError` is deprecated, use `Rhino::JSError` instead."
+ return JSError
when 'NativeObject' then
warn "[DEPRECATION] `Rhino::NativeObject` is no longer used, returning a stub."
return @@stub_class
diff --git a/lib/rhino/error.rb b/lib/rhino/error.rb
new file mode 100644
index 0000000..021d96e
--- /dev/null
+++ b/lib/rhino/error.rb
@@ -0,0 +1,25 @@
+
+module Rhino
+
+ class JSError < StandardError
+
+ def initialize(native)
+ @native = native # NativeException wrapping a Java Throwable
+ end
+
+ # most likely a Rhino::JS::JavaScriptException
+ def cause
+ @native.respond_to?(:cause) ? @native.cause : nil
+ end
+
+ def message
+ cause ? cause.details : @native.to_s
+ end
+
+ def javascript_backtrace
+ cause.is_a?(JS::RhinoException) ? cause.getScriptStackTrace : nil
+ end
+
+ end
+
+end
diff --git a/spec/rhino/deprecations_spec.rb b/spec/rhino/deprecations_spec.rb
index 060640a..eccf849 100644
--- a/spec/rhino/deprecations_spec.rb
+++ b/spec/rhino/deprecations_spec.rb
@@ -33,5 +33,9 @@ describe 'deprecations' do
it "NativeFunction constant exists" do
lambda { Rhino::NativeFunction }.should_not raise_error
end
+
+ it "JavascriptError returns JSError" do
+ lambda { Rhino::JavascriptError.should be(Rhino::JSError) }.should_not raise_error
+ end
end
\ No newline at end of file
diff --git a/spec/rhino/error_spec.rb b/spec/rhino/error_spec.rb
new file mode 100644
index 0000000..63e24cd
--- /dev/null
+++ b/spec/rhino/error_spec.rb
@@ -0,0 +1,38 @@
+require File.expand_path('../spec_helper', File.dirname(__FILE__))
+
+describe Rhino::JSError do
+
+ it "works as a StandardError with a message being passed" do
+ js_error = Rhino::JSError.new 'an error message'
+ lambda { js_error.to_s && js_error.inspect }.should_not raise_error
+
+ js_error.cause.should be_nil
+ js_error.message.should == 'an error message'
+ js_error.javascript_backtrace.should be_nil
+ end
+
+ it "might wrap a RhinoException wrapped in a NativeException like error" do
+ # JRuby's NativeException.new(rhino_e) does not work as it is
+ # intended to handle Java exceptions ... no new on the Ruby side
+ native_error_class = Class.new(RuntimeError) do
+
+ def initialize(cause)
+ @cause = cause
+ end
+
+ def cause
+ @cause
+ end
+
+ end
+
+ rhino_e = Rhino::JS::JavaScriptException.new("42".to_java)
+ js_error = Rhino::JSError.new native_error_class.new(rhino_e)
+ lambda { js_error.to_s && js_error.inspect }.should_not raise_error
+
+ js_error.cause.should be(rhino_e)
+ js_error.message.should == '42'
+ js_error.javascript_backtrace.should_not be_nil
+ end
+
+end
\ No newline at end of file