Skip to content

Force callers to claim blob url before making a fetch request#43746

Merged
simonwuelker merged 12 commits into
servo:mainfrom
simonwuelker:blob-url-early-claim-3
Apr 6, 2026
Merged

Force callers to claim blob url before making a fetch request#43746
simonwuelker merged 12 commits into
servo:mainfrom
simonwuelker:blob-url-early-claim-3

Conversation

@simonwuelker

@simonwuelker simonwuelker commented Mar 29, 2026

Copy link
Copy Markdown
Member

blob URLs have a implicit blob URL entry attached, which stores the data contained in the blob. The specification requires this entry to be resolved as the URL is parsed. We only resolve it inside net when loading the URL. That causes problems if the blob entry has been revoked in the meantime - see #25226.

Ideally we would want to resolve blobs at parse-time as required. But because ServoUrl is such a fundamental type, I've not managed to do this change without having to touch hundreds of files at once.

Thus, we now require passing a UrlWithBlobClaim instead of a ServoUrl when fetch-ing. This type proves that the caller has acquired the blob beforehand.

As a temporary escape hatch, I've added UrlWithBlobClaim::from_url_without_having_claimed_blob. That method logs a warning if its used unsafely. This method is currently used in most places to keep this change small. Only workers now acquire the blob beforehand.

Testing: A new test starts to pass
Part of #43326
Part of #25226

@simonwuelker simonwuelker added the T-linux-wpt Do a try run of the WPT label Mar 29, 2026
@github-actions github-actions Bot removed the T-linux-wpt Do a try run of the WPT label Mar 29, 2026
@github-actions

Copy link
Copy Markdown

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

@codecov-commenter

Copy link
Copy Markdown

⚠️ JUnit XML file not found

The CLI was unable to find any JUnit XML files to upload.
For more help, visit our troubleshooting guide.

@github-actions

Copy link
Copy Markdown

⚠️ Try run (#23706408001) failed!

@simonwuelker simonwuelker added the T-linux-wpt Do a try run of the WPT label Mar 29, 2026
@github-actions github-actions Bot removed the T-linux-wpt Do a try run of the WPT label Mar 29, 2026
@github-actions

Copy link
Copy Markdown

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

@github-actions

Copy link
Copy Markdown

⚠️ Try run (#23708152035) failed!

@simonwuelker simonwuelker added the T-linux-wpt Do a try run of the WPT label Mar 29, 2026
@github-actions github-actions Bot removed the T-linux-wpt Do a try run of the WPT label Mar 29, 2026
@github-actions

Copy link
Copy Markdown

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

@github-actions

Copy link
Copy Markdown

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

Flaky unexpected result (33)
  • OK /IndexedDB/idbtransaction-oncomplete.any.worker.html (#42804)
    • FAIL [expected PASS] subtest: IDBTransaction - complete event

      assert_array_equals: lengths differ, expected array ["upgradeneeded", "complete", "success", "opencursor"] length 4, got ["upgradeneeded", "complete", "success"] length 3
      

  • OK /_mozilla/css/offset_properties_inline.html (#40543)
    • FAIL [expected PASS] subtest: offsetTop

      assert_equals: offsetTop of #inline-1 should be 0. expected 0 but got -1
      

    • FAIL [expected PASS] subtest: offsetLeft

      assert_equals: offsetLeft of #inline-2 should be 40. expected 40 but got 25
      

  • OK /_mozilla/mozilla/getBoundingClientRect.html (#39668)
    • FAIL [expected PASS] subtest: getBoundingClientRect 1

      assert_equals: expected 62 but got 60.35
      

  • FAIL [expected PASS] /css/css-backgrounds/background-size-041.html
  • OK /css/css-cascade/layer-cssom-order-reverse.html (#36094)
    • FAIL [expected PASS] subtest: Delete layer invalidates @font-face

      assert_equals: expected "220px" but got "133px"
      

  • TIMEOUT [expected OK] /fetch/api/redirect/redirect-keepalive.https.any.html (#32153)
    • TIMEOUT [expected PASS] subtest: [keepalive][iframe][load] mixed content redirect; setting up

      Test timed out
      

  • OK [expected ERROR] /fetch/fetch-later/quota/same-origin-iframe/multiple-iframes.https.window.html (#35176)
  • 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)
    • FAIL [expected PASS] subtest: aElement.click() before the load event must NOT replace

      assert_equals: expected "http://web-platform.test:8000/common/blank.html?thereplacement" but got "http://web-platform.test:8000/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/resources/code-injector.html?pipe=sub(none)&code=%0A%20%20%20%20const%20a%20%3D%20document.createElement(%22a%22)%3B%0A%20%20%20%20a.href%20%3D%20%22%2Fcommon%2Fblank.html%3Fthereplacement%22%3B%0A%20%20%20%20document.currentScript.before(a)%3B%0A%20%20%20%20a.click()%3B%0A%20%20"
      

  • CRASH [expected OK] /html/browsers/browsing-the-web/unloading-documents/beforeunload-canceling.html
  • OK /html/browsers/history/the-history-interface/traverse_the_history_2.html (#21383)
    • PASS [expected FAIL] subtest: Multiple history traversals, last would be aborted
  • ERROR [expected OK] /html/canvas/offscreen/text/2d.text.measure.getActualBoundingBox.tentative.html (#43710)
  • CRASH [expected TIMEOUT] /html/canvas/offscreen/text/2d.text.measure.strokeTextCluster-align.tentative.w.html
  • OK [expected TIMEOUT] /html/infrastructure/urls/base-url/document-base-url-window-initiator-is-not-opener.https.window.html (#30970)
  • OK [expected TIMEOUT] /html/interaction/focus/the-autofocus-attribute/supported-elements.html (#24145)
    • PASS [expected TIMEOUT] subtest: Non-HTMLElement should not support autofocus
    • FAIL [expected NOTRUN] subtest: Host element with delegatesFocus should support autofocus

      assert_equals: expected Element node <div autofocus=""></div> but got Element node <body><div autofocus=""></div></body>
      

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

      assert_equals: expected Element node <input autofocus=""></input> but got Element node <body><div autofocus=""></div><input autofocus=""></body>
      

    • FAIL [expected NOTRUN] subtest: Area element should support autofocus

      promise_test: Unhandled rejection with value: object "TypeError: can't access property "appendChild", w.document.querySelector(...) is null"
      

  • OK /html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/allow-scripts-flag-changing-1.html (#39694)
    • PASS [expected FAIL] subtest: Meta refresh is blocked by the allow-scripts sandbox flag at its creation time, not when refresh comes due
  • TIMEOUT [expected OK] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigate_other_frame_popup.sub.html (#39702)
    • TIMEOUT [expected FAIL] subtest: Sandboxed iframe can not navigate other frame's popup

      Test timed out
      

  • TIMEOUT [expected OK] /html/semantics/forms/form-submission-0/form-submit-iframe-then-location-navigate.html (#29634)
    • TIMEOUT [expected FAIL] subtest: Verifies that location navigations take precedence when following form submissions.

      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.
  • TIMEOUT [expected OK] /html/user-activation/navigation-state-reset-sameorigin.html
    • TIMEOUT [expected PASS] subtest: Post-navigation state reset.

      Test timed out
      

  • OK /html/webappapis/dynamic-markup-insertion/document-write/iframe_005.html (#43671)
    • FAIL [expected PASS] subtest: document.write external script into iframe write back into parent

      assert_array_equals: lengths differ, expected array [1, 2, 3, 4, 5] length 5, got [1, 2] length 2
      

  • CRASH [expected OK] /html/webappapis/scripting/processing-model-2/window-onerror-with-cross-frame-event-listeners-5.html
  • OK /mixed-content/tentative/autoupgrades/audio-upgrade.https.sub.html (#41697)
    • FAIL [expected PASS] subtest: Audio of other host autoupgraded

      assert_equals: Length of other host audio is correct expected 1 but got Infinity
      

  • OK /mixed-content/tentative/autoupgrades/mixed-content-cors.https.sub.html (#41123)
    • FAIL [expected PASS] subtest: Cross-Origin audio should get upgraded even if CORS is set

      assert_equals: Length of other host audio is correct expected 1 but got Infinity
      

  • 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 loadEventEnd > Original loadEventEnd
    • PASS [expected FAIL] subtest: Reload loadEventStart > Original loadEventStart
  • FAIL [expected PASS] /png/apng/fcTL-blend-source-transparent.html (#39520)
  • TIMEOUT [expected OK] /preload/modulepreload-sri-importmap.html (#43354)
    • TIMEOUT [expected PASS] subtest: Script should not be loaded if modulepreload's integrity is invalid

      Test timed out
      

  • TIMEOUT [expected OK] /preload/modulepreload-sri.html (#43354)
    • TIMEOUT [expected PASS] subtest: Script should not be loaded if modulepreload's integrity is invalid

      Test timed out
      

  • OK /resource-timing/test_resource_timing.https.html (#25216)
    • PASS [expected FAIL] subtest: PerformanceEntry has correct name, initiatorType, startTime, and duration (link)
  • 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.
  • OK /visual-viewport/resize-event-order.html (#41981)
    • PASS [expected FAIL] subtest: Popup: DOMWindow resize fired before VisualViewport.
  • OK [expected ERROR] /webxr/render_state_update.https.html (#27535)
  • ERROR [expected OK] /workers/baseurl/alpha/sharedworker-in-worker.html (#21315)
Stable unexpected results that are known to be intermittent (29)
  • OK [expected TIMEOUT] /FileAPI/url/url-in-tags-revoke.window.html (#19978)
    • PASS [expected FAIL] subtest: Fetching a blob URL immediately before revoking it works in an iframe.
    • PASS [expected FAIL] subtest: Fetching a blob URL immediately before revoking it works in an iframe navigation.
    • PASS [expected TIMEOUT] subtest: Opening a blob URL in a noopener about:blank window immediately before revoking it works.
    • PASS [expected TIMEOUT] subtest: Fetching a blob URL immediately before revoking it works in <script> tags.
    • PASS [expected TIMEOUT] subtest: Opening a blob URL in a new window by clicking an <a> tag works immediately before revoking the URL.
  • OK /FileAPI/url/url-with-fetch.any.html (#21517)
    • FAIL [expected PASS] subtest: fetch of a revoked URL should fail

      assert_unreached: Should have rejected: undefined Reached unreachable code
      

    • PASS [expected FAIL] subtest: Revoke blob URL after creating Request, will fetch
    • PASS [expected FAIL] subtest: Revoke blob URL after creating Request, then clone Request, will fetch
  • OK /FileAPI/url/url-with-fetch.any.worker.html (#21517)
    • FAIL [expected PASS] subtest: fetch of a revoked URL should fail

      assert_unreached: Should have rejected: undefined Reached unreachable code
      

    • PASS [expected FAIL] subtest: Revoke blob URL after creating Request, will fetch
    • PASS [expected FAIL] subtest: Revoke blob URL after creating Request, then clone Request, will fetch
  • 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)
    • FAIL [expected PASS] subtest: WebGL test #45

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

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

      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 #49

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

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

      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 #53
    • PASS [expected FAIL] subtest: WebGL test #55
    • PASS [expected FAIL] subtest: WebGL test #57
    • PASS [expected FAIL] subtest: WebGL test #59
    • FAIL [expected PASS] subtest: WebGL test #61

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

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

      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
      

    • And 14 more unexpected results...
  • CRASH [expected OK] /content-security-policy/meta/sandbox-iframe.html (#43478)
  • OK /css/css-fonts/generic-family-keywords-001.html (#37467)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted generic(fangsong)
    • FAIL [expected PASS] subtest: @font-face matching for quoted and unquoted generic(khmer-mul)

      assert_equals: quoted generic(khmer-mul) matches  @font-face rule expected 50 but got 30
      

  • OK /css/css-fonts/generic-family-keywords-003.html (#38994)
    • FAIL [expected PASS] subtest: @font-face matching for quoted and unquoted cursive (drawing text in a canvas)

      assert_equals: quoted cursive matches  @font-face rule expected 125 but got 40
      

    • FAIL [expected PASS] subtest: @font-face matching for quoted and unquoted fantasy (drawing text in a canvas)

      assert_equals: quoted fantasy matches  @font-face rule expected 125 but got 40
      

    • FAIL [expected PASS] subtest: @font-face matching for quoted and unquoted monospace (drawing text in a canvas)

      assert_equals: quoted monospace matches  @font-face rule expected 125 but got 40
      

    • FAIL [expected PASS] subtest: @font-face matching for quoted and unquoted system-ui (drawing text in a canvas)

      assert_equals: quoted system-ui matches  @font-face rule expected 125 but got 40
      

    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted generic(khmer-mul) (drawing text in a canvas)
  • ERROR [expected OK] /fetch/fetch-later/quota/same-origin-iframe/accumulated-oversized-payload.https.window.html (#41705)
  • OK /fetch/metadata/generated/css-font-face.https.sub.tentative.html (#32732)
    • PASS [expected FAIL] subtest: sec-fetch-mode
  • OK /fetch/metadata/generated/element-iframe.https.sub.html (#40341)
    • PASS [expected FAIL] subtest: sec-fetch-site - Cross-site
    • PASS [expected FAIL] subtest: sec-fetch-site - Same site
    • PASS [expected FAIL] subtest: sec-fetch-site - Cross-Site -> Cross-Site
    • PASS [expected FAIL] subtest: sec-fetch-site - Same-Site -> Same-Site
  • OK /fetch/metadata/window-open.https.sub.html (#40339)
    • PASS [expected FAIL] subtest: Cross-site window, forced, reloaded: sec-fetch-site
    • PASS [expected FAIL] subtest: Cross-site window, forced: sec-fetch-site
    • PASS [expected FAIL] subtest: Same-site window, forced: sec-fetch-site
    • PASS [expected FAIL] subtest: Same-site window, forced, reloaded: sec-fetch-site
    • PASS [expected FAIL] subtest: Same-site window, user-activated: sec-fetch-site
    • PASS [expected FAIL] subtest: Cross-site window, user-activated: sec-fetch-site
  • OK /html/browsers/browsing-the-web/navigating-across-documents/005.html (#27062)
    • FAIL [expected PASS] subtest: Link with onclick navigation and href navigation

      assert_equals: expected "href" but got "click"
      

  • 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/history/the-history-interface/traverse_the_history_4.html (#21383)
    • PASS [expected FAIL] subtest: Multiple history traversals, last would be aborted
  • TIMEOUT [expected OK] /html/interaction/focus/the-autofocus-attribute/autofocus-dialog.html (#29087)
    • TIMEOUT [expected FAIL] subtest: <dialog>-contained autofocus element gets focused when the dialog is shown

      Test timed out
      

  • OK [expected TIMEOUT] /html/interaction/focus/the-autofocus-attribute/update-the-rendering.html (#24145)
    • FAIL [expected TIMEOUT] subtest: "Flush autofocus candidates" should be happen before a scroll event and animation frame callbacks

      assert_array_equals: animationFrame lengths differ, expected array ["autofocus", "scroll", "animationFrame"] length 3, got ["animationFrame"] length 1
      

  • 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/semantics/embedded-content/media-elements/audio_loop_seek_to_eos.html (#41226)
    • PASS [expected FAIL] subtest: seeking to the end of looping audio
  • OK /html/semantics/scripting-1/the-script-element/module/dynamic-import/blob-url.any.html (#33948)
    • FAIL [expected PASS] subtest: A revoked blob URL will not resolve

      assert_unreached: Should have rejected: undefined Reached unreachable code
      

  • OK /html/semantics/scripting-1/the-script-element/module/dynamic-import/blob-url.any.worker-module.html (#43510)
    • FAIL [expected PASS] subtest: A revoked blob URL will not resolve

      assert_unreached: Should have rejected: undefined Reached unreachable code
      

  • OK /html/semantics/scripting-1/the-script-element/module/dynamic-import/blob-url.any.worker.html (#33909)
    • FAIL [expected PASS] subtest: A revoked blob URL will not resolve

      assert_unreached: Should have rejected: undefined Reached unreachable code
      

  • OK /resource-timing/buffer-full-add-then-clear.html (#40819)
    • FAIL [expected PASS] subtest: Test that if the buffer is cleared after entries were added to the secondary buffer, those entries make it into the primary one

      assert_equals: Number of entries does not match the expected value. expected 3 but got 0
      

  • OK /touch-events/single-tap-when-touchend-listener-use-sync-xhr.html (#41175)
    • FAIL [expected PASS] subtest: Click event should be fired when touchend opens synchronous XHR

      assert_equals: expected "touchend@div, mousedown@div, mouseup@div, click@div" but got "touchend@div"
      

  • OK /trusted-types/trusted-types-reporting.html (#43737)
    • PASS [expected FAIL] subtest: Trusted Type violation report: creating a report-only-forbidden policy.
    • PASS [expected FAIL] subtest: Trusted Type violation report: Worker constructor
  • OK [expected TIMEOUT] /webmessaging/with-ports/018.html (#24485)
    • PASS [expected TIMEOUT] subtest: origin of the script that invoked the method, javascript:
  • OK [expected TIMEOUT] /webmessaging/without-ports/018.html (#24485)
    • PASS [expected TIMEOUT] subtest: origin of the script that invoked the method, javascript:
  • OK /workers/dedicated-worker-from-blob-url.window.html (#22286)
    • PASS [expected FAIL] subtest: Creating a dedicated worker from a blob URL works immediately before revoking.
Stable unexpected results (6)
  • OK /FileAPI/url/cross-global-revoke.sub.html
    • FAIL [expected PASS] subtest: It is possible to revoke same-origin blob URLs from different frames.

      assert_unreached: Should have rejected: undefined Reached unreachable code
      

    • FAIL [expected PASS] subtest: It is possible to revoke same-origin blob URLs from a different worker global.

      assert_unreached: Should have rejected: undefined Reached unreachable code
      

  • OK /FileAPI/url/url-reload.window.html
    • PASS [expected FAIL] subtest: Reloading a blob URL succeeds even if the URL was revoked.
  • OK /FileAPI/url/url-with-xhr.any.html
    • FAIL [expected PASS] subtest: XHR of a revoked URL should fail

      assert_equals: expected 0 but got 200
      

    • PASS [expected FAIL] subtest: Revoke blob URL after open(), will fetch
  • OK /FileAPI/url/url-with-xhr.any.worker.html
    • FAIL [expected PASS] subtest: XHR of a revoked URL should fail

      assert_equals: expected 0 but got 200
      

    • PASS [expected FAIL] subtest: Revoke blob URL after open(), will fetch
  • OK /html/semantics/scripting-1/the-script-element/module/dynamic-import/blob-url-workers.window.html
    • FAIL [expected PASS] subtest: A blob URL revoked in a window agent will not resolve in a worker

      assert_false: expected false got true
      

    • FAIL [expected PASS] subtest: A revoked blob URL will not resolve in a worker even if it's in the window's module graph

      assert_false: expected false got true
      

  • OK /workers/interfaces/WorkerUtils/importScripts/blob-url.worker.html
    • FAIL [expected PASS] subtest: A revoked blob URL will fail

      assert_throws_dom: function "() => {
          importScripts(blobScriptUrl);
        }" did not throw
      

    • PASS [expected FAIL] subtest: Revoking a blob URL in an earlier script will not fail

@github-actions

Copy link
Copy Markdown

⚠️ Try run (#23708823164) failed!

@simonwuelker simonwuelker force-pushed the blob-url-early-claim-3 branch from e1daa8f to 88a6b20 Compare March 29, 2026 13:41
@simonwuelker simonwuelker added the T-linux-wpt Do a try run of the WPT label Mar 29, 2026
@github-actions github-actions Bot removed the T-linux-wpt Do a try run of the WPT label Mar 29, 2026
@github-actions

Copy link
Copy Markdown

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

@github-actions

Copy link
Copy Markdown

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

Flaky unexpected result (32)
  • OK /_mozilla/css/offset_properties_inline.html (#40543)
    • FAIL [expected PASS] subtest: offsetTop

      assert_equals: offsetTop of #inline-1 should be 0. expected 0 but got -1
      

    • FAIL [expected PASS] subtest: offsetLeft

      assert_equals: offsetLeft of #inline-2 should be 40. expected 40 but got 25
      

  • OK /_mozilla/mozilla/getBoundingClientRect.html (#39668)
    • FAIL [expected PASS] subtest: getBoundingClientRect 1

      assert_equals: expected 62 but got 60.35
      

  • TIMEOUT [expected OK] /_mozilla/mozilla/img_find_non_sibling_map.html
  • CRASH [expected OK] /_webgl/conformance2/wasm/readpixels-2gb-in-4gb-wasm-memory.html
  • CRASH [expected OK] /content-security-policy/meta/sandbox-iframe.html (#43478)
  • FAIL [expected PASS] /css/css-backgrounds/background-size-042.html
  • OK /css/css-cascade/layer-cssom-order-reverse.html (#36094)
    • FAIL [expected PASS] subtest: Delete layer invalidates @font-face

      assert_equals: expected "220px" but got "133px"
      

  • OK /css/css-fonts/generic-family-keywords-002.html (#40929)
    • FAIL [expected PASS] subtest: font-family: -webkit-serif treated as <font-family>, not <generic-name>

      assert_equals: expected 30 but got 50
      

    • FAIL [expected PASS] subtest: font-family: -webkit-sans-serif treated as <font-family>, not <generic-name>

      assert_equals: expected 30 but got 50
      

    • FAIL [expected PASS] subtest: font-family: -webkit-cursive treated as <font-family>, not <generic-name>

      assert_equals: expected 30 but got 50
      

    • FAIL [expected PASS] subtest: font-family: -webkit-fantasy treated as <font-family>, not <generic-name>

      assert_equals: expected 30 but got 50
      

    • FAIL [expected PASS] subtest: font-family: -webkit-monospace treated as <font-family>, not <generic-name>

      assert_equals: expected 30 but got 50
      

    • FAIL [expected PASS] subtest: font-family: -webkit-system-ui treated as <font-family>, not <generic-name>

      assert_equals: expected 30 but got 50
      

    • FAIL [expected PASS] subtest: font-family: -webkit-math treated as <font-family>, not <generic-name>

      assert_equals: expected 30 but got 50
      

    • PASS [expected FAIL] subtest: font-family: -webkit-generic(fangsong) treated as <font-family>, not <generic-name>
    • PASS [expected FAIL] subtest: font-family: -webkit-generic(kai) treated as <font-family>, not <generic-name>
    • PASS [expected FAIL] subtest: font-family: -webkit-generic(khmer-mul) treated as <font-family>, not <generic-name>
    • And 12 more unexpected results...
  • TIMEOUT [expected OK] /fetch/api/redirect/redirect-keepalive.https.any.html (#32153)
    • TIMEOUT [expected PASS] subtest: [keepalive][iframe][load] mixed content redirect; setting up

      Test timed out
      

  • OK /fetch/metadata/generated/css-font-face.https.sub.tentative.html (#32732)
    • PASS [expected FAIL] subtest: sec-fetch-storage-access - Cross-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-site destination
    • PASS [expected FAIL] subtest: sec-fetch-storage-access - Not sent to non-trustworthy cross-site destination
  • ERROR /fetch/metadata/generated/serviceworker.https.sub.html (#36247)
    • PASS [expected FAIL] subtest: sec-fetch-site - Same origin, no options - registration
  • ERROR [expected TIMEOUT] /html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-initial-navigation.html (#40387)
  • OK /html/browsers/windows/embedded-opener-remove-frame.html (#23867)
    • FAIL [expected PASS] subtest: opener of discarded auxiliary browsing context

      assert_object_equals: property "get" expected function "function opener() {
          [native code]
      }" got function "function opener() {
          [native code]
      }"
      

  • TIMEOUT [expected PASS] /html/canvas/element/manual/filters/tentative/idl-conversions/canvas-filter-boolean-conversion.html
  • TIMEOUT [expected OK] /html/interaction/focus/the-autofocus-attribute/autofocus-dialog.html (#29087)
    • TIMEOUT [expected FAIL] subtest: <dialog>-contained autofocus element gets focused when the dialog is shown

      Test timed out
      

  • OK /html/semantics/embedded-content/media-elements/audio_loop_seek_to_eos.html (#41226)
    • PASS [expected FAIL] subtest: seeking to the end of looping audio
  • OK /html/semantics/embedded-content/media-elements/media_fragment_seek.html (#24114)
    • FAIL [expected PASS] subtest: Video should seek to time specified in media fragment syntax

      assert_equals: expected 3 but got 0
      

  • TIMEOUT [expected OK] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigate_other_frame_popup.sub.html (#39702)
    • TIMEOUT [expected FAIL] subtest: Sandboxed iframe can not navigate other frame's popup

      Test timed out
      

  • CRASH [expected ERROR] /html/semantics/forms/the-select-element/customizable-select/select-appearance-button-after-span.html
  • TIMEOUT [expected OK] /html/user-activation/navigation-state-reset-sameorigin.html
    • TIMEOUT [expected PASS] subtest: Post-navigation state reset.

      Test timed out
      

  • PASS [expected FAIL] /png/apng/acTL-plays-one.html (#41218)
  • FAIL [expected PASS] /png/apng/fcTL-dispose-before-region-background.html
  • FAIL [expected PASS] /png/apng/fcTL-dispose-in-region-previous.html (#41410)
  • FAIL [expected PASS] /png/apng/fcTL-dispose-previous.html (#41561)
  • TIMEOUT [expected OK] /preload/modulepreload-sri-importmap.html (#43354)
    • TIMEOUT [expected PASS] subtest: Script should not be loaded if modulepreload's integrity is invalid

      Test timed out
      

  • TIMEOUT [expected OK] /preload/modulepreload-sri.html (#43354)
    • TIMEOUT [expected PASS] subtest: Script should not be loaded if modulepreload's integrity is invalid

      Test timed out
      

  • OK /touch-events/single-tap-when-touchend-listener-use-sync-xhr.html (#41175)
    • FAIL [expected PASS] subtest: Click event should be fired when touchend opens synchronous XHR

      assert_equals: expected "touchend@div, mousedown@div, mouseup@div, click@div" but got "touchend@div, mousedown@div"
      

  • TIMEOUT /trusted-types/trusted-types-navigation.html?06-10 (#37920)
    • TIMEOUT [expected FAIL] subtest: Navigate a frame via anchor with javascript:-urls in report-only mode.

      Test timed out
      

    • NOTRUN [expected TIMEOUT] subtest: Navigate a frame via anchor with javascript:-urls w/ default policy in report-only mode.
  • OK /visual-viewport/resize-event-order.html (#41981)
    • PASS [expected FAIL] subtest: Popup: DOMWindow resize fired before VisualViewport.
  • CRASH [expected OK] /webxr/xrBoundedReferenceSpace_updates.https.html
  • CRASH [expected OK] /webxr/xrSession_sameObject.https.html
Stable unexpected results that are known to be intermittent (21)
  • 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 /css/css-fonts/generic-family-keywords-001.html (#37467)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted generic(fangsong)
    • FAIL [expected PASS] subtest: @font-face matching for quoted and unquoted generic(kai)

      assert_equals: quoted generic(kai) matches  @font-face rule expected 50 but got 30
      

  • OK /css/css-fonts/generic-family-keywords-003.html (#38994)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted sans-serif (drawing text in a canvas)
    • FAIL [expected PASS] subtest: @font-face matching for quoted and unquoted fantasy (drawing text in a canvas)

      assert_equals: quoted fantasy matches  @font-face rule expected 125 but got 40
      

    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted math (drawing text in a canvas)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted generic(fangsong) (drawing text in a canvas)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted ui-serif (drawing text in a canvas)
  • OK /fetch/metadata/generated/element-iframe.https.sub.html (#40341)
    • PASS [expected FAIL] subtest: sec-fetch-site - Cross-site
    • PASS [expected FAIL] subtest: sec-fetch-site - Same site
    • PASS [expected FAIL] subtest: sec-fetch-site - Cross-Site -> Cross-Site
    • PASS [expected FAIL] subtest: sec-fetch-site - Same-Site -> Same-Site
  • OK /fetch/metadata/window-open.https.sub.html (#40339)
    • PASS [expected FAIL] subtest: Same-site window, forced: sec-fetch-site
    • PASS [expected FAIL] subtest: Cross-site window, forced: sec-fetch-site
    • PASS [expected FAIL] subtest: Cross-site window, forced, reloaded: sec-fetch-site
    • PASS [expected FAIL] subtest: Same-site window, forced, reloaded: sec-fetch-site
    • PASS [expected FAIL] subtest: Same-site window, user-activated: sec-fetch-site
    • PASS [expected FAIL] subtest: Cross-site window, user-activated: sec-fetch-site
  • OK /html/browsers/browsing-the-web/navigating-across-documents/005.html (#27062)
    • FAIL [expected PASS] subtest: Link with onclick navigation and href navigation

      assert_equals: expected "href" but got "click"
      

  • 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)
    • FAIL [expected PASS] subtest: aElement.click() before the load event must NOT replace

      assert_equals: expected "http://web-platform.test:8000/common/blank.html?thereplacement" but got "http://web-platform.test:8000/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/resources/code-injector.html?pipe=sub(none)&code=%0A%20%20%20%20const%20a%20%3D%20document.createElement(%22a%22)%3B%0A%20%20%20%20a.href%20%3D%20%22%2Fcommon%2Fblank.html%3Fthereplacement%22%3B%0A%20%20%20%20document.currentScript.before(a)%3B%0A%20%20%20%20a.click()%3B%0A%20%20"
      

  • OK /html/browsers/history/the-history-interface/traverse_the_history_5.html (#21383)
    • PASS [expected FAIL] subtest: Multiple history traversals, last would be aborted
  • CRASH [expected TIMEOUT] /html/browsers/history/the-location-interface/location_replace_session_history.html (#41896)
  • OK [expected TIMEOUT] /html/interaction/focus/the-autofocus-attribute/supported-elements.html (#24145)
    • PASS [expected TIMEOUT] subtest: Non-HTMLElement should not support autofocus
    • FAIL [expected NOTRUN] subtest: Host element with delegatesFocus should support autofocus

      assert_equals: expected Element node <div autofocus=""></div> but got Element node <body></body>
      

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

      assert_equals: expected Element node <input autofocus=""></input> but got Element node <body><div autofocus=""></div><input autofocus=""></body>
      

    • FAIL [expected NOTRUN] subtest: Area element should support autofocus

      promise_test: Unhandled rejection with value: object "TypeError: can't access property "appendChild", w.document.querySelector(...) is null"
      

  • OK [expected TIMEOUT] /html/interaction/focus/the-autofocus-attribute/update-the-rendering.html (#24145)
    • FAIL [expected TIMEOUT] subtest: "Flush autofocus candidates" should be happen before a scroll event and animation frame callbacks

      assert_array_equals: animationFrame lengths differ, expected array ["autofocus", "scroll", "animationFrame"] length 3, got ["animationFrame"] length 1
      

  • 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.worker-module.html (#43510)
    • FAIL [expected PASS] subtest: Revoking a blob URL immediately after calling import will not fail

      promise_test: Unhandled rejection with value: object "TypeError: Module fetching failed"
      

  • OK /html/webappapis/dynamic-markup-insertion/document-write/iframe_005.html (#43671)
    • FAIL [expected PASS] subtest: document.write external script into iframe write back into parent

      assert_array_equals: lengths differ, expected array [1, 2, 3, 4, 5] length 5, got [1, 2] length 2
      

  • OK /resource-timing/buffer-full-add-then-clear.html (#40819)
    • FAIL [expected PASS] subtest: Test that if the buffer is cleared after entries were added to the secondary buffer, those entries make it into the primary one

      assert_equals: Number of entries does not match the expected value. expected 3 but got 0
      

  • 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.
  • OK /trusted-types/trusted-types-reporting.html (#43737)
    • PASS [expected FAIL] subtest: Trusted Type violation report: creating a forbidden-but-not-reported policy.
    • PASS [expected FAIL] subtest: Trusted Type violation report: sample for SVGScriptElement href assignment by setAttribute
    • FAIL [expected PASS] subtest: Trusted Type violation report: sample for custom element assignment

      assert_equals: a single violation reported expected 1 but got 2
      

  • OK [expected TIMEOUT] /webmessaging/with-ports/018.html (#24485)
    • PASS [expected TIMEOUT] subtest: origin of the script that invoked the method, javascript:
  • OK [expected TIMEOUT] /webmessaging/without-ports/018.html (#24485)
    • PASS [expected TIMEOUT] subtest: origin of the script that invoked the method, javascript:

@github-actions

Copy link
Copy Markdown

✨ Try run (#23710426523) succeeded.

@simonwuelker simonwuelker force-pushed the blob-url-early-claim-3 branch from 2201e5e to f4543ea Compare March 29, 2026 16:14
@simonwuelker simonwuelker marked this pull request as ready for review March 29, 2026 16:28
@servo-highfive servo-highfive added the S-awaiting-review There is new code that needs to be reviewed. label Mar 29, 2026
@jdm

jdm commented Mar 29, 2026

Copy link
Copy Markdown
Member

This is a really nice solution!

@mrobinson

Copy link
Copy Markdown
Member

@jdm Did you mean to approve this?

@jdm

jdm commented Apr 1, 2026

Copy link
Copy Markdown
Member

No, I haven't had time to.look at it closely yet. Planning on doing that tomorrow.

@jdm jdm left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I love that this can be improved incrementally instead of all at once. Great job figuring out how to make progress here!

Comment thread components/shared/net/blob_url_store.rs Outdated
Comment thread components/shared/net/blob_url_store.rs Outdated
Comment thread components/shared/net/blob_url_store.rs Outdated
Comment thread components/shared/net/blob_url_store.rs Outdated
Comment thread components/shared/net/blob_url_store.rs
}

impl BlobTokenCommunicator {
pub fn stub_for_testing() -> Arc<Mutex<Self>> {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can we gate this with #[test]?

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.

We cannot, because the tests that use this are outside of the net crate, and cfg(test) is only set for the crate being tested (That's how I understand it at least).

@servo-highfive servo-highfive added the S-needs-rebase There are merge conflict errors. label Apr 2, 2026
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
@simonwuelker simonwuelker force-pushed the blob-url-early-claim-3 branch from f4543ea to b462f19 Compare April 6, 2026 12:58
@servo-highfive servo-highfive added S-awaiting-review There is new code that needs to be reviewed. and removed S-needs-rebase There are merge conflict errors. labels Apr 6, 2026
@simonwuelker simonwuelker enabled auto-merge April 6, 2026 12:58
@simonwuelker

Copy link
Copy Markdown
Member Author

Thank you for the review!

@simonwuelker simonwuelker force-pushed the blob-url-early-claim-3 branch 2 times, most recently from 9e674ee to 50efa77 Compare April 6, 2026 14:00
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
@simonwuelker simonwuelker force-pushed the blob-url-early-claim-3 branch from 50efa77 to 14d8955 Compare April 6, 2026 14:12
@simonwuelker simonwuelker added this pull request to the merge queue Apr 6, 2026
@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 Apr 6, 2026
Merged via the queue into servo:main with commit e73c010 Apr 6, 2026
30 checks passed
@simonwuelker simonwuelker deleted the blob-url-early-claim-3 branch April 6, 2026 15:09
@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 Apr 6, 2026
github-merge-queue Bot pushed a commit that referenced this pull request Apr 6, 2026
This is a followup to #43746 that
applies the same fix to XHR. Refer to that PR for a description of the
problem.

Testing: New tests start to pass

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
github-merge-queue Bot pushed a commit that referenced this pull request Apr 8, 2026
Refer to #43746 for a description of
the problem. This change ensures that video posters can be loaded from
blob URLs, even if the URL is revoked right after.

Testing: This change adds a test

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
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.

5 participants