mirror of
https://github.com/servo/servo.git
synced 2025-09-27 23:30:08 +01:00
script: Implement CSS.registerProperty
(#38682)
The implementation is mostly equivalent to https://searchfox.org/mozilla-central/source/servo/ports/geckolib/glue.rs#9480. Testing: New web platform tests start to pass --------- Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
This commit is contained in:
parent
3a0e8fefde
commit
43da933247
9 changed files with 185 additions and 46 deletions
|
@ -22,6 +22,7 @@ atomic_refcell = { workspace = true }
|
|||
base = { workspace = true }
|
||||
bitflags = { workspace = true }
|
||||
compositing_traits = { workspace = true }
|
||||
cssparser = { workspace = true }
|
||||
data-url = { workspace = true }
|
||||
embedder_traits = { workspace = true }
|
||||
euclid = { workspace = true }
|
||||
|
|
|
@ -17,6 +17,7 @@ use base::id::{PipelineId, WebViewId};
|
|||
use bitflags::bitflags;
|
||||
use compositing_traits::CrossProcessCompositorApi;
|
||||
use compositing_traits::display_list::ScrollType;
|
||||
use cssparser::ParserInput;
|
||||
use embedder_traits::{Theme, ViewportDetails};
|
||||
use euclid::default::{Point2D as UntypedPoint2D, Rect as UntypedRect};
|
||||
use euclid::{Point2D, Scale, Size2D};
|
||||
|
@ -27,9 +28,9 @@ use fxhash::FxHashMap;
|
|||
use ipc_channel::ipc::IpcSender;
|
||||
use layout_api::wrapper_traits::LayoutNode;
|
||||
use layout_api::{
|
||||
IFrameSizes, Layout, LayoutConfig, LayoutDamage, LayoutFactory, OffsetParentResponse, QueryMsg,
|
||||
ReflowGoal, ReflowPhasesRun, ReflowRequest, ReflowRequestRestyle, ReflowResult,
|
||||
TrustedNodeAddress,
|
||||
IFrameSizes, Layout, LayoutConfig, LayoutDamage, LayoutFactory, OffsetParentResponse,
|
||||
PropertyRegistration, QueryMsg, ReflowGoal, ReflowPhasesRun, ReflowRequest,
|
||||
ReflowRequestRestyle, ReflowResult, RegisterPropertyError, TrustedNodeAddress,
|
||||
};
|
||||
use log::{debug, error, warn};
|
||||
use malloc_size_of::{MallocConditionalSizeOf, MallocSizeOf, MallocSizeOfOps};
|
||||
|
@ -50,6 +51,7 @@ use style::animation::DocumentAnimationSet;
|
|||
use style::context::{
|
||||
QuirksMode, RegisteredSpeculativePainter, RegisteredSpeculativePainters, SharedStyleContext,
|
||||
};
|
||||
use style::custom_properties::{SpecifiedValue, parse_name};
|
||||
use style::dom::{OpaqueNode, ShowSubtreeDataAndPrimaryValues, TElement, TNode};
|
||||
use style::error_reporting::RustLogReporter;
|
||||
use style::font_metrics::FontMetrics;
|
||||
|
@ -58,6 +60,11 @@ use style::invalidation::element::restyle_hints::RestyleHint;
|
|||
use style::media_queries::{Device, MediaList, MediaType};
|
||||
use style::properties::style_structs::Font;
|
||||
use style::properties::{ComputedValues, PropertyId};
|
||||
use style::properties_and_values::registry::{
|
||||
PropertyRegistration as StyloPropertyRegistration, PropertyRegistrationData,
|
||||
};
|
||||
use style::properties_and_values::rule::{Inherits, PropertyRegistrationError, PropertyRuleName};
|
||||
use style::properties_and_values::syntax::Descriptor;
|
||||
use style::queries::values::PrefersColorScheme;
|
||||
use style::selector_parser::{PseudoElement, RestyleDamage, SnapshotMap};
|
||||
use style::servo::media_queries::FontMetricsProvider;
|
||||
|
@ -72,6 +79,7 @@ use style::traversal_flags::TraversalFlags;
|
|||
use style::values::computed::font::GenericFontFamily;
|
||||
use style::values::computed::{CSSPixelLength, FontSize, Length, NonNegativeLength};
|
||||
use style::values::specified::font::{KeywordInfo, QueryFontMetricsFlags};
|
||||
use style::values::{Parser, SourceLocation};
|
||||
use style::{Zero, driver};
|
||||
use style_traits::{CSSPixel, SpeculativePainter};
|
||||
use stylo_atoms::Atom;
|
||||
|
@ -510,6 +518,92 @@ impl Layout for LayoutThread {
|
|||
fn needs_new_display_list(&self) -> bool {
|
||||
self.need_new_display_list.get()
|
||||
}
|
||||
|
||||
/// <https://drafts.css-houdini.org/css-properties-values-api-1/#the-registerproperty-function>
|
||||
fn register_custom_property(
|
||||
&mut self,
|
||||
property_registration: PropertyRegistration,
|
||||
) -> Result<(), RegisterPropertyError> {
|
||||
// Step 2. If name is not a custom property name string, throw a SyntaxError and exit this algorithm.
|
||||
// If property set already contains an entry with name as its property name
|
||||
// (compared codepoint-wise), throw an InvalidModificationError and exit this algorithm.
|
||||
let Ok(name) = parse_name(&property_registration.name) else {
|
||||
return Err(RegisterPropertyError::InvalidName);
|
||||
};
|
||||
let name = Atom::from(name);
|
||||
|
||||
if self
|
||||
.stylist
|
||||
.custom_property_script_registry()
|
||||
.get(&name)
|
||||
.is_some()
|
||||
{
|
||||
return Err(RegisterPropertyError::AlreadyRegistered);
|
||||
}
|
||||
|
||||
// Step 3. Attempt to consume a syntax definition from syntax. If it returns failure,
|
||||
// throw a SyntaxError. Otherwise, let syntax definition be the returned syntax definition.
|
||||
let syntax = Descriptor::from_str(&property_registration.syntax, false)
|
||||
.map_err(|_| RegisterPropertyError::InvalidSyntax)?;
|
||||
|
||||
// Step 4 - Parse and validate initial value
|
||||
let initial_value = match property_registration.initial_value {
|
||||
Some(value) => {
|
||||
let mut input = ParserInput::new(&value);
|
||||
let parsed = Parser::new(&mut input)
|
||||
.parse_entirely(|input| {
|
||||
input.skip_whitespace();
|
||||
SpecifiedValue::parse(input, &property_registration.url_data)
|
||||
.map(servo_arc::Arc::new)
|
||||
})
|
||||
.ok();
|
||||
if parsed.is_none() {
|
||||
return Err(RegisterPropertyError::InvalidInitialValue);
|
||||
}
|
||||
parsed
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
|
||||
StyloPropertyRegistration::validate_initial_value(&syntax, initial_value.as_deref())
|
||||
.map_err(|error| match error {
|
||||
PropertyRegistrationError::InitialValueNotComputationallyIndependent => {
|
||||
RegisterPropertyError::InitialValueNotComputationallyIndependent
|
||||
},
|
||||
PropertyRegistrationError::InvalidInitialValue => {
|
||||
RegisterPropertyError::InvalidInitialValue
|
||||
},
|
||||
PropertyRegistrationError::NoInitialValue => RegisterPropertyError::NoInitialValue,
|
||||
})?;
|
||||
|
||||
// Step 5. Set inherit flag to the value of inherits.
|
||||
let inherits = if property_registration.inherits {
|
||||
Inherits::True
|
||||
} else {
|
||||
Inherits::False
|
||||
};
|
||||
|
||||
// Step 6. Let registered property be a struct with a property name of name, a syntax of
|
||||
// syntax definition, an initial value of parsed initial value, and an inherit flag of inherit flag.
|
||||
// Append registered property to property set.
|
||||
let property_registration = StyloPropertyRegistration {
|
||||
name: PropertyRuleName(name),
|
||||
data: PropertyRegistrationData {
|
||||
syntax,
|
||||
initial_value,
|
||||
inherits,
|
||||
},
|
||||
url_data: property_registration.url_data,
|
||||
source_location: SourceLocation { line: 0, column: 0 },
|
||||
};
|
||||
|
||||
self.stylist
|
||||
.custom_property_script_registry_mut()
|
||||
.register(property_registration);
|
||||
self.stylist.rebuild_initial_values_for_custom_properties();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl LayoutThread {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue