// https://html.spec.whatwg.org/multipage/scripting.html#upgrades bool ScriptCustomElementDefinition::runConstructor(Element* element) { if (!m_scriptState->contextIsValid()) return false; ScriptState::Scope scope(m_scriptState.get()); v8::Isolate* isolate = m_scriptState->isolate(); // Step 5 says to rethrow the exception; but there is no one to // catch it. The side effect is to report the error. v8::TryCatch tryCatch(isolate); tryCatch.SetVerbose(true); Element* result = runConstructor(); // To report exception thrown from runConstructor() if (tryCatch.HasCaught()) return false; // To report InvalidStateError Exception, when the constructor returns some // different object if (result != element) { const String& message = "custom element constructors must call super() first and must " "not return a different object"; v8::Local<v8::Value> exception = V8ThrowException::createDOMException( m_scriptState->isolate(), InvalidStateError, message); dispatchErrorEvent(isolate, exception, constructor()); return false; } return true; }
// https://html.spec.whatwg.org/multipage/scripting.html#concept-upgrade-an-element void CustomElementDefinition::upgrade(Element* element) { DCHECK_EQ(element->getCustomElementState(), CustomElementState::Undefined); if (!m_observedAttributes.isEmpty()) enqueueAttributeChangedCallbackForAllAttributes(element); if (element->inShadowIncludingDocument() && hasConnectedCallback()) enqueueConnectedCallback(element); m_constructionStack.append(element); size_t depth = m_constructionStack.size(); bool 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) return; CHECK(element->getCustomElementState() == CustomElementState::Custom); }
HTMLElement* ScriptCustomElementDefinition::createElementSync( Document& document, const QualifiedName& tagName, ExceptionState& exceptionState) { DCHECK(ScriptState::current(m_scriptState->isolate()) == m_scriptState); // Create an element // https://dom.spec.whatwg.org/#concept-create-element // 6. If definition is non-null // 6.1. If the synchronous custom elements flag is set: // 6.1.2. Set result to Construct(C). Rethrow any exceptions. // 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()); element = runConstructor(); if (tryCatch.HasCaught()) { exceptionState.rethrowV8Exception(tryCatch.Exception()); return nullptr; } } // 6.1.3. through 6.1.9. checkConstructorResult(element, document, tagName, exceptionState); if (exceptionState.hadException()) return nullptr; DCHECK_EQ(element->getCustomElementState(), CustomElementState::Custom); return toHTMLElement(element); }