예제 #1
0
void CustomElement::enqueueDisconnectedCallback(Element* element)
{
    DCHECK_EQ(element->getCustomElementState(), CustomElementState::Custom);
    CustomElementDefinition* definition = definitionForElement(*element);
    if (definition->hasDisconnectedCallback())
        definition->enqueueDisconnectedCallback(element);
}
예제 #2
0
// https://html.spec.whatwg.org/multipage/scripting.html#dom-customelementsregistry-get
ScriptValue CustomElementRegistry::get(const AtomicString& name) {
  CustomElementDefinition* definition = definitionForName(name);
  if (!definition) {
    // Binding layer converts |ScriptValue()| to script specific value,
    // e.g. |undefined| for v8.
    return ScriptValue();
  }
  return definition->getConstructorForScript();
}
예제 #3
0
void CustomElement::enqueueAttributeChangedCallback(Element* element,
    const QualifiedName& name,
    const AtomicString& oldValue, const AtomicString& newValue)
{
    DCHECK_EQ(element->getCustomElementState(), CustomElementState::Custom);
    CustomElementDefinition* definition = definitionForElement(*element);
    if (definition->hasAttributeChangedCallback(name))
        definition->enqueueAttributeChangedCallback(element, name, oldValue, newValue);
}
예제 #4
0
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;
}
예제 #5
0
void
nsStyledElement::InlineStyleDeclarationWillChange(MutationClosureData& aData)
{
  MOZ_ASSERT(OwnerDoc()->UpdateNestingLevel() > 0,
             "Should be inside document update!");
  bool modification = false;
  if (MayHaveStyle()) {
    bool needsOldValue =
      !StaticPrefs::dom_mutation_events_cssom_disabled() &&
      nsContentUtils::HasMutationListeners(this,
                                           NS_EVENT_BITS_MUTATION_ATTRMODIFIED,
                                           this);

    if (!needsOldValue) {
      CustomElementDefinition* definition = GetCustomElementDefinition();
      if (definition && definition->IsInObservedAttributeList(nsGkAtoms::style)) {
        needsOldValue = true;
      }
    }

    if (needsOldValue) {
      nsAutoString oldValueStr;
      modification = GetAttr(kNameSpaceID_None, nsGkAtoms::style,
                             oldValueStr);
      if (modification) {
        aData.mOldValue.emplace();
        aData.mOldValue->SetTo(oldValueStr);
      }
    } else {
      modification = HasAttr(kNameSpaceID_None, nsGkAtoms::style);
    }
  }

  aData.mModType = modification ?
    static_cast<uint8_t>(MutationEvent_Binding::MODIFICATION) :
    static_cast<uint8_t>(MutationEvent_Binding::ADDITION);
  nsNodeUtils::AttributeWillChange(this, kNameSpaceID_None,
                                   nsGkAtoms::style,
                                   aData.mModType, nullptr);

  //XXXsmaug In order to make attribute handling more consistent, consider to
  //         call BeforeSetAttr and pass kCallAfterSetAttr to
  //         SetAttrAndNotify in SetInlineStyleDeclaration.
  //         Handling of mozAutoDocUpdate may require changes in that case.
}
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.
    const CustomElementUpgradeCandidateMap::ElementSet& upgradeCandidates = m_candidates.takeUpgradeCandidatesFor(definition->descriptor());
    for (CustomElementUpgradeCandidateMap::ElementSet::const_iterator it = upgradeCandidates.begin(); it != upgradeCandidates.end(); ++it)
        CustomElement::define(*it, definition);
}
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 (const auto& candidate : *upgradeCandidates)
        CustomElement::define(candidate, definition);
}
예제 #8
0
// 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);
}