Visitar URL original
fix(console): describe Map, Set, function, DOM node, symbol and cyclic arguments by nancy6547 · Pull Request #3199 · ChromeDevTools/chrome-devtools-mcp · GitHub
Skip to content

fix(console): describe Map, Set, function, DOM node, symbol and cyclic arguments - #3199

Merged
OrKoN merged 4 commits into
ChromeDevTools:mainfrom
nancy6547:fix/console-arg-previews
Oct 19, 2026
Merged

OrKoN merged 4 commits into
ChromeDevTools:mainfrom
nancy6547:fix/console-arg-previews

Conversation

@nancy6547

@nancy6547 nancy6547 commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

list_console_messages / get_console_message print console arguments through jsonValue(). On main a Map, Set or DOM node prints as {}, and a cyclic object shows <error: Argument N is no longer available>. This formats those arguments from the description and preview that CDP already sends with them, so nothing extra is evaluated in the page. Plain objects, arrays and primitives still use jsonValue().

User-visible behavior change (Date). Dates now print the CDP description instead of the jsonValue() ISO string. Main prints 1970-01-01T00:00:00.000Z, this PR prints Thu Jan 01 1970 00:00:00 GMT+0000 (Coordinated Universal Time), the same text the DevTools console shows. Main's ISO output was already valid; this is a change in format, not a fix.

Port origin. src/formatters/RemoteObjectFormatter.ts is a plain-text port of devtools-frontend's front_end/ui/legacy/components/object_ui/RemoteObjectPreviewFormatter.ts at revision f7e7785de52d6f5955d6a9c5956c2fe2d520d091 (the third_party/devtools-frontend revision this branch uses). Intentional differences:

  • Plain text instead of Lit templates: no CSS classes, tooltips or localized strings.
  • No nodeDescription markup: DOM nodes print their description as is (no renderNodeTitle spans); trusted types print their description instead of ClassName "value".
  • date and node print their description instead of a property preview.
  • The includeNullOrUndefined option is dropped.
  • Top-level strings print raw; unserializable primitives (NaN, -0, 1n) print from unserializableValue.
  • Upstream's inline 400-character limit is named MAX_DESCRIPTION_LENGTH (same value).

Quoting. Values formatted from a preview show nested strings as JS literals ('x'), while plain objects still go through jsonValue() and print as JSON ({"a":1}), so one message can mix both quoting styles.

Tests (no browser):

  • tests/formatters/RemoteObjectFormatter.test.ts: Map/Set entries, cyclic objects, arrays with holes and overflow, typed arrays, promise state, and description-only values (Date, DOM node, function, symbol, bigint).
  • tests/formatters/ConsoleFormatter.test.ts: Map and cyclic arguments are formatted from their preview while a plain object keeps jsonValue(); an argument whose jsonValue() rejects and has no preview is reported as <error: Argument 0 is no longer available>.

@OrKoN
OrKoN self-requested a review October 17, 2026 05:09
Comment thread src/formatters/ConsoleFormatter.ts Resolved
Instead of evaluating a describer in the page, format Map, Set, function,
DOM node, symbol, bigint and cyclic arguments from the description and
preview that CDP already sends with each console argument. The rules are a
plain-text port of devtools-frontend's RemoteObjectPreviewFormatter, which
only renders Lit templates, so the output matches the DevTools console
(for example `Map(1) {1 => 2}`, `(3) [1, empty, 3]`,
`Promise {<fulfilled>: 5}`). Since nothing runs in the page, these
arguments are also formatted after the page has navigated away.
@OrKoN
OrKoN self-requested a review October 17, 2026 06:21

@OrKoN OrKoN left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please check the following:

  1. In src/formatters/ConsoleFormatter.ts, replace the type RemoteObject = ReturnType<Awaited<ReturnType<ConsoleMessage['args']>>[number]['remoteObject']> alias with Protocol.Runtime.RemoteObject. The derived type is the same type and the alias is hard to read.

  2. In src/formatters/RemoteObjectFormatter.ts, import {DevTools} from ../third_party/index.js and use DevTools.Platform.StringUtilities, as src/telemetry/flagUtils.ts does, instead of import * as DevTools plus DevTools.DevTools.Platform. The doubled namespace is confusing.

  3. Add a note in the PR description (and in the file header comment of src/formatters/RemoteObjectFormatter.ts) that the port follows devtools-frontend's RemoteObjectPreviewFormatter at a specific revision, and list the intentional differences (plain text, no nodeDescription, MAX_DESCRIPTION_LENGTH = 400). A 259-line port of UI logic needs an anchor for future syncs.

Nit (non-blocking): previews render strings as JS literals ('x') while plain objects still go through jsonValue() and print JSON ({"a":1}). Mixed quoting in one message is acceptable, but worth a sentence in the PR description.

… origin

Use Protocol.Runtime.RemoteObject instead of a type derived from
ConsoleMessage, import DevTools the way flagUtils.ts does, and note the
devtools-frontend revision the RemoteObjectPreviewFormatter port follows
together with its intentional differences.
@nancy6547

Copy link
Copy Markdown
Contributor Author

Thanks for the review! Pushed: Protocol.Runtime.RemoteObject instead of the derived alias, import {DevTools} + DevTools.Platform.StringUtilities as in flagUtils.ts, and a header in RemoteObjectFormatter.ts that pins the port to devtools-frontend f7e7785 and lists the intentional differences. I added the same notes and the quoting nit to the PR description. One detail: upstream also uses 400 (inline in trimEndWithMaxLength), so only the constant's name is new.

@OrKoN
OrKoN self-requested a review October 19, 2026 09:23

@OrKoN OrKoN left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Plese check the following:

  1. remove the export from formatObjectPreview in src/formatters/RemoteObjectFormatter.ts. It has no caller outside the module, and AGENTS.md does not allow public functions that exist only for tests.

  2. In the PR description, list the Date change as a user-visible behavior change: main prints "1970-01-01T00:00:00.000Z" from jsonValue(), the PR prints the CDP description Thu Jan 01 1970 00:00:00 GMT+0000 (...). The title and description claim Date was printed badly, but main already printed a valid ISO string.

  3. In tests/formatters/ConsoleFormatter.test.ts, add a test where jsonValue() rejects and remoteObject() has no preview, and assert the result is <error: Argument 0 is no longer available>. The new catch has two branches (preview present or absent) and the PR tests only one.

  4. In tests/formatters/RemoteObjectFormatter.test.ts, change the preview() helper to take one options object for overflow and entries. The Map and Set tests pass a positional false placeholder to reach entries, which AGENTS.md disallo

…view helper

Make formatObjectPreview module-private, pass overflow and entries to the
test preview() helper as one options object, and test that an argument
without a preview whose jsonValue() rejects is reported as no longer
available.
@nancy6547 nancy6547 changed the title fix(console): describe Map, Set, Date, function, DOM node, symbol and cyclic arguments fix(console): describe Map, Set, function, DOM node, symbol and cyclic arguments Oct 19, 2026
@nancy6547

Copy link
Copy Markdown
Contributor Author

Thanks! Pushed 474cedd: formatObjectPreview is no longer exported, the preview() test helper takes an options object ({overflow, entries}), and there is a new ConsoleFormatter test for the no-preview branch where jsonValue() rejects. I updated the title and description: Date is now listed as a user-visible format change (ISO string on main → CDP description), not as a fix.

@OrKoN
OrKoN added this pull request to the merge queue Oct 19, 2026
Merged via the queue into ChromeDevTools:main with commit 968e4e5 Oct 19, 2026
16 checks passed
github-merge-queue Bot pushed a commit that referenced this pull request Oct 22, 2026
🤖 I have created a release *beep* *boop*
---


##
[1.12.0](chrome-devtools-mcp-v1.11.0...chrome-devtools-mcp-v1.12.0)
(2026-10-22)


### 🎉 Features

* add --maxNavigationSaved flag to configure retained navigation history
([#3018](#3018))
([a580d13](a580d13))
* add Kimi Code plugin manifest
([#3029](#3029))
([cd00b64](cd00b64))
* Analyze heap snapshots without a browser connection
([#3156](#3156))
([78c8320](78c8320))
* **config:** add --watchConfig to reload config file changes
([#3248](#3248))
([b48561f](b48561f))
* **config:** introduce layered ServerConfig for live reload
([#3203](#3203))
([37f1fda](37f1fda))
* **config:** share ReadonlyServerConfig with McpContext and McpPage
([#3204](#3204))
([0813bf3](0813bf3))
* **config:** support reloading blockedUrlPattern and allowedUrlPattern
([#3268](#3268))
([cc850f5](cc850f5))
* **context:** release disabled feature state on config reload
([#3049](#3049))
([c0140d1](c0140d1))
* Paginate by default in heap snapshot tools
([#3201](#3201))
([fb8375b](fb8375b))
* Paginate detailed diff in compare_heapsnapshots
([#3195](#3195))
([4a9dd53](4a9dd53))
* run independent tool calls in parallel with a TaskRunner
([#3243](#3243))
([8a8d877](8a8d877))
* run page-scoped tools on different pages in parallel
([#3252](#3252))
([f8f18ac](f8f18ac))
* **server:** add McpServer.applyConfig() to reload configuration
([#3051](#3051))
([f874aeb](f874aeb))
* **slim:** support filepath in slim mode screenshot
([#3296](#3296))
([d399c4a](d399c4a))
* Sort objects for class by self size in compare_heapsnapshots
([#3205](#3205))
([f8a18c6](f8a18c6))
* **tools:** support updating ToolHandler definitions in place
([#3050](#3050))
([8064138](8064138))
* **wait_for:** support opt-in visible text matching
([#3212](#3212))
([eef92da](eef92da))


### 🛠️ Fixes

* allow paths below a filesystem-root workspace root
([#3277](#3277))
([296ccef](296ccef))
* block evaluate_script while a dialog is open
([#3196](#3196))
([545bcbb](545bcbb))
* bound take_snapshot wait and clear the geolocation override
([#3265](#3265))
([6282f54](6282f54))
* **browser:** redact WebSocket headers from connection logs
([#2901](#2901))
([3a2f91e](3a2f91e))
* capture thrown transform errors as Zod validation issues
([#3242](#3242))
([0f95c21](0f95c21))
* clear handled dialog in McpPage.getDialog()
([#3241](#3241))
([2ab93a3](2ab93a3)),
closes
[#2958](#2958)
* **cli:** disallow --slim in CLI start options
([#2987](#2987))
([#3113](#3113))
([ae3f61c](ae3f61c))
* **cli:** do not forward tool args to start
([#3114](#3114))
([fef1598](fef1598))
* **cli:** serialize object daemon arguments
([#2797](#2797))
([f73a440](f73a440))
* close the tab opened by a failed new_page
([#2928](#2928))
([c174677](c174677))
* **config:** accept native JSON objects for wsHeaders in config files
([#3262](#3262))
([371e6c2](371e6c2))
* **console:** describe Map, Set, function, DOM node, symbol and cyclic
arguments
([#3199](#3199))
([968e4e5](968e4e5))
* **console:** include the reason of unhandled promise rejections
([#3148](#3148))
([f7cdf73](f7cdf73))
* defer focus emulation until a page is explicitly targeted
([#3230](#3230))
([35abe35](35abe35))
* disable Puppeteer signal handlers for launched browsers
([#3238](#3238))
([3afec73](3afec73)),
closes
[#3154](#3154)
* discover third-party developer tools before tool lookup
([#3208](#3208))
([2777fa0](2777fa0)),
closes
[#2973](#2973)
* discover third-party developer tools in page tools
([#3207](#3207))
([cf33529](cf33529)),
closes
[#2980](#2980)
* drop InlineTextBox nodes from text snapshots
([#3202](#3202))
([f8c775a](f8c775a))
* **emulate:** keep previous viewport when setViewport fails
([#3150](#3150))
([19d883c](19d883c))
* exclude source maps from the npm package
([#3295](#3295))
([d575da4](d575da4))
* keep surrogate pairs and emoji whole when truncating titles, names and
bodies
([#3215](#3215))
([058adcf](058adcf))
* let resourceTypes match CORS preflights and prefetches
([#3217](#3217))
([e342c6e](e342c6e))
* **lighthouse:** explain unsupported URL schemes in navigation mode
([#3144](#3144))
([c6ad84a](c6ad84a))
* **lighthouse:** fail the audit when Lighthouse reports a runtime error
([#3188](#3188))
([53ea78d](53ea78d))
* **lighthouse:** restore the emulated viewport after a navigation audit
([#3189](#3189))
([c777ece](c777ece))
* **network:** list only earlier hops in a request's redirect chain
([#3198](#3198))
([4675940](4675940))
* **network:** remove unsupported websocket from list_network_requests
filter
([#2961](#2961))
([#3282](#3282))
([8b119d9](8b119d9))
* **network:** reset page network emulation before applying URL
restrictions
([#3312](#3312))
([f25f3df](f25f3df))
* **pages:** reject devtools:// URLs in navigate_page and new_page
([#2935](#2935))
([#3128](#3128))
([c94c03d](c94c03d))
* **pages:** report the actual page size after resize_page
([#2998](#2998))
([#3132](#3132))
([f003056](f003056))
* **pages:** revert reporting the page size after resize_page
([#3308](#3308))
([186ea66](186ea66)),
closes
[#3306](#3306)
* **pagination:** return all items when pageSize is omitted and pageIdx
is 0
([#2996](#2996))
([#3134](#3134))
([3ad9115](3ad9115))
* **performance:** populate structuredContent for traceInsight in
performance_analyze_insight
([#2981](#2981))
([#3115](#3115))
([c2c6cc4](c2c6cc4))
* preserve unread page fallback across snapshots and deduplicate page
disposal
([#3161](#3161))
([8604365](8604365))
* print the no-roots temp-directory warning under default flags
([#2927](#2927))
([0dd8ed9](0dd8ed9))
* reject empty, extra, and unknown parts in geolocation and viewport
transforms
([#3097](#3097))
([#3120](#3120))
([3ea31fb](3ea31fb))
* resolve error causes on the session that reported the exception
([#3220](#3220))
([b2d37e8](b2d37e8))
* resolve service worker IDs for console messages
([#2881](#2881))
([3804a9a](3804a9a))
* return message when page exposes no 3p developer tools
([#3197](#3197))
([663f3c3](663f3c3)),
closes
[#3004](#3004)
* **script:** surface non-Error thrown and rejected values in
evaluate_script
([#2951](#2951))
([#3127](#3127))
([b1e6e68](b1e6e68))
* **security:** validate filesystem paths that parse as http/ws URLs
([#3186](#3186))
([91e112d](91e112d))
* **snapshot:** omit uid for accessibility nodes without backendNodeId
([#3187](#3187))
([9054351](9054351))
* stop active screencast on McpPage.dispose()
([#3160](#3160))
([558af81](558af81))
* stop get_network_request waiting forever for an unread no-store body
([#3216](#3216))
([c556be1](c556be1))
* surface nested error causes and autoConnect hint on connection failure
([#3111](#3111))
([d7f1e78](d7f1e78))
* treat 0.0.0.0 and [::] browser endpoints as local
([#3321](#3321))
([7d5f7de](7d5f7de))
* treat IPv4-mapped IPv6 loopback as localhost
([#3255](#3255))
([6cfb34c](6cfb34c))
* truncate data: URLs in accessibility snapshots
([#3292](#3292))
([11e7d47](11e7d47))
* validate type_text submitKey before typing
([#3185](#3185))
([c8615d7](c8615d7))
* **wait_for:** find text in dynamically attached iframes
([#3210](#3210))
([5f84888](5f84888))
* warn when screenshot dimensions exceed 16384px limit
([#2952](#2952))
([#3291](#3291))
([10455b7](10455b7))


### 📄 Documentation

* add a pre-submit checklist to AGENTS.md
([#3236](#3236))
([e96ee6c](e96ee6c))
* clarify URL pattern port and hostname matching
([#3287](#3287))
([4723335](4723335))
* **config:** note that hot-reloaded URL restrictions keep open targets
attached
([#3314](#3314))
([47db2b8](47db2b8))
* correct CLI availability of extension tools
([#2852](#2852))
([a7280ee](a7280ee))
* explain how to install skills, including the CLI skill
([#3274](#3274))
([46eb546](46eb546))
* remove experimental status from CLI and promote it in README
([#3273](#3273))
([0ced16b](0ced16b))
* require a rebase only when the branch has merge conflicts
([#3239](#3239))
([d1143ac](d1143ac))
* **skills:** clarify Lighthouse score scale and contrast workflow
([#3006](#3006))
([#3218](#3218))
([bf8c6d9](bf8c6d9))


### ⚡ Performance

* **cli:** load a small third-party bundle in the chrome-devtools CLI
([#3200](#3200))
([552e1f8](552e1f8))
* load the Lighthouse bundle on first use
([#3169](#3169))
([798f03a](798f03a))


### 🏗️ Refactor

* **config:** isolate scripts and unit tests from home config discovery
([#3256](#3256))
([65e6b97](65e6b97))
* **config:** lock slim and pageIdRouting options when viaCli is set
([#3257](#3257))
([384d9aa](384d9aa))
* **config:** pass ReadonlyServerConfig to BrowserManager and add
OptionGate
([#3267](#3267))
([98302f2](98302f2))
* **config:** simplify watchConfig and start watcher inside connect
([#3259](#3259))
([878c5f6](878c5f6))
* extract errorResult() and routedPageId() in ToolHandler
([#3251](#3251))
([9a6b03a](9a6b03a))
* import types and values from a module in one statement
([#3303](#3303))
([f4eaf1f](f4eaf1f))
* **lighthouse:** move Lighthouse runner methods to McpPage and add
bundle types
([#3283](#3283))
([e1823a2](e1823a2))
* list optional properties last in inline object types
([#3302](#3302))
([dc929c0](dc929c0))
* register all tools upfront across modes
([#3163](#3163))
([58f8d1f](58f8d1f))
* **response:** pass live ReadonlyServerConfig to McpResponse
([#3258](#3258))
([6042490](6042490))
* **tools:** add explicit factory types to tool definitions
([#3284](#3284))
([4d1d7b2](4d1d7b2))
* use #private names instead of the private modifier
([#3301](#3301))
([2e13311](2e13311))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
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