/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
usesuper::{
registry::PropertyRegistration,
value::{
AllowComputationallyDependent, ComputedValue as ComputedRegisteredValue,
SpecifiedValue as SpecifiedRegisteredValue,
},
}; usecrate::custom_properties::{Name as CustomPropertyName, SpecifiedValue}; usecrate::derives::*; usecrate::error_reporting::ContextualParseError; usecrate::parser::{Parse, ParserContext}; usecrate::shared_lock::{SharedRwLockReadGuard, ToCssWithGuard}; usecrate::values::{computed, serialize_atom_name}; use cssparser::{
BasicParseErrorKind, ParseErrorKind, Parser, ParserInput, RuleBodyParser, SourceLocation,
}; use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; use servo_arc::Arc; use std::fmt::{self, Write}; use style_traits::{
CssStringWriter, CssWriter, ParseError, PropertyInheritsParseError, PropertySyntaxParseError,
StyleParseErrorKind, ToCss,
}; use to_shmem::{SharedMemoryBuilder, ToShmem};
pubusesuper::syntax::Descriptor as SyntaxDescriptor; pubusecrate::properties::property::{DescriptorId, DescriptorParser, Descriptors};
/// Parse the block inside a `@property` rule. /// /// Valid `@property` rules result in a registered custom property, as if `registerProperty()` had /// been called with equivalent parameters. pubfn parse_property_block<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
name: PropertyRuleName,
source_location: SourceLocation,
) -> Result<PropertyRegistration, ParseError<'i>> { letmut descriptors = Descriptors::default(); letmut parser = DescriptorParser {
context,
descriptors: &mut descriptors,
}; letmut iter = RuleBodyParser::new(input, &mut parser); letmut syntax_err = None; letmut inherits_err = None; whilelet Some(declaration) = iter.next() { if !context.error_reporting_enabled() { continue;
} iflet Err((error, slice)) = declaration { let location = error.location; let error = match error.kind { // If the provided string is not a valid syntax string (if it // returns failure when consume a syntax definition is called on // it), the descriptor is invalid and must be ignored.
ParseErrorKind::Custom(StyleParseErrorKind::PropertySyntaxField(_)) => {
syntax_err = Some(error.clone());
ContextualParseError::UnsupportedValue(slice, error)
},
// If the provided string is not a valid inherits string, // the descriptor is invalid and must be ignored.
ParseErrorKind::Custom(StyleParseErrorKind::PropertyInheritsField(_)) => {
inherits_err = Some(error.clone());
ContextualParseError::UnsupportedValue(slice, error)
},
// Unknown descriptors are invalid and ignored, but do not // invalidate the @property rule.
_ => ContextualParseError::UnsupportedPropertyDescriptor(slice, error),
};
context.log_css_error(location, error);
}
}
// https://drafts.css-houdini.org/css-properties-values-api-1/#the-syntax-descriptor: // // The syntax descriptor is required for the @property rule to be valid; if it’s // missing, the @property rule is invalid. let Some(ref syntax) = descriptors.syntax else { return Err(iflet Some(err) = syntax_err {
err
} else { let err = input.new_custom_error(StyleParseErrorKind::PropertySyntaxField(
PropertySyntaxParseError::NoSyntax,
));
context.log_css_error(
source_location,
ContextualParseError::UnsupportedValue("", err.clone()),
);
err
});
};
// https://drafts.css-houdini.org/css-properties-values-api-1/#inherits-descriptor: // // The inherits descriptor is required for the @property rule to be valid; if it’s // missing, the @property rule is invalid. if descriptors.inherits.is_none() { return Err(iflet Some(err) = inherits_err {
err
} else { let err = input.new_custom_error(StyleParseErrorKind::PropertyInheritsField(
PropertyInheritsParseError::NoInherits,
));
context.log_css_error(
source_location,
ContextualParseError::UnsupportedValue("", err.clone()),
);
err
});
};
if PropertyRegistration::validate_initial_value(syntax, descriptors.initial_value.as_deref())
.is_err()
{ return Err(input.new_error(BasicParseErrorKind::AtRuleBodyInvalid));
}
/// Errors that can happen when registering a property. #[allow(missing_docs)] pubenum PropertyRegistrationError {
NoInitialValue,
InvalidInitialValue,
InitialValueNotComputationallyIndependent,
}
/// Performs syntax validation as per the initial value descriptor. /// https://drafts.css-houdini.org/css-properties-values-api-1/#initial-value-descriptor pubfn validate_initial_value(
syntax: &SyntaxDescriptor,
initial_value: Option<&SpecifiedValue>,
) -> Result<(), PropertyRegistrationError> { usecrate::properties::CSSWideKeyword; // If the value of the syntax descriptor is the universal syntax definition, then the // initial-value descriptor is optional. If omitted, the initial value of the property is // the guaranteed-invalid value. if syntax.is_universal() && initial_value.is_none() { return Ok(());
}
// Otherwise, if the value of the syntax descriptor is not the universal syntax definition, // the following conditions must be met for the @property rule to be valid:
// The initial-value descriptor must be present. let Some(initial) = initial_value else { return Err(PropertyRegistrationError::NoInitialValue);
};
// A value that references the environment or other variables is not computationally // independent. if initial.has_references() { return Err(PropertyRegistrationError::InitialValueNotComputationallyIndependent);
}
// The initial-value cannot include CSS-wide keywords. if input.try_parse(CSSWideKeyword::parse).is_ok() { return Err(PropertyRegistrationError::InitialValueNotComputationallyIndependent);
}
/// A custom property name wrapper that includes the `--` prefix in its serialization #[derive(Clone, Debug, PartialEq, MallocSizeOf)] pubstruct PropertyRuleName(pub CustomPropertyName);
impl Parse for Inherits { fn parse<'i, 't>(
_context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> { // FIXME(bug 1927012): Remove `return` from try_match_ident_ignore_ascii_case so the closure // can be removed. let result: Result<Inherits, ParseError> = (|| {
try_match_ident_ignore_ascii_case! { input, "true" => Ok(Inherits::True), "false" => Ok(Inherits::False),
}
})(); iflet Err(err) = result {
Err(ParseError {
kind: ParseErrorKind::Custom(StyleParseErrorKind::PropertyInheritsField(
PropertyInheritsParseError::InvalidInherits,
)),
location: err.location,
})
} else {
result
}
}
}
/// Specifies the initial value of the custom property registration represented by the @property /// rule, controlling the property’s initial value. /// /// The SpecifiedValue is wrapped in an Arc to avoid copying when using it. pubtype InitialValue = Arc<SpecifiedValue>;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.