1- // Flags: --expose-internals
1+ // Flags: --expose-internals --experimental-abortcontroller
22
33'use strict';
44
@@ -8,6 +8,7 @@ if (!common.hasCrypto)
88const assert = require('assert');
99const h2 = require('http2');
1010const { kSocket } = require('internal/http2/util');
11+ const { kEvents } = require('internal/event_target');
1112const Countdown = require('../common/countdown');
1213
1314{
@@ -165,3 +166,76 @@ const Countdown = require('../common/countdown');
165166 req.on('close', common.mustCall(() => server.close()));
166167 }));
167168}
169+
170+ // Destroy with AbortSignal
171+ {
172+ const server = h2.createServer();
173+ const controller = new AbortController();
174+
175+ server.on('stream', common.mustNotCall());
176+ server.listen(0, common.mustCall(() => {
177+ const client = h2.connect(`http://localhost:${server.address().port}`);
178+ client.on('close', common.mustCall());
179+
180+ const { signal } = controller;
181+ assert.strictEqual(signal[kEvents].get('abort'), undefined);
182+
183+ client.on('error', common.mustCall(() => {
184+ // After underlying stream dies, signal listener detached
185+ assert.strictEqual(signal[kEvents].get('abort'), undefined);
186+ }));
187+
188+ const req = client.request({}, { signal });
189+
190+ req.on('error', common.mustCall((err) => {
191+ assert.strictEqual(err.code, 'ABORT_ERR');
192+ assert.strictEqual(err.name, 'AbortError');
193+ }));
194+ req.on('close', common.mustCall(() => server.close()));
195+
196+ assert.strictEqual(req.aborted, false);
197+ assert.strictEqual(req.destroyed, false);
198+ // Signal listener attached
199+ assert.strictEqual(signal[kEvents].get('abort').size, 1);
200+
201+ controller.abort();
202+
203+ assert.strictEqual(req.aborted, false);
204+ assert.strictEqual(req.destroyed, true);
205+ }));
206+ }
207+ // Pass an already destroyed signal to abort immediately.
208+ {
209+ const server = h2.createServer();
210+ const controller = new AbortController();
211+
212+ server.on('stream', common.mustNotCall());
213+ server.listen(0, common.mustCall(() => {
214+ const client = h2.connect(`http://localhost:${server.address().port}`);
215+ client.on('close', common.mustCall());
216+
217+ const { signal } = controller;
218+ controller.abort();
219+
220+ assert.strictEqual(signal[kEvents].get('abort'), undefined);
221+
222+ client.on('error', common.mustCall(() => {
223+ // After underlying stream dies, signal listener detached
224+ assert.strictEqual(signal[kEvents].get('abort'), undefined);
225+ }));
226+
227+ const req = client.request({}, { signal });
228+ // Signal already aborted, so no event listener attached.
229+ assert.strictEqual(signal[kEvents].get('abort'), undefined);
230+
231+ assert.strictEqual(req.aborted, false);
232+ // Destroyed on same tick as request made
233+ assert.strictEqual(req.destroyed, true);
234+
235+ req.on('error', common.mustCall((err) => {
236+ assert.strictEqual(err.code, 'ABORT_ERR');
237+ assert.strictEqual(err.name, 'AbortError');
238+ }));
239+ req.on('close', common.mustCall(() => server.close()));
240+ }));
241+ }
0 commit comments