Skip to content

Instantly share code, notes, and snippets.

@mihaisucan
Created October 26, 2010 16:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mihaisucan/647260 to your computer and use it in GitHub Desktop.
Save mihaisucan/647260 to your computer and use it in GitHub Desktop.
void
DOMWorkerErrorReporter(JSContext* aCx,
const char* aMessage,
JSErrorReport* aReport)
{
NS_ASSERTION(!NS_IsMainThread(), "Huh?!");
nsDOMWorker* worker = (nsDOMWorker*)JS_GetContextPrivate(aCx);
if (worker->IsCanceled()) {
// We don't want to report errors from canceled workers. It's very likely
// that we only returned an error in the first place because the worker was
// already canceled.
return;
}
if (worker->mErrorHandlerRecursionCount == 2) {
// We've somehow ended up in a recursive onerror loop. Bail out.
return;
}
nsresult rv;
nsCOMPtr<nsIScriptError> scriptError;
{
// CreateInstance will lock, make sure we suspend our request!
JSAutoSuspendRequest ar(aCx);
scriptError = do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
}
if (NS_FAILED(rv)) {
return;
}
nsCOMPtr<nsIScriptError2> scriptError2(do_QueryInterface(scriptError));
PRUint64 windowID = 0;
// NEW code:
nsIScriptGlobalObject *globalObject = worker->Pool()->ScriptGlobalObject();
if (globalObject) {
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(globalObject);
if (win) {
windowID = win->WindowID();
}
}
nsAutoString message, filename, line;
PRUint32 lineNumber, columnNumber, flags, errorNumber;
if (aReport) {
if (aReport->ucmessage) {
message.Assign(reinterpret_cast<const PRUnichar*>(aReport->ucmessage));
}
filename.AssignWithConversion(aReport->filename);
line.Assign(reinterpret_cast<const PRUnichar*>(aReport->uclinebuf));
lineNumber = aReport->lineno;
columnNumber = aReport->uctokenptr - aReport->uclinebuf;
flags = aReport->flags;
errorNumber = aReport->errorNumber;
}
else {
lineNumber = columnNumber = errorNumber = 0;
flags = nsIScriptError::errorFlag | nsIScriptError::exceptionFlag;
}
if (message.IsEmpty()) {
message.AssignWithConversion(aMessage);
}
if (scriptError2) {
// new code
rv = scriptError2->InitWithWindowID(message.get(), filename.get(), line.get(),
lineNumber, columnNumber, flags,
"DOM Worker javascript", windowID);
}
else {
rv = scriptError->Init(message.get(), filename.get(), line.get(),
lineNumber, columnNumber, flags,
"DOM Worker javascript");
}
if (NS_FAILED(rv)) {
return;
}
// Don't call the error handler if we're out of stack space.
if (errorNumber != JSMSG_SCRIPT_STACK_QUOTA &&
errorNumber != JSMSG_OVER_RECURSED) {
// Try the onerror handler for the worker's scope.
nsRefPtr<nsDOMWorkerScope> scope = worker->GetInnerScope();
NS_ASSERTION(scope, "Null scope!");
PRBool hasListeners = scope->HasListeners(NS_LITERAL_STRING("error"));
if (hasListeners) {
nsRefPtr<nsDOMWorkerErrorEvent> event(new nsDOMWorkerErrorEvent());
if (event) {
rv = event->InitErrorEvent(NS_LITERAL_STRING("error"), PR_FALSE,
PR_TRUE, nsDependentString(message),
filename, lineNumber);
if (NS_SUCCEEDED(rv)) {
event->SetTarget(scope);
NS_ASSERTION(worker->mErrorHandlerRecursionCount >= 0,
"Bad recursion count logic!");
worker->mErrorHandlerRecursionCount++;
PRBool preventDefaultCalled = PR_FALSE;
scope->DispatchEvent(static_cast<nsDOMWorkerEvent*>(event),
&preventDefaultCalled);
worker->mErrorHandlerRecursionCount--;
if (preventDefaultCalled) {
return;
}
}
}
}
}
// Still unhandled, fire at the onerror handler on the worker.
nsCOMPtr<nsIRunnable> runnable =
new nsReportErrorRunnable(worker, scriptError);
NS_ENSURE_TRUE(runnable,);
nsRefPtr<nsDOMWorker> parent = worker->GetParent();
// If this worker has a parent then we need to send the message through the
// thread service to be run on the parent's thread. Otherwise it is a
// top-level worker and we send the message to the main thread.
rv = parent ? nsDOMThreadService::get()->Dispatch(parent, runnable)
: NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL);
if (NS_FAILED(rv)) {
return;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment