Skip to content

Commit beb07f3

Browse files
Claudemattcosta7
andcommitted
Address PR review comments
- Fix test files to check isPolyfilled() === false (4 files) - Fix iterator helpers to inherit from Iterator.prototype for proper method chaining - Updated map, filter, take, drop, flatMap to use Object.create(iteratorPrototype) - Ensure globalThis.Iterator is created if it doesn't exist in apply() - All 56 tests still passing Co-authored-by: mattcosta7 <8616962+mattcosta7@users.noreply.github.com>
1 parent 0a06e72 commit beb07f3

5 files changed

Lines changed: 107 additions & 99 deletions

File tree

src/iterator-helpers.ts

Lines changed: 103 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -16,98 +16,102 @@ function map<T, U>(this: Iterator<T>, mapper: (value: T, index: number) => U): I
1616
// eslint-disable-next-line @typescript-eslint/no-this-alias
1717
const iterator = this
1818
let index = 0
19-
return {
20-
next() {
21-
const result = iterator.next()
22-
if (result.done) {
23-
return {done: true, value: undefined} as IteratorReturnResult<undefined>
24-
}
25-
return {done: false, value: mapper(result.value, index++)}
26-
},
27-
return(value?: U) {
28-
if (iterator.return) {
29-
iterator.return()
30-
}
31-
return {done: true, value} as IteratorReturnResult<U>
32-
},
33-
} as Iterator<U>
19+
const iteratorPrototype = getIteratorPrototype()
20+
const result = Object.create(iteratorPrototype || {}) as Iterator<U>
21+
result.next = function () {
22+
const res = iterator.next()
23+
if (res.done) {
24+
return {done: true, value: undefined} as IteratorReturnResult<undefined>
25+
}
26+
return {done: false, value: mapper(res.value, index++)}
27+
}
28+
result.return = function (value?: U) {
29+
if (iterator.return) {
30+
iterator.return()
31+
}
32+
return {done: true, value} as IteratorReturnResult<U>
33+
}
34+
return result
3435
}
3536

3637
/*#__PURE__*/
3738
function filter<T>(this: Iterator<T>, predicate: (value: T, index: number) => boolean): Iterator<T> {
3839
// eslint-disable-next-line @typescript-eslint/no-this-alias
3940
const iterator = this
4041
let index = 0
41-
return {
42-
next() {
43-
// eslint-disable-next-line no-constant-condition
44-
while (true) {
45-
const result = iterator.next()
46-
if (result.done) {
47-
return {done: true, value: undefined} as IteratorReturnResult<undefined>
48-
}
49-
if (predicate(result.value, index++)) {
50-
return result
51-
}
42+
const iteratorPrototype = getIteratorPrototype()
43+
const result = Object.create(iteratorPrototype || {}) as Iterator<T>
44+
result.next = function () {
45+
// eslint-disable-next-line no-constant-condition
46+
while (true) {
47+
const res = iterator.next()
48+
if (res.done) {
49+
return {done: true, value: undefined} as IteratorReturnResult<undefined>
5250
}
53-
},
54-
return(value?: T) {
55-
if (iterator.return) {
56-
iterator.return()
51+
if (predicate(res.value, index++)) {
52+
return res
5753
}
58-
return {done: true, value} as IteratorReturnResult<T>
59-
},
60-
} as Iterator<T>
54+
}
55+
}
56+
result.return = function (value?: T) {
57+
if (iterator.return) {
58+
iterator.return()
59+
}
60+
return {done: true, value} as IteratorReturnResult<T>
61+
}
62+
return result
6163
}
6264

6365
/*#__PURE__*/
6466
function take<T>(this: Iterator<T>, limit: number): Iterator<T> {
6567
// eslint-disable-next-line @typescript-eslint/no-this-alias
6668
const iterator = this
6769
let remaining = limit
68-
return {
69-
next() {
70-
if (remaining <= 0) {
71-
if (iterator.return) {
72-
iterator.return()
73-
}
74-
return {done: true, value: undefined} as IteratorReturnResult<undefined>
75-
}
76-
remaining--
77-
return iterator.next()
78-
},
79-
return(value?: T) {
70+
const iteratorPrototype = getIteratorPrototype()
71+
const result = Object.create(iteratorPrototype || {}) as Iterator<T>
72+
result.next = function () {
73+
if (remaining <= 0) {
8074
if (iterator.return) {
8175
iterator.return()
8276
}
83-
return {done: true, value} as IteratorReturnResult<T>
84-
},
85-
} as Iterator<T>
77+
return {done: true, value: undefined} as IteratorReturnResult<undefined>
78+
}
79+
remaining--
80+
return iterator.next()
81+
}
82+
result.return = function (value?: T) {
83+
if (iterator.return) {
84+
iterator.return()
85+
}
86+
return {done: true, value} as IteratorReturnResult<T>
87+
}
88+
return result
8689
}
8790

8891
/*#__PURE__*/
8992
function drop<T>(this: Iterator<T>, limit: number): Iterator<T> {
9093
// eslint-disable-next-line @typescript-eslint/no-this-alias
9194
const iterator = this
9295
let remaining = limit
93-
return {
94-
next() {
95-
while (remaining > 0) {
96-
const result = iterator.next()
97-
if (result.done) {
98-
return {done: true, value: undefined} as IteratorReturnResult<undefined>
99-
}
100-
remaining--
101-
}
102-
return iterator.next()
103-
},
104-
return(value?: T) {
105-
if (iterator.return) {
106-
iterator.return()
96+
const iteratorPrototype = getIteratorPrototype()
97+
const result = Object.create(iteratorPrototype || {}) as Iterator<T>
98+
result.next = function () {
99+
while (remaining > 0) {
100+
const res = iterator.next()
101+
if (res.done) {
102+
return {done: true, value: undefined} as IteratorReturnResult<undefined>
107103
}
108-
return {done: true, value} as IteratorReturnResult<T>
109-
},
110-
} as Iterator<T>
104+
remaining--
105+
}
106+
return iterator.next()
107+
}
108+
result.return = function (value?: T) {
109+
if (iterator.return) {
110+
iterator.return()
111+
}
112+
return {done: true, value} as IteratorReturnResult<T>
113+
}
114+
return result
111115
}
112116

113117
/*#__PURE__*/
@@ -116,38 +120,38 @@ function flatMap<T, U>(this: Iterator<T>, mapper: (value: T, index: number) => I
116120
const iterator = this
117121
let index = 0
118122
let innerIterator: Iterator<U> | null = null
119-
120-
return {
121-
next() {
122-
// eslint-disable-next-line no-constant-condition
123-
while (true) {
124-
if (innerIterator) {
125-
const result = innerIterator.next()
126-
if (!result.done) {
127-
return result
128-
}
129-
innerIterator = null
123+
const iteratorPrototype = getIteratorPrototype()
124+
const result = Object.create(iteratorPrototype || {}) as Iterator<U>
125+
result.next = function () {
126+
// eslint-disable-next-line no-constant-condition
127+
while (true) {
128+
if (innerIterator) {
129+
const res = innerIterator.next()
130+
if (!res.done) {
131+
return res
130132
}
131-
132-
const result = iterator.next()
133-
if (result.done) {
134-
return {done: true, value: undefined} as IteratorReturnResult<undefined>
135-
}
136-
137-
const mapped = mapper(result.value, index++)
138-
innerIterator = Symbol.iterator in mapped ? mapped[Symbol.iterator]() : (mapped as Iterator<U>)
133+
innerIterator = null
139134
}
140-
},
141-
return(value?: U) {
142-
if (innerIterator?.return) {
143-
innerIterator.return()
144-
}
145-
if (iterator.return) {
146-
iterator.return()
135+
136+
const res = iterator.next()
137+
if (res.done) {
138+
return {done: true, value: undefined} as IteratorReturnResult<undefined>
147139
}
148-
return {done: true, value} as IteratorReturnResult<U>
149-
},
150-
} as Iterator<U>
140+
141+
const mapped = mapper(res.value, index++)
142+
innerIterator = Symbol.iterator in mapped ? mapped[Symbol.iterator]() : (mapped as Iterator<U>)
143+
}
144+
}
145+
result.return = function (value?: U) {
146+
if (innerIterator?.return) {
147+
innerIterator.return()
148+
}
149+
if (iterator.return) {
150+
iterator.return()
151+
}
152+
return {done: true, value} as IteratorReturnResult<U>
153+
}
154+
return result
151155
}
152156

153157
/*#__PURE__*/
@@ -353,7 +357,11 @@ export function apply(): void {
353357
}
354358
}
355359

356-
const IteratorConstructor = (globalThis as typeof globalThis & {Iterator?: {from?: unknown}}).Iterator
360+
let IteratorConstructor = (globalThis as typeof globalThis & {Iterator?: {from?: unknown}}).Iterator
361+
if (!IteratorConstructor) {
362+
;(globalThis as typeof globalThis & {Iterator?: unknown}).Iterator = {}
363+
IteratorConstructor = (globalThis as typeof globalThis & {Iterator?: {from?: unknown}}).Iterator
364+
}
357365
if (IteratorConstructor && !('from' in IteratorConstructor)) {
358366
Object.assign(IteratorConstructor, {from: iteratorFrom})
359367
}

test/iterator-helpers.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ describe('Iterator helpers', () => {
88
expect(isPolyfilled).to.be.a('function')
99
expect(apply).to.be.a('function')
1010
expect(isSupported()).to.be.a('boolean')
11-
expect(isPolyfilled()).to.be.a('boolean')
11+
expect(isPolyfilled()).to.equal(false)
1212
})
1313

1414
// Helper to create an iterator from an array

test/map-groupby.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ describe('Map.groupBy', () => {
77
expect(isPolyfilled).to.be.a('function')
88
expect(apply).to.be.a('function')
99
expect(isSupported()).to.be.a('boolean')
10-
expect(isPolyfilled()).to.be.a('boolean')
10+
expect(isPolyfilled()).to.equal(false)
1111
})
1212

1313
it('groups items by key', () => {

test/object-groupby.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ describe('Object.groupBy', () => {
77
expect(isPolyfilled).to.be.a('function')
88
expect(apply).to.be.a('function')
99
expect(isSupported()).to.be.a('boolean')
10-
expect(isPolyfilled()).to.be.a('boolean')
10+
expect(isPolyfilled()).to.equal(false)
1111
})
1212

1313
it('groups items by key', () => {

test/promise-try.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ describe('Promise.try', () => {
77
expect(isPolyfilled).to.be.a('function')
88
expect(apply).to.be.a('function')
99
expect(isSupported()).to.be.a('boolean')
10-
expect(isPolyfilled()).to.be.a('boolean')
10+
expect(isPolyfilled()).to.equal(false)
1111
})
1212

1313
it('resolves with the return value of a successful function', async () => {

0 commit comments

Comments
 (0)