Skip to content

Commit

Permalink
Update es-iterator-helpers with Iterator.concat shim and fix typos
Browse files Browse the repository at this point in the history
  • Loading branch information
jdalton committed Oct 17, 2024
1 parent 423694b commit f686630
Show file tree
Hide file tree
Showing 25 changed files with 1,758 additions and 1,876 deletions.
2,550 changes: 876 additions & 1,674 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions packages/npm/es-iterator-helpers/Iterator.concat/auto.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/* empty */
3 changes: 3 additions & 0 deletions packages/npm/es-iterator-helpers/Iterator.concat/auto.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
'use strict'

require('./shim')()
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
declare function concat<T>(
...items: Iterable<T>[]
): Iterator<T> & { return(): IteratorResult<T> }
export = concat
89 changes: 89 additions & 0 deletions packages/npm/es-iterator-helpers/Iterator.concat/implementation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
'use strict'

const sentinel = Symbol('sentinel')

// Implementation based on the following spec:
// https://tc39.es/proposal-iterator-sequencing/#sec-iterator.concat
module.exports = function concat(...items) {
// Step 1: If called with `new`, throw an error.
if (new.target) {
throw new TypeError('`Iterator.concat` is not a constructor')
}
// Step 1: Initialize empty list for iterables.
const iterables = []
// Step 2: Validate each item and add to iterables list.
for (const item of items) {
// Step 2a: Ensure each item is an object.
if (item === null || typeof item !== 'object') {
throw new TypeError(
'`Iterator.concat` requires all arguments to be objects'
)
}
const method = item[Symbol.iterator]
// Step 2c: Ensure each item is iterable.
if (typeof method !== 'function') {
throw new TypeError(
'`Iterator.concat` requires all arguments to be iterable'
)
}
// Step 2d: Add to iterables list.
iterables.push({ OpenMethod: method, Iterable: item })
}
// Step 3: Initialize the inner iterator.
let innerIterator = sentinel
const closeIfAbrupt = (iterator, abruptCompletion) => {
if (iterator && typeof iterator.return === 'function') {
try {
// Step 3a.v.3.b: Close iterator on abrupt completion.
iterator.return()
} catch {
// If `return` throws, rethrow the original error.
throw abruptCompletion
}
}
throw abruptCompletion
}
// Step 3: Create a closure function to handle iteration.
let index = 0
const closure = () => {
// Step 3a: Iterate through each iterable.
while (index < iterables.length) {
const { Iterable, OpenMethod } = iterables[index]
if (innerIterator === sentinel) {
// Step 3a.i: Call the iterator method.
innerIterator = OpenMethod.call(Iterable)
// Step 3a.ii: Ensure iterator is an object.
if (typeof innerIterator !== 'object' || innerIterator === null) {
closeIfAbrupt(
innerIterator,
new TypeError('Iterator result is not an object')
)
}
}
// Step 3a.v.1: Get the next value.
const { done, value } = innerIterator.next()
// Step 3a.v.2: Check if done, move to next iterable if true.
if (done) {
innerIterator = sentinel
index += 1
} else {
// Step 3a.v.3.a: Yield the current value.
return { value, done: false }
}
}
// Step 3b: If all iterables are done, return completed.
return { value: undefined, done: true }
}
// Step 4: Return the iterator.
return {
[Symbol.iterator]: function () {
return this
},
next: closure,
return() {
// Step 3a.v.3.b: Handle abrupt generator close.
closeIfAbrupt(innerIterator, new Error('Generator closed abruptly'))
return { value: undefined, done: true }
}
}
}
10 changes: 10 additions & 0 deletions packages/npm/es-iterator-helpers/Iterator.concat/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Impl from './implementation'
declare const {
x: EsIteratorConcat
}: {
x: typeof Impl & {
getPolyfill(): typeof Impl
shim(): typeof Impl
}
}
export = EsIteratorConcat
25 changes: 25 additions & 0 deletions packages/npm/es-iterator-helpers/Iterator.concat/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
'use strict'

const getPolyfill = require('./polyfill')
const polyfill = getPolyfill()

const desc = value => ({
__proto__: null,
configurable: true,
value,
writable: true
})

module.exports = Object.defineProperties(
function concat(...args) {
return new.target ? new polyfill() : polyfill(...args)
},
{
getPolyfill: desc(getPolyfill),
implementation: desc(require('./implementation')),
shim: desc(require('./shim'))
}
)
module.exports.getPolyfill = module.exports.getPolyfill
module.exports.implementation = module.exports.implementation
module.exports.shim = module.exports.shim
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Impl from './implementation'
declare function getPolyfill(): () => typeof Impl
export = getPolyfill
8 changes: 8 additions & 0 deletions packages/npm/es-iterator-helpers/Iterator.concat/polyfill.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'use strict'

const impl = require('./implementation')
const Iterator = require('../Iterator/implementation')

module.exports = function getPolyfill() {
return typeof Iterator.concat === 'function' ? Iterator.concat : impl
}
3 changes: 3 additions & 0 deletions packages/npm/es-iterator-helpers/Iterator.concat/shim.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Impl from './implementation'
declare function shim(): () => typeof Impl
export = shim
20 changes: 20 additions & 0 deletions packages/npm/es-iterator-helpers/Iterator.concat/shim.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'use strict'

const getPolyfill = require('./polyfill')
const Iterator = require('../Iterator/implementation')

const { defineProperty: ObjectDefineProperty } = Object

module.exports = function shimIteratorConcat() {
const polyfill = getPolyfill()
if (Iterator.concat !== polyfill) {
ObjectDefineProperty(Iterator, 'concat', {
__proto__: null,
configurable: true,
enumerable: false,
value: polyfill,
writable: true
})
}
return polyfill
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,7 @@ const IteratorPrototype = require('../Iterator.prototype/implementation')
const { isIteratorNextCheckBuggy } = require('../shared')

module.exports = function getPolyfill() {
return isIteratorNextCheckBuggy ? impl : IteratorPrototype.drop
return isIteratorNextCheckBuggy(IteratorPrototype, 'drop', 0)
? impl
: IteratorPrototype.drop
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,7 @@ const IteratorPrototype = require('../Iterator.prototype/implementation')
const { isIteratorNextCheckBuggy } = require('../shared')

module.exports = function getPolyfill() {
return isIteratorNextCheckBuggy ? impl : IteratorPrototype.filter
return isIteratorNextCheckBuggy(IteratorPrototype, 'filter', () => {})
? impl
: IteratorPrototype.filter
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const { defineProperty: ObjectDefineProperty } = Object

module.exports = function shimIteratorProtoFilter() {
const polyfill = getPolyfill()
if (polyfill && IteratorPrototype.drop !== polyfill) {
if (polyfill && IteratorPrototype.filter !== polyfill) {
ObjectDefineProperty(IteratorPrototype, 'filter', {
__proto__: null,
configurable: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,7 @@ const IteratorPrototype = require('../Iterator.prototype/implementation')
const { isIteratorNextCheckBuggy } = require('../shared')

module.exports = function getPolyfill() {
return isIteratorNextCheckBuggy ? impl : IteratorPrototype.flatMap
return isIteratorNextCheckBuggy(IteratorPrototype, 'flatMap', () => {})
? impl
: IteratorPrototype.flatMap
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const { defineProperty: ObjectDefineProperty } = Object

module.exports = function shimIteratorProtoFlatMap() {
const polyfill = getPolyfill()
if (polyfill && IteratorPrototype.drop !== polyfill) {
if (polyfill && IteratorPrototype.flatMap !== polyfill) {
ObjectDefineProperty(IteratorPrototype, 'flatMap', {
__proto__: null,
configurable: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,7 @@ const IteratorPrototype = require('../Iterator.prototype/implementation')
const { isIteratorNextCheckBuggy } = require('../shared')

module.exports = function getPolyfill() {
return isIteratorNextCheckBuggy ? impl : IteratorPrototype.map
return isIteratorNextCheckBuggy(IteratorPrototype, 'map', () => {})
? impl
: IteratorPrototype.map
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const { defineProperty: ObjectDefineProperty } = Object

module.exports = function shimIteratorProtoMap() {
const polyfill = getPolyfill()
if (polyfill && IteratorPrototype.drop !== polyfill) {
if (polyfill && IteratorPrototype.map !== polyfill) {
ObjectDefineProperty(IteratorPrototype, 'map', {
__proto__: null,
configurable: true,
Expand Down
1 change: 1 addition & 0 deletions packages/npm/es-iterator-helpers/index.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[
"Iterator",
"Iterator.concat",
"Iterator.from",
"Iterator.prototype",
"Iterator.prototype.constructor",
Expand Down
Loading

0 comments on commit f686630

Please sign in to comment.