Skip to content
Browse files

Add support for MRI 1.8.7 and jruby

  • Loading branch information...
1 parent 691c36d commit 2b245519ef6f3f54cf07c9694b7c561acc9003a7 @ConradIrwin committed Aug 11, 2012
Showing with 169 additions and 53 deletions.
  1. +2 −0 ext/extconf.rb
  2. +38 −4 ext/raise_awareness.c
  3. +100 −49 lib/raise_awareness.rb
  4. +29 −0 org/pryrepl/RaiseAwarenessEventHook.java
View
2 ext/extconf.rb
@@ -1,5 +1,7 @@
require 'mkmf'
+$CFLAGS += " -DRUBY_19" if RUBY_VERSION =~ /1.9/
+
extension_name = "raise_awareness"
dir_config(extension_name)
create_makefile(extension_name)
View
42 ext/raise_awareness.c
@@ -1,18 +1,52 @@
#include "ruby.h"
static VALUE rb_mRaiseAwareness;
-static VALUE argv[1];
+
+#ifdef RUBY_19
void
raise_awareness_hook(rb_event_flag_t evflag, VALUE data, VALUE self, ID mid, VALUE klass)
{
- VALUE binding = rb_funcall(self, rb_intern("binding"), 0, NULL);
- rb_funcall(data, rb_intern("rescue"), 2, rb_errinfo(), binding);
+ VALUE binding = rb_funcall(rb_mKernel, rb_intern("binding"), 0, NULL);
+ rb_funcall(rb_mRaiseAwareness, rb_intern("rescue"), 2, rb_errinfo(), binding);
+}
+
+VALUE
+raise_awareness_start(VALUE self)
+{
+ rb_add_event_hook(raise_awareness_hook, RUBY_EVENT_RAISE, rb_mRaiseAwareness);
+}
+
+#else
+
+#include "node.h"
+
+void
+raise_awareness_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
+{
+ VALUE binding = rb_funcall(rb_mKernel, rb_intern("binding"), 0, NULL);
+ rb_funcall(rb_mRaiseAwareness, rb_intern("rescue"), 2, ruby_errinfo, binding);
+}
+
+VALUE
+raise_awareness_start(VALUE self)
+{
+ rb_add_event_hook(raise_awareness_hook, RUBY_EVENT_RAISE);
+}
+
+#endif
+
+VALUE
+raise_awareness_stop(VALUE self)
+{
+ rb_remove_event_hook(raise_awareness_hook);
+ return Qnil;
}
void
Init_raise_awareness()
{
rb_mRaiseAwareness = rb_define_module("RaiseAwareness");
- rb_add_event_hook(raise_awareness_hook, RUBY_EVENT_RAISE, rb_mRaiseAwareness);
+ rb_define_singleton_method(rb_mRaiseAwareness, "start", raise_awareness_start, 0);
+ rb_define_singleton_method(rb_mRaiseAwareness, "stop", raise_awareness_start, 0);
}
View
149 lib/raise_awareness.rb
@@ -1,78 +1,129 @@
+require 'rubygems'
+require 'thread'
require 'pry'
-if defined? Rubinius
- class << Rubinius
+module RaiseAwareness
+
+ class << self
+ attr_accessor :mutex, :listeners
+ end
+
+ self.mutex = Mutex.new
+ self.listeners = []
- alias raise_with_no_awareness raise_exception
+ def self.listen(for_block=nil, &listen_block)
- def raise_exception(exc)
- bt = Rubinius::VM.backtrace(1, true).drop_while do |x|
- x.variables.method.file.to_s.start_with?("kernel/")
- end.first
- b = Binding.setup(bt.variables, bt.variables.method, bt.constant_scope, bt.variables.self, bt)
+ puts "FOOO"
+ raise "no block given" unless listen_block || for_block
+ listeners << listen_block || for_block
+ start
- RaiseAwareness.rescue(exc, b)
- raise_with_no_awareness(exc)
+ if listen_block && for_block
+ begin
+ for_block.call
+ ensure
+ unlisten listen_block
+ end
end
+ end
- def binding_of_caller(n)
- bt = Rubinius::VM.backtrace(1 + n, true).first
+ def self.unlisten(listen_block)
+ listeners.delete listen_block
+ stop if listeners.empty?
+ end
- b = Binding.setup(
- bt.variables,
- bt.variables.method,
- bt.constant_scope,
- bt.variables.self,
- bt
- )
+ def self.rescue(e, binding)
+ listeners.each do |l|
+ l.call(e, binding)
+ end
+ end
+end
+
+if defined? Rubinius
+ module RaiseAwareness
+ def self.start
+ class << Rubinius
+ alias raise_with_no_awareness raise_exception
+
+ def raise_exception(exc)
+ bt = Rubinius::VM.backtrace(1, true).drop_while do |x|
+ x.variables.method.file.to_s.start_with?("kernel/")
+ end.first
+ b = Binding.setup(bt.variables, bt.variables.method, bt.constant_scope, bt.variables.self, bt)
+
+ RaiseAwareness.rescue(exc, b)
+ raise_with_no_awareness(exc)
+ end
+ end
+ end
+
+ def self.stop
+ alias raise_exception raise_with_no_awareness
+ end
+ end
+elsif defined?(JRuby)
+ puts "HIHIIH"
+ $CLASSPATH << './org/pryrepl'
+ java_import org.pryrepl.RaiseAwarenessEventHook
+
+ module RaiseAwareness
+ private
+ def self.start
+ puts "START"
+ JRuby.runtime.add_event_hook(hook)
+ end
- b.instance_variable_set(:@frame_description, bt.describe)
+ def self.stop
+ JRuby.runtime.remove_event_hook(hook)
+ end
- b
+ def self.hook
+ @hook ||= RaiseAwarenessEventHook.new(proc do |e, b|
+ self.rescue(e, b)
+ end)
end
end
+
else
require './ext/raise_awareness.so'
end
-module RaiseAwareness
- def self.listeners; @listeners ||= []; end
- def self.rescue(e, binding)
- listeners.each do |l|
- l.call(e, binding)
- end
+def pryly(&block)
+ raised = []
+
+ puts "listening"
+ RaiseAwareness.listen(block) do |exception, binding|
+ raised << [exception, binding]
end
- def self.wrap
- raises = []
- listeners << proc{ |e, b| raises << [e, b] }
- yield
- ensure
- listeners.pop
- e, b = *raises.last
- if b
- $foo = e
- $bar = raises
- b.eval("_ex_ = $foo")
- b.eval("_raises_ = $bar")
- b.pry
- end
+ensure
+ if raised.last
+ e, b = *raised.last
+ $foo = e
+ $bar = raised
+ b.eval("_ex_ = $foo")
+ b.eval("_raised_ = $bar")
+ b.pry
end
end
-RaiseAwareness.wrap do
- begin
+pryly do
+
+ def a
begin
- raise "foo"
+ begin
+ raise "foo"
- rescue => e
- raise "bar"
- end
+ rescue => e
+ raise "bar"
+ end
- rescue => e
- "woo".wibble
+ rescue => e
+ 1 / 0
+ end
end
+ a
end
__END__
View
29 org/pryrepl/RaiseAwarenessEventHook.java
@@ -0,0 +1,29 @@
+package org.pryrepl;
+
+import org.jruby.runtime.builtin.IRubyObject;
+import org.jruby.runtime.EventHook;
+import org.jruby.runtime.RubyEvent;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.RubyException;
+import org.jruby.RubyBinding;
+import org.jruby.RubyProc;
+
+public class RaiseAwarenessEventHook extends EventHook {
+
+ private RubyProc proc;
+
+ public RaiseAwarenessEventHook(RubyProc proc) {
+ super();
+ this.proc = proc;
+ }
+
+ public boolean isInterestedInEvent(RubyEvent event) {
+ return event.getName().equals(RubyEvent.RAISE.getName());
+ }
+
+ public void eventHandler(ThreadContext context, String eventName, String file, int line, String name, IRubyObject type) {
+ RubyBinding binding = RubyBinding.newBinding(context.runtime, context.currentBinding());
+ RubyException exception = (RubyException)context.runtime.getGlobalVariables().get("$!");
+ proc.call(context, new IRubyObject[] {exception, binding});
+ }
+}

0 comments on commit 2b24551

Please sign in to comment.
Something went wrong with that request. Please try again.