/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
class WorkletJSRuntime final : public mozilla::CycleCollectedJSRuntime { public: explicit WorkletJSRuntime(JSContext* aCx) : CycleCollectedJSRuntime(aCx) {}
virtualvoid CustomGCCallback(JSGCStatus aStatus) override { // nsCycleCollector_collect() requires a cycle collector but // ~WorkletJSContext calls nsCycleCollector_shutdown() and the base class // destructor will trigger a final GC. The nsCycleCollector_collect() // call can be skipped in this GC as ~CycleCollectedJSContext removes the // context from |this|. if (aStatus == JSGC_END && GetContext()) {
nsCycleCollector_collect(CCReason::GC_FINISHED, nullptr);
}
}
};
class WorkletJSContext final : public CycleCollectedJSContext { public:
WorkletJSContext() {
MOZ_ASSERT(!NS_IsMainThread());
nsCycleCollector_startup();
}
// MOZ_CAN_RUN_SCRIPT_BOUNDARY because otherwise we have to annotate the // SpiderMonkey JS::JobQueue's destructor as MOZ_CAN_RUN_SCRIPT, which is a // bit of a pain.
MOZ_CAN_RUN_SCRIPT_BOUNDARY ~WorkletJSContext() override {
MOZ_ASSERT(!NS_IsMainThread());
JSContext* cx = MaybeContext(); if (!cx) { return; // Initialize() must have failed
}
void WorkletJSContext::ReportError(JSErrorReport* aReport,
JS::ConstUTF8CharsZ aToStringResult) {
RefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport();
xpcReport->Init(aReport, aToStringResult.c_str(), IsSystemCaller(),
GetCurrentWorkletWindowID());
RefPtr<AsyncErrorReporter> reporter = new AsyncErrorReporter(xpcReport);
JSContext* cx = Context(); if (JS_IsExceptionPending(cx)) {
JS::ExceptionStack exnStack(cx); if (JS::StealPendingExceptionStack(cx, &exnStack)) {
JS::Rooted<JSObject*> stack(cx);
JS::Rooted<JSObject*> stackGlobal(cx);
xpc::FindExceptionStackForConsoleReport(nullptr, exnStack.exception(),
exnStack.stack(), &stack,
&stackGlobal); if (stack) {
reporter->SerializeStack(cx, stack);
}
}
}
NS_DispatchToMainThread(reporter);
}
// This is the first runnable to be dispatched. It calls the RunEventLoop() so // basically everything happens into this runnable. The reason behind this // approach is that, when the Worklet is terminated, it must not have any JS in // stack, but, because we have CC, nsIThread creates an AutoNoJSAPI object by // default. Using this runnable, CC exists only into it. class WorkletThread::PrimaryRunnable final : public Runnable { public: explicit PrimaryRunnable(WorkletThread* aWorkletThread)
: Runnable("WorkletThread::PrimaryRunnable"),
mWorkletThread(aWorkletThread) {
MOZ_ASSERT(aWorkletThread);
MOZ_ASSERT(NS_IsMainThread());
}
// This is the last runnable to be dispatched. It calls the TerminateInternal() class WorkletThread::TerminateRunnable final : public Runnable { public: explicit TerminateRunnable(WorkletThread* aWorkletThread)
: Runnable("WorkletThread::TerminateRunnable"),
mWorkletThread(aWorkletThread) {
MOZ_ASSERT(aWorkletThread);
MOZ_ASSERT(NS_IsMainThread());
}
staticbool DispatchToEventLoop(void* aClosure,
JS::Dispatchable* aDispatchable) { // This callback may execute either on the worklet thread or a random // JS-internal helper thread.
// See comment at JS::InitDispatchToEventLoop() below for how we know the // thread is alive.
nsIThread* thread = static_cast<nsIThread*>(aClosure);
// A thread lives strictly longer than its JSRuntime so we can safely // store a raw pointer as the callback's closure argument on the JSRuntime.
JS::InitDispatchToEventLoop(context->Context(), DispatchToEventLoop,
NS_GetCurrentThread());
// When available, set the self-hosted shared memory to be read, so that we // can decode the self-hosted content instead of parsing it. auto& shm = xpc::SelfHostedShmem::GetSingleton();
JS::SelfHostedCache selfHostedContent = shm.Content();
// The WorkletImpl will terminate the worklet thread after sending a message // to release worklet thread objects.
mWorkletImpl->NotifyWorkletFinished(); return NS_OK;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.