Skip to content

layout: Clone static position rectangles when caching in IndependentFormattingContext#39591

Merged
mrobinson merged 1 commit intoservo:mainfrom
mrobinson:incremental-layout-static-position-rectangle
Oct 1, 2025
Merged

layout: Clone static position rectangles when caching in IndependentFormattingContext#39591
mrobinson merged 1 commit intoservo:mainfrom
mrobinson:incremental-layout-static-position-rectangle

Conversation

@mrobinson
Copy link
Copy Markdown
Member

@mrobinson mrobinson commented Sep 30, 2025

Hoisted absolutes that are cached in IndependentFormattingContexts may
have their HoistedSharedFragment reused between layouts. This means
that the original value of the adjusted static positioning rectangles
need to be preserved in cache. This change makes it so that these values
are cloned when being retrieved from the cache. Further adjustments up
the tree will now no longer affected the version in teh cache.

Testing: This should cause /_mozilla/css/stacked_layers.html to no longer
be flaky.
Fixes: #39548.
Fixes: #39439.

@servo-highfive servo-highfive added the S-awaiting-review There is new code that needs to be reviewed. label Sep 30, 2025
@Loirooriol Loirooriol added the T-linux-wpt Do a try run of the WPT label Sep 30, 2025
@github-actions github-actions bot removed the T-linux-wpt Do a try run of the WPT label Sep 30, 2025
@github-actions
Copy link
Copy Markdown

🔨 Triggering try run (#18136551354) for Linux (WPT)

@github-actions
Copy link
Copy Markdown

Test results for linux-wpt from try job (#18136551354):

Flaky unexpected result (30)
  • OK /FileAPI/url/url-with-fetch.any.worker.html (#21517)
    • FAIL [expected PASS] subtest: Revoke blob URL after calling fetch, fetch should succeed

      promise_test: Unhandled rejection with value: object "TypeError: Network error occurred"
      

  • OK /IndexedDB/idbfactory_open.any.html
    • FAIL [expected PASS] subtest: Calling open() with version argument 1.5 should not throw.

      assert_equals: version expected 1 but got 9007199254740991
      

  • FAIL [expected PASS] /css/CSS2/css1/c5508-ipadn-b-003.xht
  • FAIL [expected PASS] /css/CSS2/normal-flow/max-width-084.xht
  • FAIL [expected PASS] /css/CSS2/text/letter-spacing-032.xht
  • FAIL [expected PASS] /css/WOFF2/metadatadisplay-schema-description-010.xht
  • FAIL [expected PASS] /css/WOFF2/metadatadisplay-schema-description-011.xht
  • FAIL [expected PASS] /css/css-fonts/font-palette-11.html
  • FAIL [expected PASS] /css/css-fonts/font-palette-23.html
  • OK /css/css-fonts/generic-family-keywords-001.html (#37467)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted generic(fangsong)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted generic(kai)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted generic(nastaliq)
  • FAIL [expected PASS] /css/css-tables/paint/table-border-paint-caption-change.html (#38036)
  • FAIL [expected PASS] /css/css-transforms/transform-applies-to-002.xht
  • FAIL [expected PASS] /css/css-transforms/transform-input-009.html
  • ERROR [expected TIMEOUT] /fetch/fetch-later/quota/same-origin-iframe/max-payload.https.window.html (#35210)
  • OK /fetch/metadata/generated/css-font-face.https.sub.tentative.html (#32732)
    • PASS [expected FAIL] subtest: sec-fetch-storage-access - Same site
  • OK /fetch/metadata/generated/css-font-face.sub.tentative.html (#34624)
    • PASS [expected FAIL] subtest: sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination
    • PASS [expected FAIL] subtest: sec-fetch-storage-access - Not sent to non-trustworthy same-site destination
  • TIMEOUT /fetch/metadata/generated/css-images.https.sub.tentative.html
    • TIMEOUT [expected PASS] subtest: background-image sec-fetch-user

      Test timed out
      

    • TIMEOUT [expected PASS] subtest: background-image sec-fetch-storage-access - Same site

      Test timed out
      

  • OK /html/browsers/browsing-the-web/navigating-across-documents/009.html (#24456)
    • PASS [expected FAIL] subtest: Link with onclick form submit to javascript url with document.write and href navigation
  • OK /html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/iframe-nosrc.html (#34819)
    • PASS [expected FAIL] subtest: form submission
  • OK /html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/load-pageshow-events-iframe-contentWindow.html (#28681)
    • FAIL [expected PASS] subtest: load & pageshow events do not fire on contentWindow of <iframe> element created with src='about:blank'

      assert_unreached: load should not be fired Reached unreachable code
      

  • OK /html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/load-pageshow-events-window-open.html (#28691)
    • FAIL [expected PASS] subtest: load event does not fire on window.open('about:blank')

      assert_unreached: load should not be fired Reached unreachable code
      

  • OK /html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/a-click.html (#28697)
    • PASS [expected FAIL] subtest: aElement.click() before the load event must NOT replace
  • OK /html/browsers/history/the-history-interface/traverse_the_history_4.html (#21383)
    • PASS [expected FAIL] subtest: Multiple history traversals, last would be aborted
  • OK [expected CRASH] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-3.html (#24057)
    • FAIL [expected TIMEOUT] subtest: Check that popups from a sandboxed iframe escape the sandbox if allow-popups-to-escape-sandbox is used

      assert_equals: It came from a sandboxed iframe expected "null" but got "http://web-platform.test:8000"
      

  • OK /html/semantics/forms/form-submission-0/urlencoded2.window.html (#28687)
    • FAIL [expected PASS] subtest: application/x-www-form-urlencoded: Basic test (normal form)

      assert_equals: expected "basic=test" but got ""
      

  • FAIL [expected PASS] /shadow-dom/shadow-style-invalidation-vw-units.html (#38468)
  • OK /webdriver/tests/classic/find_element_from_shadow_root/find.py
    • FAIL [expected PASS] subtest: test_null_parameter_value

      webdriver.error.NoSuchElementException: no such element (404)
      

  • TIMEOUT [expected OK] /webdriver/tests/classic/perform_actions/navigation.py (#38822)
  • OK /webdriver/tests/classic/take_element_screenshot/scroll_into_view.py (#39306)
    • PASS [expected FAIL] subtest: test_scroll_into_view
  • TIMEOUT [expected OK] /webstorage/localstorage-about-blank-3P-iframe-opens-3P-window.partitioned.html (#29053)
    • TIMEOUT [expected PASS] subtest: StorageKey: test 3P about:blank window opened from a 3P iframe

      Test timed out
      

Stable unexpected results that are known to be intermittent (30)
  • OK /IndexedDB/idbcursor-continuePrimaryKey-exceptions.any.worker.html (#39277)
    • FAIL [expected PASS] subtest: IDBCursor continuePrimaryKey() on object store cursor

      assert_throws_dom: continuePrimaryKey() should throw if source is not an index function "function() {
              cursor.continuePrimaryKey(2, 2);
            }" threw object "TypeError: cursor.continuePrimaryKey is not a function" that is not a DOMException InvalidAccessError: property "code" is equal to undefined, expected 15
      

  • OK /IndexedDB/idbobjectstore_get.any.html (#38942)
    • PASS [expected FAIL] subtest: Attempts to retrieve a record that doesn't exist
  • OK /IndexedDB/idbobjectstore_getAll.any.html (#39276)
    • PASS [expected FAIL] subtest: Get all values with transaction.commit()
  • OK /IndexedDB/idbobjectstore_getAll.any.worker.html (#39400)
    • PASS [expected FAIL] subtest: Get all values with transaction.commit()
  • OK /IndexedDB/key-conversion-exceptions.any.html (#39305)
    • FAIL [expected PASS] subtest: IDBCursor continue() method with throwing/invalid keys

      assert_throws_exactly: key conversion with throwing getter should rethrow function "() => {
            receiver[method](key);
          }" threw object "TypeError: receiver[method] is not a function" but we expected it to throw object "getter: throwing from getter"
      

  • OK /IndexedDB/key-conversion-exceptions.any.worker.html (#39284)
    • FAIL [expected PASS] subtest: IDBCursor continue() method with throwing/invalid keys

      assert_throws_exactly: key conversion with throwing getter should rethrow function "() => {
            receiver[method](key);
          }" threw object "TypeError: receiver[method] is not a function" but we expected it to throw object "getter: throwing from getter"
      

  • FAIL [expected PASS] /_mozilla/mozilla/sslfail.html (#10760)
  • TIMEOUT [expected OK] /_mozilla/mozilla/window_resize_event.html (#36741)
    • TIMEOUT [expected PASS] subtest: Popup onresize event fires after resizeTo

      Test timed out
      

  • OK /_webgl/conformance/rendering/texture-switch-performance.html (#23384)
    • FAIL [expected PASS] subtest: WebGL test #0

      assert_true: Texture switching significantly hurt performance - achieved 65 frames in 2.001 seconds (0.38 times baseline performance) expected true got false
      

  • OK /_webgl/conformance2/rendering/texture-switch-performance.html (#23384)
    • FAIL [expected PASS] subtest: WebGL test #0

      assert_true: Texture switching significantly hurt performance - achieved 98 frames in 2.005 seconds (0.57 times baseline performance) expected true got false
      

  • OK /content-security-policy/frame-ancestors/frame-ancestors-path-ignored.window.html (#36468)
    • PASS [expected FAIL] subtest: A 'frame-ancestors' CSP directive with a URL that includes a path should be ignored.
  • OK /css/css-cascade/layer-font-face-override.html (#35935)
    • FAIL [expected PASS] subtest: @font-face override update with appended sheet 1

      assert_equals: expected "80px" but got "38.3166666666667px"
      

    • FAIL [expected PASS] subtest: @font-face override update with appended sheet 2

      assert_equals: expected "80px" but got "38.3166666666667px"
      

  • OK /css/css-fonts/generic-family-keywords-003.html (#38994)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted serif (drawing text in a canvas)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted ui-sans-serif (drawing text in a canvas)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted ui-monospace (drawing text in a canvas)
  • TIMEOUT [expected FAIL] /dom/xslt/large-cdata.html (#38029)
  • OK /html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-cross-origin.sub.window.html (#29056)
    • FAIL [expected PASS] subtest: Cross-origin navigation started from unload handler must be ignored

      promise_test: Unhandled rejection with value: object "SecurityError: The operation is insecure."
      

  • OK /html/browsers/browsing-the-web/navigating-across-documents/refresh/same-document-refresh.html (#34597)
    • FAIL [expected PASS] subtest: Same-Document Referrer from Refresh

      assert_equals: original page loads expected "http://web-platform.test:8000/html/browsers/browsing-the-web/navigating-across-documents/refresh/resources/refresh-with-section.sub.html?url=%23section" but got "http://web-platform.test:8000/html/browsers/browsing-the-web/navigating-across-documents/refresh/resources/refresh-with-section.sub.html?url=%23section#section"
      

  • TIMEOUT /html/browsers/history/the-history-interface/001.html (#12580)
    • FAIL [expected PASS] subtest: traversing history must also traverse hash changes

      assert_equals: (this could cause other failures later on) expected "" but got "test"
      

  • OK [expected CRASH] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-1.html (#22647)
  • TIMEOUT [expected OK] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-2.html (#22667)
    • TIMEOUT [expected FAIL] subtest: Check that popups from a sandboxed iframe escape the sandbox if allow-popups-to-escape-sandbox is used

      Test timed out
      

  • TIMEOUT [expected CRASH] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-1.html (#24066)
    • NOTRUN [expected FAIL] subtest: Check that popups from a sandboxed iframe do not escape the sandbox
  • CRASH [expected OK] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-2.html (#22154)
  • TIMEOUT [expected OK] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-3.html (#24066)
    • NOTRUN [expected FAIL] subtest: Check that popups from a sandboxed iframe do not escape the sandbox
  • OK /navigation-timing/test-navigation-type-reload.html (#33334)
    • PASS [expected FAIL] subtest: Reload domComplete > Original domComplete
    • PASS [expected FAIL] subtest: Reload domContentLoadedEventEnd > Original domContentLoadedEventEnd
    • PASS [expected FAIL] subtest: Reload domContentLoadedEventStart > Original domContentLoadedEventStart
    • PASS [expected FAIL] subtest: Reload domInteractive > Original domInteractive
    • PASS [expected FAIL] subtest: Reload fetchStart > Original fetchStart
    • PASS [expected FAIL] subtest: Reload loadEventEnd > Original loadEventEnd
    • PASS [expected FAIL] subtest: Reload loadEventStart > Original loadEventStart
  • OK /preload/preload-error.sub.html (#37177)
    • PASS [expected FAIL] subtest: success (fetch): main
    • PASS [expected FAIL] subtest: CORS (fetch): main
  • TIMEOUT /preload/preload-resource-match.https.html (#38088)
    • PASS [expected TIMEOUT] subtest: Loading module (use-credentials) with link (anonymous) should discard the preloaded response
    • PASS [expected NOTRUN] subtest: Loading module (use-credentials) with link (use-credentials) should reuse the preloaded response
    • PASS [expected NOTRUN] subtest: Loading style (same-origin) with link (same-origin) should reuse the preloaded response
    • PASS [expected NOTRUN] subtest: Loading style (no-cors) with link (no-cors) should reuse the preloaded response
    • PASS [expected NOTRUN] subtest: Loading style (no-cors) with link (anonymous) should discard the preloaded response
    • PASS [expected NOTRUN] subtest: Loading style (no-cors) with link (use-credentials) should discard the preloaded response
    • PASS [expected NOTRUN] subtest: Loading style (anonymous) with link (no-cors) should discard the preloaded response
    • PASS [expected NOTRUN] subtest: Loading style (anonymous) with link (anonymous) should reuse the preloaded response
    • PASS [expected NOTRUN] subtest: Loading style (anonymous) with link (use-credentials) should discard the preloaded response
    • PASS [expected NOTRUN] subtest: Loading style (use-credentials) with link (no-cors) should discard the preloaded response
    • And 1 more unexpected results...
  • TIMEOUT /resource-timing/nested-context-navigations-iframe.html (#24311)
    • PASS [expected TIMEOUT] subtest: Test that crossorigin iframe navigations are not observable by the parent, even after history navigations by the parent
    • TIMEOUT [expected NOTRUN] subtest: Test that cross-site iframe navigations are not observable by the parent, even after history navigations by the parent

      Test timed out
      

  • OK /trusted-types/trusted-types-navigation.html?21-25 (#38997)
    • FAIL [expected PASS] subtest: Navigate a window via form-submission with javascript:-urls in enforcing mode.

      promise_test: Unhandled rejection with value: "Unexpected message received: \"No securitypolicyviolation reported!\""
      

  • OK /trusted-types/trusted-types-navigation.html?26-30 (#38807)
    • FAIL [expected PASS] subtest: Navigate a window via form-submission with javascript:-urls in report-only mode.

      promise_test: Unhandled rejection with value: "Unexpected message received: \"No securitypolicyviolation reported!\""
      

  • OK [expected ERROR] /webxr/render_state_update.https.html (#27535)
  • OK [expected ERROR] /workers/baseurl/alpha/sharedworker-in-worker.html (#21315)
Stable unexpected results (1)
  • OK /preload/link-header-preload-delay-onload.html
    • FAIL [expected PASS] subtest: Makes sure that Link headers preload resources and block window.onload after resource discovery

      assert_true: expected true got false
      

@github-actions
Copy link
Copy Markdown

⚠️ Try run (#18136551354) failed.


fn static_position_rect(&self) -> PhysicalRect<Au> {
self.adjusted_static_position_rect
.unwrap_or(self.fragment.borrow().original_static_position_rect)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe unwrap_or_else to avoid borrowing when not necessary?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense!

@servo-highfive servo-highfive removed the S-awaiting-review There is new code that needs to be reviewed. label Sep 30, 2025
…ormattingContext

Hoisted absolutes that are cached in IndependentFormattingContexts may
have their HoistedSharedFragment resused between layouts. This means
that the original value of the adjusted static positioning rectangles
need to be preserved in cache. This change makes it so that these values
are cloned when being retrieved from the cache. Further adjustments up
the tree will now no longer affected the version in teh cache.

Signed-off-by: Martin Robinson <[email protected]>
Co-authored-by: Oriol Brufau <[email protected]>
@mrobinson mrobinson force-pushed the incremental-layout-static-position-rectangle branch from d5d3216 to 5369f25 Compare October 1, 2025 06:09
@servo-highfive servo-highfive added the S-awaiting-review There is new code that needs to be reviewed. label Oct 1, 2025
@mrobinson mrobinson changed the title layout: Clone static position rectangles when caching in IndependentFormattingContext layout: Clone static position rectangles when caching in IndependentFormattingContext Oct 1, 2025
@mrobinson mrobinson enabled auto-merge October 1, 2025 06:09
@mrobinson mrobinson added this pull request to the merge queue Oct 1, 2025
@servo-highfive servo-highfive added the S-awaiting-merge The PR is in the process of compiling and running tests on the automated CI. label Oct 1, 2025
Merged via the queue into servo:main with commit a2f551e Oct 1, 2025
29 checks passed
@mrobinson mrobinson deleted the incremental-layout-static-position-rectangle branch October 1, 2025 07:22
@servo-highfive servo-highfive removed the S-awaiting-merge The PR is in the process of compiling and running tests on the automated CI. label Oct 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-awaiting-review There is new code that needs to be reviewed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Intermittent FAIL in /_mozilla/css/stacked_layers.html Moving the mouse can cause absolutely positioned elements to move around

3 participants