diff options
Diffstat (limited to 'dom/base/nsDocument.cpp')
-rw-r--r-- | dom/base/nsDocument.cpp | 721 |
1 files changed, 224 insertions, 497 deletions
diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index 144f048eb..1c3e7a421 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -1,5 +1,4 @@ /* -*- 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/. */ @@ -116,7 +115,6 @@ #include "nsBidiUtils.h" -#include "nsIParserService.h" #include "nsContentCreatorFunctions.h" #include "nsIScriptContext.h" @@ -301,9 +299,24 @@ GetHttpChannelHelper(nsIChannel* aChannel, nsIHttpChannel** aHttpChannel) #define NAME_NOT_VALID ((nsSimpleContentList*)1) +nsIdentifierMapEntry::nsIdentifierMapEntry(const nsIdentifierMapEntry::AtomOrString& aKey) + : mKey(aKey) +{} + +nsIdentifierMapEntry::nsIdentifierMapEntry(const nsIdentifierMapEntry::AtomOrString* aKey) + : mKey(aKey ? *aKey : nullptr) +{} + nsIdentifierMapEntry::~nsIdentifierMapEntry() -{ -} +{} + +nsIdentifierMapEntry::nsIdentifierMapEntry(nsIdentifierMapEntry&& aOther) + : mKey(mozilla::Move(aOther.mKey)) + , mIdContentList(mozilla::Move(aOther.mIdContentList)) + , mNameContentList(mozilla::Move(aOther.mNameContentList)) + , mChangeCallbacks(mozilla::Move(aOther.mChangeCallbacks)) + , mImageElement(mozilla::Move(aOther.mImageElement)) +{} void nsIdentifierMapEntry::Traverse(nsCycleCollectionTraversalCallback* aCallback) @@ -327,6 +340,12 @@ nsIdentifierMapEntry::IsEmpty() !mChangeCallbacks && !mImageElement; } +bool +nsIdentifierMapEntry::HasNameElement() const +{ + return mNameContentList && mNameContentList->Length() != 0; +} + Element* nsIdentifierMapEntry::GetIdElement() { @@ -538,7 +557,7 @@ nsIdentifierMapEntry::HasIdElementExposedAsHTMLDocumentProperty() size_t nsIdentifierMapEntry::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const { - return nsStringHashKey::SizeOfExcludingThis(aMallocSizeOf); + return mKey.mString.SizeOfExcludingThisIfUnshared(aMallocSizeOf); } // Helper structs for the content->subdoc map @@ -571,78 +590,6 @@ struct nsRadioGroupStruct bool mGroupSuffersFromValueMissing; }; - -nsDOMStyleSheetList::nsDOMStyleSheetList(nsIDocument *aDocument) -{ - mLength = -1; - // Not reference counted to avoid circular references. - // The document will tell us when its going away. - mDocument = aDocument; - mDocument->AddObserver(this); -} - -nsDOMStyleSheetList::~nsDOMStyleSheetList() -{ - if (mDocument) { - mDocument->RemoveObserver(this); - } -} - -NS_IMPL_ISUPPORTS_INHERITED(nsDOMStyleSheetList, StyleSheetList, - nsIDocumentObserver, - nsIMutationObserver) - -uint32_t -nsDOMStyleSheetList::Length() -{ - if (!mDocument) { - return 0; - } - - // XXX Find the number and then cache it. We'll use the - // observer notification to figure out if new ones have - // been added or removed. - if (-1 == mLength) { - mLength = mDocument->GetNumberOfStyleSheets(); - } - return mLength; -} - -StyleSheet* -nsDOMStyleSheetList::IndexedGetter(uint32_t aIndex, bool& aFound) -{ - if (!mDocument || aIndex >= (uint32_t)mDocument->GetNumberOfStyleSheets()) { - aFound = false; - return nullptr; - } - aFound = true; - return mDocument->GetStyleSheetAt(aIndex); -} - -void -nsDOMStyleSheetList::NodeWillBeDestroyed(const nsINode *aNode) -{ - mDocument = nullptr; -} - -void -nsDOMStyleSheetList::StyleSheetAdded(StyleSheet* aStyleSheet, - bool aDocumentSheet) -{ - if (aDocumentSheet && -1 != mLength) { - mLength++; - } -} - -void -nsDOMStyleSheetList::StyleSheetRemoved(StyleSheet* aStyleSheet, - bool aDocumentSheet) -{ - if (aDocumentSheet && -1 != mLength) { - mLength--; - } -} - // nsOnloadBlocker implementation NS_IMPL_ISUPPORTS(nsOnloadBlocker, nsIRequest) @@ -1200,10 +1147,10 @@ nsDOMStyleSheetSetList::EnsureFresh() // no document, for sure } - int32_t count = mDocument->GetNumberOfStyleSheets(); + size_t count = mDocument->SheetCount(); nsAutoString title; - for (int32_t index = 0; index < count; index++) { - StyleSheet* sheet = mDocument->GetStyleSheetAt(index); + for (size_t index = 0; index < count; index++) { + StyleSheet* sheet = mDocument->SheetAt(index); NS_ASSERTION(sheet, "Null sheet in sheet list!"); // XXXheycam ServoStyleSheets don't expose their title yet. if (sheet->IsServo()) { @@ -1299,6 +1246,7 @@ static already_AddRefed<mozilla::dom::NodeInfo> nullNodeInfo; // ================================================================== nsIDocument::nsIDocument() : nsINode(nullNodeInfo), + DocumentOrShadowRoot(this), mReferrerPolicySet(false), mReferrerPolicy(mozilla::net::RP_Default), mBlockAllMixedContent(false), @@ -1328,10 +1276,15 @@ nsIDocument::nsIDocument() mFrameRequestCallbacksScheduled(false), mBidiOptions(IBMBIDI_DEFAULT_BIDI_OPTIONS), mPartID(0), - mUserHasInteracted(false) + mUserHasInteracted(false), + mThrowOnDynamicMarkupInsertionCounter(0) { SetIsInDocument(); + // Set this when document is created and value stays the same for the lifetime + // of the document. + mIsWebComponentsEnabled = nsContentUtils::IsWebComponentsEnabled(); + PR_INIT_CLIST(&mDOMMediaQueryLists); } @@ -1451,11 +1404,11 @@ nsDocument::~nsDocument() // Let the stylesheets know we're going away for (StyleSheet* sheet : mStyleSheets) { - sheet->SetOwningDocument(nullptr); + sheet->ClearAssociatedDocument(); } for (auto& sheets : mAdditionalSheets) { for (StyleSheet* sheet : sheets) { - sheet->SetOwningDocument(nullptr); + sheet->ClearAssociatedDocument(); } } if (mAttrStyleSheet) { @@ -2120,7 +2073,7 @@ nsDocument::RemoveDocStyleSheetsFromStyleSets() { // The stylesheets should forget us for (StyleSheet* sheet : Reversed(mStyleSheets)) { - sheet->SetOwningDocument(nullptr); + sheet->ClearAssociatedDocument(); if (sheet->IsApplicable()) { nsCOMPtr<nsIPresShell> shell = GetShell(); @@ -2139,7 +2092,7 @@ nsDocument::RemoveStyleSheetsFromStyleSets( { // The stylesheets should forget us for (StyleSheet* sheet : Reversed(aSheets)) { - sheet->SetOwningDocument(nullptr); + sheet->ClearAssociatedDocument(); if (sheet->IsApplicable()) { nsCOMPtr<nsIPresShell> shell = GetShell(); @@ -2318,6 +2271,29 @@ WarnIfSandboxIneffective(nsIDocShell* aDocShell, } } +bool +nsDocument::IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject) +{ + if (!nsContentUtils::IsWebComponentsEnabled()) { + return false; + } + + JS::Rooted<JSObject*> obj(aCx, aObject); + + JSAutoCompartment ac(aCx, obj); + JS::Rooted<JSObject*> global(aCx, JS_GetGlobalForObject(aCx, obj)); + nsCOMPtr<nsPIDOMWindowInner> window = + do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(global)); + + nsIDocument* doc = window ? window->GetExtantDoc() : nullptr; + if (doc && doc->IsStyledByServo()) { + NS_WARNING("stylo: Web Components not supported yet"); + return false; + } + + return true; +} + nsresult nsDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel, nsILoadGroup* aLoadGroup, @@ -2757,8 +2733,7 @@ nsDocument::AddToNameTable(Element *aElement, nsIAtom* aName) "Only put elements that need to be exposed as document['name'] in " "the named table."); - nsIdentifierMapEntry *entry = - mIdentifierMap.PutEntry(nsDependentAtomString(aName)); + nsIdentifierMapEntry* entry = mIdentifierMap.PutEntry(aName); // Null for out-of-memory if (entry) { @@ -2777,8 +2752,7 @@ nsDocument::RemoveFromNameTable(Element *aElement, nsIAtom* aName) if (mIdentifierMap.Count() == 0) return; - nsIdentifierMapEntry *entry = - mIdentifierMap.GetEntry(nsDependentAtomString(aName)); + nsIdentifierMapEntry* entry = mIdentifierMap.GetEntry(aName); if (!entry) // Could be false if the element was anonymous, hence never added return; @@ -2792,8 +2766,7 @@ nsDocument::RemoveFromNameTable(Element *aElement, nsIAtom* aName) void nsDocument::AddToIdTable(Element *aElement, nsIAtom* aId) { - nsIdentifierMapEntry *entry = - mIdentifierMap.PutEntry(nsDependentAtomString(aId)); + nsIdentifierMapEntry* entry = mIdentifierMap.PutEntry(aId); if (entry) { /* True except on OOM */ if (nsGenericHTMLElement::ShouldExposeIdAsHTMLDocumentProperty(aElement) && @@ -2815,8 +2788,7 @@ nsDocument::RemoveFromIdTable(Element *aElement, nsIAtom* aId) return; } - nsIdentifierMapEntry *entry = - mIdentifierMap.GetEntry(nsDependentAtomString(aId)); + nsIdentifierMapEntry* entry = mIdentifierMap.GetEntry(aId); if (!entry) // Can be null for XML elements with changing ids. return; @@ -2951,6 +2923,33 @@ nsDocument::IsWebAnimationsEnabled(JSContext* /*unused*/, JSObject* /*unused*/) Preferences::GetBool("dom.animations-api.core.enabled"); } +bool +nsDocument::AreWebAnimationsTimelinesEnabled(JSContext* /*unused*/, JSObject* /*unused*/) +{ + MOZ_ASSERT(NS_IsMainThread()); + + return nsContentUtils::IsCallerChrome() || + Preferences::GetBool("dom.animations-api.timelines.enabled"); +} + +bool +nsDocument::AreWebAnimationsImplicitKeyframesEnabled(JSContext* /*unused*/, JSObject* /*unused*/) +{ + MOZ_ASSERT(NS_IsMainThread()); + + return nsContentUtils::IsCallerChrome() || + Preferences::GetBool("dom.animations-api.implicit-keyframes.enabled"); +} + +bool +nsDocument::IsWebAnimationsGetAnimationsEnabled(JSContext* /*unused*/, JSObject* /*unused*/) +{ + MOZ_ASSERT(NS_IsMainThread()); + + return nsContentUtils::IsCallerChrome() || + Preferences::GetBool("dom.animations-api.getAnimations.enabled"); +} + DocumentTimeline* nsDocument::Timeline() { @@ -3066,20 +3065,9 @@ Element* nsIDocument::GetActiveElement() { // Get the focused element. - if (nsCOMPtr<nsPIDOMWindowOuter> window = GetWindow()) { - nsCOMPtr<nsPIDOMWindowOuter> focusedWindow; - nsIContent* focusedContent = - nsFocusManager::GetFocusedDescendant(window, false, - getter_AddRefs(focusedWindow)); - // be safe and make sure the element is from this document - if (focusedContent && focusedContent->OwnerDoc() == this) { - if (focusedContent->ChromeOnlyAccess()) { - focusedContent = focusedContent->FindFirstNonChromeOnlyAccessContent(); - } - if (focusedContent) { - return focusedContent->AsElement(); - } - } + Element* focusedElement = GetRetargetedFocusedElement(); + if (focusedElement) { + return focusedElement; } // No focused element anywhere in this document. Try to get the BODY. @@ -3291,12 +3279,6 @@ nsDocument::GetElementsByClassName(const nsAString& aClasses, return NS_OK; } -already_AddRefed<nsContentList> -nsIDocument::GetElementsByClassName(const nsAString& aClasses) -{ - return nsContentUtils::GetElementsByClassName(this, aClasses); -} - NS_IMETHODIMP nsDocument::ReleaseCapture() { @@ -3940,24 +3922,6 @@ nsDocument::AddOnDemandBuiltInUASheet(StyleSheet* aSheet) NotifyStyleSheetAdded(aSheet, false); } -int32_t -nsDocument::GetNumberOfStyleSheets() const -{ - return mStyleSheets.Length(); -} - -StyleSheet* -nsDocument::GetStyleSheetAt(int32_t aIndex) const -{ - return mStyleSheets.SafeElementAt(aIndex, nullptr); -} - -int32_t -nsDocument::GetIndexOfStyleSheet(const StyleSheet* aSheet) const -{ - return mStyleSheets.IndexOf(aSheet); -} - void nsDocument::AddStyleSheetToStyleSets(StyleSheet* aSheet) { @@ -4020,7 +3984,7 @@ nsDocument::AddStyleSheet(StyleSheet* aSheet) { NS_PRECONDITION(aSheet, "null arg"); mStyleSheets.AppendElement(aSheet); - aSheet->SetOwningDocument(this); + aSheet->SetAssociatedDocument(this, StyleSheet::OwnedByDocument); if (aSheet->IsApplicable()) { AddStyleSheetToStyleSets(aSheet); @@ -4057,7 +4021,7 @@ nsDocument::RemoveStyleSheet(StyleSheet* aSheet) NotifyStyleSheetRemoved(aSheet, true); } - aSheet->SetOwningDocument(nullptr); + aSheet->ClearAssociatedDocument(); } void @@ -4085,7 +4049,7 @@ nsDocument::UpdateStyleSheets(nsTArray<RefPtr<StyleSheet>>& aOldSheets, StyleSheet* newSheet = aNewSheets[i]; if (newSheet) { mStyleSheets.InsertElementAt(oldIndex, newSheet); - newSheet->SetOwningDocument(this); + newSheet->SetAssociatedDocument(this, StyleSheet::OwnedByDocument); if (newSheet->IsApplicable()) { AddStyleSheetToStyleSets(newSheet); } @@ -4098,13 +4062,13 @@ nsDocument::UpdateStyleSheets(nsTArray<RefPtr<StyleSheet>>& aOldSheets, } void -nsDocument::InsertStyleSheetAt(StyleSheet* aSheet, int32_t aIndex) +nsDocument::InsertStyleSheetAt(StyleSheet* aSheet, size_t aIndex) { - NS_PRECONDITION(aSheet, "null ptr"); + MOZ_ASSERT(aSheet); mStyleSheets.InsertElementAt(aIndex, aSheet); - aSheet->SetOwningDocument(this); + aSheet->SetAssociatedDocument(this, StyleSheet::OwnedByDocument); if (aSheet->IsApplicable()) { AddStyleSheetToStyleSets(aSheet); @@ -4229,7 +4193,7 @@ nsDocument::LoadAdditionalStyleSheet(additionalSheetType aType, nsresult rv = loader->LoadSheetSync(aSheetURI, parsingMode, true, &sheet); NS_ENSURE_SUCCESS(rv, rv); - sheet->SetOwningDocument(this); + sheet->SetAssociatedDocument(this, StyleSheet::OwnedByDocument); MOZ_ASSERT(sheet->IsApplicable()); return AddAdditionalStyleSheet(aType, sheet); @@ -4287,7 +4251,7 @@ nsDocument::RemoveAdditionalStyleSheet(additionalSheetType aType, nsIURI* aSheet NotifyStyleSheetRemoved(sheetRef, false); EndUpdate(UPDATE_STYLE); - sheetRef->SetOwningDocument(nullptr); + sheetRef->ClearAssociatedDocument(); } } @@ -4810,32 +4774,7 @@ nsDocument::BeginLoad() void nsDocument::ReportEmptyGetElementByIdArg() { - nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, - NS_LITERAL_CSTRING("DOM"), this, - nsContentUtils::eDOM_PROPERTIES, - "EmptyGetElementByIdParam"); -} - -Element* -nsDocument::GetElementById(const nsAString& aElementId) -{ - if (!CheckGetElementByIdArg(aElementId)) { - return nullptr; - } - - nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(aElementId); - return entry ? entry->GetIdElement() : nullptr; -} - -const nsTArray<Element*>* -nsDocument::GetAllElementsForId(const nsAString& aElementId) const -{ - if (aElementId.IsEmpty()) { - return nullptr; - } - - nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(aElementId); - return entry ? &entry->GetIdElements() : nullptr; + nsContentUtils::ReportEmptyGetElementByIdArg(this); } NS_IMETHODIMP @@ -4860,7 +4799,7 @@ nsDocument::AddIDTargetObserver(nsIAtom* aID, IDTargetObserver aObserver, if (!CheckGetElementByIdArg(id)) return nullptr; - nsIdentifierMapEntry *entry = mIdentifierMap.PutEntry(id); + nsIdentifierMapEntry* entry = mIdentifierMap.PutEntry(aID); NS_ENSURE_TRUE(entry, nullptr); entry->AddContentChangeCallback(aObserver, aData, aForImage); @@ -4876,7 +4815,7 @@ nsDocument::RemoveIDTargetObserver(nsIAtom* aID, IDTargetObserver aObserver, if (!CheckGetElementByIdArg(id)) return; - nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(id); + nsIdentifierMapEntry* entry = mIdentifierMap.GetEntry(aID); if (!entry) { return; } @@ -5366,29 +5305,18 @@ bool IsLowercaseASCII(const nsAString& aValue) return true; } -already_AddRefed<mozilla::dom::CustomElementRegistry> -nsDocument::GetCustomElementRegistry() +// We only support pseudo-elements with two colons in this function. +static CSSPseudoElementType +GetPseudoElementType(const nsString& aString, ErrorResult& aRv) { - nsAutoString contentType; - GetContentType(contentType); - if (!IsHTMLDocument() && - !contentType.EqualsLiteral("application/xhtml+xml")) { - return nullptr; + MOZ_ASSERT(!aString.IsEmpty(), "GetPseudoElementType aString should be non-null"); + if (aString.Length() <= 2 || aString[0] != ':' || aString[1] != ':') { + aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR); + return CSSPseudoElementType::NotPseudo; } - - nsCOMPtr<nsPIDOMWindowInner> window( - do_QueryInterface(mScriptGlobalObject ? mScriptGlobalObject - : GetScopeObject())); - if (!window) { - return nullptr; - } - - RefPtr<CustomElementRegistry> registry = window->CustomElements(); - if (!registry) { - return nullptr; - } - - return registry.forget(); + nsCOMPtr<nsIAtom> pseudo = NS_Atomize(Substring(aString, 1)); + return nsCSSPseudoElements::GetPseudoType(pseudo, + nsCSSProps::EnabledState::eInUASheets); } already_AddRefed<Element> @@ -5408,18 +5336,40 @@ nsDocument::CreateElement(const nsAString& aTagName, } const nsString* is = nullptr; + CSSPseudoElementType pseudoType = CSSPseudoElementType::NotPseudo; if (aOptions.IsElementCreationOptions()) { - // Throw NotFoundError if 'is' is not-null and definition is null - is = CheckCustomElementName(aOptions.GetAsElementCreationOptions(), - needsLowercase ? lcTagName : aTagName, mDefaultElementType, rv); - if (rv.Failed()) { - return nullptr; + const ElementCreationOptions& options = + aOptions.GetAsElementCreationOptions(); + + if (CustomElementRegistry::IsCustomElementEnabled() && + options.mIs.WasPassed()) { + is = &options.mIs.Value(); + } + + // Check 'pseudo' and throw an exception if it's not one allowed + // with CSS_PSEUDO_ELEMENT_IS_JS_CREATED_NAC. + if (options.mPseudo.WasPassed()) { + pseudoType = GetPseudoElementType(options.mPseudo.Value(), rv); + if (rv.Failed() || + pseudoType == CSSPseudoElementType::NotPseudo || + !nsCSSPseudoElements::PseudoElementIsJSCreatedNAC(pseudoType)) { + rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); + return nullptr; + } } } RefPtr<Element> elem = CreateElem( needsLowercase ? lcTagName : aTagName, nullptr, mDefaultElementType, is); + if (pseudoType != CSSPseudoElementType::NotPseudo) { + elem->SetPseudoElementType(pseudoType); + } + + if (is) { + elem->SetAttr(kNameSpaceID_None, nsGkAtoms::is, *is, true); + } + return elem.forget(); } @@ -5430,8 +5380,8 @@ nsDocument::CreateElementNS(const nsAString& aNamespaceURI, { *aReturn = nullptr; ElementCreationOptionsOrString options; - options.SetAsString(); + options.SetAsString(); ErrorResult rv; nsCOMPtr<Element> element = CreateElementNS(aNamespaceURI, aQualifiedName, options, rv); @@ -5456,12 +5406,11 @@ nsDocument::CreateElementNS(const nsAString& aNamespaceURI, } const nsString* is = nullptr; - if (aOptions.IsElementCreationOptions()) { - // Throw NotFoundError if 'is' is not-null and definition is null - is = CheckCustomElementName(aOptions.GetAsElementCreationOptions(), - aQualifiedName, nodeInfo->NamespaceID(), rv); - if (rv.Failed()) { - return nullptr; + if (CustomElementRegistry::IsCustomElementEnabled() && + aOptions.IsElementCreationOptions()) { + const ElementCreationOptions& options = aOptions.GetAsElementCreationOptions(); + if (options.mIs.WasPassed()) { + is = &options.mIs.Value(); } } @@ -5472,6 +5421,10 @@ nsDocument::CreateElementNS(const nsAString& aNamespaceURI, return nullptr; } + if (is) { + element->SetAttr(kNameSpaceID_None, nsGkAtoms::is, *is, true); + } + return element.forget(); } @@ -5668,231 +5621,9 @@ nsIDocument::CreateAttributeNS(const nsAString& aNamespaceURI, } bool -nsDocument::CustomElementConstructor(JSContext* aCx, unsigned aArgc, JS::Value* aVp) -{ - JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp); - - JS::Rooted<JSObject*> global(aCx, - JS_GetGlobalForObject(aCx, &args.callee())); - RefPtr<nsGlobalWindow> window; - UNWRAP_OBJECT(Window, global, window); - MOZ_ASSERT(window, "Should have a non-null window"); - - nsDocument* document = static_cast<nsDocument*>(window->GetDoc()); - - // Function name is the type of the custom element. - JSString* jsFunName = - JS_GetFunctionId(JS_ValueToFunction(aCx, args.calleev())); - nsAutoJSString elemName; - if (!elemName.init(aCx, jsFunName)) { - return true; - } - - RefPtr<mozilla::dom::CustomElementRegistry> registry = window->CustomElements(); - if (!registry) { - return true; - } - - nsCOMPtr<nsIAtom> typeAtom(NS_Atomize(elemName)); - CustomElementDefinition* definition = registry->mCustomDefinitions.Get(typeAtom); - if (!definition) { - return true; - } - - nsDependentAtomString localName(definition->mLocalName); - - nsCOMPtr<Element> element = - document->CreateElem(localName, nullptr, kNameSpaceID_XHTML); - NS_ENSURE_TRUE(element, true); - - if (definition->mLocalName != typeAtom) { - // This element is a custom element by extension, thus we need to - // do some special setup. For non-extended custom elements, this happens - // when the element is created. - nsContentUtils::SetupCustomElement(element, &elemName); - } - - nsresult rv = nsContentUtils::WrapNative(aCx, element, element, args.rval()); - NS_ENSURE_SUCCESS(rv, true); - - return true; -} - -bool -nsDocument::IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject) +nsDocument::IsWebComponentsEnabled(const nsINode* aNode) { - JS::Rooted<JSObject*> obj(aCx, aObject); - - //if (Preferences::GetBool("dom.webcomponents.enabled")) { - // return true; - //} - - // Check for the webcomponents permission. See Bug 1181555. - JSAutoCompartment ac(aCx, obj); - JS::Rooted<JSObject*> global(aCx, JS_GetGlobalForObject(aCx, obj)); - nsCOMPtr<nsPIDOMWindowInner> window = - do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(global)); - - return IsWebComponentsEnabled(window); -} - -bool -nsDocument::IsWebComponentsEnabled(dom::NodeInfo* aNodeInfo) -{ - //if (Preferences::GetBool("dom.webcomponents.enabled")) { - // return true; - //} - - nsIDocument* doc = aNodeInfo->GetDocument(); - // Use GetScopeObject() here so that data documents work the same way as the - // main document they're associated with. - nsCOMPtr<nsPIDOMWindowInner> window = - do_QueryInterface(doc->GetScopeObject()); - return IsWebComponentsEnabled(window); -} - -bool -nsDocument::IsWebComponentsEnabled(nsPIDOMWindowInner* aWindow) -{ -/* - if (aWindow) { - nsresult rv; - nsCOMPtr<nsIPermissionManager> permMgr = - do_GetService(NS_PERMISSIONMANAGER_CONTRACTID, &rv); - NS_ENSURE_SUCCESS(rv, false); - - uint32_t perm; - rv = permMgr->TestPermissionFromWindow( - aWindow, "moz-extremely-unstable-and-will-change-webcomponents", &perm); - NS_ENSURE_SUCCESS(rv, false); - - return perm == nsIPermissionManager::ALLOW_ACTION; - } -*/ - return false; -} - -void -nsDocument::RegisterElement(JSContext* aCx, const nsAString& aType, - const ElementRegistrationOptions& aOptions, - JS::MutableHandle<JSObject*> aRetval, - ErrorResult& rv) -{ - RefPtr<CustomElementRegistry> registry(GetCustomElementRegistry()); - if (!registry) { - rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); - return; - } - - // Unconditionally convert TYPE to lowercase. - nsAutoString lcType; - nsContentUtils::ASCIIToLower(aType, lcType); - - nsIGlobalObject* sgo = GetScopeObject(); - if (!sgo) { - rv.Throw(NS_ERROR_UNEXPECTED); - return; - } - - JS::Rooted<JSObject*> global(aCx, sgo->GetGlobalJSObject()); - JS::Rooted<JSObject*> protoObject(aCx); - - if (!aOptions.mPrototype) { - JS::Rooted<JSObject*> htmlProto(aCx); - htmlProto = HTMLElementBinding::GetProtoObjectHandle(aCx); - if (!htmlProto) { - rv.Throw(NS_ERROR_OUT_OF_MEMORY); - return; - } - - protoObject = JS_NewObjectWithGivenProto(aCx, nullptr, htmlProto); - if (!protoObject) { - rv.Throw(NS_ERROR_UNEXPECTED); - return; - } - } else { - protoObject = aOptions.mPrototype; - - // Get the unwrapped prototype to do some checks. - JS::Rooted<JSObject*> protoObjectUnwrapped(aCx, js::CheckedUnwrap(protoObject)); - if (!protoObjectUnwrapped) { - // If the caller's compartment does not have permission to access the - // unwrapped prototype then throw. - rv.Throw(NS_ERROR_DOM_SECURITY_ERR); - return; - } - - // If PROTOTYPE is already an interface prototype object for any interface - // object or PROTOTYPE has a non-configurable property named constructor, - // throw a NotSupportedError and stop. - const js::Class* clasp = js::GetObjectClass(protoObjectUnwrapped); - if (IsDOMIfaceAndProtoClass(clasp)) { - rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); - return; - } - - JS::Rooted<JS::PropertyDescriptor> descRoot(aCx); - JS::MutableHandle<JS::PropertyDescriptor> desc(&descRoot); - // This check may go through a wrapper, but as we checked above - // it should be transparent or an xray. This should be fine for now, - // until the spec is sorted out. - if (!JS_GetPropertyDescriptor(aCx, protoObject, "constructor", desc)) { - rv.Throw(NS_ERROR_UNEXPECTED); - return; - } - - if (!desc.configurable()) { - rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); - return; - } - } - - JS::Rooted<JSFunction*> constructor(aCx); - { - // Go into the document's global compartment when creating the constructor - // function because we want to get the correct document (where the - // definition is registered) when it is called. - JSAutoCompartment ac(aCx, global); - - // Create constructor to return. Store the name of the custom element as the - // name of the function. - constructor = JS_NewFunction(aCx, nsDocument::CustomElementConstructor, 0, - JSFUN_CONSTRUCTOR, - NS_ConvertUTF16toUTF8(lcType).get()); - if (!constructor) { - rv.Throw(NS_ERROR_OUT_OF_MEMORY); - return; - } - } - - JS::Rooted<JSObject*> wrappedConstructor(aCx); - wrappedConstructor = JS_GetFunctionObject(constructor); - if (!JS_WrapObject(aCx, &wrappedConstructor)) { - rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); - return; - } - - if (!JS_LinkConstructorAndPrototype(aCx, wrappedConstructor, protoObject)) { - rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); - return; - } - - ElementDefinitionOptions options; - if (!aOptions.mExtends.IsVoid()) { - // Only convert NAME to lowercase in HTML documents. - nsAutoString lcName; - IsHTMLDocument() ? nsContentUtils::ASCIIToLower(aOptions.mExtends, lcName) - : lcName.Assign(aOptions.mExtends); - - options.mExtends.Construct(lcName); - } - - RootedCallback<OwningNonNull<binding_detail::FastFunction>> functionConstructor(aCx); - functionConstructor = new binding_detail::FastFunction(aCx, wrappedConstructor, sgo); - - registry->Define(lcType, functionConstructor, options, rv); - - aRetval.set(wrappedConstructor); + return aNode->OwnerDoc()->IsWebComponentsEnabled(); } NS_IMETHODIMP @@ -5935,27 +5666,6 @@ nsDocument::BlockedTrackingNodes() const return list.forget(); } -already_AddRefed<nsContentList> -nsIDocument::GetElementsByTagNameNS(const nsAString& aNamespaceURI, - const nsAString& aLocalName, - ErrorResult& aResult) -{ - int32_t nameSpaceId = kNameSpaceID_Wildcard; - - if (!aNamespaceURI.EqualsLiteral("*")) { - aResult = - nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI, - nameSpaceId); - if (aResult.Failed()) { - return nullptr; - } - } - - NS_ASSERTION(nameSpaceId != kNameSpaceID_Unknown, "Unexpected namespace ID!"); - - return NS_GetContentList(this, nameSpaceId, aLocalName); -} - NS_IMETHODIMP nsDocument::GetElementsByTagNameNS(const nsAString& aNamespaceURI, const nsAString& aLocalName, @@ -5963,7 +5673,7 @@ nsDocument::GetElementsByTagNameNS(const nsAString& aNamespaceURI, { ErrorResult rv; RefPtr<nsContentList> list = - nsIDocument::GetElementsByTagNameNS(aNamespaceURI, aLocalName, rv); + GetElementsByTagNameNS(aNamespaceURI, aLocalName, rv); if (rv.Failed()) { return rv.StealNSResult(); } @@ -5980,15 +5690,6 @@ nsDocument::GetStyleSheets(nsIDOMStyleSheetList** aStyleSheets) return NS_OK; } -StyleSheetList* -nsDocument::StyleSheets() -{ - if (!mDOMStyleSheets) { - mDOMStyleSheets = new nsDOMStyleSheetList(this); - } - return mDOMStyleSheets; -} - NS_IMETHODIMP nsDocument::GetMozSelectedStyleSheetSet(nsAString& aSheetSet) { @@ -6002,10 +5703,10 @@ nsIDocument::GetSelectedStyleSheetSet(nsAString& aSheetSet) aSheetSet.Truncate(); // Look through our sheets, find the selected set title - int32_t count = GetNumberOfStyleSheets(); + size_t count = SheetCount(); nsAutoString title; - for (int32_t index = 0; index < count; index++) { - StyleSheet* sheet = GetStyleSheetAt(index); + for (size_t index = 0; index < count; index++) { + StyleSheet* sheet = SheetAt(index); NS_ASSERTION(sheet, "Null sheet in sheet list!"); // XXXheycam Make this work with ServoStyleSheets. @@ -6122,10 +5823,10 @@ nsDocument::EnableStyleSheetsForSetInternal(const nsAString& aSheetSet, bool aUpdateCSSLoader) { BeginUpdate(UPDATE_STYLE); - int32_t count = GetNumberOfStyleSheets(); + size_t count = SheetCount(); nsAutoString title; - for (int32_t index = 0; index < count; index++) { - StyleSheet* sheet = GetStyleSheetAt(index); + for (size_t index = 0; index < count; index++) { + StyleSheet* sheet = SheetAt(index); NS_ASSERTION(sheet, "Null sheet in sheet list!"); // XXXheycam Make this work with ServoStyleSheets. @@ -6395,7 +6096,7 @@ already_AddRefed<nsRange> nsIDocument::CreateRange(ErrorResult& rv) { RefPtr<nsRange> range = new nsRange(this); - nsresult res = range->Set(this, 0, this, 0); + nsresult res = range->CollapseTo(this, 0); if (NS_FAILED(res)) { rv.Throw(res); return nullptr; @@ -6550,6 +6251,49 @@ nsIDocument::GetHtmlChildElement(nsIAtom* aTag) return nullptr; } +nsGenericHTMLElement* +nsIDocument::GetBody() +{ + Element* html = GetHtmlElement(); + if (!html) { + return nullptr; + } + + for (nsIContent* child = html->GetFirstChild(); + child; + child = child->GetNextSibling()) { + if (child->IsHTMLElement(nsGkAtoms::body) || + child->IsHTMLElement(nsGkAtoms::frameset)) { + return static_cast<nsGenericHTMLElement*>(child); + } + } + + return nullptr; +} + +void +nsIDocument::SetBody(nsGenericHTMLElement* newBody, ErrorResult& rv) +{ + nsCOMPtr<Element> root = GetRootElement(); + + // The body element must be either a body tag or a frameset tag. And we must + // have a root element to be able to add kids to it. + if (!newBody || + !newBody->IsAnyOfHTMLElements(nsGkAtoms::body, nsGkAtoms::frameset) || + !root) { + rv.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR); + return; + } + + // Use DOM methods so that we pass through the appropriate security checks. + nsCOMPtr<Element> currentBody = GetBody(); + if (currentBody) { + root->ReplaceChild(*newBody, *currentBody, rv); + } else { + root->AppendChild(*newBody, rv); + } +} + Element* nsDocument::GetTitleElement() { @@ -7643,7 +7387,7 @@ nsDocument::GetExistingListenerManager() const } nsresult -nsDocument::PreHandleEvent(EventChainPreVisitor& aVisitor) +nsDocument::GetEventTargetParent(EventChainPreVisitor& aVisitor) { aVisitor.mCanHandle = true; // FIXME! This is a hack to make middle mouse paste working also in Editor. @@ -7653,8 +7397,8 @@ nsDocument::PreHandleEvent(EventChainPreVisitor& aVisitor) // Load events must not propagate to |window| object, see bug 335251. if (aVisitor.mEvent->mMessage != eLoad) { nsGlobalWindow* window = nsGlobalWindow::Cast(GetWindow()); - aVisitor.mParentTarget = - window ? window->GetTargetForEventTargetChain() : nullptr; + aVisitor.SetParentTarget( + window ? window->GetTargetForEventTargetChain() : nullptr, false); } return NS_OK; } @@ -9790,9 +9534,9 @@ nsIDocument::CreateStaticClone(nsIDocShell* aCloneContainer) clonedDoc->mOriginalDocument->mStaticCloneCount++; - int32_t sheetsCount = GetNumberOfStyleSheets(); - for (int32_t i = 0; i < sheetsCount; ++i) { - RefPtr<StyleSheet> sheet = GetStyleSheetAt(i); + size_t sheetsCount = SheetCount(); + for (size_t i = 0; i < sheetsCount; ++i) { + RefPtr<StyleSheet> sheet = SheetAt(i); if (sheet) { if (sheet->IsApplicable()) { // XXXheycam Need to make ServoStyleSheet cloning work. @@ -10851,7 +10595,7 @@ UpdateViewportScrollbarOverrideForFullscreen(nsIDocument* aDoc) { if (nsIPresShell* presShell = aDoc->GetShell()) { if (nsPresContext* presContext = presShell->GetPresContext()) { - presContext->UpdateViewportScrollbarStylesOverride(); + presContext->UpdateViewportScrollStylesOverride(); } } } @@ -12010,7 +11754,7 @@ SizeOfOwnedSheetArrayExcludingThis(const nsTArray<RefPtr<StyleSheet>>& aSheets, size_t n = 0; n += aSheets.ShallowSizeOfExcludingThis(aMallocSizeOf); for (StyleSheet* sheet : aSheets) { - if (!sheet->GetOwningDocument()) { + if (!sheet->GetAssociatedDocument()) { // Avoid over-reporting shared sheets. continue; } @@ -12551,8 +12295,12 @@ MarkDocumentTreeToBeInSyncOperation(nsIDocument* aDoc, void* aData) nsAutoSyncOperation::nsAutoSyncOperation(nsIDocument* aDoc) { - mMicroTaskLevel = nsContentUtils::MicroTaskLevel(); - nsContentUtils::SetMicroTaskLevel(0); + mMicroTaskLevel = 0; + CycleCollectedJSContext* ccjs = CycleCollectedJSContext::Get(); + if (ccjs) { + mMicroTaskLevel = ccjs->MicroTaskLevel(); + ccjs->SetMicroTaskLevel(0); + } if (aDoc) { if (nsPIDOMWindowOuter* win = aDoc->GetWindow()) { if (nsCOMPtr<nsPIDOMWindowOuter> top = win->GetTop()) { @@ -12568,7 +12316,10 @@ nsAutoSyncOperation::~nsAutoSyncOperation() for (int32_t i = 0; i < mDocuments.Count(); ++i) { mDocuments[i]->SetIsInSyncOperation(false); } - nsContentUtils::SetMicroTaskLevel(mMicroTaskLevel); + CycleCollectedJSContext* ccjs = CycleCollectedJSContext::Get(); + if (ccjs) { + ccjs->SetMicroTaskLevel(mMicroTaskLevel); + } } gfxUserFontSet* @@ -12738,30 +12489,6 @@ nsIDocument::UpdateStyleBackendType() #endif } -const nsString* -nsDocument::CheckCustomElementName(const ElementCreationOptions& aOptions, - const nsAString& aLocalName, - uint32_t aNamespaceID, - ErrorResult& rv) -{ - // only check aOptions if 'is' is passed and the webcomponents preference - // is enabled - if (!aOptions.mIs.WasPassed() || - !CustomElementRegistry::IsCustomElementEnabled()) { - return nullptr; - } - - const nsString* is = &aOptions.mIs.Value(); - - // Throw NotFoundError if 'is' is not-null and definition is null - if (!nsContentUtils::LookupCustomElementDefinition(this, aLocalName, - aNamespaceID, is)) { - rv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR); - } - - return is; -} - Selection* nsIDocument::GetSelection(ErrorResult& aRv) { |