fix(geometry): serialize DOMMatrix numbers like ECMAScript

Source-commit: 715995c959
This commit is contained in:
ldm0
2026-09-11 01:23:22 +08:00
parent 5699c4621b
commit 13a748b7ea
5 changed files with 58 additions and 23 deletions
Generated
+1
View File
@@ -2567,6 +2567,7 @@ dependencies = [
name = "moli-geometry"
version = "0.1.0"
dependencies = [
"dragonbox_ecma",
"moli-css-parse",
]
+1
View File
@@ -5,6 +5,7 @@ version = "0.1.0"
edition = "2024"
[dependencies]
dragonbox_ecma = "0.1.12"
moli-css-parse = { path = "../moli-css-parse" }
[lints]
+19
View File
@@ -17,6 +17,25 @@ mod tests {
);
}
#[test]
fn dom_matrix_text_uses_ecmascript_number_serialization() {
for (value, expected) in [
(1.0 / 300_000_000.0, "3.3333333333333334e-9"),
(f64::MAX, "1.7976931348623157e+308"),
(f64::MIN_POSITIVE * f64::EPSILON, "5e-324"),
] {
let matrix = DomMatrixComponents {
m42: value,
..DomMatrixComponents::identity()
};
assert_eq!(
matrix.dom_matrix_text().unwrap(),
format!("matrix(1, 0, 0, 1, 0, {expected})")
);
}
}
#[test]
fn parses_css_transform_list_into_product_matrix() {
let matrix = parse_dom_matrix_value("translateX(10px) scale(2) rotate(90deg)").unwrap();
+36 -22
View File
@@ -498,6 +498,14 @@ impl DomMatrixComponents {
}
pub fn css_text(self) -> Option<String> {
self.text(css_number)
}
pub fn dom_matrix_text(self) -> Option<String> {
self.text(ecmascript_number)
}
fn text(self, serialize_number: fn(f64) -> String) -> Option<String> {
if self.is_2d() {
let values = [self.m11, self.m12, self.m21, self.m22, self.m41, self.m42];
if !values.iter().all(|value| value.is_finite()) {
@@ -505,12 +513,12 @@ impl DomMatrixComponents {
}
return Some(format!(
"matrix({}, {}, {}, {}, {}, {})",
css_number(self.m11),
css_number(self.m12),
css_number(self.m21),
css_number(self.m22),
css_number(self.m41),
css_number(self.m42)
serialize_number(self.m11),
serialize_number(self.m12),
serialize_number(self.m21),
serialize_number(self.m22),
serialize_number(self.m41),
serialize_number(self.m42)
));
}
@@ -523,26 +531,32 @@ impl DomMatrixComponents {
}
Some(format!(
"matrix3d({}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {})",
css_number(self.m11),
css_number(self.m12),
css_number(self.m13),
css_number(self.m14),
css_number(self.m21),
css_number(self.m22),
css_number(self.m23),
css_number(self.m24),
css_number(self.m31),
css_number(self.m32),
css_number(self.m33),
css_number(self.m34),
css_number(self.m41),
css_number(self.m42),
css_number(self.m43),
css_number(self.m44)
serialize_number(self.m11),
serialize_number(self.m12),
serialize_number(self.m13),
serialize_number(self.m14),
serialize_number(self.m21),
serialize_number(self.m22),
serialize_number(self.m23),
serialize_number(self.m24),
serialize_number(self.m31),
serialize_number(self.m32),
serialize_number(self.m33),
serialize_number(self.m34),
serialize_number(self.m41),
serialize_number(self.m42),
serialize_number(self.m43),
serialize_number(self.m44)
))
}
}
fn ecmascript_number(value: f64) -> String {
dragonbox_ecma::Buffer::new()
.format_finite(value)
.to_owned()
}
fn css_number(value: f64) -> String {
if value == 0.0 {
"0".to_owned()
@@ -1966,7 +1966,7 @@ fn dom_matrix_css_text<'s>(
scope: &mut v8::PinScope<'s, '_>,
object: v8::Local<'s, v8::Object>,
) -> Option<String> {
let Some(css_text) = dom_matrix_components(scope, object).css_text() else {
let Some(css_text) = dom_matrix_components(scope, object).dom_matrix_text() else {
throw_dom_exception(
scope,
"InvalidStateError",