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);
}