|
1 | | -// Flags: --expose-internals |
| 1 | +// Flags: --expose-internals --experimental-abortcontroller |
2 | 2 |
|
3 | 3 | 'use strict'; |
4 | 4 |
|
@@ -8,6 +8,7 @@ if (!common.hasCrypto) |
8 | 8 | const assert = require('assert'); |
9 | 9 | const h2 = require('http2'); |
10 | 10 | const { kSocket } = require('internal/http2/util'); |
| 11 | +const { kEvents } = require('internal/event_target'); |
11 | 12 | const Countdown = require('../common/countdown'); |
12 | 13 |
|
13 | 14 | { |
@@ -165,3 +166,76 @@ const Countdown = require('../common/countdown'); |
165 | 166 | req.on('close', common.mustCall(() => server.close())); |
166 | 167 | })); |
167 | 168 | } |
| 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 | +} |