Array.prototype.toString violates the spec regarding recursion. |
|||||
Issue description
Consider following code:
var a = [];
a.push(a);
a.toString() // returns empty string.
The reason is that we track in a stack whether the array is cyclic. However, the spec doesn't prescribe this recursion check [0].
Now consider following code:
var counter = 0;
var side_effect_observer = {
toString() {
if (counter++ == 0) {
return array.toString();
} else {
return "a";
}
}
}
var array = [ side_effect_observer ];
array.toString(); // returns empty string.
Now arguably we do not have a cyclic array, just a recursion that does terminate. I would expect the result to be "a". All engines still return the same empty string. In V8, this is because we have a global stack to track recursion. Presumably this is implemented similarly in Safari and Firefox.
There is also this esdiscuss thread [1] that discusses this, with the conclusion that this should be spec'ed. Nothing happend since then.
Is this something we want to fix, or do we recoil in fear of breaking the web?
[0] https://tc39.github.io/ecma262/#sec-array.prototype.join
[1] https://esdiscuss.org/topic/15-4-4-5-array-prototype-join
,
Feb 9 2017
This is supported in Firefox as well (I just tested) and IIRC it's supported across browsers. I'd be surprised if we could change something like this and not break the web. I think the status is squarely "reality missing a spec", and you did the right thing to file a bug in the ES spec bug tracker. The committee is aware of the issue (at least it's come up in discussion when I was there); it's been hard to write down since it's pretty ugly-looking, but we've been establishing a good pattern of specifying things like this recently. The trick here is to figure out how each browser keeps track of whether things are cyclic (I don't know if they do it in different ways) and find something in common that's reasonable to specify.
,
Feb 9 2017
> The trick here is to figure out how each browser keeps track of whether things are cyclic (I don't know if they do it in different ways) https://github.com/mozilla/gecko-dev/blob/master/js/src/jsarray.cpp#L1165-L1172 I think it ends up being more or less the same as what v8 does (track visited objects in a per-context set), but I believe it's the same cycle-detection mechanism they use for the heap overall, so it doesn't need to add/remove items in a global/per-context stack for each visit to an element in Array-join. Since it's a complicated mechanism, it's hard to see all the details of it all at once, but most likely it behaves more or less the same as the v8 approach, perhaps with a shorter runtime due to not doing this tracking as part of the ArrayJoin algorithm. Dunno if that helps with anything or not.
,
Mar 23 2017
,
Jul 6
Peter, this could be relevant since you're working on Array.p.join.
,
Aug 16
|
|||||
►
Sign in to add a comment |
|||||
Comment 1 by yangguo@chromium.org
, Feb 9 2017