interception 0.1.pre.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/.gitignore +6 -0
- data/ext/extconf.rb +23 -0
- data/ext/interception.c +52 -0
- data/ext/org/pryrepl/InterceptionEventHook.java +29 -0
- data/interception.gemspec +15 -0
- data/lib/interception.rb +84 -0
- metadata +63 -0
data/.gitignore
ADDED
data/ext/extconf.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
|
3
|
+
if RbConfig::CONFIG['ruby_install_name'] == 'jruby'
|
4
|
+
|
5
|
+
File.open("Makefile", "w") do |f|
|
6
|
+
f.write "install:\n\tjrubyc --javac org/pryrepl/InterceptionEventHook.java\n"
|
7
|
+
end
|
8
|
+
|
9
|
+
elsif RbConfig::CONFIG['ruby_install_name'] == 'ruby'
|
10
|
+
|
11
|
+
require 'mkmf'
|
12
|
+
$CFLAGS += " -DRUBY_19" if RUBY_VERSION =~ /^1.9/
|
13
|
+
extension_name = "interception"
|
14
|
+
dir_config(extension_name)
|
15
|
+
create_makefile(extension_name)
|
16
|
+
|
17
|
+
else
|
18
|
+
|
19
|
+
File.open("Makefile", "w") do |f|
|
20
|
+
f.write "install:\n\t:\n"
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
data/ext/interception.c
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
|
3
|
+
static VALUE rb_mInterception;
|
4
|
+
|
5
|
+
#ifdef RUBY_19
|
6
|
+
|
7
|
+
void
|
8
|
+
interception_hook(rb_event_flag_t evflag, VALUE data, VALUE self, ID mid, VALUE klass)
|
9
|
+
{
|
10
|
+
VALUE binding = rb_funcall(rb_mKernel, rb_intern("binding"), 0, NULL);
|
11
|
+
rb_funcall(rb_mInterception, rb_intern("rescue"), 2, rb_errinfo(), binding);
|
12
|
+
}
|
13
|
+
|
14
|
+
VALUE
|
15
|
+
interception_start(VALUE self)
|
16
|
+
{
|
17
|
+
rb_add_event_hook(interception_hook, RUBY_EVENT_RAISE, rb_mInterception);
|
18
|
+
}
|
19
|
+
|
20
|
+
#else
|
21
|
+
|
22
|
+
#include "node.h"
|
23
|
+
|
24
|
+
void
|
25
|
+
interception_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
|
26
|
+
{
|
27
|
+
VALUE binding = rb_funcall(rb_mKernel, rb_intern("binding"), 0, NULL);
|
28
|
+
rb_funcall(rb_mInterception, rb_intern("rescue"), 2, ruby_errinfo, binding);
|
29
|
+
}
|
30
|
+
|
31
|
+
VALUE
|
32
|
+
interception_start(VALUE self)
|
33
|
+
{
|
34
|
+
rb_add_event_hook(interception_hook, RUBY_EVENT_RAISE);
|
35
|
+
}
|
36
|
+
|
37
|
+
#endif
|
38
|
+
|
39
|
+
VALUE
|
40
|
+
interception_stop(VALUE self)
|
41
|
+
{
|
42
|
+
rb_remove_event_hook(interception_hook);
|
43
|
+
return Qnil;
|
44
|
+
}
|
45
|
+
|
46
|
+
void
|
47
|
+
Init_interception()
|
48
|
+
{
|
49
|
+
rb_mInterception = rb_define_module("Interception");
|
50
|
+
rb_define_singleton_method(rb_mInterception, "start", interception_start, 0);
|
51
|
+
rb_define_singleton_method(rb_mInterception, "stop", interception_start, 0);
|
52
|
+
}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
package org.pryrepl;
|
2
|
+
|
3
|
+
import org.jruby.runtime.builtin.IRubyObject;
|
4
|
+
import org.jruby.runtime.EventHook;
|
5
|
+
import org.jruby.runtime.RubyEvent;
|
6
|
+
import org.jruby.runtime.ThreadContext;
|
7
|
+
import org.jruby.RubyException;
|
8
|
+
import org.jruby.RubyBinding;
|
9
|
+
import org.jruby.RubyProc;
|
10
|
+
|
11
|
+
public class InterceptionEventHook extends EventHook {
|
12
|
+
|
13
|
+
private RubyProc proc;
|
14
|
+
|
15
|
+
public InterceptionEventHook(RubyProc proc) {
|
16
|
+
super();
|
17
|
+
this.proc = proc;
|
18
|
+
}
|
19
|
+
|
20
|
+
public boolean isInterestedInEvent(RubyEvent event) {
|
21
|
+
return event.getName().equals(RubyEvent.RAISE.getName());
|
22
|
+
}
|
23
|
+
|
24
|
+
public void eventHandler(ThreadContext context, String eventName, String file, int line, String name, IRubyObject type) {
|
25
|
+
RubyBinding binding = RubyBinding.newBinding(context.runtime, context.currentBinding());
|
26
|
+
RubyException exception = (RubyException)context.runtime.getGlobalVariables().get("$!");
|
27
|
+
proc.call(context, new IRubyObject[] {exception, binding});
|
28
|
+
}
|
29
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "interception"
|
3
|
+
s.version = "0.1.pre.1"
|
4
|
+
s.author = "Conrad Irwin"
|
5
|
+
s.email = "conrad.irwin@gmail.com"
|
6
|
+
s.homepage = "http://github.com/ConradIrwin/interception"
|
7
|
+
s.summary = "Intercept exceptions as they are being raised"
|
8
|
+
s.description = "Provides a cross-platform ability to intercept all exceptions as they are raised."
|
9
|
+
|
10
|
+
s.files = `git ls-files`.split("\n")
|
11
|
+
s.extensions = "ext/extconf.rb"
|
12
|
+
s.require_path = "lib"
|
13
|
+
|
14
|
+
s.add_development_dependency 'rake'
|
15
|
+
end
|
data/lib/interception.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'thread'
|
2
|
+
|
3
|
+
module Interception
|
4
|
+
|
5
|
+
class << self
|
6
|
+
attr_accessor :mutex, :listeners
|
7
|
+
end
|
8
|
+
|
9
|
+
self.mutex = Mutex.new
|
10
|
+
self.listeners = []
|
11
|
+
|
12
|
+
def self.listen(for_block=nil, &listen_block)
|
13
|
+
raise "no block given" unless listen_block || for_block
|
14
|
+
mutex.synchronize{
|
15
|
+
listeners << listen_block || for_block
|
16
|
+
start
|
17
|
+
}
|
18
|
+
|
19
|
+
if listen_block && for_block
|
20
|
+
begin
|
21
|
+
for_block.call
|
22
|
+
ensure
|
23
|
+
unlisten listen_block
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.unlisten(listen_block)
|
29
|
+
mutex.synchronize{
|
30
|
+
listeners.delete listen_block
|
31
|
+
stop if listeners.empty?
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.rescue(e, binding)
|
36
|
+
listeners.each do |l|
|
37
|
+
l.call(e, binding)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
if defined? Rubinius
|
42
|
+
def self.start
|
43
|
+
class << Rubinius
|
44
|
+
alias raise_with_no_interception raise_exception
|
45
|
+
|
46
|
+
def raise_exception(exc)
|
47
|
+
bt = Rubinius::VM.backtrace(1, true).drop_while do |x|
|
48
|
+
x.variables.method.file.to_s.start_with?("kernel/")
|
49
|
+
end.first
|
50
|
+
b = Binding.setup(bt.variables, bt.variables.method, bt.constant_scope, bt.variables.self, bt)
|
51
|
+
|
52
|
+
Interception.rescue(exc, b)
|
53
|
+
raise_with_no_interception(exc)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.stop
|
59
|
+
class << Rubinius
|
60
|
+
alias raise_exception raise_with_no_interception
|
61
|
+
end
|
62
|
+
end
|
63
|
+
elsif defined?(JRuby)
|
64
|
+
$CLASSPATH << File.expand_path('../../ext/', __FILE__)
|
65
|
+
java_import org.pryrepl.InterceptionEventHook
|
66
|
+
|
67
|
+
def self.start
|
68
|
+
JRuby.runtime.add_event_hook(hook)
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.stop
|
72
|
+
JRuby.runtime.remove_event_hook(hook)
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.hook
|
76
|
+
@hook ||= InterceptionEventHook.new(proc do |e, b|
|
77
|
+
self.rescue(e, b)
|
78
|
+
end)
|
79
|
+
end
|
80
|
+
|
81
|
+
else
|
82
|
+
require File.expand_path('../../ext/interception.so', __FILE__)
|
83
|
+
end
|
84
|
+
end
|
metadata
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: interception
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: 4
|
5
|
+
version: 0.1.pre.1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Conrad Irwin
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-08-11 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
version_requirements: &2056 !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ! '>='
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
21
|
+
none: false
|
22
|
+
requirement: *2056
|
23
|
+
prerelease: false
|
24
|
+
type: :development
|
25
|
+
description: Provides a cross-platform ability to intercept all exceptions as they are raised.
|
26
|
+
email: conrad.irwin@gmail.com
|
27
|
+
executables: []
|
28
|
+
extensions:
|
29
|
+
- ext/extconf.rb
|
30
|
+
extra_rdoc_files: []
|
31
|
+
files:
|
32
|
+
- .gitignore
|
33
|
+
- ext/extconf.rb
|
34
|
+
- ext/interception.c
|
35
|
+
- ext/org/pryrepl/InterceptionEventHook.java
|
36
|
+
- interception.gemspec
|
37
|
+
- lib/interception.rb
|
38
|
+
homepage: http://github.com/ConradIrwin/interception
|
39
|
+
licenses: []
|
40
|
+
post_install_message:
|
41
|
+
rdoc_options: []
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ! '>='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
none: false
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ! '>'
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.3.1
|
55
|
+
none: false
|
56
|
+
requirements: []
|
57
|
+
rubyforge_project:
|
58
|
+
rubygems_version: 1.8.15
|
59
|
+
signing_key:
|
60
|
+
specification_version: 3
|
61
|
+
summary: Intercept exceptions as they are being raised
|
62
|
+
test_files: []
|
63
|
+
...
|