diff --git a/moli-benchmark/wpt-cross-current/failed-cases.txt b/moli-benchmark/wpt-cross-current/failed-cases.txt index 26ae2ec06c..f7db0de166 100644 --- a/moli-benchmark/wpt-cross-current/failed-cases.txt +++ b/moli-benchmark/wpt-cross-current/failed-cases.txt @@ -2513,7 +2513,6 @@ css/geometry/DOMQuad-001.html css/geometry/DOMQuad-002.html css/geometry/DOMQuad-nan.html css/geometry/DOMRect-002.html -css/geometry/DOMRect-nan.html css/geometry/DOMRectList.html css/geometry/WebKitCSSMatrix.html css/geometry/historical.html diff --git a/moli-benchmark/wpt-cross-current/passed-cases.txt b/moli-benchmark/wpt-cross-current/passed-cases.txt index 67bec9d414..052fd8002d 100644 --- a/moli-benchmark/wpt-cross-current/passed-cases.txt +++ b/moli-benchmark/wpt-cross-current/passed-cases.txt @@ -3114,6 +3114,7 @@ css/geometry/DOMMatrix-invert-preserves-2d.html css/geometry/DOMMatrix-invertSelf.html css/geometry/DOMMatrix-newobject.html css/geometry/DOMRect-001.html +css/geometry/DOMRect-nan.html css/mediaqueries/aspect-ratio-serialization.html css/mediaqueries/display-mode.html css/mediaqueries/dynamic-range.html diff --git a/moli-renderer-v8/src/context_bootstrap/dom_rect.rs b/moli-renderer-v8/src/context_bootstrap/dom_rect.rs index 941de7ad27..bafc1336e2 100644 --- a/moli-renderer-v8/src/context_bootstrap/dom_rect.rs +++ b/moli-renderer-v8/src/context_bootstrap/dom_rect.rs @@ -421,26 +421,42 @@ fn dom_rect_readonly_attribute_value<'s>( DomRectReadonlyAttribute::Top => { let y = dom_rect_slot(object, scope, DOM_RECT_Y_SLOT); let height = dom_rect_slot(object, scope, DOM_RECT_HEIGHT_SLOT); - y.min(y + height) + dom_rect_min(y, y + height) } DomRectReadonlyAttribute::Right => { let x = dom_rect_slot(object, scope, DOM_RECT_X_SLOT); let width = dom_rect_slot(object, scope, DOM_RECT_WIDTH_SLOT); - x.max(x + width) + dom_rect_max(x, x + width) } DomRectReadonlyAttribute::Bottom => { let y = dom_rect_slot(object, scope, DOM_RECT_Y_SLOT); let height = dom_rect_slot(object, scope, DOM_RECT_HEIGHT_SLOT); - y.max(y + height) + dom_rect_max(y, y + height) } DomRectReadonlyAttribute::Left => { let x = dom_rect_slot(object, scope, DOM_RECT_X_SLOT); let width = dom_rect_slot(object, scope, DOM_RECT_WIDTH_SLOT); - x.min(x + width) + dom_rect_min(x, x + width) } } } +fn dom_rect_min(lhs: f64, rhs: f64) -> f64 { + if lhs.is_nan() || rhs.is_nan() { + f64::NAN + } else { + lhs.min(rhs) + } +} + +fn dom_rect_max(lhs: f64, rhs: f64) -> f64 { + if lhs.is_nan() || rhs.is_nan() { + f64::NAN + } else { + lhs.max(rhs) + } +} + fn dom_rect_slot<'s>( object: v8::Local<'s, v8::Object>, scope: &mut v8::PinScope<'s, '_>, diff --git a/moli-renderer-v8/src/script_vm/tests/dom_xhr/misc.rs b/moli-renderer-v8/src/script_vm/tests/dom_xhr/misc.rs index d48e582a91..7594421824 100644 --- a/moli-renderer-v8/src/script_vm/tests/dom_xhr/misc.rs +++ b/moli-renderer-v8/src/script_vm/tests/dom_xhr/misc.rs @@ -1718,6 +1718,26 @@ fn dom_rect_readonly_is_constructible_and_to_json_uses_the_function_realm() { ); } +#[test] +fn dom_rect_bounds_propagate_nan_components() { + let mut vm = new_storage_test_vm("https://domrect-nan-bounds.test/"); + + let result = vm + .eval( + r#" +(() => [DOMRect, DOMRectReadOnly].every(Rect => { + const width = new Rect(0, 0, NaN, 0).toJSON(); + const height = new Rect(0, 0, 0, NaN).toJSON(); + return Number.isNaN(width.left) && Number.isNaN(width.right) && + Number.isNaN(height.top) && Number.isNaN(height.bottom); +}))() +"#, + ) + .expect("DOMRect NaN bounds should evaluate"); + + assert_eq!(result, "true"); +} + #[test] fn geometry_domrect_private_slots_ignore_reflection_and_spoofing() { let mut vm = new_storage_test_vm("https://geometry-domrect-private-slots.test/");