Esempio n. 1
0
void PropertyRegistration::registerProperty(
    ExecutionContext* executionContext,
    const PropertyDescriptor& descriptor,
    ExceptionState& exceptionState) {
  // Bindings code ensures these are set.
  DCHECK(descriptor.hasName());
  DCHECK(descriptor.hasInherits());
  DCHECK(descriptor.hasSyntax());

  String name = descriptor.name();
  if (!CSSVariableParser::isValidVariableName(name)) {
    exceptionState.throwDOMException(
        SyntaxError, "The name provided is not a valid custom property name.");
    return;
  }
  AtomicString atomicName(name);
  Document* document = toDocument(executionContext);
  PropertyRegistry& registry = *document->propertyRegistry();
  if (registry.registration(atomicName)) {
    exceptionState.throwDOMException(
        InvalidModificationError,
        "The name provided has already been registered.");
    return;
  }

  CSSSyntaxDescriptor syntaxDescriptor(descriptor.syntax());
  if (!syntaxDescriptor.isValid()) {
    exceptionState.throwDOMException(
        SyntaxError,
        "The syntax provided is not a valid custom property syntax.");
    return;
  }

  if (descriptor.hasInitialValue()) {
    CSSTokenizer tokenizer(descriptor.initialValue());
    bool isAnimationTainted = false;
    const CSSValue* initial =
        syntaxDescriptor.parse(tokenizer.tokenRange(), isAnimationTainted);
    if (!initial) {
      exceptionState.throwDOMException(
          SyntaxError,
          "The initial value provided does not parse for the given syntax.");
      return;
    }
    if (!computationallyIndependent(*initial)) {
      exceptionState.throwDOMException(
          SyntaxError,
          "The initial value provided is not computationally independent.");
      return;
    }
    RefPtr<CSSVariableData> initialVariableData = CSSVariableData::create(
        tokenizer.tokenRange(), isAnimationTainted, false);
    registry.registerProperty(atomicName, syntaxDescriptor,
                              descriptor.inherits(), initial,
                              initialVariableData.release());
  } else {
    if (!syntaxDescriptor.isTokenStream()) {
      exceptionState.throwDOMException(
          SyntaxError,
          "An initial value must be provided if the syntax is not '*'");
      return;
    }
    registry.registerProperty(atomicName, syntaxDescriptor,
                              descriptor.inherits(), nullptr, nullptr);
  }

  // TODO(timloh): Invalidate only elements with this custom property set
  document->setNeedsStyleRecalc(SubtreeStyleChange,
                                StyleChangeReasonForTracing::create(
                                    StyleChangeReason::PropertyRegistration));
}