Skip to content

Commit 5cc3f7a

Browse files
slowcheetahzloirock
authored andcommitted
Refactoring
1 parent 884e103 commit 5cc3f7a

16 files changed

+276
-46
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@
3333
- `Error.isError`
3434
- Moved to stable ES, [May 2025 TC39 meeting](https://github.com/tc39/proposals/commit/a5d4bb99d79f328533d0c36b0cd20597fa12c7a8)
3535
- Added `es.` namespace module, `/es/` and `/stable/` namespaces entries
36+
- Added [Joint iteration stage 2.7 proposal](https://github.com/tc39/proposal-joint-iteration):
37+
- Built-ins:
38+
- `Iterator.zip`
39+
- `Iterator.zipKeyed`
3640
- [`Math.clamp` proposal](https://github.com/tc39/proposal-math-clamp):
3741
- Built-ins:
3842
- `Math.clamp`

README.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ structuredClone(new Set([1, 2, 3])); // => new Set([1, 2, 3])
171171
- [`Symbol.metadata` for decorators metadata proposal](#symbolmetadata-for-decorators-metadata-proposal)
172172
- [Stage 2.7 proposals](#stage-27-proposals)
173173
- [`Iterator` sequencing](#iterator-sequencing)
174+
- [Joint iteration](#joint-iteration)
174175
- [`Map` upsert](#map-upsert)
175176
- [Stage 2 proposals](#stage-2-proposals)
176177
- [`AsyncIterator` helpers](#asynciterator-helpers)
@@ -2766,6 +2767,57 @@ Iterator.concat([0, 1].values(), [2, 3], function * () {
27662767
}()).toArray(); // => [0, 1, 2, 3, 4, 5]
27672768
```
27682769

2770+
##### [Joint iteration](https://github.com/tc39/proposal-joint-iteration)[](#index)
2771+
Modules [esnext.iterator.zip](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.iterator.zip.js), [esnext.iterator.zip-keyed](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.iterator.zip-keyed.js)
2772+
```ts
2773+
class Iterator {
2774+
zip<T extends readonly Iterable<unknown>[]>(
2775+
iterables: T,
2776+
options?: {
2777+
mode?: 'shortest' | 'longest' | 'strict';
2778+
padding?: { [K in keyof T]?: T[K] extends Iterable<infer U> ? U : never };
2779+
}
2780+
): IterableIterator<{ [K in keyof T]: T[K] extends Iterable<infer U> ? U : never }>;
2781+
zipKeyed<K extends PropertyKey, V extends Record<K, Iterable<unknown>>>(
2782+
iterables: V,
2783+
options?: {
2784+
mode?: 'shortest' | 'longest' | 'strict';
2785+
padding?: { [P in keyof V]?: V[P] extends Iterable<infer U> ? U : never };
2786+
}
2787+
): IterableIterator<{ [P in keyof V]: V[P] extends Iterable<infer U> ? U : never }>;
2788+
}
2789+
```
2790+
[*CommonJS entry points:*](#commonjs-api)
2791+
```
2792+
core-js/proposals/joint-iteration
2793+
core-js(-pure)/full/iterator/zip
2794+
core-js(-pure)/full/iterator/zip-keyed
2795+
```
2796+
[*Example*](https://tinyurl.com/vutnf2nu):
2797+
```js
2798+
Iterator.zip([
2799+
[0, 1, 2],
2800+
[3, 4, 5],
2801+
]).toArray(); // => [[0, 3], [1, 4], [2, 5]]
2802+
2803+
Iterator.zipKeyed({
2804+
a: [0, 1, 2],
2805+
b: [3, 4, 5, 6],
2806+
c: [7, 8, 9],
2807+
}, {
2808+
mode: 'longest',
2809+
padding: { c: 10 },
2810+
}).toArray();
2811+
/*
2812+
[
2813+
{ a: 0, b: 3, c: 7 },
2814+
{ a: 1, b: 4, c: 8 },
2815+
{ a: 2, b: 5, c: 9 },
2816+
{ a: undefined, b: 6, c: 10 },
2817+
];
2818+
*/
2819+
```
2820+
27692821
##### [`Map` upsert](https://github.com/thumbsupep/proposal-upsert)[](#index)
27702822
Modules [`esnext.map.get-or-insert`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.map.get-or-insert.js), [`esnext.map.get-or-insert-computed`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.map.get-or-insert-computed.js), [`esnext.weak-map.get-or-insert`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.weak-map.get-or-insert.js) and [`esnext.weak-map.get-or-insert-computed`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.weak-map.get-or-insert-computed.js)
27712823
```ts

packages/core-js/full/iterator/zip-keyed.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
'use strict';
2+
require('../../modules/es.array.iterator');
23
require('../../modules/es.object.to-string');
34
require('../../modules/es.object.create');
45
require('../../modules/es.iterator.constructor');
56
require('../../modules/es.reflect.own-keys');
7+
require('../../modules/web.dom-collections.iterator');
68
require('../../modules/esnext.iterator.zip-keyed');
79

810
var entryUnbind = require('../../internals/entry-unbind');

packages/core-js/full/iterator/zip.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
'use strict';
2+
require('../../modules/es.array.iterator');
23
require('../../modules/es.object.to-string');
34
require('../../modules/es.iterator.constructor');
5+
require('../../modules/web.dom-collections.iterator');
46
require('../../modules/esnext.iterator.zip');
57

68
var entryUnbind = require('../../internals/entry-unbind');
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
'use strict';
2+
var getIterator = require('../internals/get-iterator');
3+
var getIteratorDirect = require('../internals/get-iterator-direct');
4+
5+
module.exports = function (argument) {
6+
return getIteratorDirect(getIterator(argument));
7+
};

packages/core-js/internals/get-padding-option.js

Lines changed: 0 additions & 10 deletions
This file was deleted.

packages/core-js/internals/iterator-close-all.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ module.exports = function (iters, kind, value) {
55
for (var i = iters.length - 1; i >= 0; i--) {
66
if (iters[i] === undefined) continue;
77
try {
8-
value = iteratorClose(iters[i], kind, value);
8+
value = iteratorClose(iters[i].iterator, kind, value);
99
} catch (error) {
1010
kind = 'throw';
1111
value = error;

packages/core-js/internals/iterator-create-proxy.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ var getMethod = require('../internals/get-method');
99
var IteratorPrototype = require('../internals/iterators-core').IteratorPrototype;
1010
var createIterResultObject = require('../internals/create-iter-result-object');
1111
var iteratorClose = require('../internals/iterator-close');
12+
var iteratorCloseAll = require('./iterator-close-all');
1213

1314
var TO_STRING_TAG = wellKnownSymbol('toStringTag');
1415
var ITERATOR_HELPER = 'IteratorHelper';
@@ -47,6 +48,11 @@ var createIteratorProxyPrototype = function (IS_ITERATOR) {
4748
} catch (error) {
4849
return iteratorClose(iterator, 'throw', error);
4950
}
51+
if (state.openIters) try {
52+
iteratorCloseAll(state.openIters, 'normal');
53+
} catch (error) {
54+
return iteratorClose(iterator, 'throw', error);
55+
}
5056
if (iterator) iteratorClose(iterator, 'normal');
5157
return createIterResultObject(undefined, true);
5258
}

packages/core-js/internals/iterator-zip.js

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,28 +39,32 @@ var IteratorProxy = createIteratorProxy(function () {
3939
}
4040
if (done) {
4141
openIters[i] = undefined;
42+
this.openItersCount--;
4243
if (mode === 'shortest') {
4344
this.done = true;
44-
return iteratorCloseAll(openIters, 'return', undefined);
45+
return iteratorCloseAll(openIters, 'normal', undefined);
4546
}
4647
if (mode === 'strict') {
4748
if (i) {
4849
this.done = true;
4950
return iteratorCloseAll(openIters, 'throw', new $TypeError(ITERATOR_IS_EXHAUSTED));
5051
}
5152

52-
var open;
53+
var open, openDone;
5354
for (var k = 1; k < iterCount; k++) {
5455
// eslint-disable-next-line max-depth -- specification case
5556
try {
5657
open = call(iters[k].next, iters[k].iterator);
58+
openDone = open.done;
59+
open = open.value;
5760
} catch (error) {
5861
openIters[k] = undefined;
5962
return iteratorCloseAll(openIters, 'throw', open);
6063
}
6164
// eslint-disable-next-line max-depth -- specification case
62-
if (!open.value) {
65+
if (openDone) {
6366
openIters[k] = undefined;
67+
this.openItersCount--;
6468
} else {
6569
this.done = true;
6670
return iteratorCloseAll(openIters, 'throw', new $TypeError(ITERATOR_IS_EXHAUSTED));
@@ -69,13 +73,7 @@ var IteratorProxy = createIteratorProxy(function () {
6973
this.done = true;
7074
return;
7175
}
72-
var isEmptyOpenIters = true;
73-
for (var j = 0; j < openIters.length; j++) {
74-
if (openIters[j] === undefined) continue;
75-
isEmptyOpenIters = false;
76-
break;
77-
}
78-
if (isEmptyOpenIters) {
76+
if (!this.openItersCount) {
7977
this.done = true;
8078
return;
8179
}
@@ -91,12 +89,11 @@ var IteratorProxy = createIteratorProxy(function () {
9189

9290
module.exports = function (iters, mode, padding, finishResults) {
9391
var iterCount = iters.length;
94-
var openIters = slice(iters, 0);
95-
9692
return new IteratorProxy({
9793
iters: iters,
9894
iterCount: iterCount,
99-
openIters: openIters,
95+
openIters: slice(iters, 0),
96+
openItersCount: iterCount,
10097
mode: mode,
10198
padding: padding,
10299
finishResults: finishResults

packages/core-js/modules/esnext.iterator.zip-keyed.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ var getBuiltIn = require('../internals/get-built-in');
77
var getOwnPropertyDescriptor = require('../internals/object-get-own-property-descriptor').f;
88
var getIteratorFlattenable = require('../internals/get-iterator-flattenable');
99
var getModeOption = require('../internals/get-mode-option');
10-
var getPaddingOption = require('../internals/get-padding-option');
1110
var isDataDescriptor = require('../internals/is-data-descriptor');
1211
var iteratorCloseAll = require('../internals/iterator-close-all');
1312
var iteratorZip = require('../internals/iterator-zip');
@@ -25,7 +24,7 @@ $({ target: 'Iterator', stat: true, forced: true }, {
2524
var options = arguments.length > 1 ? arguments[1] : undefined;
2625
anObjectOrUndefined(options);
2726
var mode = getModeOption(options);
28-
var paddingOption = mode === 'longest' ? getPaddingOption(options) : undefined;
27+
var paddingOption = mode === 'longest' ? anObjectOrUndefined(options && options.padding) : undefined;
2928

3029
var iters = [];
3130
var padding = [];
@@ -40,6 +39,7 @@ $({ target: 'Iterator', stat: true, forced: true }, {
4039
return iteratorCloseAll(iters, 'throw', error);
4140
}
4241
if (!desc || !desc.enumerable) continue;
42+
value = undefined;
4343
if (isDataDescriptor(desc)) {
4444
value = desc.value;
4545
} else {
@@ -82,8 +82,8 @@ $({ target: 'Iterator', stat: true, forced: true }, {
8282

8383
var finishResults = function (results) {
8484
var obj = create(null);
85-
for (i = 0; i < iterCount; i++) {
86-
obj[keys[i]] = results[i];
85+
for (var j = 0; j < iterCount; j++) {
86+
obj[keys[j]] = results[j];
8787
}
8888
return obj;
8989
};

packages/core-js/modules/esnext.iterator.zip.js

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@ var $ = require('../internals/export');
33
var anObject = require('../internals/an-object');
44
var anObjectOrUndefined = require('../internals/an-object-or-undefined');
55
var call = require('../internals/function-call');
6-
var getIterator = require('../internals/get-iterator');
6+
var getIteratorRecord = require('../internals/get-iterator-record');
77
var getIteratorFlattenable = require('../internals/get-iterator-flattenable');
88
var getModeOption = require('../internals/get-mode-option');
9-
var getPaddingOption = require('../internals/get-padding-option');
109
var iteratorClose = require('../internals/iterator-close');
1110
var iteratorCloseAll = require('../internals/iterator-close-all');
1211
var iteratorZip = require('../internals/iterator-zip');
@@ -23,52 +22,54 @@ $({ target: 'Iterator', stat: true, forced: true }, {
2322
var options = arguments.length > 1 ? arguments[1] : undefined;
2423
anObjectOrUndefined(options);
2524
var mode = getModeOption(options);
26-
var paddingOption = mode === 'longest' ? getPaddingOption(options) : undefined;
25+
var paddingOption = mode === 'longest' ? anObjectOrUndefined(options && options.padding) : undefined;
2726

2827
var iters = [];
2928
var padding = [];
30-
var inputIter = getIterator(iterables);
31-
var iter, done, result;
29+
var inputIter = getIteratorRecord(iterables);
30+
var iter, done, next;
3231
while (!done) {
3332
try {
34-
result = anObject(call(inputIter.next, inputIter));
35-
done = result.done;
33+
next = anObject(call(inputIter.next, inputIter.iterator));
34+
done = next.done;
3635
} catch (error) {
3736
return iteratorCloseAll(iters, 'throw', error);
3837
}
3938
if (!done) {
4039
try {
41-
iter = getIteratorFlattenable(result.value, true);
40+
iter = getIteratorFlattenable(next.value, true);
4241
} catch (error) {
43-
return iteratorCloseAll(concat([inputIter], iters), 'throw', error);
42+
return iteratorCloseAll(concat([inputIter.iterator], iters), 'throw', error);
4443
}
4544
push(iters, iter);
4645
}
4746
}
4847

4948
var iterCount = iters.length;
50-
var i, paddingIter;
49+
var i, paddingDone, paddingIter;
5150
if (mode === 'longest') {
5251
if (paddingOption === undefined) {
5352
for (i = 0; i < iterCount; i++) push(padding, undefined);
5453
} else {
5554
try {
56-
paddingIter = getIterator(paddingOption);
55+
paddingIter = getIteratorRecord(paddingOption);
5756
} catch (error) {
5857
return iteratorCloseAll(iters, 'throw', error);
5958
}
6059
var usingIterator = true;
6160
for (i = 0; i < iterCount; i++) {
6261
if (usingIterator) {
6362
try {
64-
result = anObject(call(paddingIter.next, paddingIter));
63+
next = anObject(call(paddingIter.next, paddingIter.iterator));
64+
paddingDone = next.done;
65+
next = next.value;
6566
} catch (error) {
6667
return iteratorCloseAll(iters, 'throw', error);
6768
}
68-
if (result.done) {
69+
if (paddingDone) {
6970
usingIterator = false;
7071
} else {
71-
push(padding, result.value);
72+
push(padding, next);
7273
}
7374
} else {
7475
push(padding, undefined);
@@ -77,7 +78,7 @@ $({ target: 'Iterator', stat: true, forced: true }, {
7778

7879
if (usingIterator) {
7980
try {
80-
iteratorClose(paddingIter, 'normal');
81+
iteratorClose(paddingIter.iterator, 'normal');
8182
} catch (error) {
8283
return iteratorCloseAll(iters, 'throw', error);
8384
}

tests/compat/tests.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1847,7 +1847,7 @@ GLOBAL.tests = {
18471847
'esnext.iterator.zip': function () {
18481848
return Iterator.zip;
18491849
},
1850-
'esnext.iterator.zipKeyed': function () {
1850+
'esnext.iterator.zip-keyed': function () {
18511851
return Iterator.zipKeyed;
18521852
},
18531853
'esnext.json.is-raw-json': NATIVE_RAW_JSON,

tests/unit-global/esnext.iterator.zip-keyed.js

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
const { from } = Array;
1+
import { createIterator } from '../helpers/helpers.js';
2+
import { DESCRIPTORS } from '../helpers/constants.js';
23

34
QUnit.test('Iterator.zipKeyed', assert => {
45
const { zipKeyed } = Iterator;
6+
const { from } = Array;
7+
const { defineProperty } = Object;
58

69
assert.isFunction(zipKeyed);
710
assert.arity(zipKeyed, 1);
@@ -17,4 +20,24 @@ QUnit.test('Iterator.zipKeyed', assert => {
1720
assert.deepEqual(from(result), [{ a: 0, b: 3, c: 7 }, { a: 1, b: 4, c: 8 }, { a: 2, b: 5, c: 9 }, { a: undefined, b: 6, c: 10 }]);
1821
result = zipKeyed({ a: [0, 1, 2], b: [3, 4, 5, 6], c: [7, 8, 9] }, { mode: 'strict' });
1922
assert.throws(() => from(result), TypeError);
23+
24+
if (DESCRIPTORS) {
25+
let obj = {};
26+
defineProperty(obj, 'a', { get: () => [0, 1, 2], enumerable: true });
27+
defineProperty(obj, 'b', { get: () => [3, 4, 5], enumerable: true });
28+
defineProperty(obj, 'c', { get: () => [7, 8, 9], enumerable: true });
29+
defineProperty(obj, Symbol('d'), { get: () => [10, 11, 12] });
30+
assert.deepEqual(from(zipKeyed(obj)), [{ a: 0, b: 3, c: 7 }, { a: 1, b: 4, c: 8 }, { a: 2, b: 5, c: 9 }]);
31+
32+
const it = createIterator([1, 2], {
33+
return() {
34+
this.called = true;
35+
return { done: true, value: undefined };
36+
},
37+
});
38+
obj = { a: it };
39+
defineProperty(obj, 'b', { get: () => { throw new Error(); }, enumerable: true });
40+
assert.throws(() => from(zipKeyed(obj)), Error);
41+
assert.true(it.called, 'iterator return called');
42+
}
2043
});

0 commit comments

Comments
 (0)