diff --git a/lib/_http_outgoing.js b/lib/_http_outgoing.js index 8402bd2b61aaf4..1c570284ef5ccb 100644 --- a/lib/_http_outgoing.js +++ b/lib/_http_outgoing.js @@ -642,7 +642,7 @@ OutgoingMessage.prototype.write = function write(chunk, encoding, callback) { function write_(msg, chunk, encoding, callback, fromEnd) { if (msg.finished) { var err = new Error('write after end'); - nextTick(msg.socket[async_id_symbol], + nextTick(msg.socket && msg.socket[async_id_symbol], writeAfterEndNT.bind(msg), err, callback); diff --git a/lib/internal/process/next_tick.js b/lib/internal/process/next_tick.js index c063c22cd817d0..685fa6717bd9f1 100644 --- a/lib/internal/process/next_tick.js +++ b/lib/internal/process/next_tick.js @@ -281,7 +281,7 @@ function setupNextTick() { if (process._exiting) return; - if (triggerAsyncId === null) { + if (!Number.isSafeInteger(triggerAsyncId) || triggerAsyncId <= 0) { triggerAsyncId = async_hooks.initTriggerId(); } diff --git a/test/async-hooks/test-internal-nexttick-default-trigger.js b/test/async-hooks/test-internal-nexttick-default-trigger.js index 90e566b7063c46..5bd38c8a3a66a0 100644 --- a/test/async-hooks/test-internal-nexttick-default-trigger.js +++ b/test/async-hooks/test-internal-nexttick-default-trigger.js @@ -26,6 +26,11 @@ internal.nextTick(null, common.mustCall(function() { assert.strictEqual(async_hooks.triggerAsyncId(), rootAsyncId); })); +// internal default +internal.nextTick(undefined, common.mustCall(function() { + assert.strictEqual(async_hooks.triggerAsyncId(), rootAsyncId); +})); + // internal internal.nextTick(rootAsyncId + 1, common.mustCall(function() { assert.strictEqual(async_hooks.triggerAsyncId(), rootAsyncId + 1); diff --git a/test/parallel/test-http-outgoing-message-inheritance.js b/test/parallel/test-http-outgoing-message-inheritance.js new file mode 100644 index 00000000000000..05a241dc8bda00 --- /dev/null +++ b/test/parallel/test-http-outgoing-message-inheritance.js @@ -0,0 +1,32 @@ +'use strict'; + +const common = require('../common'); +const { OutgoingMessage } = require('http'); +const { Writable } = require('stream'); +const assert = require('assert'); + +// check that OutgoingMessage can be used without a proper Socket +// Fixes: https://github.com/nodejs/node/issues/14386 +// Fixes: https://github.com/nodejs/node/issues/14381 + +class Response extends OutgoingMessage { + constructor() { + super({ method: 'GET', httpVersionMajor: 1, httpVersionMinor: 1 }); + } + + _implicitHeader() {} +} + +const res = new Response(); +const ws = new Writable({ + write: common.mustCall((chunk, encoding, callback) => { + assert(chunk.toString().match(/hello world/)); + setImmediate(callback); + }) +}); + +res.socket = ws; +ws._httpMessage = res; +res.connection = ws; + +res.end('hello world'); diff --git a/test/parallel/test-http-server-response-standalone.js b/test/parallel/test-http-server-response-standalone.js new file mode 100644 index 00000000000000..7025c734b3103d --- /dev/null +++ b/test/parallel/test-http-server-response-standalone.js @@ -0,0 +1,27 @@ +'use strict'; + +const common = require('../common'); +const { ServerResponse } = require('http'); +const { Writable } = require('stream'); +const assert = require('assert'); + +// check that ServerResponse can be used without a proper Socket +// Fixes: https://github.com/nodejs/node/issues/14386 +// Fixes: https://github.com/nodejs/node/issues/14381 + +const res = new ServerResponse({ + method: 'GET', + httpVersionMajor: 1, + httpVersionMinor: 1 +}); + +const ws = new Writable({ + write: common.mustCall((chunk, encoding, callback) => { + assert(chunk.toString().match(/hello world/)); + setImmediate(callback); + }) +}); + +res.assignSocket(ws); + +res.end('hello world'); diff --git a/test/parallel/test-http-server-write-after-end.js b/test/parallel/test-http-server-write-after-end.js new file mode 100644 index 00000000000000..045cdcf4b75afb --- /dev/null +++ b/test/parallel/test-http-server-write-after-end.js @@ -0,0 +1,27 @@ +'use strict'; + +const common = require('../common'); +const http = require('http'); +const assert = require('assert'); + +// Fix for https://github.com/nodejs/node/issues/14368 + +const server = http.createServer(handle); + +function handle(req, res) { + res.on('error', common.mustCall((err) => { + assert.strictEqual(err.message, 'write after end'); + server.close(); + })); + + res.write('hello'); + res.end(); + + setImmediate(common.mustCall(() => { + res.write('world'); + })); +} + +server.listen(0, common.mustCall(() => { + http.get(`http://localhost:${server.address().port}`); +}));