mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-08-15 08:53:07 +09:00
Bug 1378079 - Part 3: Complete the steps related to custom elements in "create an element for a token".
With fixup for missing header due to unified builds. Tag UXP Issue #1344
This commit is contained in:
parent
ed18cbb741
commit
5d26d32825
8 changed files with 203 additions and 141 deletions
|
|
@ -1044,8 +1044,12 @@ CustomElementReactionsStack::PopAndInvokeElementQueue()
|
|||
// element, see https://github.com/w3c/webcomponents/issues/635.
|
||||
// We usually report the error to entry global in gecko, so just follow the
|
||||
// same behavior here.
|
||||
// This may be null if it's called from parser, see the case of
|
||||
// attributeChangedCallback in
|
||||
// https://html.spec.whatwg.org/multipage/parsing.html#create-an-element-for-the-token
|
||||
// In that case, the exception of callback reactions will be automatically
|
||||
// reported in CallSetup.
|
||||
nsIGlobalObject* global = GetEntryGlobal();
|
||||
MOZ_ASSERT(global, "Should always have a entry global here!");
|
||||
InvokeReactions(elementQueue, global);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ namespace mozilla {
|
|||
namespace dom {
|
||||
class Element;
|
||||
class NodeInfo;
|
||||
struct CustomElementDefinition;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
@ -41,7 +42,8 @@ nsresult
|
|||
NS_NewHTMLElement(mozilla::dom::Element** aResult,
|
||||
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
|
||||
mozilla::dom::FromParser aFromParser,
|
||||
const nsAString* aIs = nullptr);
|
||||
const nsAString* aIs = nullptr,
|
||||
mozilla::dom::CustomElementDefinition* aDefinition = nullptr);
|
||||
|
||||
// First argument should be nsHTMLTag, but that adds dependency to parser
|
||||
// for a bunch of files.
|
||||
|
|
|
|||
|
|
@ -255,7 +255,8 @@ DoCustomElementCreate(Element** aElement, nsIDocument* aDoc, nsIAtom* aLocalName
|
|||
|
||||
nsresult
|
||||
NS_NewHTMLElement(Element** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
|
||||
FromParser aFromParser, const nsAString* aIs)
|
||||
FromParser aFromParser, const nsAString* aIs,
|
||||
mozilla::dom::CustomElementDefinition* aDefinition)
|
||||
{
|
||||
*aResult = nullptr;
|
||||
|
||||
|
|
@ -276,8 +277,8 @@ NS_NewHTMLElement(Element** aResult, already_AddRefed<mozilla::dom::NodeInfo>&&
|
|||
// 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 = nullptr;
|
||||
if (CustomElementRegistry::IsCustomElementEnabled()) {
|
||||
CustomElementDefinition* definition = aDefinition;
|
||||
if (!definition && CustomElementRegistry::IsCustomElementEnabled()) {
|
||||
definition =
|
||||
nsContentUtils::LookupCustomElementDefinition(nodeInfo->GetDocument(),
|
||||
nodeInfo->LocalName(),
|
||||
|
|
@ -302,9 +303,20 @@ NS_NewHTMLElement(Element** aResult, already_AddRefed<mozilla::dom::NodeInfo>&&
|
|||
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.
|
||||
nsIGlobalObject* global = GetEntryGlobal();
|
||||
MOZ_ASSERT(global);
|
||||
// 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;
|
||||
|
|
@ -344,6 +356,7 @@ NS_NewHTMLElement(Element** aResult, already_AddRefed<mozilla::dom::NodeInfo>&&
|
|||
|
||||
// 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ support-files =
|
|||
[test_content_element.html]
|
||||
[test_custom_element_adopt_callbacks.html]
|
||||
[test_custom_element_callback_innerhtml.html]
|
||||
skip-if = true # disabled - See bug 1390396
|
||||
[test_custom_element_clone_callbacks_extended.html]
|
||||
[test_custom_element_htmlconstructor.html]
|
||||
skip-if = os == 'android' # bug 1323645
|
||||
|
|
@ -20,6 +21,7 @@ support-files =
|
|||
[test_custom_element_in_shadow.html]
|
||||
skip-if = true || stylo # disabled - See bug 1390396 and 1293844
|
||||
[test_custom_element_register_invalid_callbacks.html]
|
||||
[test_custom_element_throw_on_dynamic_markup_insertion.html]
|
||||
[test_custom_element_get.html]
|
||||
[test_custom_element_when_defined.html]
|
||||
[test_nested_content_element.html]
|
||||
|
|
@ -31,7 +33,6 @@ skip-if = true || stylo # disabled - See bug 1390396 and 1293844
|
|||
[test_document_adoptnode.html]
|
||||
[test_document_importnode.html]
|
||||
[test_document_register.html]
|
||||
[test_document_register_base_queue.html]
|
||||
[test_document_register_lifecycle.html]
|
||||
skip-if = true # disabled - See bug 1390396
|
||||
[test_document_register_parser.html]
|
||||
|
|
|
|||
|
|
@ -1,48 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=783129
|
||||
-->
|
||||
<head>
|
||||
<title>Test for document.registerElement lifecycle callback</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<script>
|
||||
var p = Object.create(HTMLElement.prototype);
|
||||
|
||||
var createdCallbackCallCount = 0;
|
||||
|
||||
// By the time the base element queue is processed via the microtask,
|
||||
// both x-hello elements should be in the document.
|
||||
p.createdCallback = function() {
|
||||
var one = document.getElementById("one");
|
||||
var two = document.getElementById("two");
|
||||
isnot(one, null, "First x-hello element should be in the tree.");
|
||||
isnot(two, null, "Second x-hello element should be in the tree.");
|
||||
createdCallbackCallCount++;
|
||||
if (createdCallbackCallCount == 2) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
if (createdCallbackCallCount > 2) {
|
||||
ok(false, "Created callback called too much.");
|
||||
}
|
||||
};
|
||||
|
||||
p.attributeChangedCallback = function(name, oldValue, newValue) {
|
||||
ok(false, "Attribute changed callback should not be called because callbacks should not be queued until created callback invoked.");
|
||||
};
|
||||
|
||||
document.registerElement("x-hello", { prototype: p });
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=783129">Bug 783129</a>
|
||||
<x-hello id="one"></x-hello>
|
||||
<x-hello id="two"></x-hello>
|
||||
<script>
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -11,7 +11,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=783129
|
|||
|
||||
var extendedButtonProto = Object.create(HTMLButtonElement.prototype);
|
||||
var buttonCallbackCalled = false;
|
||||
extendedButtonProto.createdCallback = function() {
|
||||
extendedButtonProto.connectedCallback = function() {
|
||||
is(buttonCallbackCalled, false, "created callback for x-button should only be called once.");
|
||||
is(this.tagName, "BUTTON", "Only the <button> element should be upgraded.");
|
||||
buttonCallbackCalled = true;
|
||||
|
|
@ -21,7 +21,7 @@ document.registerElement("x-button", { prototype: extendedButtonProto, extends:
|
|||
|
||||
var divProto = Object.create(HTMLDivElement.prototype);
|
||||
var divCallbackCalled = false;
|
||||
divProto.createdCallback = function() {
|
||||
divProto.connectedCallback = function() {
|
||||
is(divCallbackCalled, false, "created callback for x-div should only be called once.");
|
||||
is(buttonCallbackCalled, true, "crated callback should be called for x-button before x-div.");
|
||||
is(this.tagName, "X-DIV", "Only the <x-div> element should be upgraded.");
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "nsIFormControl.h"
|
||||
#include "nsIStyleSheetLinkingElement.h"
|
||||
#include "nsIDOMDocumentType.h"
|
||||
#include "DocGroup.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsIMutationObserver.h"
|
||||
|
|
@ -74,6 +75,29 @@ class MOZ_STACK_CLASS nsHtml5OtherDocUpdate {
|
|||
nsCOMPtr<nsIDocument> mDocument;
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper class to temporary break out of the document update batch. Use this
|
||||
* with caution as this will cause blocked scripts to run.
|
||||
*/
|
||||
class MOZ_RAII mozAutoPauseContentUpdate final
|
||||
{
|
||||
public:
|
||||
explicit mozAutoPauseContentUpdate(nsIDocument* aDocument)
|
||||
: mDocument(aDocument)
|
||||
{
|
||||
MOZ_ASSERT(mDocument);
|
||||
mDocument->EndUpdate(UPDATE_CONTENT_MODEL);
|
||||
}
|
||||
|
||||
~mozAutoPauseContentUpdate()
|
||||
{
|
||||
mDocument->BeginUpdate(UPDATE_CONTENT_MODEL);
|
||||
}
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIDocument> mDocument;
|
||||
};
|
||||
|
||||
nsHtml5TreeOperation::nsHtml5TreeOperation()
|
||||
: mOpCode(eTreeOpUninitialized)
|
||||
{
|
||||
|
|
@ -332,6 +356,41 @@ nsHtml5TreeOperation::AddAttributes(nsIContent* aNode,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsHtml5TreeOperation::SetHTMLElementAttributes(dom::Element* aElement,
|
||||
nsIAtom* aName,
|
||||
nsHtml5HtmlAttributes* aAttributes)
|
||||
{
|
||||
int32_t len = aAttributes->getLength();
|
||||
for (int32_t i = 0; i < len; i++) {
|
||||
// prefix doesn't need regetting. it is always null or a static atom
|
||||
// local name is never null
|
||||
nsCOMPtr<nsIAtom> localName =
|
||||
Reget(aAttributes->getLocalNameNoBoundsCheck(i));
|
||||
nsCOMPtr<nsIAtom> prefix = aAttributes->getPrefixNoBoundsCheck(i);
|
||||
int32_t nsuri = aAttributes->getURINoBoundsCheck(i);
|
||||
|
||||
nsString value; // Not Auto, because using it to hold nsStringBuffer*
|
||||
aAttributes->getValueNoBoundsCheck(i).ToString(value);
|
||||
if (nsHtml5Atoms::a == aName && nsHtml5Atoms::name == localName) {
|
||||
// This is an HTML5-incompliant Geckoism.
|
||||
// Remove when fixing bug 582361
|
||||
NS_ConvertUTF16toUTF8 cname(value);
|
||||
NS_ConvertUTF8toUTF16 uv(nsUnescape(cname.BeginWriting()));
|
||||
aElement->SetAttr(nsuri,
|
||||
localName,
|
||||
prefix,
|
||||
uv,
|
||||
false);
|
||||
} else {
|
||||
aElement->SetAttr(nsuri,
|
||||
localName,
|
||||
prefix,
|
||||
value,
|
||||
false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsIContent*
|
||||
nsHtml5TreeOperation::CreateHTMLElement(
|
||||
|
|
@ -351,106 +410,133 @@ nsHtml5TreeOperation::CreateHTMLElement(
|
|||
RefPtr<dom::NodeInfo> nodeInfo = aNodeInfoManager->GetNodeInfo(
|
||||
aName, nullptr, kNameSpaceID_XHTML, nsIDOMNode::ELEMENT_NODE);
|
||||
NS_ASSERTION(nodeInfo, "Got null nodeinfo.");
|
||||
nsCOMPtr<dom::Element> newElement = aCreator(nodeInfo.forget(), aFromParser);
|
||||
|
||||
MOZ_ASSERT(newElement, "Element creation created null pointer.");
|
||||
dom::Element* newContent = nullptr;
|
||||
nsIDocument* document = nodeInfo->GetDocument();
|
||||
bool willExecuteScript = false;
|
||||
bool isCustomElement = false;
|
||||
nsString isValue;
|
||||
dom::CustomElementDefinition* definition = nullptr;
|
||||
|
||||
dom::Element* newContent = newElement;
|
||||
aBuilder->HoldElement(newElement.forget());
|
||||
|
||||
if (aCreator == NS_NewCustomElement) {
|
||||
// Not inlining the call below into NS_NewCustomElement itself, because
|
||||
// in the near future, the code here will need to break out of an update
|
||||
// batch here.
|
||||
nsContentUtils::SetupCustomElement(newContent);
|
||||
}
|
||||
|
||||
if (MOZ_UNLIKELY(aName == nsHtml5Atoms::style || aName == nsHtml5Atoms::link)) {
|
||||
nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(newContent));
|
||||
if (ssle) {
|
||||
ssle->InitStyleLinkElement(false);
|
||||
ssle->SetEnableUpdates(false);
|
||||
}
|
||||
} else if (MOZ_UNLIKELY(isKeygen)) {
|
||||
// Adapted from CNavDTD
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIFormProcessor> theFormProcessor =
|
||||
do_GetService(kFormProcessorCID, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
return newContent;
|
||||
// Avoid overhead by checking if custom elements pref is enabled or not.
|
||||
if (nsContentUtils::IsCustomElementsEnabled()) {
|
||||
if (aAttributes) {
|
||||
nsHtml5String is = aAttributes->getValue(nsHtml5AttributeName::ATTR_IS);
|
||||
if (is) {
|
||||
is.ToString(isValue);
|
||||
}
|
||||
}
|
||||
|
||||
nsTArray<nsString> theContent;
|
||||
nsAutoString theAttribute;
|
||||
isCustomElement = (aCreator == NS_NewCustomElement || !isValue.IsEmpty());
|
||||
if (isCustomElement && aFromParser != dom::FROM_PARSER_FRAGMENT) {
|
||||
definition = nsContentUtils::LookupCustomElementDefinition(document,
|
||||
nodeInfo->LocalName(), nodeInfo->NamespaceID(),
|
||||
(isValue.IsEmpty() ? nullptr : &isValue));
|
||||
|
||||
(void) theFormProcessor->ProvideContent(NS_LITERAL_STRING("select"),
|
||||
theContent,
|
||||
theAttribute);
|
||||
|
||||
newContent->SetAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::moztype,
|
||||
nullptr,
|
||||
theAttribute,
|
||||
false);
|
||||
|
||||
RefPtr<dom::NodeInfo> optionNodeInfo =
|
||||
aNodeInfoManager->GetNodeInfo(nsHtml5Atoms::option,
|
||||
nullptr,
|
||||
kNameSpaceID_XHTML,
|
||||
nsIDOMNode::ELEMENT_NODE);
|
||||
|
||||
for (uint32_t i = 0; i < theContent.Length(); ++i) {
|
||||
RefPtr<dom::NodeInfo> ni = optionNodeInfo;
|
||||
nsCOMPtr<dom::Element> optionElt =
|
||||
NS_NewHTMLOptionElement(ni.forget(), aFromParser);
|
||||
RefPtr<nsTextNode> optionText = new nsTextNode(aNodeInfoManager);
|
||||
(void) optionText->SetText(theContent[i], false);
|
||||
optionElt->AppendChildTo(optionText, false);
|
||||
newContent->AppendChildTo(optionElt, false);
|
||||
}
|
||||
newContent->DoneAddingChildren(false);
|
||||
}
|
||||
|
||||
if (!aAttributes) {
|
||||
return newContent;
|
||||
}
|
||||
|
||||
int32_t len = aAttributes->getLength();
|
||||
for (int32_t i = 0; i < len; i++) {
|
||||
// prefix doesn't need regetting. it is always null or a static atom
|
||||
// local name is never null
|
||||
nsCOMPtr<nsIAtom> localName =
|
||||
Reget(aAttributes->getLocalNameNoBoundsCheck(i));
|
||||
nsCOMPtr<nsIAtom> prefix = aAttributes->getPrefixNoBoundsCheck(i);
|
||||
int32_t nsuri = aAttributes->getURINoBoundsCheck(i);
|
||||
|
||||
nsString value; // Not Auto, because using it to hold nsStringBuffer*
|
||||
aAttributes->getValueNoBoundsCheck(i).ToString(value);
|
||||
if (nsHtml5Atoms::a == aName && nsHtml5Atoms::name == localName) {
|
||||
// This is an HTML5-incompliant Geckoism.
|
||||
// Remove when fixing bug 582361
|
||||
NS_ConvertUTF16toUTF8 cname(value);
|
||||
NS_ConvertUTF8toUTF16 uv(nsUnescape(cname.BeginWriting()));
|
||||
newContent->SetAttr(nsuri,
|
||||
localName,
|
||||
prefix,
|
||||
uv,
|
||||
false);
|
||||
} else {
|
||||
newContent->SetAttr(nsuri,
|
||||
localName,
|
||||
prefix,
|
||||
value,
|
||||
false);
|
||||
|
||||
// Custom element setup may be needed if there is an "is" attribute.
|
||||
if (nsContentUtils::IsWebComponentsEnabled() &&
|
||||
kNameSpaceID_None == nsuri &&
|
||||
!prefix && nsGkAtoms::is == localName) {
|
||||
nsContentUtils::SetupCustomElement(newContent, &value);
|
||||
if (definition) {
|
||||
willExecuteScript = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (willExecuteScript) { // This will cause custom element constructors to run
|
||||
AutoSetThrowOnDynamicMarkupInsertionCounter
|
||||
throwOnDynamicMarkupInsertionCounter(document);
|
||||
mozAutoPauseContentUpdate autoPauseContentUpdate(document);
|
||||
{
|
||||
nsAutoMicroTask mt;
|
||||
}
|
||||
dom::AutoCEReaction
|
||||
autoCEReaction(document->GetDocGroup()->CustomElementReactionsStack());
|
||||
|
||||
nsCOMPtr<dom::Element> newElement;
|
||||
NS_NewHTMLElement(getter_AddRefs(newElement), nodeInfo.forget(),
|
||||
aFromParser, (isValue.IsEmpty() ? nullptr : &isValue),
|
||||
definition);
|
||||
|
||||
MOZ_ASSERT(newElement, "Element creation created null pointer.");
|
||||
newContent = newElement;
|
||||
aBuilder->HoldElement(newElement.forget());
|
||||
|
||||
if (MOZ_UNLIKELY(aName == nsHtml5Atoms::style || aName == nsHtml5Atoms::link)) {
|
||||
nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(newContent));
|
||||
if (ssle) {
|
||||
ssle->InitStyleLinkElement(false);
|
||||
ssle->SetEnableUpdates(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (!aAttributes) {
|
||||
return newContent;
|
||||
}
|
||||
|
||||
SetHTMLElementAttributes(newContent, aName, aAttributes);
|
||||
} else {
|
||||
nsCOMPtr<dom::Element> newElement;
|
||||
|
||||
if (isCustomElement) {
|
||||
NS_NewHTMLElement(getter_AddRefs(newElement), nodeInfo.forget(),
|
||||
aFromParser, (isValue.IsEmpty() ? nullptr : &isValue),
|
||||
definition);
|
||||
} else {
|
||||
newElement = aCreator(nodeInfo.forget(), aFromParser);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(newElement, "Element creation created null pointer.");
|
||||
|
||||
newContent = newElement;
|
||||
aBuilder->HoldElement(newElement.forget());
|
||||
|
||||
if (MOZ_UNLIKELY(aName == nsHtml5Atoms::style || aName == nsHtml5Atoms::link)) {
|
||||
nsCOMPtr<nsIStyleSheetLinkingElement> ssle(do_QueryInterface(newContent));
|
||||
if (ssle) {
|
||||
ssle->InitStyleLinkElement(false);
|
||||
ssle->SetEnableUpdates(false);
|
||||
}
|
||||
} else if (MOZ_UNLIKELY(isKeygen)) {
|
||||
// Adapted from CNavDTD
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIFormProcessor> theFormProcessor =
|
||||
do_GetService(kFormProcessorCID, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
return newContent;
|
||||
}
|
||||
|
||||
nsTArray<nsString> theContent;
|
||||
nsAutoString theAttribute;
|
||||
|
||||
(void) theFormProcessor->ProvideContent(NS_LITERAL_STRING("select"),
|
||||
theContent,
|
||||
theAttribute);
|
||||
|
||||
newContent->SetAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::moztype,
|
||||
nullptr,
|
||||
theAttribute,
|
||||
false);
|
||||
|
||||
RefPtr<dom::NodeInfo> optionNodeInfo = aNodeInfoManager->GetNodeInfo(
|
||||
nsHtml5Atoms::option, nullptr, kNameSpaceID_XHTML, nsIDOMNode::ELEMENT_NODE);
|
||||
|
||||
for (uint32_t i = 0; i < theContent.Length(); ++i) {
|
||||
RefPtr<dom::NodeInfo> ni = optionNodeInfo;
|
||||
nsCOMPtr<dom::Element> optionElt =
|
||||
NS_NewHTMLOptionElement(ni.forget(), aFromParser);
|
||||
RefPtr<nsTextNode> optionText = new nsTextNode(aNodeInfoManager);
|
||||
(void) optionText->SetText(theContent[i], false);
|
||||
optionElt->AppendChildTo(optionText, false);
|
||||
newContent->AppendChildTo(optionElt, false);
|
||||
}
|
||||
newContent->DoneAddingChildren(false);
|
||||
}
|
||||
|
||||
if (!aAttributes) {
|
||||
return newContent;
|
||||
}
|
||||
|
||||
SetHTMLElementAttributes(newContent, aName, aAttributes);
|
||||
}
|
||||
|
||||
return newContent;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -143,6 +143,10 @@ class nsHtml5TreeOperation {
|
|||
nsIContent* aTable,
|
||||
nsHtml5DocumentBuilder* aBuilder);
|
||||
|
||||
static void SetHTMLElementAttributes(mozilla::dom::Element* aElement,
|
||||
nsIAtom* aName,
|
||||
nsHtml5HtmlAttributes* aAttributes);
|
||||
|
||||
static nsresult AddAttributes(nsIContent* aNode,
|
||||
nsHtml5HtmlAttributes* aAttributes,
|
||||
nsHtml5DocumentBuilder* aBuilder);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue