Bug 968936 - Emit a warning message with stack trace when the "operation callback" (slow script dialog) stops script execution. r=luke.

This commit is contained in:
Jason Orendorff 2014-02-26 08:55:35 -06:00
parent 09e170d3ff
commit 4211f16e24
4 changed files with 30 additions and 22 deletions

View File

@ -435,3 +435,4 @@ MSG_DEF(JSMSG_INVALID_PROTOTYPE, 380, 0, JSEXN_TYPEERR, "prototype field
MSG_DEF(JSMSG_TYPEDOBJECT_HANDLE_TO_UNSIZED, 381, 0, JSEXN_TYPEERR, "cannot create a handle to an unsized type")
MSG_DEF(JSMSG_SETPROTOTYPEOF_FAIL, 382, 1, JSEXN_TYPEERR, "[[SetPrototypeOf]] failed on {0}")
MSG_DEF(JSMSG_INVALID_ARG_TYPE, 383, 3, JSEXN_TYPEERR, "Invalid type: {0} can't be a{1} {2}")
MSG_DEF(JSMSG_TERMINATED, 384, 1, JSEXN_ERR, "Script terminated by timeout at:\n{0}")

View File

@ -1008,17 +1008,13 @@ js_InvokeOperationCallback(JSContext *cx)
JSRuntime *rt = cx->runtime();
JS_ASSERT(rt->interrupt);
/*
* Reset the callback counter first, then run GC and yield. If another
* thread is racing us here we will accumulate another callback request
* which will be serviced at the next opportunity.
*/
// Reset the callback counter first, then run GC and yield. If another
// thread is racing us here we will accumulate another callback request
// which will be serviced at the next opportunity.
rt->interrupt = false;
/*
* IonMonkey sets its stack limit to UINTPTR_MAX to trigger operation
* callbacks.
*/
// IonMonkey sets its stack limit to UINTPTR_MAX to trigger operation
// callbacks.
rt->resetIonStackLimit();
js::gc::GCIfNeeded(cx);
@ -1028,20 +1024,28 @@ js_InvokeOperationCallback(JSContext *cx)
rt->interruptPar = false;
#endif
/*
* A worker thread may have set the callback after finishing an Ion
* compilation.
*/
// A worker thread may have set the callback after finishing an Ion
// compilation.
jit::AttachFinishedCompilations(cx);
#endif
/*
* Important: Additional callbacks can occur inside the callback handler
* if it re-enters the JS engine. The embedding must ensure that the
* callback is disconnected before attempting such re-entry.
*/
// Important: Additional callbacks can occur inside the callback handler
// if it re-enters the JS engine. The embedding must ensure that the
// callback is disconnected before attempting such re-entry.
JSOperationCallback cb = cx->runtime()->operationCallback;
return !cb || cb(cx);
if (!cb || cb(cx))
return true;
// No need to set aside any pending exception here: ComputeStackString
// already does that.
Rooted<JSString*> stack(cx, ComputeStackString(cx));
const jschar *chars = stack ? stack->getCharsZ(cx) : nullptr;
if (!chars)
chars = MOZ_UTF16("(stack not available)");
JS_ReportErrorFlagsAndNumberUC(cx, JSREPORT_WARNING, js_GetErrorMessage, nullptr,
JSMSG_TERMINATED, chars);
return false;
}
bool

View File

@ -202,8 +202,8 @@ struct SuppressErrorsGuard
}
};
static JSString *
ComputeStackString(JSContext *cx)
JSString *
js::ComputeStackString(JSContext *cx)
{
StringBuffer sb(cx);

View File

@ -17,8 +17,11 @@
namespace js {
class ErrorObject;
extern JSErrorReport *
JSErrorReport *
CopyErrorReport(JSContext *cx, JSErrorReport *report);
JSString *
ComputeStackString(JSContext *cx);
}
/*