Skip to content

Commit 8de4f9a

Browse files
committed
re-use IteratorResult objects when possible in Iterator.concat
tc39/proposal-iterator-sequencing#17 tc39/proposal-iterator-sequencing#18
1 parent 57ffe82 commit 8de4f9a

File tree

5 files changed

+56
-8
lines changed

5 files changed

+56
-8
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
- Added built-ins:
55
- `Error.isError`
66
- We have no bulletproof way to polyfill this method / check if the object is an error, so it's an enough naive implementation that is marked as `.sham`
7+
- Added [`Iterator` sequencing stage 2.7 proposal](https://github.com/tc39/proposal-iterator-sequencing):
8+
- Re-use `IteratorResult` objects when possible, [tc39/proposal-iterator-sequencing/17](https://github.com/tc39/proposal-iterator-sequencing/issues/17), [tc39/proposal-iterator-sequencing/18](https://github.com/tc39/proposal-iterator-sequencing/pull/18), December 2024 TC39 meeting
79
- Optimized `DataView.prototype.{ getFloat16, setFloat16 }` performance, [#1379](https://github.com/zloirock/core-js/pull/1379), thanks [**@LeviPesin**](https://github.com/LeviPesin)
810
- Dropped unneeded feature detection of non-standard `%TypedArray%.prototype.toSpliced`
911
- Dropped possible re-usage of some non-standard / early stage features (like `Math.scale`) available on global

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

+6-4
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,13 @@ var createIteratorProxyPrototype = function (IS_ITERATOR) {
2222
next: function next() {
2323
var state = getInternalState(this);
2424
// for simplification:
25-
// for `%WrapForValidIteratorPrototype%.next` our `nextHandler` returns `IterResultObject`
25+
// for `%WrapForValidIteratorPrototype%.next` or with `state.returnHandlerResult` our `nextHandler` returns `IterResultObject`
2626
// for `%IteratorHelperPrototype%.next` - just a value
2727
if (IS_ITERATOR) return state.nextHandler();
28+
if (state.done) return createIterResultObject(undefined, true);
2829
try {
29-
var result = state.done ? undefined : state.nextHandler();
30-
return createIterResultObject(result, state.done);
30+
var result = state.nextHandler();
31+
return state.returnHandlerResult ? result : createIterResultObject(result, state.done);
3132
} catch (error) {
3233
state.done = true;
3334
throw error;
@@ -57,13 +58,14 @@ var IteratorHelperPrototype = createIteratorProxyPrototype(false);
5758

5859
createNonEnumerableProperty(IteratorHelperPrototype, TO_STRING_TAG, 'Iterator Helper');
5960

60-
module.exports = function (nextHandler, IS_ITERATOR) {
61+
module.exports = function (nextHandler, IS_ITERATOR, RETURN_HANDLER_RESULT) {
6162
var IteratorProxy = function Iterator(record, state) {
6263
if (state) {
6364
state.iterator = record.iterator;
6465
state.next = record.next;
6566
} else state = record;
6667
state.type = IS_ITERATOR ? WRAP_FOR_VALID_ITERATOR : ITERATOR_HELPER;
68+
state.returnHandlerResult = !!RETURN_HANDLER_RESULT;
6769
state.nextHandler = nextHandler;
6870
state.counter = 0;
6971
state.done = false;

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

+4-3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ var aCallable = require('../internals/a-callable');
55
var anObject = require('../internals/an-object');
66
var getIteratorMethod = require('../internals/get-iterator-method');
77
var createIteratorProxy = require('../internals/iterator-create-proxy');
8+
var createIterResultObject = require('../internals/create-iter-result-object');
89

910
var $Array = Array;
1011

@@ -16,7 +17,7 @@ var IteratorProxy = createIteratorProxy(function () {
1617
var iterables = this.iterables;
1718
if (iterableIndex >= iterables.length) {
1819
this.done = true;
19-
return;
20+
return createIterResultObject(undefined, true);
2021
}
2122
var entry = iterables[iterableIndex];
2223
this.iterables[iterableIndex] = null;
@@ -29,9 +30,9 @@ var IteratorProxy = createIteratorProxy(function () {
2930
this.next = null;
3031
continue;
3132
}
32-
return result.value;
33+
return result;
3334
}
34-
});
35+
}, false, true);
3536

3637
// `Iterator.concat` method
3738
// https://github.com/tc39/proposal-iterator-sequencing

tests/unit-global/esnext.iterator.concat.js

+21
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,27 @@ QUnit.test('Iterator.concat', assert => {
6262
assert.deepEqual(iterator.return(), { done: true, value: undefined }, '.return with active inner iterator with return result');
6363
assert.true(called, 'inner .return called');
6464

65+
// https://github.com/tc39/proposal-iterator-sequencing/issues/17
66+
const oldIterResult = {
67+
done: false,
68+
value: 123,
69+
};
70+
const testIterator = {
71+
next() {
72+
return oldIterResult;
73+
},
74+
};
75+
const iterable = {
76+
[Symbol.iterator]() {
77+
return testIterator;
78+
},
79+
};
80+
iterator = concat(iterable);
81+
const iterResult = iterator.next();
82+
assert.same(iterResult.done, false);
83+
assert.same(iterResult.value, 123);
84+
assert.same(iterResult, oldIterResult);
85+
6586
assert.throws(() => concat(createIterator([1, 2, 3])), TypeError, 'non-iterable iterator #1');
6687
assert.throws(() => concat([], createIterator([1, 2, 3])), TypeError, 'non-iterable iterator #2');
6788
assert.throws(() => concat(''), TypeError, 'iterable non-object argument #1');

tests/unit-pure/esnext.iterator.concat.js

+23-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { createIterable, createIterator } from '../helpers/helpers.js';
22

33
import concat from 'core-js-pure/full/iterator/concat';
4-
import Iterator from 'core-js-pure/full/iterator';
4+
import Iterator from 'core-js-pure/es/iterator';
5+
import Symbol from 'core-js-pure/es/symbol';
56
import from from 'core-js-pure/es/array/from';
67

78
QUnit.test('Iterator.concat', assert => {
@@ -60,6 +61,27 @@ QUnit.test('Iterator.concat', assert => {
6061
assert.deepEqual(iterator.return(), { done: true, value: undefined }, '.return with active inner iterator with return result');
6162
assert.true(called, 'inner .return called');
6263

64+
// https://github.com/tc39/proposal-iterator-sequencing/issues/17
65+
const oldIterResult = {
66+
done: false,
67+
value: 123,
68+
};
69+
const testIterator = {
70+
next() {
71+
return oldIterResult;
72+
},
73+
};
74+
const iterable = {
75+
[Symbol.iterator]() {
76+
return testIterator;
77+
},
78+
};
79+
iterator = concat(iterable);
80+
const iterResult = iterator.next();
81+
assert.same(iterResult.done, false);
82+
assert.same(iterResult.value, 123);
83+
assert.same(iterResult, oldIterResult);
84+
6385
assert.throws(() => concat(createIterator([1, 2, 3])), TypeError, 'non-iterable iterator #1');
6486
assert.throws(() => concat([], createIterator([1, 2, 3])), TypeError, 'non-iterable iterator #2');
6587
assert.throws(() => concat(''), TypeError, 'iterable non-object argument #1');

0 commit comments

Comments
 (0)