--- a/dom/base/CustomElementRegistry.cpp
+++ b/dom/base/CustomElementRegistry.cpp
@@ -188,33 +188,35 @@ CustomElementData::Unlink()
//-----------------------------------------------------
// CustomElementRegistry
namespace {
class MOZ_RAII AutoConstructionStackEntry final
{
public:
- AutoConstructionStackEntry(nsTArray<RefPtr<nsGenericHTMLElement>>& aStack,
- nsGenericHTMLElement* aElement)
+ AutoConstructionStackEntry(nsTArray<RefPtr<Element>>& aStack,
+ Element* aElement)
: mStack(aStack)
{
+ MOZ_ASSERT(aElement->IsHTMLElement() || aElement->IsXULElement());
+
mIndex = mStack.Length();
mStack.AppendElement(aElement);
}
~AutoConstructionStackEntry()
{
MOZ_ASSERT(mIndex == mStack.Length() - 1,
"Removed element should be the last element");
mStack.RemoveElementAt(mIndex);
}
private:
- nsTArray<RefPtr<nsGenericHTMLElement>>& mStack;
+ nsTArray<RefPtr<Element>>& mStack;
uint32_t mIndex;
};
} // namespace anonymous
// Only needed for refcounted objects.
NS_IMPL_CYCLE_COLLECTION_CLASS(CustomElementRegistry)
@@ -985,18 +987,17 @@ CustomElementRegistry::Upgrade(Element*
// Step 4.
if (aElement->IsInComposedDoc()) {
nsContentUtils::EnqueueLifecycleCallback(nsIDocument::eConnected, aElement,
nullptr, nullptr, aDefinition);
}
// Step 5.
- AutoConstructionStackEntry acs(aDefinition->mConstructionStack,
- nsGenericHTMLElement::FromContent(aElement));
+ AutoConstructionStackEntry acs(aDefinition->mConstructionStack, aElement);
// Step 6 and step 7.
DoUpgrade(aElement, aDefinition->mConstructor, aRv);
if (aRv.Failed()) {
data->mState = CustomElementData::State::eFailed;
// Empty element's custom element reaction queue.
data->mReactionQueue.Clear();
return;
--- a/dom/base/CustomElementRegistry.h
+++ b/dom/base/CustomElementRegistry.h
@@ -178,17 +178,17 @@ struct CustomElementDefinition
// The prototype to use for new custom elements of this type.
JS::Heap<JSObject *> mPrototype;
// The lifecycle callbacks to call for this custom element.
UniquePtr<mozilla::dom::LifecycleCallbacks> mCallbacks;
// A construction stack. Use nullptr to represent an "already constructed marker".
- nsTArray<RefPtr<nsGenericHTMLElement>> mConstructionStack;
+ nsTArray<RefPtr<Element>> mConstructionStack;
// The document custom element order.
uint32_t mDocOrder;
bool IsCustomBuiltIn()
{
return mType != mLocalName;
}
--- a/dom/base/nsContentCreatorFunctions.h
+++ b/dom/base/nsContentCreatorFunctions.h
@@ -54,17 +54,19 @@ CreateHTMLElement(uint32_t aNodeType,
nsresult
NS_NewMathMLElement(mozilla::dom::Element** aResult,
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
#ifdef MOZ_XUL
nsresult
NS_NewXULElement(mozilla::dom::Element** aResult,
- already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
+ already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
+ mozilla::dom::FromParser aFromParser,
+ const nsAString* aIs);
void
NS_TrustedNewXULElement(nsIContent** aResult,
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
#endif
nsresult
NS_NewSVGElement(mozilla::dom::Element** aResult,
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -221,16 +221,17 @@
#include "mozilla/BloomFilter.h"
#include "TabChild.h"
#include "mozilla/dom/DocGroup.h"
#include "mozilla/dom/TabGroup.h"
#include "nsIWebNavigationInfo.h"
#include "nsPluginHost.h"
#include "mozilla/HangAnnotations.h"
#include "mozilla/Encoding.h"
+#include "nsXULElement.h"
#include "nsIBidiKeyboard.h"
#if defined(XP_WIN)
// Undefine LoadImage to prevent naming conflict with Windows.
#undef LoadImage
#endif
@@ -10136,25 +10137,206 @@ nsContentUtils::TryToUpgradeElement(Elem
} else {
// Add an unresolved custom element that is a candidate for
// upgrade when a custom element is connected to the document.
// We will make sure it's shadow-including tree order in bug 1326028.
nsContentUtils::RegisterUnresolvedElement(aElement, typeAtom);
}
}
+static void
+DoCustomElementCreate(Element** aElement, nsIDocument* aDoc, NodeInfo* aNodeInfo,
+ CustomElementConstructor* aConstructor, ErrorResult& aRv)
+{
+ RefPtr<Element> element =
+ aConstructor->Construct("Custom Element Create", aRv);
+ if (aRv.Failed()) {
+ return;
+ }
+
+ if (aNodeInfo->NamespaceEquals(kNameSpaceID_XHTML)) {
+ if (!element || !element->IsHTMLElement()) {
+ aRv.ThrowTypeError<MSG_THIS_DOES_NOT_IMPLEMENT_INTERFACE>(NS_LITERAL_STRING("HTMLElement"));
+ return;
+ }
+ } else {
+ if (!element || !element->IsXULElement()) {
+ aRv.ThrowTypeError<MSG_THIS_DOES_NOT_IMPLEMENT_INTERFACE>(NS_LITERAL_STRING("XULElement"));
+ return;
+ }
+ }
+
+ nsAtom* localName = aNodeInfo->NameAtom();
+
+ if (aDoc != element->OwnerDoc() || element->GetParentNode() ||
+ element->HasChildren() || element->GetAttrCount() ||
+ element->NodeInfo()->NameAtom() != localName) {
+ aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+ return;
+ }
+
+ element.forget(aElement);
+}
+
+/* static */ nsresult
+nsContentUtils::NewXULOrHTMLElement(Element** aResult, mozilla::dom::NodeInfo* aNodeInfo,
+ FromParser aFromParser, const nsAString* aIs,
+ mozilla::dom::CustomElementDefinition* aDefinition)
+{
+ RefPtr<mozilla::dom::NodeInfo> nodeInfo = aNodeInfo;
+ NS_ASSERTION(nodeInfo->NamespaceEquals(kNameSpaceID_XHTML) ||
+ nodeInfo->NamespaceEquals(kNameSpaceID_XUL),
+ "Can only create XUL or XHTML elements.");
+
+ nsAtom *name = nodeInfo->NameAtom();
+ RefPtr<nsAtom> tagAtom = nodeInfo->NameAtom();
+ RefPtr<nsAtom> typeAtom = aIs ? NS_Atomize(*aIs) : tagAtom;
+
+ int32_t tag = eHTMLTag_unknown;
+ if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML)) {
+ tag = nsHTMLTags::CaseSensitiveAtomTagToId(name);
+ }
+
+ nsIDocument* doc = nodeInfo->GetDocument();
+
+ // https://dom.spec.whatwg.org/#concept-create-element
+ // We only handle the "synchronous custom elements flag is set" now.
+ // For the unset case (e.g. cloning a node), see bug 1319342 for that.
+ // Step 4.
+ CustomElementDefinition* definition = aDefinition;
+ if (!definition && CustomElementRegistry::IsCustomElementEnabled()) {
+ definition =
+ nsContentUtils::LookupCustomElementDefinition(doc,
+ nodeInfo->LocalName(),
+ nodeInfo->NamespaceID(),
+ typeAtom);
+ }
+
+ // It might be a problem that parser synchronously calls constructor, so filed
+ // bug 1378079 to figure out what we should do for parser case.
+ if (definition) {
+ /*
+ * Synchronous custom elements flag is determined by 3 places in spec,
+ * 1) create an element for a token, the flag is determined by
+ * "will execute script" which is not originally created
+ * for the HTML fragment parsing algorithm.
+ * 2) createElement and createElementNS, the flag is the same as
+ * NOT_FROM_PARSER.
+ * 3) clone a node, our implementation will not go into this function.
+ * For the unset case which is non-synchronous only applied for
+ * inner/outerHTML.
+ */
+ bool synchronousCustomElements = aFromParser != dom::FROM_PARSER_FRAGMENT ||
+ aFromParser == dom::NOT_FROM_PARSER;
+ // Per discussion in https://github.com/w3c/webcomponents/issues/635,
+ // use entry global in those places that are called from JS APIs and use the
+ // node document's global object if it is called from parser.
+ nsIGlobalObject* global;
+ if (aFromParser == dom::NOT_FROM_PARSER) {
+ global = GetEntryGlobal();
+ } else {
+ global = nodeInfo->GetDocument()->GetScopeObject();
+ }
+ if (!global) {
+ // In browser chrome code, one may have access to a document which doesn't
+ // have scope object anymore.
+ return NS_ERROR_FAILURE;
+ }
+
+ AutoEntryScript aes(global, "create custom elements");
+ JSContext* cx = aes.cx();
+ ErrorResult rv;
+
+ // Step 5.
+ if (definition->IsCustomBuiltIn()) {
+ // SetupCustomElement() should be called with an element that don't have
+ // CustomElementData setup, if not we will hit the assertion in
+ // SetCustomElementData().
+ // Built-in element
+ if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML)) {
+ *aResult = CreateHTMLElement(tag, nodeInfo.forget(), aFromParser).take();
+ } else {
+ *aResult = new nsXULElement(nodeInfo.forget());
+ }
+ (*aResult)->SetCustomElementData(new CustomElementData(typeAtom));
+ if (synchronousCustomElements) {
+ CustomElementRegistry::Upgrade(*aResult, definition, rv);
+ if (rv.MaybeSetPendingException(cx)) {
+ aes.ReportException();
+ }
+ } else {
+ nsContentUtils::EnqueueUpgradeReaction(*aResult, definition);
+ }
+
+ return NS_OK;
+ }
+
+ // Step 6.1.
+ if (synchronousCustomElements) {
+ DoCustomElementCreate(aResult, doc, nodeInfo, definition->mConstructor, rv);
+ if (rv.MaybeSetPendingException(cx)) {
+ if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML)) {
+ NS_IF_ADDREF(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget(), aFromParser));
+ } else {
+ NS_IF_ADDREF(*aResult = new nsXULElement(nodeInfo.forget()));
+ }
+ }
+ return NS_OK;
+ }
+
+ // Step 6.2.
+ if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML)) {
+ NS_IF_ADDREF(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser));
+ } else {
+ NS_IF_ADDREF(*aResult = new nsXULElement(nodeInfo.forget()));
+ }
+ (*aResult)->SetCustomElementData(new CustomElementData(definition->mType));
+ nsContentUtils::EnqueueUpgradeReaction(*aResult, definition);
+ return NS_OK;
+ }
+
+ bool isCustomElementName = false;
+
+ if (nodeInfo->NamespaceEquals(kNameSpaceID_XHTML)) {
+ // Per the Custom Element specification, unknown tags that are valid custom
+ // element names should be HTMLElement instead of HTMLUnknownElement.
+ isCustomElementName = (tag == eHTMLTag_userdefined &&
+ nsContentUtils::IsCustomElementName(name));
+ if (isCustomElementName) {
+ NS_IF_ADDREF(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser));
+ } else {
+ *aResult = CreateHTMLElement(tag, nodeInfo.forget(), aFromParser).take();
+ }
+ } else {
+ isCustomElementName = nsContentUtils::IsCustomElementName(name);
+ NS_IF_ADDREF(*aResult = new nsXULElement(nodeInfo.forget()));
+ }
+
+ if (!*aResult) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (CustomElementRegistry::IsCustomElementEnabled() &&
+ (isCustomElementName || aIs)) {
+ (*aResult)->SetCustomElementData(new CustomElementData(typeAtom));
+ }
+
+ return NS_OK;
+}
+
/* static */ CustomElementDefinition*
nsContentUtils::LookupCustomElementDefinition(nsIDocument* aDoc,
const nsAString& aLocalName,
uint32_t aNameSpaceID,
nsAtom* aTypeAtom)
{
MOZ_ASSERT(aDoc);
- if (aNameSpaceID != kNameSpaceID_XHTML ||
+ if ((aNameSpaceID != kNameSpaceID_XUL &&
+ aNameSpaceID != kNameSpaceID_XHTML) ||
!aDoc->GetDocShell()) {
return nullptr;
}
nsCOMPtr<nsPIDOMWindowInner> window(aDoc->GetInnerWindow());
if (!window) {
return nullptr;
}
@@ -10283,17 +10465,18 @@ nsContentUtils::EnqueueLifecycleCallback
/* static */ void
nsContentUtils::GetCustomPrototype(nsIDocument* aDoc,
int32_t aNamespaceID,
nsAtom* aAtom,
JS::MutableHandle<JSObject*> aPrototype)
{
MOZ_ASSERT(aDoc);
- if (aNamespaceID != kNameSpaceID_XHTML ||
+ if ((aNamespaceID != kNameSpaceID_XHTML &&
+ aNamespaceID != kNameSpaceID_XUL) ||
!aDoc->GetDocShell()) {
return;
}
nsCOMPtr<nsPIDOMWindowInner> window(aDoc->GetInnerWindow());
if (!window) {
return;
}
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -15,16 +15,17 @@
#if defined(SOLARIS)
#include <ieeefp.h>
#endif
#include "js/TypeDecls.h"
#include "js/Value.h"
#include "js/RootingAPI.h"
+#include "mozilla/dom/FromParser.h"
#include "mozilla/BasicEvents.h"
#include "mozilla/EventForwards.h"
#include "mozilla/GuardObjects.h"
#include "mozilla/TaskCategory.h"
#include "mozilla/TimeStamp.h"
#include "nsContentListDeclarations.h"
#include "nsMathUtils.h"
#include "nsTArrayForwardDeclare.h"
@@ -3031,16 +3032,24 @@ public:
/**
* Try to upgrade an element.
* https://html.spec.whatwg.org/multipage/custom-elements.html#concept-try-upgrade
*/
static void TryToUpgradeElement(Element* aElement);
/**
+ * Creates a new XUL or XHTML element applying any appropriate custom element
+ * definition.
+ */
+ static nsresult NewXULOrHTMLElement(Element** aResult, mozilla::dom::NodeInfo* aNodeInfo,
+ mozilla::dom::FromParser aFromParser, const nsAString* aIs,
+ mozilla::dom::CustomElementDefinition* aDefinition);
+
+ /**
* Looking up a custom element definition.
* https://html.spec.whatwg.org/#look-up-a-custom-element-definition
*/
static mozilla::dom::CustomElementDefinition*
LookupCustomElementDefinition(nsIDocument* aDoc,
const nsAString& aLocalName,
uint32_t aNameSpaceID,
nsAtom* aTypeAtom);
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -6382,17 +6382,17 @@ nsDocument::CustomElementConstructor(JSC
}
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 =
+ nsTArray<RefPtr<Element>>& 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) {
--- a/dom/base/nsNameSpaceManager.cpp
+++ b/dom/base/nsNameSpaceManager.cpp
@@ -178,17 +178,17 @@ NS_NewElement(Element** aResult,
{
RefPtr<mozilla::dom::NodeInfo> ni = aNodeInfo;
int32_t ns = ni->NamespaceID();
if (ns == kNameSpaceID_XHTML) {
return NS_NewHTMLElement(aResult, ni.forget(), aFromParser, aIs);
}
#ifdef MOZ_XUL
if (ns == kNameSpaceID_XUL) {
- return NS_NewXULElement(aResult, ni.forget());
+ return NS_NewXULElement(aResult, ni.forget(), aFromParser, aIs);
}
#endif
if (ns == kNameSpaceID_MathML) {
// If the mathml.disabled pref. is true, convert all MathML nodes into
// disabled MathML nodes by swapping the namespace.
if (ni->NodeInfoManager()->MathMLEnabled()) {
return NS_NewMathMLElement(aResult, ni.forget());
}
--- a/dom/base/nsNodeUtils.cpp
+++ b/dom/base/nsNodeUtils.cpp
@@ -459,17 +459,17 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNod
if (aClone) {
nsresult rv = aNode->Clone(nodeInfo, getter_AddRefs(clone), aDeep);
if (NS_WARN_IF(NS_FAILED(rv))) {
aError.Throw(rv);
return nullptr;
}
if (CustomElementRegistry::IsCustomElementEnabled() &&
- clone->IsHTMLElement()) {
+ clone->IsElement()) {
// The cloned node may be a custom element that may require
// enqueing upgrade reaction.
Element* cloneElem = clone->AsElement();
RefPtr<nsAtom> tagAtom = nodeInfo->NameAtom();
CustomElementData* data = elem->GetCustomElementData();
// Check if node may be custom element by type extension.
// ex. <button is="x-button">
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -41,27 +41,29 @@
#include "mozilla/dom/CustomElementRegistry.h"
#include "mozilla/dom/DOMException.h"
#include "mozilla/dom/ElementBinding.h"
#include "mozilla/dom/HTMLObjectElement.h"
#include "mozilla/dom/HTMLObjectElementBinding.h"
#include "mozilla/dom/HTMLEmbedElement.h"
#include "mozilla/dom/HTMLElementBinding.h"
#include "mozilla/dom/HTMLEmbedElementBinding.h"
+#include "mozilla/dom/XULElementBinding.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/ResolveSystemBinding.h"
#include "mozilla/dom/WebIDLGlobalNameHash.h"
#include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/dom/WorkerScope.h"
#include "mozilla/dom/XrayExpandoClass.h"
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
#include "nsDOMClassInfo.h"
#include "ipc/ErrorIPCUtils.h"
#include "mozilla/UseCounter.h"
#include "mozilla/dom/DocGroup.h"
+#include "nsXULElement.h"
namespace mozilla {
namespace dom {
using namespace workers;
// Forward declare GetConstructorObject methods.
#define HTML_TAG(_tag, _classname, _interfacename) \
@@ -3543,33 +3545,38 @@ GetCustomElementReactionsStack(JS::Handl
if (!docGroup) {
return nullptr;
}
return docGroup->CustomElementReactionsStack();
}
// https://html.spec.whatwg.org/multipage/dom.html#htmlconstructor
-already_AddRefed<nsGenericHTMLElement>
-CreateHTMLElement(const GlobalObject& aGlobal, const JS::CallArgs& aCallArgs,
- JS::Handle<JSObject*> aGivenProto, ErrorResult& aRv)
+already_AddRefed<Element>
+CreateXULOrHTMLElement(const GlobalObject& aGlobal, const JS::CallArgs& aCallArgs,
+ JS::Handle<JSObject*> aGivenProto, ErrorResult& aRv)
{
// Step 1.
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal.GetAsSupports());
if (!window) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
nsIDocument* doc = window->GetExtantDoc();
if (!doc) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
+ int32_t ns = doc->GetDefaultNamespaceID();
+ if (ns != kNameSpaceID_XUL) {
+ ns = kNameSpaceID_XHTML;
+ }
+
RefPtr<mozilla::dom::CustomElementRegistry> registry(window->CustomElements());
if (!registry) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
// Step 2 is in the code output by CGClassConstructor.
// Step 3.
@@ -3592,31 +3599,44 @@ CreateHTMLElement(const GlobalObject& aG
// And the actual callee might be in different compartment, so enter its
// compartment before getting the standard constructor object to compare to,
// so we get it from the same global as callee itself.
JSAutoCompartment ac(cx, callee);
int32_t tag = eHTMLTag_userdefined;
if (!definition->IsCustomBuiltIn()) {
// Step 4.
// If the definition is for an autonomous custom element, the active
- // function should be HTMLElement.
- JS::Rooted<JSObject*> constructor(cx, HTMLElementBinding::GetConstructorObject(cx));
+ // function should be HTMLElement or XULElement
+ JS::Rooted<JSObject*> constructor(cx);
+ if (ns == kNameSpaceID_XUL) {
+ constructor = XULElementBinding::GetConstructorObject(cx);
+ } else {
+ constructor = HTMLElementBinding::GetConstructorObject(cx);
+ }
+
if (!constructor) {
aRv.NoteJSContextException(cx);
return nullptr;
}
if (callee != constructor) {
aRv.ThrowTypeError<MSG_ILLEGAL_CONSTRUCTOR>();
return nullptr;
}
} else {
// Step 5.
// If the definition is for a customized built-in element, the localName
// should be defined in the specification.
+
+ // Customized built-in elements are not supported for XUL yet.
+ if (ns == kNameSpaceID_XUL) {
+ aRv.Throw(NS_ERROR_UNEXPECTED);
+ return nullptr;
+ }
+
tag = nsHTMLTags::CaseSensitiveAtomTagToId(definition->mLocalName);
if (tag == eHTMLTag_userdefined) {
aRv.ThrowTypeError<MSG_ILLEGAL_CONSTRUCTOR>();
return nullptr;
}
MOZ_ASSERT(tag <= NS_HTML_TAG_MAX, "tag is out of bounds");
@@ -3638,47 +3658,51 @@ CreateHTMLElement(const GlobalObject& aG
aRv.ThrowTypeError<MSG_ILLEGAL_CONSTRUCTOR>();
return nullptr;
}
}
RefPtr<mozilla::dom::NodeInfo> nodeInfo =
doc->NodeInfoManager()->GetNodeInfo(definition->mLocalName,
nullptr,
- kNameSpaceID_XHTML,
+ ns,
nsIDOMNode::ELEMENT_NODE);
if (!nodeInfo) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
// Step 6 and Step 7 are in the code output by CGClassConstructor.
// Step 8.
- nsTArray<RefPtr<nsGenericHTMLElement>>& constructionStack =
+ nsTArray<RefPtr<Element>>& constructionStack =
definition->mConstructionStack;
if (constructionStack.IsEmpty()) {
- RefPtr<nsGenericHTMLElement> newElement;
- if (tag == eHTMLTag_userdefined) {
- // Autonomous custom element.
- newElement = NS_NewHTMLElement(nodeInfo.forget());
+ RefPtr<Element> newElement;
+ if (ns == kNameSpaceID_XUL) {
+ newElement = new nsXULElement(nodeInfo.forget());
} else {
- // Customized built-in element.
- newElement = CreateHTMLElement(tag, nodeInfo.forget(), NOT_FROM_PARSER);
+ if (tag == eHTMLTag_userdefined) {
+ // Autonomous custom element.
+ newElement = NS_NewHTMLElement(nodeInfo.forget());
+ } else {
+ // Customized built-in element.
+ newElement = CreateHTMLElement(tag, nodeInfo.forget(), NOT_FROM_PARSER);
+ }
}
newElement->SetCustomElementData(
new CustomElementData(definition->mType, CustomElementData::State::eCustom));
newElement->SetCustomElementDefinition(definition);
return newElement.forget();
}
// Step 9.
- RefPtr<nsGenericHTMLElement>& element = constructionStack.LastElement();
+ RefPtr<Element>& element = constructionStack.LastElement();
// Step 10.
if (element == ALEADY_CONSTRUCTED_MARKER) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return nullptr;
}
// Step 11.
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -3386,21 +3386,21 @@ GetDesiredProto(JSContext* aCx, const JS
// Get the CustomElementReactionsStack for the docgroup of the global
// of the underlying object of aObj. This can be null if aObj can't
// be CheckUnwrapped, or if the global of the result has no docgroup
// (e.g. because it's not a Window global).
CustomElementReactionsStack*
GetCustomElementReactionsStack(JS::Handle<JSObject*> aObj);
// This function is expected to be called from the constructor function for an
-// HTML element interface; the global/callargs need to be whatever was passed to
-// that constructor function.
-already_AddRefed<nsGenericHTMLElement>
-CreateHTMLElement(const GlobalObject& aGlobal, const JS::CallArgs& aCallArgs,
- JS::Handle<JSObject*> aGivenProto, ErrorResult& aRv);
+// HTML or XUL element interface; the global/callargs need to be whatever was
+// passed to that constructor function.
+already_AddRefed<Element>
+CreateXULOrHTMLElement(const GlobalObject& aGlobal, const JS::CallArgs& aCallArgs,
+ JS::Handle<JSObject*> aGivenProto, ErrorResult& aRv);
void
SetDocumentAndPageUseCounter(JSObject* aObject, UseCounter aUseCounter);
// Warnings
void
DeprecationWarning(JSContext* aCx, JSObject* aObject,
nsIDocument::DeprecatedOperations aOperation);
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -1902,21 +1902,21 @@ class CGClassConstructor(CGAbstractStati
ctorName=ctorName,
htmlConstructorSanityCheck=htmlConstructorSanityCheck,
htmlConstructorFallback=htmlConstructorFallback)
if self._ctor.isHTMLConstructor():
signatures = self._ctor.signatures()
assert len(signatures) == 1
# Given that HTMLConstructor takes no args, we can just codegen a
- # call to CreateHTMLElement() in BindingUtils which reuses the
+ # call to CreateXULOrHTMLElement() in BindingUtils which reuses the
# factory thing in HTMLContentSink. Then we don't have to implement
# Constructor on all the HTML elements.
callGenerator = CGPerSignatureCall(signatures[0][0], signatures[0][1],
- "CreateHTMLElement", True,
+ "CreateXULOrHTMLElement", True,
self.descriptor, self._ctor,
isConstructor=True)
else:
name = self._ctor.identifier.name
nativeName = MakeNativeName(self.descriptor.binaryNameFor(name))
callGenerator = CGMethodCall(nativeName, True, self.descriptor,
self._ctor, isConstructor=True,
constructorName=ctorName)
--- a/dom/html/nsHTMLContentSink.cpp
+++ b/dom/html/nsHTMLContentSink.cpp
@@ -219,165 +219,27 @@ public:
nsIContent *Add(nsIContent *child);
};
Node* mStack;
int32_t mStackSize;
int32_t mStackPos;
};
-static void
-DoCustomElementCreate(Element** aElement, nsIDocument* aDoc, nsAtom* aLocalName,
- CustomElementConstructor* aConstructor, ErrorResult& aRv)
-{
- RefPtr<Element> element =
- aConstructor->Construct("Custom Element Create", aRv);
- if (aRv.Failed()) {
- return;
- }
-
- if (!element || !element->IsHTMLElement()) {
- aRv.ThrowTypeError<MSG_THIS_DOES_NOT_IMPLEMENT_INTERFACE>(NS_LITERAL_STRING("HTMLElement"));
- return;
- }
-
- if (aDoc != element->OwnerDoc() || element->GetParentNode() ||
- element->HasChildren() || element->GetAttrCount() ||
- element->NodeInfo()->NameAtom() != aLocalName) {
- aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
- return;
- }
-
- element.forget(aElement);
-}
-
nsresult
NS_NewHTMLElement(Element** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
FromParser aFromParser, const nsAString* aIs,
mozilla::dom::CustomElementDefinition* aDefinition)
{
- *aResult = nullptr;
-
RefPtr<mozilla::dom::NodeInfo> nodeInfo = aNodeInfo;
- nsAtom *name = nodeInfo->NameAtom();
- RefPtr<nsAtom> tagAtom = nodeInfo->NameAtom();
- RefPtr<nsAtom> typeAtom = aIs ? NS_Atomize(*aIs) : tagAtom;
-
NS_ASSERTION(nodeInfo->NamespaceEquals(kNameSpaceID_XHTML),
- "Trying to HTML elements that don't have the XHTML namespace");
-
- int32_t tag = nsHTMLTags::CaseSensitiveAtomTagToId(name);
-
- // https://dom.spec.whatwg.org/#concept-create-element
- // We only handle the "synchronous custom elements flag is set" now.
- // For the unset case (e.g. cloning a node), see bug 1319342 for that.
- // Step 4.
- CustomElementDefinition* definition = aDefinition;
- if (!definition && CustomElementRegistry::IsCustomElementEnabled()) {
- definition =
- nsContentUtils::LookupCustomElementDefinition(nodeInfo->GetDocument(),
- nodeInfo->LocalName(),
- nodeInfo->NamespaceID(),
- typeAtom);
- }
-
- // It might be a problem that parser synchronously calls constructor, so filed
- // bug 1378079 to figure out what we should do for parser case.
- if (definition) {
- /*
- * Synchronous custom elements flag is determined by 3 places in spec,
- * 1) create an element for a token, the flag is determined by
- * "will execute script" which is not originally created
- * for the HTML fragment parsing algorithm.
- * 2) createElement and createElementNS, the flag is the same as
- * NOT_FROM_PARSER.
- * 3) clone a node, our implementation will not go into this function.
- * For the unset case which is non-synchronous only applied for
- * inner/outerHTML.
- */
- bool synchronousCustomElements = aFromParser != dom::FROM_PARSER_FRAGMENT ||
- aFromParser == dom::NOT_FROM_PARSER;
- // Per discussion in https://github.com/w3c/webcomponents/issues/635,
- // use entry global in those places that are called from JS APIs and use the
- // node document's global object if it is called from parser.
- nsIGlobalObject* global;
- if (aFromParser == dom::NOT_FROM_PARSER) {
- global = GetEntryGlobal();
- } else {
- global = nodeInfo->GetDocument()->GetScopeObject();
- }
- if (!global) {
- // In browser chrome code, one may have access to a document which doesn't
- // have scope object anymore.
- return NS_ERROR_FAILURE;
- }
-
- AutoEntryScript aes(global, "create custom elements");
- JSContext* cx = aes.cx();
- ErrorResult rv;
+ "Trying to create HTML elements that don't have the XHTML namespace");
- // Step 5.
- if (definition->IsCustomBuiltIn()) {
- // SetupCustomElement() should be called with an element that don't have
- // CustomElementData setup, if not we will hit the assertion in
- // SetCustomElementData().
- // Built-in element
- *aResult = CreateHTMLElement(tag, nodeInfo.forget(), aFromParser).take();
- (*aResult)->SetCustomElementData(new CustomElementData(typeAtom));
- if (synchronousCustomElements) {
- CustomElementRegistry::Upgrade(*aResult, definition, rv);
- if (rv.MaybeSetPendingException(cx)) {
- aes.ReportException();
- }
- } else {
- nsContentUtils::EnqueueUpgradeReaction(*aResult, definition);
- }
-
- return NS_OK;
- }
-
- // Step 6.1.
- if (synchronousCustomElements) {
- DoCustomElementCreate(aResult, nodeInfo->GetDocument(),
- nodeInfo->NameAtom(),
- definition->mConstructor, rv);
- if (rv.MaybeSetPendingException(cx)) {
- NS_IF_ADDREF(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget(), aFromParser));
- }
- return NS_OK;
- }
-
- // Step 6.2.
- NS_IF_ADDREF(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser));
- (*aResult)->SetCustomElementData(new CustomElementData(definition->mType));
- nsContentUtils::EnqueueUpgradeReaction(*aResult, definition);
- return NS_OK;
- }
-
- // Per the Custom Element specification, unknown tags that are valid custom
- // element names should be HTMLElement instead of HTMLUnknownElement.
- bool isCustomElementName = (tag == eHTMLTag_userdefined &&
- nsContentUtils::IsCustomElementName(name));
- if (isCustomElementName) {
- NS_IF_ADDREF(*aResult = NS_NewHTMLElement(nodeInfo.forget(), aFromParser));
- } else {
- *aResult = CreateHTMLElement(tag, nodeInfo.forget(), aFromParser).take();
- }
-
- if (!*aResult) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- if (CustomElementRegistry::IsCustomElementEnabled() &&
- (isCustomElementName || aIs)) {
- (*aResult)->SetCustomElementData(new CustomElementData(typeAtom));
- }
-
- return NS_OK;
+ return nsContentUtils::NewXULOrHTMLElement(aResult, nodeInfo, aFromParser, aIs, aDefinition);
}
already_AddRefed<nsGenericHTMLElement>
CreateHTMLElement(uint32_t aNodeType,
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
FromParser aFromParser)
{
NS_ASSERTION(aNodeType <= NS_HTML_TAG_MAX ||
--- a/dom/tests/mochitest/webcomponents/chrome.ini
+++ b/dom/tests/mochitest/webcomponents/chrome.ini
@@ -5,9 +5,10 @@ support-files =
[test_custom_element_htmlconstructor_chrome.html]
skip-if = os == 'android' # bug 1323645
support-files =
htmlconstructor_autonomous_tests.js
htmlconstructor_builtin_tests.js
[test_custom_element_upgrade_chrome.html]
support-files =
test_upgrade_page.html
- upgrade_tests.js
\ No newline at end of file
+ upgrade_tests.js
+[test_xul_custom_element.xul]
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/webcomponents/test_xul_custom_element.xul
@@ -0,0 +1,68 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
+
+<window title="XUL Custom Elements"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ onload="runTest();">
+ <title>XUL Custom Elements</title>
+
+ <script type="application/javascript"
+ src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+ <script type="application/javascript">
+ <![CDATA[
+ SimpleTest.waitForExplicitFinish();
+
+ class TestCustomElement extends XULElement {
+ constructor() {
+ super();
+ }
+
+ connectedCallback() {
+ this.textContent = "foo";
+ }
+ }
+
+ customElements.define("test-custom-element", TestCustomElement);
+
+ function runTest() {
+ const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+
+ let element = document.createElementNS(XUL_NS, "test-custom-element");
+ document.querySelector("#content").appendChild(element);
+ is(element.textContent, "foo", "Should have set the textContent");
+ ok(element instanceof TestCustomElement, "Should be an instance of TestCustomElement");
+
+ let element2 = element.cloneNode(false);
+ is(element2.textContent, "", "Shouldn't have cloned the textContent");
+ document.querySelector("#content").appendChild(element2);
+ is(element2.textContent, "foo", "Should have set the textContent");
+ ok(element2 instanceof TestCustomElement, "Should be an instance of TestCustomElement");
+
+ let element3 = new TestCustomElement();
+ is(element3.localName, "test-custom-element", "Should see the right tag");
+ is(element3.textContent, "", "Shouldn't have been inserted yet");
+ is(element3.namespaceURI, XUL_NS, "Should have set the right namespace");
+ document.querySelector("#content").appendChild(element3);
+ is(element3.textContent, "foo", "Should have set the textContent");
+ ok(element3 instanceof TestCustomElement, "Should be an instance of TestCustomElement");
+
+ let element4 = document.getElementById("element4");
+ is(element4.textContent, "foo",
+ "Parser should have instantiated the custom element.");
+ ok(element4 instanceof TestCustomElement, "Should be an instance of TestCustomElement");
+
+ SimpleTest.finish();
+ }
+ ]]>
+ </script>
+
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <p id="display"></p>
+ <div id="content" style="display: none">
+ <test-custom-element id="element4" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"/>
+ </div>
+ <pre id="test"></pre>
+ </body>
+</window>
--- a/dom/webidl/XULElement.webidl
+++ b/dom/webidl/XULElement.webidl
@@ -3,17 +3,17 @@
* 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/.
*/
interface XULControllers;
interface MozRDFCompositeDataSource;
interface MozRDFResource;
-[Func="IsChromeOrXBL"]
+[HTMLConstructor, Func="IsChromeOrXBL"]
interface XULElement : Element {
// Layout properties
[SetterThrows]
attribute DOMString align;
[SetterThrows]
attribute DOMString dir;
[SetterThrows]
attribute DOMString flex;
--- a/dom/xbl/nsXBLService.cpp
+++ b/dom/xbl/nsXBLService.cpp
@@ -1025,16 +1025,21 @@ nsXBLService::FetchBindingDocument(nsICo
if (IsChromeOrResourceURI(aDocumentURI))
aForceSyncLoad = true;
// Create document and contentsink and set them up.
nsCOMPtr<nsIDocument> doc;
rv = NS_NewXMLDocument(getter_AddRefs(doc));
NS_ENSURE_SUCCESS(rv, rv);
+ // XBL documents must allow XUL and XBL elements in them but the usual check
+ // only checks if the document is loaded in the system principal which is
+ // sometimes not the case.
+ doc->ForceEnableXULXBL();
+
// Set the style backend type before loading the XBL document. Assume
// gecko if there's no bound document.
doc->SetStyleBackendType(aBoundDocument ? aBoundDocument->GetStyleBackendType()
: StyleBackendType::Gecko);
nsCOMPtr<nsIXMLContentSink> xblSink;
rv = NS_NewXBLContentSink(getter_AddRefs(xblSink), doc, aDocumentURI, nullptr);
NS_ENSURE_SUCCESS(rv, rv);
--- a/dom/xml/XMLDocument.cpp
+++ b/dom/xml/XMLDocument.cpp
@@ -231,16 +231,22 @@ NS_NewXBLDocument(nsIDOMDocument** aInst
NS_LITERAL_STRING("http://www.mozilla.org/xbl"),
NS_LITERAL_STRING("bindings"), nullptr,
aDocumentURI, aBaseURI, aPrincipal, false,
nullptr, DocumentFlavorLegacyGuess,
aStyleBackend);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDocument> idoc = do_QueryInterface(*aInstancePtrResult);
+
+ // XBL documents must allow XUL and XBL elements in them but the usual check
+ // only checks if the document is loaded in the system principal which is
+ // sometimes not the case.
+ idoc->ForceEnableXULXBL();
+
nsDocument* doc = static_cast<nsDocument*>(idoc.get());
doc->SetLoadedAsInteractiveData(true);
doc->SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE);
return NS_OK;
}
namespace mozilla {
--- a/dom/xul/moz.build
+++ b/dom/xul/moz.build
@@ -15,16 +15,17 @@ if CONFIG['MOZ_XUL']:
DIRS += ['templates']
XPIDL_SOURCES += [
'nsIXULOverlayProvider.idl',
]
EXPORTS += [
'nsIXULDocument.h',
+ 'nsXULElement.h',
]
UNIFIED_SOURCES += [
'nsXULCommandDispatcher.cpp',
'nsXULContentSink.cpp',
'nsXULElement.cpp',
'nsXULPopupListener.cpp',
'nsXULPrototypeCache.cpp',
--- a/dom/xul/nsXULElement.cpp
+++ b/dom/xul/nsXULElement.cpp
@@ -181,18 +181,22 @@ nsXULElement::MaybeUpdatePrivateLifetime
}
/* static */
already_AddRefed<nsXULElement>
nsXULElement::Create(nsXULPrototypeElement* aPrototype, mozilla::dom::NodeInfo *aNodeInfo,
bool aIsScriptable, bool aIsRoot)
{
RefPtr<mozilla::dom::NodeInfo> ni = aNodeInfo;
- RefPtr<nsXULElement> element = new nsXULElement(ni.forget());
- if (element) {
+ nsCOMPtr<Element> baseElement;
+ NS_NewXULElement(getter_AddRefs(baseElement), ni.forget(), dom::FROM_PARSER_NETWORK, nullptr);
+
+ if (baseElement) {
+ nsXULElement* element = FromContent(baseElement);
+
if (aPrototype->mHasIdAttribute) {
element->SetHasID();
}
if (aPrototype->mHasClassAttribute) {
element->SetMayHaveClass();
}
if (aPrototype->mHasStyleAttribute) {
element->SetMayHaveStyle();
@@ -211,19 +215,21 @@ nsXULElement::Create(nsXULPrototypeEleme
if (aIsRoot && aPrototype->mNodeInfo->Equals(nsGkAtoms::window)) {
for (uint32_t i = 0; i < aPrototype->mNumAttributes; ++i) {
if (aPrototype->mAttributes[i].mName.Equals(nsGkAtoms::windowtype)) {
element->MaybeUpdatePrivateLifetime();
}
}
}
+
+ return baseElement.forget().downcast<nsXULElement>();
}
- return element.forget();
+ return nullptr;
}
nsresult
nsXULElement::Create(nsXULPrototypeElement* aPrototype,
nsIDocument* aDocument,
bool aIsScriptable,
bool aIsRoot,
Element** aResult)
@@ -250,30 +256,32 @@ nsXULElement::Create(nsXULPrototypeEleme
RefPtr<nsXULElement> element = Create(aPrototype, nodeInfo,
aIsScriptable, aIsRoot);
element.forget(aResult);
return NS_OK;
}
nsresult
-NS_NewXULElement(Element** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
+NS_NewXULElement(Element** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
+ FromParser aFromParser, const nsAString* aIs)
{
- RefPtr<mozilla::dom::NodeInfo> ni = aNodeInfo;
-
- NS_PRECONDITION(ni, "need nodeinfo for non-proto Create");
-
- nsIDocument* doc = ni->GetDocument();
+ RefPtr<mozilla::dom::NodeInfo> nodeInfo = aNodeInfo;
+
+ NS_PRECONDITION(nodeInfo, "need nodeinfo for non-proto Create");
+
+ NS_ASSERTION(nodeInfo->NamespaceEquals(kNameSpaceID_XUL),
+ "Trying to create XUL elements that don't have the XUL namespace");
+
+ nsIDocument* doc = nodeInfo->GetDocument();
if (doc && !doc->AllowXULXBL()) {
return NS_ERROR_NOT_AVAILABLE;
}
- NS_ADDREF(*aResult = new nsXULElement(ni.forget()));
-
- return NS_OK;
+ return nsContentUtils::NewXULOrHTMLElement(aResult, nodeInfo, aFromParser, aIs, nullptr);
}
void
NS_TrustedNewXULElement(nsIContent** aResult,
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
{
RefPtr<mozilla::dom::NodeInfo> ni = aNodeInfo;
NS_PRECONDITION(ni, "need nodeinfo for non-proto Create");
--- a/dom/xul/nsXULElement.h
+++ b/dom/xul/nsXULElement.h
@@ -35,16 +35,17 @@
#include "nsFrameLoader.h" // Needed because we return an
// already_AddRefed<nsFrameLoader> where bindings
// want an already_AddRefed<nsIFrameLoader> and hence
// bindings need to know that the former can cast to
// the latter.
#include "mozilla/dom/DOMRect.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/DOMString.h"
+#include "mozilla/dom/FromParser.h"
class nsIDocument;
class nsXULPrototypeDocument;
class nsIObjectInputStream;
class nsIObjectOutputStream;
class nsIOffThreadScriptReceiver;
class nsXULPrototypeNode;
@@ -794,17 +795,18 @@ protected:
nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
return slots ? slots->mControllers.get() : nullptr;
}
void UnregisterAccessKey(const nsAString& aOldValue);
bool BoolAttrIsTrue(nsAtom* aName) const;
friend nsresult
- NS_NewXULElement(mozilla::dom::Element** aResult, mozilla::dom::NodeInfo *aNodeInfo);
+ NS_NewXULElement(mozilla::dom::Element** aResult, mozilla::dom::NodeInfo *aNodeInfo,
+ mozilla::dom::FromParser aFromParser, const nsAString* aIs);
friend void
NS_TrustedNewXULElement(nsIContent** aResult, mozilla::dom::NodeInfo *aNodeInfo);
static already_AddRefed<nsXULElement>
Create(nsXULPrototypeElement* aPrototype, mozilla::dom::NodeInfo *aNodeInfo,
bool aIsScriptable, bool aIsRoot);
bool IsReadWriteTextElement() const
--- a/layout/xul/nsDocElementBoxFrame.cpp
+++ b/layout/xul/nsDocElementBoxFrame.cpp
@@ -16,16 +16,17 @@
#include "nsStackLayout.h"
#include "nsIAnonymousContentCreator.h"
#include "mozilla/dom/NodeInfo.h"
#include "nsIServiceManager.h"
#include "nsNodeInfoManager.h"
#include "nsContentCreatorFunctions.h"
#include "nsContentUtils.h"
#include "mozilla/dom/Element.h"
+#include "mozilla/dom/FromParser.h"
//#define DEBUG_REFLOW
using namespace mozilla::dom;
class nsDocElementBoxFrame final : public nsBoxFrame
, public nsIAnonymousContentCreator
{
@@ -93,29 +94,31 @@ nsDocElementBoxFrame::CreateAnonymousCon
// create the top-secret popupgroup node. shhhhh!
RefPtr<NodeInfo> nodeInfo;
nodeInfo = nodeInfoManager->GetNodeInfo(nsGkAtoms::popupgroup,
nullptr, kNameSpaceID_XUL,
nsIDOMNode::ELEMENT_NODE);
NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
nsresult rv = NS_NewXULElement(getter_AddRefs(mPopupgroupContent),
- nodeInfo.forget());
+ nodeInfo.forget(), dom::NOT_FROM_PARSER,
+ nullptr);
NS_ENSURE_SUCCESS(rv, rv);
if (!aElements.AppendElement(mPopupgroupContent))
return NS_ERROR_OUT_OF_MEMORY;
// create the top-secret default tooltip node. shhhhh!
nodeInfo = nodeInfoManager->GetNodeInfo(nsGkAtoms::tooltip, nullptr,
kNameSpaceID_XUL,
nsIDOMNode::ELEMENT_NODE);
NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
- rv = NS_NewXULElement(getter_AddRefs(mTooltipContent), nodeInfo.forget());
+ rv = NS_NewXULElement(getter_AddRefs(mTooltipContent), nodeInfo.forget(),
+ dom::NOT_FROM_PARSER, nullptr);
NS_ENSURE_SUCCESS(rv, rv);
mTooltipContent->SetAttr(kNameSpaceID_None, nsGkAtoms::_default,
NS_LITERAL_STRING("true"), false);
if (!aElements.AppendElement(mTooltipContent))
return NS_ERROR_OUT_OF_MEMORY;