• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2
3const { mustCall, mustNotCall } = require('../common');
4const { Readable } = require('stream');
5const { strictEqual } = require('assert');
6
7async function asyncSupport() {
8  const finallyMustCall = mustCall();
9  const bodyMustCall = mustCall();
10
11  async function* infiniteGenerate() {
12    try {
13      while (true) yield 'a';
14    } finally {
15      finallyMustCall();
16    }
17  }
18
19  const stream = Readable.from(infiniteGenerate());
20
21  for await (const chunk of stream) {
22    bodyMustCall();
23    strictEqual(chunk, 'a');
24    break;
25  }
26}
27
28async function syncSupport() {
29  const finallyMustCall = mustCall();
30  const bodyMustCall = mustCall();
31
32  function* infiniteGenerate() {
33    try {
34      while (true) yield 'a';
35    } finally {
36      finallyMustCall();
37    }
38  }
39
40  const stream = Readable.from(infiniteGenerate());
41
42  for await (const chunk of stream) {
43    bodyMustCall();
44    strictEqual(chunk, 'a');
45    break;
46  }
47}
48
49async function syncPromiseSupport() {
50  const returnMustBeAwaited = mustCall();
51  const bodyMustCall = mustCall();
52
53  function* infiniteGenerate() {
54    try {
55      while (true) yield Promise.resolve('a');
56    } finally {
57      // eslint-disable-next-line no-unsafe-finally
58      return { then(cb) {
59        returnMustBeAwaited();
60        cb();
61      } };
62    }
63  }
64
65  const stream = Readable.from(infiniteGenerate());
66
67  for await (const chunk of stream) {
68    bodyMustCall();
69    strictEqual(chunk, 'a');
70    break;
71  }
72}
73
74async function syncRejectedSupport() {
75  const returnMustBeAwaited = mustCall();
76  const bodyMustNotCall = mustNotCall();
77  const catchMustCall = mustCall();
78  const secondNextMustNotCall = mustNotCall();
79
80  function* generate() {
81    try {
82      yield Promise.reject('a');
83      secondNextMustNotCall();
84    } finally {
85      // eslint-disable-next-line no-unsafe-finally
86      return { then(cb) {
87        returnMustBeAwaited();
88        cb();
89      } };
90    }
91  }
92
93  const stream = Readable.from(generate());
94
95  try {
96    for await (const chunk of stream) {
97      bodyMustNotCall(chunk);
98    }
99  } catch {
100    catchMustCall();
101  }
102}
103
104async function noReturnAfterThrow() {
105  const returnMustNotCall = mustNotCall();
106  const bodyMustNotCall = mustNotCall();
107  const catchMustCall = mustCall();
108  const nextMustCall = mustCall();
109
110  const stream = Readable.from({
111    [Symbol.asyncIterator]() { return this; },
112    async next() {
113      nextMustCall();
114      throw new Error('a');
115    },
116    async return() {
117      returnMustNotCall();
118      return { done: true };
119    },
120  });
121
122  try {
123    for await (const chunk of stream) {
124      bodyMustNotCall(chunk);
125    }
126  } catch {
127    catchMustCall();
128  }
129}
130
131async function closeStreamWhileNextIsPending() {
132  const finallyMustCall = mustCall();
133  const dataMustCall = mustCall();
134
135  let resolveDestroy;
136  const destroyed =
137    new Promise((resolve) => { resolveDestroy = mustCall(resolve); });
138  let resolveYielded;
139  const yielded =
140    new Promise((resolve) => { resolveYielded = mustCall(resolve); });
141
142  async function* infiniteGenerate() {
143    try {
144      while (true) {
145        yield 'a';
146        resolveYielded();
147        await destroyed;
148      }
149    } finally {
150      finallyMustCall();
151    }
152  }
153
154  const stream = Readable.from(infiniteGenerate());
155
156  stream.on('data', (data) => {
157    dataMustCall();
158    strictEqual(data, 'a');
159  });
160
161  yielded.then(() => {
162    stream.destroy();
163    resolveDestroy();
164  });
165}
166
167async function closeAfterNullYielded() {
168  const finallyMustCall = mustCall();
169  const dataMustCall = mustCall(3);
170
171  function* generate() {
172    try {
173      yield 'a';
174      yield 'a';
175      yield 'a';
176    } finally {
177      finallyMustCall();
178    }
179  }
180
181  const stream = Readable.from(generate());
182
183  stream.on('data', (chunk) => {
184    dataMustCall();
185    strictEqual(chunk, 'a');
186  });
187}
188
189Promise.all([
190  asyncSupport(),
191  syncSupport(),
192  syncPromiseSupport(),
193  syncRejectedSupport(),
194  noReturnAfterThrow(),
195  closeStreamWhileNextIsPending(),
196  closeAfterNullYielded(),
197]).then(mustCall());
198