2014-10-05 84 views
4
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 

控制檯輸出:獲取Ruby異常

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對象?

+0

如果正在閱讀您的問題,您想知道如何訪問您的Ruby代碼中調用它的JavaScript異常? – Doon 2014-10-05 23:51:28

+0

我用'扔'而不是'提高'。就這樣。 – Jacob 2014-10-06 21:26:14

回答

2

你可能沒有做什麼你認爲你正在做的(NotImplementedError是作秀,這將包含一個消息等自定義異常被替換)。 throw關鍵字不適用於例外。它實際上是一種類似於其他語言的goto的本地跳轉。看到這個片斷:

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

這僅僅是一個控制流結構,其中「中招」對象必須在「拋出」相匹配。但是,你不能簡單地抓住所有的投擲,並找出它是哪個對象。對於例外情況(如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彈出。

+0

我知道Ruby的加註和JavaScript的拋出,但顯然我並沒有完全清醒。非常感謝你指出。 另外,我並沒有幫助我在Ruby之前幾年寫了C#,它也使用'throw'作爲JavaScript :-) – Jacob 2014-10-06 07:05:17