diff --git a/node_modules/pacote/CHANGELOG.md b/node_modules/pacote/CHANGELOG.md index 4ed92beb68213..6896c4739ce53 100644 --- a/node_modules/pacote/CHANGELOG.md +++ b/node_modules/pacote/CHANGELOG.md @@ -2,6 +2,16 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. + +## [9.5.9](https://github.com/npm/pacote/compare/v9.5.8...v9.5.9) (2019-10-29) + + +### Bug Fixes + +* include peerDependenciesMeta in manifest ([7a400d3](https://github.com/npm/pacote/commit/7a400d3)), closes [/github.com/npm/cli/pull/224#issuecomment-547666807](https://github.com//github.com/npm/cli/pull/224/issues/issuecomment-547666807) + + + ## [9.5.8](https://github.com/npm/pacote/compare/v9.5.7...v9.5.8) (2019-08-20) diff --git a/node_modules/pacote/lib/fetchers/git.js b/node_modules/pacote/lib/fetchers/git.js index a1579d1f94312..7913be8168791 100644 --- a/node_modules/pacote/lib/fetchers/git.js +++ b/node_modules/pacote/lib/fetchers/git.js @@ -166,7 +166,7 @@ function withTmp (opts, cb) { } } -// Only certain whitelisted hosted gits support shadow cloning +// Only certain whitelisted hosted gits support shallow cloning const SHALLOW_HOSTS = new Set(['github', 'gist', 'gitlab', 'bitbucket']) function cloneRepo (spec, repo, resolvedRef, rawRef, tmp, opts) { const ref = resolvedRef ? resolvedRef.ref : rawRef diff --git a/node_modules/pacote/lib/finalize-manifest.js b/node_modules/pacote/lib/finalize-manifest.js index f047517945192..d1d0f4e563eed 100644 --- a/node_modules/pacote/lib/finalize-manifest.js +++ b/node_modules/pacote/lib/finalize-manifest.js @@ -83,6 +83,7 @@ function Manifest (pkg, fromTarball, fullMetadata) { this.os = pkg.os || fromTarball.os this.dependencies = pkg.dependencies || {} this.optionalDependencies = pkg.optionalDependencies || {} + this.peerDependenciesMeta = pkg.peerDependenciesMeta || {} this.devDependencies = pkg.devDependencies || {} const bundled = ( pkg.bundledDependencies || diff --git a/node_modules/pacote/node_modules/minipass/README.md b/node_modules/pacote/node_modules/minipass/README.md index 7a83c59ffd709..c989beea0e6d9 100644 --- a/node_modules/pacote/node_modules/minipass/README.md +++ b/node_modules/pacote/node_modules/minipass/README.md @@ -24,25 +24,374 @@ If you set `objectMode: true` in the options, then whatever is written will be emitted. Otherwise, it'll do a minimal amount of Buffer copying to ensure proper Streams semantics when `read(n)` is called. +`objectMode` can also be set by doing `stream.objectMode = true`, or by +writing any non-string/non-buffer data. `objectMode` cannot be set to +false once it is set. + This is not a `through` or `through2` stream. It doesn't transform the data, it just passes it right through. If you want to transform the data, extend the class, and override the `write()` method. Once you're done transforming the data however you want, call `super.write()` with the transform output. -For an example of a stream that extends MiniPass to provide transform -capabilities, check out [minizlib](http://npm.im/minizlib). +For some examples of streams that extend Minipass in various ways, check +out: + +- [minizlib](http://npm.im/minizlib) +- [fs-minipass](http://npm.im/fs-minipass) +- [tar](http://npm.im/tar) +- [minipass-collect](http://npm.im/minipass-collect) +- [minipass-flush](http://npm.im/minipass-flush) +- [minipass-pipeline](http://npm.im/minipass-pipeline) +- [tap](http://npm.im/tap) +- [tap-parser](http://npm.im/tap) +- [treport](http://npm.im/tap) + +## Differences from Node.js Streams + +There are several things that make Minipass streams different from (and in +some ways superior to) Node.js core streams. + +Please read these caveats if you are familiar with noode-core streams and +intend to use Minipass streams in your programs. + +### Timing + +Minipass streams are designed to support synchronous use-cases. Thus, data +is emitted as soon as it is available, always. It is buffered until read, +but no longer. Another way to look at it is that Minipass streams are +exactly as synchronous as the logic that writes into them. + +This can be surprising if your code relies on `PassThrough.write()` always +providing data on the next tick rather than the current one, or being able +to call `resume()` and not have the entire buffer disappear immediately. + +However, without this synchronicity guarantee, there would be no way for +Minipass to achieve the speeds it does, or support the synchronous use +cases that it does. Simply put, waiting takes time. + +This non-deferring approach makes Minipass streams much easier to reason +about, especially in the context of Promises and other flow-control +mechanisms. + +### No High/Low Water Marks + +Node.js core streams will optimistically fill up a buffer, returning `true` +on all writes until the limit is hit, even if the data has nowhere to go. +Then, they will not attempt to draw more data in until the buffer size dips +below a minimum value. + +Minipass streams are much simpler. The `write()` method will return `true` +if the data has somewhere to go (which is to say, given the timing +guarantees, that the data is already there by the time `write()` returns). + +If the data has nowhere to go, then `write()` returns false, and the data +sits in a buffer, to be drained out immediately as soon as anyone consumes +it. + +### Hazards of Buffering (or: Why Minipass Is So Fast) + +Since data written to a Minipass stream is immediately written all the way +through the pipeline, and `write()` always returns true/false based on +whether the data was fully flushed, backpressure is communicated +immediately to the upstream caller. This minimizes buffering. + +Consider this case: + +```js +const {PassThrough} = require('stream') +const p1 = new PassThrough({ highWaterMark: 1024 }) +const p2 = new PassThrough({ highWaterMark: 1024 }) +const p3 = new PassThrough({ highWaterMark: 1024 }) +const p4 = new PassThrough({ highWaterMark: 1024 }) + +p1.pipe(p2).pipe(p3).pipe(p4) +p4.on('data', () => console.log('made it through')) + +// this returns false and buffers, then writes to p2 on next tick (1) +// p2 returns false and buffers, pausing p1, then writes to p3 on next tick (2) +// p3 returns false and buffers, pausing p2, then writes to p4 on next tick (3) +// p4 returns false and buffers, pausing p3, then emits 'data' and 'drain' +// on next tick (4) +// p3 sees p4's 'drain' event, and calls resume(), emitting 'resume' and +// 'drain' on next tick (5) +// p2 sees p3's 'drain', calls resume(), emits 'resume' and 'drain' on next tick (6) +// p1 sees p2's 'drain', calls resume(), emits 'resume' and 'drain' on next +// tick (7) + +p1.write(Buffer.alloc(2048)) // returns false +``` + +Along the way, the data was buffered and deferred at each stage, and +multiple event deferrals happened, for an unblocked pipeline where it was +perfectly safe to write all the way through! + +Furthermore, setting a `highWaterMark` of `1024` might lead someone reading +the code to think an advisory maximum of 1KiB is being set for the +pipeline. However, the actual advisory buffering level is the _sum_ of +`highWaterMark` values, since each one has its own bucket. + +Consider the Minipass case: + +```js +const m1 = new Minipass() +const m2 = new Minipass() +const m3 = new Minipass() +const m4 = new Minipass() + +m1.pipe(m2).pipe(m3).pipe(m4) +m4.on('data', () => console.log('made it through')) + +// m1 is flowing, so it writes the data to m2 immediately +// m2 is flowing, so it writes the data to m3 immediately +// m3 is flowing, so it writes the data to m4 immediately +// m4 is flowing, so it fires the 'data' event immediately, returns true +// m4's write returned true, so m3 is still flowing, returns true +// m3's write returned true, so m2 is still flowing, returns true +// m2's write returned true, so m1 is still flowing, returns true +// No event deferrals or buffering along the way! + +m1.write(Buffer.alloc(2048)) // returns true +``` + +It is extremely unlikely that you _don't_ want to buffer any data written, +or _ever_ buffer data that can be flushed all the way through. Neither +node-core streams nor Minipass ever fail to buffer written data, but +node-core streams do a lot of unnecessary buffering and pausing. + +As always, the faster implementation is the one that does less stuff and +waits less time to do it. + +### Immediately emit `end` for empty streams (when not paused) + +If a stream is not paused, and `end()` is called before writing any data +into it, then it will emit `end` immediately. + +If you have logic that occurs on the `end` event which you don't want to +potentially happen immediately (for example, closing file descriptors, +moving on to the next entry in an archive parse stream, etc.) then be sure +to call `stream.pause()` on creation, and then `stream.resume()` once you +are ready to respond to the `end` event. + +### Emit `end` When Asked + +One hazard of immediately emitting `'end'` is that you may not yet have had +a chance to add a listener. In order to avoid this hazard, Minipass +streams safely re-emit the `'end'` event if a new listener is added after +`'end'` has been emitted. + +Ie, if you do `stream.on('end', someFunction)`, and the stream has already +emitted `end`, then it will call the handler right away. (You can think of +this somewhat like attaching a new `.then(fn)` to a previously-resolved +Promise.) + +To prevent calling handlers multiple times who would not expect multiple +ends to occur, all listeners are removed from the `'end'` event whenever it +is emitted. + +### Impact of "immediate flow" on Tee-streams + +A "tee stream" is a stream piping to multiple destinations: + +```js +const tee = new Minipass() +t.pipe(dest1) +t.pipe(dest2) +t.write('foo') // goes to both destinations +``` + +Since Minipass streams _immediately_ process any pending data through the +pipeline when a new pipe destination is added, this can have surprising +effects, especially when a stream comes in from some other function and may +or may not have data in its buffer. + +```js +// WARNING! WILL LOSE DATA! +const src = new Minipass() +src.write('foo') +src.pipe(dest1) // 'foo' chunk flows to dest1 immediately, and is gone +src.pipe(dest2) // gets nothing! +``` + +The solution is to create a dedicated tee-stream junction that pipes to +both locations, and then pipe to _that_ instead. + +```js +// Safe example: tee to both places +const src = new Minipass() +src.write('foo') +const tee = new Minipass() +tee.pipe(dest1) +tee.pipe(dest2) +stream.pipe(tee) // tee gets 'foo', pipes to both locations +``` + +The same caveat applies to `on('data')` event listeners. The first one +added will _immediately_ receive all of the data, leaving nothing for the +second: + +```js +// WARNING! WILL LOSE DATA! +const src = new Minipass() +src.write('foo') +src.on('data', handler1) // receives 'foo' right away +src.on('data', handler2) // nothing to see here! +``` + +Using a dedicated tee-stream can be used in this case as well: + +```js +// Safe example: tee to both data handlers +const src = new Minipass() +src.write('foo') +const tee = new Minipass() +tee.on('data', handler1) +tee.on('data', handler2) +src.pipe(tee) +``` ## USAGE +It's a stream! Use it like a stream and it'll most likely do what you want. + ```js -const MiniPass = require('minipass') -const mp = new MiniPass(options) // optional: { encoding } +const Minipass = require('minipass') +const mp = new Minipass(options) // optional: { encoding, objectMode } mp.write('foo') mp.pipe(someOtherStream) mp.end('bar') ``` +### OPTIONS + +* `encoding` How would you like the data coming _out_ of the stream to be + encoded? Accepts any values that can be passed to `Buffer.toString()`. +* `objectMode` Emit data exactly as it comes in. This will be flipped on + by default if you write() something other than a string or Buffer at any + point. Setting `objectMode: true` will prevent setting any encoding + value. + +### API + +Implements the user-facing portions of Node.js's `Readable` and `Writable` +streams. + +### Methods + +* `write(chunk, [encoding], [callback])` - Put data in. (Note that, in the + base Minipass class, the same data will come out.) Returns `false` if + the stream will buffer the next write, or true if it's still in + "flowing" mode. +* `end([chunk, [encoding]], [callback])` - Signal that you have no more + data to write. This will queue an `end` event to be fired when all the + data has been consumed. +* `setEncoding(encoding)` - Set the encoding for data coming of the + stream. This can only be done once. +* `pause()` - No more data for a while, please. This also prevents `end` + from being emitted for empty streams until the stream is resumed. +* `resume()` - Resume the stream. If there's data in the buffer, it is + all discarded. Any buffered events are immediately emitted. +* `pipe(dest)` - Send all output to the stream provided. There is no way + to unpipe. When data is emitted, it is immediately written to any and + all pipe destinations. +* `on(ev, fn)`, `emit(ev, fn)` - Minipass streams are EventEmitters. + Some events are given special treatment, however. (See below under + "events".) +* `promise()` - Returns a Promise that resolves when the stream emits + `end`, or rejects if the stream emits `error`. +* `collect()` - Return a Promise that resolves on `end` with an array + containing each chunk of data that was emitted, or rejects if the + stream emits `error`. Note that this consumes the stream data. +* `concat()` - Same as `collect()`, but concatenates the data into a + single Buffer object. Will reject the returned promise if the stream is + in objectMode, or if it goes into objectMode by the end of the data. +* `read(n)` - Consume `n` bytes of data out of the buffer. If `n` is not + provided, then consume all of it. If `n` bytes are not available, then + it returns null. **Note** consuming streams in this way is less + efficient, and can lead to unnecessary Buffer copying. +* `destroy([er])` - Destroy the stream. If an error is provided, then an + `'error'` event is emitted. If the stream has a `close()` method, and + has not emitted a `'close'` event yet, then `stream.close()` will be + called. Any Promises returned by `.promise()`, `.collect()` or + `.concat()` will be rejected. After being destroyed, writing to the + stream will emit an error. No more data will be emitted if the stream is + destroyed, even if it was previously buffered. + +### Properties + +* `bufferLength` Read-only. Total number of bytes buffered, or in the case + of objectMode, the total number of objects. +* `encoding` The encoding that has been set. (Setting this is equivalent + to calling `setEncoding(enc)` and has the same prohibition against + setting multiple times.) +* `flowing` Read-only. Boolean indicating whether a chunk written to the + stream will be immediately emitted. +* `emittedEnd` Read-only. Boolean indicating whether the end-ish events + (ie, `end`, `prefinish`, `finish`) have been emitted. Note that + listening on any end-ish event will immediateyl re-emit it if it has + already been emitted. +* `writable` Whether the stream is writable. Default `true`. Set to + `false` when `end()` +* `readable` Whether the stream is readable. Default `true`. +* `buffer` A [yallist](http://npm.im/yallist) linked list of chunks written + to the stream that have not yet been emitted. (It's probably a bad idea + to mess with this.) +* `pipes` A [yallist](http://npm.im/yallist) linked list of streams that + this stream is piping into. (It's probably a bad idea to mess with + this.) +* `destroyed` A getter that indicates whether the stream was destroyed. +* `paused` True if the stream has been explicitly paused, otherwise false. +* `objectMode` Indicates whether the stream is in `objectMode`. Once set + to `true`, it cannot be set to `false`. + +### Events + +* `data` Emitted when there's data to read. Argument is the data to read. + This is never emitted while not flowing. If a listener is attached, that + will resume the stream. +* `end` Emitted when there's no more data to read. This will be emitted + immediately for empty streams when `end()` is called. If a listener is + attached, and `end` was already emitted, then it will be emitted again. + All listeners are removed when `end` is emitted. +* `prefinish` An end-ish event that follows the same logic as `end` and is + emitted in the same conditions where `end` is emitted. Emitted after + `'end'`. +* `finish` An end-ish event that follows the same logic as `end` and is + emitted in the same conditions where `end` is emitted. Emitted after + `'prefinish'`. +* `close` An indication that an underlying resource has been released. + Minipass does not emit this event, but will defer it until after `end` + has been emitted, since it throws off some stream libraries otherwise. +* `drain` Emitted when the internal buffer empties, and it is again + suitable to `write()` into the stream. +* `readable` Emitted when data is buffered and ready to be read by a + consumer. +* `resume` Emitted when stream changes state from buffering to flowing + mode. (Ie, when `resume` is called, `pipe` is called, or a `data` event + listener is added.) + +### Static Methods + +* `Minipass.isStream(stream)` Returns `true` if the argument is a stream, + and false otherwise. To be considered a stream, the object must be + either an instance of Minipass, or an EventEmitter that has either a + `pipe()` method, or both `write()` and `end()` methods. (Pretty much any + stream in node-land will return `true` for this.) + +## EXAMPLES + +Here are some examples of things you can do with Minipass streams. + +### simple "are you done yet" promise + +```js +mp.promise().then(() => { + // stream is finished +}, er => { + // stream emitted an error +}) +``` + ### collecting ```js @@ -57,6 +406,19 @@ mp.collect().then(all => { }) ``` +### collecting into a single blob + +This is a bit slower because it concatenates the data into one chunk for +you, but if you're going to do it yourself anyway, it's convenient this +way: + +```js +mp.concat().then(onebigchunk => { + // onebigchunk is a string if the stream + // had an encoding set, or a buffer otherwise. +}) +``` + ### iteration You can iterate over streams synchronously or asynchronously in @@ -122,3 +484,123 @@ async function consume () { consume().then(res => console.log(res)) // logs `foo\n` 5 times, and then `ok` ``` + +### subclass that `console.log()`s everything written into it + +```js +class Logger extends Minipass { + write (chunk, encoding, callback) { + console.log('WRITE', chunk, encoding) + return super.write(chunk, encoding, callback) + } + end (chunk, encoding, callback) { + console.log('END', chunk, encoding) + return super.end(chunk, encoding, callback) + } +} + +someSource.pipe(new Logger()).pipe(someDest) +``` + +### same thing, but using an inline anonymous class + +```js +// js classes are fun +someSource + .pipe(new (class extends Minipass { + emit (ev, ...data) { + // let's also log events, because debugging some weird thing + console.log('EMIT', ev) + return super.emit(ev, ...data) + } + write (chunk, encoding, callback) { + console.log('WRITE', chunk, encoding) + return super.write(chunk, encoding, callback) + } + end (chunk, encoding, callback) { + console.log('END', chunk, encoding) + return super.end(chunk, encoding, callback) + } + })) + .pipe(someDest) +``` + +### subclass that defers 'end' for some reason + +```js +class SlowEnd extends Minipass { + emit (ev, ...args) { + if (ev === 'end') { + console.log('going to end, hold on a sec') + setTimeout(() => { + console.log('ok, ready to end now') + super.emit('end', ...args) + }, 100) + } else { + return super.emit(ev, ...args) + } + } +} +``` + +### transform that creates newline-delimited JSON + +```js +class NDJSONEncode extends Minipass { + write (obj, cb) { + try { + // JSON.stringify can throw, emit an error on that + return super.write(JSON.stringify(obj) + '\n', 'utf8', cb) + } catch (er) { + this.emit('error', er) + } + } + end (obj, cb) { + if (typeof obj === 'function') { + cb = obj + obj = undefined + } + if (obj !== undefined) { + this.write(obj) + } + return super.end(cb) + } +} +``` + +### transform that parses newline-delimited JSON + +```js +class NDJSONDecode extends Minipass { + constructor (options) { + // always be in object mode, as far as Minipass is concerned + super({ objectMode: true }) + this._jsonBuffer = '' + } + write (chunk, encoding, cb) { + if (typeof chunk === 'string' && + typeof encoding === 'string' && + encoding !== 'utf8') { + chunk = Buffer.from(chunk, encoding).toString() + } else if (Buffer.isBuffer(chunk)) + chunk = chunk.toString() + } + if (typeof encoding === 'function') { + cb = encoding + } + const jsonData = (this._jsonBuffer + chunk).split('\n') + this._jsonBuffer = jsonData.pop() + for (let i = 0; i < jsonData.length; i++) { + let parsed + try { + super.write(parsed) + } catch (er) { + this.emit('error', er) + continue + } + } + if (cb) + cb() + } +} +``` diff --git a/node_modules/pacote/node_modules/minipass/index.js b/node_modules/pacote/node_modules/minipass/index.js index de472c36e7684..c072352d448a9 100644 --- a/node_modules/pacote/node_modules/minipass/index.js +++ b/node_modules/pacote/node_modules/minipass/index.js @@ -1,39 +1,62 @@ 'use strict' const EE = require('events') const Yallist = require('yallist') +const SD = require('string_decoder').StringDecoder + const EOF = Symbol('EOF') const MAYBE_EMIT_END = Symbol('maybeEmitEnd') const EMITTED_END = Symbol('emittedEnd') +const EMITTING_END = Symbol('emittingEnd') const CLOSED = Symbol('closed') const READ = Symbol('read') const FLUSH = Symbol('flush') -const doIter = process.env._MP_NO_ITERATOR_SYMBOLS_ !== '1' -const ASYNCITERATOR = doIter && Symbol.asyncIterator || Symbol('asyncIterator not implemented') -const ITERATOR = doIter && Symbol.iterator || Symbol('iterator not implemented') const FLUSHCHUNK = Symbol('flushChunk') -const SD = require('string_decoder').StringDecoder const ENCODING = Symbol('encoding') const DECODER = Symbol('decoder') const FLOWING = Symbol('flowing') +const PAUSED = Symbol('paused') const RESUME = Symbol('resume') const BUFFERLENGTH = Symbol('bufferLength') const BUFFERPUSH = Symbol('bufferPush') const BUFFERSHIFT = Symbol('bufferShift') const OBJECTMODE = Symbol('objectMode') +const DESTROYED = Symbol('destroyed') + +// TODO remove when Node v8 support drops +const doIter = global._MP_NO_ITERATOR_SYMBOLS_ !== '1' +const ASYNCITERATOR = doIter && Symbol.asyncIterator + || Symbol('asyncIterator not implemented') +const ITERATOR = doIter && Symbol.iterator + || Symbol('iterator not implemented') // Buffer in node 4.x < 4.5.0 doesn't have working Buffer.from // or Buffer.alloc, and Buffer in node 10 deprecated the ctor. // .M, this is fine .\^/M.. -let B = Buffer -/* istanbul ignore next */ -if (!B.alloc) { - B = require('safe-buffer').Buffer -} - -module.exports = class MiniPass extends EE { +const B = Buffer.alloc ? Buffer + : /* istanbul ignore next */ require('safe-buffer').Buffer + +// events that mean 'the stream is over' +// these are treated specially, and re-emitted +// if they are listened for after emitting. +const isEndish = ev => + ev === 'end' || + ev === 'finish' || + ev === 'prefinish' + +const isArrayBuffer = b => b instanceof ArrayBuffer || + typeof b === 'object' && + b.constructor && + b.constructor.name === 'ArrayBuffer' && + b.byteLength >= 0 + +const isArrayBufferView = b => !B.isBuffer(b) && ArrayBuffer.isView(b) + +module.exports = class Minipass extends EE { constructor (options) { super() this[FLOWING] = false + // whether we're explicitly paused + this[PAUSED] = false this.pipes = new Yallist() this.buffer = new Yallist() this[OBJECTMODE] = options && options.objectMode || false @@ -46,10 +69,12 @@ module.exports = class MiniPass extends EE { this[DECODER] = this[ENCODING] ? new SD(this[ENCODING]) : null this[EOF] = false this[EMITTED_END] = false + this[EMITTING_END] = false this[CLOSED] = false this.writable = true this.readable = true this[BUFFERLENGTH] = 0 + this[DESTROYED] = false } get bufferLength () { return this[BUFFERLENGTH] } @@ -76,16 +101,52 @@ module.exports = class MiniPass extends EE { this.encoding = enc } + get objectMode () { return this[OBJECTMODE] } + set objectMode (ॐ ) { this[OBJECTMODE] = this[OBJECTMODE] || !!ॐ } + write (chunk, encoding, cb) { if (this[EOF]) throw new Error('write after end') + if (this[DESTROYED]) { + this.emit('error', Object.assign( + new Error('Cannot call write after a stream was destroyed'), + { code: 'ERR_STREAM_DESTROYED' } + )) + return true + } + if (typeof encoding === 'function') cb = encoding, encoding = 'utf8' if (!encoding) encoding = 'utf8' + // convert array buffers and typed array views into buffers + // at some point in the future, we may want to do the opposite! + // leave strings and buffers as-is + // anything else switches us into object mode + if (!this[OBJECTMODE] && !B.isBuffer(chunk)) { + if (isArrayBufferView(chunk)) + chunk = B.from(chunk.buffer, chunk.byteOffset, chunk.byteLength) + else if (isArrayBuffer(chunk)) + chunk = B.from(chunk) + else if (typeof chunk !== 'string') + // use the setter so we throw if we have encoding set + this.objectMode = true + } + + // this ensures at this point that the chunk is a buffer or string + // don't buffer it up or send it to the decoder + if (!this.objectMode && !chunk.length) { + const ret = this.flowing + if (this[BUFFERLENGTH] !== 0) + this.emit('readable') + if (cb) + cb() + return ret + } + // fast-path writing strings of same encoding to a stream with // an empty buffer, skipping the buffer/decoder dance if (typeof chunk === 'string' && !this[OBJECTMODE] && @@ -102,13 +163,17 @@ module.exports = class MiniPass extends EE { ? (this.emit('data', chunk), this.flowing) : (this[BUFFERPUSH](chunk), false) } finally { - this.emit('readable') + if (this[BUFFERLENGTH] !== 0) + this.emit('readable') if (cb) cb() } } read (n) { + if (this[DESTROYED]) + return null + try { if (this[BUFFERLENGTH] === 0 || n === 0 || n > this[BUFFERLENGTH]) return null @@ -161,12 +226,22 @@ module.exports = class MiniPass extends EE { this.once('end', cb) this[EOF] = true this.writable = false - if (this.flowing) + + // if we haven't written anything, then go ahead and emit, + // even if we're not reading. + // we'll re-emit if a new 'end' listener is added anyway. + // This makes MP more suitable to write-only use cases. + if (this.flowing || !this[PAUSED]) this[MAYBE_EMIT_END]() + return this } // don't let the internal resume be overwritten [RESUME] () { + if (this[DESTROYED]) + return + + this[PAUSED] = false this[FLOWING] = true this.emit('resume') if (this.buffer.length) @@ -183,12 +258,21 @@ module.exports = class MiniPass extends EE { pause () { this[FLOWING] = false + this[PAUSED] = true + } + + get destroyed () { + return this[DESTROYED] } get flowing () { return this[FLOWING] } + get paused () { + return this[PAUSED] + } + [BUFFERPUSH] (chunk) { if (this[OBJECTMODE]) this[BUFFERLENGTH] += 1 @@ -219,13 +303,24 @@ module.exports = class MiniPass extends EE { } pipe (dest, opts) { + if (this[DESTROYED]) + return + + const ended = this[EMITTED_END] + opts = opts || {} if (dest === process.stdout || dest === process.stderr) - (opts = opts || {}).end = false + opts.end = false + else + opts.end = opts.end !== false + const p = { dest: dest, opts: opts, ondrain: _ => this[RESUME]() } this.pipes.push(p) dest.on('drain', p.ondrain) this[RESUME]() + // piping an ended stream ends immediately + if (ended && p.opts.end) + p.dest.end() return dest } @@ -239,9 +334,9 @@ module.exports = class MiniPass extends EE { } finally { if (ev === 'data' && !this.pipes.length && !this.flowing) this[RESUME]() - else if (ev === 'end' && this[EMITTED_END]) { - super.emit('end') - this.removeAllListeners('end') + else if (isEndish(ev) && this[EMITTED_END]) { + super.emit(ev) + this.removeAllListeners(ev) } } } @@ -251,23 +346,34 @@ module.exports = class MiniPass extends EE { } [MAYBE_EMIT_END] () { - if (!this[EMITTED_END] && this.buffer.length === 0 && this[EOF]) { + if (!this[EMITTING_END] && + !this[EMITTED_END] && + !this[DESTROYED] && + this.buffer.length === 0 && + this[EOF]) { + this[EMITTING_END] = true this.emit('end') this.emit('prefinish') this.emit('finish') if (this[CLOSED]) this.emit('close') + this[EMITTING_END] = false } } emit (ev, data) { - if (ev === 'data') { + // error and close are only events allowed after calling destroy() + if (ev !== 'error' && ev !== 'close' && ev !== DESTROYED && this[DESTROYED]) + return + else if (ev === 'data') { if (!data) return if (this.pipes.length) - this.pipes.forEach(p => p.dest.write(data) || this.pause()) + this.pipes.forEach(p => + p.dest.write(data) === false && this.pause()) } else if (ev === 'end') { + // only actual end gets this treatment if (this[EMITTED_END] === true) return @@ -284,16 +390,17 @@ module.exports = class MiniPass extends EE { this.pipes.forEach(p => { p.dest.removeListener('drain', p.ondrain) - if (!p.opts || p.opts.end !== false) + if (p.opts.end) p.dest.end() }) } else if (ev === 'close') { this[CLOSED] = true // don't emit close before 'end' and 'finish' - if (!this[EMITTED_END]) + if (!this[EMITTED_END] && !this[DESTROYED]) return } + // TODO: replace with a spread operator when Node v4 support drops const args = new Array(arguments.length) args[0] = ev args[1] = data @@ -306,20 +413,40 @@ module.exports = class MiniPass extends EE { try { return super.emit.apply(this, args) } finally { - if (ev !== 'end') + if (!isEndish(ev)) this[MAYBE_EMIT_END]() else - this.removeAllListeners('end') + this.removeAllListeners(ev) } } // const all = await stream.collect() collect () { + const buf = [] + buf.dataLength = 0 + this.on('data', c => { + buf.push(c) + buf.dataLength += c.length + }) + return this.promise().then(() => buf) + } + + // const data = await stream.concat() + concat () { + return this[OBJECTMODE] + ? Promise.reject(new Error('cannot concat in objectMode')) + : this.collect().then(buf => + this[OBJECTMODE] + ? Promise.reject(new Error('cannot concat in objectMode')) + : this[ENCODING] ? buf.join('') : B.concat(buf, buf.dataLength)) + } + + // stream.promise().then(() => done, er => emitted error) + promise () { return new Promise((resolve, reject) => { - const buf = [] - this.on('data', c => buf.push(c)) - this.on('end', () => resolve(buf)) - this.on('error', reject) + this.on(DESTROYED, () => reject(new Error('stream destroyed'))) + this.on('end', () => resolve()) + this.on('error', er => reject(er)) }) } @@ -351,9 +478,11 @@ module.exports = class MiniPass extends EE { this.removeListener('data', ondata) resolve({ done: true }) } + const ondestroy = () => onerr(new Error('stream destroyed')) return new Promise((res, rej) => { reject = rej resolve = res + this.once(DESTROYED, ondestroy) this.once('error', onerr) this.once('end', onend) this.once('data', ondata) @@ -372,4 +501,37 @@ module.exports = class MiniPass extends EE { } return { next } } + + destroy (er) { + if (this[DESTROYED]) { + if (er) + this.emit('error', er) + else + this.emit(DESTROYED) + return this + } + + this[DESTROYED] = true + + // throw away all buffered data, it's never coming out + this.buffer = new Yallist() + this[BUFFERLENGTH] = 0 + + if (typeof this.close === 'function' && !this[CLOSED]) + this.close() + + if (er) + this.emit('error', er) + else // if no error to emit, still reject pending promises + this.emit(DESTROYED) + + return this + } + + static isStream (s) { + return !!s && (s instanceof Minipass || s instanceof EE && ( + typeof s.pipe === 'function' || // readable + (typeof s.write === 'function' && typeof s.end === 'function') // writable + )) + } } diff --git a/node_modules/pacote/node_modules/minipass/package.json b/node_modules/pacote/node_modules/minipass/package.json index d2adc87994780..59adc63528e77 100644 --- a/node_modules/pacote/node_modules/minipass/package.json +++ b/node_modules/pacote/node_modules/minipass/package.json @@ -1,8 +1,8 @@ { "_from": "minipass@^2.3.5", - "_id": "minipass@2.3.5", + "_id": "minipass@2.9.0", "_inBundle": false, - "_integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", + "_integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", "_location": "/pacote/minipass", "_phantomChildren": {}, "_requested": { @@ -18,10 +18,10 @@ "_requiredBy": [ "/pacote" ], - "_resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz", - "_shasum": "cacebe492022497f656b0f0f51e2682a9ed2d848", + "_resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "_shasum": "e713762e7d3e32fed803115cf93e04bca9fcc9a6", "_spec": "minipass@^2.3.5", - "_where": "/Users/zkat/Documents/code/work/npm/node_modules/pacote", + "_where": "/Users/ruyadorno/Documents/workspace/cli/node_modules/pacote", "author": { "name": "Isaac Z. Schlueter", "email": "i@izs.me", @@ -39,7 +39,7 @@ "description": "minimal implementation of a PassThrough stream", "devDependencies": { "end-of-stream": "^1.4.0", - "tap": "^12.0.1", + "tap": "^14.6.5", "through2": "^2.0.3" }, "files": [ @@ -58,10 +58,13 @@ "url": "git+https://github.com/isaacs/minipass.git" }, "scripts": { - "postpublish": "git push origin --all; git push origin --tags", + "postpublish": "git push origin --follow-tags", "postversion": "npm publish", "preversion": "npm test", - "test": "tap test/*.js --100" + "test": "tap" }, - "version": "2.3.5" + "tap": { + "check-coverage": true + }, + "version": "2.9.0" } diff --git a/node_modules/pacote/package.json b/node_modules/pacote/package.json index 58826586a3520..a60ed75270353 100644 --- a/node_modules/pacote/package.json +++ b/node_modules/pacote/package.json @@ -1,8 +1,8 @@ { - "_from": "pacote@9.5.8", - "_id": "pacote@9.5.8", + "_from": "pacote@9.5.9", + "_id": "pacote@9.5.9", "_inBundle": false, - "_integrity": "sha512-0Tl8Oi/K0Lo4MZmH0/6IsT3gpGf9eEAznLXEQPKgPq7FscnbUOyopnVpwXlnQdIbCUaojWy1Wd7VMyqfVsRrIw==", + "_integrity": "sha512-S1nYW9ly+3btn3VmwRAk2LG3TEh8mkrFdY+psbnHSk8oPODbZ28uG0Z0d3yI0EpqcpLR6BukoVRf3H4IbGCkPQ==", "_location": "/pacote", "_phantomChildren": { "safe-buffer": "5.1.2", @@ -11,12 +11,12 @@ "_requested": { "type": "version", "registry": true, - "raw": "pacote@9.5.8", + "raw": "pacote@9.5.9", "name": "pacote", "escapedName": "pacote", - "rawSpec": "9.5.8", + "rawSpec": "9.5.9", "saveSpec": null, - "fetchSpec": "9.5.8" + "fetchSpec": "9.5.9" }, "_requiredBy": [ "#USER", @@ -24,10 +24,10 @@ "/libcipm", "/libnpm" ], - "_resolved": "https://registry.npmjs.org/pacote/-/pacote-9.5.8.tgz", - "_shasum": "23480efdc4fa74515855c9ecf39cf64078f99786", - "_spec": "pacote@9.5.8", - "_where": "/Users/isaacs/dev/npm/cli", + "_resolved": "https://registry.npmjs.org/pacote/-/pacote-9.5.9.tgz", + "_shasum": "fa3a08629c9390b2b99769c55b2cc137e1a24df3", + "_spec": "pacote@9.5.9", + "_where": "/Users/ruyadorno/Documents/workspace/cli", "author": { "name": "Kat Marchán", "email": "kzm@sykosomatic.org" @@ -119,5 +119,5 @@ "update-coc": "weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'", "update-contrib": "weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'" }, - "version": "9.5.8" + "version": "9.5.9" } diff --git a/package-lock.json b/package-lock.json index 92e0c660ba44b..125f37f22e6c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4414,9 +4414,9 @@ } }, "pacote": { - "version": "9.5.8", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-9.5.8.tgz", - "integrity": "sha512-0Tl8Oi/K0Lo4MZmH0/6IsT3gpGf9eEAznLXEQPKgPq7FscnbUOyopnVpwXlnQdIbCUaojWy1Wd7VMyqfVsRrIw==", + "version": "9.5.9", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-9.5.9.tgz", + "integrity": "sha512-S1nYW9ly+3btn3VmwRAk2LG3TEh8mkrFdY+psbnHSk8oPODbZ28uG0Z0d3yI0EpqcpLR6BukoVRf3H4IbGCkPQ==", "requires": { "bluebird": "^3.5.3", "cacache": "^12.0.2", @@ -4450,9 +4450,9 @@ }, "dependencies": { "minipass": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz", - "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" diff --git a/package.json b/package.json index d051bfca9ba65..8f7add5b84b5f 100644 --- a/package.json +++ b/package.json @@ -110,7 +110,7 @@ "once": "~1.4.0", "opener": "^1.5.1", "osenv": "^0.1.5", - "pacote": "^9.5.8", + "pacote": "^9.5.9", "path-is-inside": "~1.0.2", "promise-inflight": "~1.0.1", "qrcode-terminal": "^0.12.0",