Skip to content

Reland Input type=text Shadow DOM With Performance Improvement#37483

Merged
xiaochengh merged 3 commits intoservo:mainfrom
stevennovaryo:input-type-text-reland
Jul 23, 2025
Merged

Reland Input type=text Shadow DOM With Performance Improvement#37483
xiaochengh merged 3 commits intoservo:mainfrom
stevennovaryo:input-type-text-reland

Conversation

@stevennovaryo
Copy link
Copy Markdown
Contributor

@stevennovaryo stevennovaryo commented Jun 16, 2025

Depends on #37427.

In addition to the changes introduced by #37065, there are several performance improvements and nits as follows:

  • Use the internal pseudo element for style matching, this will reduce the performance regression by ~66%.
  • Manual construction of the Text node inside a text container. This is followed by the modification of the inner Text node instead of using SetTextContent which is more expensive.
  • Use implemented_pseudo_element instead of text_control_inner_editor NodeFlag to handle the special cases that these elements should follow, specifically the:
    • focus delegation workaround;
    • selections; and
    • line height resolving.
  • More documentation.

Servo's side of: servo/stylo#217

Testing: No new unexpected WPT failure, except for the one introduced by #37065.
Fixes: #36307 #37205

@stevennovaryo
Copy link
Copy Markdown
Contributor Author

stevennovaryo commented Jun 16, 2025

Performance Impact

Note that these changes will definitely introduce some performance regression due to the bulkier <input> element. But the current <input> element should not be the benchmark point either, since it is not and won't be able to support the behavior of a <input> element.

Specifically, the main cause of the regression should be the construction of the UA shadow DOM. Particularly, it will construct 6 additional nodes that include a shadow root, three div elements, and two text nodes. The previous version of <input> would skip all of these and handle it in the layout stages. However, this would make the encapsulation and implementation of input components too unorthodox and difficult to support (e.g., would not be able to utilize Stylo for the pseudo elements ::placeholder, ::field-text).

Future Plan

cc: @xiaochengh

@stevennovaryo stevennovaryo force-pushed the input-type-text-reland branch from a86aff8 to 52697ae Compare June 16, 2025 08:48
@stevennovaryo stevennovaryo changed the title Reland Input type=text With Performance Improvement Reland Input type=text Shadow DOM With Performance Improvement Jun 16, 2025
@xiaochengh xiaochengh self-requested a review June 16, 2025 10:34
@stevennovaryo stevennovaryo force-pushed the input-type-text-reland branch from 52697ae to 5fd2d6e Compare July 10, 2025 03:13
@stevennovaryo stevennovaryo added the T-linux-wpt Do a try run of the WPT label Jul 10, 2025
@stevennovaryo stevennovaryo marked this pull request as ready for review July 10, 2025 03:14
@github-actions github-actions bot removed the T-linux-wpt Do a try run of the WPT label Jul 10, 2025
@github-actions
Copy link
Copy Markdown

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

@github-actions
Copy link
Copy Markdown

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

Flaky unexpected result (20)
  • FAIL [expected PASS] /_mozilla/css/iframe/hide_and_show.html (#15265)
  • OK /css/css-fonts/variations/at-font-face-font-matching.html (#20684)
    • PASS [expected FAIL] subtest: Matching font-style: 'oblique 0deg' should prefer 'oblique -40deg -30deg' over 'italic'
  • 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/009.html (#24456)
    • FAIL [expected PASS] subtest: Link with onclick form submit to javascript url with document.write and href navigation

      assert_array_equals: expected property 1 to be "href" but got "click" (expected array ["write", "href"] got ["write", "click"])
      

  • 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/browsing-the-web/navigating-across-documents/navigation-unload-same-origin.window.html (#29049)
    • PASS [expected FAIL] subtest: Same-origin navigation started from unload handler must be ignored
  • OK /html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/a-click.html (#28697)
    • PASS [expected FAIL] subtest: aElement.click() before the load event must NOT replace
  • OK /html/browsers/history/the-history-interface/traverse_the_history_4.html (#21383)
    • PASS [expected FAIL] subtest: Multiple history traversals, last would be aborted
  • TIMEOUT [expected OK] /html/infrastructure/urls/base-url/document-base-url-window-initiator-is-not-opener.https.window.html (#30970)
  • OK /html/semantics/embedded-content/the-video-element/intrinsic_sizes.htm (#37173)
    • FAIL [expected PASS] subtest: default object size after src is removed

      assert_equals: expected "300px" but got "320px"
      

  • OK /html/semantics/forms/form-submission-0/urlencoded2.window.html (#28687)
    • PASS [expected FAIL] subtest: application/x-www-form-urlencoded: Basic test (normal form)
  • OK /navigation-timing/test-navigation-type-reload.html (#33334)
    • PASS [expected FAIL] subtest: Reload domContentLoadedEventStart &gt; Original domContentLoadedEventStart
    • PASS [expected FAIL] subtest: Reload domInteractive &gt; Original domInteractive
    • PASS [expected FAIL] subtest: Reload fetchStart &gt; Original fetchStart
  • 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
      

  • TIMEOUT /preload/preload-resource-match.https.html
    • TIMEOUT [expected FAIL] subtest: Loading script (use-credentials) with link (no-cors) should discard the preloaded response

      Test timed out
      

    • NOTRUN [expected TIMEOUT] subtest: Loading script (use-credentials) with link (anonymous) should discard the preloaded response
  • OK /resize-observer/change-layout-in-error.html (#32629)
    • PASS [expected FAIL] subtest: Changing layout in window error handler should not result in lifecyle loop when resize observer loop limit is reached.
  • OK [expected TIMEOUT] /webmessaging/without-ports/017.html (#24486)
    • PASS [expected TIMEOUT] subtest: origin of the script that invoked the method, about:blank
  • TIMEOUT [expected OK] /webstorage/localstorage-about-blank-3P-iframe-opens-3P-window.partitioned.html (#29053)
    • TIMEOUT [expected PASS] subtest: StorageKey: test 3P about:blank window opened from a 3P iframe

      Test timed out
      

  • OK [expected ERROR] /webxr/render_state_update.https.html (#27535)
  • OK [expected ERROR] /workers/constructors/Worker/Worker-constructor.html (#22991)
  • OK /xhr/open-url-multi-window-5.htm (#23360)
    • FAIL [expected PASS] subtest: XMLHttpRequest: open() resolving URLs (multi-Window; 5)

      assert_throws_dom: function "function() {client.open("GET", "...") }" did not throw
      

Stable unexpected results that are known to be intermittent (23)
  • 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
      

  • OK /css/cssom-view/scroll-behavior-smooth-navigation.html (#29564)
    • PASS [expected FAIL] subtest: Smooth scrolling while doing history navigation.
  • ERROR [expected TIMEOUT] /fetch/fetch-later/quota/same-origin-iframe/max-payload.tentative.https.window.html (#35210)
  • OK [expected ERROR] /fetch/fetch-later/quota/same-origin-iframe/multiple-iframes.tentative.https.window.html (#35176)
  • OK /fetch/metadata/generated/css-font-face.https.sub.tentative.html (#32732)
    • PASS [expected FAIL] subtest: sec-fetch-dest
    • PASS [expected FAIL] subtest: sec-fetch-user
  • OK /html/browsers/history/the-history-interface/traverse_the_history_5.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])
      

  • PASS [expected FAIL] /html/canvas/element/manual/text/canvas.2d.disconnected.html (#30063)
  • OK [expected TIMEOUT] /html/interaction/focus/the-autofocus-attribute/supported-elements.html (#24145)
    • PASS [expected NOTRUN] subtest: Non-HTMLElement should not support autofocus
    • FAIL [expected NOTRUN] subtest: Host element with delegatesFocus should support autofocus

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

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

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

      Test timed out
      

  • OK [expected TIMEOUT] /html/semantics/embedded-content/media-elements/playing-the-media-resource/loop-from-ended.tentative.html (#33778)
    • FAIL [expected TIMEOUT] subtest: play() with loop set to true after playback ended

      this argument is not a finite floating-point value
      

  • OK /html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-nav-location-assign.html (#32863)
    • PASS [expected FAIL] subtest: Navigating iframe loading='lazy' before it is loaded: location.assign
  • CRASH [expected TIMEOUT] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-2.html (#22667)
  • OK [expected TIMEOUT] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-3.html (#24057)
  • TIMEOUT /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-2.html (#22154)
    • NOTRUN [expected FAIL] subtest: Check that popups from a sandboxed iframe do not escape the sandbox
  • OK [expected TIMEOUT] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-3.html (#24066)
  • OK /preload/preload-error.sub.html (#37177)
    • PASS [expected FAIL] subtest: 404 (style): main
    • PASS [expected FAIL] subtest: success (script): main
    • PASS [expected FAIL] subtest: CORS (script): main
    • PASS [expected FAIL] subtest: success (xhr): main
    • PASS [expected FAIL] subtest: 404 (xhr): main
    • PASS [expected FAIL] subtest: CORS (xhr): main
    • PASS [expected FAIL] subtest: MIME-error (script): main
  • OK [expected TIMEOUT] /resource-timing/tentative/document-initiated.html (#37785)
  • 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()
  • CRASH [expected TIMEOUT] /trusted-types/trusted-types-navigation.html?06-10 (#37920)
  • TIMEOUT [expected OK] /webmessaging/with-ports/018.html (#24485)
    • TIMEOUT [expected PASS] subtest: origin of the script that invoked the method, javascript:

      Test timed out
      

  • OK [expected TIMEOUT] /webmessaging/without-ports/018.html (#24485)
    • PASS [expected TIMEOUT] subtest: origin of the script that invoked the method, javascript:
Stable unexpected results (6)
  • OK /content-security-policy/form-action/form-action-src-default-ignored.sub.html
    • PASS [expected FAIL] subtest: Expecting logs: ["PASS","TEST COMPLETE"]
  • OK /url/IdnaTestV2.window.html
    • PASS [expected FAIL] subtest: ToASCII("≠ᢙ&gt;̸.솣-ᡴႠ")
    • PASS [expected FAIL] subtest: ToASCII("≠ᢙ≯.솣-ᡴႠ")
    • PASS [expected FAIL] subtest: ToASCII("𞤥󠅮.ᡄႮ")
    • PASS [expected FAIL] subtest: ToASCII("𞤥󠅮.ᡄႮ")
    • PASS [expected FAIL] subtest: ToASCII("𞤃󠅮.ᡄႮ")
    • PASS [expected FAIL] subtest: ToASCII("𞤃.ᡄႮ")
    • PASS [expected FAIL] subtest: ToASCII("𞤃󠅮.ᡄႮ")
    • PASS [expected FAIL] subtest: ToASCII("𞤥.ᡄႮ")
    • PASS [expected FAIL] subtest: ToASCII("ß。𐋳Ⴌྸ")
    • PASS [expected FAIL] subtest: ToASCII("ß。𐋳Ⴌྸ")
    • And 58 more unexpected results...
  • OK /url/toascii.window.html
    • PASS [expected FAIL] subtest: look᠎out.net (using URL)
    • PASS [expected FAIL] subtest: look᠎out.net (using URL.host)
    • PASS [expected FAIL] subtest: look᠎out.net (using URL.hostname)
    • PASS [expected FAIL] subtest: look᠎out.net (using &lt;a&gt;)
    • PASS [expected FAIL] subtest: look᠎out.net (using &lt;a&gt;.host)
    • PASS [expected FAIL] subtest: look᠎out.net (using &lt;a&gt;.hostname)
    • PASS [expected FAIL] subtest: look᠎out.net (using &lt;area&gt;)
    • PASS [expected FAIL] subtest: look᠎out.net (using &lt;area&gt;.host)
    • PASS [expected FAIL] subtest: look᠎out.net (using &lt;area&gt;.hostname)
    • PASS [expected FAIL] subtest: lookout.net (using URL)
    • And 26 more unexpected results...
  • OK /url/url-setters-a-area.window.html?exclude=(file|javascript|mailto)
    • FAIL [expected PASS] subtest: &lt;a&gt;: Setting &lt;non-spec:/&gt;.pathname = '/.//p' Serialize /. in path

      assert_equals: expected "non-spec:/.//p" but got "non-spec://p"
      

    • FAIL [expected PASS] subtest: &lt;area&gt;: Setting &lt;non-spec:/&gt;.pathname = '/.//p' Serialize /. in path

      assert_equals: expected "non-spec:/.//p" but got "non-spec://p"
      

    • FAIL [expected PASS] subtest: &lt;a&gt;: Setting &lt;non-spec:/&gt;.pathname = '/..//p'

      assert_equals: expected "non-spec:/.//p" but got "non-spec://p"
      

    • FAIL [expected PASS] subtest: &lt;area&gt;: Setting &lt;non-spec:/&gt;.pathname = '/..//p'

      assert_equals: expected "non-spec:/.//p" but got "non-spec://p"
      

    • FAIL [expected PASS] subtest: &lt;a&gt;: Setting &lt;non-spec:/&gt;.pathname = '//p'

      assert_equals: expected "non-spec:/.//p" but got "non-spec://p"
      

    • FAIL [expected PASS] subtest: &lt;area&gt;: Setting &lt;non-spec:/&gt;.pathname = '//p'

      assert_equals: expected "non-spec:/.//p" but got "non-spec://p"
      

  • OK /url/url-setters.any.html?exclude=(file|javascript|mailto)
    • FAIL [expected PASS] subtest: URL: Setting &lt;non-spec:/&gt;.pathname = '/.//p' Serialize /. in path

      assert_equals: expected "non-spec:/.//p" but got "non-spec://p"
      

    • FAIL [expected PASS] subtest: URL: Setting &lt;non-spec:/&gt;.pathname = '/..//p'

      assert_equals: expected "non-spec:/.//p" but got "non-spec://p"
      

    • FAIL [expected PASS] subtest: URL: Setting &lt;non-spec:/&gt;.pathname = '//p'

      assert_equals: expected "non-spec:/.//p" but got "non-spec://p"
      

    • FAIL [expected PASS] subtest: URL: Setting &lt;non-spec:/.//&gt;.pathname = 'p' Drop /. from path

      assert_equals: expected "non-spec:/p" but got "non-spec:/./p"
      

  • OK /url/url-setters.any.worker.html?exclude=(file|javascript|mailto)
    • FAIL [expected PASS] subtest: URL: Setting &lt;non-spec:/&gt;.pathname = '/.//p' Serialize /. in path

      assert_equals: expected "non-spec:/.//p" but got "non-spec://p"
      

    • FAIL [expected PASS] subtest: URL: Setting &lt;non-spec:/&gt;.pathname = '/..//p'

      assert_equals: expected "non-spec:/.//p" but got "non-spec://p"
      

    • FAIL [expected PASS] subtest: URL: Setting &lt;non-spec:/&gt;.pathname = '//p'

      assert_equals: expected "non-spec:/.//p" but got "non-spec://p"
      

    • FAIL [expected PASS] subtest: URL: Setting &lt;non-spec:/.//&gt;.pathname = 'p' Drop /. from path

      assert_equals: expected "non-spec:/p" but got "non-spec:/./p"
      

@github-actions
Copy link
Copy Markdown

⚠️ Try run (#16185265029) failed.

@stevennovaryo stevennovaryo force-pushed the input-type-text-reland branch from 5fd2d6e to 8fb0489 Compare July 10, 2025 06:18
@stevennovaryo stevennovaryo added the T-linux-wpt Do a try run of the WPT label Jul 10, 2025
@github-actions github-actions bot removed the T-linux-wpt Do a try run of the WPT label Jul 10, 2025
@github-actions
Copy link
Copy Markdown

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

@github-actions
Copy link
Copy Markdown

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

Flaky unexpected result (22)
  • OK /_webgl/conformance/textures/misc/texture-upload-size.html (#21770)
    • FAIL [expected PASS] subtest: WebGL test #77

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

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

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

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

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

      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
      

  • OK /css/css-cascade/layer-cssom-order-reverse.html (#36094)
    • PASS [expected FAIL] subtest: Delete layer invalidates @font-face
  • ERROR [expected TIMEOUT] /fetch/fetch-later/quota/same-origin-iframe/max-payload.tentative.https.window.html (#35210)
  • OK /fetch/metadata/generated/css-font-face.https.sub.tentative.html (#32732)
    • PASS [expected FAIL] subtest: sec-fetch-dest
    • PASS [expected FAIL] subtest: sec-fetch-user
  • OK /html/browsers/browsing-the-web/navigating-across-documents/009.html (#24456)
    • FAIL [expected PASS] subtest: Link with onclick form submit to javascript url with document.write and href navigation

      assert_array_equals: expected property 1 to be "href" but got "click" (expected array ["write", "href"] got ["write", "click"])
      

  • 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-same-origin.window.html (#29049)
    • PASS [expected FAIL] subtest: Same-origin navigation started from unload handler must be ignored
  • OK /html/browsers/browsing-the-web/navigating-across-documents/refresh/same-document-refresh.html (#34597)
    • FAIL [expected PASS] subtest: Same-Document Referrer from Refresh

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

  • TIMEOUT [expected OK] /html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/form-requestsubmit.html (#28716)
    • TIMEOUT [expected FAIL] subtest: Replace before load, triggered by formElement.requestSubmit()

      Test timed out
      

  • 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 /html/browsers/history/the-history-interface/traverse_the_history_5.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])
      

  • TIMEOUT [expected OK] /html/browsers/sandboxing/sandbox-initial-empty-document-toward-same-origin.html (#35948)
  • OK /html/browsers/windows/browsing-context-names/duplicate-name-order.html (#34623)
    • PASS [expected FAIL] subtest: Duplicate name lookup order
  • FAIL [expected PASS] /html/canvas/element/manual/drawing-text-to-the-canvas/canvas.2d.disconnected-font-size-math.html (#30063)
  • TIMEOUT [expected OK] /html/infrastructure/urls/base-url/document-base-url-window-initiator-is-not-opener.https.window.html (#30970)
  • TIMEOUT [expected OK] /html/interaction/focus/the-autofocus-attribute/update-the-rendering.html (#24145)
    • TIMEOUT [expected FAIL] subtest: "Flush autofocus candidates" should be happen before a scroll event and animation frame callbacks

      Test timed out
      

  • 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 /resize-observer/change-layout-in-error.html (#32629)
    • PASS [expected FAIL] subtest: Changing layout in window error handler should not result in lifecyle loop when resize observer loop limit is reached.
  • OK /resize-observer/eventloop.html (#33599)
    • FAIL [expected PASS] subtest: test0: multiple notifications inside same event loop

      assert_equals: new loop expected 1 but got 0
      

  • OK [expected TIMEOUT] /resource-timing/tentative/document-initiated.html (#37785)
  • 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 OK] /webmessaging/with-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 (17)
  • 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.
  • FAIL [expected PASS] /css/css-grid/grid-items/grid-auto-margin-and-replaced-item-001.html (#37162)
  • OK /css/cssom-view/scroll-behavior-smooth-navigation.html (#29564)
    • PASS [expected FAIL] subtest: Smooth scrolling while doing history navigation.
  • PASS [expected FAIL] /html/canvas/element/manual/text/canvas.2d.disconnected.html (#30063)
  • TIMEOUT /html/interaction/focus/the-autofocus-attribute/supported-elements.html (#24145)
    • PASS [expected NOTRUN] subtest: Non-HTMLElement should not support autofocus
    • FAIL [expected NOTRUN] subtest: Host element with delegatesFocus should support autofocus

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

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

      Test timed out
      

  • OK /html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-nav-location-assign.html (#32863)
    • PASS [expected FAIL] subtest: Navigating iframe loading='lazy' before it is loaded: location.assign
  • OK /html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-nav-location-replace-set-src.html (#32697)
    • PASS [expected FAIL] subtest: Navigating iframe loading='lazy' and then setting src: location.replace
  • OK [expected TIMEOUT] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-2.html (#22667)
  • OK [expected TIMEOUT] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-3.html (#24057)
  • CRASH [expected TIMEOUT] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-2.html (#22154)
  • OK [expected TIMEOUT] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-3.html (#24066)
  • OK /preload/preload-error.sub.html (#37177)
    • PASS [expected FAIL] subtest: 404 (style): main
    • PASS [expected FAIL] subtest: CORS (script): main
    • PASS [expected FAIL] subtest: success (xhr): main
    • PASS [expected FAIL] subtest: 404 (xhr): main
    • FAIL [expected PASS] subtest: Decode-error (style): main

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

    • PASS [expected FAIL] subtest: Decode-error (script): main
  • CRASH [expected TIMEOUT] /trusted-types/trusted-types-navigation.html?06-10 (#37920)
  • OK [expected TIMEOUT] /webmessaging/with-ports/017.html (#24486)
    • PASS [expected TIMEOUT] subtest: origin of the script that invoked the method, about:blank

@github-actions
Copy link
Copy Markdown

✨ Try run (#16187653685) succeeded.

Comment on lines +1 to +2
[input_placeholder.html]
expected: FAIL
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.

Why is this test now failing?

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.

We are now using grey color for the placeholder text, while that test assumes placeholder and value share the appearence. #37065 (comment)

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.

We should modify the test case instead.

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.

Per offline discussion with @xiaochengh. The test looks quite flawed, in terms that it was assuming placeholder text should have a same style as the editable text. So we are removing the test. The new input could relies on the new appearance test.

Comment on lines +1229 to +1236

// The addition of zero-width space here forces the text input to have an inline formatting
// context that might otherwise be trimmed if there's no text. This is important to ensure
// that the input element is at least as tall as the line gap of the caret:
// <https://drafts.csswg.org/css-ui/#element-with-default-preferred-size>.
//
// This is also used to ensure that the caret will still be rendered when the input is empty.
// TODO: Is there a less hacky way to do this?
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.

Why is this copied from layout? Can we remove the corresponding code there as well? I It's possible that with shadow DOM and styling support this hack can be removed

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.

Instead of hacking the text value, can we append a <br> to the inner editor element?

I just tested the latest Servo and confirmed that <div><br></div> doesn't collapse.

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.

Why is this copied from layout?

Practically, we are moving this from layout to script. Though the documentation in layout should be changed.

Can we remove the corresponding code there as well?

We are not able to, because the other types of input are still using that hack. Added a documentation for this.

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.

I It's possible that with shadow DOM and styling support this hack can be removed

It might be possible with using something like <br> or modifying the styles. We could file a issue for this, but I am not sure it should be filed before the PR getting merged or after.

Instead of hacking the text value, can we append a <br> to the inner editor element?

I am not sure that It would not disturb with the DOM modification presented by the PRs. Since we are using the CharacterData right now and modifying the inner data of it to improve the text editing performance, while <br> is another type of element.

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.

Per offline discussion, using appending extra <br> to input, alongside the CharacterData for editable text seems very reasonable, but this would prevent the caret from being rendered. This behavior seems unintended, so we should fix the caret rendering first before removing this hack.

}

/// Whether this is a container for the editable text within a single-line text input.
/// This is used to solve the special case of line height for a text editor.
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.

Nit: "editor" isn't quite the right word here as a "text editor" is a program for editing text. What is it exactly that you are trying to describe? Is it the text inside the text entry surrounded by the border, etc? I would call it the "text entry text" or something along those lines maybe so "is_single_line_text_entry_text_element" or something like that.

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.

We probably copied this name from Blink, using "inner editor" to refer to the container element of the value text inside the shadow DOM. The element is implemented as a contenteditable in Blink.

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.

Added more context for the TODOs. Ideally this would refer only to the text container within input element. But because we are supporting the older version of input element (one without UA widget) as well, then we are still considering the HTMLInputElement here.

Comment on lines +1 to +14
<!DOCTYPE html>
<html>
<head>
<title>Appearance of an Input type=text With a Definite Width</title>
<link rel="stylesheet" href="./supports/input-text-ref.css">
</head>
<body>
Display of an input type=text should match the display generated by the CSS reference.
<div>
<div id="input" class="definite-width">
Foo
</div>
</div>
</body>
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 have to think about these tests a bit, as I think they are just verifying that the style of the fields doesn't change from what you have originally chosen for them. It may be enough just to have a manual text with all of the form controls. More important are things such as ensuring the placeholder works properly. That said, I think they probably don't hurt.

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.

The purpose of these tests is to make sure that the appearance is correct without comparing it to another input element. Non Servo-specific WPTs are unable to do these test since each browser have their own input styles and appearance.

Ideally we could do comparison to an image like how Chromium handles this, but keeping input elements up to the standard would be more important.

@stevennovaryo stevennovaryo force-pushed the input-type-text-reland branch from 58731a8 to 1cd0cfc Compare July 16, 2025 09:56
@stevennovaryo stevennovaryo requested a review from mrobinson July 16, 2025 10:07
@stevennovaryo stevennovaryo force-pushed the input-type-text-reland branch from 1cd0cfc to b0d7a75 Compare July 16, 2025 10:20
@xiaochengh xiaochengh dismissed mrobinson’s stale review July 22, 2025 09:23

Review comments are already addressed without further feedback

Signed-off-by: stevennovaryo <[email protected]>
Signed-off-by: stevennovaryo <[email protected]>
Signed-off-by: stevennovaryo <[email protected]>
@stevennovaryo stevennovaryo force-pushed the input-type-text-reland branch from b0d7a75 to b2c5310 Compare July 23, 2025 02:32
@mrobinson
Copy link
Copy Markdown
Member

Out of curiosity, what kind of results do you see before and after when running Speedometer 2.1?

@stevennovaryo
Copy link
Copy Markdown
Contributor Author

Out of curiosity, what kind of results do you see before and after when running Speedometer 2.1?

From one of the test:

  • Without Shadow DOM: 50
  • With Shadow DOM: 45
  • Initial reverted implementation: 39* (for comparison)

It was from a test more than one month ago. cc: @webbeef

My tests before getting this PR merged also produces similar results (i.e., reduce the performance regression by ~66%)

@xiaochengh xiaochengh added this pull request to the merge queue Jul 23, 2025
Merged via the queue into servo:main with commit 3cb16eb Jul 23, 2025
22 checks passed
github-merge-queue bot pushed a commit that referenced this pull request Jul 25, 2025
Depend on: 
- #37427
- #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]>
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]>
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.

Misalignment of Input type="text" Content

3 participants