diff --git a/.github/workflows/browsers.yml b/.github/workflows/browsers.yml index 4bf2ab12e..6fce3bbcd 100644 --- a/.github/workflows/browsers.yml +++ b/.github/workflows/browsers.yml @@ -23,10 +23,10 @@ jobs: steps: - name: Checkout uses: actions/checkout@v3 - - name: Use Node.js 16 + - name: Use Node.js 20 uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 20 - name: Restore cached dependencies uses: actions/cache@v3 with: diff --git a/build/replacements.mjs b/build/replacements.mjs index e5d97ecc7..710a7b73b 100644 --- a/build/replacements.mjs +++ b/build/replacements.mjs @@ -55,6 +55,11 @@ const internalStreamsRequireErrors = ["require\\('internal/errors'\\)", "require const internalStreamsRequireEventEmitter = ['const EE =', 'const { EventEmitter: EE } ='] +const internalStreamsLegacyListenerCount = [ + "EE\\.listenerCount\\(this, 'error'\\) === 0", + "this.listenerCount?.('error') === 0" +] + const internalStreamsRequirePrimordials = ['= primordials', "= require('../../ours/primordials')"] const internalStreamsRequireRelativeUtil = [ @@ -157,6 +162,7 @@ const testCommonKnownGlobals = [ typeof AbortSignal !== 'undefined' ? AbortSignal : require('abort-controller').AbortSignal, typeof EventTarget !== 'undefined' ? EventTarget : require('event-target-shim').EventTarget, typeof navigator !== 'undefined' ? navigator : {}, + typeof sessionStorage !== 'undefined' ? sessionStorage : {}, ` ] @@ -214,6 +220,12 @@ const testParallelReadableBufferListInspect = [ const testParallelRequireStream = ["require\\('stream'\\)", "require('../../lib/ours/index')"] +const testParallelStreamBaseTypecheckingError = [ + "code: 'ERR_INVALID_ARG_TYPE',\\n\\s+message: 'Second argument must be a buffer'", + `code: /^ERR_(?:INVALID_ARG_TYPE|UNKNOWN_ENCODING)$/, + message: /^(?:Second argument must be a buffer|Unknown encoding: buffer)$/` +] + const testParallelRequireStreamConsumer = ["require\\('stream/consumer'\\)", "require('../../lib/stream/consumer')"] const testParallelRequireStreamInternals = ["require\\('(internal/.+)'\\)", "require('../../lib/$1')"] @@ -317,6 +329,7 @@ export const replacements = { removetoWebReadableMethod, stringDecoderRequirePackage ], + 'lib/internal/streams/legacy.js': [internalStreamsLegacyListenerCount], 'lib/internal/streams/.+': [ internalStreamsRequireErrors, internalStreamsRequireEventEmitter, @@ -358,6 +371,7 @@ export const replacements = { 'test/common/index.js': [testCommonKnownGlobals], 'test/parallel/.+': [ testParallelIncludeTap, + testParallelStreamBaseTypecheckingError, testParallelRequireStream, testParallelRequireStreamConsumer, testParallelRequireStreamInternals, diff --git a/lib/internal/streams/legacy.js b/lib/internal/streams/legacy.js index d492f7ff4..8b22b400c 100644 --- a/lib/internal/streams/legacy.js +++ b/lib/internal/streams/legacy.js @@ -42,8 +42,13 @@ Stream.prototype.pipe = function (dest, options) { // Don't leave dangling pipes when there are errors. function onerror(er) { + var _this$listenerCount cleanup() - if (EE.listenerCount(this, 'error') === 0) { + if ( + ((_this$listenerCount = this.listenerCount) === null || _this$listenerCount === undefined + ? undefined + : _this$listenerCount.call(this, 'error')) === 0 + ) { this.emit('error', er) } } diff --git a/package.json b/package.json index 98b48e686..7e38cdd2c 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "@rollup/plugin-inject": "^4.0.4", "@rollup/plugin-node-resolve": "^13.3.0", "@sinonjs/fake-timers": "^9.1.2", + "ajv": "^8.20.0", "browserify": "^17.0.0", "c8": "^7.11.2", "esbuild": "^0.19.9", diff --git a/src/test/browser/test-stream-pipe-without-listenerCount.js b/src/test/browser/test-stream-pipe-without-listenerCount.js index 1e8238cd8..79278ec65 100644 --- a/src/test/browser/test-stream-pipe-without-listenerCount.js +++ b/src/test/browser/test-stream-pipe-without-listenerCount.js @@ -10,13 +10,14 @@ module.exports = function (t) { read: function () {} }) r.listenerCount = undefined + r.on('error', function () {}) const w = new Stream() w.on('pipe', function () { r.emit('error', new Error('Readable Error')) }) - t.throws(() => r.pipe(w), 'TypeError: this.listenerCount is not a function') + t.doesNotThrow(() => r.pipe(w)) } module.exports[kReadableStreamSuiteName] = 'stream-pipe-without-listenerCount' diff --git a/test/browser/test-stream-pipe-without-listenerCount.js b/test/browser/test-stream-pipe-without-listenerCount.js index 3b498a09b..292eaa78e 100644 --- a/test/browser/test-stream-pipe-without-listenerCount.js +++ b/test/browser/test-stream-pipe-without-listenerCount.js @@ -8,10 +8,11 @@ module.exports = function (t) { read: function () {} }) r.listenerCount = undefined + r.on('error', function () {}) const w = new Stream() w.on('pipe', function () { r.emit('error', new Error('Readable Error')) }) - t.throws(() => r.pipe(w), 'TypeError: this.listenerCount is not a function') + t.doesNotThrow(() => r.pipe(w)) } module.exports[kReadableStreamSuiteName] = 'stream-pipe-without-listenerCount' diff --git a/test/common/index.js b/test/common/index.js index 3e9b4c3ea..2c47c28da 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -255,6 +255,7 @@ let knownGlobals = [ typeof AbortSignal !== 'undefined' ? AbortSignal : require('abort-controller').AbortSignal, typeof EventTarget !== 'undefined' ? EventTarget : require('event-target-shim').EventTarget, typeof navigator !== 'undefined' ? navigator : {}, + typeof sessionStorage !== 'undefined' ? sessionStorage : {}, atob, btoa, clearImmediate, diff --git a/test/parallel/test-stream-base-typechecking.js b/test/parallel/test-stream-base-typechecking.js index 070e7563f..67d4aa3fd 100644 --- a/test/parallel/test-stream-base-typechecking.js +++ b/test/parallel/test-stream-base-typechecking.js @@ -20,8 +20,8 @@ const server = net.createServer().listen( }, { name: 'TypeError', - code: 'ERR_INVALID_ARG_TYPE', - message: 'Second argument must be a buffer' + code: /^ERR_(?:INVALID_ARG_TYPE|UNKNOWN_ENCODING)$/, + message: /^(?:Second argument must be a buffer|Unknown encoding: buffer)$/ } ) client.destroy()