summaryrefslogtreecommitdiffstats
path: root/dom/base/nsDocument.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/base/nsDocument.cpp')
-rw-r--r--dom/base/nsDocument.cpp721
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)
{