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.cpp179
1 files changed, 123 insertions, 56 deletions
diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp
index afe88a454..293e48eb0 100644
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -1329,7 +1329,8 @@ nsIDocument::nsIDocument()
mFrameRequestCallbacksScheduled(false),
mBidiOptions(IBMBIDI_DEFAULT_BIDI_OPTIONS),
mPartID(0),
- mUserHasInteracted(false)
+ mUserHasInteracted(false),
+ mThrowOnDynamicMarkupInsertionCounter(0)
{
SetIsInDocument();
@@ -5395,18 +5396,14 @@ nsDocument::CreateElement(const nsAString& aTagName,
}
const nsString* is = nullptr;
- 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;
- }
- }
RefPtr<Element> elem = CreateElem(
needsLowercase ? lcTagName : aTagName, nullptr, mDefaultElementType, is);
+ if (is) {
+ elem->SetAttr(kNameSpaceID_None, nsGkAtoms::is, *is, true);
+ }
+
return elem.forget();
}
@@ -5443,14 +5440,6 @@ 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;
- }
- }
nsCOMPtr<Element> element;
rv = NS_NewElement(getter_AddRefs(element), nodeInfo.forget(),
@@ -5459,6 +5448,10 @@ nsDocument::CreateElementNS(const nsAString& aNamespaceURI,
return nullptr;
}
+ if (is) {
+ element->SetAttr(kNameSpaceID_None, nsGkAtoms::is, *is, true);
+ }
+
return element.forget();
}
@@ -5681,24 +5674,70 @@ nsDocument::CustomElementConstructor(JSContext* aCx, unsigned aArgc, JS::Value*
}
nsCOMPtr<nsIAtom> typeAtom(NS_Atomize(elemName));
- CustomElementDefinition* definition = registry->mCustomDefinitions.Get(typeAtom);
+ CustomElementDefinition* definition =
+ registry->mCustomDefinitions.GetWeak(typeAtom);
if (!definition) {
return true;
}
- nsDependentAtomString localName(definition->mLocalName);
+ RefPtr<Element> element;
+
+ // We integrate with construction stack and do prototype swizzling here, so
+ // that old upgrade behavior could also share the new upgrade steps.
+ // And this old upgrade will be remove at some point (when everything is
+ // switched to latest custom element spec).
+ nsTArray<RefPtr<nsGenericHTMLElement>>& constructionStack =
+ definition->mConstructionStack;
+ if (constructionStack.Length()) {
+ element = constructionStack.LastElement();
+ NS_ENSURE_TRUE(element != ALEADY_CONSTRUCTED_MARKER, false);
+
+ // Do prototype swizzling if dom reflector exists.
+ JS::Rooted<JSObject*> reflector(aCx, element->GetWrapper());
+ if (reflector) {
+ Maybe<JSAutoCompartment> ac;
+ JS::Rooted<JSObject*> prototype(aCx, definition->mPrototype);
+ if (element->NodePrincipal()->SubsumesConsideringDomain(nsContentUtils::ObjectPrincipal(prototype))) {
+ ac.emplace(aCx, reflector);
+ if (!JS_WrapObject(aCx, &prototype) ||
+ !JS_SetPrototype(aCx, reflector, prototype)) {
+ return false;
+ }
+ } else {
+ // We want to set the custom prototype in the compartment where it was
+ // registered. We store the prototype from define() without unwrapped,
+ // hence the prototype's compartment is the compartment where it was
+ // registered.
+ // In the case that |reflector| and |prototype| are in different
+ // compartments, this will set the prototype on the |reflector|'s wrapper
+ // and thus only visible in the wrapper's compartment, since we know
+ // reflector's principal does not subsume prototype's in this case.
+ ac.emplace(aCx, prototype);
+ if (!JS_WrapObject(aCx, &reflector) ||
+ !JS_SetPrototype(aCx, reflector, prototype)) {
+ return false;
+ }
+ }
- nsCOMPtr<Element> element =
- document->CreateElem(localName, nullptr, kNameSpaceID_XHTML);
- NS_ENSURE_TRUE(element, true);
+ // Wrap into current context.
+ if (!JS_WrapObject(aCx, &reflector)) {
+ return false;
+ }
- 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);
+ args.rval().setObject(*reflector);
+ return true;
+ }
+ } else {
+ nsDependentAtomString localName(definition->mLocalName);
+ element =
+ document->CreateElem(localName, nullptr, kNameSpaceID_XHTML,
+ (definition->mLocalName != typeAtom) ? &elemName
+ : nullptr);
+ NS_ENSURE_TRUE(element, false);
}
+ // The prototype setup happens in Element::WrapObject().
+
nsresult rv = nsContentUtils::WrapNative(aCx, element, element, args.rval());
NS_ENSURE_SUCCESS(rv, true);
@@ -5710,7 +5749,7 @@ nsDocument::IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject)
{
JS::Rooted<JSObject*> obj(aCx, aObject);
- if (Preferences::GetBool("dom.webcomponents.enabled")) {
+ if (nsContentUtils::IsWebComponentsEnabled()) {
return true;
}
@@ -5726,7 +5765,7 @@ nsDocument::IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject)
bool
nsDocument::IsWebComponentsEnabled(dom::NodeInfo* aNodeInfo)
{
- if (Preferences::GetBool("dom.webcomponents.enabled")) {
+ if (nsContentUtils::IsWebComponentsEnabled()) {
return true;
}
@@ -5770,6 +5809,8 @@ nsDocument::RegisterElement(JSContext* aCx, const nsAString& aType,
return;
}
+ AutoCEReaction ceReaction(this->GetDocGroup()->CustomElementReactionsStack(),
+ aCx);
// Unconditionally convert TYPE to lowercase.
nsAutoString lcType;
nsContentUtils::ASCIIToLower(aType, lcType);
@@ -6536,6 +6577,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()
{
@@ -12526,8 +12610,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()) {
@@ -12543,7 +12631,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*
@@ -12713,30 +12804,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)
{