forked from mirrors/0ad
Improve JS Exception handling.
- Check for pending exceptions after function calls and script executions. - Call LOGERROR instead of JS_ReportError when there is a conversion error in FromJSVal, since that can only be called from C++ (where JS errors don't really make sense). Instead, C++ callers of FromJSVal should handle the failure and, themselves, either report an error or simply do something else. - Wrap JS_ReportError since that makes updating it later easier. This isn't a systematical fix since ToJSVal also ought return a boolean for failures, and we probably should trigger errors instead of warnings on 'implicit' conversions, rather a preparation diff. Part of the SM52 migration, stage: SM45 compatible (actually SM52 incompatible, too). Based on a patch by: Itms Comments by: Vladislavbelov, Stan` Refs #742, #4893 Differential Revision: https://code.wildfiregames.com/D3093 This was SVN commit r24187.
This commit is contained in:
@@ -90,51 +90,6 @@ void GCSliceCallbackHook(JSRuntime* UNUSED(rt), JS::GCProgress progress, const J
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
void ErrorReporter(JSContext* cx, const char* message, JSErrorReport* report)
|
||||
{
|
||||
ScriptInterface::Request rq(*ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface);
|
||||
|
||||
std::stringstream msg;
|
||||
bool isWarning = JSREPORT_IS_WARNING(report->flags);
|
||||
msg << (isWarning ? "JavaScript warning: " : "JavaScript error: ");
|
||||
if (report->filename)
|
||||
{
|
||||
msg << report->filename;
|
||||
msg << " line " << report->lineno << "\n";
|
||||
}
|
||||
|
||||
msg << message;
|
||||
|
||||
// If there is an exception, then print its stack trace
|
||||
JS::RootedValue excn(rq.cx);
|
||||
if (JS_GetPendingException(rq.cx, &excn) && excn.isObject())
|
||||
{
|
||||
JS::RootedValue stackVal(rq.cx);
|
||||
JS::RootedObject excnObj(rq.cx, &excn.toObject());
|
||||
JS_GetProperty(rq.cx, excnObj, "stack", &stackVal);
|
||||
|
||||
std::string stackText;
|
||||
ScriptInterface::FromJSVal(rq, stackVal, stackText);
|
||||
|
||||
std::istringstream stream(stackText);
|
||||
for (std::string line; std::getline(stream, line);)
|
||||
msg << "\n " << line;
|
||||
}
|
||||
|
||||
if (isWarning)
|
||||
LOGWARNING("%s", msg.str().c_str());
|
||||
else
|
||||
LOGERROR("%s", msg.str().c_str());
|
||||
|
||||
// When running under Valgrind, print more information in the error message
|
||||
// VALGRIND_PRINTF_BACKTRACE("->");
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
shared_ptr<ScriptContext> ScriptContext::CreateContext(int contextSize, int heapGrowthBytesGCTrigger)
|
||||
{
|
||||
return shared_ptr<ScriptContext>(new ScriptContext(contextSize, heapGrowthBytesGCTrigger));
|
||||
@@ -161,6 +116,7 @@ ScriptContext::ScriptContext(int contextSize, int heapGrowthBytesGCTrigger):
|
||||
// We disable it to make it more clear if full GCs happen triggered by this JSAPI internal mechanism.
|
||||
JS_SetGCParameter(m_rt, JSGC_DYNAMIC_HEAP_GROWTH, false);
|
||||
|
||||
JS_SetErrorReporter(m_rt, ScriptException::ErrorReporter);
|
||||
|
||||
m_cx = JS_NewContext(m_rt, STACK_CHUNK_SIZE);
|
||||
ENSURE(m_cx); // TODO: error handling
|
||||
@@ -172,8 +128,6 @@ ScriptContext::ScriptContext(int contextSize, int heapGrowthBytesGCTrigger):
|
||||
|
||||
JS_SetContextPrivate(m_cx, nullptr);
|
||||
|
||||
JS_SetErrorReporter(m_rt, ErrorReporter);
|
||||
|
||||
JS_SetGlobalJitCompilerOption(m_rt, JSJITCOMPILER_ION_ENABLE, 1);
|
||||
JS_SetGlobalJitCompilerOption(m_rt, JSJITCOMPILER_BASELINE_ENABLE, 1);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user