Bug 132658 - Array.prototype.find and findIndex should skip holes
Summary: Array.prototype.find and findIndex should skip holes
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: JavaScriptCore (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Antoine Quint
URL:
Keywords:
Depends on:
Blocks: 145361
  Show dependency treegraph
 
Reported: 2014-05-07 12:31 PDT by Joseph Pecoraro
Modified: 2015-05-24 12:45 PDT (History)
6 users (show)

See Also:


Attachments
Patch (10.23 KB, patch)
2014-05-21 00:57 PDT, Antoine Quint
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Joseph Pecoraro 2014-05-07 12:31:58 PDT
From: <https://webkit.org/b/130966> Implement Array.prototype.find()

> Source/JavaScriptCore/builtins/Array.prototype.js:210
> +    for (var i = 0; i < length; i++) {
> +        if (callback.@call(thisArg, array[i], i, array))
> +            return array[i];
> +    }

Should we only call the callback if "i in array" for sparse arrays?
<http://people.mozilla.org/~jorendorff/es6-draft.html#sec-array.prototype.find>

Seems to indicate it only proceeds to calling the callback if the "i" was present:

. Repeat, while k < len
. Let Pk be ToString(k).
. Let kPresent be HasProperty(O, Pk).
. ReturnIfAbrupt(kPresent).
. If kPresent is true, then
.   . Let kValue be Get(O, Pk).
.   . ReturnIfAbrupt(kValue).
.   . Let testResult be the result of calling the [[Call]] internal method of predicate with T as thisArgument and a List containing kValue, k, and O as argumentsList.


Test:

<script>
function passUndefined(element, index, array) {
    return typeof element === "undefined";
}

arrayWithHoles = [];
arrayWithHoles[10] = 0;
arrayWithHoles[20] = null;
arrayWithHoles[30] = false;
arrayWithHoles[40] = "";
arrayWithHoles.findIndex(passUndefined); // -1
arrayWithHoles[50] = undefined;
arrayWithHoles.findIndex(passUndefined); // 50
</script>

Expected: -1, 50.
Saw: 0, 0

Firefox Nightly gives the expected values.
Comment 1 Alexey Proskuryakov 2014-05-20 09:51:48 PDT
Is it a problem to expose Array.prototype.find() with this bug? I winder if it should be disabled until this is fixed.
Comment 2 Geoffrey Garen 2014-05-20 09:54:24 PDT
Yes, let's disable it.
Comment 3 Antoine Quint 2014-05-20 10:16:46 PDT
I'll look into this tomorrow!
Comment 4 Joseph Pecoraro 2014-05-20 10:19:36 PDT
(In reply to comment #0)
> From: <https://webkit.org/b/130966> Implement Array.prototype.find()
> 
> > Source/JavaScriptCore/builtins/Array.prototype.js:210
> > +    for (var i = 0; i < length; i++) {
> > +        if (callback.@call(thisArg, array[i], i, array))
> > +            return array[i];
> > +    }
> 
> Should we only call the callback if "i in array" for sparse arrays?
> <http://people.mozilla.org/~jorendorff/es6-draft.html#sec-array.prototype.find>

I really think all that is needed is:

    if (!(i in array))
       continue;

I just haven't had the time to try it.
Comment 5 Oliver Hunt 2014-05-20 10:29:34 PDT
(In reply to comment #4)
> (In reply to comment #0)
> > From: <https://webkit.org/b/130966> Implement Array.prototype.find()
> > 
> > > Source/JavaScriptCore/builtins/Array.prototype.js:210
> > > +    for (var i = 0; i < length; i++) {
> > > +        if (callback.@call(thisArg, array[i], i, array))
> > > +            return array[i];
> > > +    }
> > 
> > Should we only call the callback if "i in array" for sparse arrays?
> > <http://people.mozilla.org/~jorendorff/es6-draft.html#sec-array.prototype.find>
> 
> I really think all that is needed is:
> 
>     if (!(i in array))
>        continue;
> 
> I just haven't had the time to try it.

That's all the needed -- the code should essentially match all the other array methods
Comment 6 Antoine Quint 2014-05-20 10:39:20 PDT
That, and a test, I'll have a patch out within 24 hours.
Comment 7 Antoine Quint 2014-05-20 10:46:05 PDT
For .find(), I was thinking of adding a test where we count the number of callbacks to check that we indeed only call the callback where there are entries.
Comment 8 Oliver Hunt 2014-05-20 11:05:33 PDT
(In reply to comment #7)
> For .find(), I was thinking of adding a test where we count the number of callbacks to check that we indeed only call the callback where there are entries.

Look at the tests for other array prototype functions - you want to check the number and order of callbacks
Comment 9 Antoine Quint 2014-05-21 00:57:56 PDT
Created attachment 231819 [details]
Patch
Comment 10 Geoffrey Garen 2014-05-21 08:23:44 PDT
Comment on attachment 231819 [details]
Patch

r=me
Comment 11 WebKit Commit Bot 2014-05-21 09:15:25 PDT
Comment on attachment 231819 [details]
Patch

Clearing flags on attachment: 231819

Committed r169162: <http://trac.webkit.org/changeset/169162>
Comment 12 WebKit Commit Bot 2014-05-21 09:15:28 PDT
All reviewed patches have been landed.  Closing bug.