从V8上下文获取ruby异常

时间:2014-10-05 18:57:27

标签: ruby v8 therubyracer

context = V8::Context.new(timeout: 20000) do |context|
  context['ForbidAccess'] = ->(message) { throw NotImplementedError }
end

begin
  context.eval("ForbidAccess();")
rescue => e
  puts "e.class = #{e.class.name}"
  puts "e.causes = #{e.causes}"
  puts "e.root_cause = #{e.root_cause}"
  puts "e.root_cause.class = #{e.root_cause.class}"
end

控制台输出:

e.class = V8::Error
e.causes = [#<V8::Error: uncaught throw NotImplementedError>, #<ArgumentError: uncaught throw NotImplementedError>]
e.root_cause = uncaught throw NotImplementedError
e.root_cause.class = ArgumentError

如何访问NotImplementedError对象?

(NotImplementedError仅用于show。它将替换为包含消息等的自定义异常。)

1 个答案:

答案 0 :(得分:2)

你可能没有做你认为自己在做的事情。 throw关键字不适用于例外情况。它实际上是一种类似于其他语言的goto的局部跳转。请参阅以下代码段:

catch :done do
  while true
    array = [1,2,3]
    for i in array
      if i > 2
        throw :done
      end
    end
  end
end

这只是一个控制流程结构,其中&#34;捕获&#34;对象必须匹配&#34;抛出&#34;一。但你不能简单地抓住所有的投掷并弄清楚它是哪个物体。对于例外(例如NotImplementedError),正确使用的是raise

context = V8::Context.new(timeout: 20000) do |context|
  context['ForbidAccess'] = ->(message) { raise NotImplementedError }
end

begin
  context.eval("ForbidAccess();")
rescue => e
  puts "e.root_cause = #{e.root_cause.inspect}"
  # correctly prints #<NotImplementedError: NotImplementedError>
end

至于为什么你会看到ArgumentError,这很简单:投掷无法通过begin - rescue结构(从例外中拯救)。当未被捕获的投掷遇到救援时,会创建一个关于它的新例外。检查以下内容:

begin
  throw "whatever"
rescue e
  p e   #=> ArgumentError: uncaught throw "whatever"
end

internally会发生这种情况,并且所有V8库都会弹出ArgumentError