-
Notifications
You must be signed in to change notification settings - Fork 29.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
util: compact inspect() for sparse arrays #5070
Conversation
Thanks for the fix!
|
String(i), true)); | ||
} else { | ||
output.push(''); | ||
var isSparse = keys.length * 10 < value.length; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has to be explained in the comments. How this calculation determines if the array is sparse or not?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@thefourtheye added a comment. If less than 1/10th of the slots in an array are populated, util.inspect
/ console.log
now renders it compactly
var arr = []
arr[100] = 1
console.log(arr)
Before:
[ , , , , , (lots of commas) , 1 ]
After:
[ 100:1 ]
6c3bd3a
to
d7b8af2
Compare
@Trott @thefourtheye sounds good, fixed |
65033e3
to
6821944
Compare
@Trott added test cases, LMK if these look dece var arr = [];
arr[2] = 1; // expect util.inspect() to return [ , , 1 ]
arr[1000] = 1; // expect [ 2: 1, 1000: 1, <sparse array, length 1001> ]')
arr['foo'] = 'bar'; // expect [ 2: 1, 1000: 1, foo: 'bar', <sparse array, length 1001> ]
arr = new Array(1000000); // expect [ <empty array, length 1000000> ] |
This prevents `console.log(arr)` from crashing node when given a sparse array with large length. Fixes nodejs#4905
6821944
to
d257683
Compare
I think the sparse arrays are used only to prove the point. What happens when you use a dense array? |
@thefourtheye no, I think it's specifically about sparse arrays, where a small object can potentially lead to a huge
...by contrast there are lots of ways to make a large JSON produce a large |
Say you can crash a server by sending a 10GB POST, I think the fix is just to set request length limits. If you can crash a server by sending a 1KB POST which turns into a 10GB string internally, that's a bigger problem. |
Fair enough. But I am not sure if it is acceptable to special case it in the order of 10 like this. Lets hear from @nodejs/collaborators. |
Perhaps have something configurable like with |
+1 to @mscdex 's idea. If users want to see more data, they can explicitly adjust the value and invoke |
👍 for @mscdex idea, but with a default, something like |
-1. We shouldn't treat sparse arrays differently |
@vkurchatkin how would you fix the crash issue then? |
Not sure how I feel about this, surprising behaviour if you accidentally ran into it and I'm not sure it's intuitive although I guess the message helps. @vkurchatkin given that sparse arrays can kill Node, and this is an even more surprising and destructive behaviour, I'm not sure there's anything else we can do than treat large arrays differently. In terms of this actually fixing said issue, it only deals with sparse arrays, not large arrays. Consider:
That won't be solved here |
Maybe we should treat large (and not sparse) arrays differently. E.g.: if the array has more than 1000 elements, print a |
exactly. printing very large array to console is not useful anyway |
I also think adding an What I was saying above is, that will not just apply to arrays -- it'll have to limit output of strings and objects as well. Doable but a bit involved, esp since To give an example of what that would entail, I think we'd have to add a function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
var name, str, desc;
desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
if (desc.get) {
if (desc.set) {
str = ctx.stylize('[Getter/Setter]', 'special');
} else {
str = ctx.stylize('[Getter]', 'special');
}
} else {
if (desc.set) {
str = ctx.stylize('[Setter]', 'special');
}
}
if (!hasOwnProperty(visibleKeys, key)) {
if (typeof key === 'symbol') {
name = '[' + ctx.stylize(key.toString(), 'symbol') + ']';
} else {
name = '[' + key + ']';
}
}
if (!str) {
if (ctx.seen.indexOf(desc.value) < 0) {
if (recurseTimes === null) {
str = formatValue(ctx, desc.value, null);
} else {
str = formatValue(ctx, desc.value, recurseTimes - 1);
}
if (str.indexOf('\n') > -1) {
if (array) {
str = str.replace(/\n/g, '\n ');
} else {
str = str.replace(/(^|\n)/g, '\n ');
}
}
} else {
str = ctx.stylize('[Circular]', 'special');
}
}
if (name === undefined) {
if (array && key.match(/^\d+$/)) {
return str;
}
name = JSON.stringify('' + key);
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
name = name.substr(1, name.length - 2);
name = ctx.stylize(name, 'name');
} else {
name = name.replace(/'/g, "\\'")
.replace(/\\"/g, '"')
.replace(/(^"|"$)/g, "'")
.replace(/\\\\/g, '\\');
name = ctx.stylize(name, 'string');
}
}
return name + ': ' + str;
} |
This change is smaller and at least covers the small-HTTP-POST-crashing-node case. |
That might not be a bad thing. The current algorithm for identifying sparse arrays seems pretty arbitrary. And, as pointed out, it doesn't do anything about large arrays. |
This change is similar to the behavior of Chrome's console with sparse arrays. It may be useful to look and see what Blink/Chrome does to decide whether to do this special rendering or the usual expected rendering. EDIT: Specifically, how does Chrome/Blink decide that an array requires special rendering? |
curious if this would be a feature change or a fix? minor or patch? lts or no? |
IMO it's a breaking change. |
@Trott just did some experimenting. In Chrome:
So it looks like it prints a normal dense array for all indices starting from 0, then as soon as it gets to an index that is not set (which is not the same as an index whose corresponding value is If you want I can change this PR slightly to match that behavior. |
@dcposch I don't have an opinion on that one way or the other, but someone else might. |
Personally I can't understand how this is minor---what new feature does it introduce? It's either major (breaking change to existing feature) or patch (bugfix to existing feature). |
I'm finding it hard to conjure up much of an opinion on this one. @nodejs/collaborators anyone else want to champion this one through? I'd like to fix the crashes but am also concerned about how people might already be relying on |
As I previously mentioned, I wouldn't mind having a |
EDIT: Oops, posted the comment to the wrong place. Moved to: #4905 (comment) |
Building on @tunniclm's suggestion that he's since moved, perhaps the easiest path forward on this one is to add an option to |
Looking at this again, I would find it difficult to justify leaving the current crash behavior as the default.
|
I've opened an alternative PR that takes a slightly different approach to this. See #6334 |
7da4fd4
to
c7066fb
Compare
I think consensus is going towards #6334 - is this still being pursued? |
I'd recommend closing this in favor of #6334 (but I'm a bit biased lol) |
I think we can close this now and it can always be reopened. It seems stalled and there seems to be consensus is with the other proposal anyway. Feel free to reopen. |
As an alternative to nodejs#5070, set the max length of Arrays/TypedArrays in util.inspect() to `100` and provide a `maxArrayLength` option to override.
As an alternative to #5070, set the max length of Arrays/TypedArrays in util.inspect() to `100` and provide a `maxArrayLength` option to override. PR-URL: #6334 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com> Reviewed-By: Roman Reiss <me@silverwind.io>
As an alternative to #5070, set the max length of Arrays/TypedArrays in util.inspect() to `100` and provide a `maxArrayLength` option to override. PR-URL: #6334 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com> Reviewed-By: Roman Reiss <me@silverwind.io>
As an alternative to nodejs#5070, set the max length of Arrays/TypedArrays in util.inspect() to `100` and provide a `maxArrayLength` option to override. PR-URL: nodejs#6334 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com> Reviewed-By: Roman Reiss <me@silverwind.io>
This prevents
console.log(arr)
from crashing node when given a small sparse array with large lengthFixes #4905