Ignore:
Timestamp:
Dec 16, 2021, 8:10:09 AM (4 years ago)
Author:
Devin Rousso
Message:

Implement Array.prototype.groupBy and Array.prototype.groupByToMap
https://bugs.webkit.org/show_bug.cgi?id=234327

Reviewed by Yusuke Suzuki.

JSTests:

  • stress/array-groupBy.js: Added.

(shouldBe):
(shouldBeObject):
(shouldBeObject.replacer):
(notReached):
(toObject):
(reverseInsertionOrder):

  • stress/array-groupByToMap.js: Added.

(shouldBe):
(shouldBeObject):
(shouldBeObject.replacer):
(shouldBeMap):
(notReached):
(toObject):
(reverseInsertionOrder):

Source/JavaScriptCore:

Implement new Array Grouping proposal <https://tc39.es/proposal-array-grouping/>, which just
reached Stage 3.

Array.prototype.groupBy/Array.prototype.groupByToMap will return a {}/Map where each
value in the array is put into a "bucket" keyed by the return value of the provoded callback.

`js
const array = [1, 2, 3, 4];

array.groupBy(n => n % 2 ? "odd" : "even") { odd: [1, 3], even: [2, 4] }
array.groupByToMap(n => n % 2 ? "odd" : "even")
new Map("odd", [1, 3, ["even", [2, 4]])
`

  • builtins/ArrayPrototype.js:

(groupBy): Added.
(groupByToMap): Added.

  • runtime/ArrayPrototype.cpp:

(JSC::ArrayPrototype::finishCreation):

  • bytecode/BytecodeIntrinsicRegistry.h:
  • bytecompiler/NodesCodegen.cpp:

(JSC::BytecodeIntrinsicNode::emit_intrinsic_toPropertyKey): Added.
Allow @toPropertyKey to be used in builtins to convert a value to a property key. This is
used to avoid converting the return value of the callback given to groupBy more than once.

  • builtins/BuiltinNames.h:
  • bytecode/LinkTimeConstant.h:
  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::init):
Allow @Map to be used in builtins to create a primordial Map instance. This is used to
avoid side effects when creating and populating the Map returned by groupByToMap.

  • runtime/OptionsList.h:

Add useArrayGroupByMethod option.

Source/WebInspectorUI:

  • UserInterface/Models/NativeFunctionParameters.js:
Location:
trunk/Source/JavaScriptCore/builtins
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/builtins/ArrayPrototype.js

    r279937 r287136  
    157157}
    158158
     159function groupBy(callback /*, thisArg */)
     160{
     161    var array = @toObject(this, "Array.prototype.groupBy requires that |this| not be null or undefined");
     162    var length = @toLength(array.length);
     163
     164    if (!@isCallable(callback))
     165        @throwTypeError("Array.prototype.groupBy callback must be a function");
     166
     167    var thisArg = @argument(1);
     168
     169    var groups = @Object.@create(null);
     170    for (var i = 0; i < length; ++i) {
     171        var value = array[i];
     172        var key = @toPropertyKey(callback.@call(thisArg, value, i, array));
     173        var group = groups[key];
     174        if (!group) {
     175            group = [];
     176            @putByValDirect(groups, key, group);
     177        }
     178        @putByValDirect(group, group.length, value);
     179    }
     180    return groups;
     181}
     182
     183function groupByToMap(callback /*, thisArg */)
     184{
     185    var array = @toObject(this, "Array.prototype.groupByToMap requires that |this| not be null or undefined");
     186    var length = @toLength(array.length);
     187
     188    if (!@isCallable(callback))
     189        @throwTypeError("Array.prototype.groupByToMap callback must be a function");
     190
     191    var thisArg = @argument(1);
     192
     193    var groups = new @Map;
     194    for (var i = 0; i < length; ++i) {
     195        var value = array[i];
     196        var key = callback.@call(thisArg, value, i, array);
     197        var group = groups.@get(key);
     198        if (!group) {
     199            group = [];
     200            groups.@set(key, group);
     201        }
     202        @putByValDirect(group, group.length, value);
     203    }
     204    return groups;
     205}
     206
    159207function map(callback /*, thisArg */)
    160208{
  • trunk/Source/JavaScriptCore/builtins/BuiltinNames.h

    r286069 r287136  
    7171    macro(defaultPromiseThen) \
    7272    macro(Set) \
     73    macro(Map) \
    7374    macro(throwTypeErrorFunction) \
    7475    macro(typedArrayLength) \
Note: See TracChangeset for help on using the changeset viewer.