Skip to content

script: Support sprintf-style substitutions in console methods#43897

Merged
simonwuelker merged 3 commits into
servo:mainfrom
TG199:console-sprintf-substitutions
Apr 7, 2026
Merged

script: Support sprintf-style substitutions in console methods#43897
simonwuelker merged 3 commits into
servo:mainfrom
TG199:console-sprintf-substitutions

Conversation

@TG199

@TG199 TG199 commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

Implement the Console Formatter operation for all console methods.
Fixes: #43827

Signed-off-by: Kelechi Ebiri <ebiritg@gmail.com>
@TG199 TG199 requested a review from gterzian as a code owner April 3, 2026 10:17
@servo-highfive servo-highfive added the S-awaiting-review There is new code that needs to be reviewed. label Apr 3, 2026
@simonwuelker simonwuelker added the T-linux-wpt Do a try run of the WPT label Apr 3, 2026
@github-actions github-actions Bot removed the T-linux-wpt Do a try run of the WPT label Apr 3, 2026
@github-actions

github-actions Bot commented Apr 3, 2026

Copy link
Copy Markdown

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

@github-actions

github-actions Bot commented Apr 3, 2026

Copy link
Copy Markdown

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

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

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

    • FAIL [expected PASS] subtest: offsetLeft

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

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

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

  • OK /css/css-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
  • TIMEOUT [expected OK] /fetch/api/redirect/redirect-keepalive.https.any.html (#32153)
    • TIMEOUT [expected PASS] subtest: [keepalive][iframe][load] mixed content redirect; setting up

      Test timed out
      

  • OK /fetch/metadata/generated/css-font-face.sub.tentative.html (#34624)
    • PASS [expected FAIL] subtest: sec-fetch-storage-access - Not sent to non-trustworthy same-site destination
  • ERROR /fetch/metadata/generated/serviceworker.https.sub.html (#36247)
    • PASS [expected FAIL] subtest: sec-fetch-site - Same origin, no options - registration
  • ERROR [expected OK] /focus/focus-event-after-switching-iframes.sub.html (#40368)
  • CRASH [expected OK] /html/browsers/history/the-location-interface/location-non-configurable-toString-valueOf.html
  • CRASH [expected OK] /html/browsers/windows/nested-browsing-contexts/frameElement-siblings.sub.html
  • 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 /mixed-content/tentative/autoupgrades/mixed-content-cors.https.sub.html (#41123)
    • PASS [expected FAIL] subtest: Cross-Origin video should get upgraded even if CORS is set
  • PASS [expected FAIL] /png/apng/fcTL-dispose-none.html (#41817)
  • FAIL [expected PASS] /png/apng/fcTL-dispose-previous.html (#41561)
  • OK /pointerevents/compat/pointerevent_touch_target_after_pointerdown_target_removed.tentative.html (#42813)
    • PASS [expected FAIL] subtest: After a touchstart listener removes its target, touch events should be fired on the touchstart target even though an orphan and pointer events should be fired on the parent
    • PASS [expected FAIL] subtest: After a touchstart listener removes its target, touchmove event should be fired on the pointerdown target
  • TIMEOUT [expected OK] /preload/modulepreload-sri-importmap.html (#43354)
    • TIMEOUT [expected PASS] subtest: Script should not be loaded if modulepreload's integrity is invalid

      Test timed out
      

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

      Test timed out
      

  • OK [expected CRASH] /resource-timing/render-blocking-status-link.html (#41664)
  • CRASH [expected OK] /resource-timing/sizes-redirect-img.html
  • OK /resource-timing/test_resource_timing.https.html (#25216)
    • PASS [expected FAIL] subtest: PerformanceEntry has correct name, initiatorType, startTime, and duration (iframe)
  • 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()
  • OK /touch-events/single-tap-when-touchend-listener-use-sync-xhr.html (#41175)
    • FAIL [expected PASS] subtest: Click event should be fired when touchend opens synchronous XHR

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

  • TIMEOUT /trusted-types/trusted-types-navigation.html?06-10 (#37920)
    • PASS [expected FAIL] subtest: Navigate a frame via anchor with javascript:-urls in report-only mode.
  • OK /trusted-types/trusted-types-reporting.html (#43737)
    • PASS [expected FAIL] subtest: Trusted Type violation report: sample for SVGScriptElement href assignment by setAttribute
    • PASS [expected FAIL] subtest: Trusted Type violation report: sample for eval
    • PASS [expected FAIL] subtest: Trusted Type violation report: sample for custom element assignment
    • PASS [expected FAIL] subtest: Trusted Type violation report: Worker constructor
  • OK /webdriver/tests/classic/accept_alert/accept.py (#43194)
    • FAIL [expected PASS] subtest: test_accept_in_popup_window

      AssertionError: no such alert (404): No user prompt is currently active.
      

  • OK /webdriver/tests/classic/dismiss_alert/dismiss.py (#39098)
    • FAIL [expected PASS] subtest: test_dismiss_in_popup_window

      AssertionError: no such alert (404): No user prompt is currently active.
      

Stable unexpected results that are known to be intermittent (17)
  • 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 OK] /content-security-policy/meta/sandbox-iframe.html (#43478)
  • OK /css/css-fonts/generic-family-keywords-001.html (#37467)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted generic(fangsong)
  • OK /css/css-fonts/generic-family-keywords-003.html (#38994)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted math (drawing text in a canvas)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted generic(fangsong) (drawing text in a canvas)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted ui-serif (drawing text in a canvas)
  • OK /dom/nodes/moveBefore/iframe-document-preserve.window.html (#43152)
    • PASS [expected FAIL] subtest: moveBefore(): cross-origin iframe is preserved: remove self
  • ERROR [expected OK] /fetch/fetch-later/quota/same-origin-iframe/accumulated-oversized-payload.https.window.html (#41705)
  • OK /html/browsers/browsing-the-web/navigating-across-documents/005.html (#27062)
    • FAIL [expected PASS] subtest: Link with onclick navigation and href navigation

      assert_equals: expected "href" but got "click"
      

  • OK /html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-same-origin-fragment.html (#20768)
    • PASS [expected FAIL] subtest: Tests that a fragment navigation in the unload handler will not block the initial navigation
  • OK /html/browsers/history/the-history-interface/traverse_the_history_4.html (#21383)
    • PASS [expected FAIL] subtest: Multiple history traversals, last would be aborted
  • OK /html/browsers/history/the-history-interface/traverse_the_history_5.html (#21383)
    • PASS [expected FAIL] subtest: Multiple history traversals, last would be aborted
  • CRASH [expected TIMEOUT] /html/browsers/history/the-location-interface/location_replace_session_history.html (#41896)
  • TIMEOUT /html/interaction/focus/the-autofocus-attribute/supported-elements.html (#24145)
    • PASS [expected TIMEOUT] subtest: Non-HTMLElement should not support autofocus
    • TIMEOUT [expected NOTRUN] subtest: Host element with delegatesFocus should support autofocus

      Test timed out
      

  • OK /navigation-timing/test-navigation-type-reload.html (#33334)
    • PASS [expected FAIL] subtest: Reload domComplete &gt; Original domComplete
    • PASS [expected FAIL] subtest: Reload domInteractive &gt; Original domInteractive
    • PASS [expected FAIL] subtest: Reload fetchStart &gt; Original fetchStart
    • PASS [expected FAIL] subtest: Reload loadEventEnd &gt; Original loadEventEnd
    • PASS [expected FAIL] subtest: Reload loadEventStart &gt; Original loadEventStart
  • OK /resource-timing/test_resource_timing.html (#25720)
    • PASS [expected FAIL] subtest: PerformanceEntry has correct name, initiatorType, startTime, and duration (link)
  • TIMEOUT /trusted-types/trusted-types-navigation.html?26-30 (#38807)
    • PASS [expected TIMEOUT] subtest: Navigate a window via form-submission with javascript:-urls in report-only mode.
    • PASS [expected NOTRUN] subtest: Navigate a window via form-submission with javascript:-urls w/ default policy in report-only mode.
    • PASS [expected NOTRUN] subtest: Navigate a frame via form-submission with javascript:-urls in enforcing mode.
    • TIMEOUT [expected NOTRUN] subtest: Navigate a frame via form-submission with javascript:-urls w/ default policy in enforcing mode.

      Test timed out
      

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

@github-actions

github-actions Bot commented Apr 3, 2026

Copy link
Copy Markdown

✨ Try run (#23944429964) succeeded.

Comment thread components/script/dom/console.rs
Some('c') => {
chars.next();
if arg_index < messages.len() {
arg_index += 1; // consume but ignore CSS styling

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.

"css styling"? Why can we ignore the argument in this case?

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.

"css styling"? Why can we ignore the argument in this case?

In https://console.spec.whatwg.org/#formatter, the behaviour is not yet specified but the argument is used for styling console output in other browers and I don't think Servo supports styled console output at the moment.

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.

Thanks, I had naively assumed that %c would format a char like it does in C (:

@simonwuelker simonwuelker left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, can you write a test?

You can test console functionality with the devtools tests in devtools_tests.py, there are already some other console tests that you can use as a reference.

Some('d') | Some('i') => {
let spec = chars.next().unwrap();
if arg_index < messages.len() {
let num = unsafe { ToNumber(*cx, messages[arg_index]) };

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.

Does this throw if the value is a BigInt/Symbol like https://tc39.es/ecma262/#sec-tonumber? If so we need some if checks to avoid that.

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.

okay, on it

@TG199

TG199 commented Apr 5, 2026

Copy link
Copy Markdown
Contributor Author

LGTM, can you write a test?

You can test console functionality with the devtools tests in devtools_tests.py, there are already some other console tests that you can use as a reference.

I see, I'll give it a try

TG199 added 2 commits April 5, 2026 20:46
…ormatter

Signed-off-by: Kelechi Ebiri <ebiritg@gmail.com>
Signed-off-by: Kelechi Ebiri <ebiritg@gmail.com>
Comment on lines +520 to +522
if num.is_err() {
unsafe { jsapi::JS_ClearPendingException(*cx) };
}

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.

Rather than clearing the exception I'd prefer if we didn't call ToNumber at all in those error cases.

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.

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.

okay

@TG199

TG199 commented Apr 7, 2026

Copy link
Copy Markdown
Contributor Author

@simonwuelker is this good enough to land?

@simonwuelker simonwuelker left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks!

@servo-highfive servo-highfive removed the S-awaiting-review There is new code that needs to be reviewed. label Apr 7, 2026
@simonwuelker simonwuelker added this pull request to the merge queue Apr 7, 2026
@servo-highfive servo-highfive added the S-awaiting-merge The PR is in the process of compiling and running tests on the automated CI. label Apr 7, 2026
Merged via the queue into servo:main with commit a7e4b80 Apr 7, 2026
30 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 Apr 7, 2026
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.

console.debug() does not support sprintf-style substitutions

3 participants