From fe0375364ab1cca512701f1009461eda33fc0131 Mon Sep 17 00:00:00 2001 From: Vance Ingalls Date: Thu, 5 Nov 2026 18:52:04 -0800 Subject: [PATCH] fix(core): the filter tier's svg no longer changes which child is last in the root Co-Authored-By: Claude Sonnet 5.5 --- .../runtime/captureMotionBlur/filterTier.ts | 2 +- .../runtime/captureMotionBlur/index.test.ts | 19 +++++++++++++++++++ .../__fixtures__/motionBlur/thresholds.ts | 1 - .../captureMotionBlur.sweep.browser.test.ts | 6 ------ 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/packages/core/src/runtime/captureMotionBlur/filterTier.ts b/packages/core/src/runtime/captureMotionBlur/filterTier.ts index 7395ae62e7c..2ef7b879ffe 100644 --- a/packages/core/src/runtime/captureMotionBlur/filterTier.ts +++ b/packages/core/src/runtime/captureMotionBlur/filterTier.ts @@ -167,7 +167,7 @@ export function createFilterTier( defs.setAttribute("data-hf-ignore", ""); defs.style.cssText = "position:absolute;left:0;top:0;pointer-events:none"; node(defs, "defs", {}); - root.append(defs); + document.documentElement.append(defs); } layer = buildLayer(defs.querySelector("defs") ?? defs, layers.size, el); layers.set(el, layer); diff --git a/packages/core/src/runtime/captureMotionBlur/index.test.ts b/packages/core/src/runtime/captureMotionBlur/index.test.ts index a9caea4ab70..5b889602cc0 100644 --- a/packages/core/src/runtime/captureMotionBlur/index.test.ts +++ b/packages/core/src/runtime/captureMotionBlur/index.test.ts @@ -2078,6 +2078,25 @@ describe("filter fallback", () => { expect(h.seek.mock.calls.every(([, suppress]) => suppress === true)).toBe(true); }); + it("keeps the filter tier's svg out of the root and removes it on teardown", () => { + const { root, h } = movingHost(); + const svgs = () => document.querySelectorAll("svg[data-hf-ignore]").length; + initCaptureMotionBlur(h); + void paintCaptureMotionBlur(0.5, PLAY); + expect(root.querySelector("svg[data-hf-ignore]")).toBeNull(); + expect(svgs()).toBe(1); + initCaptureMotionBlur({ ...h, timeline: () => "tl2" }); + void paintCaptureMotionBlur(0.6, PLAY); + expect(svgs()).toBe(1); + const next = movingHost(); + initCaptureMotionBlur(next.h); + void paintCaptureMotionBlur(0.5, PLAY); + expect(next.root.querySelector("svg[data-hf-ignore]")).toBeNull(); + expect(svgs()).toBe(1); + resetCaptureMotionBlurForTests(); + expect(svgs()).toBe(0); + }); + it("removes its filters and its SVG on teardown", () => { const { el, h } = movingHost(); initCaptureMotionBlur(h); diff --git a/packages/engine/src/services/__fixtures__/motionBlur/thresholds.ts b/packages/engine/src/services/__fixtures__/motionBlur/thresholds.ts index 22c699b6135..5b585aa5591 100644 --- a/packages/engine/src/services/__fixtures__/motionBlur/thresholds.ts +++ b/packages/engine/src/services/__fixtures__/motionBlur/thresholds.ts @@ -58,7 +58,6 @@ export const SWEEP_SYMPTOMS = { F_CAPTURE: 40.62, F_FILTER: 126.54, H: 135.67, - I: 53.63, J: 25.79, K: MEASURED_ORACLE_SMALLEST_SYMPTOM, M: 18.31, diff --git a/packages/engine/src/services/captureMotionBlur.sweep.browser.test.ts b/packages/engine/src/services/captureMotionBlur.sweep.browser.test.ts index 8ffe1cede1d..3ec2b212ad5 100644 --- a/packages/engine/src/services/captureMotionBlur.sweep.browser.test.ts +++ b/packages/engine/src/services/captureMotionBlur.sweep.browser.test.ts @@ -184,12 +184,6 @@ const CASES: readonly SweepCase[] = [ tier: "filter", frame: 11, check: "outside", - bug: { - finding: "I", - reason: "the filter tier's svg becomes the root's last child, so :last-child moves to it", - regions: [rect(0, 0, 0, 0), rect(494, 14, 112, 62)], - measuredMae: S.I, - }, }, { fixture: "overflow-card",