Skip to content

Commit 9208459

Browse files
🩹 fix: Make module and cjs build work.
1 parent 9bffb20 commit 9208459

7 files changed

+156
-33
lines changed

src/asyncIterableChain.js

+31-3
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,36 @@
55
* @param {AsyncIterable<AsyncIterable>} iterables - the input iterable of iterables.
66
* @returns {AsyncIterable} The chain of the input iterables.
77
*/
8-
export default async function* asyncIterableChain(iterables) {
9-
for await (const iterable of iterables) {
10-
for await (const item of iterable) yield item;
8+
export default function asyncIterableChain(iterables) {
9+
return new Chain(iterables);
10+
}
11+
12+
export class Chain {
13+
constructor(iterables) {
14+
this.iterators = iterables[Symbol.asyncIterator]();
15+
this.iterator = null;
16+
}
17+
18+
async next() {
19+
for (;;) {
20+
if (this.iterator === null) {
21+
// eslint-disable-next-line no-await-in-loop
22+
const {done, value} = await this.iterators.next();
23+
if (done) return {done: true};
24+
this.iterator = value[Symbol.asyncIterator]();
25+
}
26+
27+
// eslint-disable-next-line no-await-in-loop
28+
const {done, value} = await this.iterator.next();
29+
if (done) {
30+
this.iterator = null;
31+
} else {
32+
return {done: false, value};
33+
}
34+
}
35+
}
36+
37+
[Symbol.asyncIterator]() {
38+
return this;
1139
}
1240
}

src/asyncIterableMap.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import asyncIteratorMap from './asyncIteratorMap.js';
2+
13
/**
24
* Utility function to apply a sync callable to each item of an async iterable.
35
*
@@ -6,7 +8,6 @@
68
* @param {AsyncIterable} iterable - The iterable to process.
79
* @returns {AsyncIterable} The iterable of mapped values.
810
*/
9-
export default async function* asyncIterableMap(callable, iterable) {
10-
// Should the callable also be async ?
11-
for await (const item of iterable) yield callable(item);
11+
export default function asyncIterableMap(callable, iterable) {
12+
return asyncIteratorMap(callable, iterable[Symbol.asyncIterator]());
1213
}

src/asyncIterableToArray.js

+8-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@
77
*/
88
export default async function asyncIterableToArray(asyncIterable) {
99
const array = [];
10-
for await (const item of asyncIterable) array.push(item);
10+
const it = asyncIterable[Symbol.asyncIterator]();
11+
for (;;) {
12+
// eslint-disable-next-line no-await-in-loop
13+
const {done, value} = await it.next();
14+
if (done) break;
15+
array.push(value);
16+
}
17+
1118
return array;
1219
}

src/asyncIteratorMap.js

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
* Utility function to apply a sync callable to each item of an async iterator.
3+
*
4+
* @private
5+
* @param {Function} callable - The callable to apply.
6+
* @param {AsyncIterator} iterator - The iterator to process.
7+
* @returns {AsyncIterator} The iterator of mapped values.
8+
*/
9+
export default async function* asyncIteratorMap(callable, iterator) {
10+
// Should the callable also be async ?
11+
for (;;) {
12+
// eslint-disable-next-line no-await-in-loop
13+
const {done, value} = await iterator.next();
14+
if (done) break;
15+
yield callable(value);
16+
}
17+
}

src/exhaust.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,10 @@
33
* @param {Tape} tape - The tape to read from.
44
*/
55
export default async function exhaust(tape) {
6-
while ((await tape.read()) !== tape.eof); // eslint-disable-line no-await-in-loop
6+
// While ((await tape.read()) !== tape.eof); // eslint-disable-line no-await-in-loop
7+
for (;;) {
8+
// eslint-disable-next-line no-await-in-loop
9+
const token = await tape.read();
10+
if (token === tape.eof) return;
11+
}
712
}

src/fromReadStream.js

+23-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,35 @@
11
import fromAsyncIterable from './fromAsyncIterable.js';
22

3+
/**
4+
* Converts a ReadStream iterator to an async iterable of tokens.
5+
*
6+
* @private
7+
* @param {AsyncIterator} iterator - The ReadStream iterator to convert.
8+
* @returns {AsyncIterable} The converted iterable.
9+
*/
10+
export async function* _fromReadStreamIterator(iterator) {
11+
for (;;) {
12+
// eslint-disable-next-line no-await-in-loop
13+
const {done, value: chunk} = await iterator.next();
14+
if (done) break;
15+
const chunkIterator = chunk[Symbol.iterator]();
16+
for (;;) {
17+
const {done, value} = chunkIterator.next();
18+
if (done) break;
19+
yield value;
20+
}
21+
}
22+
}
23+
324
/**
425
* Converts a ReadStream object to an async iterable of tokens.
526
*
627
* @private
728
* @param {ReadStream} readStream - The ReadStream object to convert.
829
* @returns {AsyncIterable} The converted iterable.
930
*/
10-
export async function* _fromReadStream(readStream) {
11-
for await (const chunk of readStream) {
12-
for (const piece of chunk) yield piece;
13-
}
31+
export function _fromReadStream(readStream) {
32+
return _fromReadStreamIterator(readStream[Symbol.asyncIterator]());
1433
}
1534

1635
/**

src/split.js

+67-21
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import assert from 'assert';
12
import fromAsyncIterable from './fromAsyncIterable.js';
23
import exhaust from './exhaust.js';
34

@@ -13,6 +14,38 @@ export default function split(tape, sep) {
1314
return fromAsyncIterable(_split(tape, sep));
1415
}
1516

17+
export class Group {
18+
constructor(first, sep, tape) {
19+
this.first = first;
20+
this.sep = sep;
21+
this.tape = tape;
22+
this.state = 0;
23+
}
24+
25+
async next() {
26+
if (this.state === 0) {
27+
this.state = 1;
28+
return {done: false, value: this.first};
29+
}
30+
31+
if (this.state === 1) {
32+
const value = await this.tape.read();
33+
if (value !== this.tape.eof && !this.sep.has(value))
34+
return {done: false, value};
35+
this.sep = null;
36+
this.tape = null;
37+
this.state = 2;
38+
return {done: true};
39+
}
40+
41+
return {done: true};
42+
}
43+
44+
[Symbol.asyncIterator]() {
45+
return this;
46+
}
47+
}
48+
1649
/**
1750
* Same as {@link split}, but returns an iterable rather than a tape.
1851
*
@@ -21,32 +54,45 @@ export default function split(tape, sep) {
2154
* @param {Iterable} sep - An iterable of separators.
2255
* @returns {AsyncIterable} An iterable of tapes.
2356
*/
24-
export async function* _split(tape, sep) {
25-
const _sep = new Set(sep);
26-
27-
while (true) {
28-
const token = await tape.read(); // eslint-disable-line no-await-in-loop
29-
30-
if (token === tape.eof) break;
31-
32-
if (_sep.has(token)) continue;
57+
export function _split(tape, sep) {
58+
return new Split(tape, sep);
59+
}
3360

34-
const group = fromAsyncIterable(
35-
(async function* () {
36-
yield token;
61+
class Split {
62+
constructor(tape, sep) {
63+
this.tape = tape;
64+
this.sep = new Set(sep);
65+
this.group = null;
66+
this.state = 0;
67+
assert(!this.sep.has(this.tape.eof));
68+
}
3769

38-
while (true) {
39-
const token = await tape.read(); // eslint-disable-line no-await-in-loop
70+
async next() {
71+
if (this.state === 0) {
72+
if (this.group !== null) await exhaust(this.group);
73+
let token;
74+
do {
75+
// eslint-disable-next-line no-await-in-loop
76+
token = await this.tape.read();
77+
} while (this.sep.has(token));
4078

41-
if (_sep.has(token)) break;
79+
if (token === this.tape.eof) {
80+
this.tape = null;
81+
this.sep = null;
82+
this.group = null;
83+
this.state = 1;
84+
return {done: true};
85+
}
4286

43-
yield token;
44-
}
45-
})(),
46-
);
87+
assert(!this.sep.has(token));
88+
this.group = fromAsyncIterable(new Group(token, this.sep, this.tape));
89+
return {done: false, value: this.group};
90+
}
4791

48-
yield group;
92+
return {done: true};
93+
}
4994

50-
await exhaust(group); // eslint-disable-line no-await-in-loop
95+
[Symbol.asyncIterator]() {
96+
return this;
5197
}
5298
}

0 commit comments

Comments
 (0)