GroupBy.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. 'use strict';
  2. var GetIntrinsic = require('get-intrinsic');
  3. var AddValueToKeyedGroup = require('./AddValueToKeyedGroup');
  4. var Call = require('es-abstract/2022/Call');
  5. var GetIterator = require('es-abstract/2022/GetIterator');
  6. var IsCallable = require('es-abstract/2022/IsCallable');
  7. var IteratorClose = require('./IteratorClose');
  8. var IteratorStep = require('./IteratorStep');
  9. var IteratorValue = require('es-abstract/2022/IteratorValue');
  10. var maxSafeInteger = require('es-abstract/helpers/maxSafeInteger');
  11. var RequireObjectCoercible = require('es-abstract/2022/RequireObjectCoercible');
  12. var ThrowCompletion = require('es-abstract/2022/ThrowCompletion');
  13. var ToPropertyKey = require('es-abstract/2022/ToPropertyKey');
  14. var $TypeError = GetIntrinsic('%TypeError%');
  15. module.exports = function GroupBy(items, callbackfn, coercion) {
  16. if (coercion !== 'property' && coercion !== 'zero') {
  17. throw new $TypeError('Assertion failed: `coercion` must be `"property"` or `"zero"`');
  18. }
  19. RequireObjectCoercible(items); // step 1
  20. if (!IsCallable(callbackfn)) { // step 2
  21. throw new $TypeError('`callbackfn` must be callable');
  22. }
  23. var groups = []; // step 3
  24. var iterator = GetIterator(items); // step 4
  25. var iteratorRecord = { // TODO: remove this once GetIterator is on ES2023+
  26. '[[Iterator]]': iterator,
  27. '[[NextMethod]]': iterator.next,
  28. '[[Done]]': false // eslint-disable-line sort-keys
  29. };
  30. var k = 0; // step 5
  31. // eslint-disable-next-line no-constant-condition
  32. while (true) { // step 6
  33. if (k >= maxSafeInteger) { // step 6.a
  34. var error = ThrowCompletion(new $TypeError('Iteration count exceeds the max safe integer value')); // step 6.a.i
  35. return IteratorClose(iteratorRecord, error); // step 6.a.ii
  36. }
  37. var next = IteratorStep(iteratorRecord); // step 6.b
  38. if (!next) { // step 6.c
  39. return groups; // step 6.c.i
  40. }
  41. var value = IteratorValue(next); // step 6.d
  42. var key;
  43. try {
  44. key = Call(callbackfn, undefined, [value, k]); // step 6.e
  45. } catch (e) {
  46. IteratorClose(iteratorRecord, ThrowCompletion(e)); // step 6.f
  47. }
  48. if (coercion === 'property') { // step 6.g
  49. try {
  50. key = ToPropertyKey(key); // step 6.g.i
  51. } catch (e) {
  52. IteratorClose(iteratorRecord, ThrowCompletion(e)); // step 6.g.ii
  53. }
  54. } else {
  55. if (coercion !== 'zero') {
  56. throw new $TypeError('Assertion failed: `coercion` should be `"zero"` here'); // step 6.h.i
  57. }
  58. if (key === 0) { // step 6.h.ii
  59. key = 0; // handle negative zero
  60. }
  61. }
  62. AddValueToKeyedGroup(groups, key, value); // step 6.i
  63. k += 1; // step 6.j
  64. }
  65. };