tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit d0f3055eed7eaf6088de2f8314fa55ffa63ade08
parent 2fa8cf93bd86d9e32c8350030d24e18a6a505f44
Author: agoloman <agoloman@mozilla.com>
Date:   Wed, 19 Nov 2025 19:30:37 +0200

Revert "Bug 1986627 - Parse attr function as a substitution function when generalized attr is preffed on. r=layout-reviewers,firefox-style-system-reviewers,emilio" for causing wr failures @variable-generated-content-dynamic-001.html.

This reverts commit f5edda047abe2757d89bb0b14651cb1a7de2c082.

Revert "Bug 1986627 - Add preference for parsing css-attr. r=layout-reviewers,emilio"

This reverts commit 3644366ec62cdcef51a632ab489531229dc8357f.

Diffstat:
Mmodules/libpref/init/StaticPrefList.yaml | 10----------
Mservo/components/style/custom_properties.rs | 128+++++++++++++++++++++++++++++++++----------------------------------------------
Mservo/components/style/properties/mod.rs | 9+--------
3 files changed, 55 insertions(+), 92 deletions(-)

diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml @@ -9859,16 +9859,6 @@ mirror: always rust: true -# Whether to enable generalized CSS Attr Support. If this pref is set to false -# we treat attr as a regular function with support only for the `content` css -# property. If it is set to true, attr is parsed as a subtitution function. -# https://drafts.csswg.org/css-values-5/#attr-notation -- name: layout.css.attr.enabled - type: RelaxedAtomicBool - value: false - mirror: always - rust: true - # Whether to enable CSS @custom-media # https://drafts.csswg.org/mediaqueries-5/ # TODO(emilio): Needs more tests before enabling. diff --git a/servo/components/style/custom_properties.rs b/servo/components/style/custom_properties.rs @@ -458,13 +458,6 @@ pub enum DeferFontRelativeCustomPropertyResolution { No, } -#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem, Parse)] -enum SubstitutionFunctionKind { - Var, - Env, - Attr, -} - #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)] struct VariableFallback { start: num::NonZeroUsize, @@ -473,25 +466,24 @@ struct VariableFallback { } #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)] -struct SubstitutionFunctionReference { +struct VarOrEnvReference { name: Name, start: usize, end: usize, fallback: Option<VariableFallback>, prev_token_type: TokenSerializationType, next_token_type: TokenSerializationType, - substitution_kind: SubstitutionFunctionKind, + is_var: bool, } /// A struct holding information about the external references to that a custom /// property value may have. #[derive(Clone, Debug, Default, MallocSizeOf, PartialEq, ToShmem)] struct References { - refs: Vec<SubstitutionFunctionReference>, + refs: Vec<VarOrEnvReference>, non_custom_references: NonCustomReferences, any_env: bool, any_var: bool, - any_attr: bool, } impl References { @@ -792,33 +784,32 @@ fn parse_declaration_value_block<'i, 't>( return Err(input.new_custom_error(e)); }, Token::Function(ref name) => { - let substitution_kind = SubstitutionFunctionKind::from_ident(name).ok(); - if let Some(substitution_kind) = substitution_kind { + let is_var = name.eq_ignore_ascii_case("var"); + if is_var || name.eq_ignore_ascii_case("env") { let our_ref_index = references.refs.len(); let fallback = input.parse_nested_block(|input| { // TODO(emilio): For env() this should be <custom-ident> per spec, but no other browser does // that, see https://github.com/w3c/csswg-drafts/issues/3262. let name = input.expect_ident()?; - let name = - Atom::from(if substitution_kind == SubstitutionFunctionKind::Var { - match parse_name(name.as_ref()) { - Ok(name) => name, - Err(()) => { - let name = name.clone(); - return Err(input.new_custom_error( - SelectorParseErrorKind::UnexpectedIdent(name), - )); - }, - } - } else { - name.as_ref() - }); + let name = Atom::from(if is_var { + match parse_name(name.as_ref()) { + Ok(name) => name, + Err(()) => { + let name = name.clone(); + return Err(input.new_custom_error( + SelectorParseErrorKind::UnexpectedIdent(name), + )); + }, + } + } else { + name.as_ref() + }); // We want the order of the references to match source order. So we need to reserve our slot // now, _before_ parsing our fallback. Note that we don't care if parsing fails after all, since // if this fails we discard the whole result anyways. let start = token_start.byte_index() - input_start.byte_index(); - references.refs.push(SubstitutionFunctionReference { + references.refs.push(VarOrEnvReference { name, start, // To be fixed up after parsing fallback and auto-closing via our_ref_index. @@ -828,7 +819,7 @@ fn parse_declaration_value_block<'i, 't>( next_token_type: TokenSerializationType::Nothing, // To be fixed up after parsing fallback. fallback: None, - substitution_kind: substitution_kind.clone(), + is_var, }); let mut fallback = None; @@ -872,11 +863,11 @@ fn parse_declaration_value_block<'i, 't>( reference.end = input.position().byte_index() - input_start.byte_index() + missing_closing_characters.len(); reference.fallback = fallback; - match substitution_kind { - SubstitutionFunctionKind::Var => references.any_var = true, - SubstitutionFunctionKind::Env => references.any_env = true, - SubstitutionFunctionKind::Attr => references.any_attr = true, - }; + if is_var { + references.any_var = true; + } else { + references.any_env = true; + } } else { nested!(); check_closed!(")"); @@ -1047,7 +1038,6 @@ impl<'a, 'b: 'a> CustomPropertiesBuilder<'a, 'b> { // Non-custom dependency is really relevant for registered custom properties // that require computed value of such dependencies. let has_dependency = unparsed_value.references.any_var - || unparsed_value.references.any_attr || find_non_custom_references( registration, unparsed_value, @@ -1132,7 +1122,7 @@ impl<'a, 'b: 'a> CustomPropertiesBuilder<'a, 'b> { _ => return, }; - if !refs.any_var && !refs.any_attr { + if !refs.any_var { return; } @@ -1161,7 +1151,7 @@ impl<'a, 'b: 'a> CustomPropertiesBuilder<'a, 'b> { .refs .iter() .filter_map(|reference| { - if reference.substitution_kind != SubstitutionFunctionKind::Var { + if !reference.is_var { return None; } let registration = self @@ -1517,9 +1507,7 @@ fn substitute_all( /* include_unregistered = */ true, ); context.non_custom_references |= non_custom_refs.unwrap_or_default(); - let has_dependency = value.references.any_var - || value.references.any_attr - || non_custom_refs.is_some(); + let has_dependency = value.references.any_var || non_custom_refs.is_some(); // Nothing to resolve. if !has_dependency { debug_assert!(!value.references.any_env, "Should've been handled earlier"); @@ -1617,7 +1605,7 @@ fn substitute_all( // Visit other custom properties... // FIXME: Maybe avoid visiting the same var twice if not needed? for next in &v.references.refs { - if next.substitution_kind != SubstitutionFunctionKind::Var { + if !next.is_var { continue; } visit_link( @@ -1743,9 +1731,7 @@ fn substitute_all( ) .is_some() || v.references.refs.iter().any(|reference| { - (reference.substitution_kind == SubstitutionFunctionKind::Var - && deferred.get(&reference.name).is_some()) - || reference.substitution_kind == SubstitutionFunctionKind::Attr + reference.is_var && deferred.get(&reference.name).is_some() }); if defer { @@ -1756,7 +1742,7 @@ fn substitute_all( } // If there are no var references we should already be computed and substituted by now. - if !defer && (v.references.any_var || v.references.any_attr) { + if !defer && v.references.any_var { substitute_references_if_needed_and_apply( &name, v, @@ -2007,7 +1993,7 @@ fn do_substitute_chunk<'a>( custom_properties: &'a ComputedCustomProperties, stylist: &Stylist, computed_context: &computed::Context, - references: &mut std::iter::Peekable<std::slice::Iter<SubstitutionFunctionReference>>, + references: &mut std::iter::Peekable<std::slice::Iter<VarOrEnvReference>>, ) -> Result<Substitution<'a>, ()> { if start == end { // Empty string. Easy. @@ -2068,37 +2054,31 @@ fn substitute_one_reference<'a>( css: &'a str, url_data: &UrlExtraData, custom_properties: &'a ComputedCustomProperties, - reference: &SubstitutionFunctionReference, + reference: &VarOrEnvReference, stylist: &Stylist, computed_context: &computed::Context, - references: &mut std::iter::Peekable<std::slice::Iter<SubstitutionFunctionReference>>, + references: &mut std::iter::Peekable<std::slice::Iter<VarOrEnvReference>>, ) -> Result<Substitution<'a>, ()> { - match reference.substitution_kind { - SubstitutionFunctionKind::Var => { - let registration = stylist.get_custom_property_registration(&reference.name); - if let Some(v) = custom_properties.get(registration, &reference.name) { - // Skip references that are inside the outer variable (in fallback for example). - while references - .next_if(|next_ref| next_ref.end <= reference.end) - .is_some() - {} - return Ok(Substitution::from_value(v.to_variable_value())); - } - }, - SubstitutionFunctionKind::Env => { - let device = stylist.device(); - if let Some(v) = device.environment().get(&reference.name, device, url_data) { - while references - .next_if(|next_ref| next_ref.end <= reference.end) - .is_some() - {} - return Ok(Substitution::from_value(v)); - } - }, - SubstitutionFunctionKind::Attr => { - // TODO(descalante): implement attribute lookup. - }, - }; + if reference.is_var { + let registration = stylist.get_custom_property_registration(&reference.name); + if let Some(v) = custom_properties.get(registration, &reference.name) { + // Skip references that are inside the outer variable (in fallback for example). + while references + .next_if(|next_ref| next_ref.end <= reference.end) + .is_some() + {} + return Ok(Substitution::from_value(v.to_variable_value())); + } + } else { + let device = stylist.device(); + if let Some(v) = device.environment().get(&reference.name, device, url_data) { + while references + .next_if(|next_ref| next_ref.end <= reference.end) + .is_some() + {} + return Ok(Substitution::from_value(v)); + } + } let Some(ref fallback) = reference.fallback else { return Err(()); diff --git a/servo/components/style/properties/mod.rs b/servo/components/style/properties/mod.rs @@ -747,14 +747,7 @@ fn parse_non_custom_property_declaration_value_into<'i>( }; input.reset(&start); - input.look_for_arbitrary_substitution_functions( - if static_prefs::pref!("layout.css.attr.enabled") { - &["var", "env", "attr"] - } else { - &["var", "env"] - }, - ); - + input.look_for_arbitrary_substitution_functions(&["var", "env"]); let err = match parse_entirely_into(declarations, input) { Ok(()) => { input.seen_arbitrary_substitution_functions();