-
-
Notifications
You must be signed in to change notification settings - Fork 732
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
stringify: Avoid arr = arr.concat(...), push to the existing instance #269
stringify: Avoid arr = arr.concat(...), push to the existing instance #269
Conversation
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.
I'm hesitant to do this; 5 seconds for a million iterations means that in the common case, it will be a scattering of milliseconds' difference.
lib/stringify.js
Outdated
@@ -15,6 +15,14 @@ var arrayPrefixGenerators = { | |||
} | |||
}; | |||
|
|||
var pushToArray = function (arr, valueOrArray) { | |||
if (Array.isArray(valueOrArray)) { | |||
Array.prototype.push.apply(arr, valueOrArray); |
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 changes a dependency on concat
to a dependency on both push
and apply
.
Separately, concat
actually has different semantics - it uses isConcatSpreadable
, which includes more than just arrays (altho perhaps that doesn't matter here).
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.
Why is it bad to depend on Array#push
and apply
? They're fairly standard :). It'd look nicer with array spread, of course.
I had no idea about Symbol.isConcatSpreadable
. As far as I can tell, the operand will always be an array or a string, though.
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.
They're all standard, but the more things that the package depends on existing, the more likely it will break if people mess with the builtin prototypes.
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.
That's technically correct, but is it really worth worrying about? It seems unlikely that anyone will overwrite ES3 methods from prototypes in this day and age? Especially methods that have been in the language for 20 years?
I'm caught a bit off-guard because I haven't heard that kind of reasoning for preferring one piece of code over another for a very long time. I'm aware of MooTools, should.js and some of the even crazier things people did before, but hasn't the community stopped doing it and moved on at this point?
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 is the web; I always write all my code assuming that everything will be deleted off the prototype (or replaced with a malicious version) after my code runs :-)
This code predates me, and your PR is changing the attack surface. I agree it's a minor concern in practice, but it's still nonzero.
Well, okay, I'm not totally invested in this. Just seemed wasteful and O(n^2)-y to create all those intermediate arrays. |
4df4608
to
829f866
Compare
@ljharb, I've rebased this branch now. Still a bit baffled about your initial reaction to this change, do you still feel the same way? |
829f866
to
75f0fbc
Compare
75f0fbc
to
b853cb8
Compare
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.
Made some small tweaks so that now the only runtime dependency is "apply"; I guess this is fine to merge.
Currently
qs.stringify
will create a new array whenever a new parameter is added. This fixes it by pushing to the existing one instead.Very unscientific benchmark:
Before:
After: