【发布时间】:2014-03-21 21:45:26
【问题描述】:
下面的代码定义了一个钩子 Kernel#at_exit 来捕获异常并在退出时执行操作,然后通过传递无效的 SASS 字符串引发 Sass::SyntaxError。
require "sass"
module Kernel
at_exit do
puts "--Before backtrace"
p $!
$!.backtrace
puts "--After backtrace"
p $!
end
end
Sass::Engine.new("Invalid {sass").render
它给出的输出如下:
...
--Before backtrace
#<Sass::SyntaxError: ...>
--After backtrace
nil
...
这表明$! 是一个Sass::SyntaxError,但是在调用backtrace 之后它就变成了nil。为什么$! 只调用backtrace 就改变了?
如下手动引发Sass::SyntaxError时似乎不会出现这种效果:
raise Sass::SyntaxError.new("foo")
或者当出现不同类型的错误时(可能是错误的)。
编辑
我不确定,但当引发 sass 错误时,sass 可能会使用 set_backtrace 操纵回溯。这是为了提供有关在 sass 文件中导致 sass 语法错误的位置的信息。手动引发错误和以编程方式引发错误之间的不同行为让人想起 Ruby 2.1 中的一个错误,该错误中途实现了backtrace_locations,但在某些情况下返回了nil。我大致猜测这些因素会造成干扰,但不确定。
【问题讨论】:
-
非常好的问题,我正在研究它,但没有任何线索。 BTW:你不需要打开内核模块来调用
at_exit -
@ArupRakshit - 你得到了运行时错误,而不是 Sass::SyntaxError 错误 - 那里抛出了其他东西。
-
@sawa - 关于您的更新:我刚刚创建了自己的异常类,它非常模仿
Sass::SyntaxError回溯方法,但它按预期工作。不过,我无法想象这将如何清除 $!变量。 -
好的,再看一点:
at_exit { p $@; p $@ }也返回不同的值(一个数组和 nil)。 -
看来你是对的 - 这是由这种摆弄引起的,我的异常还不够接近,无法捕捉到它。我会在一分钟内发布答案。