Custom Formatters (devtoolsFormatters) break the "Copy Object" context menu item, causing it to copy (portions of) the displayed text content and not the actual logged object
Categories
(DevTools :: Console, defect, P3)
Tracking
(firefox138 fixed)
Tracking | Status | |
---|---|---|
firefox138 | --- | fixed |
People
(Reporter: cob.bzmoz, Assigned: cob.bzmoz)
Details
Attachments
(2 files)
User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:135.0) Gecko/20100101 Firefox/135.0
Steps to reproduce:
Implement a basic Custom Formatter via the Custom Formatters API (devtoolsFormatters
). Log an object to the console which is affected by the custom formatter. Right-click on the logged message and select "Copy Object." Go to any text editor (e.g. Notepad) and paste into it to see what you copied.
The attached file contains a simplified test-case: a custom formatter is installed, and a simple object literal is logged when the page loads. You can right-click on any part of the logged message (whether you expand it first doesn't matter) and click "Copy Object."
Actual results:
You will copy the textContent
of whatever DOM node, within the custom-formatted output, you right-clicked on. Using the attached file as an example, if you right-clicked on the green "World!" text, then you will copy "World!" to the clipboard.
Expected results:
You should copy the exact same text as would be copied if the logged object didn't use a custom formatter, e.g. a JSON serialization of the logged object, because the context menu item that you clicked was labeled "Copy Object," not "Copy Message," much less "Copy This One Specific Portion Of The Logged Message."
The code which sets up the context menu is createContextMenu
in /devtools/client/webconsole/utils/context-menu.js
. On line 65 we see that the variableText
variable is set to the textContent
of whatever specific DOM node you right-clicked on. On line 73, we see that console log messages are associated with "actors" (logged objects) based on whether the messages have a data-link-actor-id
attribute.
The "Copy Object" context menu item is enabled if there exists variableText
or an "actor", with the item coded to copy the actor if one exists or the variableText
otherwise (the choice between the two is implemented here). Looking upward a bit, we also see that "Store as global variable" is only enabled if there exists an actor, and sure enough, custom-formatted messages also disable the "Store as global variable" option in addition to causing "Copy Object" to malfunction. (In essence, I think "Copy Object" being broken and "Store as global variable" being unavailable are the same bug.)
You can also observe, by using the Browser Toolbox to run devtools on the devtools, that the data-link-actor-id
attribute isn't present anywhere within the custom-formatted log message.
Unfortunately, I couldn't find where the actor ID gets lost -- where the devtools forget to write it into their DOM.
From what I can understand after digging around the devtools source (both now and in the past), "rep" objects define the visual representation of some object within the devtools console (or debugger, or anywhere else that JS values may be displayed I guess). Per the comments on getRep
(defined here), a "grip" is a "handle to a remote debuggee object," e.g. JavaScript objects and DOM nodes in the page being debugged.
The default GripRep
is one of the few places that actually uses the data-link-actor-id
within Firefox's source code. The CustomFormatter
rep, by contrast, does not.
When the devtools want to log an object, they start by choosing between the reps
and noGripReps
lists of possible reps to use. (CustomFormatter
is only added to reps
when custom formatting is enabled, in which case it goes at the very start of that list.) After choosing one of those lists, getRep
loops through it and chooses the first rep that claims to support the to-be-displayed entity. CustomFormatter
supports any entity that opts into custom formatting and has a custom-formatted header.
It seems to me like fixing this would have something to do with having CustomFormatter.prototype.render
check this.props.object.actor
and log the actor ID. However, I'm not familiar enough with the overall architecture of the devtools to know if that would work (e.g. if the object in question has an actor ID at the time that that function would run, versus if an actor ID has to be given to it somehow).
(It sucks not to have an edit button.)
To hopefully make my last comment clearer: I believe the render
method on CustomFormatter
needs to be updated to set the data-link-actor-id
in the same manner that GripRep
does. GripRep
acts on the assumption that the object already has an actor ID. If the object would also have an actor ID when run through CustomFormatter
, then the fix for this bug might be as simple as adding the following line after both line 103 and line 120 of the CustomFormatter
source file, if I'm properly understanding the minutiae of how these reps are implemented:
"data-link-actor-id": this.props.object.actor,
Updated•8 months ago
|
Updated•8 months ago
|
Comment 4•8 months ago
|
||
Cob, since you ran an extensive investigation here, would you try to fix the bug yourself?
We have some documentation on how to get started: https://firefox-source-docs.mozilla.org/devtools/index.html
If you don't want or don't have the time, that's fine, I'll look at the bug myself
Wish I could, but no time right now, sorry. Ran into this while working on something for another programming project, which I'm still actively dealing with.
Thanks for the link, though; I'll keep it open in Firefox along with the instructions for building on Windows. If I find time to set up a Firefox dev environment down the road, and this bug is still open by then, I'll see what I can do about it at that time.
Updated•7 months ago
|
Comment 8•7 months ago
|
||
bugherder |
Description
•