import changes from `dev' branch of rmottola/Arctic-Fox:

- Bug 1173958: convert FixedTableLayoutStrategy to logical coordinates, r=jfkthame (cf2c57043)
- Bug 1173958: whitespace and bracing changes to make FixedTableLayoutStrategy conform to local style, r=jfkthame (0ae378556)
- Bug 1177606 - Correct the row positioning within rowGroups in vertical-rl tables when distributing extra width. r=dholbert (1dffbe5a9)
- Bug 1173958 followup - A few of the tests have a pixel of fuzz on B2G. no_r=orange (314a9208f)
- Bug 1178059: fix a pair of failing reftests from bug 1173958 by forcing a div to align like a td, r=jfkthame (ec2284038)
- Bug 1165168 - Tests from Grard Talbot for border-spacing in vertical writing-modes. r=smontagu (2c3d82d75)
- Bug 1165172 - Tests from Grard Talbot for table row progression in vertical writing-modes. r=smontagu (965828bbe)
- Bug 1165172 followup - Mark tests as fuzzy on OS X in addition to Windows. (9f23dfb3d)
- Bug 1177076 patch 2.1 - Annotate vertical-table-specified-width-2.html because it will assert in FinishReflowChild() due to unconstrained containerWidth. r=dholbert (c43e77d31)
- Bug 1177076 patch 3 - Change the initial value of 'caption-side' from 'top' (physical) to 'block-start' (logical). r=heycam (336bb6726)
- Bug 1177076 - patch 4 - Reftests for logical and physical caption-side placement. r=dholbert (3323b59ed)
- Bug 1177076 followup - Some of the tests are a bit fuzzy on Android. (8fbec9908)
- Bug 1174631 (part 1) - Replace nsRuleNode's uses of PL_DHashTableEnumerate() with PLDHashTable::{,Removing}Iterator. r=dholbert. (265e5c39c)
- Bug 1174631 (part 2) - Replace nsCSSRuleProcessor's uses of PL_DHashTableEnumerate() with PLDHashTable::Iterator. r=dholbert. (583aa6dec)
- Bug 1174631 (part 3) - Replace SpanningCellSorter's uses of PL_DHashTableEnumerate() with PLDHashTable::Iterator. r=dholbert. (dffd16064)
- Bug 1174631 (part 4) - Replace nsFrameManager's uses of PL_DHashTableEnumerate() with PLDHashTable::Iterator. r=dholbert. (5eb697aec)
- Bug 1176159 (part 1) - Remove pref_SaveTypes. r=bsmedberg. (ad62e83d8)
- Bug 1176159 (part 2) - Remove uses of PL_DHashTableEnumerate() from libpref. r=bsmedberg. (dcc05f19a)
- Bug 1175771 (part 1) - Fix indentation in nsHostResolver::FlushCache(). r=michal. (fcfb05c57)
- Bug 1175771 (part 2) - Remove PL_DHashTableEnumerate() use from nsHostResolver. r=michal. (d79e95969)
- Bug 1175771 (part 3) - Replace nsCacheEntryHashable::VisitEntries() with iterators. r=michal. (f79745d9b)
- Bug 1175807 - Remove PL_DHashTableEnumerate() uses from nsNSSShutdown. r=honzab. (b88e91643)
- Bug 1179071 - Merge RemovingIterator into Iterator. r=froydnj. (fb22f5c91)
- Bug 1153426 - Don't crash when doing an off-main-thread animation of a transform to or from the 'none' value. r=birtles (23f9940e3)
This commit is contained in:
2021-02-04 22:46:24 +08:00
parent 37477b2115
commit 9ecd7c73be
65 changed files with 2733 additions and 964 deletions
+1 -1
View File
@@ -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<NPObjWrapperHashEntry*>(i.Get());
if (entry->mNpp == npp) {
+6 -6
View File
@@ -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<XPCNativeScriptableSharedMap::Entry*>(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<ClassInfo2NativeSetMap::Entry*>(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<NativeSetMap::Entry*>(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<IID2NativeInterfaceMap::Entry*>(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<XPCWrappedNativeProtoMap::Entry*>(i.Get());
delete static_cast<const XPCWrappedNativeProto*>(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<NativeSetMap::Entry*>(i.Get());
entry->key_value->DebugDump(depth);
}
+6 -8
View File
@@ -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:
+2 -2
View File
@@ -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<ClassInfo2WrappedNativeProtoMap::Entry*>(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<Native2WrappedNativeMap::Entry*>(i.Get());
XPCWrappedNative* wrapper = entry->value;
if (wrapper->IsValid()) {
+4 -10
View File
@@ -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<PlaceholderMapEntry*>(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<PlaceholderMapEntry*>(iter.Get());
entry->placeholderFrame->SetOutOfFlowFrame(nullptr);
}
mPlaceholderMap.Clear();
}
@@ -9,6 +9,7 @@
div.stripe
{
width: 20px;
line-height: 20px;
height: 200px;
}
div.blue {background-color: blue; }
@@ -0,0 +1,37 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>CSS Reftest Reference</title>
<link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2013-07-27 -->
<link type="text/css" rel="stylesheet" href="support/ahem.css" />
<meta name="flags" content="image" />
<style type="text/css"><![CDATA[
div
{
background-color: black;
color: yellow;
font: 1.25em/1 Ahem;
width: 21em;
}
img {vertical-align: top;}
]]></style>
</head>
<body>
<!-- body of reference case rewritten by Jonathan Kew to use Ahem glyphs instead of images,
to reduce antialiasing fuzz in comparison with testcases -->
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;XXXX&nbsp;XXXX&nbsp;XXXX&nbsp;XXXX&nbsp;
&nbsp;X&nbsp;&nbsp;X&nbsp;X&nbsp;&nbsp;X&nbsp;X&nbsp;&nbsp;&nbsp;&nbsp;X&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;X&nbsp;&nbsp;X&nbsp;X&nbsp;&nbsp;X&nbsp;X&nbsp;&nbsp;&nbsp;&nbsp;X&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;XXXX&nbsp;XXXX&nbsp;XXXX&nbsp;XXXX&nbsp;
&nbsp;X&nbsp;&nbsp;&nbsp;&nbsp;X&nbsp;&nbsp;X&nbsp;&nbsp;&nbsp;&nbsp;X&nbsp;&nbsp;&nbsp;&nbsp;X&nbsp;
&nbsp;X&nbsp;&nbsp;&nbsp;&nbsp;X&nbsp;&nbsp;X&nbsp;&nbsp;&nbsp;&nbsp;X&nbsp;&nbsp;&nbsp;&nbsp;X&nbsp;
&nbsp;X&nbsp;&nbsp;&nbsp;&nbsp;X&nbsp;&nbsp;X&nbsp;XXXX&nbsp;XXXX&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</div>
</body>
</html>
@@ -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
@@ -0,0 +1,22 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>CSS Reftest Reference</title>
<link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
<meta name="flags" content="image" />
</head>
<body>
<p>Test passes if there is a filled green rectangle and <strong>no red</strong>.</p>
<div><img src="support/swatch-green.png" width="100" height="200" alt="Image download support must be enabled" /></div>
</body>
</html>
@@ -0,0 +1,144 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>CSS Writing Modes Test: border-spacing - first value is specified and non-zero in 'vertical-rl' table</title>
<link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#dimension-mapping" title="7.2 Dimension Mapping" />
<link rel="help" href="http://www.w3.org/TR/2011/REC-CSS2-20110607/tables.html#separated-borders" title="17.6.1 The separated borders model" />
<link rel="match" href="s72-border-spacing-002-ref.xht" />
<!--
To be replaced with
<link rel="match" href="border-spacing-wm-002-ref.xht" />
-->
<meta content="ahem" name="flags" />
<meta content="This test checks that first value of 'border-spacing' represents, from top to bottom, a) spacing between logical table right padding (physical table top padding) and rightmost cells and b) inter-column spacing and c) spacing between leftmost cells and logical table left padding (physical table bottom padding)." name="assert" />
<link type="text/css" rel="stylesheet" href="support/ahem.css" />
<style type="text/css"><![CDATA[
table
{
border-spacing: 0.5em 0em; /* computes to logical horizontal border-spacing: 10px */
font: 1.25em/1 Ahem; /* computes to 20px/20px */
padding: 1.25em 0em; /* computes to padding-top: 25px and padding-bottom: 25px */
-ah-writing-mode: vertical-rl;
-webkit-writing-mode: vertical-rl;
writing-mode: tb-rl; /* IE11 */
writing-mode: vertical-rl;
}
td
{
height: 0.5em;
padding: 0em;
width: 1em;
}
/*
0px width of nth row 20px TOP
| |
=================================== 0x (0em) |||
| table padding-top 25px (1.25em) | |||
| with red background=color | \ ||| /
| with red background=color | \ /
| with red background=color | \ /
| with red background=color | v
=================================== 25px (1.25em)
|logical righ border-spacing: 10px|
| with red background=color |
=================================== 35px (1.75em)
| height of 1st td 10px (0.5em) | |||
| with red background=color | |||
=================================== 45px (2.25em) \ ||| /
|inter-column spacing 10px (0.5em)| \ /
| with red background=color | \ /
=================================== 55px (2.75em) v
| height of 2nd td 10px (0.5em) |
| with red background=color |
=================================== 65px (3.25em)
|logical left border-spacing: 10px| |||
| with red background=color | |||
=================================== 75px (3.75em) \ ||| /
|tble padding-bottom 25px (1.25em)| \ /
| with red background=color | \ /
| with red background=color | v
| with red background=color |
| with red background=color |
=================================== 100px (5em) BOTTOM
*/
div#reference-overlapping-green
{
background-color: green;
height: 6.25em;
position: absolute;
width: 6.25em;
}
div#reference-overlapped-red
{
background-color: red;
height: 6.25em;
position: absolute;
width: 6.25em;
z-index: -1;
}
table#test-overlapped-red
{
background-color: red;
}
table#test-overlapping-green
{
background-color: green;
}
]]></style>
</head>
<body>
<p>Test passes if there is a filled green rectangle and <strong>no red</strong>.</p>
<div id="reference-overlapping-green"></div>
<table id="test-overlapped-red">
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
</table>
<div id="reference-overlapped-red"></div>
<table id="test-overlapping-green">
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
</table>
</body>
</html>
@@ -0,0 +1,144 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>CSS Writing Modes Test: border-spacing - first value is specified and non-zero in 'vertical-lr' table</title>
<link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#dimension-mapping" title="7.2 Dimension Mapping" />
<link rel="help" href="http://www.w3.org/TR/2011/REC-CSS2-20110607/tables.html#separated-borders" title="17.6.1 The separated borders model" />
<link rel="match" href="s72-border-spacing-002-ref.xht" />
<!--
To be replaced with
<link rel="match" href="border-spacing-wm-002-ref.xht" />
-->
<meta content="ahem" name="flags" />
<meta content="This test checks that first value of 'border-spacing' represents, from top to bottom, a) spacing between logical table left padding (physical table top padding) and leftmost cells and b) inter-column spacing and c) spacing between rightmost cells and logical table right padding (physical table bottom padding)." name="assert" />
<link type="text/css" rel="stylesheet" href="support/ahem.css" />
<style type="text/css"><![CDATA[
table
{
border-spacing: 0.5em 0em; /* computes to logical horizontal border-spacing: 10px */
font: 1.25em/1 Ahem; /* computes to 20px/20px */
padding: 1.25em 0em; /* computes to padding-top: 25px and padding-bottom: 25px */
-ah-writing-mode: vertical-lr;
-webkit-writing-mode: vertical-lr;
writing-mode: tb-lr; /* IE11 */
writing-mode: vertical-lr;
}
td
{
height: 0.5em;
padding: 0em;
width: 1em;
}
/*
0px width of nth row 20px TOP
| |
=================================== 0x (0em) |||
| table padding-top 25px (1.25em) | |||
| with red background=color | \ ||| /
| with red background=color | \ /
| with red background=color | \ /
| with red background=color | v
=================================== 25px (1.25em)
|logical left border-spacing: 10px|
| with red background=color |
=================================== 35px (1.75em)
| height of 1st td 10px (0.5em) | |||
| with red background=color | |||
=================================== 45px (2.25em) \ ||| /
|inter-column spacing 10px (0.5em)| \ /
| with red background=color | \ /
=================================== 55px (2.75em) v
| height of 2nd td 10px (0.5em) |
| with red background=color |
=================================== 65px (3.25em)
|logical righ border-spacing: 10px| |||
| with red background=color | |||
=================================== 75px (3.75em) \ ||| /
|tble padding-bottom 25px (1.25em)| \ /
| with red background=color | \ /
| with red background=color | v
| with red background=color |
| with red background=color |
=================================== 100px (5em) BOTTOM
*/
div#reference-overlapping-green
{
background-color: green;
height: 6.25em;
position: absolute;
width: 6.25em;
}
div#reference-overlapped-red
{
background-color: red;
height: 6.25em;
position: absolute;
width: 6.25em;
z-index: -1;
}
table#test-overlapped-red
{
background-color: red;
}
table#test-overlapping-green
{
background-color: green;
}
]]></style>
</head>
<body>
<p>Test passes if there is a filled green rectangle and <strong>no red</strong>.</p>
<div id="reference-overlapping-green"></div>
<table id="test-overlapped-red">
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
</table>
<div id="reference-overlapped-red"></div>
<table id="test-overlapping-green">
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
<tr><td></td><td></td></tr>
</table>
</body>
</html>
@@ -0,0 +1,124 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>CSS Writing Modes Test: border-spacing - second value is specified and non-zero in 'vertical-rl' table</title>
<link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#dimension-mapping" title="7.2 Dimension Mapping" />
<link rel="help" href="http://www.w3.org/TR/2011/REC-CSS2-20110607/tables.html#separated-borders" title="17.6.1 The separated borders model" />
<link rel="match" href="s72-border-spacing-002-ref.xht" />
<meta content="ahem" name="flags" />
<meta content="This test checks that second value of 'border-spacing' represents, from right to left, a) spacing between logical table top padding (physical table right padding) and topmost cells and b) inter-row spacing and c) between bottommost cells and logical table bottom padding (physical table left padding)." name="assert" />
<link type="text/css" rel="stylesheet" href="support/ahem.css" />
<style type="text/css"><![CDATA[
table
{
border-spacing: 0em 0.5em; /* computes to logical vertical border-spacing: 10px */
font: 1.25em/1 Ahem; /* computes to 20px/20px */
padding: 0em 1.25em; /* computes to padding-left: 25px and padding-right: 25px */
-ah-writing-mode: vertical-rl;
-webkit-writing-mode: vertical-rl;
writing-mode: tb-rl; /* IE11 */
writing-mode: vertical-rl;
}
td
{
height: 1em;
padding: 0em;
width: 0.5em;
}
/*
0px 25px 35px 45px 55px 65px 75px 100px
| padding-left | left | 2nd | middle | 1st | right | padding-right|
| of table | vert. | right | vert. | right | vert. | of table |
| | border | most | border | most | border | |
| | spacing| row | spacing| row | spacing| |
20| | | | | | | |
px| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
40| | | | | | | |
px| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
60| | | | | | | |
px| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
80| | | | | | | |
px| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
00| | | | | | | |
px| | | | | | | |
*/
div#reference-overlapping-green
{
background-color: green;
height: 6.25em;
position: absolute;
width: 6.25em;
}
div#reference-overlapped-red
{
background-color: red;
height: 6.25em;
position: absolute;
width: 6.25em;
z-index: -1;
}
table#test-overlapped-red
{
background-color: red;
}
table#test-overlapping-green
{
background-color: green;
}
]]></style>
</head>
<body>
<p>Test passes if there is a filled green rectangle and <strong>no red</strong>.</p>
<div id="reference-overlapping-green"></div>
<table id="test-overlapped-red">
<tr><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td><td></td><td></td></tr>
</table>
<div id="reference-overlapped-red"></div>
<table id="test-overlapping-green">
<tr><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td><td></td><td></td></tr>
</table>
</body>
</html>
@@ -0,0 +1,124 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>CSS Writing Modes Test: border-spacing - second value is specified and non-zero in 'vertical-lr' table</title>
<link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#dimension-mapping" title="7.2 Dimension Mapping" />
<link rel="help" href="http://www.w3.org/TR/2011/REC-CSS2-20110607/tables.html#separated-borders" title="17.6.1 The separated borders model" />
<link rel="match" href="s72-border-spacing-002-ref.xht" />
<meta content="ahem" name="flags" />
<meta content="This test checks that second value of 'border-spacing' represents, from left to right, a) spacing between logical table top padding (physical table left padding) and topmost cells and b) inter-row spacing and c) spacing between bottommost cells and logical table bottom padding (physical table right padding)." name="assert" />
<link type="text/css" rel="stylesheet" href="support/ahem.css" />
<style type="text/css"><![CDATA[
table
{
border-spacing: 0em 0.5em; /* computes to logical vertical border-spacing: 10px */
font: 1.25em/1 Ahem; /* computes to 20px/20px */
padding: 0em 1.25em; /* computes to padding-left: 25px and padding-right: 25px */
-ah-writing-mode: vertical-lr;
-webkit-writing-mode: vertical-lr;
writing-mode: tb-lr; /* IE11 */
writing-mode: vertical-lr;
}
td
{
height: 1em;
padding: 0em;
width: 0.5em;
}
/*
0px 25px 35px 45px 55px 65px 75px 100px
| padding-left | left | 2nd | middle | 1st | right | padding-right|
| of table | vert. | row | vert. | right | vert. | of table |
| | border | | border | most | border | |
| | spacing| | spacing| row | spacing| |
20| | | | | | | |
px| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
40| | | | | | | |
px| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
60| | | | | | | |
px| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
80| | | | | | | |
px| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
00| | | | | | | |
px| | | | | | | |
*/
div#reference-overlapping-green
{
background-color: green;
height: 6.25em;
position: absolute;
width: 6.25em;
}
div#reference-overlapped-red
{
background-color: red;
height: 6.25em;
position: absolute;
width: 6.25em;
z-index: -1;
}
table#test-overlapped-red
{
background-color: red;
}
table#test-overlapping-green
{
background-color: green;
}
]]></style>
</head>
<body>
<p>Test passes if there is a filled green rectangle and <strong>no red</strong>.</p>
<div id="reference-overlapping-green"></div>
<table id="test-overlapped-red">
<tr><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td><td></td><td></td></tr>
</table>
<div id="reference-overlapped-red"></div>
<table id="test-overlapping-green">
<tr><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td><td></td><td></td></tr>
</table>
</body>
</html>
@@ -0,0 +1,4 @@
@font-face {
font-family: Ahem;
src: url("../../../fonts/Ahem.ttf");
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 84 B

@@ -0,0 +1,53 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<style>
html {
font: 12px sans-serif;
}
body > div {
margin-bottom: 10px;
}
.h {
writing-mode: horizontal-tb;
}
.vlr {
writing-mode: vertical-lr;
}
.vrl {
writing-mode: vertical-rl;
}
.t {
width: 200px;
height: 100px;
background: silver;
}
.c {
background: cyan;
text-align: center;
min-block-size: 20px;
}
</style>
</head>
<body>
<div class="h">
<div class="t"></div>
<div class="c" style="width: 200px">table caption</div>
</div>
<div class="h">
<div class="t"></div>
<div class="c" style="width: 200px">table caption</div>
</div>
<div class="vlr">
<div class="t"></div>
<div class="c" style="height: 100px">table caption</div>
</div>
<div class="vrl">
<div class="t"></div>
<div class="c" style="height: 100px">table caption</div>
</div>
@@ -0,0 +1,61 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<style>
html {
font: 12px sans-serif;
}
.h {
writing-mode: horizontal-tb;
}
.vlr {
writing-mode: vertical-lr;
}
.vrl {
writing-mode: vertical-rl;
}
.ltr {
direction: ltr;
}
.rtl {
direction: rtl;
}
table {
border-spacing: 0;
margin-bottom: 10px;
caption-side: block-end;
}
td {
width: 200px;
height: 100px;
background: silver;
padding: 0;
}
caption {
background: cyan;
min-block-size: 20px;
}
</style>
</head>
<body>
<table class="h ltr">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
<table class="h rtl">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
<table class="vlr ltr">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
<table class="vrl ltr">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
@@ -0,0 +1,53 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<style>
html {
font: 12px sans-serif;
}
body > div {
margin-bottom: 10px;
}
.h {
writing-mode: horizontal-tb;
}
.vlr {
writing-mode: vertical-lr;
}
.vrl {
writing-mode: vertical-rl;
}
.t {
width: 200px;
height: 100px;
background: silver;
}
.c {
background: cyan;
text-align: center;
min-block-size: 20px;
}
</style>
</head>
<body>
<div class="h">
<div class="c" style="width: 200px">table caption</div>
<div class="t"></div>
</div>
<div class="h">
<div class="c" style="width: 200px">table caption</div>
<div class="t"></div>
</div>
<div class="vlr">
<div class="c" style="height: 100px">table caption</div>
<div class="t"></div>
</div>
<div class="vrl">
<div class="c" style="height: 100px">table caption</div>
<div class="t"></div>
</div>
@@ -0,0 +1,61 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<style>
html {
font: 12px sans-serif;
}
.h {
writing-mode: horizontal-tb;
}
.vlr {
writing-mode: vertical-lr;
}
.vrl {
writing-mode: vertical-rl;
}
.ltr {
direction: ltr;
}
.rtl {
direction: rtl;
}
table {
border-spacing: 0;
margin-bottom: 10px;
caption-side: block-start;
}
td {
width: 200px;
height: 100px;
background: silver;
padding: 0;
}
caption {
background: cyan;
min-block-size: 20px;
}
</style>
</head>
<body>
<table class="h ltr">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
<table class="h rtl">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
<table class="vlr ltr">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
<table class="vrl ltr">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
@@ -0,0 +1,54 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<style>
html {
font: 0px sans-serif;
}
body > div {
margin-bottom: 10px;
}
.h {
writing-mode: horizontal-tb;
}
.vlr {
writing-mode: vertical-lr;
}
.vrl {
writing-mode: vertical-rl;
}
.t {
width: 200px;
height: 100px;
background: silver;
}
.c {
background: cyan;
text-align: center;
min-block-size: 20px;
font-size: 12px;
}
</style>
</head>
<body>
<div class="h">
<div class="t"></div>
<div class="c" style="width: 200px">table caption</div>
</div>
<div class="h">
<div class="t"></div>
<div class="c" style="width: 200px">table caption</div>
</div>
<div class="vlr">
<div class="t" style="display: inline-block"></div>
<div class="c" style="display: inline-block; inline-size: -moz-min-content; vertical-align: bottom">table caption</div>
</div>
<div class="vrl">
<div class="t" style="display: inline-block"></div>
<div class="c" style="display: inline-block; inline-size: -moz-min-content; vertical-align: top">table caption</div>
</div>
@@ -0,0 +1,61 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<style>
html {
font: 12px sans-serif;
}
.h {
writing-mode: horizontal-tb;
}
.vlr {
writing-mode: vertical-lr;
}
.vrl {
writing-mode: vertical-rl;
}
.ltr {
direction: ltr;
}
.rtl {
direction: rtl;
}
table {
border-spacing: 0;
margin-bottom: 10px;
caption-side: bottom;
}
td {
width: 200px;
height: 100px;
background: silver;
padding: 0;
}
caption {
background: cyan;
min-block-size: 20px;
}
</style>
</head>
<body>
<table class="h ltr">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
<table class="h rtl">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
<table class="vlr ltr">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
<table class="vrl ltr">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
@@ -0,0 +1,57 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<style>
html {
font: 0px sans-serif;
}
body > div {
margin-bottom: 10px;
}
.h {
writing-mode: horizontal-tb;
}
.vlr {
writing-mode: vertical-lr;
}
.vrl {
writing-mode: vertical-rl;
}
.t {
width: 200px;
height: 100px;
background: silver;
display: inline-block;
}
.c {
background: cyan;
text-align: center;
min-block-size: 20px;
display: inline-block;
font-size: 12px;
vertical-align: top;
}
</style>
</head>
<body>
<div class="h">
<div class="t"></div>
<div class="c" style="inline-size: -moz-min-content">table caption</div>
</div>
<div class="h">
<div class="c" style="inline-size: -moz-min-content">table caption</div>
<div class="t"></div>
</div>
<div class="vlr">
<div class="t"></div>
<div class="c" style="inline-size: -moz-min-content; vertical-align: bottom">table caption</div>
</div>
<div class="vrl">
<div class="t"></div>
<div class="c" style="inline-size: -moz-min-content">table caption</div>
</div>
@@ -0,0 +1,61 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<style>
html {
font: 12px sans-serif;
}
.h {
writing-mode: horizontal-tb;
}
.vlr {
writing-mode: vertical-lr;
}
.vrl {
writing-mode: vertical-rl;
}
.ltr {
direction: ltr;
}
.rtl {
direction: rtl;
}
table {
border-spacing: 0;
margin-bottom: 10px;
caption-side: inline-end;
}
td {
width: 200px;
height: 100px;
background: silver;
padding: 0;
}
caption {
background: cyan;
min-block-size: 20px;
}
</style>
</head>
<body>
<table class="h ltr">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
<table class="h rtl">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
<table class="vlr ltr">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
<table class="vrl ltr">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
@@ -0,0 +1,57 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<style>
html {
font: 0px sans-serif;
}
body > div {
margin-bottom: 10px;
}
.h {
writing-mode: horizontal-tb;
}
.vlr {
writing-mode: vertical-lr;
}
.vrl {
writing-mode: vertical-rl;
}
.t {
width: 200px;
height: 100px;
background: silver;
display: inline-block;
}
.c {
background: cyan;
text-align: center;
min-block-size: 20px;
display: inline-block;
font-size: 12px;
vertical-align: top;
}
</style>
</head>
<body>
<div class="h">
<div class="c" style="inline-size: -moz-min-content">table caption</div>
<div class="t"></div>
</div>
<div class="h">
<div class="t"></div>
<div class="c" style="inline-size: -moz-min-content">table caption</div>
</div>
<div class="vlr">
<div class="c" style="inline-size: -moz-min-content; vertical-align: bottom">table caption</div>
<div class="t"></div>
</div>
<div class="vrl">
<div class="c" style="inline-size: -moz-min-content">table caption</div>
<div class="t"></div>
</div>
@@ -0,0 +1,61 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<style>
html {
font: 12px sans-serif;
}
.h {
writing-mode: horizontal-tb;
}
.vlr {
writing-mode: vertical-lr;
}
.vrl {
writing-mode: vertical-rl;
}
.ltr {
direction: ltr;
}
.rtl {
direction: rtl;
}
table {
border-spacing: 0;
margin-bottom: 10px;
caption-side: inline-start;
}
td {
width: 200px;
height: 100px;
background: silver;
padding: 0;
}
caption {
background: cyan;
min-block-size: 20px;
}
</style>
</head>
<body>
<table class="h ltr">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
<table class="h rtl">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
<table class="vlr ltr">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
<table class="vrl ltr">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
@@ -0,0 +1,55 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<style>
html {
font: 0px sans-serif;
}
body > div {
margin-bottom: 10px;
}
.h {
writing-mode: horizontal-tb;
}
.vlr {
writing-mode: vertical-lr;
}
.vrl {
writing-mode: vertical-rl;
}
.t {
width: 200px;
height: 100px;
background: silver;
}
.c {
background: cyan;
text-align: center;
min-block-size: 20px;
font-size: 12px;
vertical-align: top;
}
</style>
</head>
<body>
<div class="h">
<div class="c" style="display: inline-block; inline-size: -moz-min-content">table caption</div>
<div class="t" style="display: inline-block"></div>
</div>
<div class="h">
<div class="c" style="display: inline-block; inline-size: -moz-min-content">table caption</div>
<div class="t" style="display: inline-block"></div>
</div>
<div class="vlr">
<div class="c" style="height: 100px">table caption</div>
<div class="t"></div>
</div>
<div class="vrl">
<div class="t"></div>
<div class="c" style="height: 100px">table caption</div>
</div>
@@ -0,0 +1,61 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<style>
html {
font: 12px sans-serif;
}
.h {
writing-mode: horizontal-tb;
}
.vlr {
writing-mode: vertical-lr;
}
.vrl {
writing-mode: vertical-rl;
}
.ltr {
direction: ltr;
}
.rtl {
direction: rtl;
}
table {
border-spacing: 0;
margin-bottom: 10px;
caption-side: left;
}
td {
width: 200px;
height: 100px;
background: silver;
padding: 0;
}
caption {
background: cyan;
min-block-size: 20px;
}
</style>
</head>
<body>
<table class="h ltr">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
<table class="h rtl">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
<table class="vlr ltr">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
<table class="vrl ltr">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
@@ -0,0 +1,55 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<style>
html {
font: 0px sans-serif;
}
body > div {
margin-bottom: 10px;
}
.h {
writing-mode: horizontal-tb;
}
.vlr {
writing-mode: vertical-lr;
}
.vrl {
writing-mode: vertical-rl;
}
.t {
width: 200px;
height: 100px;
background: silver;
}
.c {
background: cyan;
text-align: center;
min-block-size: 20px;
font-size: 12px;
vertical-align: top;
}
</style>
</head>
<body>
<div class="h">
<div class="t" style="display: inline-block"></div>
<div class="c" style="display: inline-block; inline-size: -moz-min-content">table caption</div>
</div>
<div class="h">
<div class="t" style="display: inline-block"></div>
<div class="c" style="display: inline-block; inline-size: -moz-min-content">table caption</div>
</div>
<div class="vlr">
<div class="t"></div>
<div class="c" style="height: 100px">table caption</div>
</div>
<div class="vrl">
<div class="c" style="height: 100px">table caption</div>
<div class="t"></div>
</div>
@@ -0,0 +1,61 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<style>
html {
font: 12px sans-serif;
}
.h {
writing-mode: horizontal-tb;
}
.vlr {
writing-mode: vertical-lr;
}
.vrl {
writing-mode: vertical-rl;
}
.ltr {
direction: ltr;
}
.rtl {
direction: rtl;
}
table {
border-spacing: 0;
margin-bottom: 10px;
caption-side: right;
}
td {
width: 200px;
height: 100px;
background: silver;
padding: 0;
}
caption {
background: cyan;
min-block-size: 20px;
}
</style>
</head>
<body>
<table class="h ltr">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
<table class="h rtl">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
<table class="vlr ltr">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
<table class="vrl ltr">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
@@ -0,0 +1,54 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<style>
html {
font: 0px sans-serif;
}
body > div {
margin-bottom: 10px;
}
.h {
writing-mode: horizontal-tb;
}
.vlr {
writing-mode: vertical-lr;
}
.vrl {
writing-mode: vertical-rl;
}
.t {
width: 200px;
height: 100px;
background: silver;
}
.c {
background: cyan;
text-align: center;
min-block-size: 20px;
font-size: 12px;
}
</style>
</head>
<body>
<div class="h">
<div class="c" style="width: 200px">table caption</div>
<div class="t"></div>
</div>
<div class="h">
<div class="c" style="width: 200px">table caption</div>
<div class="t"></div>
</div>
<div class="vlr">
<div class="c" style="display: inline-block; inline-size: -moz-min-content; vertical-align: bottom">table caption</div>
<div class="t" style="display: inline-block"></div>
</div>
<div class="vrl">
<div class="c" style="display: inline-block; inline-size: -moz-min-content; vertical-align: top">table caption</div>
<div class="t" style="display: inline-block"></div>
</div>
@@ -0,0 +1,61 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<style>
html {
font: 12px sans-serif;
}
.h {
writing-mode: horizontal-tb;
}
.vlr {
writing-mode: vertical-lr;
}
.vrl {
writing-mode: vertical-rl;
}
.ltr {
direction: ltr;
}
.rtl {
direction: rtl;
}
table {
border-spacing: 0;
margin-bottom: 10px;
caption-side: top;
}
td {
width: 200px;
height: 100px;
background: silver;
padding: 0;
}
caption {
background: cyan;
min-block-size: 20px;
}
</style>
</head>
<body>
<table class="h ltr">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
<table class="h rtl">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
<table class="vlr ltr">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
<table class="vrl ltr">
<caption>table caption</caption>
<tr><td></td></tr>
</table>
@@ -0,0 +1,73 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>CSS Writing Modes Test: vertical-rl - table rows progression</title>
<link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
<link rel="match" href="multicol-count-002-ref.xht" />
<!--
to be replaced with
<link rel="match" href="../css-multicol-1/multicol-count-002-ref.xht" />
-->
<meta content="ahem" name="flags" />
<meta content="This test checks that rows of a table element with in a 'vertical-rl' writing mode are laid out one after the other, leftwardedly, with the first beginning at the rightmost side of the table box; table rows are ordered from right to left meaning that the 1st row is the rightmost one and then the 2nd row is juxtaposed to its left-hand side, the 3rd row is juxtaposed to the 2nd row on its left-hand side, etc..." name="assert" />
<link type="text/css" rel="stylesheet" href="support/ahem.css" />
<style type="text/css"><![CDATA[
body
{
color: yellow;
font: 1.25em/1 Ahem;
}
table
{
background-color: black;
border-spacing: 0em;
border: black solid 1em;
height: 7em;
-ah-writing-mode: vertical-rl;
-webkit-writing-mode: vertical-rl;
writing-mode: tb-rl; /* IE11 */
writing-mode: vertical-rl;
}
td
{
padding-bottom: 0em;
padding-left: 1em;
padding-right: 0em;
padding-top: 0em;
}
td.left-most-cell { padding-left: 0em; }
]]></style>
</head>
<body>
<table>
<!-- The right-most "S" -->
<tr><td>A&nbsp; B&nbsp; C&nbsp; DDD</td><td>EE F G H</td><td>JJ &nbsp;K &nbsp;L &nbsp;M</td></tr>
<!-- The left-most "S" -->
<tr><td>N&nbsp; O&nbsp; Q&nbsp; RRR</td><td>SS T U V</td><td>WW &nbsp;X &nbsp;Y &nbsp;Z</td></tr>
<!-- The "A" -->
<tr><td>aaa b&nbsp; c&nbsp; ddd</td><td>ee f g hh</td><td>jj &nbsp; &nbsp; kk</td></tr>
<!-- The "P" -->
<tr><td class="left-most-cell">mmm n&nbsp; o&nbsp; qqq</td><td class="left-most-cell">r s t uu</td><td class="left-most-cell">&nbsp; &nbsp; &nbsp; vv</td></tr>
</table>
</body>
</html>
@@ -0,0 +1,73 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>CSS Writing Modes Test: vertical-lr - line boxes progression</title>
<link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
<link rel="match" href="multicol-count-002-ref.xht" />
<!--
to be replaced with
<link rel="match" href="../css-multicol-1/multicol-count-002-ref.xht" />
-->
<meta content="ahem" name="flags" />
<meta content="This test checks that rows of a table element with in a 'vertical-lr' writing mode are laid out one after the other, rightwardedly, with the first beginning at the leftmost side of the table box; table rows are ordered from left to right meaning that the 1st row is the leftmost one and then the 2nd row is juxtaposed to its right-hand side, the 3rd row is juxtaposed to the 2nd row on its right-hand side, etc..." name="assert" />
<link type="text/css" rel="stylesheet" href="support/ahem.css" />
<style type="text/css"><![CDATA[
body
{
color: yellow;
font: 1.25em/1 Ahem;
}
table
{
background-color: black;
border-spacing: 0em;
border: black solid 1em;
height: 7em;
-ah-writing-mode: vertical-lr;
-webkit-writing-mode: vertical-lr;
writing-mode: tb-lr; /* IE11 */
writing-mode: vertical-lr;
}
td
{
padding-bottom: 0em;
padding-left: 1em;
padding-right: 0em;
padding-top: 0em;
}
td.left-most-cell { padding-left: 0em; }
]]></style>
</head>
<body>
<table>
<!-- The "P" -->
<tr><td class="left-most-cell">AAA B&nbsp; C&nbsp; DDD</td><td class="left-most-cell">EE F G H</td><td class="left-most-cell">JJ &nbsp; &nbsp; &nbsp;</td></tr>
<!-- The "A" -->
<tr><td>KKK L&nbsp; M&nbsp; NNN</td><td>OO Q R SS</td><td>TT &nbsp; &nbsp; UU</td></tr>
<!-- The left-most "S" -->
<tr><td>VVV W&nbsp; X&nbsp; Y&nbsp;</td><td>a b c dd</td><td>&nbsp;e &nbsp;f &nbsp;g hh</td></tr>
<!-- The right-most "S" -->
<tr><td>jjj k&nbsp; m&nbsp; n&nbsp;</td><td>q r s tt</td><td>&nbsp;u &nbsp;v &nbsp;w xx</td></tr>
</table>
</body>
</html>
@@ -0,0 +1,73 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>CSS Writing Modes Test: vertical-rl - table rows progression and colspan</title>
<link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
<link rel="match" href="multicol-count-002-ref.xht" />
<!--
to be replaced with
<link rel="match" href="../css-multicol-1/multicol-count-002-ref.xht" />
-->
<meta content="ahem" name="flags" />
<meta content="This test checks that colspanned cells in a table are handled according to a top-to-bottom inline flow direction." name="assert" />
<link type="text/css" rel="stylesheet" href="support/ahem.css" />
<style type="text/css"><![CDATA[
body
{
color: yellow;
font: 1.25em/1 Ahem;
}
table
{
background-color: black;
border-spacing: 0em;
border: black solid 1em;
height: 7em;
-ah-writing-mode: vertical-rl;
-webkit-writing-mode: vertical-rl;
writing-mode: tb-rl; /* IE11 */
writing-mode: vertical-rl;
}
td
{
padding-bottom: 0em;
padding-left: 1em;
padding-right: 0em;
padding-top: 0em;
}
td.left-most-cell { padding-left: 0em; }
]]></style>
</head>
<body>
<table>
<!-- The right-most "S" -->
<tr><td>A&nbsp; B&nbsp; C&nbsp; DDD</td><td>EE F G H</td><td>JJ &nbsp;K &nbsp;L &nbsp;M</td></tr>
<!-- The left-most "S" -->
<tr><td colspan="2">N&nbsp; OO Q&nbsp; R&nbsp; S&nbsp; T&nbsp; UUUU</td><td>WW &nbsp;X &nbsp;Y &nbsp;Z</td></tr>
<!-- The "A" -->
<tr><td>aaa b&nbsp; c&nbsp; ddd</td><td colspan="2">eeff g&nbsp;&nbsp; h&nbsp;&nbsp; jjjj</td></tr>
<!-- The "P" -->
<tr><td class="left-most-cell">mmm n&nbsp; o&nbsp; qqq</td><td class="left-most-cell">r s t uu</td><td class="left-most-cell">&nbsp; &nbsp; &nbsp; vv</td></tr>
</table>
</body>
</html>
@@ -0,0 +1,73 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>CSS Writing Modes Test: vertical-lr - table rows progression and colspan</title>
<link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
<link rel="match" href="multicol-count-002-ref.xht" />
<!--
to be replaced with
<link rel="match" href="../css-multicol-1/multicol-count-002-ref.xht" />
-->
<meta content="ahem" name="flags" />
<meta content="This test checks that colspanned cells in a table are handled according to a top-to-bottom inline flow direction." name="assert" />
<link type="text/css" rel="stylesheet" href="support/ahem.css" />
<style type="text/css"><![CDATA[
body
{
color: yellow;
font: 1.25em/1 Ahem;
}
table
{
background-color: black;
border-spacing: 0em;
border: black solid 1em;
height: 7em;
-ah-writing-mode: vertical-lr;
-webkit-writing-mode: vertical-lr;
writing-mode: tb-lr; /* IE11 */
writing-mode: vertical-lr;
}
td
{
padding-bottom: 0em;
padding-left: 1em;
padding-right: 0em;
padding-top: 0em;
}
td.left-most-cell { padding-left: 0em; }
]]></style>
</head>
<body>
<table>
<!-- The "P" -->
<tr><td class="left-most-cell">AAA B&nbsp; C&nbsp; DDD</td><td class="left-most-cell">EE F G H</td><td class="left-most-cell">JJ &nbsp; &nbsp; &nbsp;</td></tr>
<!-- The "A" -->
<tr><td colspan="2">KKKOO L&nbsp; Q&nbsp; M&nbsp; R&nbsp; NNNSS</td><td>TT &nbsp; &nbsp; UU</td></tr>
<!-- The left-most "S" -->
<tr><td>VVV W&nbsp; X&nbsp; Y&nbsp;</td><td colspan="2">a&nbsp; b c&nbsp; d e&nbsp; f gggg</td></tr>
<!-- The right-most "S" -->
<tr><td>jjj k&nbsp; m&nbsp; n&nbsp;</td><td>q r s tt</td><td>&nbsp;u &nbsp;v &nbsp;w xx</td></tr>
</table>
</body>
</html>
@@ -0,0 +1,73 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>CSS Writing Modes Test: vertical-rl - table rows progression and rowspan</title>
<link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
<link rel="match" href="multicol-count-002-ref.xht" />
<!--
to be replaced with
<link rel="match" href="../css-multicol-1/multicol-count-002-ref.xht" />
-->
<meta content="ahem" name="flags" />
<meta content="This test checks that rowspanned cells in a table are handled according to a right-to-left direction." name="assert" />
<link type="text/css" rel="stylesheet" href="support/ahem.css" />
<style type="text/css"><![CDATA[
body
{
color: yellow;
font: 1.25em/1 Ahem;
}
table
{
background-color: black;
border-spacing: 0em;
border: black solid 1em;
height: 7em;
-ah-writing-mode: vertical-rl;
-webkit-writing-mode: vertical-rl;
writing-mode: tb-rl; /* IE11 */
writing-mode: vertical-rl;
}
td
{
padding-bottom: 0em;
padding-left: 1em;
padding-right: 0em;
padding-top: 0em;
}
td.left-most-cell { padding-left: 0em; }
]]></style>
</head>
<body>
<table>
<!-- The right-most "S" -->
<tr><td>A&nbsp; B&nbsp; C&nbsp; DDD</td><td>EE F G H</td><td rowspan="2">JJ &nbsp;K &nbsp;L &nbsp;M &nbsp; WW &nbsp;X &nbsp;Y &nbsp;Z</td></tr>
<!-- The left-most "S" -->
<tr><td>N&nbsp; O&nbsp; Q&nbsp; RRR</td><td>SS T U V</td></tr>
<!-- The "A" -->
<tr><td>aaa b&nbsp; c&nbsp; ddd</td><td rowspan="2" class="left-most-cell">ee f g hh &nbsp; r s t uu</td><td>jj &nbsp; &nbsp; kk</td></tr>
<!-- The "P" -->
<tr><td class="left-most-cell">mmm n&nbsp; o&nbsp; qqq</td><td class="left-most-cell">&nbsp; &nbsp; &nbsp; vv</td></tr>
</table>
</body>
</html>
@@ -0,0 +1,73 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>CSS Writing Modes Test: vertical-lr - table rows progression and rowspan</title>
<link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
<link rel="match" href="multicol-count-002-ref.xht" />
<!--
to be replaced with
<link rel="match" href="../css-multicol-1/multicol-count-002-ref.xht" />
-->
<meta content="ahem" name="flags" />
<meta content="This test checks that rowspanned cells in a table are handled according to a left-to-right direction." name="assert" />
<link type="text/css" rel="stylesheet" href="support/ahem.css" />
<style type="text/css"><![CDATA[
body
{
color: yellow;
font: 1.25em/1 Ahem;
}
table
{
background-color: black;
border-spacing: 0em;
border: black solid 1em;
height: 7em;
-ah-writing-mode: vertical-lr;
-webkit-writing-mode: vertical-lr;
writing-mode: tb-lr; /* IE11 */
writing-mode: vertical-lr;
}
td
{
padding-bottom: 0em;
padding-left: 1em;
padding-right: 0em;
padding-top: 0em;
}
td.left-most-cell { padding-left: 0em; }
]]></style>
</head>
<body>
<table>
<!-- The "P" -->
<tr><td class="left-most-cell">AAA B&nbsp; C&nbsp; DDD</td><td class="left-most-cell">EE F G H</td><td class="left-most-cell" rowspan="2">JJ &nbsp; &nbsp; &nbsp; &nbsp; TT &nbsp; &nbsp; UU</td></tr>
<!-- The "A" -->
<tr><td>KKK L&nbsp; M&nbsp; NNN</td><td>OO Q R SS</td></tr>
<!-- The left-most "S" -->
<tr><td>VVV W&nbsp; X&nbsp; Y&nbsp;</td><td rowspan="2">a b c dd &nbsp; q r s tt</td><td>&nbsp;e &nbsp;f &nbsp;g hh</td></tr>
<!-- The right-most "S" -->
<tr><td>jjj k&nbsp; m&nbsp; n&nbsp;</td><td>&nbsp;u &nbsp;v &nbsp;w xx</td></tr>
</table>
</body>
</html>
+5 -26
View File
@@ -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<FillWeightArrayData*>(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<PerWeightData> 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<const RuleByWeightEntry*>(iter.Get());
weightArray[j++] = entry->data;
}
NS_QuickSort(weightArray, weightCount, sizeof(PerWeightData),
CompareWeightData, nullptr);
+19 -34
View File
@@ -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<ChildrenHashEntry*>(hdr);
nsRuleNode ***destroyQueueTail = static_cast<nsRuleNode***>(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<ChildrenHashEntry*>(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<ChildrenHashEntry*>(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<nsRuleNode**>(arg);
node->mNextSibling = *headQ;
*headQ = node;
}
return PL_DHASH_NEXT;
}
void
nsRuleNode::SweepChildren(nsTArray<nsRuleNode*>& aSweepQueue)
{
@@ -9428,7 +9401,19 @@ nsRuleNode::SweepChildren(nsTArray<nsRuleNode*>& 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<ChildrenHashEntry*>(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;
+1 -1
View File
@@ -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;
}
+7 -2
View File
@@ -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!");
+2 -2
View File
@@ -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": {
@@ -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 }
}
</style>
</head>
<body>
@@ -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();
});
</script>
+358 -352
View File
@@ -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<nscoord> 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<nscoord> 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;
}
}
}
+14 -13
View File
@@ -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_) */
+4 -13
View File
@@ -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<HashTableEntry*>(hdr);
HashTableEntry **sh = static_cast<HashTableEntry**>(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<HashTableEntry*>(iter.Get());
}
NS_QuickSort(sh, mHashTable.EntryCount(), sizeof(sh[0]),
SortArray, nullptr);
mSortedHashTable = sh;
+40 -17
View File
@@ -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
+6 -5
View File
@@ -739,7 +739,11 @@ void
Preferences::GetPreferences(InfallibleTArray<PrefSetting>* aPrefs)
{
aPrefs->SetCapacity(gHashTable->Capacity());
PL_DHashTableEnumerate(gHashTable, pref_GetPrefs, aPrefs);
for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
auto entry = static_cast<PrefHashEntry*>(iter.Get());
dom::PrefSetting *pref = aPrefs->AppendElement();
pref_GetPrefFromEntry(entry, pref);
}
}
NS_IMETHODIMP
@@ -961,12 +965,9 @@ Preferences::WritePrefFile(nsIFile* aFile)
nsAutoArrayPtr<char*> 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 *),
+8 -27
View File
@@ -42,17 +42,6 @@
}
#endif
// Definitions
struct EnumerateData {
const char *parent;
nsTArray<nsCString> *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<nsCString, 32> 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<PrefHashEntry*>(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<PrefHashEntry*>(heh);
EnumerateData *d = reinterpret_cast<EnumerateData *>(arg);
if (strncmp(he->key, d->parent, strlen(d->parent)) == 0) {
d->pref_list->AppendElement(he->key);
}
return PL_DHASH_NEXT;
}
//----------------------------------------------------------------------------
// nsPrefLocalizedString
//----------------------------------------------------------------------------
+70 -107
View File
@@ -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<pref_saveArgs *>(arg);
PrefHashEntry *pref = static_cast<PrefHashEntry *>(heh);
int32_t j = 0;
for (auto iter = aTable->Iter(); !iter.Done(); iter.Next()) {
auto pref = static_cast<PrefHashEntry*>(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<PrefHashEntry *>(heh);
dom::PrefSetting *pref =
static_cast<InfallibleTArray<dom::PrefSetting>*>(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<PrefHashEntry*>(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<PrefHashEntry*>(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<PrefHashEntry*>(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<std::vector<std::string>*>(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<std::string> prefStrings;
PL_DHashTableEnumerate(gHashTable, pref_ClearUserPref, static_cast<void*>(&prefStrings));
for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
auto pref = static_cast<PrefHashEntry*>(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());
+2 -14
View File
@@ -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);
+3 -7
View File
@@ -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
*/
+5 -16
View File
@@ -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;
+20 -43
View File
@@ -2883,58 +2883,32 @@ nsCacheService::ClearDoomList()
}
}
PLDHashOperator
nsCacheService::GetActiveEntries(PLDHashTable * table,
PLDHashEntryHdr * hdr,
uint32_t number,
void * arg)
{
static_cast<nsTArray<nsCacheEntry*>*>(arg)->AppendElement(
((nsCacheEntryHashTableEntry *)hdr)->cacheEntry);
return PL_DHASH_NEXT;
}
struct ActiveEntryArgs
{
nsTArray<nsCacheEntry*>* mActiveArray;
nsCacheService::DoomCheckFn mCheckFn;
};
void
nsCacheService::DoomActiveEntries(DoomCheckFn check)
{
nsAutoTArray<nsCacheEntry*, 8> array;
ActiveEntryArgs args = { &array, check };
mActiveEntries.VisitEntries(RemoveActiveEntry, &args);
for (auto iter = mActiveEntries.Iter(); !iter.Done(); iter.Next()) {
nsCacheEntry* entry =
static_cast<nsCacheEntryHashTableEntry*>(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<ActiveEntryArgs*>(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<nsCacheEntryHashTableEntry*>(iter.Get());
entries.AppendElement(entry->cacheEntry);
}
NS_ASSERTION(entries.IsEmpty(), "Bad state");
#endif
-11
View File
@@ -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<nsOfflineCacheDevice>& aDevice,
+4 -10
View File
@@ -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
+68 -92
View File
@@ -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<nsHostDBEnt *>(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<nsHostRecord *>(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<nsHostRecord *>(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<nsHostDBEnt *>(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<nsHostDBEnt*>(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<DNSCacheEntries> *args = static_cast<nsTArray<DNSCacheEntries> *>(arg);
args->AppendElement(info);
return PL_DHASH_NEXT;
}
void
nsHostResolver::GetDNSCacheEntries(nsTArray<DNSCacheEntries> *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<nsHostDBEnt*>(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);
}
}
+1 -1
View File
@@ -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<Entry*>(iter.Get());
Assertion* as = entry->mAssertions;
+24 -36
View File
@@ -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<ObjectHashEntry*>(hdr);
nsOnPK11LogoutCancelObject *pklco =
reinterpret_cast<nsOnPK11LogoutCancelObject*>(entry->obj);
if (pklco) {
pklco->logout();
for (auto iter = mPK11LogoutCancelObjects.Iter(); !iter.Done(); iter.Next()) {
auto entry = static_cast<ObjectHashEntry*>(iter.Get());
nsOnPK11LogoutCancelObject *pklco =
reinterpret_cast<nsOnPK11LogoutCancelObject*>(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<ObjectHashEntry*>(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<ObjectHashEntry*>(iter.Get());
{
MutexAutoUnlock unlock(singleton->mListLock);
entry->obj->shutdown(nsNSSShutDownObject::calledFromList);
}
iter.Remove();
}
mActivityState.releaseCurrentThreadActivityRestriction();
return NS_OK;
}
nsNSSShutDownList *nsNSSShutDownList::construct()
-6
View File
@@ -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;
+2 -2
View File
@@ -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<EntryType*>(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<EntryType*>(iter.Get());
PLDHashOperator op = aEnumFunc(entry->GetKey(), entry->mData, aUserArg);
n++;
+1 -1
View File
@@ -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<EntryType*>(iter.Get());
PLDHashOperator op = aEnumFunc(entry, aUserArg);
n++;
+12 -36
View File
@@ -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<PLDHashTable*>(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<PLDHashTable*>(mTable)->RawRemove(Get());
mTable->RawRemove(Get());
mHaveRemoved = true;
}
+22 -32
View File
@@ -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<FooEntry*>(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<FooEntry*>(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<PLDHashTable*>(this));
return Iterator(const_cast<PLDHashTable*>(this));
}
private:
+5 -20
View File
@@ -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<PLDHashEntryStub*>(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<PLDHashEntryStub*>(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);