firefox-devtools / devtools-core

:rocket: Packages for Firefox DevTools

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Maps and Sets `<entries>` node should be automatically expanded

julienw opened this issue · comments

STR:

  1. run this in the console:
var map = new Map(); for (var i = 0; i < 20; i++) { map.set('foo' + i, 'bar' + i); } map

=> We see some data but not all. But in other contexts, like in the debugger's scopes panel, we don't see the data.
2. Expands the map.
=> We still don't see the data. What we see is some useless information: size (ok, we know it already, it's written on the first line), prototype (useless in this case), and "entries" that is expandable.
3. Expands entries
=> now we see the data.

2 clicks to access the data is 1 useless extra click.

The same happens for Sets with:

var set = new Set(); for (var i = 0; i < 20; i++) { set.add('foo' + i); } set

After discussing this with @jasonLaster we thought that Maps could be displayed as Objects, while Sets could be displayed as Arrays. That is, without the step 2.

I disagree that we should show Maps and Sets as Arrays and Objects, it's important that these each printed object is clear about what it is.
The real issue is the extra step you mention to display the Map/Set entries. What could be done (and what Chrome does), is auto expand the ▶︎ <entries> node, so you only click once to get your entries.
We should make sure to handle this right when we have a lots of entries and we are using buckets, but that should be fine IMO.

prototype (useless in this case)
I'm curious why you think the prototype is useless here ?

I disagree that we should show Maps and Sets as Arrays and Objects, it's important that these each printed object is clear about what it is.

I think the first line is perfect as it is, and should stay the same -- so totally not like Arrays and Objects. But that when expanded the expansion itself should be like arrays and objects.

I'm curious why you think the prototype is useless here ?

It's not what a user wants to see when expanding the data. If I want to see the prototype, I type "map.prototype" and then I can see it if I want to. But usually that's not what's useful for these types of data.

Although I don't really mind if it's still displayed at the top of all entries :-) It's not in the way either

But that when expanded the expansion itself should be like arrays and objects.

The map could be augmented with properties which we do want to show so the user can really see what the object is like, e.g. :

var map = new Map(Array(20).fill(1).map((_, i) => ["foo" + i, "bar" + i])); 
map.test = "hello"; 
map[Symbol("foo")] = "bar"; 
map;

This is truly important as this kind of thing can lead to the hairiest issues.

It's not what a user wants to see when expanding the data. If I want to see the prototype, I type "map.prototype" and then I can see it if I want to. But usually that's not what's useful for these types of data.

I'm unsure about this, or if this is true, it is for every type of objects :)
I think the prototype node is still useful so you can navigate into and see what method you can call. In the future, we might want to have a link from a prototype function to the matching mdn page, which would make them even more useful.

The map could be augmented with properties which we do want to show so the user can really see what the object is like, e.g. :

It could but this isn't the general case. Can we optimize for the general case?
Is there an easy way to know whether the map has been "augmented" ?

I don't know, but I guess more work than simply autoexpand the <entries> node :)

I strongly oppose this. If you display a map as an object, i.e.

inspect(new Map([["foo", "bar"]]));
▼ Map(1)
| "foo": "bar"

then people will think that they can use map.foo and they will obtain "bar". But nope, they need to use map.get("foo") instead.

Maps are just ordinary objects with a [[MapData]] internal slot. Then, as @nchevobbe says, they can have normal properties just like any object. These should be displayed differently than [[MapData]] keys.

Can we optimize for the general case?

This would mean that the rendering wouldn't be consistent. Users wouldn't know if they are seeing normal properties of an "augmented" map or if they are seeing [[MapData]] entries of a non-"augmented" map.

Therefore, I want <entries> representing the [[MapData]]. It's true that in most cases the user may only be interested in [[MapData]], and this is solved by expanding <entries> automatically, not by merging it with normal properties.

Is there an easy way to know whether the map has been "augmented"?

This depends on how do you define "augmented", which is not a concept that exists in the spec. But I guess one could say that a non-"augmented" map is a map with no own property and which only inherits the safe getter size.

If I want to see the prototype, I type "map.prototype"

Er, this does not work. If you want to see the [[Prototype]], you need Reflect.getPrototypeOf(map) or equivalent.

But usually that's not what's useful for these types of data

I don't agree, defining a class that extends Map and adds new methods is super useful. The inspector should not make it harder to see these inherited methods just because the object is a map.

Thanks, I'm convinced now.

I changed the title of the issue to automatically expand the <entries> node for Maps and Sets, which should help browsing them.