Skip to content

dom: Textual Input UA Shadow Dom#37527

Merged
xiaochengh merged 4 commits intoservo:mainfrom
stevennovaryo:textual-input-shadow-dom
Jul 25, 2025
Merged

dom: Textual Input UA Shadow Dom#37527
xiaochengh merged 4 commits intoservo:mainfrom
stevennovaryo:textual-input-shadow-dom

Conversation

@stevennovaryo
Copy link
Copy Markdown
Contributor

Depend on:

Utilize input type=text for the display of all textual input. In which, consist of https://html.spec.whatwg.org/#the-input-element-as-a-text-entry-widget and https://html.spec.whatwg.org/#the-input-element-as-domain-specific-widgets inputs.

For password, url, tel, and, email input, the appearance of input container is exactly the same as the text input. Other types of textual input simply extends text input by adding extra components inside the container.

Testing: Servo textual input appearance WPT.

@stevennovaryo stevennovaryo force-pushed the textual-input-shadow-dom branch from 00b02f4 to 19ff07d Compare June 18, 2025 08:54
@stevennovaryo stevennovaryo force-pushed the textual-input-shadow-dom branch from 19ff07d to 146c40f Compare July 23, 2025 20:37
@stevennovaryo stevennovaryo added the T-linux-wpt Do a try run of the WPT label Jul 23, 2025
@github-actions github-actions bot removed the T-linux-wpt Do a try run of the WPT label Jul 23, 2025
@github-actions
Copy link
Copy Markdown

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

@stevennovaryo stevennovaryo marked this pull request as ready for review July 23, 2025 20:39
@stevennovaryo stevennovaryo requested a review from gterzian as a code owner July 23, 2025 20:39
@stevennovaryo stevennovaryo requested a review from xiaochengh July 23, 2025 20:39
@github-actions
Copy link
Copy Markdown

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

Flaky unexpected result (15)
  • OK /css/css-fonts/generic-family-keywords-001.html (#37467)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted generic(nastaliq)
  • FAIL [expected PASS] /css/css-sizing/dynamic-available-size-iframe.html (#31559)
  • OK [expected ERROR] /fetch/fetch-later/quota/same-origin-iframe/small-payload.tentative.https.window.html (#35210)
  • 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 cross-site destination
  • PASS [expected FAIL] /html/canvas/element/manual/text/canvas.2d.disconnected.html (#30063)
  • CRASH [expected OK] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-3.html (#24057)
  • OK /html/semantics/forms/form-submission-0/multipart-formdata.window.html (#28725)
    • PASS [expected FAIL] subtest: multipart/form-data: Basic test (normal form)
  • OK /html/semantics/forms/form-submission-0/urlencoded2.window.html (#28687)
    • FAIL [expected PASS] subtest: application/x-www-form-urlencoded: Basic test (normal form)

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

  • CRASH [expected TIMEOUT] /html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener.html
  • 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 /resource-timing/test_resource_timing.html (#25720)
    • PASS [expected FAIL] subtest: PerformanceEntry has correct name, initiatorType, startTime, and duration (img)
  • ERROR /service-workers/idlharness.https.any.html (#36250)
    • PASS [expected TIMEOUT] subtest: ServiceWorkerContainer interface: operation register((TrustedScriptURL or USVString), optional RegistrationOptions)
    • PASS [expected TIMEOUT] subtest: NavigationPreloadManager interface: operation enable()
    • PASS [expected TIMEOUT] subtest: NavigationPreloadManager interface: operation disable()
    • PASS [expected TIMEOUT] subtest: NavigationPreloadManager interface: operation setHeaderValue(ByteString)
    • PASS [expected TIMEOUT] subtest: NavigationPreloadManager interface: operation getState()
  • TIMEOUT [expected CRASH] /trusted-types/trusted-types-navigation.html?31-35 (#38034)
    • FAIL [expected PASS] subtest: Navigate a frame via form-submission with javascript:-urls in report-only mode.

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

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

      Test timed out
      

    • NOTRUN [expected PASS] subtest: Navigate a window via form-submission with javascript:-urls w/ a default policy throwing an exception in enforcing mode.
    • NOTRUN [expected PASS] subtest: Navigate a window via form-submission with javascript:-urls w/ a default policy throwing an exception in report-only mode.
    • NOTRUN [expected PASS] subtest: Navigate a window via form-submission with javascript:-urls w/ a default policy making the URL invalid in enforcing mode.
  • TIMEOUT [expected OK] /webmessaging/without-ports/018.html (#24485)
    • TIMEOUT [expected PASS] subtest: origin of the script that invoked the method, javascript:

      Test timed out
      

Stable unexpected results that are known to be intermittent (19)
  • OK /FileAPI/url/url-with-fetch.any.worker.html (#21517)
    • FAIL [expected PASS] subtest: Revoke blob URL after calling fetch, fetch should succeed

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

  • FAIL [expected PASS] /_mozilla/css/stacked_layers.html (#15988)
  • 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
      

  • TIMEOUT [expected FAIL] /dom/xslt/large-cdata.html (#38029)
  • OK /html/browsers/browsing-the-web/navigating-across-documents/008.html (#24456)
    • PASS [expected FAIL] subtest: Link with onclick form submit to javascript url and href navigation
  • OK /html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/load-pageshow-events-iframe-contentWindow.html (#28681)
    • PASS [expected FAIL] subtest: load & pageshow events do not fire on contentWindow of <iframe> element created with src='about:blank'
  • OK /html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/a-click.html (#28697)
    • PASS [expected FAIL] subtest: aElement.click() before the load event must NOT replace
  • OK [expected TIMEOUT] /html/interaction/focus/the-autofocus-attribute/supported-elements.html (#24145)
    • 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></body>
      

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

      promise_test: Unhandled rejection with value: object "TypeError: w.document.querySelector(...) is null"
      

  • CRASH [expected OK] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-2.html (#22667)
  • TIMEOUT [expected OK] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-1.html (#24066)
    • NOTRUN [expected FAIL] subtest: Check that popups from a sandboxed iframe do not escape the sandbox
  • OK /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-2.html (#22154)
    • FAIL [expected NOTRUN] subtest: Check that popups from a sandboxed iframe do not escape the sandbox

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

  • OK [expected CRASH] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-3.html (#24066)
    • FAIL [expected NOTRUN] subtest: Check that popups from a sandboxed iframe do not escape the sandbox

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

  • OK [expected TIMEOUT] /html/semantics/forms/form-submission-0/reparent-form-during-planned-navigation-task.html (#29724)
    • PASS [expected TIMEOUT] subtest: reparent-form-during-planned-navigation-task
  • OK /navigation-timing/test-navigation-type-reload.html (#33334)
    • PASS [expected FAIL] subtest: Reload domContentLoadedEventEnd > Original domContentLoadedEventEnd
    • PASS [expected FAIL] subtest: Reload domContentLoadedEventStart > Original domContentLoadedEventStart
    • PASS [expected FAIL] subtest: Reload domInteractive > Original domInteractive
    • PASS [expected FAIL] subtest: Reload fetchStart > Original fetchStart
  • OK /preload/preload-error.sub.html (#37177)
    • FAIL [expected PASS] subtest: success (style): main

      assert_greater_than: http://web-platform.test:8000/preload/resources/dummy.css?label=style should be loaded expected a number greater than 0 but got 0
      

    • PASS [expected FAIL] subtest: CORS (style): main
    • PASS [expected FAIL] subtest: success (script): main
    • FAIL [expected PASS] subtest: 404 (script): main

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

    • PASS [expected FAIL] subtest: success (xhr): main
    • PASS [expected FAIL] subtest: 404 (xhr): main
    • FAIL [expected PASS] subtest: Decode-error (script): main

      assert_greater_than: http://web-platform.test:8000/preload/resources/dummy.xml?pipe=header%28Content-Type%2Ctext%2Fjavascript%29&label=script should be loaded expected a number greater than 0 but got 0
      

  • CRASH [expected TIMEOUT] /trusted-types/trusted-types-navigation.html?06-10 (#37920)
  • OK /webaudio/the-audio-api/the-audiobuffersourcenode-interface/sub-sample-buffer-stitching.html (#22849)
    • FAIL [expected PASS] subtest: X Stitched sine-wave buffers at sample rate 43800 does not equal [0,0.06264832615852356,0.12505052983760834,0.18696144223213196,0.24813786149024963,0.308339387178421,0.36732959747314453,0.4248766601085663,0.480754554271698,0.5347436666488647,0.5866320133209229,0.6362156271934509,0.6832997798919678,0.7276994585990906,0.7692402601242065,0.8077589869499207...] with an element-wise tolerance of {"absoluteThreshold":0.0038986,"relativeThreshold":0}. Index Actual Expected AbsError RelError Test threshold [14620] -1.3314420899840000e+12 -7.3546999692916870e-1 1.3314420899832646e+12 1.8103282194276819e+12 3.8985999999999999e-3 [14621] -3.6017334461212158e-1 -6.9157749414443970e-1 3.3140414953231812e-1 4.7920030992665957e-1 3.8985999999999999e-3 Max AbsError of 1.3314420899832646e+12 at index of 14620. Max RelError of 1.8103282194276819e+12 at index of 14620.

      assert_true: expected true got false
      

    • FAIL [expected PASS] subtest: X SNR (-199.0523596937963 dB) is not greater than or equal to 65.737. Got -199.0523596937963.

      assert_true: expected true got false
      

  • OK [expected ERROR] /webxr/render_state_update.https.html (#27535)
Stable unexpected results (5)
  • FAIL [expected PASS] /html/rendering/replaced-elements/attributes-for-embedded-content-and-images/number-placeholder-right-aligned.html
  • OK /html/rendering/widgets/field-sizing-input-number.html
    • FAIL [expected PASS] subtest: number: Text caret is taller than the placeholder

      assert_less_than: expected a number less than 338 but got 338
      

  • FAIL [expected PASS] /html/rendering/widgets/input-date-content-size.html
  • FAIL [expected PASS] /html/rendering/widgets/input-number-text-size.tentative.html
  • FAIL [expected PASS] /html/rendering/widgets/input-time-content-size.html

@github-actions
Copy link
Copy Markdown

⚠️ Try run (#16481302530) failed.

Copy link
Copy Markdown
Contributor

@xiaochengh xiaochengh left a comment

Choose a reason for hiding this comment

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

Looks good overall!

I assume in future PRs you'll make different text input types have slightly different shadow DOM?

fn update_shadow_tree(&self, can_gc: CanGc) {
let input_type = self.input_type();
match input_type {
_ if input_type.is_textual_or_password() => self.update_textual_or_password_shadow_tree(can_gc),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

is_textual includes the hidden type.

I don't think we should construct a shadow DOM for hidden inputs.

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.

Ah yes it also include type=hidden ones. Thanks for catching that!

@stevennovaryo
Copy link
Copy Markdown
Contributor Author

Looks good overall!

I assume in future PRs you'll make different text input types have slightly different shadow DOM?

Yes, any textual inputs with its unique widgets will get its own shadow tree logic.

I picture there will be more sophisticated architecture for constructing the shadow DOM, especially when we want to reuse some logic and optimize the construction.

@stevennovaryo
Copy link
Copy Markdown
Contributor Author

stevennovaryo commented Jul 24, 2025

Done a little bit of look through failed WPTs, all of them is a false positive PASS.

  • Failed WPT due to rendering the input element without default sizes (e.g., it will follow the inline size of the content, thus would be zero when there are no width).
    • /html/rendering/widgets/input-date-content-size.html
    • /html/rendering/widgets/input-number-text-size.tentative.html
    • /html/rendering/widgets/input-time-content-size.html
  • Caret size issues and field-sizing
    • /html/rendering/widgets/field-sizing-input-number.html
  • /html/rendering/replaced-elements/attributes-for-embedded-content-and-images/number-placeholder-right-aligned.html
    • Is also a false positive PASS, we are yet to use Shadow DOM for number not to mention a specific case of it.

Signed-off-by: Jo Steven Novaryo <[email protected]>
Signed-off-by: Jo Steven Novaryo <[email protected]>
@stevennovaryo stevennovaryo requested a review from xiaochengh July 24, 2025 09:21
@stevennovaryo stevennovaryo added the T-linux-wpt Do a try run of the WPT label Jul 24, 2025
@github-actions github-actions bot removed the T-linux-wpt Do a try run of the WPT label Jul 24, 2025
@github-actions
Copy link
Copy Markdown

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

@github-actions
Copy link
Copy Markdown

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

Flaky unexpected result (11)
  • 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/variations/at-font-face-font-matching.html (#20684)
    • FAIL [expected PASS] subtest: Matching font-style: 'normal' should prefer 'oblique -50deg -20deg' over 'oblique -40deg -30deg'

      assert_equals: Unexpected font on test element expected 487 but got 532
      

    • PASS [expected FAIL] subtest: Matching font-style: 'oblique -20deg' should prefer 'oblique 40deg 50deg' over 'italic'
  • 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 /html/browsers/browsing-the-web/navigating-across-documents/009.html (#24456)
    • PASS [expected FAIL] subtest: Link with onclick form submit to javascript url with document.write and href navigation
  • OK /html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-same-origin-fragment.html (#20768)
    • FAIL [expected PASS] subtest: Tests that a fragment navigation in the unload handler will not block the initial navigation

      assert_equals: expected "" but got "#fragment"
      

  • OK /html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/form-submit-cross-frame.html (#37183)
    • FAIL [expected PASS] subtest: No replace before load, triggered by cross-iframe formElement.submit()

      assert_equals: frame's after-submit history.length expected 2 but got 1
      

  • TIMEOUT [expected OK] /html/browsers/sandboxing/sandbox-initial-empty-document-toward-same-origin.html (#35948)
  • TIMEOUT [expected OK] /html/infrastructure/urls/base-url/document-base-url-window-initiator-is-not-opener.https.window.html (#30970)
  • TIMEOUT [expected OK] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-1.html (#22647)
    • TIMEOUT [expected FAIL] subtest: Check that popups from a sandboxed iframe escape the sandbox if allow-popups-to-escape-sandbox is used

      Test timed out
      

  • OK /html/semantics/forms/form-submission-0/text-plain.window.html (#28687)
    • PASS [expected FAIL] subtest: text/plain: Basic test (normal form)
  • OK /resize-observer/eventloop.html (#33599)
    • PASS [expected FAIL] subtest: test0: multiple notifications inside same event loop
Stable unexpected results that are known to be intermittent (25)
  • OK /FileAPI/url/url-with-fetch.any.worker.html (#21517)
    • FAIL [expected PASS] subtest: Revoke blob URL after calling fetch, fetch should succeed

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

  • FAIL [expected PASS] /_mozilla/css/stacked_layers.html (#15988)
  • FAIL [expected PASS] /_mozilla/mozilla/sslfail.html (#10760)
  • OK /content-security-policy/frame-ancestors/frame-ancestors-path-ignored.window.html (#36468)
    • PASS [expected FAIL] subtest: A 'frame-ancestors' CSP directive with a URL that includes a path should be ignored.
  • OK /css/css-cascade/layer-font-face-override.html (#35935)
    • PASS [expected FAIL] subtest: @font-face override update with appended sheet 1
    • PASS [expected FAIL] subtest: @font-face override update with appended sheet 2
  • OK /css/css-fonts/generic-family-keywords-001.html (#37467)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted generic(khmer-mul)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted generic(nastaliq)
  • TIMEOUT [expected FAIL] /dom/xslt/large-cdata.html (#38029)
  • OK /fetch/metadata/generated/css-font-face.https.sub.tentative.html (#32732)
    • PASS [expected FAIL] subtest: sec-fetch-dest
  • 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
  • OK /html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/load-pageshow-events-iframe-contentWindow.html (#28681)
    • PASS [expected FAIL] subtest: load &amp; pageshow events do not fire on contentWindow of &lt;iframe&gt; element created with src='about:blank'
  • OK /html/browsers/history/the-history-interface/traverse_the_history_4.html (#21383)
    • FAIL [expected PASS] subtest: Multiple history traversals, last would be aborted

      assert_array_equals: Pages opened during history navigation expected property 1 to be 5 but got 3 (expected array [6, 5] got [6, 3])
      

  • OK [expected TIMEOUT] /html/interaction/focus/the-autofocus-attribute/supported-elements.html (#24145)
    • 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: w.document.querySelector(...) is null"
      

  • OK /html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-reload-location-reload.html (#32595)
    • FAIL [expected PASS] subtest: Reloading iframe loading='lazy' before it is loaded: location.reload

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

  • OK /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-2.html (#22154)
    • FAIL [expected NOTRUN] subtest: Check that popups from a sandboxed iframe do not escape the sandbox

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

  • OK [expected CRASH] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-3.html (#24066)
    • FAIL [expected NOTRUN] subtest: Check that popups from a sandboxed iframe do not escape the sandbox

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

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

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

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

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

  • OK /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 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/preload-error.sub.html (#37177)
    • FAIL [expected PASS] subtest: success (style): main

      assert_greater_than: http://web-platform.test:8000/preload/resources/dummy.css?label=style should be loaded expected a number greater than 0 but got 0
      

    • PASS [expected FAIL] subtest: CORS (style): main
    • PASS [expected FAIL] subtest: success (script): main
    • FAIL [expected PASS] subtest: 404 (script): main

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

    • FAIL [expected PASS] subtest: CORS (script): main

      assert_greater_than: http://not-web-platform.test:8000/preload/resources/dummy.js?pipe=header%28Access-Control-Allow-Origin%2C*%29&amp;label=script should be loaded expected a number greater than 0 but got 0
      

    • PASS [expected FAIL] subtest: Decode-error (style): main
    • PASS [expected FAIL] subtest: MIME-error (script): main
  • CRASH [expected OK] /resource-timing/tentative/document-initiated.html (#37785)
  • OK /webaudio/the-audio-api/the-audiobuffersourcenode-interface/sub-sample-buffer-stitching.html (#22849)
    • FAIL [expected PASS] subtest: X Stitched sine-wave buffers at sample rate 43800 does not equal [0,0.06264832615852356,0.12505052983760834,0.18696144223213196,0.24813786149024963,0.308339387178421,0.36732959747314453,0.4248766601085663,0.480754554271698,0.5347436666488647,0.5866320133209229,0.6362156271934509,0.6832997798919678,0.7276994585990906,0.7692402601242065,0.8077589869499207...] with an element-wise tolerance of {"absoluteThreshold":0.0038986,"relativeThreshold":0}. Index Actual Expected AbsError RelError Test threshold [14620] -2.0318148000000000e+7 -7.3546999692916870e-1 2.0318147264530003e+7 2.7626072238656927e+7 3.8985999999999999e-3 [14621] -3.6017334461212158e-1 -6.9157749414443970e-1 3.3140414953231812e-1 4.7920030992665957e-1 3.8985999999999999e-3 Max AbsError of 2.0318147264530003e+7 at index of 14620. Max RelError of 2.7626072238656927e+7 at index of 14620.

      assert_true: expected true got false
      

    • FAIL [expected PASS] subtest: X SNR (-102.72359613067829 dB) is not greater than or equal to 65.737. Got -102.72359613067829.

      assert_true: expected true got false
      

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

      Test timed out
      

@github-actions
Copy link
Copy Markdown

✨ Try run (#16493052265) succeeded.

// To increase the performance, we would only do this when it is necessary.
fn update_text_shadow_tree_placeholder(&self, can_gc: CanGc) {
if self.input_type() != InputType::Text {
if !self.input_type().is_textual_or_password() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Need to exclude hidden

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, I have changed it!


// FIXME: All the non-color and non-text input types currently render as text
!matches!(input.input_type(), InputType::Color | InputType::Text)
!input.input_type().is_textual_or_password() && input.input_type() != InputType::Color
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

How about hidden?

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!

@xiaochengh
Copy link
Copy Markdown
Contributor

I'm wondering if there's a chance of refactoring input:

  • HTMLInputElement only keeps the DOM and JS interfaces
  • Everything else is routed to distinct internal implementations e.g. TextInputType, ColorInputType, TimeInputType, etc.

<input> was a design mistake of HTML that puts too many unrelated stuff into one element. If it were designed today, it would be designed as many different elements. For our implementation, we can try to alleviate this design mistake as much as we can.

Signed-off-by: Jo Steven Novaryo <[email protected]>
@stevennovaryo stevennovaryo force-pushed the textual-input-shadow-dom branch from 3daff7d to 6c1848d Compare July 25, 2025 04:03
@stevennovaryo
Copy link
Copy Markdown
Contributor Author

stevennovaryo commented Jul 25, 2025

I'm wondering if there's a chance of refactoring input:

  • HTMLInputElement only keeps the DOM and JS interfaces
  • Everything else is routed to distinct internal implementations e.g. TextInputType, ColorInputType, TimeInputType, etc.

<input> was a design mistake of HTML that puts too many unrelated stuff into one element. If it were designed today, it would be designed as many different elements. For our implementation, we can try to alleviate this design mistake as much as we can.

I am wondering the same, I feel like one of the possible refactoring is by moving the input specific utilities to other a trait, or, if it is large enough we could create a wrapper for all attributes that is related to it. e.g., for wrapper for textual inputs, wrapping textinput inside of it, and containing all of utilities specific to textual ones (e.g. validations, pattern checking).

A further design planning should be required though.

@xiaochengh
Copy link
Copy Markdown
Contributor

I'm wondering if there's a chance of refactoring input:

  • HTMLInputElement only keeps the DOM and JS interfaces
  • Everything else is routed to distinct internal implementations e.g. TextInputType, ColorInputType, TimeInputType, etc.

<input> was a design mistake of HTML that puts too many unrelated stuff into one element. If it were designed today, it would be designed as many different elements. For our implementation, we can try to alleviate this design mistake as much as we can.

I am wondering the same, I feel like one of the possible refactoring is by moving the input specific utilities to other a trait, or, if it is large enough we could create a wrapper for all attributes that is related to it. e.g., for wrapper for textual inputs, wrapping textinput inside of it, and containing all of utilities specific to textual ones (e.g. validations, pattern checking).

A further design planning should be required though.

True, that's way out of the scope of this PR. We can file an issue and think about it later.

@xiaochengh xiaochengh enabled auto-merge July 25, 2025 04:35
@xiaochengh xiaochengh added this pull request to the merge queue Jul 25, 2025
Merged via the queue into servo:main with commit 6cd8578 Jul 25, 2025
21 checks passed
minghuaw pushed a commit to minghuaw/servo that referenced this pull request Aug 1, 2025
Depend on: 
- servo#37427
- servo#37483

Utilize input `type=text` for the display of all textual input. In
which, consist of
https://html.spec.whatwg.org/#the-input-element-as-a-text-entry-widget
and
https://html.spec.whatwg.org/#the-input-element-as-domain-specific-widgets
inputs.

For `password`, `url`, `tel`, and, `email` input, the appearance of
input container is exactly the same as the `text` input. Other types of
textual input simply extends `text` input by adding extra components
inside the container.

Testing: Servo textual input appearance WPT.

---------

Signed-off-by: stevennovaryo <[email protected]>
Signed-off-by: Jo Steven Novaryo <[email protected]>
github-merge-queue bot pushed a commit that referenced this pull request Aug 22, 2025
Following #37527, every textual input is constructing the containers for
value and placeholder. However not all of textual `<input>` element
require the initialization of such placeholder container. This is
apparent with JS UI framework that defines its own placeholder
management.

This PR add lazy initialization for placeholder which construct the
relevant HTML elements for placeholder container whenever it is
necessary.

Testing: Existing WPT coverage

Signed-off-by: Jo Steven Novaryo <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants