mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
Bug 1596756 - Support FinalizationGroup objects in the browser r=mccr8
Add browser support for FinalizationGroup by setting the HostCleanupFinalizationGroupCallback in CycleCollectedJSContext. The callback adds groups pending cleanup to a vector stored in a PersistentRooted. A runnable is dispatched to call back into the JS engine and perform cleanup at a later time as a separate task. Using AutoEntryScript reports errors to the console. Differential Revision: https://phabricator.services.mozilla.com/D53248 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
565c221ae9
commit
5af1cef3ff
@ -13,6 +13,7 @@
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/Sprintf.h"
|
||||
#include "mozilla/SystemGroup.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/TimelineConsumers.h"
|
||||
#include "mozilla/TimelineMarker.h"
|
||||
@ -77,6 +78,10 @@ CycleCollectedJSContext::~CycleCollectedJSContext() {
|
||||
return;
|
||||
}
|
||||
|
||||
JS::SetHostCleanupFinalizationGroupCallback(
|
||||
mJSContext, nullptr, nullptr);
|
||||
mFinalizationGroupsToCleanUp.reset();
|
||||
|
||||
JS_SetContextPrivate(mJSContext, nullptr);
|
||||
|
||||
mRuntime->SetContext(nullptr);
|
||||
@ -144,6 +149,10 @@ nsresult CycleCollectedJSContext::Initialize(JSRuntime* aParentRuntime,
|
||||
JS::GCVector<JSObject*, 0, js::SystemAllocPolicy>(
|
||||
js::SystemAllocPolicy()));
|
||||
|
||||
mFinalizationGroupsToCleanUp.init(mJSContext);
|
||||
JS::SetHostCleanupFinalizationGroupCallback(
|
||||
mJSContext, CleanupFinalizationGroupCallback, this);
|
||||
|
||||
// Cast to PerThreadAtomCache for dom::GetAtomCache(JSContext*).
|
||||
JS_SetContextPrivate(mJSContext, static_cast<PerThreadAtomCache*>(this));
|
||||
|
||||
@ -722,4 +731,54 @@ nsresult CycleCollectedJSContext::NotifyUnhandledRejections::Cancel() {
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class CleanupFinalizationGroupsRunnable : public CancelableRunnable {
|
||||
public:
|
||||
explicit CleanupFinalizationGroupsRunnable(CycleCollectedJSContext* aContext)
|
||||
: CancelableRunnable("CleanupFinalizationGroupsRunnable"), mContext(aContext) {}
|
||||
NS_DECL_NSIRUNNABLE
|
||||
private:
|
||||
CycleCollectedJSContext* mContext;
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
CleanupFinalizationGroupsRunnable::Run() {
|
||||
if (mContext->mFinalizationGroupsToCleanUp.empty()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JS::RootingContext* cx = mContext->RootingCx();
|
||||
|
||||
JS::Rooted<CycleCollectedJSContext::ObjectVector> groups(cx);
|
||||
std::swap(groups.get(), mContext->mFinalizationGroupsToCleanUp.get());
|
||||
|
||||
JS::Rooted<JSObject*> group(cx);
|
||||
for (const auto& g : groups) {
|
||||
group = g;
|
||||
|
||||
AutoEntryScript aes(group, "cleanupFinalizationGroup");
|
||||
mozilla::Unused << JS::CleanupQueuedFinalizationGroup(aes.cx(), group);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void CycleCollectedJSContext::CleanupFinalizationGroupCallback(JSObject* aGroup,
|
||||
void* aData) {
|
||||
CycleCollectedJSContext* ccjs = static_cast<CycleCollectedJSContext*>(aData);
|
||||
ccjs->QueueFinalizationGroupForCleanup(aGroup);
|
||||
}
|
||||
|
||||
void CycleCollectedJSContext::QueueFinalizationGroupForCleanup(
|
||||
JSObject* aGroup) {
|
||||
bool firstGroup = mFinalizationGroupsToCleanUp.empty();
|
||||
MOZ_ALWAYS_TRUE(mFinalizationGroupsToCleanUp.append(aGroup));
|
||||
if (firstGroup) {
|
||||
RefPtr<CleanupFinalizationGroupsRunnable> cleanup =
|
||||
new CleanupFinalizationGroupsRunnable(this);
|
||||
NS_DispatchToCurrentThread(cleanup.forget());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "mozilla/dom/AtomList.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "jsapi.h"
|
||||
#include "js/GCVector.h"
|
||||
#include "js/Promise.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
@ -263,6 +264,9 @@ class CycleCollectedJSContext
|
||||
class SavedMicroTaskQueue;
|
||||
js::UniquePtr<SavedJobQueue> saveJobQueue(JSContext*) override;
|
||||
|
||||
static void CleanupFinalizationGroupCallback(JSObject* aGroup, void* aData);
|
||||
void QueueFinalizationGroupForCleanup(JSObject* aGroup);
|
||||
|
||||
private:
|
||||
CycleCollectedJSRuntime* mRuntime;
|
||||
|
||||
@ -336,6 +340,15 @@ class CycleCollectedJSContext
|
||||
CycleCollectedJSContext* mCx;
|
||||
PromiseArray mUnhandledRejections;
|
||||
};
|
||||
|
||||
// Support for JS FinalizationGroup objects.
|
||||
//
|
||||
// These allow a JS callback to be registered that is called when an object
|
||||
// dies. The browser part of the implementation keeps a vector of
|
||||
// FinalizationGroups with pending callbacks here.
|
||||
friend class CleanupFinalizationGroupsRunnable;
|
||||
using ObjectVector = JS::GCVector<JSObject*, 0, InfallibleAllocPolicy>;
|
||||
JS::PersistentRooted<ObjectVector> mFinalizationGroupsToCleanUp;
|
||||
};
|
||||
|
||||
class MOZ_STACK_CLASS nsAutoMicroTask {
|
||||
|
Loading…
Reference in New Issue
Block a user