CustomElementDefinition* CustomElementRegistry::definitionFor( const CustomElementDescriptor& desc) const { CustomElementDefinition* definition = definitionForName(desc.name()); if (!definition) return nullptr; // The definition for a customized built-in element, such as // <button is="my-button"> should not be provided for an // autonomous element, such as <my-button>, even though the // name "my-button" matches. return definition->descriptor() == desc ? definition : nullptr; }
// http://w3c.github.io/webcomponents/spec/custom/#dfn-element-definition void CustomElementRegistry::define(const AtomicString& name, CustomElementDefinitionBuilder& builder, const ElementDefinitionOptions& options, ExceptionState& exceptionState) { if (!builder.checkConstructorIntrinsics()) return; if (throwIfInvalidName(name, exceptionState)) return; if (nameIsDefined(name) || v0NameIsDefined(name)) { exceptionState.throwDOMException( NotSupportedError, "this name has already been used with this registry"); return; } if (!builder.checkConstructorNotRegistered()) return; // Step 7. customized built-in elements definition // element interface extends option checks if (RuntimeEnabledFeatures::customElementsBuiltinEnabled() && options.hasExtends()) { // If element interface is valid custom element name, throw exception if (throwIfValidName(AtomicString(options.extends()), exceptionState)) return; // If element interface is undefined element, throw exception // Set localname to extends } // TODO(dominicc): Add a test where the prototype getter destroys // the context. // 8. If this CustomElementRegistry's element definition is // running flag is set, then throw a "NotSupportedError" // DOMException and abort these steps. if (m_elementDefinitionIsRunning) { exceptionState.throwDOMException( NotSupportedError, "an element definition is already being processed"); return; } { // 9. Set this CustomElementRegistry's element definition is // running flag. ElementDefinitionIsRunning defining(m_elementDefinitionIsRunning); // 10.1-2 if (!builder.checkPrototype()) return; // 10.3-6 if (!builder.rememberOriginalProperties()) return; // "Then, perform the following substep, regardless of whether // the above steps threw an exception or not: Unset this // CustomElementRegistry's element definition is running // flag." // (ElementDefinitionIsRunning destructor does this.) } CustomElementDescriptor descriptor(name, name); CustomElementDefinition* definition = builder.build(descriptor); CHECK(!exceptionState.hadException()); CHECK(definition->descriptor() == descriptor); DefinitionMap::AddResult result = m_definitions.add(descriptor.name(), definition); CHECK(result.isNewEntry); HeapVector<Member<Element>> candidates; collectCandidates(descriptor, &candidates); for (Element* candidate : candidates) definition->enqueueUpgradeReaction(candidate); // 16: when-defined promise processing const auto& entry = m_whenDefinedPromiseMap.find(name); if (entry == m_whenDefinedPromiseMap.end()) return; entry->value->resolve(); m_whenDefinedPromiseMap.remove(entry); }
void CustomElementRegistrationContext::registerElement(Document* document, CustomElementConstructorBuilder* constructorBuilder, const AtomicString& type, CustomElement::NameSet validNames, ExceptionState& exceptionState) { CustomElementDefinition* definition = m_registry.registerElement(document, constructorBuilder, type, validNames, exceptionState); if (!definition) return; // Upgrade elements that were waiting for this definition. OwnPtrWillBeRawPtr<CustomElementUpgradeCandidateMap::ElementSet> upgradeCandidates = m_candidates->takeUpgradeCandidatesFor(definition->descriptor()); if (!upgradeCandidates) return; for (CustomElementUpgradeCandidateMap::ElementSet::const_iterator it = upgradeCandidates->begin(); it != upgradeCandidates->end(); ++it) CustomElement::define(*it, definition); }