Closed Bug 1035122 Opened 11 years ago Closed 11 years ago

Polyfill of Array.prototype.forEach incorrect

Categories

(Developer Documentation Graveyard :: JavaScript, defect, P5)

All
Other
defect

Tracking

(Not tracked)

RESOLVED INVALID

People

(Reporter: chris, Assigned: rwaldron)

References

()

Details

Attachments

(2 files)

:: Developer Documentation Request Request Type: Correction Gecko Version: unspecified Technical Contact: :: Details Since the array can be modified during for each the 'cacheing' of the length value in the method would result in different behaviour since the function would be called for more or less elements
Rick, can you have a look the Array.prototype.forEach polyfill on MDN? You are maintaining the others quite well, too :-)
Flags: needinfo?(waldron.rick)
Will do
Assignee: fscholz → waldron.rick
Flags: needinfo?(waldron.rick)
This report is invalid. As the ES5 spec states: 15.4.4.18 The range of elements processed by forEach is set before the first call to callbackfn. Elements which are appended to the array after the call to forEach begins will not be visited by callbackfn. If existing elements of the array are changed, their value as passed to callback will be the value at the time forEach visits them; elements that are deleted after the call to forEach begins and before being visited are not visited. If more elements are added, they are ignored. If elements are removed, they are skipped by steps 7.B and 7.C
Status: UNCONFIRMED → RESOLVED
Closed: 11 years ago
Resolution: --- → INVALID
elements that are deleted after the call to forEach begins and before being visited are not visited. However in the current polyfill they will be visited (the value passed will be undefined)...
Status: RESOLVED → UNCONFIRMED
Resolution: INVALID → ---
Attached file foreach-visit.js
Please see the attached test case file that illustrates the correct behaviour of the polyfill.
Status: UNCONFIRMED → RESOLVED
Closed: 11 years ago11 years ago
Resolution: --- → INVALID
Thanks gonna write some tests so I'm happy
Status: RESOLVED → UNCONFIRMED
Resolution: INVALID → ---
Attached file array.forEach.spec.js
Okay your interpretation of the spec seems to be way better than mine (funnily enough the poly fill I wrote behaves the same way as you and the browsers (but includes string support for IE) - it was only when I checked the spec (which I clearly misinterpreted I hopped to check if yours was better!) IE6/7/ and 8 (the browsers we need the polyfill for) failures listed below - also in other browsers the first two failures occur but this may be Jasmine... PLEASE NOTE: Jasmine does not support IE6/7 (think 8 is ok) I run with a sloppily patched version for them (basically it uses querySelector and createTextNode which aren't supported - oh and the CSS sucks!) Anyway here are the failures 24 specs, 5 failures Spec List | Failures Spec List | Failures Array.prototype.forEach tests throws an error with null Expected function to throw an exception. Array.prototype.forEach tests throws an error with undefined Expected function to throw an exception. Array.prototype.forEach tests it works on literal strings Expected 0 to be 6. Array.prototype.forEach tests works on String objects with length and members Expected 0 to be 3. Array.prototype.forEach tests visits explicitly set to undefined elements Expected 0 to equal 1.
you can fix the last failure (which is the only important using the 'in' solution I suggested when the index is undefined)
> Array.prototype.forEach tests throws an error with null > Expected function to throw an exception. > Array.prototype.forEach tests throws an error with undefined > Expected function to throw an exception. Not sure how to reasonably cover these two without strict mode, which isn't implemented in IE 6, 7, 8 or 9. See: http://es5.github.io/#x15.3.4.4 specifically, read the NOTE section were null and undefined are automatically replaced by the global object. This means that: Array.prototype.forEach.call(null, function() { console.log(this); }); That will log the `window` object in those browsers. > Array.prototype.forEach tests it works on literal strings > Expected 0 to be 6. > Array.prototype.forEach tests works on String objects with length and members > Expected 0 to be 3. The "generic" semantics that Array.prototype.forEach has are defined for an ES5 compliant environment, which IE6, 7 and 8 are not. The reason this can't be supported is because bracket notation "property" access doesn't work on strings in those browsers. Try the following: var foo = "foo"; alert(foo); alert(foo[0]); alert(foo.charAt(0)); The results will be: "foo" undefined "f" The last test is not fixable, that caused by a bug in IE6, 7, 8 and would require omitting the `k in O` check altogether and treating the array as "always dense" instead of "possibly sparse", which breaks the polyfill. Holes must be skipped, per spec. Further reading: https://github.com/es-shims/es5-shim/issues/190 https://github.com/es-shims/es5-shim/pull/131 These specifically: https://github.com/es-shims/es5-shim/issues/190#issuecomment-34931058 https://github.com/es-shims/es5-shim/issues/190#issuecomment-34933840
Yeah I just ran the tests against my code and it failed too :( Here's my code (bit simpler than yours but passes all the tests except the undefined one (which I thought it did!) - could do while loops but scoping the variables to the for seems to be faster (guess thats an engine/interpreter thing) Array.prototype.forEach = function(callback, thisArg) { if (this == window) { throw new Error(".forEach called on null or undefined") } if (this.constructor == String || this instanceof String) { for (var i = 0,l=this.length||0; i != l; i++) { callback.call(thisArg, this.charAt(i), i, this); } } else { for (var i = 0,l=this.length||0; i != l; i++) { if (i in this) { callback.call(thisArg, this[i], i, this); } } } }
Mind you I dont check the length is a number :( darn it and of course I suppose you could call it on the window object too so there's another oversight on my part) Oh well thanks for your time and I'll do unit tests first before I start misinterpreting the spec :)
Status: UNCONFIRMED → RESOLVED
Closed: 11 years ago11 years ago
Resolution: --- → INVALID
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: