mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-12 02:31:41 +00:00
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:
parent
e653609e42
commit
ccc51b2ce0
@ -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();
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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]
|
||||
|
@ -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>';
|
||||
|
19
layout/base/tests/chrome/test_shared_adopted_styles.html
Normal file
19
layout/base/tests/chrome/test_shared_adopted_styles.html
Normal 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>
|
16
layout/base/tests/chrome/test_shared_adopted_styles_ref.html
Normal file
16
layout/base/tests/chrome/test_shared_adopted_styles_ref.html
Normal 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>
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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"),
|
||||
|
Loading…
x
Reference in New Issue
Block a user