Bug 42758 - Web Inspector: consider jQuery object to be of 'array' nature.
Summary: Web Inspector: consider jQuery object to be of 'array' nature.
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Web Inspector (Deprecated) (show other bugs)
Version: 528+ (Nightly build)
Hardware: All All
: P2 Normal
Assignee: Pavel Feldman
URL: http://firequery.binaryage.com/test/i...
Keywords:
Depends on:
Blocks:
 
Reported: 2010-07-21 09:05 PDT by Pavel Feldman
Modified: 2010-08-12 15:58 PDT (History)
19 users (show)

See Also:


Attachments
[PATCH] Proposed change. (1.11 KB, patch)
2010-07-21 09:08 PDT, Pavel Feldman
no flags Details | Formatted Diff | Diff
[IMAGE] Firebug looks (59.90 KB, image/png)
2010-07-21 09:12 PDT, Pavel Feldman
no flags Details
[IMAGE] Web Inspector today. (82.86 KB, image/png)
2010-07-21 09:13 PDT, Pavel Feldman
no flags Details
[IMAGE] Web Inspector with patch applied. (110.56 KB, image/png)
2010-07-21 09:13 PDT, Pavel Feldman
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Pavel Feldman 2010-07-21 09:05:59 PDT
- Go to the specified url
- Open console
- See a bunch of "> Object" entries there.

Do similar with Firebug+FireQuery, see nice output there. Considering jQuery object an array we get pretty much same results. I think jQuery is big enough to do it for them.
Comment 1 Pavel Feldman 2010-07-21 09:08:22 PDT
Created attachment 62189 [details]
[PATCH] Proposed change.
Comment 2 Pavel Feldman 2010-07-21 09:12:58 PDT
Created attachment 62190 [details]
[IMAGE] Firebug looks
Comment 3 Pavel Feldman 2010-07-21 09:13:27 PDT
Created attachment 62191 [details]
[IMAGE] Web Inspector today.
Comment 4 Pavel Feldman 2010-07-21 09:13:53 PDT
Created attachment 62192 [details]
[IMAGE] Web Inspector with patch applied.
Comment 5 Joseph Pecoraro 2010-07-21 10:14:43 PDT
This sounds like what bug 30974 was opened for:
https://bugs.webkit.org/show_bug.cgi?id=30974

Any new comments on that?
Comment 6 WebKit Commit Bot 2010-07-21 10:26:36 PDT
Comment on attachment 62189 [details]
[PATCH] Proposed change.

Clearing flags on attachment: 62189

Committed r63837: <http://trac.webkit.org/changeset/63837>
Comment 7 WebKit Commit Bot 2010-07-21 10:26:41 PDT
All reviewed patches have been landed.  Closing bug.
Comment 8 John-David Dalton 2010-08-12 14:14:27 PDT
Why is a browser giving special treatment to a specific JS lib?

Why not extend the same functionality to any array-like object say that has a `length` property and `index` properties?

Maybe the devs using console.log() were just doing it wrong as:
[].slice.call($('div')) would produce an output like an array without a lib specific patch.
Comment 9 kangax 2010-08-12 14:20:29 PDT
I'll second John-David. It would make more sense to extend this functionality for any array-like object. This will display similar array-like abstractions from other libraries in similar, descriptive way.

It would also make sense to indicate that an object is not a real array (where "real array" could be considered, for example, anything with [[Class]] of "Array").

Perhaps prepend returning value with "ArrayLike: " or something along those lines.
Comment 10 Kyle Simpson 2010-08-12 14:26:04 PDT
i concur with dalton and kangax. it's a bad pattern to specifically tie features to one lib and not the others.
Comment 11 Angus Croll 2010-08-12 14:29:12 PDT
Agree with previous 3. Basing logic on knowledge of 3rd party library objects is analogous to browser sniffing. Just check for length etc. regardless of type
Comment 12 Guillermo Rauch 2010-08-12 14:31:26 PDT
Agree with previous comments.
Comment 13 Mathias Bynens 2010-08-12 14:32:49 PDT
I agree with comments #8 and up. Why tie features to specific libraries when it can just as easily be done for all of them, as John-David Dalton proposed:

> Why not extend the same functionality to any array-like object say that has `length` and `index` properties?
Comment 14 Nick Carter 2010-08-12 14:33:32 PDT
Definitely think if this functionality is going to be available to jQuery it should be available to everything, and if we can apply it to all array-likes that'd be great! Just need to be sure it's presented clearly enough that it's NOT an array.
Comment 15 Pavel Feldman 2010-08-12 14:35:47 PDT
I agree that "tie features to one lib and not the others" is a bad pattern, we've just had too many requests for this specific one. I am sure many users will benefit from this suboptimal solution. While we are thinking about a more generic one, could we get the use cases where other libraries would benefit from the array-alike output as well? It is just that 'length + index' requirement seems to be to loose, so we might add more.
Comment 16 Mike Taylor 2010-08-12 14:39:31 PDT
+1 for adding this capability for all array-like objects, agnostic of library.
Comment 17 John-David Dalton 2010-08-12 14:44:33 PDT
MooTools 1.3beta, MooTools' next release, returns an array-like object for its DOM query method.

http://dl.dropbox.com/u/513327/log_array_like.html

Note that in Firebug it displays like an array because it is array-like.
Comment 18 kangax 2010-08-12 14:50:44 PDT
(In reply to comment #15)
> I agree that "tie features to one lib and not the others" is a bad pattern, we've just had too many requests for this specific one. I am sure many users will benefit from this suboptimal solution. While we are thinking about a more generic one, could we get the use cases where other libraries would benefit from the array-alike output as well? It is just that 'length + index' requirement seems to be to loose, so we might add more.

Well, detecting length + index properties would cover:

1) real arrays
2) nodelists (already displayed as arrays)
5) arguments object
3) jquery objects
4) any other array-like abstractions from other scripts/libraries

I could see how this could be "too loose", which is why some kind of indication of array-like nature of an object seems reasonable here (e.g.: #Arguments: ['foo', 'bar', 'baz'], #ArrayLike: ['foo', 'bar', 'baz'], etc.)
Comment 19 Ryan Grove 2010-08-12 14:56:19 PDT
(In reply to comment #15)
> It is just that 'length + index' requirement seems to be to loose, so we might add more.

I agree with kangax that it seems reasonable to assume that an object with both "length" and "index" properties wants to be treated as an array-like object, or at least that it would not be surprising for such an object to be treated as array-like (as long as the distinction between "array" and "array-like" is clear).

This also provides a simple convention for library developers. Want your object to be considered array-like? Give it "length" and "index" properties. Don't want that? Call them "size" and "indexOf" (or something else) instead.
Comment 20 Kit Cambridge 2010-08-12 14:58:41 PDT
I agree with all of the above comments as well; however, I think that checking for the existence of the `length` property is not enough, as an object like `{"title": "Commentaries", "length": 25, "content": [...]}` would be incorrectly represented as an array. A more robust (though certainly not foolproof) check might be `(obj.length === obj.length >>> 0) && "0" in obj`, or even iterating over the object's properties until a numeric one is encountered.

I also like kangax's proposal for a separate representation for array-like objects, maybe something akin to `<List: [...]>`. I would, however, also like to propose using that representation for NodeLists and HTMLCollections as well, reserving `[...]` for arrays only.
Comment 21 Timothy Hatcher 2010-08-12 15:05:56 PDT
Looking from "0" in obj would not work for sparse arrays.
Comment 22 Kit Cambridge 2010-08-12 15:16:32 PDT
(In reply to comment #21)
> Looking from "0" in obj would not work for sparse arrays.

Good point. The alternative method I mentioned above (looping over the object's properties using a `for..in` loop, breaking as soon as a numeric key is encountered) should be more effective in that regard, although performance might be an issue.
Comment 23 Kyle Simpson 2010-08-12 15:18:12 PDT
for-in loops have *vastly* worse performance.

http://jsperf.com/for-loop-vs-for-in-loop
Comment 24 Joseph Pecoraro 2010-08-12 15:19:14 PDT
Hey Guys! Thanks for the comments.

As I mentioned in comment #5, we opened a bug for this already, and had
some discussion on it. I'd recommend the discussion move over to that
bug if possible. I'll duplicate this comment on that bug as well:
<http://webkit.org/b/30974> Web Inspector: Pretty print array-like objects

(In reply to comment #20)
> A more robust (though certainly not foolproof) check might be `(obj.length ===
> obj.length >>> 0) && "0" in obj`, or even iterating over the object's properties
> until a numeric one is encountered.

I think this check is pretty sufficient.


> I also like kangax's proposal for a separate representation for array-like
> objects, maybe something akin to `<List: [...]>`. I would, however, also like
> to propose using that representation for NodeLists and HTMLCollections as well,
> reserving `[...]` for arrays only.

I also like this idea. Currently we treat NodeLists and Collections as arrays,
and I think they deserve some differentiation.

http://trac.webkit.org/browser/trunk/WebCore/inspector/front-end/InjectedScript.js

>    if (obj instanceof inspectedWindow.Array)
>        return "array";
>    if (obj instanceof inspectedWindow.NodeList)
>        return "array";
>    if (obj instanceof inspectedWindow.HTMLCollection)
>        return "array";

------

It seems the major issue is:

  JavaScript libraries have "array like" collections which would be useful to
  display like arrays in the console! But, sometimes this could go wrong, or
  sometimes this could hide information.

For those "sometimes" cases, like was mentioned above, I think it would be
good enough to indicate that this is in fact not an array, but an "array like"
object. As a user, if I saw this indicator it be helpful, and I might want
to display this as an object instead. So, if that indicator was clickable,
and could toggle between the array-like quick view and the complete object
view that sounds best to me.

Does that sound good? Is there a use case I'm missing?
Comment 25 Pavel Feldman 2010-08-12 15:25:53 PDT
You just made "window" render as 
[undefined]
in the console :P
Comment 26 kangax 2010-08-12 15:26:27 PDT
Welcome to the can of worms :)

Detecting by both indices and length will not work with `arguments` object, since arguments object could well have `length` of 0 and no indices. 

One possible workaround for that is to consider objects with length === 0 to be array-like even if no indices are present.

Another workaround is to catch `arguments` object before testing for array-like'ness — for example, by checking if [[Class]] of object is "Arguments" (as per ES5), or that it has `callee` property of function value, besides `length` (as per ES3), or maybe even checking `length` and `callee` properties' non-enumerability if we want to be really paranoid. But since webkit already sets arguments's [[Class]] to "Arguments", the other — more complex — versions could probably be avoided.

I like second solution better, as it's both more robust and goes in line with detecting not just array-like objects, but arguments, nodelists, and "the rest" (e.g. jQuery) separately. It's also less confusing that way.
Comment 27 Joseph Pecoraro 2010-08-12 15:34:19 PDT
(In reply to comment #25)
> You just made "window" render as  [undefined] in the console :P

Yah, I guess more have a "length" than I thought. Functions do too, but they
have good instanceof and typeof semantics.


> But since webkit already sets arguments's [[Class]] to "Arguments", the other
> — more complex — versions could probably be avoided.

"Arguments" is one of my major use-cases. I would like to see that arraylike.
And you're right, this can be special cased differently.
Comment 28 John-David Dalton 2010-08-12 15:42:13 PDT
For reference this is how Firebug detects array-like:
http://code.google.com/p/fbug/source/browse/branches/firebug1.6/content/firebug/reps.js#560

This allows jQuery results, MooTools 1.3 results and anything with a 
length property and splice method to be displayed as an array. It covers the arguments object too.
Comment 29 Joseph Pecoraro 2010-08-12 15:58:41 PDT
(In reply to comment #28)
> For reference this is how Firebug detects array-like:
> http://code.google.com/p/fbug/source/browse/branches/firebug1.6/content/firebug/reps.js#560
> 
> This allows jQuery results, MooTools 1.3 results and anything with a 
> length property and splice method to be displayed as an array. It covers the arguments object too.

Pavel just put a patch to this affect up on bug 30974.