/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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/. */
void DocumentOrShadowRoot::RemoveStyleSheet(StyleSheet& aSheet) { auto index = mStyleSheets.IndexOf(&aSheet); if (index == mStyleSheets.NoIndex) { // We should only hit this case if we are unlinking // in which case mStyleSheets should be cleared.
MOZ_ASSERT(mKind != Kind::Document ||
AsNode().AsDocument()->InUnlinkOrDeletion());
MOZ_ASSERT(mStyleSheets.IsEmpty()); return;
}
RefPtr<StyleSheet> sheet = std::move(mStyleSheets[index]);
mStyleSheets.RemoveElementAt(index);
RemoveSheetFromStylesIfApplicable(*sheet);
sheet->ClearAssociatedDocumentOrShadowRoot();
AsNode().OwnerDoc()->PostStyleSheetRemovedEvent(aSheet);
}
// https://drafts.csswg.org/cssom/#dom-documentorshadowroot-adoptedstylesheets void DocumentOrShadowRoot::OnSetAdoptedStyleSheets(StyleSheet& aSheet,
uint32_t aIndex,
ErrorResult& aRv) {
Document& doc = *AsNode().OwnerDoc(); // 1. If value’s constructed flag is not set, or its constructor document is // not equal to this DocumentOrShadowRoot's node document, throw a // "NotAllowedError" DOMException.
if (!StaticPrefs::
dom_webcomponents_lift_adoptedstylesheets_restriction_enabled()) { if (!aSheet.IsConstructed()) { return aRv.ThrowNotAllowedError( "Adopted style sheet must be created through the Constructable " "StyleSheets API");
}
if (!aSheet.ConstructorDocumentMatches(doc)) { return aRv.ThrowNotAllowedError( "Adopted style sheet's constructor document must match the " "document or shadow root's node document");
}
}
auto existingIndex = mAdoptedStyleSheets.LastIndexOf(&aSheet); // Ensure it's in the backing array at the right index.
mAdoptedStyleSheets.InsertElementAt(aIndex, &aSheet); if (existingIndex == mAdoptedStyleSheets.NoIndex) { // common case: we're not already adopting this sheet.
aSheet.AddAdopter(*this);
} elseif (existingIndex < aIndex) { // We're inserting an already-adopted stylesheet in a later position, so // this one should take precedent and we should remove the old one.
RemoveSheetFromStylesIfApplicable(aSheet);
} else { // The sheet is already at a position later than or equal to the current // one, and is already adopted by us, we have nothing to do here other than // adding to the current list. return;
}
if (aSheet.IsApplicable()) { if (mKind == Kind::Document) {
doc.AddStyleSheetToStyleSets(aSheet);
} else {
shadow->InsertSheetIntoAuthorData(aIndex, aSheet, mAdoptedStyleSheets);
}
}
}
void DocumentOrShadowRoot::OnDeleteAdoptedStyleSheets(StyleSheet& aSheet,
uint32_t aIndex,
ErrorResult&) {
MOZ_ASSERT(mAdoptedStyleSheets.ElementAt(aIndex) == &aSheet);
mAdoptedStyleSheets.RemoveElementAt(aIndex); auto existingIndex = mAdoptedStyleSheets.LastIndexOf(&aSheet); if (existingIndex != mAdoptedStyleSheets.NoIndex && existingIndex >= aIndex) { // The sheet is still adopted by us and was already later from the one we're // removing, so nothing to do. return;
}
RemoveSheetFromStylesIfApplicable(aSheet); if (existingIndex == mAdoptedStyleSheets.NoIndex) { // The sheet is no longer adopted by us.
aSheet.RemoveAdopter(*this);
} elseif (aSheet.IsApplicable()) { // We need to re-insert the sheet at the right (pre-existing) index.
nsINode& node = AsNode(); if (mKind == Kind::Document) {
node.AsDocument()->AddStyleSheetToStyleSets(aSheet);
} else {
ShadowRoot::FromNode(node)->InsertSheetIntoAuthorData(
existingIndex, aSheet, mAdoptedStyleSheets);
}
}
}
// We don't need to care about the reflector (AdoptedStyleSheetsHelpers and // so) because this is only used for static documents. for (const StyleSheet* sheet : aSource.mAdoptedStyleSheets) {
RefPtr<StyleSheet> clone = clonedSheetMap->LookupOrInsertWith(
sheet, [&] { return sheet->CloneAdoptedSheet(ownerDoc); });
MOZ_ASSERT(clone);
MOZ_DIAGNOSTIC_ASSERT(clone->ConstructorDocumentMatches(ownerDoc));
ErrorResult rv;
OnSetAdoptedStyleSheets(*clone, mAdoptedStyleSheets.Length(), rv);
MOZ_ASSERT(!rv.Failed());
}
}
Element* DocumentOrShadowRoot::GetFullscreenElement() const { if (!AsNode().IsInComposedDoc()) { return nullptr;
}
Element* element = AsNode().OwnerDoc()->GetUnretargetedFullscreenElement();
NS_ASSERTION(!element || element->State().HasState(ElementState::FULLSCREEN), "Fullscreen element should have fullscreen styles applied"); return Element::FromNodeOrNull(Retarget(element));
}
namespace {
using FrameForPointOption = nsLayoutUtils::FrameForPointOption; using FrameForPointOptions = nsLayoutUtils::FrameForPointOptions;
// Whether only one node or multiple nodes is requested. enumclass Multiple {
No,
Yes,
};
// Whether we should flush layout or not. enumclass FlushLayout {
No,
Yes,
};
// Make sure the layout information we get is up-to-date, and // ensure we get a root frame (for everything but XUL) if (aShouldFlushLayout == FlushLayout::Yes) {
doc->FlushPendingNotifications(FlushType::Layout);
}
PresShell* presShell = doc->GetPresShell(); if (!presShell) { return;
}
nsIFrame* rootFrame = presShell->GetRootFrame(); // XUL docs, unlike HTML, have no frame tree until everything's done loading if (!rootFrame) { return; // return null to premature XUL callers as a reminder to wait
}
for (nsIFrame* frame : frames) {
nsINode* node = doc->GetContentInThisDocument(frame); while (node && node->IsInNativeAnonymousSubtree()) {
nsIContent* root = node->GetClosestNativeAnonymousSubtreeRoot();
MOZ_ASSERT(root, "content is connected");
MOZ_ASSERT(root->IsRootOfNativeAnonymousSubtree(), "wat"); if (root == &aRoot.AsNode()) { // If we're in the anonymous subtree root we care about, don't retarget. break;
}
node = root->GetParentOrShadowHostNode();
}
if (!node) { continue;
}
if (returningElements && !node->IsElement()) { // If this helper is called via ElementsFromPoint, we need to make sure // our frame is an element. Otherwise return whatever the top frame is // even if it isn't the top-painted element. // SVG 'text' element's SVGTextFrame doesn't respond to hit-testing, so // if 'content' is a child of such an element then we need to manually // defer to the parent here. if (aMultiple == Multiple::Yes && !frame->IsInSVGTextSubtree()) { continue;
}
void DocumentOrShadowRoot::GetAnimations(
nsTArray<RefPtr<Animation>>& aAnimations) { // As with Element::GetAnimations we initially flush style here. // This should ensure that there are no subsequent changes to the tree // structure while iterating over the children below. if (Document* doc = AsNode().GetComposedDoc()) {
doc->FlushPendingNotifications(
ChangesToFlush(FlushType::Style, false/* flush animations */));
}
int32_t DocumentOrShadowRoot::StyleOrderIndexOfSheet( const StyleSheet& aSheet) const { if (aSheet.IsConstructed()) { // NOTE: constructable sheets can have duplicates, so we need to start // looking from behind.
int32_t index = mAdoptedStyleSheets.LastIndexOf(&aSheet); return (index < 0) ? index : index + SheetCount();
} return mStyleSheets.IndexOf(&aSheet);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.