diff --git a/dom/plugins/base/nsJSNPRuntime.cpp b/dom/plugins/base/nsJSNPRuntime.cpp index 7a93168515..e92d99b263 100644 --- a/dom/plugins/base/nsJSNPRuntime.cpp +++ b/dom/plugins/base/nsJSNPRuntime.cpp @@ -1974,7 +1974,7 @@ nsJSNPRuntime::OnPluginDestroy(NPP npp) } if (sNPObjWrappers) { - for (auto i = sNPObjWrappers->RemovingIter(); !i.Done(); i.Next()) { + for (auto i = sNPObjWrappers->Iter(); !i.Done(); i.Next()) { auto entry = static_cast(i.Get()); if (entry->mNpp == npp) { diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index adb0f3899e..f6fdcab29c 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -775,7 +775,7 @@ XPCJSRuntime::FinalizeCallback(JSFreeOp* fop, // At this point there may be JSObjects using them that have // been removed from the other maps. if (!nsXPConnect::XPConnect()->IsShuttingDown()) { - for (auto i = self->mNativeScriptableSharedMap->RemovingIter(); !i.Done(); i.Next()) { + for (auto i = self->mNativeScriptableSharedMap->Iter(); !i.Done(); i.Next()) { auto entry = static_cast(i.Get()); XPCNativeScriptableShared* shared = entry->key; if (shared->IsMarked()) { @@ -788,14 +788,14 @@ XPCJSRuntime::FinalizeCallback(JSFreeOp* fop, } if (!isCompartmentGC) { - for (auto i = self->mClassInfo2NativeSetMap->RemovingIter(); !i.Done(); i.Next()) { + for (auto i = self->mClassInfo2NativeSetMap->Iter(); !i.Done(); i.Next()) { auto entry = static_cast(i.Get()); if (!entry->value->IsMarked()) i.Remove(); } } - for (auto i = self->mNativeSetMap->RemovingIter(); !i.Done(); i.Next()) { + for (auto i = self->mNativeSetMap->Iter(); !i.Done(); i.Next()) { auto entry = static_cast(i.Get()); XPCNativeSet* set = entry->key_value; if (set->IsMarked()) { @@ -806,7 +806,7 @@ XPCJSRuntime::FinalizeCallback(JSFreeOp* fop, } } - for (auto i = self->mIID2NativeInterfaceMap->RemovingIter(); !i.Done(); i.Next()) { + for (auto i = self->mIID2NativeInterfaceMap->Iter(); !i.Done(); i.Next()) { auto entry = static_cast(i.Get()); XPCNativeInterface* iface = entry->value; if (iface->IsMarked()) { @@ -871,7 +871,7 @@ XPCJSRuntime::FinalizeCallback(JSFreeOp* fop, // referencing the protos in the dying list are themselves dead. // So, we can safely delete all the protos in the list. - for (auto i = self->mDyingWrappedNativeProtoMap->RemovingIter(); !i.Done(); i.Next()) { + for (auto i = self->mDyingWrappedNativeProtoMap->Iter(); !i.Done(); i.Next()) { auto entry = static_cast(i.Get()); delete static_cast(entry->key); i.Remove(); @@ -3536,7 +3536,7 @@ XPCJSRuntime::DebugDump(int16_t depth) // iterate sets... if (depth && mNativeSetMap->Count()) { XPC_LOG_INDENT(); - for (auto i = mNativeSetMap->RemovingIter(); !i.Done(); i.Next()) { + for (auto i = mNativeSetMap->Iter(); !i.Done(); i.Next()) { auto entry = static_cast(i.Get()); entry->key_value->DebugDump(depth); } diff --git a/js/xpconnect/src/XPCMaps.h b/js/xpconnect/src/XPCMaps.h index 97337a0545..7fd880560f 100644 --- a/js/xpconnect/src/XPCMaps.h +++ b/js/xpconnect/src/XPCMaps.h @@ -150,8 +150,6 @@ public: inline uint32_t Count() { return mTable->EntryCount(); } PLDHashTable::Iterator Iter() const { return PLDHashTable::Iterator(mTable); } - PLDHashTable::RemovingIterator RemovingIter() { return PLDHashTable::RemovingIterator(mTable); } - size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf); ~Native2WrappedNativeMap(); @@ -263,7 +261,7 @@ public: inline uint32_t Count() { return mTable->EntryCount(); } - PLDHashTable::RemovingIterator RemovingIter() { return PLDHashTable::RemovingIterator(mTable); } + PLDHashTable::Iterator Iter() { return PLDHashTable::Iterator(mTable); } size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf); @@ -319,7 +317,7 @@ public: inline uint32_t Count() { return mTable->EntryCount(); } - PLDHashTable::RemovingIterator RemovingIter() { return PLDHashTable::RemovingIterator(mTable); } + PLDHashTable::Iterator Iter() { return PLDHashTable::Iterator(mTable); } // ClassInfo2NativeSetMap holds pointers to *some* XPCNativeSets. // So we don't want to count those XPCNativeSets, because they are better @@ -377,7 +375,7 @@ public: inline uint32_t Count() { return mTable->EntryCount(); } PLDHashTable::Iterator Iter() const { return PLDHashTable::Iterator(mTable); } - PLDHashTable::RemovingIterator RemovingIter() { return PLDHashTable::RemovingIterator(mTable); } + PLDHashTable::Iterator Iter() { return PLDHashTable::Iterator(mTable); } size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf); @@ -448,7 +446,7 @@ public: inline uint32_t Count() { return mTable->EntryCount(); } PLDHashTable::Iterator Iter() const { return PLDHashTable::Iterator(mTable); } - PLDHashTable::RemovingIterator RemovingIter() { return PLDHashTable::RemovingIterator(mTable); } + PLDHashTable::Iterator Iter() { return PLDHashTable::Iterator(mTable); } size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf); @@ -545,7 +543,7 @@ public: inline uint32_t Count() { return mTable->EntryCount(); } - PLDHashTable::RemovingIterator RemovingIter() { return PLDHashTable::RemovingIterator(mTable); } + PLDHashTable::Iterator Iter() { return PLDHashTable::Iterator(mTable); } ~XPCNativeScriptableSharedMap(); private: @@ -586,7 +584,7 @@ public: inline uint32_t Count() { return mTable->EntryCount(); } PLDHashTable::Iterator Iter() const { return PLDHashTable::Iterator(mTable); } - PLDHashTable::RemovingIterator RemovingIter() { return PLDHashTable::RemovingIterator(mTable); } + PLDHashTable::Iterator Iter() { return PLDHashTable::Iterator(mTable); } ~XPCWrappedNativeProtoMap(); private: diff --git a/js/xpconnect/src/XPCWrappedNativeScope.cpp b/js/xpconnect/src/XPCWrappedNativeScope.cpp index 5513231f0d..2ef1e0e9fc 100644 --- a/js/xpconnect/src/XPCWrappedNativeScope.cpp +++ b/js/xpconnect/src/XPCWrappedNativeScope.cpp @@ -649,12 +649,12 @@ XPCWrappedNativeScope::SystemIsBeingShutDown() // Walk the protos first. Wrapper shutdown can leave dangling // proto pointers in the proto map. - for (auto i = cur->mWrappedNativeProtoMap->RemovingIter(); !i.Done(); i.Next()) { + for (auto i = cur->mWrappedNativeProtoMap->Iter(); !i.Done(); i.Next()) { auto entry = static_cast(i.Get()); entry->value->SystemIsBeingShutDown(); i.Remove(); } - for (auto i = cur->mWrappedNativeMap->RemovingIter(); !i.Done(); i.Next()) { + for (auto i = cur->mWrappedNativeMap->Iter(); !i.Done(); i.Next()) { auto entry = static_cast(i.Get()); XPCWrappedNative* wrapper = entry->value; if (wrapper->IsValid()) { diff --git a/layout/base/nsFrameManager.cpp b/layout/base/nsFrameManager.cpp index eefb5125e2..16359ae502 100644 --- a/layout/base/nsFrameManager.cpp +++ b/layout/base/nsFrameManager.cpp @@ -203,19 +203,13 @@ nsFrameManager::UnregisterPlaceholderFrame(nsPlaceholderFrame* aPlaceholderFrame aPlaceholderFrame->GetOutOfFlowFrame()); } -static PLDHashOperator -UnregisterPlaceholders(PLDHashTable* table, PLDHashEntryHdr* hdr, - uint32_t number, void* arg) -{ - PlaceholderMapEntry* entry = static_cast(hdr); - entry->placeholderFrame->SetOutOfFlowFrame(nullptr); - return PL_DHASH_NEXT; -} - void nsFrameManager::ClearPlaceholderFrameMap() { - PL_DHashTableEnumerate(&mPlaceholderMap, UnregisterPlaceholders, nullptr); + for (auto iter = mPlaceholderMap.Iter(); !iter.Done(); iter.Next()) { + auto entry = static_cast(iter.Get()); + entry->placeholderFrame->SetOutOfFlowFrame(nullptr); + } mPlaceholderMap.Clear(); } diff --git a/layout/reftests/writing-mode/tables/fixed-table-layout-010-ref.html b/layout/reftests/writing-mode/tables/fixed-table-layout-010-ref.html index 5ca0f37baa..f53e1160b2 100644 --- a/layout/reftests/writing-mode/tables/fixed-table-layout-010-ref.html +++ b/layout/reftests/writing-mode/tables/fixed-table-layout-010-ref.html @@ -9,6 +9,7 @@ div.stripe { width: 20px; + line-height: 20px; height: 200px; } div.blue {background-color: blue; } diff --git a/layout/reftests/writing-mode/tables/multicol-count-002-ref.xht b/layout/reftests/writing-mode/tables/multicol-count-002-ref.xht new file mode 100644 index 0000000000..499debaf14 --- /dev/null +++ b/layout/reftests/writing-mode/tables/multicol-count-002-ref.xht @@ -0,0 +1,37 @@ + + + + CSS Reftest Reference + + + + + + + + + +
                      +  XXXX XXXX XXXX XXXX  +  X  X X  X X    X     +  X  X X  X X    X     +  XXXX XXXX XXXX XXXX  +  X    X  X    X    X  +  X    X  X    X    X  +  X    X  X XXXX XXXX  +                       +
+ + + \ No newline at end of file diff --git a/layout/reftests/writing-mode/tables/reftest.list b/layout/reftests/writing-mode/tables/reftest.list index 690d93a063..b547941663 100644 --- a/layout/reftests/writing-mode/tables/reftest.list +++ b/layout/reftests/writing-mode/tables/reftest.list @@ -7,19 +7,19 @@ == vertical-table-colspan-1.html vertical-table-colspan-1-ref.html == vertical-table-colspan-2.html vertical-table-colspan-2-ref.html == vertical-table-specified-width-1.html vertical-table-specified-width-1-ref.html -== vertical-table-specified-width-2.html vertical-table-specified-width-2-ref.html +asserts(1) == vertical-table-specified-width-2.html vertical-table-specified-width-2-ref.html # bug 1179741 fuzzy-if(cocoaWidget,141,24) == vertical-border-collapse-1.html vertical-border-collapse-1-ref.html fuzzy-if(cocoaWidget,141,24) == vertical-border-collapse-2.html vertical-border-collapse-2-ref.html -== fixed-table-layout-002-vlr.html fixed-table-layout-002-ref.html -== fixed-table-layout-003-vlr.html fixed-table-layout-002-ref.html +fuzzy-if(B2G,5,1) == fixed-table-layout-002-vlr.html fixed-table-layout-002-ref.html +fuzzy-if(B2G,5,1) == fixed-table-layout-003-vlr.html fixed-table-layout-002-ref.html == fixed-table-layout-004-vlr.html fixed-table-layout-004-ref.html == fixed-table-layout-005-vlr.html fixed-table-layout-005-ref.html == fixed-table-layout-006-vlr.html fixed-table-layout-006-ref.html -== fixed-table-layout-007-vlr.html fixed-table-layout-007-ref.html +fuzzy-if(B2G,5,1) == fixed-table-layout-007-vlr.html fixed-table-layout-007-ref.html == fixed-table-layout-009-vlr.html fixed-table-layout-009-ref.html -random == fixed-table-layout-010-vlr.html fixed-table-layout-010-ref.html # bug 1178059 -== fixed-table-layout-012-vlr.html fixed-table-layout-012-ref.html +fuzzy-if(Android,255,400) == fixed-table-layout-010-vlr.html fixed-table-layout-010-ref.html +fuzzy-if(B2G,5,1) == fixed-table-layout-012-vlr.html fixed-table-layout-012-ref.html == fixed-table-layout-013-vlr.html fixed-table-layout-002-ref.html == fixed-table-layout-014-vlr.html fixed-table-layout-002-ref.html == fixed-table-layout-015-vlr.html fixed-table-layout-002-ref.html @@ -37,15 +37,15 @@ random == fixed-table-layout-010-vlr.html fixed-table-layout-010-ref.html # bug == fixed-table-layout-030-vlr.html fixed-table-layout-025-ref.html == fixed-table-layout-031-vlr.html fixed-table-layout-025-ref.html -== fixed-table-layout-002-vrl.html fixed-table-layout-002-ref.html -== fixed-table-layout-003-vrl.html fixed-table-layout-002-ref.html +fuzzy-if(B2G,5,1) == fixed-table-layout-002-vrl.html fixed-table-layout-002-ref.html +fuzzy-if(B2G,5,1) == fixed-table-layout-003-vrl.html fixed-table-layout-002-ref.html == fixed-table-layout-004-vrl.html fixed-table-layout-004-ref.html == fixed-table-layout-005-vrl.html fixed-table-layout-005-ref.html == fixed-table-layout-006-vrl.html fixed-table-layout-006-ref.html -== fixed-table-layout-007-vrl.html fixed-table-layout-007-ref.html +fuzzy-if(B2G,5,1) == fixed-table-layout-007-vrl.html fixed-table-layout-007-ref.html == fixed-table-layout-009-vrl.html fixed-table-layout-009-ref.html -random == fixed-table-layout-010-vrl.html fixed-table-layout-010-ref.html # bug 1178059 -== fixed-table-layout-012-vrl.html fixed-table-layout-012-ref.html +fuzzy-if(Android,255,400) == fixed-table-layout-010-vrl.html fixed-table-layout-010-ref.html +fuzzy-if(B2G,5,1) == fixed-table-layout-012-vrl.html fixed-table-layout-012-ref.html == fixed-table-layout-013-vrl.html fixed-table-layout-002-ref.html == fixed-table-layout-014-vrl.html fixed-table-layout-002-ref.html == fixed-table-layout-015-vrl.html fixed-table-layout-002-ref.html @@ -62,3 +62,23 @@ random == fixed-table-layout-010-vrl.html fixed-table-layout-010-ref.html # bug == fixed-table-layout-029-vrl.html fixed-table-layout-025-ref.html == fixed-table-layout-030-vrl.html fixed-table-layout-025-ref.html == fixed-table-layout-031-vrl.html fixed-table-layout-025-ref.html + +HTTP(../..) == s72-border-spacing-002.xht s72-border-spacing-002-ref.xht +HTTP(../..) == s72-border-spacing-003.xht s72-border-spacing-002-ref.xht +HTTP(../..) == s72-border-spacing-004.xht s72-border-spacing-002-ref.xht +HTTP(../..) == s72-border-spacing-005.xht s72-border-spacing-002-ref.xht +fuzzy-if(winWidget,48,600) fuzzy-if(cocoaWidget,19,97) HTTP(../..) == wm-row-progression-002.xht multicol-count-002-ref.xht +fuzzy-if(winWidget,48,600) fuzzy-if(cocoaWidget,19,97) HTTP(../..) == wm-row-progression-003.xht multicol-count-002-ref.xht +fuzzy-if(winWidget,48,600) fuzzy-if(cocoaWidget,19,97) HTTP(../..) == wm-row-progression-004.xht multicol-count-002-ref.xht +fuzzy-if(winWidget,48,600) fuzzy-if(cocoaWidget,19,97) HTTP(../..) == wm-row-progression-005.xht multicol-count-002-ref.xht +fuzzy-if(winWidget,48,600) fuzzy-if(cocoaWidget,19,97) HTTP(../..) == wm-row-progression-006.xht multicol-count-002-ref.xht +fuzzy-if(winWidget,48,600) fuzzy-if(cocoaWidget,19,97) HTTP(../..) == wm-row-progression-007.xht multicol-count-002-ref.xht + +fuzzy-if(Android,255,38) == table-caption-block-start-1.html table-caption-block-start-1-ref.html +fuzzy-if(Android,255,38) == table-caption-block-end-1.html table-caption-block-end-1-ref.html +== table-caption-inline-start-1.html table-caption-inline-start-1-ref.html +== table-caption-inline-end-1.html table-caption-inline-end-1-ref.html +fuzzy-if(Android,255,38) == table-caption-top-1.html table-caption-top-1-ref.html +fuzzy-if(Android,255,38) == table-caption-bottom-1.html table-caption-bottom-1-ref.html +== table-caption-left-1.html table-caption-left-1-ref.html +== table-caption-right-1.html table-caption-right-1-ref.html diff --git a/layout/reftests/writing-mode/tables/s72-border-spacing-002-ref.xht b/layout/reftests/writing-mode/tables/s72-border-spacing-002-ref.xht new file mode 100644 index 0000000000..958ba060f1 --- /dev/null +++ b/layout/reftests/writing-mode/tables/s72-border-spacing-002-ref.xht @@ -0,0 +1,22 @@ + + + + + + + CSS Reftest Reference + + + + + + + + + +

Test passes if there is a filled green rectangle and no red.

+ +
Image download support must be enabled
+ + + \ No newline at end of file diff --git a/layout/reftests/writing-mode/tables/s72-border-spacing-002.xht b/layout/reftests/writing-mode/tables/s72-border-spacing-002.xht new file mode 100644 index 0000000000..3e8ba5d5e0 --- /dev/null +++ b/layout/reftests/writing-mode/tables/s72-border-spacing-002.xht @@ -0,0 +1,144 @@ + + + + + + + CSS Writing Modes Test: border-spacing - first value is specified and non-zero in 'vertical-rl' table + + + + + + + + + + + + + + + + + + +

Test passes if there is a filled green rectangle and no red.

+ +
+ + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + +
+ + + \ No newline at end of file diff --git a/layout/reftests/writing-mode/tables/s72-border-spacing-003.xht b/layout/reftests/writing-mode/tables/s72-border-spacing-003.xht new file mode 100644 index 0000000000..eba0a9dd51 --- /dev/null +++ b/layout/reftests/writing-mode/tables/s72-border-spacing-003.xht @@ -0,0 +1,144 @@ + + + + + + + CSS Writing Modes Test: border-spacing - first value is specified and non-zero in 'vertical-lr' table + + + + + + + + + + + + + + + + + + +

Test passes if there is a filled green rectangle and no red.

+ +
+ + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + +
+ + + \ No newline at end of file diff --git a/layout/reftests/writing-mode/tables/s72-border-spacing-004.xht b/layout/reftests/writing-mode/tables/s72-border-spacing-004.xht new file mode 100644 index 0000000000..db81c77c87 --- /dev/null +++ b/layout/reftests/writing-mode/tables/s72-border-spacing-004.xht @@ -0,0 +1,124 @@ + + + + + + + CSS Writing Modes Test: border-spacing - second value is specified and non-zero in 'vertical-rl' table + + + + + + + + + + + + + + + + +

Test passes if there is a filled green rectangle and no red.

+ +
+ + + + + + + +
+ +
+ + + + + + + +
+ + + \ No newline at end of file diff --git a/layout/reftests/writing-mode/tables/s72-border-spacing-005.xht b/layout/reftests/writing-mode/tables/s72-border-spacing-005.xht new file mode 100644 index 0000000000..0fd61d0f22 --- /dev/null +++ b/layout/reftests/writing-mode/tables/s72-border-spacing-005.xht @@ -0,0 +1,124 @@ + + + + + + + CSS Writing Modes Test: border-spacing - second value is specified and non-zero in 'vertical-lr' table + + + + + + + + + + + + + + + + +

Test passes if there is a filled green rectangle and no red.

+ +
+ + + + + + + +
+ +
+ + + + + + + +
+ + + \ No newline at end of file diff --git a/layout/reftests/writing-mode/tables/support/ahem.css b/layout/reftests/writing-mode/tables/support/ahem.css new file mode 100644 index 0000000000..cf2cd818f4 --- /dev/null +++ b/layout/reftests/writing-mode/tables/support/ahem.css @@ -0,0 +1,4 @@ +@font-face { + font-family: Ahem; + src: url("../../../fonts/Ahem.ttf"); +} diff --git a/layout/reftests/writing-mode/tables/support/swatch-green.png b/layout/reftests/writing-mode/tables/support/swatch-green.png new file mode 100644 index 0000000000..0aa79b0c86 Binary files /dev/null and b/layout/reftests/writing-mode/tables/support/swatch-green.png differ diff --git a/layout/reftests/writing-mode/tables/table-caption-block-end-1-ref.html b/layout/reftests/writing-mode/tables/table-caption-block-end-1-ref.html new file mode 100644 index 0000000000..fd446c3f5b --- /dev/null +++ b/layout/reftests/writing-mode/tables/table-caption-block-end-1-ref.html @@ -0,0 +1,53 @@ + + + + + + + + +
+
+
table caption
+
+ +
+
+
table caption
+
+ +
+
+
table caption
+
+ +
+
+
table caption
+
diff --git a/layout/reftests/writing-mode/tables/table-caption-block-end-1.html b/layout/reftests/writing-mode/tables/table-caption-block-end-1.html new file mode 100644 index 0000000000..645f7dc644 --- /dev/null +++ b/layout/reftests/writing-mode/tables/table-caption-block-end-1.html @@ -0,0 +1,61 @@ + + + + + + + + + + + +
table caption
+ + + + +
table caption
+ + + + +
table caption
+ + + + +
table caption
diff --git a/layout/reftests/writing-mode/tables/table-caption-block-start-1-ref.html b/layout/reftests/writing-mode/tables/table-caption-block-start-1-ref.html new file mode 100644 index 0000000000..d4f8ab717c --- /dev/null +++ b/layout/reftests/writing-mode/tables/table-caption-block-start-1-ref.html @@ -0,0 +1,53 @@ + + + + + + + + +
+
table caption
+
+
+ +
+
table caption
+
+
+ +
+
table caption
+
+
+ +
+
table caption
+
+
diff --git a/layout/reftests/writing-mode/tables/table-caption-block-start-1.html b/layout/reftests/writing-mode/tables/table-caption-block-start-1.html new file mode 100644 index 0000000000..f8a04bb67e --- /dev/null +++ b/layout/reftests/writing-mode/tables/table-caption-block-start-1.html @@ -0,0 +1,61 @@ + + + + + + + + + + + +
table caption
+ + + + +
table caption
+ + + + +
table caption
+ + + + +
table caption
diff --git a/layout/reftests/writing-mode/tables/table-caption-bottom-1-ref.html b/layout/reftests/writing-mode/tables/table-caption-bottom-1-ref.html new file mode 100644 index 0000000000..8ffc4937d5 --- /dev/null +++ b/layout/reftests/writing-mode/tables/table-caption-bottom-1-ref.html @@ -0,0 +1,54 @@ + + + + + + + + +
+
+
table caption
+
+ +
+
+
table caption
+
+ +
+
+
table caption
+
+ +
+
+
table caption
+
diff --git a/layout/reftests/writing-mode/tables/table-caption-bottom-1.html b/layout/reftests/writing-mode/tables/table-caption-bottom-1.html new file mode 100644 index 0000000000..74cd13dd2a --- /dev/null +++ b/layout/reftests/writing-mode/tables/table-caption-bottom-1.html @@ -0,0 +1,61 @@ + + + + + + + + + + + +
table caption
+ + + + +
table caption
+ + + + +
table caption
+ + + + +
table caption
diff --git a/layout/reftests/writing-mode/tables/table-caption-inline-end-1-ref.html b/layout/reftests/writing-mode/tables/table-caption-inline-end-1-ref.html new file mode 100644 index 0000000000..d26b51e26a --- /dev/null +++ b/layout/reftests/writing-mode/tables/table-caption-inline-end-1-ref.html @@ -0,0 +1,57 @@ + + + + + + + + +
+
+
table caption
+
+ +
+
table caption
+
+
+ +
+
+
table caption
+
+ +
+
+
table caption
+
diff --git a/layout/reftests/writing-mode/tables/table-caption-inline-end-1.html b/layout/reftests/writing-mode/tables/table-caption-inline-end-1.html new file mode 100644 index 0000000000..835d4a6f0a --- /dev/null +++ b/layout/reftests/writing-mode/tables/table-caption-inline-end-1.html @@ -0,0 +1,61 @@ + + + + + + + + + + + +
table caption
+ + + + +
table caption
+ + + + +
table caption
+ + + + +
table caption
diff --git a/layout/reftests/writing-mode/tables/table-caption-inline-start-1-ref.html b/layout/reftests/writing-mode/tables/table-caption-inline-start-1-ref.html new file mode 100644 index 0000000000..bbc533a0d1 --- /dev/null +++ b/layout/reftests/writing-mode/tables/table-caption-inline-start-1-ref.html @@ -0,0 +1,57 @@ + + + + + + + + +
+
table caption
+
+
+ +
+
+
table caption
+
+ +
+
table caption
+
+
+ +
+
table caption
+
+
diff --git a/layout/reftests/writing-mode/tables/table-caption-inline-start-1.html b/layout/reftests/writing-mode/tables/table-caption-inline-start-1.html new file mode 100644 index 0000000000..86f59a40a7 --- /dev/null +++ b/layout/reftests/writing-mode/tables/table-caption-inline-start-1.html @@ -0,0 +1,61 @@ + + + + + + + + + + + +
table caption
+ + + + +
table caption
+ + + + +
table caption
+ + + + +
table caption
diff --git a/layout/reftests/writing-mode/tables/table-caption-left-1-ref.html b/layout/reftests/writing-mode/tables/table-caption-left-1-ref.html new file mode 100644 index 0000000000..7c10436c96 --- /dev/null +++ b/layout/reftests/writing-mode/tables/table-caption-left-1-ref.html @@ -0,0 +1,55 @@ + + + + + + + + +
+
table caption
+
+
+ +
+
table caption
+
+
+ +
+
table caption
+
+
+ +
+
+
table caption
+
diff --git a/layout/reftests/writing-mode/tables/table-caption-left-1.html b/layout/reftests/writing-mode/tables/table-caption-left-1.html new file mode 100644 index 0000000000..469fb2783c --- /dev/null +++ b/layout/reftests/writing-mode/tables/table-caption-left-1.html @@ -0,0 +1,61 @@ + + + + + + + + + + + +
table caption
+ + + + +
table caption
+ + + + +
table caption
+ + + + +
table caption
diff --git a/layout/reftests/writing-mode/tables/table-caption-right-1-ref.html b/layout/reftests/writing-mode/tables/table-caption-right-1-ref.html new file mode 100644 index 0000000000..7a2b42cdd5 --- /dev/null +++ b/layout/reftests/writing-mode/tables/table-caption-right-1-ref.html @@ -0,0 +1,55 @@ + + + + + + + + +
+
+
table caption
+
+ +
+
+
table caption
+
+ +
+
+
table caption
+
+ +
+
table caption
+
+
diff --git a/layout/reftests/writing-mode/tables/table-caption-right-1.html b/layout/reftests/writing-mode/tables/table-caption-right-1.html new file mode 100644 index 0000000000..d4e36485cf --- /dev/null +++ b/layout/reftests/writing-mode/tables/table-caption-right-1.html @@ -0,0 +1,61 @@ + + + + + + + + + + + +
table caption
+ + + + +
table caption
+ + + + +
table caption
+ + + + +
table caption
diff --git a/layout/reftests/writing-mode/tables/table-caption-top-1-ref.html b/layout/reftests/writing-mode/tables/table-caption-top-1-ref.html new file mode 100644 index 0000000000..8c3ff8621f --- /dev/null +++ b/layout/reftests/writing-mode/tables/table-caption-top-1-ref.html @@ -0,0 +1,54 @@ + + + + + + + + +
+
table caption
+
+
+ +
+
table caption
+
+
+ +
+
table caption
+
+
+ +
+
table caption
+
+
diff --git a/layout/reftests/writing-mode/tables/table-caption-top-1.html b/layout/reftests/writing-mode/tables/table-caption-top-1.html new file mode 100644 index 0000000000..5955d01461 --- /dev/null +++ b/layout/reftests/writing-mode/tables/table-caption-top-1.html @@ -0,0 +1,61 @@ + + + + + + + + + + + +
table caption
+ + + + +
table caption
+ + + + +
table caption
+ + + + +
table caption
diff --git a/layout/reftests/writing-mode/tables/wm-row-progression-002.xht b/layout/reftests/writing-mode/tables/wm-row-progression-002.xht new file mode 100644 index 0000000000..4749c5f451 --- /dev/null +++ b/layout/reftests/writing-mode/tables/wm-row-progression-002.xht @@ -0,0 +1,73 @@ + + + + + + + CSS Writing Modes Test: vertical-rl - table rows progression + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
A  B  C  DDDEE F G HJJ  K  L  M
N  O  Q  RRRSS T U VWW  X  Y  Z
aaa b  c  dddee f g hhjj     kk
mmm n  o  qqqr s t uu      vv
+ + + \ No newline at end of file diff --git a/layout/reftests/writing-mode/tables/wm-row-progression-003.xht b/layout/reftests/writing-mode/tables/wm-row-progression-003.xht new file mode 100644 index 0000000000..dbb7cf4fb5 --- /dev/null +++ b/layout/reftests/writing-mode/tables/wm-row-progression-003.xht @@ -0,0 +1,73 @@ + + + + + + + CSS Writing Modes Test: vertical-lr - line boxes progression + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AAA B  C  DDDEE F G HJJ      
KKK L  M  NNNOO Q R SSTT     UU
VVV W  X  Y a b c dd e  f  g hh
jjj k  m  n q r s tt u  v  w xx
+ + + \ No newline at end of file diff --git a/layout/reftests/writing-mode/tables/wm-row-progression-004.xht b/layout/reftests/writing-mode/tables/wm-row-progression-004.xht new file mode 100644 index 0000000000..7178cc1342 --- /dev/null +++ b/layout/reftests/writing-mode/tables/wm-row-progression-004.xht @@ -0,0 +1,73 @@ + + + + + + + CSS Writing Modes Test: vertical-rl - table rows progression and colspan + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
A  B  C  DDDEE F G HJJ  K  L  M
N  OO Q  R  S  T  UUUUWW  X  Y  Z
aaa b  c  dddeeff g   h   jjjj
mmm n  o  qqqr s t uu      vv
+ + + \ No newline at end of file diff --git a/layout/reftests/writing-mode/tables/wm-row-progression-005.xht b/layout/reftests/writing-mode/tables/wm-row-progression-005.xht new file mode 100644 index 0000000000..0d3abf6539 --- /dev/null +++ b/layout/reftests/writing-mode/tables/wm-row-progression-005.xht @@ -0,0 +1,73 @@ + + + + + + + CSS Writing Modes Test: vertical-lr - table rows progression and colspan + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AAA B  C  DDDEE F G HJJ      
KKKOO L  Q  M  R  NNNSSTT     UU
VVV W  X  Y a  b c  d e  f gggg
jjj k  m  n q r s tt u  v  w xx
+ + + \ No newline at end of file diff --git a/layout/reftests/writing-mode/tables/wm-row-progression-006.xht b/layout/reftests/writing-mode/tables/wm-row-progression-006.xht new file mode 100644 index 0000000000..32d3b089d8 --- /dev/null +++ b/layout/reftests/writing-mode/tables/wm-row-progression-006.xht @@ -0,0 +1,73 @@ + + + + + + + CSS Writing Modes Test: vertical-rl - table rows progression and rowspan + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
A  B  C  DDDEE F G HJJ  K  L  M   WW  X  Y  Z
N  O  Q  RRRSS T U V
aaa b  c  dddee f g hh   r s t uujj     kk
mmm n  o  qqq      vv
+ + + \ No newline at end of file diff --git a/layout/reftests/writing-mode/tables/wm-row-progression-007.xht b/layout/reftests/writing-mode/tables/wm-row-progression-007.xht new file mode 100644 index 0000000000..5280f845db --- /dev/null +++ b/layout/reftests/writing-mode/tables/wm-row-progression-007.xht @@ -0,0 +1,73 @@ + + + + + + + CSS Writing Modes Test: vertical-lr - table rows progression and rowspan + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AAA B  C  DDDEE F G HJJ         TT     UU
KKK L  M  NNNOO Q R SS
VVV W  X  Y a b c dd   q r s tt e  f  g hh
jjj k  m  n  u  v  w xx
+ + + \ No newline at end of file diff --git a/layout/style/nsCSSRuleProcessor.cpp b/layout/style/nsCSSRuleProcessor.cpp index 924526a254..16f8d3e577 100644 --- a/layout/style/nsCSSRuleProcessor.cpp +++ b/layout/style/nsCSSRuleProcessor.cpp @@ -3435,30 +3435,6 @@ static int CompareWeightData(const void* aArg1, const void* aArg2, return arg1->mWeight - arg2->mWeight; // put lower weight first } - -struct FillWeightArrayData { - explicit FillWeightArrayData(PerWeightData* aArrayData) : - mIndex(0), - mWeightArray(aArrayData) - { - } - int32_t mIndex; - PerWeightData* mWeightArray; -}; - - -static PLDHashOperator -FillWeightArray(PLDHashTable *table, PLDHashEntryHdr *hdr, - uint32_t number, void *arg) -{ - FillWeightArrayData* data = static_cast(arg); - const RuleByWeightEntry *entry = (const RuleByWeightEntry *)hdr; - - data->mWeightArray[data->mIndex++] = entry->data; - - return PL_DHASH_NEXT; -} - RuleCascadeData* nsCSSRuleProcessor::GetRuleCascade(nsPresContext* aPresContext) { @@ -3525,8 +3501,11 @@ nsCSSRuleProcessor::RefreshRuleCascade(nsPresContext* aPresContext) // Sort the hash table of per-weight linked lists by weight. uint32_t weightCount = data.mRulesByWeight.EntryCount(); nsAutoArrayPtr weightArray(new PerWeightData[weightCount]); - FillWeightArrayData fwData(weightArray); - PL_DHashTableEnumerate(&data.mRulesByWeight, FillWeightArray, &fwData); + int32_t j = 0; + for (auto iter = data.mRulesByWeight.Iter(); !iter.Done(); iter.Next()) { + auto entry = static_cast(iter.Get()); + weightArray[j++] = entry->data; + } NS_QuickSort(weightArray, weightCount, sizeof(PerWeightData), CompareWeightData, nullptr); diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index f446a5f2f1..33069db407 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -1405,17 +1405,6 @@ nsRuleNode::operator new(size_t sz, nsPresContext* aPresContext) CPP_THROW_NEW return aPresContext->PresShell()->AllocateByObjectID(nsPresArena::nsRuleNode_id, sz); } -/* static */ PLDHashOperator -nsRuleNode::EnqueueRuleNodeChildren(PLDHashTable *table, PLDHashEntryHdr *hdr, - uint32_t number, void *arg) -{ - ChildrenHashEntry *entry = static_cast(hdr); - nsRuleNode ***destroyQueueTail = static_cast(arg); - **destroyQueueTail = entry->mRuleNode; - *destroyQueueTail = &entry->mRuleNode->mNextSibling; - return PL_DHASH_NEXT; -} - // Overridden to prevent the global delete from being called, since the memory // came out of an nsIArena instead of the global delete operator's heap. void @@ -1431,8 +1420,11 @@ nsRuleNode::DestroyInternal(nsRuleNode ***aDestroyQueueTail) if (ChildrenAreHashed()) { PLDHashTable *children = ChildrenHash(); - PL_DHashTableEnumerate(children, EnqueueRuleNodeChildren, - &destroyQueueTail); + for (auto iter = children->Iter(); !iter.Done(); iter.Next()) { + auto entry = static_cast(iter.Get()); + *destroyQueueTail = entry->mRuleNode; + destroyQueueTail = &entry->mRuleNode->mNextSibling; + } *destroyQueueTail = nullptr; // ensure null-termination delete children; } else if (HaveChildren()) { @@ -8023,7 +8015,7 @@ nsRuleNode::ComputeTableBorderData(void* aStartStruct, table->mCaptionSide, conditions, SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, parentTable->mCaptionSide, - NS_STYLE_CAPTION_SIDE_TOP, 0, 0, 0, 0); + NS_STYLE_CAPTION_SIDE_BSTART, 0, 0, 0, 0); // empty-cells: enum, inherit, initial SetDiscrete(*aRuleData->ValueForEmptyCells(), @@ -9397,25 +9389,6 @@ nsRuleNode::DestroyIfNotMarked() return false; } -PLDHashOperator -nsRuleNode::SweepHashEntry(PLDHashTable *table, PLDHashEntryHdr *hdr, - uint32_t number, void *arg) -{ - ChildrenHashEntry *entry = static_cast(hdr); - nsRuleNode* node = entry->mRuleNode; - if (node->DestroyIfNotMarked()) { - return PL_DHASH_REMOVE; // implies NEXT, unless |ed with STOP - } - if (node->HaveChildren()) { - // When children are hashed mNextSibling is not normally used but we use it - // here to build a list of children that needs to be swept. - nsRuleNode** headQ = static_cast(arg); - node->mNextSibling = *headQ; - *headQ = node; - } - return PL_DHASH_NEXT; -} - void nsRuleNode::SweepChildren(nsTArray& aSweepQueue) { @@ -9428,7 +9401,19 @@ nsRuleNode::SweepChildren(nsTArray& aSweepQueue) if (ChildrenAreHashed()) { PLDHashTable* children = ChildrenHash(); uint32_t oldChildCount = children->EntryCount(); - PL_DHashTableEnumerate(children, SweepHashEntry, &survivorsWithChildren); + for (auto iter = children->Iter(); !iter.Done(); iter.Next()) { + auto entry = static_cast(iter.Get()); + nsRuleNode* node = entry->mRuleNode; + if (node->DestroyIfNotMarked()) { + iter.Remove(); + } else if (node->HaveChildren()) { + // When children are hashed mNextSibling is not normally used but we + // use it here to build a list of children that needs to be swept. + nsRuleNode** headQ = &survivorsWithChildren; + node->mNextSibling = *headQ; + *headQ = node; + } + } childrenDestroyed = oldChildCount - children->EntryCount(); if (childrenDestroyed == oldChildCount) { delete children; diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index 437cbeab65..e149f49f35 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -1706,7 +1706,7 @@ nsStyleTableBorder::nsStyleTableBorder() mBorderCollapse = NS_STYLE_BORDER_SEPARATE; mEmptyCells = NS_STYLE_TABLE_EMPTY_CELLS_SHOW; - mCaptionSide = NS_STYLE_CAPTION_SIDE_TOP; + mCaptionSide = NS_STYLE_CAPTION_SIDE_BSTART; mBorderSpacingCol = 0; mBorderSpacingRow = 0; } diff --git a/layout/style/nsStyleTransformMatrix.cpp b/layout/style/nsStyleTransformMatrix.cpp index 2716b8cb67..d0f416d798 100644 --- a/layout/style/nsStyleTransformMatrix.cpp +++ b/layout/style/nsStyleTransformMatrix.cpp @@ -726,8 +726,13 @@ ReadTransforms(const nsCSSValueList* aList, for (const nsCSSValueList* curr = aList; curr != nullptr; curr = curr->mNext) { const nsCSSValue &currElem = curr->mValue; - NS_ASSERTION(currElem.GetUnit() == eCSSUnit_Function, - "Stream should consist solely of functions!"); + if (currElem.GetUnit() != eCSSUnit_Function) { + NS_ASSERTION(currElem.GetUnit() == eCSSUnit_None && + !aList->mNext, + "stream should either be a list of functions or a " + "lone None"); + continue; + } NS_ASSERTION(currElem.GetArrayValue()->Count() >= 1, "Incoming function is too short!"); diff --git a/layout/style/test/property_database.js b/layout/style/test/property_database.js index 45469c031b..de5e9a5ce3 100644 --- a/layout/style/test/property_database.js +++ b/layout/style/test/property_database.js @@ -2361,8 +2361,8 @@ var gCSSProperties = { domProp: "captionSide", inherited: true, type: CSS_TYPE_LONGHAND, - initial_values: [ "top" ], - other_values: [ "block-start", "block-end", "inline-start", "inline-end", "block-start-outside", "block-end-outside", "bottom", "left", "right", "top-outside", "bottom-outside" ], + initial_values: [ "block-start" ], + other_values: [ "block-end", "inline-start", "inline-end", "block-start-outside", "block-end-outside", "top", "bottom", "left", "right", "top-outside", "bottom-outside" ], invalid_values: [] }, "clear": { diff --git a/layout/style/test/test_animations_omta.html b/layout/style/test/test_animations_omta.html index 2f147c173e..f579e77c24 100644 --- a/layout/style/test/test_animations_omta.html +++ b/layout/style/test/test_animations_omta.html @@ -159,6 +159,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=964646 0% { opacity: 0.2 } 100% { opacity: 0.8 } } + + @keyframes transformnone { + 0%, 100% { transform: translateX(50px) } + 25%, 75% { transform: none } + } @@ -2194,6 +2199,17 @@ addAsyncAnimTest(function *() { omta_is("opacity", 0.875, RunningOn.Compositor, "anim2 at 900ms"); done_div(); + + // Test that an interpolation that produces transform: none doesn't + // crash. + new_div("animation: transformnone 1s linear"); + yield waitForPaintsFlushed(); + omta_is("transform", { tx: 50 }, RunningOn.Compositor, + "transformnone animation at 0ms"); + advance_clock(500); + omta_is("transform", { tx: 0 }, RunningOn.Compositor, + "transformnone animation at 500ms, interpolating none values"); + done_div(); }); diff --git a/layout/tables/FixedTableLayoutStrategy.cpp b/layout/tables/FixedTableLayoutStrategy.cpp index dbb93134dc..4d0e32368e 100644 --- a/layout/tables/FixedTableLayoutStrategy.cpp +++ b/layout/tables/FixedTableLayoutStrategy.cpp @@ -1,12 +1,12 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -// vim:cindent:ts=4:et:sw=4: +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +// vim:cindent:ts=2:et:sw=2: /* 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/. */ /* - * Algorithms that determine column and table widths used for CSS2's - * 'table-layout: fixed'. + * Algorithms that determine column and table inline sizes used for + * CSS2's 'table-layout: fixed'. */ #include "FixedTableLayoutStrategy.h" @@ -19,7 +19,7 @@ FixedTableLayoutStrategy::FixedTableLayoutStrategy(nsTableFrame *aTableFrame) : nsITableLayoutStrategy(nsITableLayoutStrategy::Fixed) , mTableFrame(aTableFrame) { - MarkIntrinsicISizesDirty(); + MarkIntrinsicISizesDirty(); } /* virtual */ @@ -30,398 +30,404 @@ FixedTableLayoutStrategy::~FixedTableLayoutStrategy() /* virtual */ nscoord FixedTableLayoutStrategy::GetMinISize(nsRenderingContext* aRenderingContext) { - DISPLAY_MIN_WIDTH(mTableFrame, mMinWidth); - if (mMinWidth != NS_INTRINSIC_WIDTH_UNKNOWN) - return mMinWidth; + DISPLAY_MIN_WIDTH(mTableFrame, mMinISize); + if (mMinISize != NS_INTRINSIC_WIDTH_UNKNOWN) { + return mMinISize; + } - // It's theoretically possible to do something much better here that - // depends only on the columns and the first row (where we look at - // intrinsic widths inside the first row and then reverse the - // algorithm to find the narrowest width that would hold all of - // those intrinsic widths), but it wouldn't be compatible with other - // browsers, or with the use of GetMinISize by - // nsTableFrame::ComputeSize to determine the width of a fixed - // layout table, since CSS2.1 says: - // The width of the table is then the greater of the value of the - // 'width' property for the table element and the sum of the - // column widths (plus cell spacing or borders). + // It's theoretically possible to do something much better here that + // depends only on the columns and the first row (where we look at + // intrinsic inline sizes inside the first row and then reverse the + // algorithm to find the narrowest inline size that would hold all of + // those intrinsic inline sizes), but it wouldn't be compatible with + // other browsers, or with the use of GetMinISize by + // nsTableFrame::ComputeSize to determine the inline size of a fixed + // layout table, since CSS2.1 says: + // The width of the table is then the greater of the value of the + // 'width' property for the table element and the sum of the column + // widths (plus cell spacing or borders). - // XXX Should we really ignore 'min-width' and 'max-width'? - // XXX Should we really ignore widths on column groups? + // XXX Should we really ignore 'min-width' and 'max-width'? + // XXX Should we really ignore widths on column groups? - nsTableCellMap *cellMap = mTableFrame->GetCellMap(); - int32_t colCount = cellMap->GetColCount(); + nsTableCellMap *cellMap = mTableFrame->GetCellMap(); + int32_t colCount = cellMap->GetColCount(); - nscoord result = 0; + nscoord result = 0; - if (colCount > 0) { - result += mTableFrame->GetColSpacing(-1, colCount); + if (colCount > 0) { + result += mTableFrame->GetColSpacing(-1, colCount); + } + + WritingMode wm = mTableFrame->GetWritingMode(); + for (int32_t col = 0; col < colCount; ++col) { + nsTableColFrame *colFrame = mTableFrame->GetColFrame(col); + if (!colFrame) { + NS_ERROR("column frames out of sync with cell map"); + continue; } + nscoord spacing = mTableFrame->GetColSpacing(col); + const nsStyleCoord *styleISize = &colFrame->StylePosition()->ISize(wm); + if (styleISize->ConvertsToLength()) { + result += nsLayoutUtils::ComputeISizeValue(aRenderingContext, + colFrame, 0, 0, 0, + *styleISize); + } else if (styleISize->GetUnit() == eStyleUnit_Percent) { + // do nothing + } else { + NS_ASSERTION(styleISize->GetUnit() == eStyleUnit_Auto || + styleISize->GetUnit() == eStyleUnit_Enumerated || + (styleISize->IsCalcUnit() && styleISize->CalcHasPercent()), + "bad inline size"); - for (int32_t col = 0; col < colCount; ++col) { - nsTableColFrame *colFrame = mTableFrame->GetColFrame(col); - if (!colFrame) { - NS_ERROR("column frames out of sync with cell map"); - continue; - } - nscoord spacing = mTableFrame->GetColSpacing(col); - const nsStyleCoord *styleWidth = - &colFrame->StylePosition()->mWidth; - if (styleWidth->ConvertsToLength()) { - result += nsLayoutUtils::ComputeWidthValue(aRenderingContext, - colFrame, 0, 0, 0, *styleWidth); - } else if (styleWidth->GetUnit() == eStyleUnit_Percent) { - // do nothing - } else { - NS_ASSERTION(styleWidth->GetUnit() == eStyleUnit_Auto || - styleWidth->GetUnit() == eStyleUnit_Enumerated || - (styleWidth->IsCalcUnit() && styleWidth->CalcHasPercent()), - "bad width"); - - // The 'table-layout: fixed' algorithm considers only cells - // in the first row. - bool originates; - int32_t colSpan; - nsTableCellFrame *cellFrame = - cellMap->GetCellInfoAt(0, col, &originates, &colSpan); - if (cellFrame) { - styleWidth = &cellFrame->StylePosition()->mWidth; - if (styleWidth->ConvertsToLength() || - (styleWidth->GetUnit() == eStyleUnit_Enumerated && - (styleWidth->GetIntValue() == NS_STYLE_WIDTH_MAX_CONTENT || - styleWidth->GetIntValue() == NS_STYLE_WIDTH_MIN_CONTENT))) { - nscoord cellWidth = nsLayoutUtils::IntrinsicForContainer( - aRenderingContext, cellFrame, nsLayoutUtils::MIN_ISIZE); - if (colSpan > 1) { - // If a column-spanning cell is in the first - // row, split up the space evenly. (XXX This - // isn't quite right if some of the columns it's - // in have specified widths. Should we care?) - cellWidth = ((cellWidth + spacing) / colSpan) - spacing; - } - result += cellWidth; - } else if (styleWidth->GetUnit() == eStyleUnit_Percent) { - if (colSpan > 1) { - // XXX Can this force columns to negative - // widths? - result -= spacing * (colSpan - 1); - } - } - // else, for 'auto', '-moz-available', '-moz-fit-content', - // and 'calc()' with percentages, do nothing - } + // The 'table-layout: fixed' algorithm considers only cells in the + // first row. + bool originates; + int32_t colSpan; + nsTableCellFrame *cellFrame = cellMap->GetCellInfoAt(0, col, &originates, + &colSpan); + if (cellFrame) { + styleISize = &cellFrame->StylePosition()->ISize(wm); + if (styleISize->ConvertsToLength() || + (styleISize->GetUnit() == eStyleUnit_Enumerated && + (styleISize->GetIntValue() == NS_STYLE_WIDTH_MAX_CONTENT || + styleISize->GetIntValue() == NS_STYLE_WIDTH_MIN_CONTENT))) { + nscoord cellISize = + nsLayoutUtils::IntrinsicForContainer(aRenderingContext, cellFrame, + nsLayoutUtils::MIN_ISIZE); + if (colSpan > 1) { + // If a column-spanning cell is in the first row, split up + // the space evenly. (XXX This isn't quite right if some of + // the columns it's in have specified inline sizes. Should + // we care?) + cellISize = ((cellISize + spacing) / colSpan) - spacing; + } + result += cellISize; + } else if (styleISize->GetUnit() == eStyleUnit_Percent) { + if (colSpan > 1) { + // XXX Can this force columns to negative inline sizes? + result -= spacing * (colSpan - 1); + } } + // else, for 'auto', '-moz-available', '-moz-fit-content', + // and 'calc()' with percentages, do nothing + } } + } - return (mMinWidth = result); + return (mMinISize = result); } /* virtual */ nscoord FixedTableLayoutStrategy::GetPrefISize(nsRenderingContext* aRenderingContext, bool aComputingSize) { - // It's theoretically possible to do something much better here that - // depends only on the columns and the first row (where we look at - // intrinsic widths inside the first row and then reverse the - // algorithm to find the narrowest width that would hold all of - // those intrinsic widths), but it wouldn't be compatible with other - // browsers. - nscoord result = nscoord_MAX; - DISPLAY_PREF_WIDTH(mTableFrame, result); - return result; + // It's theoretically possible to do something much better here that + // depends only on the columns and the first row (where we look at + // intrinsic inline sizes inside the first row and then reverse the + // algorithm to find the narrowest inline size that would hold all of + // those intrinsic inline sizes), but it wouldn't be compatible with + // other browsers. + nscoord result = nscoord_MAX; + DISPLAY_PREF_WIDTH(mTableFrame, result); + return result; } /* virtual */ void FixedTableLayoutStrategy::MarkIntrinsicISizesDirty() { - mMinWidth = NS_INTRINSIC_WIDTH_UNKNOWN; - mLastCalcWidth = nscoord_MIN; + mMinISize = NS_INTRINSIC_WIDTH_UNKNOWN; + mLastCalcISize = nscoord_MIN; } static inline nscoord AllocateUnassigned(nscoord aUnassignedSpace, float aShare) { - if (aShare == 1.0f) { - // This happens when the numbers we're dividing to get aShare - // are equal. We want to return unassignedSpace exactly, even - // if it can't be precisely round-tripped through float. - return aUnassignedSpace; - } - return NSToCoordRound(float(aUnassignedSpace) * aShare); + if (aShare == 1.0f) { + // This happens when the numbers we're dividing to get aShare are + // equal. We want to return unassignedSpace exactly, even if it + // can't be precisely round-tripped through float. + return aUnassignedSpace; + } + return NSToCoordRound(float(aUnassignedSpace) * aShare); } /* virtual */ void FixedTableLayoutStrategy::ComputeColumnISizes(const nsHTMLReflowState& aReflowState) { - nscoord tableWidth = aReflowState.ComputedWidth(); + nscoord tableISize = aReflowState.ComputedISize(); - if (mLastCalcWidth == tableWidth) - return; - mLastCalcWidth = tableWidth; + if (mLastCalcISize == tableISize) { + return; + } + mLastCalcISize = tableISize; - nsTableCellMap *cellMap = mTableFrame->GetCellMap(); - int32_t colCount = cellMap->GetColCount(); + nsTableCellMap *cellMap = mTableFrame->GetCellMap(); + int32_t colCount = cellMap->GetColCount(); - if (colCount == 0) { - // No Columns - nothing to compute - return; + if (colCount == 0) { + // No Columns - nothing to compute + return; + } + + // border-spacing isn't part of the basis for percentages. + tableISize -= mTableFrame->GetColSpacing(-1, colCount); + + // store the old column inline sizes. We might call SetFinalISize + // multiple times on the columns, due to this we can't compare at the + // last call that the inline size has changed with respect to the last + // call to ComputeColumnISizes. In order to overcome this we store the + // old values in this array. A single call to SetFinalISize would make + // it possible to call GetFinalISize before and to compare when + // setting the final inline size. + nsTArray oldColISizes; + + // XXX This ignores the 'min-width' and 'max-width' properties + // throughout. Then again, that's what the CSS spec says to do. + + // XXX Should we really ignore widths on column groups? + + uint32_t unassignedCount = 0; + nscoord unassignedSpace = tableISize; + const nscoord unassignedMarker = nscoord_MIN; + + // We use the PrefPercent on the columns to store the percentages + // used to compute column inline sizes in case we need to shrink or + // expand the columns. + float pctTotal = 0.0f; + + // Accumulate the total specified (non-percent) on the columns for + // distributing excess inline size to the columns. + nscoord specTotal = 0; + + WritingMode wm = mTableFrame->GetWritingMode(); + for (int32_t col = 0; col < colCount; ++col) { + nsTableColFrame *colFrame = mTableFrame->GetColFrame(col); + if (!colFrame) { + oldColISizes.AppendElement(0); + NS_ERROR("column frames out of sync with cell map"); + continue; + } + oldColISizes.AppendElement(colFrame->GetFinalISize()); + colFrame->ResetPrefPercent(); + const nsStyleCoord *styleISize = &colFrame->StylePosition()->ISize(wm); + nscoord colISize; + if (styleISize->ConvertsToLength()) { + colISize = nsLayoutUtils::ComputeISizeValue(aReflowState.rendContext, + colFrame, 0, 0, 0, + *styleISize); + specTotal += colISize; + } else if (styleISize->GetUnit() == eStyleUnit_Percent) { + float pct = styleISize->GetPercentValue(); + colISize = NSToCoordFloor(pct * float(tableISize)); + colFrame->AddPrefPercent(pct); + pctTotal += pct; + } else { + NS_ASSERTION(styleISize->GetUnit() == eStyleUnit_Auto || + styleISize->GetUnit() == eStyleUnit_Enumerated || + (styleISize->IsCalcUnit() && styleISize->CalcHasPercent()), + "bad inline size"); + + // The 'table-layout: fixed' algorithm considers only cells in the + // first row. + bool originates; + int32_t colSpan; + nsTableCellFrame *cellFrame = cellMap->GetCellInfoAt(0, col, &originates, + &colSpan); + if (cellFrame) { + styleISize = &cellFrame->StylePosition()->ISize(wm); + if (styleISize->ConvertsToLength() || + (styleISize->GetUnit() == eStyleUnit_Enumerated && + (styleISize->GetIntValue() == NS_STYLE_WIDTH_MAX_CONTENT || + styleISize->GetIntValue() == NS_STYLE_WIDTH_MIN_CONTENT))) { + // XXX This should use real percentage padding + // Note that the difference between MIN_ISIZE and PREF_ISIZE + // shouldn't matter for any of these values of styleISize; use + // MIN_ISIZE for symmetry with GetMinISize above, just in case + // there is a difference. + colISize = + nsLayoutUtils::IntrinsicForContainer(aReflowState.rendContext, + cellFrame, + nsLayoutUtils::MIN_ISIZE); + } else if (styleISize->GetUnit() == eStyleUnit_Percent) { + // XXX This should use real percentage padding + nsIFrame::IntrinsicISizeOffsetData offsets = + cellFrame->IntrinsicISizeOffsets(); + float pct = styleISize->GetPercentValue(); + colISize = NSToCoordFloor(pct * float(tableISize)); + + nscoord boxSizingAdjust = 0; + switch (cellFrame->StylePosition()->mBoxSizing) { + case NS_STYLE_BOX_SIZING_CONTENT: + boxSizingAdjust += offsets.hPadding; + // Fall through + case NS_STYLE_BOX_SIZING_PADDING: + boxSizingAdjust += offsets.hBorder; + // Fall through + case NS_STYLE_BOX_SIZING_BORDER: + // Don't add anything + break; + } + colISize += boxSizingAdjust; + + pct /= float(colSpan); + colFrame->AddPrefPercent(pct); + pctTotal += pct; + } else { + // 'auto', '-moz-available', '-moz-fit-content', and 'calc()' + // with percentages + colISize = unassignedMarker; + } + if (colISize != unassignedMarker) { + if (colSpan > 1) { + // If a column-spanning cell is in the first row, split up + // the space evenly. (XXX This isn't quite right if some of + // the columns it's in have specified iSizes. Should we + // care?) + nscoord spacing = mTableFrame->GetColSpacing(col); + colISize = ((colISize + spacing) / colSpan) - spacing; + if (colISize < 0) { + colISize = 0; + } + } + if (styleISize->GetUnit() != eStyleUnit_Percent) { + specTotal += colISize; + } + } + } else { + colISize = unassignedMarker; + } } - // border-spacing isn't part of the basis for percentages. - tableWidth -= mTableFrame->GetColSpacing(-1, colCount); + colFrame->SetFinalISize(colISize); - // store the old column widths. We might call multiple times SetFinalISize - // on the columns, due to this we can't compare at the last call that the - // width has changed with the respect to the last call to - // ComputeColumnISizes. In order to overcome this we store the old values - // in this array. A single call to SetFinalISize would make it possible to - // call GetFinalISize before and to compare when setting the final width. - nsTArray oldColWidths; + if (colISize == unassignedMarker) { + ++unassignedCount; + } else { + unassignedSpace -= colISize; + } + } - // XXX This ignores the 'min-width' and 'max-width' properties - // throughout. Then again, that's what the CSS spec says to do. + if (unassignedSpace < 0) { + if (pctTotal > 0) { + // If the columns took up too much space, reduce those that had + // percentage inline sizes. The spec doesn't say to do this, but + // we've always done it in the past, and so does WinIE6. + nscoord pctUsed = NSToCoordFloor(pctTotal * float(tableISize)); + nscoord reduce = std::min(pctUsed, -unassignedSpace); + float reduceRatio = float(reduce) / pctTotal; + for (int32_t col = 0; col < colCount; ++col) { + nsTableColFrame *colFrame = mTableFrame->GetColFrame(col); + if (!colFrame) { + NS_ERROR("column frames out of sync with cell map"); + continue; + } + nscoord colISize = colFrame->GetFinalISize(); + colISize -= NSToCoordFloor(colFrame->GetPrefPercent() * reduceRatio); + if (colISize < 0) { + colISize = 0; + } + colFrame->SetFinalISize(colISize); + } + } + unassignedSpace = 0; + } - // XXX Should we really ignore widths on column groups? - - uint32_t unassignedCount = 0; - nscoord unassignedSpace = tableWidth; - const nscoord unassignedMarker = nscoord_MIN; - - // We use the PrefPercent on the columns to store the percentages - // used to compute column widths in case we need to shrink or expand + if (unassignedCount > 0) { + // The spec says to distribute the remaining space evenly among // the columns. - float pctTotal = 0.0f; - - // Accumulate the total specified (non-percent) on the columns for - // distributing excess width to the columns. - nscoord specTotal = 0; - + nscoord toAssign = unassignedSpace / unassignedCount; for (int32_t col = 0; col < colCount; ++col) { + nsTableColFrame *colFrame = mTableFrame->GetColFrame(col); + if (!colFrame) { + NS_ERROR("column frames out of sync with cell map"); + continue; + } + if (colFrame->GetFinalISize() == unassignedMarker) { + colFrame->SetFinalISize(toAssign); + } + } + } else if (unassignedSpace > 0) { + // The spec doesn't say how to distribute the unassigned space. + if (specTotal > 0) { + // Distribute proportionally to non-percentage columns. + nscoord specUndist = specTotal; + for (int32_t col = 0; col < colCount; ++col) { nsTableColFrame *colFrame = mTableFrame->GetColFrame(col); if (!colFrame) { - oldColWidths.AppendElement(0); - NS_ERROR("column frames out of sync with cell map"); - continue; + NS_ERROR("column frames out of sync with cell map"); + continue; } - oldColWidths.AppendElement(colFrame->GetFinalISize()); - colFrame->ResetPrefPercent(); - const nsStyleCoord *styleWidth = - &colFrame->StylePosition()->mWidth; - nscoord colWidth; - if (styleWidth->ConvertsToLength()) { - colWidth = nsLayoutUtils::ComputeWidthValue( - aReflowState.rendContext, - colFrame, 0, 0, 0, *styleWidth); - specTotal += colWidth; - } else if (styleWidth->GetUnit() == eStyleUnit_Percent) { - float pct = styleWidth->GetPercentValue(); - colWidth = NSToCoordFloor(pct * float(tableWidth)); - colFrame->AddPrefPercent(pct); - pctTotal += pct; - } else { - NS_ASSERTION(styleWidth->GetUnit() == eStyleUnit_Auto || - styleWidth->GetUnit() == eStyleUnit_Enumerated || - (styleWidth->IsCalcUnit() && styleWidth->CalcHasPercent()), - "bad width"); - - // The 'table-layout: fixed' algorithm considers only cells - // in the first row. - bool originates; - int32_t colSpan; - nsTableCellFrame *cellFrame = - cellMap->GetCellInfoAt(0, col, &originates, &colSpan); - if (cellFrame) { - styleWidth = &cellFrame->StylePosition()->mWidth; - if (styleWidth->ConvertsToLength() || - (styleWidth->GetUnit() == eStyleUnit_Enumerated && - (styleWidth->GetIntValue() == NS_STYLE_WIDTH_MAX_CONTENT || - styleWidth->GetIntValue() == NS_STYLE_WIDTH_MIN_CONTENT))) { - // XXX This should use real percentage padding - // Note that the difference between MIN_ISIZE and - // PREF_ISIZE shouldn't matter for any of these - // values of styleWidth; use MIN_ISIZE for symmetry - // with GetMinISize above, just in case there is a - // difference. - colWidth = nsLayoutUtils::IntrinsicForContainer( - aReflowState.rendContext, - cellFrame, nsLayoutUtils::MIN_ISIZE); - } else if (styleWidth->GetUnit() == eStyleUnit_Percent) { - // XXX This should use real percentage padding - nsIFrame::IntrinsicISizeOffsetData offsets = - cellFrame->IntrinsicISizeOffsets(); - float pct = styleWidth->GetPercentValue(); - colWidth = NSToCoordFloor(pct * float(tableWidth)); - - nscoord boxSizingAdjust = 0; - switch (cellFrame->StylePosition()->mBoxSizing) { - case NS_STYLE_BOX_SIZING_CONTENT: - boxSizingAdjust += offsets.hPadding; - // Fall through - case NS_STYLE_BOX_SIZING_PADDING: - boxSizingAdjust += offsets.hBorder; - // Fall through - case NS_STYLE_BOX_SIZING_BORDER: - // Don't add anything - break; - } - colWidth += boxSizingAdjust; - - pct /= float(colSpan); - colFrame->AddPrefPercent(pct); - pctTotal += pct; - } else { - // 'auto', '-moz-available', '-moz-fit-content', and - // 'calc()' with percentages - colWidth = unassignedMarker; - } - if (colWidth != unassignedMarker) { - if (colSpan > 1) { - // If a column-spanning cell is in the first - // row, split up the space evenly. (XXX This - // isn't quite right if some of the columns it's - // in have specified widths. Should we care?) - nscoord spacing = mTableFrame->GetColSpacing(col); - colWidth = ((colWidth + spacing) / colSpan) - spacing; - if (colWidth < 0) - colWidth = 0; - } - if (styleWidth->GetUnit() != eStyleUnit_Percent) { - specTotal += colWidth; - } - } - } else { - colWidth = unassignedMarker; - } - } - - colFrame->SetFinalISize(colWidth); - - if (colWidth == unassignedMarker) { - ++unassignedCount; - } else { - unassignedSpace -= colWidth; - } - } - - if (unassignedSpace < 0) { - if (pctTotal > 0) { - // If the columns took up too much space, reduce those that - // had percentage widths. The spec doesn't say to do this, - // but we've always done it in the past, and so does WinIE6. - nscoord pctUsed = NSToCoordFloor(pctTotal * float(tableWidth)); - nscoord reduce = std::min(pctUsed, -unassignedSpace); - float reduceRatio = float(reduce) / pctTotal; - for (int32_t col = 0; col < colCount; ++col) { - nsTableColFrame *colFrame = mTableFrame->GetColFrame(col); - if (!colFrame) { - NS_ERROR("column frames out of sync with cell map"); - continue; - } - nscoord colWidth = colFrame->GetFinalISize(); - colWidth -= NSToCoordFloor(colFrame->GetPrefPercent() * - reduceRatio); - if (colWidth < 0) - colWidth = 0; - colFrame->SetFinalISize(colWidth); - } - } - unassignedSpace = 0; - } - - if (unassignedCount > 0) { - // The spec says to distribute the remaining space evenly among - // the columns. - nscoord toAssign = unassignedSpace / unassignedCount; - for (int32_t col = 0; col < colCount; ++col) { - nsTableColFrame *colFrame = mTableFrame->GetColFrame(col); - if (!colFrame) { - NS_ERROR("column frames out of sync with cell map"); - continue; - } - if (colFrame->GetFinalISize() == unassignedMarker) - colFrame->SetFinalISize(toAssign); - } - } else if (unassignedSpace > 0) { - // The spec doesn't say how to distribute the unassigned space. - if (specTotal > 0) { - // Distribute proportionally to non-percentage columns. - nscoord specUndist = specTotal; - for (int32_t col = 0; col < colCount; ++col) { - nsTableColFrame *colFrame = mTableFrame->GetColFrame(col); - if (!colFrame) { - NS_ERROR("column frames out of sync with cell map"); - continue; - } - if (colFrame->GetPrefPercent() == 0.0f) { - NS_ASSERTION(colFrame->GetFinalISize() <= specUndist, - "widths don't add up"); - nscoord toAdd = AllocateUnassigned(unassignedSpace, - float(colFrame->GetFinalISize()) / float(specUndist)); - specUndist -= colFrame->GetFinalISize(); - colFrame->SetFinalISize(colFrame->GetFinalISize() + toAdd); - unassignedSpace -= toAdd; - if (specUndist <= 0) { - NS_ASSERTION(specUndist == 0, - "math should be exact"); - break; - } - } - } - NS_ASSERTION(unassignedSpace == 0, "failed to redistribute"); - } else if (pctTotal > 0) { - // Distribute proportionally to percentage columns. - float pctUndist = pctTotal; - for (int32_t col = 0; col < colCount; ++col) { - nsTableColFrame *colFrame = mTableFrame->GetColFrame(col); - if (!colFrame) { - NS_ERROR("column frames out of sync with cell map"); - continue; - } - if (pctUndist < colFrame->GetPrefPercent()) { - // This can happen with floating-point math. - NS_ASSERTION(colFrame->GetPrefPercent() - pctUndist - < 0.0001, - "widths don't add up"); - pctUndist = colFrame->GetPrefPercent(); - } - nscoord toAdd = AllocateUnassigned(unassignedSpace, - colFrame->GetPrefPercent() / pctUndist); - colFrame->SetFinalISize(colFrame->GetFinalISize() + toAdd); - unassignedSpace -= toAdd; - pctUndist -= colFrame->GetPrefPercent(); - if (pctUndist <= 0.0f) { - break; - } - } - NS_ASSERTION(unassignedSpace == 0, "failed to redistribute"); - } else { - // Distribute equally to the zero-width columns. - int32_t colsLeft = colCount; - for (int32_t col = 0; col < colCount; ++col) { - nsTableColFrame *colFrame = mTableFrame->GetColFrame(col); - if (!colFrame) { - NS_ERROR("column frames out of sync with cell map"); - continue; - } - NS_ASSERTION(colFrame->GetFinalISize() == 0, "yikes"); - nscoord toAdd = AllocateUnassigned(unassignedSpace, - 1.0f / float(colsLeft)); - colFrame->SetFinalISize(toAdd); - unassignedSpace -= toAdd; - --colsLeft; - } - NS_ASSERTION(unassignedSpace == 0, "failed to redistribute"); - } - } - for (int32_t col = 0; col < colCount; ++col) { - nsTableColFrame *colFrame = mTableFrame->GetColFrame(col); - if (!colFrame) { - NS_ERROR("column frames out of sync with cell map"); - continue; - } - if (oldColWidths.ElementAt(col) != colFrame->GetFinalISize()) { - mTableFrame->DidResizeColumns(); + if (colFrame->GetPrefPercent() == 0.0f) { + NS_ASSERTION(colFrame->GetFinalISize() <= specUndist, + "inline sizes don't add up"); + nscoord toAdd = AllocateUnassigned(unassignedSpace, + float(colFrame->GetFinalISize()) / + float(specUndist)); + specUndist -= colFrame->GetFinalISize(); + colFrame->SetFinalISize(colFrame->GetFinalISize() + toAdd); + unassignedSpace -= toAdd; + if (specUndist <= 0) { + NS_ASSERTION(specUndist == 0, "math should be exact"); break; + } } + } + NS_ASSERTION(unassignedSpace == 0, "failed to redistribute"); + } else if (pctTotal > 0) { + // Distribute proportionally to percentage columns. + float pctUndist = pctTotal; + for (int32_t col = 0; col < colCount; ++col) { + nsTableColFrame *colFrame = mTableFrame->GetColFrame(col); + if (!colFrame) { + NS_ERROR("column frames out of sync with cell map"); + continue; + } + if (pctUndist < colFrame->GetPrefPercent()) { + // This can happen with floating-point math. + NS_ASSERTION(colFrame->GetPrefPercent() - pctUndist < 0.0001, + "inline sizes don't add up"); + pctUndist = colFrame->GetPrefPercent(); + } + nscoord toAdd = AllocateUnassigned(unassignedSpace, + colFrame->GetPrefPercent() / + pctUndist); + colFrame->SetFinalISize(colFrame->GetFinalISize() + toAdd); + unassignedSpace -= toAdd; + pctUndist -= colFrame->GetPrefPercent(); + if (pctUndist <= 0.0f) { + break; + } + } + NS_ASSERTION(unassignedSpace == 0, "failed to redistribute"); + } else { + // Distribute equally to the zero-iSize columns. + int32_t colsRemaining = colCount; + for (int32_t col = 0; col < colCount; ++col) { + nsTableColFrame *colFrame = mTableFrame->GetColFrame(col); + if (!colFrame) { + NS_ERROR("column frames out of sync with cell map"); + continue; + } + NS_ASSERTION(colFrame->GetFinalISize() == 0, "yikes"); + nscoord toAdd = AllocateUnassigned(unassignedSpace, + 1.0f / float(colsRemaining)); + colFrame->SetFinalISize(toAdd); + unassignedSpace -= toAdd; + --colsRemaining; + } + NS_ASSERTION(unassignedSpace == 0, "failed to redistribute"); } + } + for (int32_t col = 0; col < colCount; ++col) { + nsTableColFrame *colFrame = mTableFrame->GetColFrame(col); + if (!colFrame) { + NS_ERROR("column frames out of sync with cell map"); + continue; + } + if (oldColISizes.ElementAt(col) != colFrame->GetFinalISize()) { + mTableFrame->DidResizeColumns(); + break; + } + } } diff --git a/layout/tables/FixedTableLayoutStrategy.h b/layout/tables/FixedTableLayoutStrategy.h index 7005106320..cea84195ca 100644 --- a/layout/tables/FixedTableLayoutStrategy.h +++ b/layout/tables/FixedTableLayoutStrategy.h @@ -1,5 +1,5 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -// vim:cindent:ts=4:et:sw=4: +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +// vim:cindent:ts=2:et:sw=2: /* 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/. */ @@ -20,20 +20,21 @@ class nsTableFrame; class FixedTableLayoutStrategy : public nsITableLayoutStrategy { public: - explicit FixedTableLayoutStrategy(nsTableFrame *aTableFrame); - virtual ~FixedTableLayoutStrategy(); + explicit FixedTableLayoutStrategy(nsTableFrame *aTableFrame); + virtual ~FixedTableLayoutStrategy(); - // nsITableLayoutStrategy implementation - virtual nscoord GetMinISize(nsRenderingContext* aRenderingContext) override; - virtual nscoord GetPrefISize(nsRenderingContext* aRenderingContext, - bool aComputingSize) override; - virtual void MarkIntrinsicISizesDirty() override; - virtual void ComputeColumnISizes(const nsHTMLReflowState& aReflowState) override; + // nsITableLayoutStrategy implementation + virtual nscoord GetMinISize(nsRenderingContext* aRenderingContext) override; + virtual nscoord GetPrefISize(nsRenderingContext* aRenderingContext, + bool aComputingSize) override; + virtual void MarkIntrinsicISizesDirty() override; + virtual void ComputeColumnISizes(const nsHTMLReflowState& aReflowState) + override; private: - nsTableFrame *mTableFrame; - nscoord mMinWidth; - nscoord mLastCalcWidth; + nsTableFrame *mTableFrame; + nscoord mMinISize; + nscoord mLastCalcISize; }; #endif /* !defined(FixedTableLayoutStrategy_h_) */ diff --git a/layout/tables/SpanningCellSorter.cpp b/layout/tables/SpanningCellSorter.cpp index a2334e35c8..9d20372d5f 100644 --- a/layout/tables/SpanningCellSorter.cpp +++ b/layout/tables/SpanningCellSorter.cpp @@ -86,18 +86,6 @@ SpanningCellSorter::AddCell(int32_t aColSpan, int32_t aRow, int32_t aCol) return true; } -/* static */ PLDHashOperator -SpanningCellSorter::FillSortedArray(PLDHashTable *table, PLDHashEntryHdr *hdr, - uint32_t number, void *arg) -{ - HashTableEntry *entry = static_cast(hdr); - HashTableEntry **sh = static_cast(arg); - - sh[number] = entry; - - return PL_DHASH_NEXT; -} - /* static */ int SpanningCellSorter::SortArray(const void *a, const void *b, void *closure) { @@ -143,7 +131,10 @@ SpanningCellSorter::GetNext(int32_t *aColSpan) if (mHashTable.EntryCount() > 0) { HashTableEntry **sh = new HashTableEntry*[mHashTable.EntryCount()]; - PL_DHashTableEnumerate(&mHashTable, FillSortedArray, sh); + int32_t j = 0; + for (auto iter = mHashTable.Iter(); !iter.Done(); iter.Next()) { + sh[j++] = static_cast(iter.Get()); + } NS_QuickSort(sh, mHashTable.EntryCount(), sizeof(sh[0]), SortArray, nullptr); mSortedHashTable = sh; diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp index 7c87a3a8d8..55b32519d8 100644 --- a/layout/tables/nsTableFrame.cpp +++ b/layout/tables/nsTableFrame.cpp @@ -3388,6 +3388,13 @@ nsTableFrame::DistributeBSizeToRows(const nsHTMLReflowState& aReflowState, WritingMode wm = aReflowState.GetWritingMode(); LogicalMargin borderPadding = GetChildAreaOffset(wm, &aReflowState); + nscoord containerWidth = aReflowState.ComputedWidth(); + if (containerWidth == NS_UNCONSTRAINEDSIZE) { + containerWidth = 0; + } else { + containerWidth += aReflowState.ComputedPhysicalBorderPadding().LeftRight(); + } + RowGroupArray rowGroups; OrderRowGroups(rowGroups); @@ -3403,13 +3410,13 @@ nsTableFrame::DistributeBSizeToRows(const nsHTMLReflowState& aReflowState, nsTableRowGroupFrame* rgFrame = rowGroups[rgX]; nscoord amountUsedByRG = 0; nscoord bOriginRow = 0; - // We pass containerWidth of zero when constructing the LogicalRect here, - // and similarly below. This is OK because these rects will be used to make - // relative adjustments, not for actual conversion to physical coords. - LogicalRect rgNormalRect(wm, rgFrame->GetNormalRect(), 0); + LogicalRect rgNormalRect(wm, rgFrame->GetNormalRect(), containerWidth); if (!rgFrame->HasStyleBSize()) { nsTableRowFrame* rowFrame = rgFrame->GetFirstRow(); while (rowFrame) { + // We don't know the final width of the rowGroupFrame yet, so use zero + // as a "fake" containerWidth here; we'll adjust the row positions at + // the end, after the rowGroup size is finalized. LogicalRect rowNormalRect(wm, rowFrame->GetNormalRect(), 0); nscoord cellSpacingB = GetRowSpacing(rowFrame->GetRowIndex()); if ((amountUsed < aAmount) && rowFrame->HasPctBSize()) { @@ -3547,12 +3554,12 @@ nsTableFrame::DistributeBSizeToRows(const nsHTMLReflowState& aReflowState, nsTableRowGroupFrame* rgFrame = rowGroups[rgX]; nscoord amountUsedByRG = 0; nscoord bOriginRow = 0; - LogicalRect rgNormalRect(wm, rgFrame->GetNormalRect(), 0); + LogicalRect rgNormalRect(wm, rgFrame->GetNormalRect(), containerWidth); nsRect rgVisualOverflow = rgFrame->GetVisualOverflowRect(); // see if there is an eligible row group or we distribute to all rows if (!firstUnStyledRG || !rgFrame->HasStyleBSize() || !eligibleRows) { - nsTableRowFrame* rowFrame = rgFrame->GetFirstRow(); - while (rowFrame) { + for (nsTableRowFrame* rowFrame = rgFrame->GetFirstRow(); + rowFrame; rowFrame = rowFrame->GetNextRow()) { nscoord cellSpacingB = GetRowSpacing(rowFrame->GetRowIndex()); LogicalRect rowNormalRect(wm, rowFrame->GetNormalRect(), 0); nsRect rowVisualOverflow = rowFrame->GetVisualOverflowRect(); @@ -3616,8 +3623,8 @@ nsTableFrame::DistributeBSizeToRows(const nsHTMLReflowState& aReflowState, bOriginRow += rowNormalRect.BSize(wm) + cellSpacingB; bEndRG += rowNormalRect.BSize(wm) + cellSpacingB; } - rowFrame = rowFrame->GetNextRow(); } + if (amountUsed > 0) { if (rgNormalRect.BStart(wm) != bOriginRG) { rgFrame->InvalidateFrameSubtree(); @@ -3632,7 +3639,23 @@ nsTableFrame::DistributeBSizeToRows(const nsHTMLReflowState& aReflowState, nsTableFrame::InvalidateTableFrame(rgFrame, origRgNormalRect, rgVisualOverflow, false); } - // Make sure child views are properly positioned + + // For vertical-rl mode, we needed to position the rows relative to the + // right-hand (block-start) side of the group; but we couldn't do that + // above, as we didn't know the rowGroupFrame's final block size yet. + // So we used a containerWidth of zero earlier, placing the rows to the + // left of the rowGroupFrame's (physical) origin. Now we move them all + // rightwards by its final width. + if (wm.IsVerticalRL()) { + nscoord rgWidth = rgFrame->GetRect().width; + for (nsTableRowFrame* rowFrame = rgFrame->GetFirstRow(); + rowFrame; rowFrame = rowFrame->GetNextRow()) { + rowFrame->InvalidateFrameSubtree(); + rowFrame->MovePositionBy(nsPoint(rgWidth, 0)); + nsTableFrame::RePositionViews(rowFrame); + rowFrame->InvalidateFrameSubtree(); + } + } } else if (amountUsed > 0 && bOriginRG != rgNormalRect.BStart(wm)) { rgFrame->InvalidateFrameSubtree(); @@ -3836,14 +3859,14 @@ nsTableFrame::IsAutoLayout() { if (StyleTable()->mLayoutStrategy == NS_STYLE_TABLE_LAYOUT_AUTO) return true; - // a fixed-layout inline-table must have a width - // and tables with 'width: -moz-max-content' must be auto-layout - // (at least as long as FixedTableLayoutStrategy::GetPrefISize returns - // nscoord_MAX) - const nsStyleCoord &width = StylePosition()->mWidth; - return (width.GetUnit() == eStyleUnit_Auto) || - (width.GetUnit() == eStyleUnit_Enumerated && - width.GetIntValue() == NS_STYLE_WIDTH_MAX_CONTENT); + // a fixed-layout inline-table must have a inline size + // and tables with inline size set to '-moz-max-content' must be + // auto-layout (at least as long as + // FixedTableLayoutStrategy::GetPrefISize returns nscoord_MAX) + const nsStyleCoord &iSize = StylePosition()->ISize(GetWritingMode()); + return (iSize.GetUnit() == eStyleUnit_Auto) || + (iSize.GetUnit() == eStyleUnit_Enumerated && + iSize.GetIntValue() == NS_STYLE_WIDTH_MAX_CONTENT); } #ifdef DEBUG_FRAME_DUMP diff --git a/modules/libpref/Preferences.cpp b/modules/libpref/Preferences.cpp index 21b6251f92..14c0825b8b 100644 --- a/modules/libpref/Preferences.cpp +++ b/modules/libpref/Preferences.cpp @@ -739,7 +739,11 @@ void Preferences::GetPreferences(InfallibleTArray* aPrefs) { aPrefs->SetCapacity(gHashTable->Capacity()); - PL_DHashTableEnumerate(gHashTable, pref_GetPrefs, aPrefs); + for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) { + auto entry = static_cast(iter.Get()); + dom::PrefSetting *pref = aPrefs->AppendElement(); + pref_GetPrefFromEntry(entry, pref); + } } NS_IMETHODIMP @@ -961,12 +965,9 @@ Preferences::WritePrefFile(nsIFile* aFile) nsAutoArrayPtr valueArray(new char*[gHashTable->EntryCount()]); memset(valueArray, 0, gHashTable->EntryCount() * sizeof(char*)); - pref_saveArgs saveArgs; - saveArgs.prefArray = valueArray; - saveArgs.saveTypes = SAVE_ALL; // get the lines that we're supposed to be writing to the file - PL_DHashTableEnumerate(gHashTable, pref_savePref, &saveArgs); + pref_savePrefs(gHashTable, valueArray); /* Sort the preferences to make a readable file on disk */ NS_QuickSort(valueArray, gHashTable->EntryCount(), sizeof(char *), diff --git a/modules/libpref/nsPrefBranch.cpp b/modules/libpref/nsPrefBranch.cpp index 4f858d68ee..1923bbd73c 100644 --- a/modules/libpref/nsPrefBranch.cpp +++ b/modules/libpref/nsPrefBranch.cpp @@ -42,17 +42,6 @@ } #endif -// Definitions -struct EnumerateData { - const char *parent; - nsTArray *pref_list; -}; - -// Prototypes -static PLDHashOperator - pref_enumChild(PLDHashTable *table, PLDHashEntryHdr *heh, - uint32_t i, void *arg); - using mozilla::dom::ContentChild; static ContentChild* @@ -531,7 +520,6 @@ NS_IMETHODIMP nsPrefBranch::GetChildList(const char *aStartingAt, uint32_t *aCou char **outArray; int32_t numPrefs; int32_t dwIndex; - EnumerateData ed; nsAutoTArray prefArray; NS_ENSURE_ARG(aStartingAt); @@ -544,9 +532,14 @@ NS_IMETHODIMP nsPrefBranch::GetChildList(const char *aStartingAt, uint32_t *aCou // this will contain a list of all the pref name strings // allocate on the stack for speed - ed.parent = getPrefName(aStartingAt); - ed.pref_list = &prefArray; - PL_DHashTableEnumerate(gHashTable, pref_enumChild, &ed); + const char* parent = getPrefName(aStartingAt); + size_t parentLen = strlen(parent); + for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) { + auto entry = static_cast(iter.Get()); + if (strncmp(entry->key, parent, parentLen) == 0) { + prefArray.AppendElement(entry->key); + } + } // now that we've built up the list, run the callback on // all the matching elements @@ -759,18 +752,6 @@ const char *nsPrefBranch::getPrefName(const char *aPrefName) return mPrefRoot.get(); } -static PLDHashOperator -pref_enumChild(PLDHashTable *table, PLDHashEntryHdr *heh, - uint32_t i, void *arg) -{ - PrefHashEntry *he = static_cast(heh); - EnumerateData *d = reinterpret_cast(arg); - if (strncmp(he->key, d->parent, strlen(d->parent)) == 0) { - d->pref_list->AppendElement(he->key); - } - return PL_DHASH_NEXT; -} - //---------------------------------------------------------------------------- // nsPrefLocalizedString //---------------------------------------------------------------------------- diff --git a/modules/libpref/prefapi.cpp b/modules/libpref/prefapi.cpp index 5cd5063bcd..6fec760839 100644 --- a/modules/libpref/prefapi.cpp +++ b/modules/libpref/prefapi.cpp @@ -319,79 +319,54 @@ pref_SetPref(const dom::PrefSetting& aPref) return rv; } -PLDHashOperator -pref_savePref(PLDHashTable *table, PLDHashEntryHdr *heh, uint32_t i, void *arg) +void +pref_savePrefs(PLDHashTable* aTable, char** aPrefArray) { - pref_saveArgs *argData = static_cast(arg); - PrefHashEntry *pref = static_cast(heh); + int32_t j = 0; + for (auto iter = aTable->Iter(); !iter.Done(); iter.Next()) { + auto pref = static_cast(iter.Get()); - PR_ASSERT(pref); - if (!pref) - return PL_DHASH_NEXT; + nsAutoCString prefValue; + nsAutoCString prefPrefix; + prefPrefix.AssignLiteral("user_pref(\""); - nsAutoCString prefValue; - nsAutoCString prefPrefix; - prefPrefix.AssignLiteral("user_pref(\""); + // where we're getting our pref from + PrefValue* sourcePref; - // where we're getting our pref from - PrefValue* sourcePref; - - if (PREF_HAS_USER_VALUE(pref) && - (pref_ValueChanged(pref->defaultPref, - pref->userPref, - (PrefType) PREF_TYPE(pref)) || - !(pref->flags & PREF_HAS_DEFAULT) || - pref->flags & PREF_STICKY_DEFAULT)) { - sourcePref = &pref->userPref; - } else { - if (argData->saveTypes == SAVE_ALL_AND_DEFAULTS) { - prefPrefix.AssignLiteral("pref(\""); - sourcePref = &pref->defaultPref; - } - else + if (PREF_HAS_USER_VALUE(pref) && + (pref_ValueChanged(pref->defaultPref, + pref->userPref, + (PrefType) PREF_TYPE(pref)) || + !(pref->flags & PREF_HAS_DEFAULT) || + pref->flags & PREF_STICKY_DEFAULT)) { + sourcePref = &pref->userPref; + } else { // do not save default prefs that haven't changed - return PL_DHASH_NEXT; + continue; + } + + // strings are in quotes! + if (pref->flags & PREF_STRING) { + prefValue = '\"'; + str_escape(sourcePref->stringVal, prefValue); + prefValue += '\"'; + + } else if (pref->flags & PREF_INT) { + prefValue.AppendInt(sourcePref->intVal); + + } else if (pref->flags & PREF_BOOL) { + prefValue = (sourcePref->boolVal) ? "true" : "false"; + } + + nsAutoCString prefName; + str_escape(pref->key, prefName); + + aPrefArray[j++] = ToNewCString(prefPrefix + + prefName + + NS_LITERAL_CSTRING("\", ") + + prefValue + + NS_LITERAL_CSTRING(");")); } - - // strings are in quotes! - if (pref->flags & PREF_STRING) { - prefValue = '\"'; - str_escape(sourcePref->stringVal, prefValue); - prefValue += '\"'; - } - - else if (pref->flags & PREF_INT) - prefValue.AppendInt(sourcePref->intVal); - - else if (pref->flags & PREF_BOOL) - prefValue = (sourcePref->boolVal) ? "true" : "false"; - - nsAutoCString prefName; - str_escape(pref->key, prefName); - - argData->prefArray[i] = ToNewCString(prefPrefix + - prefName + - NS_LITERAL_CSTRING("\", ") + - prefValue + - NS_LITERAL_CSTRING(");")); - - return PL_DHASH_NEXT; -} - -PLDHashOperator -pref_GetPrefs(PLDHashTable *table, - PLDHashEntryHdr *heh, - uint32_t i, - void *arg) -{ - if (heh) { - PrefHashEntry *entry = static_cast(heh); - dom::PrefSetting *pref = - static_cast*>(arg)->AppendElement(); - - pref_GetPrefFromEntry(entry, pref); - } - return PL_DHASH_NEXT; } static void @@ -555,23 +530,6 @@ nsresult PREF_GetBoolPref(const char *pref_name, bool * return_value, bool get_d return rv; } -/* Delete a branch. Used for deleting mime types */ -static PLDHashOperator -pref_DeleteItem(PLDHashTable *table, PLDHashEntryHdr *heh, uint32_t i, void *arg) -{ - PrefHashEntry* he = static_cast(heh); - const char *to_delete = (const char *) arg; - int len = strlen(to_delete); - - /* note if we're deleting "ldap" then we want to delete "ldap.xxx" - and "ldap" (if such a leaf node exists) but not "ldap_1.xxx" */ - if (to_delete && (PL_strncmp(he->key, to_delete, (uint32_t) len) == 0 || - (len-1 == (int)strlen(he->key) && PL_strncmp(he->key, to_delete, (uint32_t)(len-1)) == 0))) - return PL_DHASH_REMOVE; - - return PL_DHASH_NEXT; -} - nsresult PREF_DeleteBranch(const char *branch_name) { @@ -594,8 +552,22 @@ PREF_DeleteBranch(const char *branch_name) if ((len > 1) && branch_name[len - 1] != '.') branch_dot += '.'; - PL_DHashTableEnumerate(gHashTable, pref_DeleteItem, - (void*) branch_dot.get()); + /* Delete a branch. Used for deleting mime types */ + const char *to_delete = branch_dot.get(); + MOZ_ASSERT(to_delete); + len = strlen(to_delete); + for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) { + auto entry = static_cast(iter.Get()); + + /* note if we're deleting "ldap" then we want to delete "ldap.xxx" + and "ldap" (if such a leaf node exists) but not "ldap_1.xxx" */ + if (PL_strncmp(entry->key, to_delete, (uint32_t) len) == 0 || + (len-1 == (int)strlen(entry->key) && + PL_strncmp(entry->key, to_delete, (uint32_t)(len-1)) == 0)) { + iter.Remove(); + } + } + gDirty = true; return NS_OK; } @@ -622,26 +594,6 @@ PREF_ClearUserPref(const char *pref_name) return NS_OK; } -static PLDHashOperator -pref_ClearUserPref(PLDHashTable *table, PLDHashEntryHdr *he, uint32_t, - void *arg) -{ - PrefHashEntry *pref = static_cast(he); - - PLDHashOperator nextOp = PL_DHASH_NEXT; - - if (PREF_HAS_USER_VALUE(pref)) - { - pref->flags &= ~PREF_USERSET; - - if (!(pref->flags & PREF_HAS_DEFAULT)) { - nextOp = PL_DHASH_REMOVE; - } - static_cast*>(arg)->push_back(std::string(pref->key)); - } - return nextOp; -} - nsresult PREF_ClearAllUserPrefs() { @@ -653,7 +605,18 @@ PREF_ClearAllUserPrefs() return NS_ERROR_NOT_INITIALIZED; std::vector prefStrings; - PL_DHashTableEnumerate(gHashTable, pref_ClearUserPref, static_cast(&prefStrings)); + for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) { + auto pref = static_cast(iter.Get()); + + if (PREF_HAS_USER_VALUE(pref)) { + prefStrings.push_back(std::string(pref->key)); + + pref->flags &= ~PREF_USERSET; + if (!(pref->flags & PREF_HAS_DEFAULT)) { + iter.Remove(); + } + } + } for (std::string& prefString : prefStrings) { pref_DoCallback(prefString.c_str()); diff --git a/modules/libpref/prefapi_private_data.h b/modules/libpref/prefapi_private_data.h index aa90c1c42a..4ccf8c1bc6 100644 --- a/modules/libpref/prefapi_private_data.h +++ b/modules/libpref/prefapi_private_data.h @@ -19,20 +19,8 @@ class PrefSetting; } // namespace dom } // namespace mozilla -enum pref_SaveTypes { SAVE_NONSHARED, SAVE_SHARED, SAVE_ALL, SAVE_ALL_AND_DEFAULTS }; - -// Passed as the arg to pref_savePref -struct pref_saveArgs { - char **prefArray; - pref_SaveTypes saveTypes; -}; - -PLDHashOperator -pref_savePref(PLDHashTable *table, PLDHashEntryHdr *heh, uint32_t i, void *arg); - -PLDHashOperator -pref_GetPrefs(PLDHashTable *table, - PLDHashEntryHdr *heh, uint32_t i, void *arg); +void +pref_savePrefs(PLDHashTable* aTable, char** aPrefArray); nsresult pref_SetPref(const mozilla::dom::PrefSetting& aPref); diff --git a/netwerk/cache/nsCacheEntry.cpp b/netwerk/cache/nsCacheEntry.cpp index 9e5cbf8548..e3d32cad13 100644 --- a/netwerk/cache/nsCacheEntry.cpp +++ b/netwerk/cache/nsCacheEntry.cpp @@ -462,16 +462,12 @@ nsCacheEntryHashTable::RemoveEntry( nsCacheEntry *cacheEntry) PL_DHashTableRemove(&table, &(cacheEntry->mKey)); } - -void -nsCacheEntryHashTable::VisitEntries( PLDHashEnumerator etor, void *arg) +PLDHashTable::Iterator +nsCacheEntryHashTable::Iter() { - NS_ASSERTION(initialized, "nsCacheEntryHashTable not initialized"); - if (!initialized) return; // NS_ERROR_NOT_INITIALIZED - PL_DHashTableEnumerate(&table, etor, arg); + return PLDHashTable::Iterator(&table); } - /** * hash table operation callback functions */ diff --git a/netwerk/cache/nsCacheEntry.h b/netwerk/cache/nsCacheEntry.h index 5c4156e55b..6b15324911 100644 --- a/netwerk/cache/nsCacheEntry.h +++ b/netwerk/cache/nsCacheEntry.h @@ -255,11 +255,11 @@ private: /****************************************************************************** * nsCacheEntryHashTable *******************************************************************************/ -typedef struct { - PLDHashNumber keyHash; - nsCacheEntry *cacheEntry; -} nsCacheEntryHashTableEntry; +struct nsCacheEntryHashTableEntry : public PLDHashEntryHdr +{ + nsCacheEntry *cacheEntry; +}; class nsCacheEntryHashTable { @@ -274,7 +274,7 @@ public: nsresult AddEntry( nsCacheEntry *entry); void RemoveEntry( nsCacheEntry *entry); - void VisitEntries( PLDHashEnumerator etor, void *arg); + PLDHashTable::Iterator Iter(); private: // PLDHashTable operation callbacks @@ -292,17 +292,6 @@ private: static void Finalize( PLDHashTable *table); - static - PLDHashOperator FreeCacheEntries(PLDHashTable * table, - PLDHashEntryHdr * hdr, - uint32_t number, - void * arg); - static - PLDHashOperator VisitEntry(PLDHashTable * table, - PLDHashEntryHdr * hdr, - uint32_t number, - void * arg); - // member variables static const PLDHashTableOps ops; PLDHashTable table; diff --git a/netwerk/cache/nsCacheService.cpp b/netwerk/cache/nsCacheService.cpp index f50e1aa4a4..e4b5fc1acd 100644 --- a/netwerk/cache/nsCacheService.cpp +++ b/netwerk/cache/nsCacheService.cpp @@ -2883,58 +2883,32 @@ nsCacheService::ClearDoomList() } } -PLDHashOperator -nsCacheService::GetActiveEntries(PLDHashTable * table, - PLDHashEntryHdr * hdr, - uint32_t number, - void * arg) -{ - static_cast*>(arg)->AppendElement( - ((nsCacheEntryHashTableEntry *)hdr)->cacheEntry); - return PL_DHASH_NEXT; -} - -struct ActiveEntryArgs -{ - nsTArray* mActiveArray; - nsCacheService::DoomCheckFn mCheckFn; -}; - void nsCacheService::DoomActiveEntries(DoomCheckFn check) { nsAutoTArray array; - ActiveEntryArgs args = { &array, check }; - mActiveEntries.VisitEntries(RemoveActiveEntry, &args); + for (auto iter = mActiveEntries.Iter(); !iter.Done(); iter.Next()) { + nsCacheEntry* entry = + static_cast(iter.Get())->cacheEntry; + + if (check && !check(entry)) { + continue; + } + + array.AppendElement(entry); + + // entry is being removed from the active entry list + entry->MarkInactive(); + iter.Remove(); + } uint32_t count = array.Length(); - for (uint32_t i=0; i < count; ++i) + for (uint32_t i = 0; i < count; ++i) { DoomEntry_Internal(array[i], true); + } } -PLDHashOperator -nsCacheService::RemoveActiveEntry(PLDHashTable * table, - PLDHashEntryHdr * hdr, - uint32_t number, - void * arg) -{ - nsCacheEntry * entry = ((nsCacheEntryHashTableEntry *)hdr)->cacheEntry; - NS_ASSERTION(entry, "### active entry = nullptr!"); - - ActiveEntryArgs* args = static_cast(arg); - if (args->mCheckFn && !args->mCheckFn(entry)) - return PL_DHASH_NEXT; - - NS_ASSERTION(args->mActiveArray, "### array = nullptr!"); - args->mActiveArray->AppendElement(entry); - - // entry is being removed from the active entry list - entry->MarkInactive(); - return PL_DHASH_REMOVE; // and continue enumerating -} - - void nsCacheService::CloseAllStreams() { @@ -2948,7 +2922,10 @@ nsCacheService::CloseAllStreams() #if DEBUG // make sure there is no active entry - mActiveEntries.VisitEntries(GetActiveEntries, &entries); + for (auto iter = mActiveEntries.Iter(); !iter.Done(); iter.Next()) { + auto entry = static_cast(iter.Get()); + entries.AppendElement(entry->cacheEntry); + } NS_ASSERTION(entries.IsEmpty(), "Bad state"); #endif diff --git a/netwerk/cache/nsCacheService.h b/netwerk/cache/nsCacheService.h index 27890f6ebc..88fde3db40 100644 --- a/netwerk/cache/nsCacheService.h +++ b/netwerk/cache/nsCacheService.h @@ -310,17 +310,6 @@ private: void CloseAllStreams(); void FireClearNetworkCacheStoredAnywhereNotification(); - static - PLDHashOperator GetActiveEntries(PLDHashTable * table, - PLDHashEntryHdr * hdr, - uint32_t number, - void * arg); - static - PLDHashOperator RemoveActiveEntry(PLDHashTable * table, - PLDHashEntryHdr * hdr, - uint32_t number, - void * arg); - static PLDHashOperator ShutdownCustomCacheDeviceEnum(const nsAString& aProfileDir, nsRefPtr& aDevice, diff --git a/netwerk/cache/nsMemoryCacheDevice.cpp b/netwerk/cache/nsMemoryCacheDevice.cpp index 4cebf3cff6..4ed23cc697 100644 --- a/netwerk/cache/nsMemoryCacheDevice.cpp +++ b/netwerk/cache/nsMemoryCacheDevice.cpp @@ -527,14 +527,6 @@ nsMemoryCacheDevice::SetMaxEntrySize(int32_t maxSizeInKilobytes) } #ifdef DEBUG -static PLDHashOperator -CountEntry(PLDHashTable * table, PLDHashEntryHdr * hdr, uint32_t number, void * arg) -{ - int32_t *entryCount = (int32_t *)arg; - ++(*entryCount); - return PL_DHASH_NEXT; -} - void nsMemoryCacheDevice::CheckEntryCount() { @@ -551,8 +543,10 @@ nsMemoryCacheDevice::CheckEntryCount() NS_ASSERTION(mEntryCount == evictionListCount, "### mem cache badness"); int32_t entryCount = 0; - mMemCacheEntries.VisitEntries(CountEntry, &entryCount); - NS_ASSERTION(mEntryCount == entryCount, "### mem cache badness"); + for (auto iter = mMemCacheEntries.Iter(); !iter.Done(); iter.Next()) { + ++entryCount; + } + NS_ASSERTION(mEntryCount == entryCount, "### mem cache badness"); } #endif diff --git a/netwerk/dns/nsHostResolver.cpp b/netwerk/dns/nsHostResolver.cpp index de03e81700..6022405119 100644 --- a/netwerk/dns/nsHostResolver.cpp +++ b/netwerk/dns/nsHostResolver.cpp @@ -489,30 +489,6 @@ static const PLDHashTableOps gHostDB_ops = HostDB_InitEntry, }; -static PLDHashOperator -HostDB_RemoveEntry(PLDHashTable *table, - PLDHashEntryHdr *hdr, - uint32_t number, - void *arg) -{ - return PL_DHASH_REMOVE; -} - -static PLDHashOperator -HostDB_PruneEntry(PLDHashTable *table, - PLDHashEntryHdr *hdr, - uint32_t number, - void *arg) -{ - nsHostDBEnt* ent = static_cast(hdr); - // Try to remove the record, or mark it for refresh - if (ent->rec->RemoveOrRefresh()) { - PR_REMOVE_LINK(ent->rec); - return PL_DHASH_REMOVE; - } - return PL_DHASH_NEXT; -} - //---------------------------------------------------------------------------- #if TTL_AVAILABLE @@ -630,24 +606,31 @@ nsHostResolver::ClearPendingQueue(PRCList *aPendingQ) void nsHostResolver::FlushCache() { - MutexAutoLock lock(mLock); - mEvictionQSize = 0; + MutexAutoLock lock(mLock); + mEvictionQSize = 0; - // Clear the evictionQ and remove all its corresponding entries from - // the cache first - if (!PR_CLIST_IS_EMPTY(&mEvictionQ)) { - PRCList *node = mEvictionQ.next; - while (node != &mEvictionQ) { - nsHostRecord *rec = static_cast(node); - node = node->next; - PR_REMOVE_AND_INIT_LINK(rec); - PL_DHashTableRemove(&mDB, (nsHostKey *) rec); - NS_RELEASE(rec); - } - } + // Clear the evictionQ and remove all its corresponding entries from + // the cache first + if (!PR_CLIST_IS_EMPTY(&mEvictionQ)) { + PRCList *node = mEvictionQ.next; + while (node != &mEvictionQ) { + nsHostRecord *rec = static_cast(node); + node = node->next; + PR_REMOVE_AND_INIT_LINK(rec); + PL_DHashTableRemove(&mDB, (nsHostKey *) rec); + NS_RELEASE(rec); + } + } - // Refresh the cache entries that are resolving RIGHT now, remove the rest. - PL_DHashTableEnumerate(&mDB, HostDB_PruneEntry, nullptr); + // Refresh the cache entries that are resolving RIGHT now, remove the rest. + for (auto iter = mDB.Iter(); !iter.Done(); iter.Next()) { + auto entry = static_cast(iter.Get()); + // Try to remove the record, or mark it for refresh. + if (entry->rec->RemoveOrRefresh()) { + PR_REMOVE_LINK(entry->rec); + iter.Remove(); + } + } } void @@ -686,7 +669,7 @@ nsHostResolver::Shutdown() mIdleThreadCV.NotifyAll(); // empty host database - PL_DHashTableEnumerate(&mDB, HostDB_RemoveEntry, nullptr); + mDB.Clear(); } ClearPendingQueue(&pendingQHigh); @@ -1442,58 +1425,51 @@ nsHostResolver::Create(uint32_t maxCacheEntries, return rv; } -PLDHashOperator -CacheEntryEnumerator(PLDHashTable *table, PLDHashEntryHdr *entry, - uint32_t number, void *arg) -{ - // We don't pay attention to address literals, only resolved domains. - // Also require a host. - nsHostRecord *rec = static_cast(entry)->rec; - MOZ_ASSERT(rec, "rec should never be null here!"); - if (!rec || !rec->addr_info || !rec->host) { - return PL_DHASH_NEXT; - } - - DNSCacheEntries info; - info.hostname = rec->host; - info.family = rec->af; - info.netInterface = rec->netInterface; - info.expiration = - (int64_t)(rec->mValidEnd - TimeStamp::NowLoRes()).ToSeconds(); - if (info.expiration <= 0) { - // We only need valid DNS cache entries - return PL_DHASH_NEXT; - } - - { - MutexAutoLock lock(rec->addr_info_lock); - - NetAddr *addr = nullptr; - NetAddrElement *addrElement = rec->addr_info->mAddresses.getFirst(); - if (addrElement) { - addr = &addrElement->mAddress; - } - while (addr) { - char buf[kIPv6CStrBufSize]; - if (NetAddrToString(addr, buf, sizeof(buf))) { - info.hostaddr.AppendElement(buf); - } - addr = nullptr; - addrElement = addrElement->getNext(); - if (addrElement) { - addr = &addrElement->mAddress; - } - } - } - - nsTArray *args = static_cast *>(arg); - args->AppendElement(info); - - return PL_DHASH_NEXT; -} - void nsHostResolver::GetDNSCacheEntries(nsTArray *args) { - PL_DHashTableEnumerate(&mDB, CacheEntryEnumerator, args); + for (auto iter = mDB.Iter(); !iter.Done(); iter.Next()) { + // We don't pay attention to address literals, only resolved domains. + // Also require a host. + auto entry = static_cast(iter.Get()); + nsHostRecord* rec = entry->rec; + MOZ_ASSERT(rec, "rec should never be null here!"); + if (!rec || !rec->addr_info || !rec->host) { + continue; + } + + DNSCacheEntries info; + info.hostname = rec->host; + info.family = rec->af; + info.netInterface = rec->netInterface; + info.expiration = + (int64_t)(rec->mValidEnd - TimeStamp::NowLoRes()).ToSeconds(); + if (info.expiration <= 0) { + // We only need valid DNS cache entries + continue; + } + + { + MutexAutoLock lock(rec->addr_info_lock); + + NetAddr *addr = nullptr; + NetAddrElement *addrElement = rec->addr_info->mAddresses.getFirst(); + if (addrElement) { + addr = &addrElement->mAddress; + } + while (addr) { + char buf[kIPv6CStrBufSize]; + if (NetAddrToString(addr, buf, sizeof(buf))) { + info.hostaddr.AppendElement(buf); + } + addr = nullptr; + addrElement = addrElement->getNext(); + if (addrElement) { + addr = &addrElement->mAddress; + } + } + } + + args->AppendElement(info); + } } diff --git a/rdf/base/nsInMemoryDataSource.cpp b/rdf/base/nsInMemoryDataSource.cpp index 0862d4ba29..fafa4d7f88 100644 --- a/rdf/base/nsInMemoryDataSource.cpp +++ b/rdf/base/nsInMemoryDataSource.cpp @@ -1806,7 +1806,7 @@ void InMemoryDataSource::SweepForwardArcsEntries(PLDHashTable* aTable, SweepInfo* aInfo) { - for (auto iter = aTable->RemovingIter(); !iter.Done(); iter.Next()) { + for (auto iter = aTable->Iter(); !iter.Done(); iter.Next()) { auto entry = static_cast(iter.Get()); Assertion* as = entry->mAssertions; diff --git a/security/manager/ssl/nsNSSShutDown.cpp b/security/manager/ssl/nsNSSShutDown.cpp index cdba3a1fb3..290cd0b8b8 100644 --- a/security/manager/ssl/nsNSSShutDown.cpp +++ b/security/manager/ssl/nsNSSShutDown.cpp @@ -133,25 +133,16 @@ nsresult nsNSSShutDownList::doPK11Logout() // This is guaranteed by holding the list lock. MutexAutoLock lock(singleton->mListLock); - PL_DHashTableEnumerate(&mPK11LogoutCancelObjects, doPK11LogoutHelper, 0); - - return NS_OK; -} - -PLDHashOperator -nsNSSShutDownList::doPK11LogoutHelper(PLDHashTable *table, - PLDHashEntryHdr *hdr, uint32_t number, void *arg) -{ - ObjectHashEntry *entry = static_cast(hdr); - - nsOnPK11LogoutCancelObject *pklco = - reinterpret_cast(entry->obj); - - if (pklco) { - pklco->logout(); + for (auto iter = mPK11LogoutCancelObjects.Iter(); !iter.Done(); iter.Next()) { + auto entry = static_cast(iter.Get()); + nsOnPK11LogoutCancelObject *pklco = + reinterpret_cast(entry->obj); + if (pklco) { + pklco->logout(); + } } - return PL_DHASH_NEXT; + return NS_OK; } bool nsNSSShutDownList::isUIActive() @@ -180,29 +171,26 @@ nsresult nsNSSShutDownList::evaporateAllNSSResources() } PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("now evaporating NSS resources\n")); - int removedCount; - do { - MutexAutoLock lock(mListLock); - removedCount = PL_DHashTableEnumerate(&mObjects, evaporateAllNSSResourcesHelper, 0); - } while (removedCount > 0); - mActivityState.releaseCurrentThreadActivityRestriction(); - return NS_OK; -} - -PLDHashOperator -nsNSSShutDownList::evaporateAllNSSResourcesHelper(PLDHashTable *table, - PLDHashEntryHdr *hdr, uint32_t number, void *arg) -{ - ObjectHashEntry *entry = static_cast(hdr); - { - MutexAutoUnlock unlock(singleton->mListLock); - entry->obj->shutdown(nsNSSShutDownObject::calledFromList); - } // Never free more than one entry, because other threads might be calling // us and remove themselves while we are iterating over the list, // and the behaviour of changing the list while iterating is undefined. - return (PLDHashOperator)(PL_DHASH_STOP | PL_DHASH_REMOVE); + while (true) { + MutexAutoLock lock(mListLock); + auto iter = mObjects.Iter(); + if (iter.Done()) { + break; + } + auto entry = static_cast(iter.Get()); + { + MutexAutoUnlock unlock(singleton->mListLock); + entry->obj->shutdown(nsNSSShutDownObject::calledFromList); + } + iter.Remove(); + } + + mActivityState.releaseCurrentThreadActivityRestriction(); + return NS_OK; } nsNSSShutDownList *nsNSSShutDownList::construct() diff --git a/security/manager/ssl/nsNSSShutDown.h b/security/manager/ssl/nsNSSShutDown.h index f3558ecfa1..6e954e7f92 100644 --- a/security/manager/ssl/nsNSSShutDown.h +++ b/security/manager/ssl/nsNSSShutDown.h @@ -147,13 +147,7 @@ public: private: nsNSSShutDownList(); - static PLDHashOperator - evaporateAllNSSResourcesHelper(PLDHashTable *table, PLDHashEntryHdr *hdr, - uint32_t number, void *arg); - static PLDHashOperator - doPK11LogoutHelper(PLDHashTable *table, PLDHashEntryHdr *hdr, - uint32_t number, void *arg); protected: mozilla::Mutex mListLock; static nsNSSShutDownList *singleton; diff --git a/xpcom/glue/nsBaseHashtable.h b/xpcom/glue/nsBaseHashtable.h index f70af4ce24..b7a782f9ff 100644 --- a/xpcom/glue/nsBaseHashtable.h +++ b/xpcom/glue/nsBaseHashtable.h @@ -168,7 +168,7 @@ public: uint32_t EnumerateRead(EnumReadFunction aEnumFunc, void* aUserArg) const { uint32_t n = 0; - for (auto iter = this->mTable.Iter(); !iter.Done(); iter.Next()) { + for (auto iter = this->mTable.ConstIter(); !iter.Done(); iter.Next()) { auto entry = static_cast(iter.Get()); PLDHashOperator op = aEnumFunc(entry->GetKey(), entry->mData, aUserArg); n++; @@ -204,7 +204,7 @@ public: uint32_t Enumerate(EnumFunction aEnumFunc, void* aUserArg) { uint32_t n = 0; - for (auto iter = this->mTable.RemovingIter(); !iter.Done(); iter.Next()) { + for (auto iter = this->mTable.Iter(); !iter.Done(); iter.Next()) { auto entry = static_cast(iter.Get()); PLDHashOperator op = aEnumFunc(entry->GetKey(), entry->mData, aUserArg); n++; diff --git a/xpcom/glue/nsTHashtable.h b/xpcom/glue/nsTHashtable.h index ad15f6a700..d588e295f6 100644 --- a/xpcom/glue/nsTHashtable.h +++ b/xpcom/glue/nsTHashtable.h @@ -208,7 +208,7 @@ public: uint32_t EnumerateEntries(Enumerator aEnumFunc, void* aUserArg) { uint32_t n = 0; - for (auto iter = mTable.RemovingIter(); !iter.Done(); iter.Next()) { + for (auto iter = mTable.Iter(); !iter.Done(); iter.Next()) { auto entry = static_cast(iter.Get()); PLDHashOperator op = aEnumFunc(entry, aUserArg); n++; diff --git a/xpcom/glue/pldhash.cpp b/xpcom/glue/pldhash.cpp index e579be3838..74f49207a7 100644 --- a/xpcom/glue/pldhash.cpp +++ b/xpcom/glue/pldhash.cpp @@ -827,7 +827,7 @@ PLDHashTable::SizeOfExcludingThis( size_t n = aMallocSizeOf(mEntryStore); if (aSizeOfEntryExcludingThis) { - for (auto iter = Iter(); !iter.Done(); iter.Next()) { + for (auto iter = ConstIter(); !iter.Done(); iter.Next()) { n += aSizeOfEntryExcludingThis(iter.Get(), aMallocSizeOf, aArg); } } @@ -868,17 +868,20 @@ PLDHashTable::Iterator::Iterator(Iterator&& aOther) : mTable(aOther.mTable) , mCurrent(aOther.mCurrent) , mLimit(aOther.mLimit) + , mHaveRemoved(aOther.mHaveRemoved) { // No need to change |mChecker| here. aOther.mTable = nullptr; aOther.mCurrent = nullptr; aOther.mLimit = nullptr; + aOther.mHaveRemoved = false; } -PLDHashTable::Iterator::Iterator(const PLDHashTable* aTable) +PLDHashTable::Iterator::Iterator(PLDHashTable* aTable) : mTable(aTable) , mCurrent(mTable->mEntryStore) , mLimit(mTable->mEntryStore + mTable->Capacity() * mTable->mEntrySize) + , mHaveRemoved(false) { #ifdef DEBUG mTable->mChecker.StartReadOp(); @@ -892,11 +895,14 @@ PLDHashTable::Iterator::Iterator(const PLDHashTable* aTable) PLDHashTable::Iterator::~Iterator() { -#ifdef DEBUG if (mTable) { + if (mHaveRemoved) { + mTable->ShrinkIfAppropriate(); + } +#ifdef DEBUG mTable->mChecker.EndReadOp(); - } #endif + } } bool @@ -931,41 +937,11 @@ PLDHashTable::Iterator::Next() } while (IsOnNonLiveEntry()); } -PLDHashTable::RemovingIterator::RemovingIterator(RemovingIterator&& aOther) - : Iterator(mozilla::Move(aOther)) - , mHaveRemoved(aOther.mHaveRemoved) -{ - // Do nothing with mChecker here. We treat RemovingIterator like Iterator -- - // i.e. as a read operation -- until the very end. Then, if any elements have - // been removed, we temporarily treat it as a write operation. -} - -PLDHashTable::RemovingIterator::RemovingIterator(PLDHashTable* aTable) - : Iterator(aTable) - , mHaveRemoved(false) -{ -} - -PLDHashTable::RemovingIterator::~RemovingIterator() -{ - if (mHaveRemoved) { -#ifdef DEBUG - AutoIteratorRemovalOp op(mTable->mChecker); -#endif - - // Why is this cast needed? In Iterator, |mTable| is const. In - // RemovingIterator it should be non-const, but it inherits from Iterator - // so that's not possible. But it's ok because RemovingIterator's - // constructor takes a pointer to a non-const table in the first place. - const_cast(mTable)->ShrinkIfAppropriate(); - } -} - void -PLDHashTable::RemovingIterator::Remove() +PLDHashTable::Iterator::Remove() { // This cast is needed for the same reason as the one in the destructor. - const_cast(mTable)->RawRemove(Get()); + mTable->RawRemove(Get()); mHaveRemoved = true; } diff --git a/xpcom/glue/pldhash.h b/xpcom/glue/pldhash.h index 14d634f467..0a81410a3c 100644 --- a/xpcom/glue/pldhash.h +++ b/xpcom/glue/pldhash.h @@ -404,15 +404,19 @@ public: void ClearEntryStub(PLDHashEntryHdr* aEntry); - // This is an iterator for PLDHashtable. It is not safe to modify the - // table while it is being iterated over; on debug builds, attempting to do - // so will result in an assertion failure. + // This is an iterator for PLDHashtable. Assertions will detect some, but not + // all, mid-iteration table modifications that might invalidate (e.g. + // reallocate) the entry storage. + // + // Any element can be removed during iteration using Remove(). If any + // elements are removed, the table may be resized once iteration ends. // // Example usage: // // for (auto iter = table.Iter(); !iter.Done(); iter.Next()) { // auto entry = static_cast(iter.Get()); // // ... do stuff with |entry| ... + // // ... possibly call iter.Remove() once ... // } // // or: @@ -420,6 +424,7 @@ public: // for (PLDHashTable::Iterator iter(&table); !iter.Done(); iter.Next()) { // auto entry = static_cast(iter.Get()); // // ... do stuff with |entry| ... + // // ... possibly call iter.Remove() once ... // } // // The latter form is more verbose but is easier to work with when @@ -428,20 +433,27 @@ public: class Iterator { public: - explicit Iterator(const PLDHashTable* aTable); + explicit Iterator(PLDHashTable* aTable); Iterator(Iterator&& aOther); ~Iterator(); + bool Done() const; // Have we finished? PLDHashEntryHdr* Get() const; // Get the current entry. void Next(); // Advance to the next entry. + // Remove the current entry. Must only be called once per entry, and Get() + // must not be called on that entry afterwards. + void Remove(); + protected: - const PLDHashTable* mTable; // Main table pointer. + PLDHashTable* mTable; // Main table pointer. private: char* mCurrent; // Pointer to the current entry. char* mLimit; // One past the last entry. + bool mHaveRemoved; // Have any elements been removed? + bool IsOnNonLiveEntry() const; Iterator() = delete; @@ -450,35 +462,13 @@ public: Iterator& operator=(const Iterator&&) = delete; }; - Iterator Iter() const { return Iterator(this); } + Iterator Iter() { return Iterator(this); } - // This is an iterator that allows elements to be removed during iteration. - // If any elements are removed, the table may be resized once iteration ends. - // Its usage is similar to that of Iterator, with the addition that Remove() - // can be called once per element. - class RemovingIterator : public Iterator + // Use this if you need to initialize an Iterator in a const method. If you + // use this case, you should not call Remove() on the iterator. + Iterator ConstIter() const { - public: - explicit RemovingIterator(PLDHashTable* aTable); - RemovingIterator(RemovingIterator&& aOther); - ~RemovingIterator(); - - // Remove the current entry. Must only be called once per entry, and Get() - // must not be called on that entry afterwards. - void Remove(); - - private: - bool mHaveRemoved; // Have any elements been removed? - - RemovingIterator() = delete; - RemovingIterator(const RemovingIterator&) = delete; - RemovingIterator& operator=(const RemovingIterator&) = delete; - RemovingIterator& operator=(const RemovingIterator&&) = delete; - }; - - RemovingIterator RemovingIter() const - { - return RemovingIterator(const_cast(this)); + return Iterator(const_cast(this)); } private: diff --git a/xpcom/tests/gtest/TestPLDHash.cpp b/xpcom/tests/gtest/TestPLDHash.cpp index 48edafff7d..33fc6819a0 100644 --- a/xpcom/tests/gtest/TestPLDHash.cpp +++ b/xpcom/tests/gtest/TestPLDHash.cpp @@ -51,10 +51,6 @@ TEST(PLDHashTableTest, LazyStorage) ASSERT_TRUE(false); // shouldn't hit this on an empty table } - for (auto iter = t.RemovingIter(); !iter.Done(); iter.Next()) { - ASSERT_TRUE(false); // shouldn't hit this on an empty table - } - // Using a null |mallocSizeOf| should be fine because it shouldn't be called // for an empty table. mozilla::MallocSizeOf mallocSizeOf = nullptr; @@ -185,19 +181,8 @@ TEST(PLDHashTableIterator, Iterator) n++; } ASSERT_TRUE(saw77 && saw88 && saw99 && n == 3); -} -TEST(PLDHashTableTest, RemovingIterator) -{ - PLDHashTable t(&trivialOps, sizeof(PLDHashEntryStub)); - - // Explicitly test the move constructor. We do this because, due to copy - // elision, compilers might optimize away move constructor calls for normal - // iterator use. - { - PLDHashTable::RemovingIterator iter1(&t); - PLDHashTable::RemovingIterator iter2(mozilla::Move(iter1)); - } + t.Clear(); // First, we insert 64 items, which results in a capacity of 128, and a load // factor of 50%. @@ -209,7 +194,7 @@ TEST(PLDHashTableTest, RemovingIterator) // The first removing iterator does no removing; capacity and entry count are // unchanged. - for (PLDHashTable::RemovingIterator iter(&t); !iter.Done(); iter.Next()) { + for (PLDHashTable::Iterator iter(&t); !iter.Done(); iter.Next()) { (void) iter.Get(); } ASSERT_EQ(t.EntryCount(), 64u); @@ -217,7 +202,7 @@ TEST(PLDHashTableTest, RemovingIterator) // The second removing iterator removes 16 items. This reduces the load // factor to 37.5% (48 / 128), which isn't low enough to shrink the table. - for (auto iter = t.RemovingIter(); !iter.Done(); iter.Next()) { + for (auto iter = t.Iter(); !iter.Done(); iter.Next()) { auto entry = static_cast(iter.Get()); if ((intptr_t)(entry->key) % 4 == 0) { iter.Remove(); @@ -228,7 +213,7 @@ TEST(PLDHashTableTest, RemovingIterator) // The third removing iterator removes another 16 items. This reduces // the load factor to 25% (32 / 128), so the table is shrunk. - for (auto iter = t.RemovingIter(); !iter.Done(); iter.Next()) { + for (auto iter = t.Iter(); !iter.Done(); iter.Next()) { auto entry = static_cast(iter.Get()); if ((intptr_t)(entry->key) % 2 == 0) { iter.Remove(); @@ -239,7 +224,7 @@ TEST(PLDHashTableTest, RemovingIterator) // The fourth removing iterator removes all remaining items. This reduces // the capacity to the minimum. - for (auto iter = t.RemovingIter(); !iter.Done(); iter.Next()) { + for (auto iter = t.Iter(); !iter.Done(); iter.Next()) { iter.Remove(); } ASSERT_EQ(t.EntryCount(), 0u);