Node-API-JSI: rethrow native errors from host functions as their JS value - #252
Open
matthargett wants to merge 2 commits into
Open
matthargett wants to merge 2 commits into
matthargett wants to merge 2 commits into
Conversation
…alue
Native code throws Napi::Error, a C++ exception carrying the JavaScript
error object. JSI reports any std::exception that escapes a host
function as a fresh Error("Exception in HostFunction: " + what()), so
on the JSI backend a polyfill's TypeError reached scripts as a plain
Error with a prefixed message: `instanceof TypeError` was false and
messages no longer compared equal, unlike every other backend.
Route every host-function trampoline (Function::New callbacks, class
constructors, static and instance methods and accessors) through a
helper that catches Napi::Error and rethrows jsi::JSError with the
original value, the same conversion Napi::Eval already does in the
other direction (BabylonJS#246).
Regression test: "native exceptions reach scripts as the thrown error
object, with its class and message, on every engine".
JS-to-native callbacks can report an error either by throwing Napi::Error or by calling ThrowAsJavaScriptException, which records an exception in the environment. The JSI trampoline converted only the first form, allowing pending exceptions to escape their JavaScript call site and surface later as uncaught dispatcher failures.\n\nCheck and clear the pending slot before every JSI host callback returns, then throw its original JavaScript value through JSI. Add a reentrant callback regression that exercises the pending-exception form without depending on a particular polyfill.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On the JSI backend, an error thrown by native code — every
Napi::TypeError/RangeError/Errora polyfill raises — reaches scripts as a genericError("Exception in HostFunction: <message>"): JSI wraps anystd::exceptionescaping a host function that way.e instanceof TypeErroris false ande.messagecarries the prefix, unlike every other backend. #251's twin hit exactly this (expected [Function] to throw TypeError but Error: Exception in HostFunction: URL.createObjectURL: argument is not a Blob was thrown), andtests.tsalready carries a comment working around the prefix.Change
Every host-function trampoline in
Core/Node-API-JSI/Include/napi/napi-inl.h(Function::Newcallbacks, class constructors, static/instance methods and accessors) now runs throughdetails::CallHost, which catchesNapi::Errorand rethrowsjsi::JSErrorwith the original JS value — the same conversionNapi::Evalalready performs in the other direction (#246). JSI propagates aJSError's value unchanged, so scripts observe the same exception on JSI as elsewhere.Regression test (
native exceptionssuite): aTypeErrorfrom a static method and one from a constructor arrive asTypeErrorwith their message and noHostFunctionprefix. Passes on JavaScriptCore locally; the fork twin exercises the JSI matrix. Fork twin: rebeckerspecialties#36.