blob: 29bf4106a1b4b809810ea114f185277eb8f8840b (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
require 'continuation' if RUBY_VERSION.to_f >= 1.9
class Exception
attr_accessor :continuation
def restart(&block)
continuation.call block
end
end
module RaisePlus
alias :original_raise :raise
private
def raise(*args)
exception = case
when args.size == 0
$!.nil? ? RuntimeError.exception : $!
when args.size == 1 && args[0].is_a?(String)
RuntimeError.exception(args[0])
when args.size == 2 && args[0].is_a?(Exception)
args[0].exception(args[1])
when args[0].is_a?(Class) && args[0].ancestors.include?(Exception)
args[0].exception(args[1])
else
args[0]
end
# passing something other than a String or Exception is illegal, but if someone does it anyway,
# that object won't have backtrace or continuation methods. in that case, let's pass it on to
# the original raise, which will reject it
return super exception unless exception.is_a?(Exception)
# keep original backtrace if reraising
exception.set_backtrace(args.size >= 3 ? args[2] : caller) if exception.backtrace.nil?
blk = callcc do |cc|
exception.continuation = cc
super exception
end
blk.call unless blk.nil?
end
alias :fail :raise
end
|