Is it safe to throw exceptions inside JSNative, when it call from JS?
For example, if i ./configure tracemonkey with --enable-cpp-
exceptions, will it be ok?
Does tracemonkey support C++ exceptions (i mean correct memory
freeing, etc)?
If not, i assume that the strategy must be:
JSnative() {
try {
} catch {
JS_SendPengingException();
return JS_FALSE;
}
return JS_TRUE;
}
Example:
script.js
throw "JS_EXCEPTION";
C code:
JS_ExecuteSqript(context, .../*precomiled script for scriptjs*/);
if (JS_IsExceptionPending(context)) {
// i think i must be there. but there is no exception on context.
}
> Is it safe to throw exceptions inside JSNative, when it call from JS?
No. The Spidermonkey code is not C++-exception-safe at all.
> If not, i assume that the strategy must be:
>
> JSnative() {
> try {
>
> } catch {
> JS_SendPengingException();
> return JS_FALSE;
> }
> return JS_TRUE;
> }
Yes, exactly. Most SM embedders do not use C++ exceptions, and propagate
errors using return codes or other methods.
--BDS
If you want to get exceptions from outermost API call, you must set
option JSOPTION_DONT_REPORT_UNCAUGHT.
https://developer.mozilla.org/en/SpiderMonkey/JSAPI_Reference/JS_SetOptions
If this option is not set, then js exception will be reported and
cleared (as in following backtrace)
[Switching to Thread -1213303104 (LWP 14466)]
Breakpoint 3, JS_ClearPendingException (cx=0x8827b20) at jsapi.cpp:
5725
5725 cx->throwing = JS_FALSE;
(gdb) bt
#0 JS_ClearPendingException (cx=0x8827b20) at jsapi.cpp:5725
#1 0xb7ba4b4f in js_ReportUncaughtException (cx=0x8827b20) at
jsexn.cpp:1243
#2 0xb7b53f1c in JS_ExecuteScript (cx=0x8827b20, obj=0x8849000,
script=0x8858650, rval=0xbf8f476c) at jsapi.cpp:4946
That is definitely incorrect. Just because you can compile the code
with -fexceptions doesn't mean the API contract supports throwing
exceptions across API boundaries!
Throwing bypasses all cleanup actions, not just freeing memory. In
SpiderMonkey this includes things like unwinding the JS stack or
removing stack variables from the GC's root set. Skipping that kind of
cleanup would be Bad. So when the User Guide says, "JSAPI functions
never throw C++ exceptions, and when SpiderMonkey calls an application
callback, the callback must not throw a C++ exception.", it really
means that.
Why do we have --enable-cpp-exceptions then? I hacked it in because my
initial jsapi-tests runner used C++ exceptions (in code that was
outside all JSAPI calls).
> Is there any plans
> to make tracemonkey/spidermonkey exception-safe? Can I help somehow
> with that?
Well, there are no immediate plans, but it would be useful. The desired
semantics would be:
* JSAPI callbacks that currently can't fail, like JSClass.mark,
must not throw (we can enforce this with assertions in the engine)
* JSAPI callbacks like JSNative and JSPropertyOp may throw,
in which case the JS stack is unwound as for out-of-memory[1].
* The JS engine still never throws any exceptions of its own,
so the only way a JSAPI function can throw is if the application
threw that exception itself.
* The JS engine never catches any exceptions thrown by callbacks.
If you want to help, here's what a plan would look like:
1. Wait for bug 516832 and bug 523765 to be fixed. These will remove a
significant amount of post-error cleanup code.
2. RAII-ify the remaining TempValueRooter uses.
3. Look for other places where we do stuff after an error and find ways
to RAII-ify them. (Start by searching for goto; many but not all gotos
in SpiderMonkey are for cleanup.)
4. Write JSAPI tests for a variety of situations where C++ JSNatives
and other callbacks throw exceptions. Fuzz-test. Fix any remaining bugs.
Go for it.
-j
[1]
https://developer.mozilla.org/En/SpiderMonkey/JSAPI_User_Guide#Uncatchable_errors