Skip to content

Commit

Permalink
Lazily require abort-controller (#478)
Browse files Browse the repository at this point in the history
* Lazily require abort-controller, since it throws when it has been bundled, then loaded in node

* Make changes to build script and re-run them.  Only did 18.0.0 to minimize the changeset.
  • Loading branch information
hildjj committed Jul 11, 2022
1 parent 69708c7 commit c04c4db
Show file tree
Hide file tree
Showing 17 changed files with 315 additions and 282 deletions.
3 changes: 1 addition & 2 deletions build/replacements.mjs
Expand Up @@ -14,7 +14,6 @@ const internalStreamsAbortControllerPolyfill = [
`
'use strict'
const abortControllerModule = require('abort-controller');
`
]

Expand All @@ -30,7 +29,7 @@ const internalStreamsInspectCustom = ['inspect.custom', "Symbol.for('nodejs.util

const internalStreamsNoRequireAbortController = [
'const \\{ AbortController \\} = .+',
'const AbortController = globalThis.AbortController || abortControllerModule.AbortController;'
'const AbortController = globalThis.AbortController || require(\'abort-controller\').AbortController;'
]

const internalStreamsRequireInternal = ["require\\('internal/([^']+)'\\)", "require('../$1')"]
Expand Down
5 changes: 2 additions & 3 deletions lib/internal/streams/duplexify.js
@@ -1,7 +1,5 @@
'use strict'

const abortControllerModule = require('abort-controller')

const bufferModule = require('buffer')

const {
Expand Down Expand Up @@ -40,7 +38,8 @@ const isBlob =
: function isBlob(b) {
return false
}
const AbortController = globalThis.AbortController || abortControllerModule.AbortController

const AbortController = globalThis.AbortController || require('abort-controller').AbortController

const { FunctionPrototypeCall } = require('../../ours/primordials') // This is needed for pre node 17.

Expand Down
4 changes: 1 addition & 3 deletions lib/internal/streams/operators.js
@@ -1,8 +1,6 @@
'use strict'

const abortControllerModule = require('abort-controller')

const AbortController = globalThis.AbortController || abortControllerModule.AbortController
const AbortController = globalThis.AbortController || require('abort-controller').AbortController

const {
codes: { ERR_INVALID_ARG_TYPE, ERR_MISSING_ARGS, ERR_OUT_OF_RANGE },
Expand Down
5 changes: 2 additions & 3 deletions lib/internal/streams/pipeline.js
Expand Up @@ -2,8 +2,6 @@
// permission from the author, Mathias Buus (@mafintosh).
'use strict'

const abortControllerModule = require('abort-controller')

const { ArrayIsArray, Promise, SymbolAsyncIterator } = require('../../ours/primordials')

const eos = require('./end-of-stream')
Expand All @@ -24,7 +22,8 @@ const { validateFunction, validateAbortSignal } = require('../validators')

const { isIterable, isReadable, isReadableNodeStream, isNodeStream } = require('./utils')

const AbortController = globalThis.AbortController || abortControllerModule.AbortController
const AbortController = globalThis.AbortController || require('abort-controller').AbortController

let PassThrough
let Readable

Expand Down
23 changes: 17 additions & 6 deletions lib/ours/errors.js
Expand Up @@ -82,14 +82,25 @@ function E(code, message, Base) {
}
}

NodeError.prototype.name = Base.name
Object.defineProperties(NodeError.prototype, {
name: {
value: Base.name,
writable: true,
enumerable: false,
configurable: true
},
toString: {
value() {
return `${this.name} [${code}]: ${this.message}`
},

writable: true,
enumerable: false,
configurable: true
}
})
NodeError.prototype.code = code
NodeError.prototype[kIsNodeError] = true

NodeError.prototype.toString = function () {
return `${this.name} [${code}]: ${this.message}`
}

codes[code] = NodeError
}

Expand Down
1 change: 0 additions & 1 deletion test/browser/test-stream3-pause-then-read.js
Expand Up @@ -47,7 +47,6 @@ module.exports = function (t) {
function readn(n, then) {
// console.error('read %d', n);
expectEndingData -= n

;(function read() {
const c = r.read(n)

Expand Down
18 changes: 3 additions & 15 deletions test/common/fixtures.mjs
@@ -1,17 +1,5 @@
import fixtures from './fixtures.js';
import fixtures from './fixtures.js'

const {
fixturesDir,
path,
fileURL,
readSync,
readKey,
} = fixtures;
const { fixturesDir, path, fileURL, readSync, readKey } = fixtures

export {
fixturesDir,
path,
fileURL,
readSync,
readKey,
};
export { fixturesDir, path, fileURL, readSync, readKey }
4 changes: 2 additions & 2 deletions test/common/index.js
Expand Up @@ -124,7 +124,7 @@ const isOSX = process.platform === 'darwin'

const isPi = (() => {
try {
var _$exec
var _exec

// Normal Raspberry Pi detection is to find the `Raspberry Pi` string in
// the contents of `/sys/firmware/devicetree/base/model` but that doesn't
Expand All @@ -133,7 +133,7 @@ const isPi = (() => {
encoding: 'utf8'
})
return (
((_$exec = /^Hardware\s*:\s*(.*)$/im.exec(cpuinfo)) === null || _$exec === undefined ? undefined : _$exec[1]) ===
((_exec = /^Hardware\s*:\s*(.*)$/im.exec(cpuinfo)) === null || _exec === undefined ? undefined : _exec[1]) ===
'BCM2835'
)
} catch {
Expand Down
10 changes: 5 additions & 5 deletions test/common/index.mjs
@@ -1,7 +1,7 @@
import { createRequire } from 'module';
import { createRequire } from 'module'

const require = createRequire(import.meta.url);
const common = require('./index.js');
const require = createRequire(import.meta.url)
const common = require('./index.js')

const {
isMainThread,
Expand Down Expand Up @@ -47,7 +47,7 @@ const {
getBufferSources,
getTTYfd,
runWithInvalidFD
} = common;
} = common

export {
isMainThread,
Expand Down Expand Up @@ -94,4 +94,4 @@ export {
getTTYfd,
runWithInvalidFD,
createRequire
};
}
100 changes: 59 additions & 41 deletions test/parallel/test-stream-asIndexedPairs.mjs
@@ -1,64 +1,82 @@
import '../common/index.mjs';
import { Readable }from '../../lib/ours/index.js';
import { deepStrictEqual, rejects, throws } from 'assert';
import tap from 'tap';
import '../common/index.mjs'
import { Readable } from '../../lib/ours/index.js'
import { deepStrictEqual, rejects, throws } from 'assert'
import tap from 'tap'

{
// asIndexedPairs with a synchronous stream
const pairs = await Readable.from([1, 2, 3]).asIndexedPairs().toArray();
deepStrictEqual(pairs, [[0, 1], [1, 2], [2, 3]]);
const empty = await Readable.from([]).asIndexedPairs().toArray();
deepStrictEqual(empty, []);
const pairs = await Readable.from([1, 2, 3]).asIndexedPairs().toArray()
deepStrictEqual(pairs, [
[0, 1],
[1, 2],
[2, 3]
])
const empty = await Readable.from([]).asIndexedPairs().toArray()
deepStrictEqual(empty, [])
}

{
// asIndexedPairs works an asynchronous streams
const asyncFrom = (...args) => Readable.from(...args).map(async (x) => x);
const pairs = await asyncFrom([1, 2, 3]).asIndexedPairs().toArray();
deepStrictEqual(pairs, [[0, 1], [1, 2], [2, 3]]);
const empty = await asyncFrom([]).asIndexedPairs().toArray();
deepStrictEqual(empty, []);
const asyncFrom = (...args) => Readable.from(...args).map(async (x) => x)
const pairs = await asyncFrom([1, 2, 3]).asIndexedPairs().toArray()
deepStrictEqual(pairs, [
[0, 1],
[1, 2],
[2, 3]
])
const empty = await asyncFrom([]).asIndexedPairs().toArray()
deepStrictEqual(empty, [])
}

{
// Does not enumerate an infinite stream
const infinite = () => Readable.from(async function* () {
while (true) yield 1;
}());
const pairs = await infinite().asIndexedPairs().take(3).toArray();
deepStrictEqual(pairs, [[0, 1], [1, 1], [2, 1]]);
const empty = await infinite().asIndexedPairs().take(0).toArray();
deepStrictEqual(empty, []);
const infinite = () =>
Readable.from(
(async function* () {
while (true) yield 1
})()
)
const pairs = await infinite().asIndexedPairs().take(3).toArray()
deepStrictEqual(pairs, [
[0, 1],
[1, 1],
[2, 1]
])
const empty = await infinite().asIndexedPairs().take(0).toArray()
deepStrictEqual(empty, [])
}

{
// AbortSignal
await rejects(async () => {
const ac = new AbortController();
const { signal } = ac;
const p = Readable.from([1, 2, 3]).asIndexedPairs({ signal }).toArray();
ac.abort();
await p;
}, { name: 'AbortError' });
await rejects(
async () => {
const ac = new AbortController()
const { signal } = ac
const p = Readable.from([1, 2, 3]).asIndexedPairs({ signal }).toArray()
ac.abort()
await p
},
{ name: 'AbortError' }
)

await rejects(async () => {
const signal = AbortSignal.abort();
await Readable.from([1, 2, 3]).asIndexedPairs({ signal }).toArray();
}, /AbortError/);
const signal = AbortSignal.abort()
await Readable.from([1, 2, 3]).asIndexedPairs({ signal }).toArray()
}, /AbortError/)
}

{
// Error cases
throws(() => Readable.from([1]).asIndexedPairs(1), /ERR_INVALID_ARG_TYPE/);
throws(() => Readable.from([1]).asIndexedPairs({ signal: true }), /ERR_INVALID_ARG_TYPE/);
throws(() => Readable.from([1]).asIndexedPairs(1), /ERR_INVALID_ARG_TYPE/)
throws(() => Readable.from([1]).asIndexedPairs({ signal: true }), /ERR_INVALID_ARG_TYPE/)
}

/* replacement start */
process.on('beforeExit', (code) => {
if(code === 0) {
tap.pass('test succeeded');
} else {
tap.fail(`test failed - exited code ${code}`);
}
});
/* replacement end */
/* replacement start */
process.on('beforeExit', (code) => {
if (code === 0) {
tap.pass('test succeeded')
} else {
tap.fail(`test failed - exited code ${code}`)
}
})
/* replacement end */
2 changes: 0 additions & 2 deletions test/parallel/test-stream-drop-take.js
Expand Up @@ -55,7 +55,6 @@ const naturals = () =>
deepStrictEqual(await from([1, 2]).drop(0).toArray(), [1, 2])
deepStrictEqual(await from([1, 2]).take(0).toArray(), [])
})().then(common.mustCall()) // Asynchronous streams

;(async () => {
deepStrictEqual(await fromAsync([1, 2, 3]).drop(2).toArray(), [3])
deepStrictEqual(await fromAsync([1, 2, 3]).take(1).toArray(), [1])
Expand All @@ -66,7 +65,6 @@ const naturals = () =>
deepStrictEqual(await fromAsync([1, 2]).take(0).toArray(), [])
})().then(common.mustCall()) // Infinite streams
// Asynchronous streams

;(async () => {
deepStrictEqual(await naturals().take(1).toArray(), [1])
deepStrictEqual(await naturals().drop(1).take(1).toArray(), [2])
Expand Down
1 change: 0 additions & 1 deletion test/parallel/test-stream-flatMap.js
Expand Up @@ -91,7 +91,6 @@ function oneTo5() {
.toArray()
assert.deepStrictEqual(result, [1, 1, 2, 2, 3, 3, 4, 4, 5, 5])
})().then(common.mustCall()) // flatMap works on an objectMode stream where mappign returns a stream

;(async () => {
const result = await oneTo5()
.flatMap(() => {
Expand Down

0 comments on commit c04c4db

Please sign in to comment.