Commit 9636049c authored by kojii's avatar kojii Committed by Commit bot

Fix ScriptCustomElementDefinition::createElementSync to use the given document

This patch fixes ScriptCustomElementDefinition::createElementSync to
create an element with its ownerDocument set to the given document by
using the construction stack.

Before this fix, V8HTMLElement::constructorCustom assumed it matches to
window.document. The assumption does not stand when custom elements are
created in import documents.

BUG=640465

Review-Url: https://codereview.chromium.org/2274883005
Cr-Commit-Position: refs/heads/master@{#414434}
parent 359659b8
...@@ -424,8 +424,6 @@ crbug.com/404597 fast/css/text-overflow-ellipsis-button.html [ Pass Failure ] ...@@ -424,8 +424,6 @@ crbug.com/404597 fast/css/text-overflow-ellipsis-button.html [ Pass Failure ]
crbug.com/404597 [ Win ] fast/selectors/007a.html [ Pass Failure ] crbug.com/404597 [ Win ] fast/selectors/007a.html [ Pass Failure ]
# Web Components related tests (Shadow DOM, Custom Elements) failures. # Web Components related tests (Shadow DOM, Custom Elements) failures.
crbug.com/640465 custom-elements/imports/create-element-in-import.html [ Failure ]
crbug.com/640465 custom-elements/imports/sync-create-element-order.html [ Failure ]
crbug.com/505364 imported/wpt/shadow-dom/untriaged/styles/test-003.html [ Failure ] crbug.com/505364 imported/wpt/shadow-dom/untriaged/styles/test-003.html [ Failure ]
crbug.com/505364 imported/wpt/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-event-interface/event-path-001.html [ Failure ] crbug.com/505364 imported/wpt/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-event-interface/event-path-001.html [ Failure ]
crbug.com/505364 imported/wpt/custom-elements/v0/instantiating/extensions-to-document-interface/create-element-interface-type-is-a-type-extension.html [ Failure ] crbug.com/505364 imported/wpt/custom-elements/v0/instantiating/extensions-to-document-interface/create-element-interface-type-is-a-type-extension.html [ Failure ]
......
...@@ -170,8 +170,15 @@ HTMLElement* ScriptCustomElementDefinition::createElementSync( ...@@ -170,8 +170,15 @@ HTMLElement* ScriptCustomElementDefinition::createElementSync(
// 6. If definition is non-null // 6. If definition is non-null
// 6.1. If the synchronous custom elements flag is set: // 6.1. If the synchronous custom elements flag is set:
// 6.1.2. Set result to Construct(C). Rethrow any exceptions. // 6.1.2. Set result to Construct(C). Rethrow any exceptions.
Element* element = nullptr;
// Create an element and push to the construction stack.
// V8HTMLElement::constructorCustom() can only refer to
// window.document(), but it is different from the document here
// when it is an import document. This is not exactly what the
// spec defines, but the public behavior matches to the spec.
Element* element = createElementForConstructor(document);
{ {
ConstructionStackScope constructionStackScope(this, element);
v8::TryCatch tryCatch(m_scriptState->isolate()); v8::TryCatch tryCatch(m_scriptState->isolate());
element = runConstructor(); element = runConstructor();
if (tryCatch.HasCaught()) { if (tryCatch.HasCaught()) {
......
...@@ -56,15 +56,7 @@ void V8HTMLElement::constructorCustom( ...@@ -56,15 +56,7 @@ void V8HTMLElement::constructorCustom(
Element* element; Element* element;
if (definition->constructionStack().isEmpty()) { if (definition->constructionStack().isEmpty()) {
// This is an element being created with 'new' from script // This is an element being created with 'new' from script
// TODO(kojii): When HTMLElementFactory has an option not to queue element = definition->createElementForConstructor(*window->document());
// upgrade, call that instead of HTMLElement. HTMLElement is enough
// for now, but type extension will require HTMLElementFactory.
element = HTMLElement::create(
QualifiedName(nullAtom, definition->descriptor().localName(), HTMLNames::xhtmlNamespaceURI),
*window->document());
// TODO(davaajav): write this as one call to setCustomElementState instead of two
element->setCustomElementState(CustomElementState::Undefined);
element->setCustomElementDefinition(definition);
} else { } else {
element = definition->constructionStack().last(); element = definition->constructionStack().last();
if (element) { if (element) {
......
...@@ -84,6 +84,22 @@ void CustomElementDefinition::checkConstructorResult(Element* element, ...@@ -84,6 +84,22 @@ void CustomElementDefinition::checkConstructorResult(Element* element,
exceptionState.throwDOMException(NotSupportedError, message); exceptionState.throwDOMException(NotSupportedError, message);
} }
HTMLElement* CustomElementDefinition::createElementForConstructor(
Document& document)
{
// TODO(kojii): When HTMLElementFactory has an option not to queue
// upgrade, call that instead of HTMLElement. HTMLElement is enough
// for now, but type extension will require HTMLElementFactory.
HTMLElement* element = HTMLElement::create(
QualifiedName(nullAtom, descriptor().localName(),
HTMLNames::xhtmlNamespaceURI),
document);
// TODO(davaajav): write this as one call to setCustomElementState instead of two
element->setCustomElementState(CustomElementState::Undefined);
element->setCustomElementDefinition(this);
return element;
}
HTMLElement* CustomElementDefinition::createElementAsync(Document& document, const QualifiedName& tagName) HTMLElement* CustomElementDefinition::createElementAsync(Document& document, const QualifiedName& tagName)
{ {
// https://dom.spec.whatwg.org/#concept-create-element // https://dom.spec.whatwg.org/#concept-create-element
...@@ -101,6 +117,25 @@ HTMLElement* CustomElementDefinition::createElementAsync(Document& document, con ...@@ -101,6 +117,25 @@ HTMLElement* CustomElementDefinition::createElementAsync(Document& document, con
return element; return element;
} }
CustomElementDefinition::ConstructionStackScope::ConstructionStackScope(
CustomElementDefinition* definition, Element* element)
: m_constructionStack(definition->m_constructionStack)
, m_element(element)
{
// Push the construction stack.
m_constructionStack.append(element);
m_depth = m_constructionStack.size();
}
CustomElementDefinition::ConstructionStackScope::~ConstructionStackScope()
{
// Pop the construction stack.
DCHECK(!m_constructionStack.last()
|| m_constructionStack.last() == m_element);
DCHECK_EQ(m_constructionStack.size(), m_depth); // It's a *stack*.
m_constructionStack.removeLast();
}
// https://html.spec.whatwg.org/multipage/scripting.html#concept-upgrade-an-element // https://html.spec.whatwg.org/multipage/scripting.html#concept-upgrade-an-element
void CustomElementDefinition::upgrade(Element* element) void CustomElementDefinition::upgrade(Element* element)
{ {
...@@ -112,17 +147,11 @@ void CustomElementDefinition::upgrade(Element* element) ...@@ -112,17 +147,11 @@ void CustomElementDefinition::upgrade(Element* element)
if (element->isConnected() && hasConnectedCallback()) if (element->isConnected() && hasConnectedCallback())
enqueueConnectedCallback(element); enqueueConnectedCallback(element);
m_constructionStack.append(element); bool succeeded = false;
size_t depth = m_constructionStack.size(); {
ConstructionStackScope constructionStackScope(this, element);
bool succeeded = runConstructor(element); succeeded = runConstructor(element);
}
// Pop the construction stack.
if (m_constructionStack.last().get())
DCHECK_EQ(m_constructionStack.last(), element);
DCHECK_EQ(m_constructionStack.size(), depth); // It's a *stack*.
m_constructionStack.removeLast();
if (!succeeded) { if (!succeeded) {
element->setCustomElementState(CustomElementState::Failed); element->setCustomElementState(CustomElementState::Failed);
return; return;
......
...@@ -48,6 +48,7 @@ public: ...@@ -48,6 +48,7 @@ public:
return m_constructionStack; return m_constructionStack;
} }
HTMLElement* createElementForConstructor(Document&);
virtual HTMLElement* createElementSync(Document&, const QualifiedName&) = 0; virtual HTMLElement* createElementSync(Document&, const QualifiedName&) = 0;
virtual HTMLElement* createElementSync(Document&, const QualifiedName&, ExceptionState&) = 0; virtual HTMLElement* createElementSync(Document&, const QualifiedName&, ExceptionState&) = 0;
HTMLElement* createElementAsync(Document&, const QualifiedName&); HTMLElement* createElementAsync(Document&, const QualifiedName&);
...@@ -73,6 +74,18 @@ public: ...@@ -73,6 +74,18 @@ public:
void enqueueAttributeChangedCallback(Element*, const QualifiedName&, void enqueueAttributeChangedCallback(Element*, const QualifiedName&,
const AtomicString& oldValue, const AtomicString& newValue); const AtomicString& oldValue, const AtomicString& newValue);
class CORE_EXPORT ConstructionStackScope final {
STACK_ALLOCATED();
DISALLOW_COPY_AND_ASSIGN(ConstructionStackScope);
public:
ConstructionStackScope(CustomElementDefinition*, Element*);
~ConstructionStackScope();
private:
ConstructionStack& m_constructionStack;
Member<Element> m_element;
size_t m_depth;
};
protected: protected:
virtual bool runConstructor(Element*) = 0; virtual bool runConstructor(Element*) = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment