Refactor PerformanceObserver to use hash tables for entry type validation and improve ThrottleInputStream state management

This commit is contained in:
wuggy 2026-04-26 11:13:27 -07:00
commit a2a4c62a9b
4 changed files with 55 additions and 12 deletions

View file

@ -10,9 +10,11 @@
#include "mozilla/dom/PerformanceEntryBinding.h"
#include "mozilla/dom/PerformanceObserverBinding.h"
#include "nsIScriptError.h"
#include "nsHashKeys.h"
#include "nsPIDOMWindow.h"
#include "nsQueryObject.h"
#include "nsString.h"
#include "nsTHashtable.h"
#include "PerformanceEntry.h"
#include "PerformanceObserverEntryList.h"
#include "WorkerPrivate.h"
@ -225,19 +227,28 @@ void PerformanceObserver::Observe(const PerformanceObserverInit& aOptions,
}
/* 3.3.1.5.2 */
nsTHashtable<nsStringHashKey> requestedTypes(entryTypes.Length());
for (const auto& type : entryTypes) {
requestedTypes.PutEntry(type);
}
nsTArray<nsString> validEntryTypes;
for (const char16_t* name : sValidTypeNames) {
nsDependentString validTypeName(name);
if (entryTypes.Contains<nsString>(validTypeName) &&
!validEntryTypes.Contains<nsString>(validTypeName)) {
if (requestedTypes.GetEntry(validTypeName)) {
validEntryTypes.AppendElement(validTypeName);
}
}
nsTHashtable<nsStringHashKey> validTypeSet(validEntryTypes.Length());
for (const auto& validType : validEntryTypes) {
validTypeSet.PutEntry(validType);
}
nsAutoString invalidTypesJoined;
bool addComma = false;
for (const auto& type : entryTypes) {
if (!validEntryTypes.Contains<nsString>(type)) {
if (!validTypeSet.GetEntry(type)) {
if (addComma) {
invalidTypesJoined.AppendLiteral(", ");
}
@ -289,13 +300,13 @@ void PerformanceObserver::Observe(const PerformanceObserverInit& aOptions,
/* 3.3.1.6.4, 3.3.1.6.4 */
bool didUpdateOptionsList = false;
nsTArray<PerformanceObserverInit> updatedOptionsList;
nsTArray<PerformanceObserverInit> updatedOptionsList(mOptions.Length() + 1);
for (auto& option : mOptions) {
if (option.mType.WasPassed() && option.mType.Value() == type) {
updatedOptionsList.AppendElement(aOptions);
didUpdateOptionsList = true;
} else {
updatedOptionsList.AppendElement(option);
updatedOptionsList.AppendElement(Move(option));
}
}
if (!didUpdateOptionsList) {

View file

@ -103,13 +103,23 @@ static LayerSortOrder CompareDepth(Layer* aOne, Layer* aTwo) {
// Could we just check Contains() on the bounds rects. ie, is it possible
// for layers to overlap without intersections (in 2d space) and yet still
// have their bounds rects not completely enclose each other?
nsTArray<gfxPoint> points;
AutoTArray<gfxPoint, 24> points;
auto appendUniquePoint = [&points](const gfxPoint& aPoint) {
static const gfxFloat kDuplicateEpsilon = 0.01;
for (const auto& point : points) {
if (fabs(point.x - aPoint.x) < kDuplicateEpsilon &&
fabs(point.y - aPoint.y) < kDuplicateEpsilon) {
return;
}
}
points.AppendElement(aPoint);
};
for (uint32_t i = 0; i < 4; i++) {
if (ourTransformedRect.Contains(otherTransformedRect.mPoints[i])) {
points.AppendElement(otherTransformedRect.mPoints[i]);
appendUniquePoint(otherTransformedRect.mPoints[i]);
}
if (otherTransformedRect.Contains(ourTransformedRect.mPoints[i])) {
points.AppendElement(ourTransformedRect.mPoints[i]);
appendUniquePoint(ourTransformedRect.mPoints[i]);
}
}
@ -123,7 +133,7 @@ static LayerSortOrder CompareDepth(Layer* aOne, Layer* aTwo) {
gfxLineSegment two(otherTransformedRect.mPoints[j],
otherTransformedRect.mPoints[(j + 1) % 4]);
if (one.Intersects(two, intersection)) {
points.AppendElement(intersection);
appendUniquePoint(intersection);
}
}
}

View file

@ -30,6 +30,8 @@ public:
NS_DECL_NSIASYNCINPUTSTREAM
void AllowInput();
bool IsQueued() const;
void SetQueued(bool aQueued);
private:
@ -41,6 +43,7 @@ private:
nsCOMPtr<nsIInputStreamCallback> mCallback;
nsCOMPtr<nsIEventTarget> mEventTarget;
bool mIsQueued;
};
NS_IMPL_ISUPPORTS(ThrottleInputStream, nsIAsyncInputStream, nsIInputStream, nsISeekableStream)
@ -49,6 +52,7 @@ ThrottleInputStream::ThrottleInputStream(nsIInputStream *aStream, ThrottleQueue*
: mStream(aStream)
, mQueue(aQueue)
, mClosedStatus(NS_OK)
, mIsQueued(false)
{
MOZ_ASSERT(aQueue != nullptr);
}
@ -233,6 +237,18 @@ ThrottleInputStream::AllowInput()
callbackEvent->OnInputStreamReady(this);
}
bool
ThrottleInputStream::IsQueued() const
{
return mIsQueued;
}
void
ThrottleInputStream::SetQueued(bool aQueued)
{
mIsQueued = aQueued;
}
//-----------------------------------------------------------------------------
NS_IMPL_ISUPPORTS(ThrottleQueue, nsIInputChannelThrottleQueue, nsITimerCallback)
@ -348,6 +364,7 @@ ThrottleQueue::Notify(nsITimer* aTimer)
// Optimistically notify all the waiting readers, and then let them
// requeue if there isn't enough bandwidth.
for (size_t i = 0; i < events.Length(); ++i) {
events[i]->SetQueued(false);
events[i]->AllowInput();
}
@ -359,7 +376,8 @@ void
ThrottleQueue::QueueStream(ThrottleInputStream* aStream)
{
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
if (mAsyncEvents.IndexOf(aStream) == mAsyncEvents.NoIndex) {
if (!aStream->IsQueued()) {
aStream->SetQueued(true);
mAsyncEvents.AppendElement(aStream);
if (!mTimerArmed) {
@ -386,7 +404,12 @@ void
ThrottleQueue::DequeueStream(ThrottleInputStream* aStream)
{
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
if (!aStream->IsQueued()) {
return;
}
mAsyncEvents.RemoveElement(aStream);
aStream->SetQueued(false);
}
}

View file

@ -354,8 +354,7 @@ TimerThread::Shutdown()
// might potentially call some code reentering the same lock
// that leads to unexpected behavior or deadlock.
// See bug 422472.
timers.AppendElements(mTimers);
mTimers.Clear();
timers.SwapElements(mTimers);
}
uint32_t timersCount = timers.Length();