Skip to content

script: Impl UserActivation interface#42060

Merged
jdm merged 8 commits intoservo:mainfrom
stevennovaryo:user-activation
Feb 4, 2026
Merged

script: Impl UserActivation interface#42060
jdm merged 8 commits intoservo:mainfrom
stevennovaryo:user-activation

Conversation

@stevennovaryo
Copy link
Copy Markdown
Contributor

@stevennovaryo stevennovaryo commented Jan 22, 2026

User activation is a concept used to prevents annoying usage of specific API (Fullscreen API, Virtual Keyboard) to the user by states that the API needs to have in order to process. This PR implements the UserActivation interface and keep track of the last user interaction. Each Window will keep track the last activation time stamp, which will be set if there are a triggering input event firing in the Window and propagating across the browsing contexts ancestors and descendants. These timestamp could be consumed, and the timestamp will be set to negative infinite.

It is then used to gate some APIs within browser that is determined as transient activation consuming-gated APIs, which needs transient activation to be true and consumes the activation. For the purpose of testing, this PR would implement this behavior on fullscreen API which is used to test activation consuming behavior.

Spec: https://html.spec.whatwg.org/multipage/interaction.html#the-useractivation-interface

Testing: Existing WPT

@stevennovaryo stevennovaryo force-pushed the user-activation branch 2 times, most recently from 8d5d0bd to 5f73f5a Compare January 22, 2026 02:50
@stevennovaryo stevennovaryo changed the title Impl UserActivation interface script: Impl UserActivation interface Jan 22, 2026
@stevennovaryo stevennovaryo added the T-linux-wpt Do a try run of the WPT label Jan 28, 2026
@github-actions github-actions bot removed the T-linux-wpt Do a try run of the WPT label Jan 28, 2026
@github-actions
Copy link
Copy Markdown

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

@github-actions
Copy link
Copy Markdown

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

Flaky unexpected result (24)
  • OK /FileAPI/file/send-file-form-controls.html
    • FAIL [expected PASS] subtest: Upload file-for-upload-in-form-BS-[�].txt (ASCII) in UTF-8 form

      assert_greater_than: file-for-upload-in-form-BS-[�].txt: multipart form data must have at least 3 lines: "" expected a number greater than 2 but got 0
      

    • FAIL [expected PASS] subtest: Upload file-for-upload-in-form-VT-[�].txt (ASCII) in UTF-8 form

      assert_greater_than: file-for-upload-in-form-VT-[�].txt: multipart form data must have at least 3 lines: "" expected a number greater than 2 but got 0
      

  • OK /IndexedDB/idbfactory-open-error-properties.any.html
    • PASS [expected FAIL] subtest: Properties of error event from failed open()
  • OK /IndexedDB/idbfactory-open-error-properties.any.worker.html
    • PASS [expected FAIL] subtest: Properties of error event from failed open()
  • OK /_mozilla/css/offset_properties_inline.html (#40543)
    • PASS [expected FAIL] subtest: offsetTop
    • PASS [expected FAIL] subtest: offsetLeft
  • CRASH [expected PASS] /_mozilla/shadow-dom/move-element-with-ua-shadow-tree-crash.html (#39473)
  • CRASH [expected OK] /_webgl/conformance2/glsl3/array-complex-indexing.html
  • FAIL [expected PASS] /css/css-backgrounds/background-size-041.html
  • OK /custom-elements/form-associated/ElementInternals-setFormValue.html (#29174)
    • PASS [expected FAIL] subtest: Null value should submit nothing
    • PASS [expected FAIL] subtest: Newline normalization - \r\n in value (formdata)
  • OK [expected ERROR] /fetch/fetch-later/quota/same-origin-iframe/accumulated-oversized-payload.https.window.html (#41705)
  • OK [expected ERROR] /fetch/fetch-later/quota/same-origin-iframe/sandboxed-iframe.https.window.html (#41704)
  • OK /fetch/metadata/generated/css-font-face.https.sub.tentative.html (#32732)
    • PASS [expected FAIL] subtest: sec-fetch-dest
    • FAIL [expected PASS] subtest: sec-fetch-user

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

  • TIMEOUT [expected OK] /fullscreen/api/element-request-fullscreen-and-exit-iframe.html
    • TIMEOUT [expected FAIL] subtest: Checks that the fullscreenchange events fire in right order when exiting fullscreen

      Test timed out
      

  • CRASH [expected OK] /html/anonymous-iframe/local-storage.tentative.https.window.html
  • ERROR [expected TIMEOUT] /html/browsers/browsing-the-web/history-traversal/pageswap/pageswap-initial-navigation.html (#40387)
  • CRASH [expected OK] /html/browsers/sandboxing/sandbox-initial-empty-document-toward-same-origin.html (#35948)
  • 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
      

  • OK /html/semantics/forms/form-submission-0/multipart-formdata.window.html (#28725)
    • FAIL [expected PASS] subtest: multipart/form-data: Basic test (formdata event)

      assert_equals: expected "\r\nContent-Disposition: form-data; name=\"basic\"\r\n\r\ntest\r\n--\r\n" but got ""
      

    • FAIL [expected PASS] subtest: multipart/form-data: Basic File test (normal form)

      assert_equals: expected "\r\nContent-Disposition: form-data; name=\"basic\"; filename=\"file-test.txt\"\r\nContent-Type: text/plain\r\n\r\n\r\n--\r\n" but got ""
      

  • OK /html/semantics/forms/form-submission-0/text-plain.window.html (#28687)
    • PASS [expected FAIL] subtest: text/plain: Basic File test (formdata event)
    • PASS [expected FAIL] subtest: text/plain: 0x00 in value (formdata event)
  • TIMEOUT [expected ERROR] /html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener_base.html (#40347)
  • 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/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"])
      

  • TIMEOUT [expected OK] /trusted-types/trusted-types-navigation.html?01-05 (#38975)
    • TIMEOUT [expected PASS] subtest: Navigate a window via anchor with javascript:-urls in report-only mode.

      Test timed out
      

    • NOTRUN [expected PASS] subtest: Navigate a window via anchor with javascript:-urls w/ default policy in report-only mode.
    • NOTRUN [expected PASS] subtest: Navigate a frame via anchor with javascript:-urls in enforcing mode.
  • CRASH [expected OK] /workers/shared-worker-in-data-url-context.window.html
Stable unexpected results that are known to be intermittent (23)
  • OK /IndexedDB/idbcursor-continuePrimaryKey-exceptions.any.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/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_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/idbrequest-onupgradeneeded.any.html (#38895)
    • PASS [expected FAIL] subtest: transaction oncomplete ordering relative to open request onsuccess
  • OK /IndexedDB/idbrequest-onupgradeneeded.any.worker.html (#38971)
    • PASS [expected FAIL] subtest: transaction oncomplete ordering relative to open request onsuccess
  • 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"
      

    • FAIL [expected PASS] subtest: IDBCursor update() method with throwing/invalid keys

      assert_throws_exactly: throwing getter should rethrow during clone function "() => {
            cursor.update(value);
          }" threw object "TypeError: cursor.update 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] subtest: IDBCursor update() method with throwing/invalid keys

      assert_throws_exactly: throwing getter should rethrow during clone function "() => {
            cursor.update(value);
          }" threw object "TypeError: cursor.update 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 /css/css-cascade/layer-cssom-order-reverse.html (#36094)
    • PASS [expected FAIL] subtest: Delete layer invalidates @font-face
  • OK /css/css-cascade/layer-font-face-override.html (#35935)
    • 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-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)
  • OK /css/css-fonts/generic-family-keywords-003.html (#38994)
    • 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 ui-serif (drawing text in a canvas)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted ui-monospace (drawing text in a canvas)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted ui-rounded (drawing text in a canvas)
  • OK /css/cssom-view/offsetTopLeft-border-box.html (#40826)
    • PASS [expected FAIL] subtest: container: 0
    • PASS [expected FAIL] subtest: container: 1
  • 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 [expected ERROR] /focus/focus-event-after-switching-iframes.sub.html (#40368)
  • 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"
      

  • TIMEOUT /html/semantics/embedded-content/media-elements/autoplay-disabled-by-feature-policy.https.sub.html (#41221)
    • TIMEOUT [expected FAIL] subtest: Feature-Policy header: autoplay "none" disallows same-origin iframes.

      Test timed out
      

  • OK [expected TIMEOUT] /resource-timing/test_resource_timing.html (#25720)
    • PASS [expected TIMEOUT] subtest: window.performance.getEntriesByName() and window.performance.getEntriesByNameType() return same data (link)
    • FAIL [expected NOTRUN] subtest: PerformanceEntry has correct name, initiatorType, startTime, and duration (link)

      assert_equals: expected 13.219999999999999 but got 13.22
      

    • FAIL [expected NOTRUN] subtest: PerformanceEntry has correct order of timing attributes (link)

      assert_greater_than_equal: domainLookupEnd after domainLookupStart expected a number greater than or equal to 40.5 but got 0
      

    • FAIL [expected NOTRUN] subtest: PerformanceEntry has correct network transfer attributes (link)

      assert_equals: encodedBodySize size expected 44 but got 0
      

    • FAIL [expected NOTRUN] subtest: PerformanceEntry has correct protocol attribute (link)

      assert_equals: expected protocol expected "http/1.1" but got ""
      

    • PASS [expected FAIL] subtest: PerformanceEntry has correct name, initiatorType, startTime, and duration (xmlhttprequest)
  • OK [expected TIMEOUT] /resource-timing/test_resource_timing.https.html (#25216)
    • FAIL [expected PASS] subtest: PerformanceEntry has correct name, initiatorType, startTime, and duration (img)

      assert_equals: expected 8.070000000000004 but got 8.06
      

    • PASS [expected TIMEOUT] subtest: window.performance.getEntriesByName() and window.performance.getEntriesByNameType() return same data (link)
    • FAIL [expected NOTRUN] subtest: PerformanceEntry has correct name, initiatorType, startTime, and duration (link)

      assert_equals: expected 5.740000000000002 but got 5.74
      

    • FAIL [expected NOTRUN] subtest: PerformanceEntry has correct order of timing attributes (link)

      assert_greater_than_equal: domainLookupEnd after domainLookupStart expected a number greater than or equal to 24.09 but got 0
      

    • FAIL [expected NOTRUN] subtest: PerformanceEntry has correct network transfer attributes (link)

      assert_equals: encodedBodySize size expected 44 but got 0
      

    • FAIL [expected NOTRUN] subtest: PerformanceEntry has correct protocol attribute (link)

      assert_equals: expected protocol expected "http/1.1" but got ""
      

    • PASS [expected FAIL] subtest: PerformanceEntry has correct name, initiatorType, startTime, and duration (xmlhttprequest)
  • OK /touch-events/single-tap-when-touchend-listener-use-sync-xhr.html (#41175)
    • PASS [expected FAIL] subtest: Click event should be fired when touchend opens synchronous XHR
  • OK [expected TIMEOUT] /trusted-types/trusted-types-navigation.html?31-35 (#38034)
    • PASS [expected TIMEOUT] subtest: Navigate a frame via form-submission with javascript:-urls w/ default policy in report-only mode.
    • FAIL [expected NOTRUN] subtest: Navigate a window via form-submission 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 form-submission 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!\""
      

    • FAIL [expected NOTRUN] subtest: Navigate a window via form-submission with javascript:-urls w/ a default policy making the URL invalid in enforcing mode.

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

Stable unexpected results (12)
  • ERROR [expected OK] /_mozilla/mozilla/fullscreen-remove-single.html
    • TIMEOUT [expected PASS] subtest: Remove the single element on the fullscreen element stack

      Test timed out
      

  • FAIL [expected PASS] /_mozilla/mozilla/fullscreen/reftests/fullscreen-baseline.html
  • OK /_mozilla/mozilla/interfaces.https.html
    • FAIL [expected PASS] subtest: Interfaces exposed on the window

      assert_true: If this is failing: DANGER, are you sure you want to expose the new interface UserActivation to all webpages as a property on the global? expected true got false
      

  • OK /fullscreen/api/element-request-fullscreen-consume-user-activation.html
    • PASS [expected FAIL] subtest: Element#requestFullscreen() consumes user activation
  • OK /fullscreen/api/element-request-fullscreen-options.html
    • PASS [expected FAIL] subtest: requestFullscreen() with invalid navigationUI values
  • OK /fullscreen/api/element-request-fullscreen-twice.html
    • PASS [expected FAIL] subtest: requestFullscreen() multiple times after going fullscreen
  • OK /fullscreen/api/element-request-fullscreen-without-user-activation.tentative.https.html
    • PASS [expected FAIL] subtest: Element#requestFullscreen() rejects without user activation by default
  • OK /html/capability-delegation/delegate-fullscreen-request-popup-cross-origin.https.sub.tentative.html
    • PASS [expected FAIL] subtest: Fullscreen requests from a cross-origin popup fails without delegation from an opener with no user activation
    • PASS [expected FAIL] subtest: Fullscreen requests from a cross-origin popup fails without delegation from an opener with user activation
    • FAIL [expected PASS] subtest: Fullscreen requests from a cross-origin popup succeeds with delegation from an opener with user activation

      assert_equals: expected "success" but got "failure"
      

  • OK /html/capability-delegation/delegate-fullscreen-request-popup-same-origin.https.tentative.html
    • PASS [expected FAIL] subtest: Fullscreen requests from a same-origin popup fails without delegation from an opener with no user activation
    • PASS [expected FAIL] subtest: Fullscreen requests from a same-origin popup fails without delegation from an opener with user activation
    • FAIL [expected PASS] subtest: Fullscreen requests from a same-origin popup succeeds with delegation from an opener with user activation

      assert_equals: expected "success" but got "failure"
      

  • OK /html/dom/idlharness.https.html?exclude=(Document|Window|HTML.+)
    • PASS [expected FAIL] subtest: UserActivation interface: existence and properties of interface object
    • PASS [expected FAIL] subtest: UserActivation interface object length
    • PASS [expected FAIL] subtest: UserActivation interface object name
    • PASS [expected FAIL] subtest: UserActivation interface: existence and properties of interface prototype object
    • PASS [expected FAIL] subtest: UserActivation interface: existence and properties of interface prototype object's "constructor" property
    • PASS [expected FAIL] subtest: UserActivation interface: existence and properties of interface prototype object's @@unscopables property
    • PASS [expected FAIL] subtest: UserActivation interface: attribute hasBeenActive
    • PASS [expected FAIL] subtest: UserActivation interface: attribute isActive
    • PASS [expected FAIL] subtest: Navigator interface: attribute userActivation
    • PASS [expected FAIL] subtest: Navigator interface: window.navigator must inherit property "userActivation" with the proper type
  • TIMEOUT [expected ERROR] /html/semantics/links/links-created-by-a-and-area-elements/target_blank_useractivation.html
    • TIMEOUT [expected FAIL] subtest: <area target=_blank">.click()

      Test timed out
      

    • NOTRUN [expected TIMEOUT] subtest: <area target=_blank"> mouse click
  • TIMEOUT [expected OK] /html/semantics/links/links-created-by-a-and-area-elements/target_blank_useractivation_multi_globals.html
    • TIMEOUT [expected FAIL] subtest: <area target=_blank">.click()

      Test timed out
      

@github-actions
Copy link
Copy Markdown

⚠️ Try run (#21429463551) failed!

Signed-off-by: Jo Steven Novaryo <[email protected]>
Signed-off-by: Jo Steven Novaryo <[email protected]>
Signed-off-by: Jo Steven Novaryo <[email protected]>
Signed-off-by: Jo Steven Novaryo <[email protected]>
@stevennovaryo stevennovaryo force-pushed the user-activation branch 2 times, most recently from 140862e to e67cbac Compare February 2, 2026 06:19
@stevennovaryo stevennovaryo added the T-linux-wpt Do a try run of the WPT label Feb 2, 2026
@github-actions github-actions bot removed the T-linux-wpt Do a try run of the WPT label Feb 2, 2026
@github-actions
Copy link
Copy Markdown

github-actions bot commented Feb 2, 2026

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

Signed-off-by: Jo Steven Novaryo <[email protected]>
@github-actions
Copy link
Copy Markdown

github-actions bot commented Feb 2, 2026

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

Flaky unexpected result (31)
  • OK /FileAPI/file/send-file-form-controls.html
    • FAIL [expected PASS] subtest: Upload file-for-upload-in-form-BS-[�].txt (ASCII) in UTF-8 form

      assert_greater_than: file-for-upload-in-form-BS-[�].txt: multipart form data must have at least 3 lines: "" expected a number greater than 2 but got 0
      

    • FAIL [expected PASS] subtest: Upload file-for-upload-in-form-VT-[�].txt (ASCII) in UTF-8 form

      assert_greater_than: file-for-upload-in-form-VT-[�].txt: multipart form data must have at least 3 lines: "" expected a number greater than 2 but got 0
      

  • OK /FileAPI/file/send-file-form-utf-8.html
    • FAIL [expected PASS] subtest: Upload file-for-upload-in-form-.txt (x-user-defined) in UTF-8 form

      assert_greater_than: file-for-upload-in-form-.txt: multipart form data must have at least 3 lines: "" expected a number greater than 2 but got 0
      

    • FAIL [expected PASS] subtest: Upload file-for-upload-in-form-☺😂.txt (windows-1252) in UTF-8 form

      assert_greater_than: file-for-upload-in-form-☺😂.txt: multipart form data must have at least 3 lines: "" expected a number greater than 2 but got 0
      

  • OK /IndexedDB/idbfactory-databases-opaque-origin.html
    • FAIL [expected PASS] subtest: IDBFactory.databases() in non-sandboxed iframe should not reject

      assert_equals: IDBFactory.databases() should not reject expected "no exception" but got "OperationError"
      

  • OK /IndexedDB/idbfactory-open-error-properties.any.html
    • PASS [expected FAIL] subtest: Properties of error event from failed open()
  • OK /IndexedDB/idbfactory-open-error-properties.any.worker.html
    • PASS [expected FAIL] subtest: Properties of error event from failed open()
  • CRASH [expected OK] /_webgl/conformance/extensions/khr-parallel-shader-compile.html
  • OK /beacon/beacon-basic.https.window.html (#41723)
    • FAIL [expected PASS] subtest: Payload size restriction should be accumulated: type = string

      assert_false: expected false got true
      

  • FAIL [expected PASS] /css/css-backgrounds/background-size-041.html
  • FAIL [expected PASS] /css/css-backgrounds/border-image-repeat-space-9.html
  • 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] /css/css-ui/appearance-menulist-button-001.html
  • OK /custom-elements/form-associated/ElementInternals-setFormValue.html (#29174)
    • PASS [expected FAIL] subtest: Single value - empty name exists
    • PASS [expected FAIL] subtest: Single value - Non-empty name exists
    • PASS [expected FAIL] subtest: Multiple values - name content attribute is ignored
  • 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."
      

  • CRASH [expected OK] /html/browsers/history/the-history-interface/history_replacestate.html
  • TIMEOUT /html/semantics/embedded-content/media-elements/preserves-pitch.html (#40352)
    • PASS [expected TIMEOUT] subtest: Speed-ups should not change the pitch when preservesPitch=true
    • PASS [expected NOTRUN] subtest: Slow-downs should not change the pitch when preservesPitch=true
    • FAIL [expected NOTRUN] subtest: Speed-ups should change the pitch when preservesPitch=false

      assert_approx_equals: The actual pitch should be close to the expected pitch. expected 880 +/- 132 but got 431.0850439882698
      

    • TIMEOUT [expected NOTRUN] subtest: Slow-downs should change the pitch when preservesPitch=false

      Test timed out
      

  • OK [expected TIMEOUT] /html/semantics/embedded-content/media-elements/src_object_blob.html (#40340)
    • PASS [expected TIMEOUT] subtest: HTMLMediaElement.srcObject blob
  • OK /html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-nav-location-assign.html (#32863)
    • FAIL [expected PASS] subtest: Navigating iframe loading='lazy' before it is loaded: location.assign

      uncaught exception: Error: assert_equals: expected "http://web-platform.test:8000/html/semantics/embedded-content/the-iframe-element/support/blank.htm?nav" but got "http://web-platform.test:8000/html/semantics/embedded-content/the-iframe-element/support/blank.htm?src"
      

  • OK /html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-nav-window-open.html (#32596)
    • FAIL [expected PASS] subtest: Navigating iframe loading='lazy' before it is loaded: location.replace

      uncaught exception: Error: assert_equals: expected "http://web-platform.test:8000/html/semantics/embedded-content/the-iframe-element/support/blank.htm?nav" but got "http://web-platform.test:8000/html/semantics/embedded-content/the-iframe-element/support/blank.htm?src"
      

  • 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
      

  • 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)
    • FAIL [expected PASS] subtest: multipart/form-data: Basic test (formdata event)

      assert_equals: expected "\r\nContent-Disposition: form-data; name=\"basic\"\r\n\r\ntest\r\n--\r\n" but got ""
      

    • FAIL [expected PASS] subtest: multipart/form-data: Basic File test (normal form)

      assert_equals: expected "\r\nContent-Disposition: form-data; name=\"basic\"; filename=\"file-test.txt\"\r\nContent-Type: text/plain\r\n\r\n\r\n--\r\n" but got ""
      

  • 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: \r\n in name (normal form)
    • PASS [expected FAIL] subtest: text/plain: \r\n in value (formdata event)
    • PASS [expected FAIL] subtest: text/plain: double quote in value (formdata event)
    • PASS [expected FAIL] subtest: text/plain: non-ASCII in filename (normal form)
  • OK /html/semantics/forms/form-submission-0/urlencoded2.window.html (#28687)
    • 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 value (formdata event)
  • TIMEOUT [expected ERROR] /html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener_base.html (#40347)
  • TIMEOUT [expected OK] /html/user-activation/navigation-state-reset-sameorigin.html
    • TIMEOUT [expected PASS] subtest: Post-navigation state reset.

      Test timed out
      

  • FAIL [expected PASS] /png/apng/fcTL-dispose-previous-first.html
  • 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 /wasm/webapi/abort.any.worker.html (#40013)
    • FAIL [expected PASS] subtest: instantiateStreaming() asynchronously racing with abort should succeed or reject with AbortError

      assert_equals: expected "AbortError" but got "CompileError"
      

  • OK /webdriver/tests/classic/element_click/user_prompts.py
    • FAIL [expected PASS] subtest: test_accept[alert-None]

      webdriver.error.NoSuchWindowException: no such window (404): No such window
      

  • OK /webdriver/tests/classic/new_window/new.py
    • ERROR [expected PASS] subtest: test_no_top_browsing_context

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

  • 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 (36)
  • OK /IndexedDB/idbcursor-continuePrimaryKey-exceptions.any.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/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_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/idbrequest-onupgradeneeded.any.html (#38895)
    • PASS [expected FAIL] subtest: transaction oncomplete ordering relative to open request onsuccess
  • OK /IndexedDB/idbrequest-onupgradeneeded.any.worker.html (#38971)
    • PASS [expected FAIL] subtest: transaction oncomplete ordering relative to open request onsuccess
  • 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 "() =&gt; {
            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] subtest: IDBCursor update() method with throwing/invalid keys

      assert_throws_exactly: throwing getter should rethrow during clone function "() =&gt; {
            cursor.update(value);
          }" threw object "TypeError: cursor.update 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 "() =&gt; {
            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] subtest: IDBCursor update() method with throwing/invalid keys

      assert_throws_exactly: throwing getter should rethrow during clone function "() =&gt; {
            cursor.update(value);
          }" threw object "TypeError: cursor.update is not a function" but we expected it to throw object "getter: throwing from getter"
      

  • OK /IndexedDB/transaction-deactivation-timing.any.html (#38772)
    • PASS [expected FAIL] subtest: New transactions are deactivated before next task
    • PASS [expected FAIL] subtest: New transactions from microtask are deactivated before next task
  • 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
      

  • CRASH [expected PASS] /_mozilla/shadow-dom/move-element-with-ua-shadow-tree-crash.html (#39473)
  • OK /css/css-cascade/layer-font-face-override.html (#35935)
    • 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-001.html (#37467)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted generic(khmer-mul)
  • OK /css/cssom-view/offsetTopLeft-border-box.html (#40826)
    • PASS [expected FAIL] subtest: container: 0
    • PASS [expected FAIL] subtest: container: 1
  • 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/accumulated-oversized-payload.https.window.html (#41705)
  • OK /fetch/metadata/generated/css-font-face.https.sub.tentative.html (#32732)
    • FAIL [expected PASS] subtest: sec-fetch-mode

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

    • PASS [expected FAIL] subtest: sec-fetch-dest
    • FAIL [expected PASS] subtest: sec-fetch-user

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

  • 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."
      

  • TIMEOUT /fetch/metadata/generated/css-images.https.sub.tentative.html (#42229)
    • PASS [expected FAIL] subtest: content sec-fetch-site - Same-Origin -&gt; Same Origin
  • OK /html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/load-pageshow-events-window-open.html (#28691)
    • PASS [expected FAIL] subtest: load event does not fire on window.open('about:blank')
  • 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/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_2.html (#21383)
    • PASS [expected FAIL] subtest: Multiple history traversals, last would be aborted
  • 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 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 &lt;div autofocus=""&gt;&lt;/div&gt; but got Element node &lt;body&gt;&lt;/body&gt;
      

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

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

    • 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"
      

  • TIMEOUT /html/semantics/embedded-content/media-elements/autoplay-allowed-by-feature-policy.https.sub.html (#41404)
    • TIMEOUT [expected PASS] subtest: Feature-Policy header: autoplay * allows same-origin iframes.

      Test timed out
      

  • TIMEOUT /html/semantics/embedded-content/media-elements/autoplay-disabled-by-feature-policy.https.sub.html (#41221)
    • TIMEOUT [expected FAIL] subtest: Feature-Policy header: autoplay "none" disallows same-origin iframes.

      Test timed out
      

  • 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 /navigation-timing/test-navigation-type-reload.html (#33334)
    • FAIL [expected PASS] subtest: Reload domComplete &gt; Original domComplete

      assert_true: Reload domComplete &gt; Original domComplete expected true got false
      

    • FAIL [expected PASS] subtest: Reload domContentLoadedEventEnd &gt; Original domContentLoadedEventEnd

      assert_true: Reload domContentLoadedEventEnd &gt; Original domContentLoadedEventEnd expected true got false
      

    • FAIL [expected PASS] subtest: Reload loadEventEnd &gt; Original loadEventEnd

      assert_true: Reload loadEventEnd &gt; Original loadEventEnd expected true got false
      

    • FAIL [expected PASS] subtest: Reload loadEventStart &gt; Original loadEventStart

      assert_true: Reload loadEventStart &gt; Original loadEventStart expected true got false
      

  • OK /preload/prefetch-document.html (#37210)
    • FAIL [expected PASS] subtest: different-site document prefetch with 'as=document' should not be consumed

      assert_equals: expected 2 but got 1
      

  • OK /resource-timing/test_resource_timing.html (#25720)
    • FAIL [expected NOTRUN] subtest: PerformanceEntry has correct name, initiatorType, startTime, and duration (link)

      assert_equals: expected 10.049999999999997 but got 10.05
      

  • OK /resource-timing/test_resource_timing.https.html (#25216)
    • FAIL [expected PASS] subtest: PerformanceEntry has correct name, initiatorType, startTime, and duration (img)

      assert_equals: expected 9.89 but got 9.88
      

  • TIMEOUT [expected OK] /trusted-types/trusted-types-navigation.html?01-05 (#38975)
    • TIMEOUT [expected PASS] subtest: Navigate a window via anchor with javascript:-urls in report-only mode.

      Test timed out
      

    • NOTRUN [expected PASS] subtest: Navigate a window via anchor with javascript:-urls w/ default policy in report-only mode.
    • NOTRUN [expected PASS] subtest: Navigate a frame via anchor with javascript:-urls in enforcing mode.
  • OK [expected TIMEOUT] /trusted-types/trusted-types-navigation.html?31-35 (#38034)
    • PASS [expected TIMEOUT] subtest: Navigate a frame via form-submission with javascript:-urls w/ default policy in report-only mode.
    • FAIL [expected NOTRUN] subtest: Navigate a window via form-submission 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 form-submission 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!\""
      

    • FAIL [expected NOTRUN] subtest: Navigate a window via form-submission with javascript:-urls w/ a default policy making the URL invalid in enforcing mode.

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

  • OK /visual-viewport/resize-event-order.html (#41981)
    • PASS [expected FAIL] subtest: Popup: DOMWindow resize fired before VisualViewport.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Feb 2, 2026

✨ Try run (#21579578666) succeeded.

@stevennovaryo stevennovaryo marked this pull request as ready for review February 2, 2026 06:54
@servo-highfive servo-highfive added the S-awaiting-review There is new code that needs to be reviewed. label Feb 2, 2026
@stevennovaryo stevennovaryo requested a review from jdm February 2, 2026 06:54
@jdm
Copy link
Copy Markdown
Member

jdm commented Feb 2, 2026

I've asked @kkoyung to take a first look at this PR.


/// <https://html.spec.whatwg.org/multipage/#last-activation-timestamp>
#[no_trace]
last_activation_timestamp: Cell<CrossProcessInstant>,
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.

A last activation timestamp, which is either a DOMHighResTimeStamp, positive infinity (indicating that W has never been activated), or negative infinity (indicating that the activation has been consumed). Initially positive infinity.

We could define a new enum with three variants: NegativeInfinity, TimeStamp(CrossProcessInstant) and PositiveInfinity, and derive PartialOrd trait. This is less ambiguous than using u64::MAX to represent positive infinity.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks! Sure, the definition seems quite specific to UserActivation.

/// <https://html.spec.whatwg.org/multipage/#sticky-activation>
pub(crate) fn has_sticky_activation(&self) -> bool {
// > When the current high resolution time given W is greater than or equal to the last activation timestamp in W, W is said to have sticky activation.
CrossProcessInstant::now() > self.last_activation_timestamp.get()
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.

It should be >=, though it’s unlikely to hit this case :)

self.navigation_start.set(CrossProcessInstant::now());
}

pub(crate) fn last_activation_timestamp(&self) -> CrossProcessInstant {
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.

Will the timestamp read from the outside of window.rs? If no, we directly use self.last_activation_timestamp.get() instead of making a public function.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

For now not, it does sound unnecessary. Thanks!

Copy link
Copy Markdown
Member

@kkoyung kkoyung left a comment

Choose a reason for hiding this comment

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

We can make use of derived PartialOrd and Default trait for UserActivationTimestamp so that we don't need to manually implement PartialEq<CrossProcessInstant>, PartialOrd<CrossProcessInstant> and Default trait.

/// <https://html.spec.whatwg.org/multipage/#sticky-activation>
pub(crate) fn has_sticky_activation(&self) -> bool {
// > When the current high resolution time given W is greater than or equal to the last activation timestamp in W, W is said to have sticky activation.
self.last_activation_timestamp.get() <= CrossProcessInstant::now()
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.

Suggested change
self.last_activation_timestamp.get() <= CrossProcessInstant::now()
UserActivationTimestamp::TimeStamp(CrossProcessInstant::now()) >= self.last_activation_timestamp.get()

Comment on lines +3670 to +3671
self.last_activation_timestamp.get() <= current_time &&
self.last_activation_timestamp.get() >= current_time - time::Duration::milliseconds(pref!(dom_transient_activation_duration_ms))
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.

Suggested change
self.last_activation_timestamp.get() <= current_time &&
self.last_activation_timestamp.get() >= current_time - time::Duration::milliseconds(pref!(dom_transient_activation_duration_ms))
UserActivationTimestamp::TimeStamp(current_time) >= self.last_activation_timestamp.get()
&& UserActivationTimestamp::TimeStamp(current_time) < self.last_activation_timestamp.get() + pref!(dom_transient_activation_duration_ms)

But we still need to implement std::ops::Add<i64> trait for UserActivationTimestamp in useractivation.rs if we write it in this way.

Comment on lines +99 to +104
#[derive(Clone, Copy, PartialEq, MallocSizeOf)]
pub(crate) enum UserActivationTimestamp {
PositiveInfinity,
TimeStamp(CrossProcessInstant),
NegativeInfinity,
}
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.

Suggested change
#[derive(Clone, Copy, PartialEq, MallocSizeOf)]
pub(crate) enum UserActivationTimestamp {
PositiveInfinity,
TimeStamp(CrossProcessInstant),
NegativeInfinity,
}
#[derive(Clone, Copy, Default, PartialEq, PartialOrd, MallocSizeOf)]
pub(crate) enum UserActivationTimestamp {
NegativeInfinity,
TimeStamp(CrossProcessInstant),
#[default]
PositiveInfinity,
}

@stevennovaryo
Copy link
Copy Markdown
Contributor Author

We can make use of derived PartialOrd and Default trait for UserActivationTimestamp so that we don't need to manually implement PartialEq<CrossProcessInstant>, PartialOrd<CrossProcessInstant> and Default trait.

Updated, thanks! It definitely looks better! Just realized how does a PartialOrd implement for enum.

dom_testing_html_input_element_select_files_enabled: false,
dom_testperf_enabled: false,
dom_testutils_enabled: false,
dom_transient_activation_duration_ms: 5000,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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.

The spec expects this to be at most a few seconds, so setting it to 5 seconds seems fine and aligns with Firefox and Chrome.

Signed-off-by: Jo Steven Novaryo <[email protected]>
@stevennovaryo
Copy link
Copy Markdown
Contributor Author

stevennovaryo commented Feb 2, 2026

I have also done some WPT analysis to take a look at implementation correctness and at what's need to be completed.

Details html\user-activation\message-event-init.tentative.html

html\user-activation\message-event-activation-api-iframe-cross-origin.sub.tentative.html
* MessageEvent with UserActivation is not a standardized yet.

html\user-activation\activation-trigger-mouse-right.html.ini
* We doesn't fire auxclick event for right mouse click.

html\user-activation\activation-trigger-pointerevent.html
* Need to wait for PointerEvent implementation.

html\user-activation\navigate-to-sameorigin.html
* Needs more investigation.

html\user-activation\navigation-state-reset-crossorigin.sub.html
html\user-activation\propagation-crossorigin.sub.html
html\user-activation\propagation-same-and-cross-origin.sub.html
* Cross origin propagation is not supposed to work.

html/semantics/links/links-created-by-a-and-area-elements/target_blank_useractivation.html
html/semantics/links/links-created-by-a-and-area-elements/target_blank_useractivation_multi_globals.html
* User activation should be considered in navigation.

html/capability-delegation/delegate-fullscreen-request-popup-cross-origin.https.sub.tentative.html
html/capability-delegation/delegate-fullscreen-request-popup-same-origin.https.tentative.html
* Capability Delegation is yet to be implemented.

@kkoyung
Copy link
Copy Markdown
Member

kkoyung commented Feb 2, 2026

I have also done some WPT analysis to take a look at implementation correctness and at what's need to be completed.
Details

This PR looks good to me now. Those failing tests mostly depend on implementation of other parts. We can open an issue with your analysis after merging this PR so that we won't lose it.

@servo-highfive servo-highfive removed the S-awaiting-review There is new code that needs to be reviewed. label Feb 2, 2026
Signed-off-by: Jo Steven Novaryo <[email protected]>
@servo-highfive servo-highfive added the S-awaiting-review There is new code that needs to be reviewed. label Feb 3, 2026
@jdm jdm added this pull request to the merge queue Feb 3, 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 Feb 3, 2026
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Feb 3, 2026
@servo-highfive servo-highfive added S-tests-failed The changes caused existing tests to fail. and removed S-awaiting-merge The PR is in the process of compiling and running tests on the automated CI. labels Feb 3, 2026
@jdm jdm added this pull request to the merge queue Feb 3, 2026
@servo-highfive servo-highfive added S-awaiting-merge The PR is in the process of compiling and running tests on the automated CI. and removed S-tests-failed The changes caused existing tests to fail. labels Feb 3, 2026
Merged via the queue into servo:main with commit 42359b2 Feb 4, 2026
38 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 Feb 4, 2026
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.

4 participants