createElementPropertyAst function

BoundElementPropertyAst createElementPropertyAst(
  1. String elementName,
  2. String name,
  3. BoundValue value,
  4. SourceSpan sourceSpan,
  5. ElementSchemaRegistry schemaRegistry,
)

Implementation

BoundElementPropertyAst createElementPropertyAst(
  String elementName,
  String name,
  BoundValue value,
  SourceSpan sourceSpan,
  ElementSchemaRegistry schemaRegistry,
) {
  String? unit;
  String? namespace;
  PropertyBindingType? bindingType;
  String? boundPropertyName;
  TemplateSecurityContext? securityContext;
  var parts = name.split(_propertyPartsSeparator);
  if (identical(parts.length, 1)) {
    boundPropertyName = schemaRegistry.getMappedPropName(parts[0]);
    securityContext =
        schemaRegistry.securityContext(elementName, boundPropertyName);
    bindingType = PropertyBindingType.property;
    if (!schemaRegistry.hasProperty(elementName, boundPropertyName)) {
      if (boundPropertyName == 'ngclass') {
        CompileContext.current.reportAndRecover(BuildError.forSourceSpan(
          sourceSpan,
          'Please use camel-case ngClass instead of ngclass in your template',
        ));
      } else {
        CompileContext.current.reportAndRecover(BuildError.forSourceSpan(
          sourceSpan,
          "Can't bind to '$boundPropertyName' since it isn't a known "
          'native property or known directive. Please fix typo or add to '
          'directives list.',
        ));
      }
    }
  } else {
    if (parts[0] == _attributePrefix) {
      boundPropertyName = parts[1];
      if (boundPropertyName.toLowerCase().startsWith('on')) {
        CompileContext.current.reportAndRecover(BuildError.forSourceSpan(
          sourceSpan,
          'Binding to event attribute \'$boundPropertyName\' '
          'is disallowed for security reasons, please use '
          '(${boundPropertyName.substring(2)})=...',
        ));
      }
      unit = parts.length > 2 ? parts[2] : null;
      if (unit != null && unit != 'if') {
        CompileContext.current.reportAndRecover(BuildError.forSourceSpan(
          sourceSpan,
          'Invalid attribute unit "$unit"',
        ));
      }
      // NB: For security purposes, use the mapped property name, not the
      // attribute name.
      securityContext = schemaRegistry.securityContext(
          elementName, schemaRegistry.getMappedPropName(boundPropertyName));
      var nsSeparatorIdx = boundPropertyName.indexOf(':');
      if (nsSeparatorIdx > -1) {
        namespace = boundPropertyName.substring(0, nsSeparatorIdx);
        boundPropertyName = boundPropertyName.substring(nsSeparatorIdx + 1);
      }
      bindingType = PropertyBindingType.attribute;
    } else if (parts[0] == _classPrefix) {
      boundPropertyName = parts[1];
      bindingType = PropertyBindingType.cssClass;
      securityContext = TemplateSecurityContext.none;
    } else if (parts[0] == _stylePrefix) {
      unit = parts.length > 2 ? parts[2] : null;
      boundPropertyName = parts[1];
      bindingType = PropertyBindingType.style;
      securityContext = TemplateSecurityContext.style;
    } else {
      // Throw an error, otherwise it builds a BoundElementPropertyAst with null
      // fields that will result in a crash when trying to transform this Ast
      // node to an IR node.
      CompileContext.current.reportAndRecover(BuildError.forSourceSpan(
        sourceSpan,
        "Invalid property name '$name'",
      ));
      bindingType = null;
      securityContext = null;
    }
  }
  return BoundElementPropertyAst(
    namespace,
    boundPropertyName,
    bindingType,
    securityContext,
    value,
    unit,
    sourceSpan,
  );
}