Skip to content

Conversation

@tharkum
Copy link
Contributor

@tharkum tharkum commented Nov 25, 2025

The media session is allowed to control the state of the media element (play, pause) and is holding DOM reference, so the latest registered media element is not be able to be GCed, so let's use the weak reference to break this dependency.

Note that weakReference property was added to interfaces

  • HTMLMediaElement: The Mutable/WeakRef requires T to be bound by WeakReferenceable
  • HTMLAudio/VideoElement: The DOM_WEAK_SLOT must be reserved by concrete DOM JS class

Testing: No expected testing results changes

The media session UI functionality is implemented for Android and didn't test due lack of testing sample.

Fixes: #40854

The media session is allowed to control the state of the
media element (play, pause) and is holding DOM reference,
so the latest registered media element is not be able to
be GCed, so let's use the weak reference to break this
dependency.

Note that `weakReference` property was added to interfaces
- HTMLMediaElement:
  The `Mutable/WeakRef` requires T to be bound by `WeakReferenceable`
- HTMLAudio/VideoElement:
  The `DOM_WEAK_SLOT` must be reserved by concrete DOM JS class

Testing: No expected testing results changes

The media session UI functionality is implemented for
Android and didn't test due lack of testing sample.

Fixes: servo#40854

Signed-off-by: Andrei Volykhin <andrei.volykhin@gmail.com>
@tharkum tharkum requested a review from gterzian as a code owner November 25, 2025 05:28
@servo-highfive servo-highfive added the S-awaiting-review There is new code that needs to be reviewed. label Nov 25, 2025
@tharkum tharkum added the T-linux-wpt Do a try run of the WPT label Nov 25, 2025
@github-actions github-actions bot removed the T-linux-wpt Do a try run of the WPT label Nov 25, 2025
@github-actions
Copy link

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

@github-actions
Copy link

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

Flaky unexpected result (27)
  • 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
      

  • OK /_mozilla/webxr/create_session.https.html
    • FAIL [expected PASS] subtest: create_session

      can't access property "simulateDeviceConnection", navigator.xr.test is undefined
      

  • OK /_mozilla/webxr/obtain_frame.https.html
    • FAIL [expected PASS] subtest: obtain_frame

      promise_test: Unhandled rejection with value: object "TypeError: can't access property "simulateDeviceConnection", navigator.xr.test is undefined"
      

  • CRASH [expected OK] /_webgl/conformance2/wasm/readpixels-2gb-in-4gb-wasm-memory.html
  • OK [expected TIMEOUT] /cookiestore/httponly_cookies.https.window.html (#40697)
    • FAIL [expected TIMEOUT] subtest: HttpOnly cookies are not observed

      assert_equals: HttpOnly cookie we wrote using HTTP in cookie jar is invisible to script expected (undefined) undefined but got (string) "cspViolationReportCookie1=1"
      

    • FAIL [expected NOTRUN] subtest: HttpOnly cookies can not be set by document.cookie

      assert_equals: Trying to store an HttpOnly cookie with document.cookie fails expected "cookie1=value1; cookie3=value3" but got "HTTPONLY-cookie=value; cookie1=value1; cookie3=value3"
      

    • FAIL [expected NOTRUN] subtest: HttpOnly cookies can not be set by CookieStore

      assert_equals: httpOnly is not an option for CookieStore.set() expected "cookie1=value1; cookie2=value2; cookie3=value3" but got "HTTPONLY-cookie=value; cookie1=value1; cookie2=value2; cookie3=value3"
      

    • FAIL [expected NOTRUN] subtest: HttpOnly cookies are not deleted/overwritten

      assert_equals: HttpOnly cookie is not deleted expected (string) "HTTPONLY-cookie=value" but got (undefined) undefined
      

  • CRASH [expected OK] /cookiestore/idlharness.https.any.worker.html
  • OK /custom-elements/form-associated/ElementInternals-setFormValue.html (#29174)
    • PASS [expected FAIL] subtest: Single value - empty name exists
  • OK /fetch/fetch-later/send-on-discard/not-send-after-abort.https.window.html (#40696)
    • FAIL [expected PASS] subtest: A discarded document does not send an already aborted fetchLater request.

      assert_equals: Number of sent beacons does not match expected count: expected 1 but got 0
      

  • OK [expected ERROR] /focus/focus-event-after-switching-iframes.sub.html (#40368)
  • CRASH [expected OK] /html/browsers/windows/browsing-context.html
  • CRASH [expected OK] /html/canvas/element/fill-and-stroke-styles/2d.fillStyle.parse.hsl-5.html
  • OK /html/dom/documents/resource-metadata-management/document-cookie.html (#40673)
    • FAIL [expected PASS] subtest: document has no cookie

      assert_equals: expected "" but got "domain-attribute-matches-host=0"
      

    • FAIL [expected PASS] subtest: document.cookie

      assert_equals: expected "" but got "domain-attribute-matches-host=0"
      

    • FAIL [expected PASS] subtest: document.cookie 1

      assert_equals: expected "a=b" but got "a=b; domain-attribute-matches-host=0"
      

    • FAIL [expected PASS] subtest: document.cookie 2

      assert_equals: expected "" but got "a=b; domain-attribute-matches-host=0"
      

  • TIMEOUT /html/interaction/focus/the-autofocus-attribute/supported-elements.html (#24145)
    • FAIL [expected TIMEOUT] subtest: Element with tabindex should support autofocus

      assert_equals: expected "SPAN" but got "BODY"
      

    • PASS [expected NOTRUN] subtest: Non-HTMLElement should not support autofocus
    • FAIL [expected NOTRUN] subtest: Host element with delegatesFocus should support autofocus

      assert_equals: expected Element node &lt;div autofocus=""&gt;&lt;/div&gt; but got Element node &lt;body&gt;&lt;div autofocus=""&gt;&lt;/div&gt;&lt;/body&gt;
      

    • TIMEOUT [expected NOTRUN] subtest: Host element with delegatesFocus including no focusable descendants should be skipped

      Test timed out
      

  • OK /html/semantics/forms/form-submission-0/jsurl-form-submit.tentative.html (#36489)
    • PASS [expected FAIL] subtest: Verifies that form submissions scheduled inside javascript: urls take precedence over the javascript: url's return value.
  • OK /html/semantics/forms/form-submission-0/multipart-formdata.window.html (#28725)
    • PASS [expected FAIL] subtest: multipart/form-data: 0x00 in value (normal form)
  • OK /html/semantics/forms/form-submission-0/text-plain.window.html (#28687)
    • FAIL [expected PASS] subtest: text/plain: Basic File test (normal form)

      assert_equals: expected "basic=file-test.txt\r\n" but got ""
      

    • PASS [expected FAIL] subtest: text/plain: 0x00 in name (normal form)
    • PASS [expected FAIL] subtest: text/plain: 0x00 in value (formdata event)
    • PASS [expected FAIL] subtest: text/plain: backslash in name (formdata event)
  • OK /html/semantics/forms/form-submission-0/urlencoded2.window.html (#28687)
    • FAIL [expected PASS] subtest: application/x-www-form-urlencoded: Basic test (formdata event)

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

    • FAIL [expected PASS] subtest: application/x-www-form-urlencoded: Basic File test (normal form)

      assert_equals: expected "basic=file-test.txt" but got ""
      

    • PASS [expected FAIL] subtest: application/x-www-form-urlencoded: Basic File test (formdata event)
    • PASS [expected FAIL] subtest: application/x-www-form-urlencoded: 0x00 in name (formdata event)
    • PASS [expected FAIL] subtest: application/x-www-form-urlencoded: 0x00 in filename (formdata event)
    • PASS [expected FAIL] subtest: application/x-www-form-urlencoded: non-ASCII in name and value (formdata event)
  • OK [expected CRASH] /html/semantics/forms/the-fieldset-element/disabled-003.html (#31730, #39631)
  • OK /html/semantics/scripting-1/the-script-element/execution-timing/077.html (#22139)
    • FAIL [expected PASS] subtest: adding several types of scripts through the DOM and removing some of them confuses scheduler

      assert_array_equals: expected property 1 to be "Script #1 ran" but got "Script #3 ran" (expected array ["Script #2 ran", "Script #1 ran", "Script #3 ran", "Script #4 ran"] got ["Script #2 ran", "Script #3 ran", "Script #4 ran", "Script #1 ran"])
      

  • OK /html/semantics/scripting-1/the-script-element/module/dynamic-import/blob-url.any.html (#33948)
    • FAIL [expected PASS] subtest: Revoking a blob URL immediately after calling import will not fail

      promise_test: Unhandled rejection with value: object "TypeError: Dynamic import failed"
      

  • OK [expected ERROR] /html/user-activation/no-activation-thru-escape-key.html (#40343)
  • OK /navigation-timing/test-navigation-type-reload.html (#33334)
    • PASS [expected FAIL] subtest: Reload domComplete &gt; Original domComplete
    • PASS [expected FAIL] subtest: Reload domContentLoadedEventStart &gt; Original domContentLoadedEventStart
    • PASS [expected FAIL] subtest: Reload domInteractive &gt; Original domInteractive
    • PASS [expected FAIL] subtest: Reload fetchStart &gt; Original fetchStart
    • PASS [expected FAIL] subtest: Reload loadEventEnd &gt; Original loadEventEnd
    • PASS [expected FAIL] subtest: Reload loadEventStart &gt; Original loadEventStart
  • CRASH [expected OK] /shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/ownerdocument-002.html
  • OK [expected TIMEOUT] /trusted-types/trusted-types-navigation.html?06-10 (#37920)
    • PASS [expected FAIL] subtest: Navigate a frame via anchor with javascript:-urls in report-only mode.
    • PASS [expected TIMEOUT] subtest: Navigate a frame via anchor with javascript:-urls w/ default policy in report-only mode.
    • FAIL [expected NOTRUN] subtest: Navigate a window via anchor with javascript:-urls w/ a default policy throwing an exception in enforcing mode.

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

    • FAIL [expected NOTRUN] subtest: Navigate a window via anchor with javascript:-urls w/ a default policy throwing an exception in report-only mode.

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

  • CRASH [expected OK] /uievents/order-of-events/mouse-events/click-order.html
  • CRASH [expected ERROR] /wasm/webapi/invalid-code.any.sharedworker.html
  • OK /webxr/xrSession_features_deviceSupport.https.html (#24357)
    • FAIL [expected PASS] subtest: Immersive XRSession requests with no supported device should reject

      assert_unreached: Should have rejected: undefined Reached unreachable code
      

Stable unexpected results that are known to be intermittent (25)
  • TIMEOUT /FileAPI/url/url-in-tags-revoke.window.html (#19978)
    • TIMEOUT [expected PASS] subtest: Fetching a blob URL immediately before revoking it works in &lt;script&gt; tags.

      Test timed out
      

  • 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()
  • 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/textures/misc/texture-upload-size.html (#21770)
    • PASS [expected FAIL] subtest: WebGL test #45
    • PASS [expected FAIL] subtest: WebGL test #47
    • PASS [expected FAIL] subtest: WebGL test #49
    • PASS [expected FAIL] subtest: WebGL test #51
    • FAIL [expected PASS] subtest: WebGL test #53

      assert_true: Texture was smaller than the expected size 2x2 expected true got false
      

    • FAIL [expected PASS] subtest: WebGL test #55

      assert_true: getError expected: INVALID_VALUE. Was NO_ERROR : when calling texSubImage2D with the same texture upload with offset 1, 1 expected true got false
      

    • FAIL [expected PASS] subtest: WebGL test #57

      assert_true: Texture was smaller than the expected size 2x2 expected true got false
      

    • FAIL [expected PASS] subtest: WebGL test #59

      assert_true: getError expected: INVALID_VALUE. Was NO_ERROR : when calling texSubImage2D with the same texture upload with offset 1, 1 expected true got false
      

    • PASS [expected FAIL] subtest: WebGL test #61
    • PASS [expected FAIL] subtest: WebGL test #63
    • And 10 more unexpected results...
  • 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-grid/grid-lanes/tentative/alignment/row-grid-lanes-align-self-003.html (#40833)
  • FAIL [expected PASS] /css/css-grid/grid-lanes/tentative/grid-placement/row-explicit-placement-004.html (#40834)
  • FAIL [expected PASS] /css/css-grid/masonry/tentative/subgrid/column/masonry-subgrid-002f.html (#40830)
  • OK /fetch/metadata/generated/css-font-face.https.sub.tentative.html (#32732)
    • PASS [expected FAIL] subtest: sec-fetch-dest
    • PASS [expected FAIL] subtest: sec-fetch-user
    • FAIL [expected PASS] subtest: sec-fetch-storage-access - Cross-site

      promise_test: Unhandled rejection with value: object "Error: Failed to query for recorded headers."
      

    • PASS [expected FAIL] subtest: sec-fetch-storage-access - Same site
  • OK /fetch/metadata/generated/css-font-face.sub.tentative.html (#34624)
    • FAIL [expected PASS] subtest: sec-fetch-storage-access - Not sent to non-trustworthy same-site destination

      promise_test: Unhandled rejection with value: object "Error: Failed to query for recorded headers."
      

    • PASS [expected FAIL] subtest: sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination
  • OK /fetch/metadata/generated/element-img-environment-change.https.sub.html (#30111)
    • PASS [expected FAIL] subtest: sec-fetch-site - Cross-site, no attributes
    • PASS [expected FAIL] subtest: sec-fetch-site - Same-Origin -&gt; Same Origin, no attributes
    • PASS [expected FAIL] subtest: sec-fetch-mode - no attributes
    • FAIL [expected PASS] subtest: sec-fetch-mode - attributes: crossorigin

      promise_test: Unhandled rejection with value: object "Error: Failed to query for recorded headers."
      

    • PASS [expected FAIL] subtest: sec-fetch-mode - attributes: crossorigin=anonymous
    • FAIL [expected PASS] subtest: sec-fetch-mode - attributes: crossorigin=use-credentials

      promise_test: Unhandled rejection with value: object "Error: Failed to query for recorded headers."
      

    • PASS [expected FAIL] subtest: sec-fetch-dest - no attributes
    • PASS [expected FAIL] subtest: sec-fetch-storage-access - Same site, no attributes
  • OK /fetch/metadata/generated/element-img-environment-change.sub.html (#30111)
    • PASS [expected FAIL] subtest: sec-fetch-site - Not sent to non-trustworthy same-site destination, no attributes
    • PASS [expected FAIL] subtest: sec-fetch-mode - Not sent to non-trustworthy cross-site destination, no attributes
    • PASS [expected FAIL] subtest: sec-fetch-dest - Not sent to non-trustworthy cross-site destination, no attributes
    • PASS [expected FAIL] subtest: sec-fetch-user - Not sent to non-trustworthy cross-site destination, no attributes
  • ERROR /fetch/metadata/generated/serviceworker.https.sub.html (#36247)
    • FAIL [expected PASS] subtest: sec-fetch-site - Same origin, no options - registration

      promise_test: Unhandled rejection with value: object "Error: Failed to query for recorded headers."
      

  • OK /html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-same-origin-fragment.html (#20768)
    • PASS [expected FAIL] subtest: Tests that a fragment navigation in the unload handler will not block the initial navigation
  • 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 [expected TIMEOUT] /html/interaction/focus/the-autofocus-attribute/autofocus-dialog.html (#29087)
    • FAIL [expected TIMEOUT] subtest: &lt;dialog&gt;-contained autofocus element gets focused when the dialog is shown

      assert_equals: expected "DIV" but got "BODY"
      

  • OK /html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/allow-scripts-flag-changing-2.html (#39703)
    • FAIL [expected PASS] subtest: Meta refresh of the original iframe is not blocked if moved into a sandboxed iframe

      uncaught exception: Error: assert_unreached: The iframe into which the meta was moved must not refresh Reached unreachable code
      

  • OK /html/webappapis/user-prompts/print-during-unload.html (#35944)
    • FAIL [expected PASS] subtest: print() during unload

      assert_array_equals: expected property 1 to be "destination" but got "error: window.print is not a function" (expected array ["start", "destination"] got ["start", "error: window.print is not a function"])
      

  • CRASH [expected OK] /pointerevents/compat/pointerevent_touch-action_two-finger_interaction.html (#40418)
  • OK /preload/preload-error.sub.html (#37177)
    • FAIL [expected PASS] subtest: 404 (fetch): main

      assert_greater_than: http://web-platform.test:8000/preload/resources/dummy.xml?pipe=status%28404%29&amp;label=fetch should be loaded expected a number greater than 0 but got 0
      

  • OK [expected ERROR] /resource-timing/cors-preflight.any.html (#28694)
  • TIMEOUT [expected OK] /trusted-types/trusted-types-navigation.html?26-30 (#38807)
    • TIMEOUT [expected FAIL] subtest: Navigate a window via form-submission with javascript:-urls in report-only mode.

      Test timed out
      

    • NOTRUN [expected PASS] subtest: Navigate a window via form-submission with javascript:-urls w/ default policy in report-only mode.
    • NOTRUN [expected FAIL] subtest: Navigate a frame via form-submission with javascript:-urls in enforcing mode.
    • NOTRUN [expected PASS] subtest: Navigate a frame via form-submission with javascript:-urls w/ default policy in enforcing mode.
  • TIMEOUT /trusted-types/trusted-types-navigation.html?31-35 (#38034)
    • TIMEOUT [expected PASS] subtest: Navigate a frame via form-submission with javascript:-urls in report-only mode.

      Test timed out
      

    • NOTRUN [expected TIMEOUT] subtest: Navigate a frame via form-submission with javascript:-urls w/ default policy in report-only mode.

@github-actions
Copy link

✨ Try run (#19659490102) succeeded.

@servo-highfive servo-highfive removed the S-awaiting-review There is new code that needs to be reviewed. label Nov 25, 2025
@TimvdLippe TimvdLippe added this pull request to the merge queue Nov 25, 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 Nov 25, 2025
Merged via the queue into servo:main with commit cdb6c5c Nov 25, 2025
73 checks passed
@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 Nov 25, 2025
@tharkum tharkum deleted the html-media-session-weakref-media-element branch November 25, 2025 08:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The MediaSession holds DOM reference to the media element

3 participants