Bug 1622322 - Improve print performance when sheets are adopted multiple times r=emilio

Differential Revision: https://phabricator.services.mozilla.com/D68116

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Erik Nordin 2020-04-01 20:06:47 +00:00
parent e653609e42
commit ccc51b2ce0
10 changed files with 71 additions and 11 deletions

View File

@ -12024,7 +12024,11 @@ void Document::FlushPendingLinkUpdates() {
already_AddRefed<Document> Document::CreateStaticClone(
nsIDocShell* aCloneContainer) {
MOZ_ASSERT(!mCreatingStaticClone);
MOZ_ASSERT(!GetProperty(nsGkAtoms::adoptedsheetclones));
mCreatingStaticClone = true;
SetProperty(nsGkAtoms::adoptedsheetclones, new AdoptedStyleSheetCloneCache(),
nsINode::DeleteProperty<AdoptedStyleSheetCloneCache>);
// Make document use different container during cloning.
RefPtr<nsDocShell> originalShell = mDocumentContainer.get();
@ -12094,6 +12098,7 @@ already_AddRefed<Document> Document::CreateStaticClone(
clonedDoc->mPreloadReferrerInfo = clonedDoc->mReferrerInfo;
}
}
RemoveProperty(nsGkAtoms::adoptedsheetclones);
mCreatingStaticClone = false;
return clonedDoc.forget();
}

View File

@ -488,6 +488,8 @@ class Document : public nsINode,
public:
typedef dom::ExternalResourceMap::ExternalResourceLoad ExternalResourceLoad;
typedef dom::ReferrerPolicy ReferrerPolicyEnum;
using AdoptedStyleSheetCloneCache =
nsRefPtrHashtable<nsPtrHashKey<const StyleSheet>, StyleSheet>;
// nsINode overrides the new operator for DOM Arena allocation.
// to use the default one, we need to bring it back again
@ -2810,7 +2812,7 @@ class Document : public nsINode,
* Note that static documents are also "loaded as data" (if this method
* returns true, IsLoadedAsData() will also return true).
*/
bool IsStaticDocument() { return mIsStaticDocument; }
bool IsStaticDocument() const { return mIsStaticDocument; }
/**
* Clones the document along with any subdocuments, stylesheet, etc.

View File

@ -199,18 +199,27 @@ void DocumentOrShadowRoot::ClearAdoptedStyleSheets() {
}
void DocumentOrShadowRoot::CloneAdoptedSheetsFrom(
DocumentOrShadowRoot& aSource) {
Document& ownerDoc = *AsNode().OwnerDoc();
const DocumentOrShadowRoot& aSource) {
if (!aSource.AdoptedSheetCount()) {
return;
}
Sequence<OwningNonNull<StyleSheet>> list;
if (!list.SetCapacity(mAdoptedStyleSheets.Length(), fallible)) {
return;
}
// TODO(nordzilla, bug 1621415) We can improve the performance here.
// https://bugzilla.mozilla.org/show_bug.cgi?id=1622322
for (auto& sheet : aSource.mAdoptedStyleSheets) {
DebugOnly<bool> succeeded =
list.AppendElement(sheet->CloneAdoptedSheet(ownerDoc), fallible);
Document& ownerDoc = *AsNode().OwnerDoc();
const Document& sourceDoc = *aSource.AsNode().OwnerDoc();
auto* clonedSheetMap = static_cast<Document::AdoptedStyleSheetCloneCache*>(
sourceDoc.GetProperty(nsGkAtoms::adoptedsheetclones));
MOZ_ASSERT(clonedSheetMap);
for (const StyleSheet* sheet : aSource.mAdoptedStyleSheets) {
RefPtr<StyleSheet> clone = clonedSheetMap->LookupForAdd(sheet).OrInsert(
[&] { return sheet->CloneAdoptedSheet(ownerDoc); });
MOZ_ASSERT(clone);
MOZ_DIAGNOSTIC_ASSERT(clone->ConstructorDocumentMatches(ownerDoc));
DebugOnly<bool> succeeded = list.AppendElement(std::move(clone), fallible);
MOZ_ASSERT(succeeded);
}

View File

@ -249,7 +249,7 @@ class DocumentOrShadowRoot {
* Clone's the argument's adopted style sheets into this.
* This should only be used when cloning a static document for printing.
*/
void CloneAdoptedSheetsFrom(DocumentOrShadowRoot&);
void CloneAdoptedSheetsFrom(const DocumentOrShadowRoot&);
// Returns the reference to the sheet, if found in mStyleSheets.
already_AddRefed<StyleSheet> RemoveSheet(StyleSheet& aSheet);

View File

@ -26,6 +26,8 @@ support-files =
test_document_adopted_styles_ref.html
test_shadow_root_adopted_styles.html
test_shadow_root_adopted_styles_ref.html
test_shared_adopted_styles.html
test_shared_adopted_styles_ref.html
file_bug1018265.xhtml
[test_bug396367-1.html]

View File

@ -438,8 +438,14 @@ async function runTest13() {
requestAnimationFrame(function() { setTimeout(runTest14); } );
}
// Crash test for bug 1615261
// bug 1622322
async function runTest14() {
await compareFiles("test_shared_adopted_styles.html", "test_shared_adopted_styles_ref.html");
requestAnimationFrame(function() { setTimeout(runTest15); } );
}
// Crash test for bug 1615261
async function runTest15() {
frameElts[0].contentDocument.body.innerHTML =
'<style> div { width: 100px; height: 100px; background-image: url("animated.gif"); } </style>' +
'<div>Firefox will crash if you try and print this page</div>';

View File

@ -0,0 +1,19 @@
<!doctype html>
<meta charset="utf-8">
<body>
<div class="target"></div>
<span id="shadowHostA"></span>
<span id="shadowHostB"></span>
</body>
<script>
const sheet = new CSSStyleSheet();
sheet.replaceSync(".target { width: 100px; height: 100px; border-style: solid; border-color: blue; }");
const innerHTMLText = `<div class="target"></div>`
shadowHostA.attachShadow({mode: "open"}).innerHTML = innerHTMLText;
shadowHostB.attachShadow({mode: "open"}).innerHTML = innerHTMLText;
document.adoptedStyleSheets = [sheet];
shadowHostA.shadowRoot.adoptedStyleSheets = [sheet];
shadowHostB.shadowRoot.adoptedStyleSheets = [sheet];
</script>

View File

@ -0,0 +1,16 @@
<!doctype html>
<meta charset="utf-8">
<body>
<div class="target"></div>
<span id="shadowHostA"></span>
<span id="shadowHostB"></span>
<style> .target { width: 100px; height: 100px; border-style: solid; border-color: blue; } </style>
</body>
<script>
const innerHTMLText = `
<div class="target"></div>
<style> .target { width: 100px; height: 100px; border-style: solid; border-color: blue; } </style>
`;
shadowHostA.attachShadow({mode: "open"}).innerHTML = innerHTMLText;
shadowHostB.attachShadow({mode: "open"}).innerHTML = innerHTMLText;
</script>

View File

@ -412,7 +412,7 @@ class StyleSheet final : public nsICSSLoaderObserver, public nsWrapperCache {
}
// Ture if the sheet's constructor document matches the given document
bool ConstructorDocumentMatches(dom::Document& aDocument) const {
bool ConstructorDocumentMatches(const dom::Document& aDocument) const {
return mConstructorDocument == &aDocument;
}

View File

@ -69,6 +69,7 @@ STATIC_ATOMS = [
Atom("activateontab", "activateontab"),
Atom("actuate", "actuate"),
Atom("address", "address"),
Atom("adoptedsheetclones", "adoptedsheetclones"),
Atom("after", "after"),
Atom("align", "align"),
Atom("alink", "alink"),