Backed out 2 changesets (bug 1617746) assertion failures on ShadowRoot.cpp.

CLOSED TREE
Backed out changeset 6cb30e866b95 (bug 1617746)
Backed out changeset 3543162b815b (bug 1617746)
This commit is contained in:
Cosmin Sabou 2020-02-27 01:12:46 +02:00
parent a4cb1b1fae
commit 3497aa8314
17 changed files with 355 additions and 316 deletions

View File

@ -2705,35 +2705,70 @@ size_t Document::FindDocStyleSheetInsertionPoint(const StyleSheet& aSheet) {
return index; return index;
} }
void Document::AppendAdoptedStyleSheet(StyleSheet& aSheet) {
DocumentOrShadowRoot::InsertAdoptedSheetAt(mAdoptedStyleSheets.Length(),
aSheet);
if (aSheet.IsApplicable()) {
AddStyleSheetToStyleSets(&aSheet);
}
}
void Document::RemoveDocStyleSheetsFromStyleSets() {
MOZ_ASSERT(mStyleSetFilled);
// The stylesheets should forget us
for (StyleSheet* sheet : Reversed(mStyleSheets)) {
sheet->ClearAssociatedDocumentOrShadowRoot();
if (sheet->IsApplicable()) {
mStyleSet->RemoveDocStyleSheet(sheet);
}
// XXX Tell observers?
}
}
void Document::RemoveStyleSheetsFromStyleSets(
const nsTArray<RefPtr<StyleSheet>>& aSheets, StyleOrigin aType) {
// The stylesheets should forget us
for (StyleSheet* sheet : Reversed(aSheets)) {
sheet->ClearAssociatedDocumentOrShadowRoot();
if (mStyleSetFilled && sheet->IsApplicable()) {
mStyleSet->RemoveStyleSheet(aType, sheet);
}
// XXX Tell observers?
}
}
void Document::ResetStylesheetsToURI(nsIURI* aURI) { void Document::ResetStylesheetsToURI(nsIURI* aURI) {
MOZ_ASSERT(aURI); MOZ_ASSERT(aURI);
ClearAdoptedStyleSheets();
auto ClearSheetList = [&](nsTArray<RefPtr<StyleSheet>>& aSheetList) {
for (auto& sheet : Reversed(aSheetList)) {
sheet->ClearAssociatedDocumentOrShadowRoot();
if (mStyleSetFilled) {
mStyleSet->RemoveStyleSheet(*sheet);
}
}
aSheetList.Clear();
};
ClearSheetList(mStyleSheets);
for (auto& sheets : mAdditionalSheets) {
ClearSheetList(sheets);
}
if (mStyleSetFilled) { if (mStyleSetFilled) {
if (auto* ss = nsStyleSheetService::GetInstance()) { // Skip removing style sheets from the style set if we know we haven't
for (auto& sheet : Reversed(*ss->AuthorStyleSheets())) { // filled the style set. (This allows us to avoid calling
MOZ_ASSERT(!sheet->GetAssociatedDocumentOrShadowRoot()); // GetStyleBackendType() too early.)
if (sheet->IsApplicable()) { RemoveDocStyleSheetsFromStyleSets();
mStyleSet->RemoveStyleSheet(*sheet); RemoveStyleSheetsFromStyleSets(mAdditionalSheets[eAgentSheet],
} StyleOrigin::UserAgent);
} RemoveStyleSheetsFromStyleSets(mAdditionalSheets[eUserSheet],
StyleOrigin::User);
RemoveStyleSheetsFromStyleSets(mAdditionalSheets[eAuthorSheet],
StyleOrigin::Author);
if (nsStyleSheetService* sheetService =
nsStyleSheetService::GetInstance()) {
RemoveStyleSheetsFromStyleSets(*sheetService->AuthorStyleSheets(),
StyleOrigin::Author);
} }
} }
// Release all the sheets
mStyleSheets.Clear();
for (auto& sheets : mAdditionalSheets) {
sheets.Clear();
}
// NOTE: We don't release the catalog sheets. It doesn't really matter
// now, but it could in the future -- in which case not releasing them
// is probably the right thing to do.
// Now reset our inline style and attribute sheets. // Now reset our inline style and attribute sheets.
if (mAttrStyleSheet) { if (mAttrStyleSheet) {
mAttrStyleSheet->Reset(); mAttrStyleSheet->Reset();
@ -2755,10 +2790,11 @@ void Document::ResetStylesheetsToURI(nsIURI* aURI) {
} }
} }
static void AppendSheetsToStyleSet( static void AppendSheetsToStyleSet(ServoStyleSet* aStyleSet,
ServoStyleSet* aStyleSet, const nsTArray<RefPtr<StyleSheet>>& aSheets) { const nsTArray<RefPtr<StyleSheet>>& aSheets,
StyleOrigin aOrigin) {
for (StyleSheet* sheet : Reversed(aSheets)) { for (StyleSheet* sheet : Reversed(aSheets)) {
aStyleSet->AppendStyleSheet(*sheet); aStyleSet->AppendStyleSheet(aOrigin, sheet);
} }
} }
@ -2775,57 +2811,59 @@ void Document::FillStyleSetUserAndUASheets() {
"service has gone"); "service has gone");
for (StyleSheet* sheet : *sheetService->UserStyleSheets()) { for (StyleSheet* sheet : *sheetService->UserStyleSheets()) {
mStyleSet->AppendStyleSheet(*sheet); mStyleSet->AppendStyleSheet(StyleOrigin::User, sheet);
} }
StyleSheet* sheet = IsInChromeDocShell() ? cache->GetUserChromeSheet() StyleSheet* sheet = IsInChromeDocShell() ? cache->GetUserChromeSheet()
: cache->GetUserContentSheet(); : cache->GetUserContentSheet();
if (sheet) { if (sheet) {
mStyleSet->AppendStyleSheet(*sheet); mStyleSet->AppendStyleSheet(StyleOrigin::User, sheet);
} }
mStyleSet->AppendStyleSheet(*cache->UASheet()); mStyleSet->AppendStyleSheet(StyleOrigin::UserAgent, cache->UASheet());
if (MOZ_LIKELY(NodeInfoManager()->MathMLEnabled())) { if (MOZ_LIKELY(NodeInfoManager()->MathMLEnabled())) {
mStyleSet->AppendStyleSheet(*cache->MathMLSheet()); mStyleSet->AppendStyleSheet(StyleOrigin::UserAgent, cache->MathMLSheet());
} }
if (MOZ_LIKELY(NodeInfoManager()->SVGEnabled())) { if (MOZ_LIKELY(NodeInfoManager()->SVGEnabled())) {
mStyleSet->AppendStyleSheet(*cache->SVGSheet()); mStyleSet->AppendStyleSheet(StyleOrigin::UserAgent, cache->SVGSheet());
} }
mStyleSet->AppendStyleSheet(*cache->HTMLSheet()); mStyleSet->AppendStyleSheet(StyleOrigin::UserAgent, cache->HTMLSheet());
if (nsLayoutUtils::ShouldUseNoFramesSheet(this)) { if (nsLayoutUtils::ShouldUseNoFramesSheet(this)) {
mStyleSet->AppendStyleSheet(*cache->NoFramesSheet()); mStyleSet->AppendStyleSheet(StyleOrigin::UserAgent, cache->NoFramesSheet());
} }
if (nsLayoutUtils::ShouldUseNoScriptSheet(this)) { if (nsLayoutUtils::ShouldUseNoScriptSheet(this)) {
mStyleSet->AppendStyleSheet(*cache->NoScriptSheet()); mStyleSet->AppendStyleSheet(StyleOrigin::UserAgent, cache->NoScriptSheet());
} }
mStyleSet->AppendStyleSheet(*cache->CounterStylesSheet()); mStyleSet->AppendStyleSheet(StyleOrigin::UserAgent,
cache->CounterStylesSheet());
// Load the minimal XUL rules for scrollbars and a few other XUL things // Load the minimal XUL rules for scrollbars and a few other XUL things
// that non-XUL (typically HTML) documents commonly use. // that non-XUL (typically HTML) documents commonly use.
mStyleSet->AppendStyleSheet(*cache->MinimalXULSheet()); mStyleSet->AppendStyleSheet(StyleOrigin::UserAgent, cache->MinimalXULSheet());
// Only load the full XUL sheet if we'll need it. // Only load the full XUL sheet if we'll need it.
if (LoadsFullXULStyleSheetUpFront()) { if (LoadsFullXULStyleSheetUpFront()) {
mStyleSet->AppendStyleSheet(*cache->XULSheet()); mStyleSet->AppendStyleSheet(StyleOrigin::UserAgent, cache->XULSheet());
} }
mStyleSet->AppendStyleSheet(*cache->FormsSheet()); mStyleSet->AppendStyleSheet(StyleOrigin::UserAgent, cache->FormsSheet());
mStyleSet->AppendStyleSheet(*cache->ScrollbarsSheet()); mStyleSet->AppendStyleSheet(StyleOrigin::UserAgent, cache->ScrollbarsSheet());
mStyleSet->AppendStyleSheet(*cache->PluginProblemSheet()); mStyleSet->AppendStyleSheet(StyleOrigin::UserAgent,
cache->PluginProblemSheet());
for (StyleSheet* sheet : *sheetService->AgentStyleSheets()) { for (StyleSheet* sheet : *sheetService->AgentStyleSheets()) {
mStyleSet->AppendStyleSheet(*sheet); mStyleSet->AppendStyleSheet(StyleOrigin::UserAgent, sheet);
} }
MOZ_ASSERT(!mQuirkSheetAdded); MOZ_ASSERT(!mQuirkSheetAdded);
if (NeedsQuirksSheet()) { if (NeedsQuirksSheet()) {
mStyleSet->AppendStyleSheet(*cache->QuirkSheet()); mStyleSet->AppendStyleSheet(StyleOrigin::UserAgent, cache->QuirkSheet());
mQuirkSheetAdded = true; mQuirkSheetAdded = true;
} }
} }
@ -2843,12 +2881,14 @@ void Document::RemoveContentEditableStyleSheets() {
auto* cache = GlobalStyleSheetCache::Singleton(); auto* cache = GlobalStyleSheetCache::Singleton();
bool changed = false; bool changed = false;
if (mDesignModeSheetAdded) { if (mDesignModeSheetAdded) {
mStyleSet->RemoveStyleSheet(*cache->DesignModeSheet()); mStyleSet->RemoveStyleSheet(StyleOrigin::UserAgent,
cache->DesignModeSheet());
mDesignModeSheetAdded = false; mDesignModeSheetAdded = false;
changed = true; changed = true;
} }
if (mContentEditableSheetAdded) { if (mContentEditableSheetAdded) {
mStyleSet->RemoveStyleSheet(*cache->ContentEditableSheet()); mStyleSet->RemoveStyleSheet(StyleOrigin::UserAgent,
cache->ContentEditableSheet());
mContentEditableSheetAdded = false; mContentEditableSheetAdded = false;
changed = true; changed = true;
} }
@ -2866,15 +2906,18 @@ void Document::AddContentEditableStyleSheetsToStyleSet(bool aDesignMode) {
auto* cache = GlobalStyleSheetCache::Singleton(); auto* cache = GlobalStyleSheetCache::Singleton();
bool changed = false; bool changed = false;
if (!mContentEditableSheetAdded) { if (!mContentEditableSheetAdded) {
mStyleSet->AppendStyleSheet(*cache->ContentEditableSheet()); mStyleSet->AppendStyleSheet(StyleOrigin::UserAgent,
cache->ContentEditableSheet());
mContentEditableSheetAdded = true; mContentEditableSheetAdded = true;
changed = true; changed = true;
} }
if (mDesignModeSheetAdded != aDesignMode) { if (mDesignModeSheetAdded != aDesignMode) {
if (mDesignModeSheetAdded) { if (mDesignModeSheetAdded) {
mStyleSet->RemoveStyleSheet(*cache->DesignModeSheet()); mStyleSet->RemoveStyleSheet(StyleOrigin::UserAgent,
cache->DesignModeSheet());
} else { } else {
mStyleSet->AppendStyleSheet(*cache->DesignModeSheet()); mStyleSet->AppendStyleSheet(StyleOrigin::UserAgent,
cache->DesignModeSheet());
} }
mDesignModeSheetAdded = !mDesignModeSheetAdded; mDesignModeSheetAdded = !mDesignModeSheetAdded;
changed = true; changed = true;
@ -2888,32 +2931,31 @@ void Document::FillStyleSetDocumentSheets() {
MOZ_ASSERT(mStyleSet->SheetCount(StyleOrigin::Author) == 0, MOZ_ASSERT(mStyleSet->SheetCount(StyleOrigin::Author) == 0,
"Style set already has document sheets?"); "Style set already has document sheets?");
// Sheets are added in reverse order to avoid worst-case time complexity when // Sheets are added in reverse order to avoid worst-case
// looking up the index of a sheet. // time complexity when looking up the index of a sheet
//
// Note that usually appending is faster (rebuilds less stuff in the
// styleset), but in this case it doesn't matter since we're filling the
// styleset from scratch anyway.
for (StyleSheet* sheet : Reversed(mStyleSheets)) { for (StyleSheet* sheet : Reversed(mStyleSheets)) {
if (sheet->IsApplicable()) { if (sheet->IsApplicable()) {
mStyleSet->AddDocStyleSheet(*sheet); mStyleSet->AddDocStyleSheet(sheet);
} }
} }
EnumerateUniqueAdoptedStyleSheetsBackToFront([&](StyleSheet& aSheet) { for (StyleSheet* sheet : Reversed(mAdoptedStyleSheets)) {
if (aSheet.IsApplicable()) { if (sheet->IsApplicable()) {
mStyleSet->AddDocStyleSheet(aSheet); mStyleSet->AddDocStyleSheet(sheet);
} }
}); }
nsStyleSheetService* sheetService = nsStyleSheetService::GetInstance(); nsStyleSheetService* sheetService = nsStyleSheetService::GetInstance();
for (StyleSheet* sheet : *sheetService->AuthorStyleSheets()) { for (StyleSheet* sheet : *sheetService->AuthorStyleSheets()) {
mStyleSet->AppendStyleSheet(*sheet); mStyleSet->AppendStyleSheet(StyleOrigin::Author, sheet);
} }
AppendSheetsToStyleSet(mStyleSet.get(), mAdditionalSheets[eAgentSheet]); AppendSheetsToStyleSet(mStyleSet.get(), mAdditionalSheets[eAgentSheet],
AppendSheetsToStyleSet(mStyleSet.get(), mAdditionalSheets[eUserSheet]); StyleOrigin::UserAgent);
AppendSheetsToStyleSet(mStyleSet.get(), mAdditionalSheets[eAuthorSheet]); AppendSheetsToStyleSet(mStyleSet.get(), mAdditionalSheets[eUserSheet],
StyleOrigin::User);
AppendSheetsToStyleSet(mStyleSet.get(), mAdditionalSheets[eAuthorSheet],
StyleOrigin::Author);
} }
void Document::CompatibilityModeChanged() { void Document::CompatibilityModeChanged() {
@ -2935,9 +2977,9 @@ void Document::CompatibilityModeChanged() {
auto* cache = GlobalStyleSheetCache::Singleton(); auto* cache = GlobalStyleSheetCache::Singleton();
StyleSheet* sheet = cache->QuirkSheet(); StyleSheet* sheet = cache->QuirkSheet();
if (mQuirkSheetAdded) { if (mQuirkSheetAdded) {
mStyleSet->RemoveStyleSheet(*sheet); mStyleSet->RemoveStyleSheet(StyleOrigin::UserAgent, sheet);
} else { } else {
mStyleSet->AppendStyleSheet(*sheet); mStyleSet->AppendStyleSheet(StyleOrigin::UserAgent, sheet);
} }
mQuirkSheetAdded = !mQuirkSheetAdded; mQuirkSheetAdded = !mQuirkSheetAdded;
ApplicableStylesChanged(); ApplicableStylesChanged();
@ -6501,7 +6543,7 @@ void Document::RemoveChildNode(nsIContent* aKid, bool aNotify) {
"(maybe somebody called GetRootElement() too early?)"); "(maybe somebody called GetRootElement() too early?)");
} }
void Document::AddStyleSheetToStyleSets(StyleSheet& aSheet) { void Document::AddStyleSheetToStyleSets(StyleSheet* aSheet) {
if (mStyleSetFilled) { if (mStyleSetFilled) {
mStyleSet->AddDocStyleSheet(aSheet); mStyleSet->AddDocStyleSheet(aSheet);
ApplicableStylesChanged(); ApplicableStylesChanged();
@ -6537,9 +6579,9 @@ void Document::ApplicableStylesChanged() {
pc->RestyleManager()->NextRestyleIsForCSSRuleChanges(); pc->RestyleManager()->NextRestyleIsForCSSRuleChanges();
} }
void Document::RemoveStyleSheetFromStyleSets(StyleSheet& aSheet) { void Document::RemoveStyleSheetFromStyleSets(StyleSheet* aSheet) {
if (mStyleSetFilled) { if (mStyleSetFilled) {
mStyleSet->RemoveStyleSheet(aSheet); mStyleSet->RemoveDocStyleSheet(aSheet);
ApplicableStylesChanged(); ApplicableStylesChanged();
} }
} }
@ -6553,7 +6595,7 @@ void Document::RemoveStyleSheet(StyleSheet& aSheet) {
} }
if (!mIsGoingAway && sheet->IsApplicable()) { if (!mIsGoingAway && sheet->IsApplicable()) {
RemoveStyleSheetFromStyleSets(*sheet); RemoveStyleSheetFromStyleSets(sheet);
} }
sheet->ClearAssociatedDocumentOrShadowRoot(); sheet->ClearAssociatedDocumentOrShadowRoot();
@ -6563,7 +6605,7 @@ void Document::InsertSheetAt(size_t aIndex, StyleSheet& aSheet) {
DocumentOrShadowRoot::InsertSheetAt(aIndex, aSheet); DocumentOrShadowRoot::InsertSheetAt(aIndex, aSheet);
if (aSheet.IsApplicable()) { if (aSheet.IsApplicable()) {
AddStyleSheetToStyleSets(aSheet); AddStyleSheetToStyleSets(&aSheet);
} }
} }
@ -6572,9 +6614,9 @@ void Document::StyleSheetApplicableStateChanged(StyleSheet& aSheet) {
// If we're actually in the document style sheet list // If we're actually in the document style sheet list
if (StyleOrderIndexOfSheet(aSheet) >= 0) { if (StyleOrderIndexOfSheet(aSheet) >= 0) {
if (applicable) { if (applicable) {
AddStyleSheetToStyleSets(aSheet); AddStyleSheetToStyleSets(&aSheet);
} else { } else {
RemoveStyleSheetFromStyleSets(aSheet); RemoveStyleSheetFromStyleSets(&aSheet);
} }
} }
@ -6616,6 +6658,20 @@ void Document::NotifyStyleSheetApplicableStateChanged() {
} }
} }
static StyleOrigin ConvertAdditionalSheetType(
Document::additionalSheetType aType) {
switch (aType) {
case Document::eAgentSheet:
return StyleOrigin::UserAgent;
case Document::eUserSheet:
return StyleOrigin::User;
case Document::eAuthorSheet:
return StyleOrigin::Author;
default:
MOZ_CRASH("Wrong sheet type");
}
}
static int32_t FindSheet(const nsTArray<RefPtr<StyleSheet>>& aSheets, static int32_t FindSheet(const nsTArray<RefPtr<StyleSheet>>& aSheets,
nsIURI* aSheetURI) { nsIURI* aSheetURI) {
for (int32_t i = aSheets.Length() - 1; i >= 0; i--) { for (int32_t i = aSheets.Length() - 1; i >= 0; i--) {
@ -6686,7 +6742,7 @@ nsresult Document::AddAdditionalStyleSheet(additionalSheetType aType,
mAdditionalSheets[aType].AppendElement(aSheet); mAdditionalSheets[aType].AppendElement(aSheet);
if (mStyleSetFilled) { if (mStyleSetFilled) {
mStyleSet->AppendStyleSheet(*aSheet); mStyleSet->AppendStyleSheet(ConvertAdditionalSheetType(aType), aSheet);
ApplicableStylesChanged(); ApplicableStylesChanged();
} }
return NS_OK; return NS_OK;
@ -6700,13 +6756,14 @@ void Document::RemoveAdditionalStyleSheet(additionalSheetType aType,
int32_t i = FindSheet(mAdditionalSheets[aType], aSheetURI); int32_t i = FindSheet(mAdditionalSheets[aType], aSheetURI);
if (i >= 0) { if (i >= 0) {
RefPtr<StyleSheet> sheetRef = std::move(sheets[i]); RefPtr<StyleSheet> sheetRef = sheets[i];
sheets.RemoveElementAt(i); sheets.RemoveElementAt(i);
if (!mIsGoingAway) { if (!mIsGoingAway) {
MOZ_ASSERT(sheetRef->IsApplicable()); MOZ_ASSERT(sheetRef->IsApplicable());
if (mStyleSetFilled) { if (mStyleSetFilled) {
mStyleSet->RemoveStyleSheet(*sheetRef); mStyleSet->RemoveStyleSheet(ConvertAdditionalSheetType(aType),
sheetRef);
ApplicableStylesChanged(); ApplicableStylesChanged();
} }
} }
@ -16113,5 +16170,34 @@ Document::RecomputeContentBlockingAllowListPrincipal(
return copy.forget(); return copy.forget();
} }
// https://wicg.github.io/construct-stylesheets/#dom-documentorshadowroot-adoptedstylesheets
void Document::SetAdoptedStyleSheets(
const Sequence<OwningNonNull<StyleSheet>>& aAdoptedStyleSheets,
ErrorResult& aRv) {
// Step 1 is a variable declaration
// 2.1 Check if all sheets are constructed, else throw NotAllowedError
// 2.2 Check if all sheets' constructor documents match the
// DocumentOrShadowRoot's node document, else throw NotAlloweError
EnsureAdoptedSheetsAreValid(aAdoptedStyleSheets, aRv);
if (aRv.Failed()) {
return;
}
// 3. Set the adopted style sheets to the new sheets
for (const RefPtr<StyleSheet>& sheet : mAdoptedStyleSheets) {
if (sheet->IsApplicable()) {
RemoveStyleSheetFromStyleSets(sheet);
}
sheet->RemoveAdopter(*this);
}
mAdoptedStyleSheets.ClearAndRetainStorage();
mAdoptedStyleSheets.SetCapacity(aAdoptedStyleSheets.Length());
for (const OwningNonNull<StyleSheet>& sheet : aAdoptedStyleSheets) {
sheet->AddAdopter(*this);
AppendAdoptedStyleSheet(*sheet);
}
}
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla

View File

@ -475,8 +475,6 @@ class Document : public nsINode,
public nsStubMutationObserver, public nsStubMutationObserver,
public DispatcherTrait, public DispatcherTrait,
public SupportsWeakPtr<Document> { public SupportsWeakPtr<Document> {
friend class DocumentOrShadowRoot;
protected: protected:
explicit Document(const char* aContentType); explicit Document(const char* aContentType);
virtual ~Document(); virtual ~Document();
@ -1728,6 +1726,8 @@ class Document : public nsINode,
return mAdditionalSheets[eAuthorSheet].SafeElementAt(0); return mAdditionalSheets[eAuthorSheet].SafeElementAt(0);
} }
void AppendAdoptedStyleSheet(StyleSheet& aSheet);
/** /**
* Returns the index that aSheet should be inserted at to maintain document * Returns the index that aSheet should be inserted at to maintain document
* ordering. * ordering.
@ -3882,6 +3882,10 @@ class Document : public nsINode,
already_AddRefed<Promise> AddCertException(bool aIsTemporary); already_AddRefed<Promise> AddCertException(bool aIsTemporary);
void SetAdoptedStyleSheets(
const Sequence<OwningNonNull<StyleSheet>>& aAdoptedStyleSheets,
ErrorResult& aRv);
protected: protected:
void DoUpdateSVGUseElementShadowTrees(); void DoUpdateSVGUseElementShadowTrees();
@ -3936,6 +3940,8 @@ class Document : public nsINode,
} }
void RemoveDocStyleSheetsFromStyleSets(); void RemoveDocStyleSheetsFromStyleSets();
void RemoveStyleSheetsFromStyleSets(
const nsTArray<RefPtr<StyleSheet>>& aSheets, StyleOrigin);
void ResetStylesheetsToURI(nsIURI* aURI); void ResetStylesheetsToURI(nsIURI* aURI);
void FillStyleSet(); void FillStyleSet();
void FillStyleSetUserAndUASheets(); void FillStyleSetUserAndUASheets();
@ -3948,8 +3954,8 @@ class Document : public nsINode,
} }
void AddContentEditableStyleSheetsToStyleSet(bool aDesignMode); void AddContentEditableStyleSheetsToStyleSet(bool aDesignMode);
void RemoveContentEditableStyleSheets(); void RemoveContentEditableStyleSheets();
void AddStyleSheetToStyleSets(StyleSheet&); void AddStyleSheetToStyleSets(StyleSheet* aSheet);
void RemoveStyleSheetFromStyleSets(StyleSheet&); void RemoveStyleSheetFromStyleSets(StyleSheet* aSheet);
void NotifyStyleSheetApplicableStateChanged(); void NotifyStyleSheetApplicableStateChanged();
// Just like EnableStyleSheetsForSet, but doesn't check whether // Just like EnableStyleSheetsForSet, but doesn't check whether
// aSheetSet is null and allows the caller to control whether to set // aSheetSet is null and allows the caller to control whether to set

View File

@ -78,6 +78,11 @@ void DocumentOrShadowRoot::InsertSheetAt(size_t aIndex, StyleSheet& aSheet) {
mStyleSheets.InsertElementAt(aIndex, &aSheet); mStyleSheets.InsertElementAt(aIndex, &aSheet);
} }
void DocumentOrShadowRoot::InsertAdoptedSheetAt(size_t aIndex,
StyleSheet& aSheet) {
mAdoptedStyleSheets.InsertElementAt(aIndex, &aSheet);
}
already_AddRefed<StyleSheet> DocumentOrShadowRoot::RemoveSheet( already_AddRefed<StyleSheet> DocumentOrShadowRoot::RemoveSheet(
StyleSheet& aSheet) { StyleSheet& aSheet) {
auto index = mStyleSheets.IndexOf(&aSheet); auto index = mStyleSheets.IndexOf(&aSheet);
@ -90,24 +95,13 @@ already_AddRefed<StyleSheet> DocumentOrShadowRoot::RemoveSheet(
return sheet.forget(); return sheet.forget();
} }
void DocumentOrShadowRoot::RemoveSheetFromStylesIfApplicable(
StyleSheet& aSheet) {
if (!aSheet.IsApplicable()) {
return;
}
if (mKind == Kind::Document) {
AsNode().AsDocument()->RemoveStyleSheetFromStyleSets(aSheet);
} else {
MOZ_ASSERT(AsNode().IsShadowRoot());
static_cast<ShadowRoot&>(AsNode()).RemoveSheetFromStyles(aSheet);
}
}
// https://wicg.github.io/construct-stylesheets/#dom-documentorshadowroot-adoptedstylesheets // https://wicg.github.io/construct-stylesheets/#dom-documentorshadowroot-adoptedstylesheets
void DocumentOrShadowRoot::SetAdoptedStyleSheets( void DocumentOrShadowRoot::EnsureAdoptedSheetsAreValid(
const Sequence<OwningNonNull<StyleSheet>>& aAdoptedStyleSheets, const Sequence<OwningNonNull<StyleSheet>>& aAdoptedStyleSheets,
ErrorResult& aRv) { ErrorResult& aRv) {
Document& doc = *AsNode().OwnerDoc(); nsTHashtable<nsPtrHashKey<const StyleSheet>> set(
aAdoptedStyleSheets.Length());
for (const OwningNonNull<StyleSheet>& sheet : aAdoptedStyleSheets) { for (const OwningNonNull<StyleSheet>& sheet : aAdoptedStyleSheets) {
// 2.1 Check if all sheets are constructed, else throw NotAllowedError // 2.1 Check if all sheets are constructed, else throw NotAllowedError
if (!sheet->IsConstructed()) { if (!sheet->IsConstructed()) {
@ -117,51 +111,23 @@ void DocumentOrShadowRoot::SetAdoptedStyleSheets(
} }
// 2.2 Check if all sheets' constructor documents match the // 2.2 Check if all sheets' constructor documents match the
// DocumentOrShadowRoot's node document, else throw NotAlloweError // DocumentOrShadowRoot's node document, else throw NotAlloweError
if (!sheet->ConstructorDocumentMatches(doc)) { if (!sheet->ConstructorDocumentMatches(AsNode().OwnerDoc())) {
return aRv.ThrowNotAllowedError( return aRv.ThrowNotAllowedError(
"Each adopted style sheet's constructor document must match the " "Each adopted style sheet's constructor document must match the "
"document or shadow root's node document"); "document or shadow root's node document");
} }
}
auto* shadow = ShadowRoot::FromNode(AsNode()); // FIXME(nordzilla): This is temporary code to disallow duplicate sheets.
MOZ_ASSERT((mKind == Kind::ShadowRoot) == !!shadow); // This exists to ensure that the fuzzers aren't blocked.
// This code will eventually be removed.
ClearAdoptedStyleSheets(); // https://bugzilla.mozilla.org/show_bug.cgi?id=1617302
if (!set.EnsureInserted(sheet.get())) {
// 3. Set the adopted style sheets to the new sheets return aRv.ThrowNotAllowedError(
mAdoptedStyleSheets.SetCapacity(aAdoptedStyleSheets.Length()); "Temporarily disallowing duplicate stylesheets.");
AdoptedStyleSheetSet set(aAdoptedStyleSheets.Length());
for (const OwningNonNull<StyleSheet>& sheet : aAdoptedStyleSheets) {
if (MOZ_UNLIKELY(!set.EnsureInserted(sheet.get()))) {
// The idea is that this case is rare, so we pay the price of removing the
// old sheet from the styles and append it later rather than the other way
// around.
RemoveSheetFromStylesIfApplicable(*sheet);
} else {
sheet->AddAdopter(*this);
}
mAdoptedStyleSheets.AppendElement(sheet);
if (sheet->IsApplicable()) {
if (mKind == Kind::Document) {
doc.AddStyleSheetToStyleSets(*sheet);
} else {
shadow->InsertSheetIntoAuthorData(mAdoptedStyleSheets.Length() - 1,
*sheet, mAdoptedStyleSheets);
}
} }
} }
} }
void DocumentOrShadowRoot::ClearAdoptedStyleSheets() {
EnumerateUniqueAdoptedStyleSheetsBackToFront([&](StyleSheet& aSheet) {
RemoveSheetFromStylesIfApplicable(aSheet);
aSheet.RemoveAdopter(*this);
});
mAdoptedStyleSheets.Clear();
}
Element* DocumentOrShadowRoot::GetElementById(const nsAString& aElementId) { Element* DocumentOrShadowRoot::GetElementById(const nsAString& aElementId) {
if (MOZ_UNLIKELY(aElementId.IsEmpty())) { if (MOZ_UNLIKELY(aElementId.IsEmpty())) {
nsContentUtils::ReportEmptyGetElementByIdArg(AsNode().OwnerDoc()); nsContentUtils::ReportEmptyGetElementByIdArg(AsNode().OwnerDoc());
@ -696,9 +662,7 @@ nsRadioGroupStruct* DocumentOrShadowRoot::GetOrCreateRadioGroup(
int32_t DocumentOrShadowRoot::StyleOrderIndexOfSheet( int32_t DocumentOrShadowRoot::StyleOrderIndexOfSheet(
const StyleSheet& aSheet) const { const StyleSheet& aSheet) const {
if (aSheet.IsConstructed()) { if (aSheet.IsConstructed()) {
// NOTE: constructable sheets can have duplicates, so we need to start int32_t index = mAdoptedStyleSheets.IndexOf(&aSheet);
// looking from behind.
int32_t index = mAdoptedStyleSheets.LastIndexOf(&aSheet);
return (index < 0) ? index : index + SheetCount(); return (index < 0) ? index : index + SheetCount();
} }
return mStyleSheets.IndexOf(&aSheet); return mStyleSheets.IndexOf(&aSheet);
@ -715,27 +679,26 @@ void DocumentOrShadowRoot::Traverse(DocumentOrShadowRoot* tmp,
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMStyleSheets) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMStyleSheets)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAdoptedStyleSheets) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAdoptedStyleSheets)
auto NoteSheetIfApplicable = [&](StyleSheet& aSheet) { auto NoteSheets = [tmp, &cb = cb](nsTArray<RefPtr<StyleSheet>>& sheetList) {
if (!aSheet.IsApplicable()) { for (StyleSheet* sheet : sheetList) {
return; if (!sheet->IsApplicable()) {
} continue;
// The style set or mServoStyles keep more references to it if the sheet }
// is applicable. // The style set or mServoStyles keep more references to it if the sheet
if (tmp->mKind == Kind::ShadowRoot) { // is applicable.
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mServoStyles->sheets[i]"); if (tmp->mKind == Kind::ShadowRoot) {
cb.NoteXPCOMChild(&aSheet); NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mServoStyles->sheets[i]");
} else if (tmp->AsNode().AsDocument()->StyleSetFilled()) { cb.NoteXPCOMChild(sheet);
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME( } else if (tmp->AsNode().AsDocument()->StyleSetFilled()) {
cb, "mStyleSet->mRawSet.stylist.stylesheets.author[i]"); NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(
cb.NoteXPCOMChild(&aSheet); cb, "mStyleSet->mRawSet.stylist.stylesheets.author[i]");
cb.NoteXPCOMChild(sheet);
}
} }
}; };
for (auto& sheet : tmp->mStyleSheets) { NoteSheets(tmp->mStyleSheets);
NoteSheetIfApplicable(*sheet); NoteSheets(tmp->mAdoptedStyleSheets);
}
tmp->EnumerateUniqueAdoptedStyleSheetsBackToFront(NoteSheetIfApplicable);
for (auto iter = tmp->mIdentifierMap.ConstIter(); !iter.Done(); iter.Next()) { for (auto iter = tmp->mIdentifierMap.ConstIter(); !iter.Done(); iter.Next()) {
iter.Get()->Traverse(&cb); iter.Get()->Traverse(&cb);

View File

@ -221,33 +221,15 @@ class DocumentOrShadowRoot {
nsIContent* Retarget(nsIContent* aContent) const; nsIContent* Retarget(nsIContent* aContent) const;
void SetAdoptedStyleSheets(
const Sequence<OwningNonNull<StyleSheet>>& aAdoptedStyleSheets,
ErrorResult& aRv);
// This is needed because ServoStyleSet / ServoAuthorData don't deal with
// duplicate stylesheets (and it's unclear we'd want to support that as it'd
// be a bunch of duplicate work), while adopted stylesheets do need to deal
// with them.
template <typename Callback>
void EnumerateUniqueAdoptedStyleSheetsBackToFront(Callback aCallback) {
AdoptedStyleSheetSet set(mAdoptedStyleSheets.Length());
for (StyleSheet* sheet : Reversed(mAdoptedStyleSheets)) {
if (MOZ_UNLIKELY(!set.EnsureInserted(sheet))) {
continue;
}
aCallback(*sheet);
}
}
protected: protected:
using AdoptedStyleSheetSet = nsTHashtable<nsPtrHashKey<const StyleSheet>>;
void RemoveSheetFromStylesIfApplicable(StyleSheet&);
void ClearAdoptedStyleSheets();
// Returns the reference to the sheet, if found in mStyleSheets. // Returns the reference to the sheet, if found in mStyleSheets.
already_AddRefed<StyleSheet> RemoveSheet(StyleSheet& aSheet); already_AddRefed<StyleSheet> RemoveSheet(StyleSheet& aSheet);
void InsertSheetAt(size_t aIndex, StyleSheet& aSheet); void InsertSheetAt(size_t aIndex, StyleSheet& aSheet);
void InsertAdoptedSheetAt(size_t aIndex, StyleSheet& aSheet);
void EnsureAdoptedSheetsAreValid(
const Sequence<OwningNonNull<StyleSheet>>& aAdoptedStyleSheets,
ErrorResult& aRv);
void AddSizeOfExcludingThis(nsWindowSizes&) const; void AddSizeOfExcludingThis(nsWindowSizes&) const;
void AddSizeOfOwnedSheetArrayExcludingThis( void AddSizeOfOwnedSheetArrayExcludingThis(

View File

@ -376,17 +376,11 @@ void ShadowRoot::InsertSheetAt(size_t aIndex, StyleSheet& aSheet) {
} }
} }
StyleSheet* FirstApplicableAdoptedStyleSheet( void ShadowRoot::InsertAdoptedSheetAt(size_t aIndex, StyleSheet& aSheet) {
const nsTArray<RefPtr<StyleSheet>>& aList) { DocumentOrShadowRoot::InsertAdoptedSheetAt(aIndex, aSheet);
size_t i = 0; if (aSheet.IsApplicable()) {
for (StyleSheet* sheet : aList) { InsertSheetIntoAuthorData(aIndex, aSheet, mAdoptedStyleSheets);
// Deal with duplicate sheets by only considering the last one.
if (sheet->IsApplicable() && MOZ_LIKELY(aList.LastIndexOf(sheet) == i)) {
return sheet;
}
i++;
} }
return nullptr;
} }
void ShadowRoot::InsertSheetIntoAuthorData( void ShadowRoot::InsertSheetIntoAuthorData(
@ -394,7 +388,6 @@ void ShadowRoot::InsertSheetIntoAuthorData(
const nsTArray<RefPtr<StyleSheet>>& aList) { const nsTArray<RefPtr<StyleSheet>>& aList) {
MOZ_ASSERT(aSheet.IsApplicable()); MOZ_ASSERT(aSheet.IsApplicable());
MOZ_ASSERT(aList[aIndex] == &aSheet); MOZ_ASSERT(aList[aIndex] == &aSheet);
MOZ_ASSERT(aList.LastIndexOf(&aSheet) == aIndex);
MOZ_ASSERT(&aList == &mAdoptedStyleSheets || &aList == &mStyleSheets); MOZ_ASSERT(&aList == &mAdoptedStyleSheets || &aList == &mStyleSheets);
if (!mServoStyles) { if (!mServoStyles) {
@ -405,38 +398,25 @@ void ShadowRoot::InsertSheetIntoAuthorData(
mStyleRuleMap->SheetAdded(aSheet); mStyleRuleMap->SheetAdded(aSheet);
} }
auto changedOnExit =
mozilla::MakeScopeExit([&] { ApplicableRulesChanged(); });
for (size_t i = aIndex + 1; i < aList.Length(); ++i) { for (size_t i = aIndex + 1; i < aList.Length(); ++i) {
StyleSheet* beforeSheet = aList.ElementAt(i); StyleSheet* beforeSheet = aList.ElementAt(i);
if (!beforeSheet->IsApplicable()) { if (!beforeSheet->IsApplicable()) {
continue; continue;
} }
// If this is a duplicate adopted stylesheet that is not in the right
// position (the last one) then we skip over it. Otherwise we're done.
if (&aList == &mAdoptedStyleSheets &&
MOZ_UNLIKELY(aList.LastIndexOf(beforeSheet) != i)) {
continue;
}
Servo_AuthorStyles_InsertStyleSheetBefore(mServoStyles.get(), &aSheet, Servo_AuthorStyles_InsertStyleSheetBefore(mServoStyles.get(), &aSheet,
beforeSheet); beforeSheet);
ApplicableRulesChanged();
return; return;
} }
if (mAdoptedStyleSheets.IsEmpty() || &aList == &mAdoptedStyleSheets) { if (mAdoptedStyleSheets.IsEmpty() || &aList == &mAdoptedStyleSheets) {
Servo_AuthorStyles_AppendStyleSheet(mServoStyles.get(), &aSheet); Servo_AuthorStyles_AppendStyleSheet(mServoStyles.get(), &aSheet);
return;
}
if (auto* before = FirstApplicableAdoptedStyleSheet(mAdoptedStyleSheets)) {
Servo_AuthorStyles_InsertStyleSheetBefore(mServoStyles.get(), &aSheet,
before);
} else { } else {
Servo_AuthorStyles_AppendStyleSheet(mServoStyles.get(), &aSheet); Servo_AuthorStyles_InsertStyleSheetBefore(mServoStyles.get(), &aSheet,
mAdoptedStyleSheets.ElementAt(0));
} }
ApplicableRulesChanged();
} }
// FIXME(emilio): This needs to notify document observers and such, // FIXME(emilio): This needs to notify document observers and such,
@ -466,22 +446,29 @@ void ShadowRoot::StyleSheetApplicableStateChanged(StyleSheet& aSheet) {
} }
} }
void ShadowRoot::RemoveSheetFromStyles(StyleSheet& aSheet) { void ShadowRoot::ClearAdoptedStyleSheets() {
MOZ_ASSERT(aSheet.IsApplicable()); for (const RefPtr<StyleSheet>& sheet : mAdoptedStyleSheets) {
MOZ_ASSERT(mServoStyles); RemoveSheetFromStyles(*sheet);
if (mStyleRuleMap) { sheet->RemoveAdopter(*this);
mStyleRuleMap->SheetRemoved(aSheet); }
mAdoptedStyleSheets.Clear();
}
void ShadowRoot::RemoveSheetFromStyles(StyleSheet& aSheet) {
if (aSheet.IsApplicable()) {
MOZ_ASSERT(mServoStyles);
if (mStyleRuleMap) {
mStyleRuleMap->SheetRemoved(aSheet);
}
Servo_AuthorStyles_RemoveStyleSheet(mServoStyles.get(), &aSheet);
ApplicableRulesChanged();
} }
Servo_AuthorStyles_RemoveStyleSheet(mServoStyles.get(), &aSheet);
ApplicableRulesChanged();
} }
void ShadowRoot::RemoveSheet(StyleSheet& aSheet) { void ShadowRoot::RemoveSheet(StyleSheet& aSheet) {
RefPtr<StyleSheet> sheet = DocumentOrShadowRoot::RemoveSheet(aSheet); RefPtr<StyleSheet> sheet = DocumentOrShadowRoot::RemoveSheet(aSheet);
MOZ_ASSERT(sheet); MOZ_ASSERT(sheet);
if (sheet->IsApplicable()) { RemoveSheetFromStyles(*sheet);
RemoveSheetFromStyles(*sheet);
}
} }
void ShadowRoot::AddToIdTable(Element* aElement, nsAtom* aId) { void ShadowRoot::AddToIdTable(Element* aElement, nsAtom* aId) {
@ -727,3 +714,29 @@ nsresult ShadowRoot::Clone(dom::NodeInfo* aNodeInfo, nsINode** aResult) const {
*aResult = nullptr; *aResult = nullptr;
return NS_ERROR_DOM_NOT_SUPPORTED_ERR; return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
} }
// https://wicg.github.io/construct-stylesheets/#dom-documentorshadowroot-adoptedstylesheets
void ShadowRoot::SetAdoptedStyleSheets(
const Sequence<OwningNonNull<StyleSheet>>& aAdoptedStyleSheets,
ErrorResult& aRv) {
// Step 1 is a variable declaration
// 2.1 Check if all sheets are constructed, else throw NotAllowedError
// 2.2 Check if all sheets' constructor documents match the
// DocumentOrShadowRoot's node document, else throw NotAlloweError
EnsureAdoptedSheetsAreValid(aAdoptedStyleSheets, aRv);
if (aRv.Failed()) {
return;
}
// 3. Set the adopted style sheets to the new sheets
// TODO(nordzilla): There are optimizations that can be made here
// in the case of only appending new sheets.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1611236
ClearAdoptedStyleSheets();
mAdoptedStyleSheets.SetCapacity(aAdoptedStyleSheets.Length());
for (const OwningNonNull<StyleSheet>& sheet : aAdoptedStyleSheets) {
sheet->AddAdopter(*this);
AppendAdoptedStyleSheet(*sheet);
}
}

View File

@ -41,8 +41,6 @@ class HTMLInputElement;
class ShadowRoot final : public DocumentFragment, class ShadowRoot final : public DocumentFragment,
public DocumentOrShadowRoot, public DocumentOrShadowRoot,
public nsIRadioGroupContainer { public nsIRadioGroupContainer {
friend class DocumentOrShadowRoot;
public: public:
NS_IMPL_FROMNODE_HELPER(ShadowRoot, IsShadowRoot()); NS_IMPL_FROMNODE_HELPER(ShadowRoot, IsShadowRoot());
@ -88,6 +86,7 @@ class ShadowRoot final : public DocumentFragment,
*/ */
void CloneInternalDataFrom(ShadowRoot* aOther); void CloneInternalDataFrom(ShadowRoot* aOther);
void InsertSheetAt(size_t aIndex, StyleSheet&); void InsertSheetAt(size_t aIndex, StyleSheet&);
void InsertAdoptedSheetAt(size_t aIndex, StyleSheet&);
// Calls UnbindFromTree for each of our kids, and also flags us as no longer // Calls UnbindFromTree for each of our kids, and also flags us as no longer
// being connected. // being connected.
@ -111,6 +110,10 @@ class ShadowRoot final : public DocumentFragment,
InsertSheetAt(SheetCount(), aSheet); InsertSheetAt(SheetCount(), aSheet);
} }
void AppendAdoptedStyleSheet(StyleSheet& aSheet) {
InsertAdoptedSheetAt(AdoptedSheetCount(), aSheet);
}
/** /**
* Represents the insertion point in a slot for a given node. * Represents the insertion point in a slot for a given node.
*/ */
@ -253,6 +256,12 @@ class ShadowRoot final : public DocumentFragment,
return DocumentOrShadowRoot::SetValueMissingState(aName, aValue); return DocumentOrShadowRoot::SetValueMissingState(aName, aValue);
} }
void SetAdoptedStyleSheets(
const Sequence<OwningNonNull<StyleSheet>>& aAdoptedStyleSheets,
ErrorResult& aRv);
void ClearAdoptedStyleSheets();
protected: protected:
// FIXME(emilio): This will need to become more fine-grained. // FIXME(emilio): This will need to become more fine-grained.
void ApplicableRulesChanged(); void ApplicableRulesChanged();

View File

@ -1477,13 +1477,13 @@ void PresShell::UpdatePreferenceStyles() {
// it to be modifiable from devtools and similar, see bugs 1239336 and // it to be modifiable from devtools and similar, see bugs 1239336 and
// 1436782. I think it conceptually should be a user sheet, and could be // 1436782. I think it conceptually should be a user sheet, and could be
// without too much trouble I'd think. // without too much trouble I'd think.
StyleSet()->AppendStyleSheet(*newPrefSheet); StyleSet()->AppendStyleSheet(StyleOrigin::UserAgent, newPrefSheet);
mPrefStyleSheet = newPrefSheet; mPrefStyleSheet = newPrefSheet;
} }
void PresShell::RemovePreferenceStyles() { void PresShell::RemovePreferenceStyles() {
if (mPrefStyleSheet) { if (mPrefStyleSheet) {
StyleSet()->RemoveStyleSheet(*mPrefStyleSheet); StyleSet()->RemoveStyleSheet(StyleOrigin::UserAgent, mPrefStyleSheet);
mPrefStyleSheet = nullptr; mPrefStyleSheet = nullptr;
} }
} }
@ -1514,10 +1514,10 @@ void PresShell::AddUserSheet(StyleSheet* aSheet) {
} }
if (index == static_cast<size_t>(StyleSet()->SheetCount(StyleOrigin::User))) { if (index == static_cast<size_t>(StyleSet()->SheetCount(StyleOrigin::User))) {
StyleSet()->AppendStyleSheet(*aSheet); StyleSet()->AppendStyleSheet(StyleOrigin::User, aSheet);
} else { } else {
StyleSheet* ref = StyleSet()->SheetAt(StyleOrigin::User, index); StyleSheet* ref = StyleSet()->SheetAt(StyleOrigin::User, index);
StyleSet()->InsertStyleSheetBefore(*aSheet, *ref); StyleSet()->InsertStyleSheetBefore(StyleOrigin::User, aSheet, ref);
} }
mDocument->ApplicableStylesChanged(); mDocument->ApplicableStylesChanged();
@ -1526,7 +1526,7 @@ void PresShell::AddUserSheet(StyleSheet* aSheet) {
void PresShell::AddAgentSheet(StyleSheet* aSheet) { void PresShell::AddAgentSheet(StyleSheet* aSheet) {
// Make sure this does what nsDocumentViewer::CreateStyleSet does // Make sure this does what nsDocumentViewer::CreateStyleSet does
// wrt ordering. // wrt ordering.
StyleSet()->AppendStyleSheet(*aSheet); StyleSet()->AppendStyleSheet(StyleOrigin::UserAgent, aSheet);
mDocument->ApplicableStylesChanged(); mDocument->ApplicableStylesChanged();
} }
@ -1535,14 +1535,20 @@ void PresShell::AddAuthorSheet(StyleSheet* aSheet) {
// ones added with the StyleSheetService. // ones added with the StyleSheetService.
StyleSheet* firstAuthorSheet = mDocument->GetFirstAdditionalAuthorSheet(); StyleSheet* firstAuthorSheet = mDocument->GetFirstAdditionalAuthorSheet();
if (firstAuthorSheet) { if (firstAuthorSheet) {
StyleSet()->InsertStyleSheetBefore(*aSheet, *firstAuthorSheet); StyleSet()->InsertStyleSheetBefore(StyleOrigin::Author, aSheet,
firstAuthorSheet);
} else { } else {
StyleSet()->AppendStyleSheet(*aSheet); StyleSet()->AppendStyleSheet(StyleOrigin::Author, aSheet);
} }
mDocument->ApplicableStylesChanged(); mDocument->ApplicableStylesChanged();
} }
void PresShell::RemoveSheet(StyleOrigin aOrigin, StyleSheet* aSheet) {
StyleSet()->RemoveStyleSheet(aOrigin, aSheet);
mDocument->ApplicableStylesChanged();
}
NS_IMETHODIMP NS_IMETHODIMP
PresShell::SetDisplaySelection(int16_t aToggle) { PresShell::SetDisplaySelection(int16_t aToggle) {
RefPtr<nsFrameSelection> frameSelection = mSelection; RefPtr<nsFrameSelection> frameSelection = mSelection;
@ -8871,12 +8877,12 @@ bool PresShell::IsDisplayportSuppressed() {
} }
nsresult PresShell::AddOverrideStyleSheet(StyleSheet* aSheet) { nsresult PresShell::AddOverrideStyleSheet(StyleSheet* aSheet) {
StyleSet()->AppendStyleSheet(*aSheet); StyleSet()->AppendStyleSheet(aSheet->GetOrigin(), aSheet);
return NS_OK; return NS_OK;
} }
nsresult PresShell::RemoveOverrideStyleSheet(StyleSheet* aSheet) { nsresult PresShell::RemoveOverrideStyleSheet(StyleSheet* aSheet) {
StyleSet()->RemoveStyleSheet(*aSheet); StyleSet()->RemoveStyleSheet(aSheet->GetOrigin(), aSheet);
return NS_OK; return NS_OK;
} }
@ -10920,6 +10926,21 @@ void PresShell::SyncWindowProperties(nsView* aView) {
} }
} }
static StyleOrigin ToOrigin(uint32_t aServiceSheetType) {
switch (aServiceSheetType) {
case nsIStyleSheetService::AGENT_SHEET:
return StyleOrigin::UserAgent;
break;
case nsIStyleSheetService::USER_SHEET:
return StyleOrigin::User;
break;
default:
MOZ_FALLTHROUGH_ASSERT("unexpected aSheetType value");
case nsIStyleSheetService::AUTHOR_SHEET:
return StyleOrigin::Author;
}
}
nsresult PresShell::HasRuleProcessorUsedByMultipleStyleSets(uint32_t aSheetType, nsresult PresShell::HasRuleProcessorUsedByMultipleStyleSets(uint32_t aSheetType,
bool* aRetVal) { bool* aRetVal) {
*aRetVal = false; *aRetVal = false;
@ -10946,8 +10967,7 @@ void PresShell::NotifyStyleSheetServiceSheetAdded(StyleSheet* aSheet,
void PresShell::NotifyStyleSheetServiceSheetRemoved(StyleSheet* aSheet, void PresShell::NotifyStyleSheetServiceSheetRemoved(StyleSheet* aSheet,
uint32_t aSheetType) { uint32_t aSheetType) {
StyleSet()->RemoveStyleSheet(*aSheet); RemoveSheet(ToOrigin(aSheetType), aSheet);
mDocument->ApplicableStylesChanged();
} }
void PresShell::SetIsUnderHiddenEmbedderElement( void PresShell::SetIsUnderHiddenEmbedderElement(

View File

@ -1826,6 +1826,7 @@ class PresShell final : public nsStubDocumentObserver,
void AddUserSheet(StyleSheet*); void AddUserSheet(StyleSheet*);
void AddAgentSheet(StyleSheet*); void AddAgentSheet(StyleSheet*);
void AddAuthorSheet(StyleSheet*); void AddAuthorSheet(StyleSheet*);
void RemoveSheet(StyleOrigin, StyleSheet*);
void RemovePreferenceStyles(); void RemovePreferenceStyles();
/** /**

View File

@ -90,9 +90,6 @@ void InspectorUtils::GetAllStyleSheets(GlobalObject& aGlobalObject,
for (size_t i = 0; i < aDocument.SheetCount(); i++) { for (size_t i = 0; i < aDocument.SheetCount(); i++) {
aResult.AppendElement(aDocument.SheetAt(i)); aResult.AppendElement(aDocument.SheetAt(i));
} }
// FIXME(emilio, bug 1617948): This doesn't deal with adopted stylesheets, and
// it should. It should also handle duplicates correctly when it does.
} }
bool InspectorUtils::IsIgnorableWhitespace(CharacterData& aDataNode) { bool InspectorUtils::IsIgnorableWhitespace(CharacterData& aDataNode) {

View File

@ -134,7 +134,7 @@ void ServoStyleSet::ShellDetachedFromDocument() {
// Remove all our stylesheets... // Remove all our stylesheets...
for (auto origin : kOrigins) { for (auto origin : kOrigins) {
for (size_t count = SheetCount(origin); count--;) { for (size_t count = SheetCount(origin); count--;) {
RemoveStyleSheet(*SheetAt(origin, count)); RemoveStyleSheet(origin, SheetAt(origin, count));
} }
} }
@ -563,60 +563,66 @@ already_AddRefed<ComputedStyle> ServoStyleSet::ResolveXULTreePseudoStyle(
#endif #endif
// manage the set of style sheets in the style set // manage the set of style sheets in the style set
void ServoStyleSet::AppendStyleSheet(StyleSheet& aSheet) { void ServoStyleSet::AppendStyleSheet(StyleOrigin aOrigin, StyleSheet* aSheet) {
MOZ_ASSERT(aSheet.IsApplicable()); MOZ_ASSERT(aSheet);
MOZ_ASSERT(aSheet.RawContents(), MOZ_ASSERT(aSheet->IsApplicable());
MOZ_ASSERT(aSheet->RawContents(),
"Raw sheet should be in place before insertion."); "Raw sheet should be in place before insertion.");
aSheet.AddStyleSet(this); aSheet->AddStyleSet(this);
// Maintain a mirrored list of sheets on the servo side. // Maintain a mirrored list of sheets on the servo side.
// Servo will remove aSheet from its original position as part of the call // Servo will remove aSheet from its original position as part of the call
// to Servo_StyleSet_AppendStyleSheet. // to Servo_StyleSet_AppendStyleSheet.
Servo_StyleSet_AppendStyleSheet(mRawSet.get(), &aSheet); Servo_StyleSet_AppendStyleSheet(mRawSet.get(), aSheet);
SetStylistStyleSheetsDirty(); SetStylistStyleSheetsDirty();
if (mStyleRuleMap) { if (mStyleRuleMap) {
mStyleRuleMap->SheetAdded(aSheet); mStyleRuleMap->SheetAdded(*aSheet);
} }
} }
void ServoStyleSet::RemoveStyleSheet(StyleSheet& aSheet) { void ServoStyleSet::RemoveStyleSheet(StyleOrigin aOrigin, StyleSheet* aSheet) {
aSheet.DropStyleSet(this); MOZ_ASSERT(aSheet);
aSheet->DropStyleSet(this);
// Maintain a mirrored list of sheets on the servo side. // Maintain a mirrored list of sheets on the servo side.
Servo_StyleSet_RemoveStyleSheet(mRawSet.get(), &aSheet); Servo_StyleSet_RemoveStyleSheet(mRawSet.get(), aSheet);
SetStylistStyleSheetsDirty(); SetStylistStyleSheetsDirty();
if (mStyleRuleMap) { if (mStyleRuleMap) {
mStyleRuleMap->SheetRemoved(aSheet); mStyleRuleMap->SheetRemoved(*aSheet);
} }
} }
void ServoStyleSet::InsertStyleSheetBefore(StyleSheet& aNewSheet, void ServoStyleSet::RemoveDocStyleSheet(StyleSheet* aSheet) {
StyleSheet& aReferenceSheet) { RemoveStyleSheet(Origin::Author, aSheet);
MOZ_ASSERT(aNewSheet.IsApplicable()); }
MOZ_ASSERT(aReferenceSheet.IsApplicable());
MOZ_ASSERT(&aNewSheet != &aReferenceSheet, void ServoStyleSet::InsertStyleSheetBefore(Origin aOrigin,
"Can't place sheet before itself."); StyleSheet* aNewSheet,
MOZ_ASSERT(aNewSheet.GetOrigin() == aReferenceSheet.GetOrigin(), StyleSheet* aReferenceSheet) {
"Sheets should be in the same origin"); MOZ_ASSERT(aNewSheet);
MOZ_ASSERT(aNewSheet.RawContents(), MOZ_ASSERT(aReferenceSheet);
MOZ_ASSERT(aNewSheet->IsApplicable());
MOZ_ASSERT(aNewSheet != aReferenceSheet, "Can't place sheet before itself.");
MOZ_ASSERT(aNewSheet->RawContents(),
"Raw sheet should be in place before insertion."); "Raw sheet should be in place before insertion.");
MOZ_ASSERT(aReferenceSheet.RawContents(), MOZ_ASSERT(aReferenceSheet->RawContents(),
"Reference sheet should have a raw sheet."); "Reference sheet should have a raw sheet.");
// Servo will remove aNewSheet from its original position as part of the // Servo will remove aNewSheet from its original position as part of the
// call to Servo_StyleSet_InsertStyleSheetBefore. // call to Servo_StyleSet_InsertStyleSheetBefore.
aNewSheet.AddStyleSet(this); aNewSheet->AddStyleSet(this);
// Maintain a mirrored list of sheets on the servo side. // Maintain a mirrored list of sheets on the servo side.
Servo_StyleSet_InsertStyleSheetBefore(mRawSet.get(), &aNewSheet, Servo_StyleSet_InsertStyleSheetBefore(mRawSet.get(), aNewSheet,
&aReferenceSheet); aReferenceSheet);
SetStylistStyleSheetsDirty(); SetStylistStyleSheetsDirty();
if (mStyleRuleMap) { if (mStyleRuleMap) {
mStyleRuleMap->SheetAdded(aNewSheet); mStyleRuleMap->SheetAdded(*aNewSheet);
} }
} }
@ -638,29 +644,31 @@ void ServoStyleSet::AppendAllNonDocumentAuthorSheets(
}); });
} }
void ServoStyleSet::AddDocStyleSheet(StyleSheet& aSheet) { void ServoStyleSet::AddDocStyleSheet(StyleSheet* aSheet) {
MOZ_ASSERT(aSheet.IsApplicable()); MOZ_ASSERT(aSheet->IsApplicable());
MOZ_ASSERT(aSheet.RawContents(), MOZ_ASSERT(aSheet->RawContents(),
"Raw sheet should be in place by this point."); "Raw sheet should be in place by this point.");
size_t index = mDocument->FindDocStyleSheetInsertionPoint(aSheet); RefPtr<StyleSheet> strong(aSheet);
aSheet.AddStyleSet(this);
size_t index = mDocument->FindDocStyleSheetInsertionPoint(*aSheet);
aSheet->AddStyleSet(this);
if (index < SheetCount(Origin::Author)) { if (index < SheetCount(Origin::Author)) {
// This case is insert before. // This case is insert before.
StyleSheet* beforeSheet = SheetAt(Origin::Author, index); StyleSheet* beforeSheet = SheetAt(Origin::Author, index);
// Maintain a mirrored list of sheets on the servo side. // Maintain a mirrored list of sheets on the servo side.
Servo_StyleSet_InsertStyleSheetBefore(mRawSet.get(), &aSheet, beforeSheet); Servo_StyleSet_InsertStyleSheetBefore(mRawSet.get(), aSheet, beforeSheet);
SetStylistStyleSheetsDirty(); SetStylistStyleSheetsDirty();
} else { } else {
// Maintain a mirrored list of sheets on the servo side. // Maintain a mirrored list of sheets on the servo side.
Servo_StyleSet_AppendStyleSheet(mRawSet.get(), &aSheet); Servo_StyleSet_AppendStyleSheet(mRawSet.get(), aSheet);
SetStylistStyleSheetsDirty(); SetStylistStyleSheetsDirty();
} }
if (mStyleRuleMap) { if (mStyleRuleMap) {
mStyleRuleMap->SheetAdded(aSheet); mStyleRuleMap->SheetAdded(*aSheet);
} }
} }

View File

@ -231,16 +231,19 @@ class ServoStyleSet {
ComputedStyle* aParentStyle, const AtomArray& aInputWord); ComputedStyle* aParentStyle, const AtomArray& aInputWord);
#endif #endif
// manage the set of style sheets in the style set
void AppendStyleSheet(Origin, StyleSheet*);
void RemoveStyleSheet(Origin, StyleSheet*);
void InsertStyleSheetBefore(Origin, StyleSheet*, StyleSheet* aReferenceSheet);
size_t SheetCount(Origin) const; size_t SheetCount(Origin) const;
StyleSheet* SheetAt(Origin, size_t aIndex) const; StyleSheet* SheetAt(Origin, size_t aIndex) const;
void AppendAllNonDocumentAuthorSheets(nsTArray<StyleSheet*>& aArray) const; void AppendAllNonDocumentAuthorSheets(nsTArray<StyleSheet*>& aArray) const;
// Manage the set of style sheets in the style set void RemoveDocStyleSheet(StyleSheet* aSheet);
void AppendStyleSheet(StyleSheet&);
void InsertStyleSheetBefore(StyleSheet&, StyleSheet& aReferenceSheet); void AddDocStyleSheet(StyleSheet* aSheet);
void RemoveStyleSheet(StyleSheet&);
void AddDocStyleSheet(StyleSheet&);
/** /**
* Performs a Servo traversal to compute style for all dirty nodes in the * Performs a Servo traversal to compute style for all dirty nodes in the

View File

@ -394,15 +394,14 @@ class StyleSheet final : public nsICSSLoaderObserver, public nsWrapperCache {
bool IsConstructed() const { return !!mConstructorDocument; } bool IsConstructed() const { return !!mConstructorDocument; }
// Ture if the sheet's constructor document matches the given document // Ture if the sheet's constructor document matches the given document
bool ConstructorDocumentMatches(dom::Document& aDocument) const { bool ConstructorDocumentMatches(dom::Document* aDocument) const {
return mConstructorDocument == &aDocument; return mConstructorDocument == aDocument;
} }
// Add a document or shadow root to the list of adopters. // Add a document or shadow root to the list of adopters.
// Adopters will be notified when styles are changed. // Adopters will be notified when styles are changed.
void AddAdopter(dom::DocumentOrShadowRoot& aAdopter) { void AddAdopter(dom::DocumentOrShadowRoot& aAdopter) {
MOZ_ASSERT(IsConstructed()); MOZ_ASSERT(IsConstructed());
MOZ_ASSERT(!mAdopters.Contains(&aAdopter));
mAdopters.AppendElement(&aAdopter); mAdopters.AppendElement(&aAdopter);
} }

View File

@ -294,9 +294,7 @@ where
// Removing sheets makes us tear down the whole cascade and invalidation // Removing sheets makes us tear down the whole cascade and invalidation
// data, but only if the sheet has been involved in at least one flush. // data, but only if the sheet has been involved in at least one flush.
// Checking whether the sheet has been committed allows us to avoid // Checking whether the sheet has been committed allows us to avoid
// rebuilding the world when sites quickly append and remove a // rebuilding the world when sites quickly append and remove a stylesheet.
// stylesheet.
//
// See bug 1434756. // See bug 1434756.
if sheet.committed { if sheet.committed {
self.set_data_validity_at_least(DataValidity::FullyInvalid); self.set_data_validity_at_least(DataValidity::FullyInvalid);

View File

@ -1,2 +0,0 @@
[CSSStyleSheet-constructable-disabled-regular-sheet-insertion.html]
prefs: [layout.css.constructable-stylesheets.enabled:true]

View File

@ -1,2 +0,0 @@
[CSSStyleSheet-constructable-duplicate.html]
prefs: [layout.css.constructable-stylesheets.enabled:true]

View File

@ -1,22 +0,0 @@
<!doctype html>
<title>Shouldn't crash / assert when inserting a stylesheet after there are disabled constructable sheets</title>
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
<link rel="help" href="https://wicg.github.io/construct-stylesheets/">
<script src = '/resources/testharness.js'></script>
<script src = '/resources/testharnessreport.js'></script>
<div id="host"></div>
<script>
test(function() {
let sheet = new CSSStyleSheet({ disabled: true });
sheet.replaceSync("div { color: red }");
let root = document.getElementById("host").attachShadow({ mode: "open" });
root.adoptedStyleSheets = [sheet];
let style = document.createElement("style");
root.innerHTML = `
<style>div { color: green }</style>
<div>Should be green</div>
`;
assert_equals(getComputedStyle(root.querySelector("div")).color, "rgb(0, 128, 0)", "Should insert the sheet at the right position and not crash");
});
</script>

View File

@ -1,20 +0,0 @@
<!doctype html>
<title>Cascade order of a stylesheet for duplicate sheets.</title>
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
<link rel="help" href="https://wicg.github.io/construct-stylesheets/">
<script src = '/resources/testharness.js'></script>
<script src = '/resources/testharnessreport.js'></script>
<div></div>
<script>
test(function() {
let sheets = [];
for (let i = 0; i < 2; ++i) {
sheets.push(new CSSStyleSheet());
sheets[i].replaceSync("div { z-index: " + i + " }");
}
document.adoptedStyleSheets = [sheets[1], sheets[0], sheets[1]];
assert_equals(getComputedStyle(document.querySelector("div")).zIndex, "1", "duplicate stylesheet should take right position in the cascade");
});
</script>