Search code examples
javascriptwxwidgetsxulrunner

Find and report Javascript compilation errors in XULRunner using nsIScriptContext or the SpiderMonkey API


I have an experimental version of wxWebConnect (embedding XULRunner in wxWidgets) at https://github.com/jonmmorgan/wxwebconnect/. It offers a method

wxString wxWebControl::ExecuteScriptWithResult(const wxString& js_code)

which executes the Javascript string using nsIScriptContext::EvaluateStringWithValue, converts the value to a string with JS_ValueToString, and then returns the string.

However, I found with the current implementation that if the Javascript string is syntactically invalid (e.g. WebControl.ExecuteScriptWithResult('{a:2')) then the program would crash when trying to convert the result to a string. I discovered the aIsUndefined parameter, which I can use to determine whether script execution succeeded or not and prevent the crash. However, this doesn't help me find what the actual error was, and I think it would be good to report that (like Firebug tells me "SyntaxError: missing } in compound statement"). As far as I can see, even using something like nsIScriptContext::CompileScript will just tell me whether the compilation succeeded or not, and doesn't give me a way to get at the actual syntax error.

Following http://chadaustin.me/2009/02/evaluating-javascript-in-an-embedded-xulrunnergecko-window/, I tried using JS_GetPendingException, but it never seems to return true. Even when I run webcontrol.ExecuteScriptWithResult("throw new Error('a');") it still doesn't have a pending exception, but does say the result is undefined.

Is there any other good way to get a compilation or execution error from nsIScriptContext or the SpiderMonkey API? Any idea why JS_GetPendingException doesn't seem to do this?


Solution

  • I have actually found an answer to this: In nsJSContext, it registers an error reporter function. As part of that error reporter function, it clears pending exceptions. If you register your own error reporter it overrides that and allows you to actually do something with the error. This does mean that your error won't turn up in the Error Console. I don't know if you lose any other important functionality by overriding the builtin error handler.