Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions src/css/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ mod inherent_bridge {
impl<T: Clone + PartialEq> CssEql for Size2D<T> {
#[inline]
fn eql(&self, other: &Self) -> bool {
Size2D::<T>::eql(self, other)
PartialEq::eq(self, other)
}
}
impl<'bump, T: Clone + PartialEq> DeepClone<'bump> for Size2D<T> {
Expand Down Expand Up @@ -589,10 +589,8 @@ mod inherent_bridge {
bridge_eql!(BorderImage);

use crate::properties::border_radius::BorderRadius;
// BorderRadius has inherent deep_clone/eql (Size2D<T> lacks
// Clone/PartialEq derives — see border_radius.rs).
bridge_deep_clone!(BorderRadius);
bridge_eql!(BorderRadius);
bridge_eql_partialeq!(BorderRadius);

// ── properties/background ──
use crate::properties::background::{
Expand Down
20 changes: 4 additions & 16 deletions src/css/properties/border_radius.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@ use crate::css_values::size::Size2D;
use bun_alloc::ArenaVecExt as _;

/// A value for the [border-radius](https://www.w3.org/TR/css-backgrounds-3/#border-radius) property.
// `Size2D<T>` carries no `Clone`/`PartialEq` derives (it exposes
// inherent `deep_clone`/`eql` instead), so
// `BorderRadius` can't `#[derive]` them either. The handler below uses
// `Size2D::deep_clone`/`Size2D::eql` directly.
#[derive(PartialEq)]
pub struct BorderRadius {
/// The x and y radius values for the top left corner.
pub(crate) top_left: Size2D<LengthPercentage>,
Expand All @@ -37,13 +34,6 @@ impl BorderRadius {
}
}

pub fn eql(&self, other: &Self) -> bool {
Size2D::eql(&self.top_left, &other.top_left)
&& Size2D::eql(&self.top_right, &other.top_right)
&& Size2D::eql(&self.bottom_right, &other.bottom_right)
&& Size2D::eql(&self.bottom_left, &other.bottom_left)
}

pub fn parse(input: &mut css::Parser) -> css::Result<BorderRadius> {
let widths = Rect::<LengthPercentage>::parse_with(input, LengthPercentage::parse)?;
let heights = if input.try_parse(|i| i.expect_delim(b'/')).is_ok() {
Expand Down Expand Up @@ -133,9 +123,6 @@ impl BorderRadius {
}
Ok(())
}

// deep_clone comes from #[derive(Clone)].
// eql comes from #[derive(PartialEq)].
}

#[derive(Default)]
Expand Down Expand Up @@ -174,7 +161,7 @@ macro_rules! maybe_flush {
// If two vendor prefixes for the same property have different
// values, we need to flush what we have immediately to preserve order.
if let Some(existing) = &$self.$prop {
if !Size2D::eql(&existing.0, $val) && !existing.1.contains($vp) {
if existing.0 != *$val && !existing.1.contains($vp) {
Comment thread
robobun marked this conversation as resolved.
Resolved
$self.flush($d, $ctx);
}
}
Expand All @@ -198,7 +185,8 @@ macro_rules! property_helper {

// Otherwise, update the value and add the prefix.
if let Some(existing) = &mut $self.$prop {
*existing = ($val.deep_clone($bump), $vp);
existing.0 = $val.deep_clone($bump);
existing.1.insert($vp);
Comment thread
robobun marked this conversation as resolved.
Resolved
} else {
$self.$prop = Some(($val.deep_clone($bump), $vp));
$self.has_any = true;
Expand Down
2 changes: 1 addition & 1 deletion src/css/rules/font_face.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ impl FontStyle {
FontStyle::Italic => dest.write_str("italic"),
FontStyle::Oblique(angle) => {
dest.write_str("oblique")?;
if !Size2D::<Angle>::eql(angle, &FontStyle::default_oblique_angle()) {
if *angle != FontStyle::default_oblique_angle() {
dest.write_char(b' ')?;
angle.to_css(dest)?;
}
Expand Down
7 changes: 1 addition & 6 deletions src/css/values/size.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use bun_alloc::Arena;
/// A generic value that represents a value with two components, e.g. a border radius.
///
/// When serialized, only a single component will be written if both are equal.
#[derive(PartialEq, Eq)]
pub struct Size2D<T> {
pub(crate) a: T,
pub(crate) b: T,
Expand Down Expand Up @@ -73,12 +74,6 @@ where
// f32 → `lhs.* == rhs.*`, else → `lhs.eql(rhs)` — unified under PartialEq.
lhs == rhs
}

#[inline]
pub(crate) fn eql(lhs: &Self, rhs: &Self) -> bool {
// Note: compares lhs.a against rhs.b only (not a/a && b/b).
lhs.a == rhs.b
}
}

// Keep references to the f32/LengthPercentage special-case helpers so trait
Expand Down
48 changes: 48 additions & 0 deletions test/bundler/esbuild/css.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1264,6 +1264,54 @@ b {
},
});

// Two neighbouring rules stay two rules when one of their two-component values differs.
for (const [backend, minifyWhitespace, target] of [
["cli", true, "browser"],
["cli", false, "bun"],
["api", true, "bun"],
["api", false, "browser"],
] as const) {
itBundled(`css/TwoComponentValuesStayApart/${backend}/${minifyWhitespace ? "minify" : "pretty"}/${target}`, {
files: {
"/entry.css": /* css */ `
.table { border-spacing: 0 }
.rows { border-spacing: 0 8px }
.gap { color: red }
.circle { border-radius: 50% }
.oval { border-radius: 50% / 10% }
`,
},
backend,
minifyWhitespace,
target,
outdir: "/out",
onAfterBundle(api) {
api.expectFile("/out/entry.css").toEqualIgnoringWhitespace(
minifyWhitespace
? /* css */ `.table{border-spacing:0}.rows{border-spacing:0 8px}.gap{color:red}.circle{border-radius:50%}.oval{border-radius:50%/10%}`
: /* css */ `
/* entry.css */
.table {
border-spacing: 0;
}
.rows {
border-spacing: 0 8px;
}
.gap {
color: red;
}
.circle {
border-radius: 50%;
}
.oval {
border-radius: 50% / 10%;
}
`,
);
},
});
}

itBundled("css/IgnoreURLsInAtRulePrelude", {
// GENERATED
files: {
Expand Down
Loading
Loading