bool WrapperAnswer::fail(AutoJSAPI& jsapi, ReturnStatus* rs) { // By default, we set |undefined| unless we can get a more meaningful // exception. *rs = ReturnStatus(ReturnException(JSVariant(UndefinedVariant()))); // Note we always return true from this function, since this propagates // to the IPC code, and we don't want a JS failure to cause the death // of the child process. JSContext* cx = jsapi.cx(); RootedValue exn(cx); if (!jsapi.HasException()) return true; jsapi.StealException(&exn); if (JS_IsStopIteration(exn)) { *rs = ReturnStatus(ReturnStopIteration()); return true; } // If this fails, we still don't want to exit. Just return an invalid // exception. (void) toVariant(cx, exn, &rs->get_ReturnException().exn()); return true; }
void ProfileGatherer::Finish() { MOZ_ASSERT(NS_IsMainThread()); if (!mTicker) { // We somehow got called after we were cancelled! This shouldn't // be possible, but doing a belt-and-suspenders check to be sure. return; } UniquePtr<char[]> buf = mTicker->ToJSON(mSinceTime); nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService(); if (os) { DebugOnly<nsresult> rv = os->RemoveObserver(this, "profiler-subprocess"); NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "RemoveObserver failed"); } AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(mPromise->GlobalJSObject()))) { // We're really hosed if we can't get a JS context for some reason. Reset(); return; } JSContext* cx = jsapi.cx(); // Now parse the JSON so that we resolve with a JS Object. JS::RootedValue val(cx); { NS_ConvertUTF8toUTF16 js_string(nsDependentCString(buf.get())); if (!JS_ParseJSON(cx, static_cast<const char16_t*>(js_string.get()), js_string.Length(), &val)) { if (!jsapi.HasException()) { mPromise->MaybeReject(NS_ERROR_DOM_UNKNOWN_ERR); } else { JS::RootedValue exn(cx); DebugOnly<bool> gotException = jsapi.StealException(&exn); MOZ_ASSERT(gotException); jsapi.ClearException(); mPromise->MaybeReject(cx, exn); } } else { mPromise->MaybeResolve(val); } } Reset(); }