Commit 1f26576a3f1 for nodejs

commit 1f26576a3f13b8cc0d09b443efcfc071c667b35f
Author: Lazizbek Ergashev <lazerg2@gmail.com>
Date:   Tue Sep 29 15:27:53 2026 +0500

    http2: submit RST_STREAM before emitting 'aborted'

    Signed-off-by: lazerg <lazerg2@gmail.com>
    PR-URL: https://github.com/nodejs/node/pull/66314
    Fixes: https://github.com/nodejs/node/issues/66306
    Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
    Reviewed-By: Tim Perry <pimterry@gmail.com>

diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js
index 1774808da13..9f14c5f2aef 100644
--- a/lib/internal/http2/core.js
+++ b/lib/internal/http2/core.js
@@ -2153,14 +2153,7 @@ function closeStream(stream, code, rstStreamStatus = kSubmitRstStream) {
   stream.setTimeout(0);
   stream.removeAllListeners('timeout');

-  // Emit 'aborted' if the user hadn't ended the writable yet. This is
-  // unusual and doesn't match 'error' but is deprecated & preserved for
-  // backward compat (DEP0207).
   const { ending } = stream._writableState;
-  if (!ending && !stream.aborted) {
-    state.flags |= STREAM_FLAGS_ABORTED;
-    stream.emit('aborted');
-  }

   if (rstStreamStatus !== kNoRstStream) {
     // If the user already called .end() and writes are still draining,
@@ -2174,6 +2167,14 @@ function closeStream(stream, code, rstStreamStatus = kSubmitRstStream) {
     }
   }

+  // Emit 'aborted' if the user hadn't ended the writable yet. This is
+  // unusual and doesn't match 'error' but is deprecated & preserved for
+  // backward compat (DEP0207).
+  if (!ending && !stream.aborted) {
+    state.flags |= STREAM_FLAGS_ABORTED;
+    stream.emit('aborted');
+  }
+
   if (type === NGHTTP2_SESSION_CLIENT) {
     if (onClientStreamCloseChannel.hasSubscribers) {
       onClientStreamCloseChannel.publish({ stream });
diff --git a/test/parallel/test-http2-close-aborted-destroy.js b/test/parallel/test-http2-close-aborted-destroy.js
new file mode 100644
index 00000000000..61abafed194
--- /dev/null
+++ b/test/parallel/test-http2-close-aborted-destroy.js
@@ -0,0 +1,32 @@
+'use strict';
+
+const common = require('../common');
+if (!common.hasCrypto)
+  common.skip('missing crypto');
+const assert = require('assert');
+const http2 = require('http2');
+const { NGHTTP2_CANCEL } = http2.constants;
+
+const server = http2.createServer();
+
+server.on('stream', common.mustCall((stream) => {
+  stream.respond();
+  stream.on('error', common.expectsError({
+    code: 'ERR_HTTP2_STREAM_ABORTED',
+  }));
+  stream.on('close', common.mustCall(() => {
+    assert.strictEqual(stream.rstCode, NGHTTP2_CANCEL);
+    server.close();
+  }));
+}));
+
+server.listen(0, common.mustCall(() => {
+  const client = http2.connect(`http://localhost:${server.address().port}`);
+  const req = client.request({ ':method': 'POST' });
+
+  req.on('aborted', common.mustCall(() => req.destroy()));
+  req.on('close', common.mustCall(() => client.close()));
+  req.on('response', common.mustCall(() => {
+    req.close(NGHTTP2_CANCEL);
+  }));
+}));