Repository navigation
css: parse the *property hack as a declaration
#46751
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,7 +7,7 @@ use crate::css_properties::align::AlignHandler; | |
| use crate::css_properties::background::BackgroundHandler; | ||
| use crate::css_properties::border::BorderHandler; | ||
| use crate::css_properties::box_shadow::BoxShadowHandler; | ||
| use crate::css_properties::custom::CustomPropertyName; | ||
| use crate::css_properties::custom::{CustomProperty, CustomPropertyName}; | ||
| use crate::css_properties::flex::FlexHandler; | ||
| use crate::css_properties::font::FontHandler; | ||
| use crate::css_properties::margin_padding::{ | ||
|
|
@@ -19,6 +19,7 @@ use crate::css_properties::text::Direction; | |
| use crate::css_properties::transform::TransformHandler; | ||
| use crate::css_properties::transition::TransitionHandler; | ||
| use crate::css_properties::ui::ColorSchemeHandler; | ||
| use crate::css_values::ident::Ident; | ||
|
|
||
| pub type DeclarationList<'bump> = bun_alloc::ArenaVec<'bump, css::Property>; | ||
|
|
||
|
|
@@ -46,6 +47,20 @@ impl<'bump> DeclarationBlock<'bump> { | |
| self.declarations.len() + self.important_declarations.len() | ||
| } | ||
|
|
||
| /// Whether a declaration is an IE star hack (`*zoom: 1`). | ||
| pub(crate) fn has_star_hack(&self) -> bool { | ||
| self.declarations | ||
| .iter() | ||
| .chain(self.important_declarations.iter()) | ||
| .any(|property| { | ||
| matches!( | ||
| property, | ||
| css::Property::Custom(custom) | ||
| if matches!(custom.name, CustomPropertyName::StarHack(_)) | ||
| ) | ||
| }) | ||
| } | ||
|
|
||
| pub(crate) fn new_in(bump: &'bump Bump) -> Self { | ||
| Self { | ||
| important_declarations: DeclarationList::new_in(bump), | ||
|
|
@@ -280,6 +295,20 @@ impl<'a, 'bump> css::DeclarationParser for PropertyDeclarationParser<'a, 'bump> | |
| this.options, | ||
| ) | ||
| } | ||
|
|
||
| fn parse_star_hack( | ||
| this: &mut Self, | ||
| name: &'static [u8], | ||
| input: &mut css::Parser, | ||
| ) -> Result<Self::Declaration> { | ||
| parse_star_hack( | ||
| name, | ||
| input, | ||
| this.declarations, | ||
| this.important_declarations, | ||
| this.options, | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| impl<'a, 'bump> css::RuleBodyItemParser for PropertyDeclarationParser<'a, 'bump> { | ||
|
|
@@ -386,6 +415,34 @@ where | |
| Ok(()) | ||
| } | ||
|
|
||
| /// The value of a `*property` declaration, read as the value of an unknown | ||
| /// property is read above. `name` keeps its `*`: it is not `property`. | ||
| #[cold] | ||
| pub(crate) fn parse_star_hack<'bump>( | ||
| name: &'static [u8], | ||
| input: &mut css::Parser, | ||
| declarations: &mut DeclarationList<'bump>, | ||
| important_declarations: &mut DeclarationList<'bump>, | ||
| options: &css::ParserOptions, | ||
| ) -> Result<()> { | ||
| let name = CustomPropertyName::StarHack(Ident { v: name }); | ||
| let value = input.parse_until_before( | ||
| css::Delimiters::BANG | css::Delimiters::CURLY_BRACKET, | ||
| |input2: &mut css::Parser| CustomProperty::parse(name, input2, options), | ||
| )?; | ||
| let important = input.try_parse(css::parse_important).is_ok(); | ||
| input.expect_exhausted()?; | ||
|
|
||
| let property = css::Property::Custom(value); | ||
| if important { | ||
| important_declarations.push(property); | ||
| } else { | ||
| declarations.push(property); | ||
|
Comment on lines
+436
to
+440
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 (optional) Users minifying Why this was flaggedTrigger: any stylesheet with Verification: A star-hack declaration that follows a property a shorthand handler owns (
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Documented under "Position" in the notes and pinned by a test beside its |
||
| } | ||
|
|
||
| Ok(()) | ||
| } | ||
|
|
||
| /// Per-shorthand-group handler state used by `DeclarationBlock::minify`. | ||
| pub struct DeclarationHandler<'bump> { | ||
| pub(crate) background: BackgroundHandler, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -496,6 +496,10 @@ impl<R> StyleRule<R> { | |
| } | ||
| true | ||
| } | ||
| // `PropertyId` equality takes `*zoom` for `zoom`, and the loops do | ||
| // not pair a normal declaration with an important one. | ||
| && !self.declarations.has_star_hack() | ||
| && !other.declarations.has_star_hack() | ||
|
Comment on lines
+499
to
+502
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟣 pre-existing, not blocking: pre-existing: minified output still drops a whole style rule when an unknown property such as Why this was flaggedInput Verification: pre-existing; acknowledged in diff: the guard added at src/css/rules/style.rs:501-502 exempts only
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the defect that #33684 fixes at its owner: |
||
| } | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟡 (optional) Users bundling a sheet whose keyframe block holds
*background: url(./missing.png)now get a failed build where main exits 0. The star-hack value is parsed as a CustomProperty at src/css/declaration.rs:429-432, so everyurl()in it becomes an import record that the bundler must resolve. On main the*made the declaration an error, the recovering body dropped the block, and the build went on. Legacy sheets whose IE-only assets were pruned are exactly the population this hack appears in. Fix: aurl()inside a*propertyvalue should not fail the build (resolve it best-effort and keep the raw text, or warn), for keyframes, @ page and style rules alike.Why this was flagged
Trigger: a stylesheet containing
@ keyframes k{from{*background:url(./missing.png)}to{top:2px}}or@ page{*background:url(./missing.png)}passed tobun build. The new path src/css/css_parser.rs:2903-2909 accepts the*identand calls parse_star_hack at src/css/declaration.rs:421; CustomProperty::parse at src/css/declaration.rs:431 records the url() via add_import_record (src/css/css_parser.rs:3153) and the declaration succeeds, so reset never truncates it. On the base commit the*reaches the else branch at src/css/css_parser.rs:2920 as an unexpected token; the keyframe body drops the block and the build exits 0. After merge the bundler reportsCould not resolve: "./missing.png"and the build fails. Population: legacy sheets with star-hacked IE asset paths whose images were removed. Remedy: do not turn aurl()in a star-hack value into a hard import, or at least degrade it to a warning like esbuild does.Verification: Trigger: a star-hack declaration inside a @ keyframes block whose url() names a file that does not exist. src/css/declaration.rs:429-432
parse_star_hackparses the value withCustomProperty::parse, which callsinput.add_import_record(...); the bundler treats an unresolvable record as a hard error. On base the keyframes loop at src/css/css_parser.rs:1780-1784 drops the block and exits 0.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Kept on purpose. A
url()in the value of any unknown property is an import on main:_background: url(./missing.png)fails the build in the same way, in a style rule and in a keyframe block. A hack value that kept itsurl()as text would point at a file that the bundler did not copy, also when the file exists. The description lists the keyframe case as a new failure, andcss/StarHackURLMissingFilepins the error. If a maintainer wants a different policy for hack values, it is a change inparse_star_hackonly.