JS::TraceIncomingCCWs(JSTracer* trc, const JS::CompartmentSet& compartments) { for (js::CompartmentsIter comp(trc->runtime(), SkipAtoms); !comp.done(); comp.next()) { if (compartments.has(comp)) continue; for (JSCompartment::WrapperEnum e(comp); !e.empty(); e.popFront()) { const CrossCompartmentKey& key = e.front().key(); JSObject* obj; JSScript* script; switch (key.kind) { case CrossCompartmentKey::StringWrapper: // StringWrappers are just used to avoid copying strings // across zones multiple times, and don't hold a strong // reference. continue; case CrossCompartmentKey::ObjectWrapper: case CrossCompartmentKey::DebuggerObject: case CrossCompartmentKey::DebuggerSource: case CrossCompartmentKey::DebuggerEnvironment: case CrossCompartmentKey::DebuggerWasmScript: case CrossCompartmentKey::DebuggerWasmSource: obj = static_cast<JSObject*>(key.wrapped); // Ignore CCWs whose wrapped value doesn't live in our given // set of zones. if (!compartments.has(obj->compartment())) continue; TraceManuallyBarrieredEdge(trc, &obj, "cross-compartment wrapper"); MOZ_ASSERT(obj == key.wrapped); break; case CrossCompartmentKey::DebuggerScript: script = static_cast<JSScript*>(key.wrapped); // Ignore CCWs whose wrapped value doesn't live in our given // set of compartments. if (!compartments.has(script->compartment())) continue; TraceManuallyBarrieredEdge(trc, &script, "cross-compartment wrapper"); MOZ_ASSERT(script == key.wrapped); break; } } } }
JS_PUBLIC_API void JS::TraceIncomingCCWs( JSTracer* trc, const JS::CompartmentSet& compartments) { for (js::CompartmentsIter comp(trc->runtime()); !comp.done(); comp.next()) { if (compartments.has(comp)) { continue; } for (Compartment::WrapperEnum e(comp); !e.empty(); e.popFront()) { mozilla::DebugOnly<const CrossCompartmentKey> prior = e.front().key(); e.front().mutableKey().applyToWrapped( TraceIncomingFunctor(trc, compartments)); MOZ_ASSERT(e.front().key() == prior); } } }