PageRenderTime 58ms CodeModel.GetById 9ms app.highlight 44ms RepoModel.GetById 1ms app.codeStats 0ms

/node_modules/minipass/index.js

https://bitbucket.org/coleman333/smartsite
JavaScript | 304 lines | 252 code | 43 blank | 9 comment | 76 complexity | e8c90e209dd3dcbc2d870c78bbc968f1 MD5 | raw file
  1'use strict'
  2const EE = require('events')
  3const Yallist = require('yallist')
  4const EOF = Symbol('EOF')
  5const MAYBE_EMIT_END = Symbol('maybeEmitEnd')
  6const EMITTED_END = Symbol('emittedEnd')
  7const CLOSED = Symbol('closed')
  8const READ = Symbol('read')
  9const FLUSH = Symbol('flush')
 10const FLUSHCHUNK = Symbol('flushChunk')
 11const SD = require('string_decoder').StringDecoder
 12const ENCODING = Symbol('encoding')
 13const DECODER = Symbol('decoder')
 14const FLOWING = Symbol('flowing')
 15const RESUME = Symbol('resume')
 16const BUFFERLENGTH = Symbol('bufferLength')
 17const BUFFERPUSH = Symbol('bufferPush')
 18const BUFFERSHIFT = Symbol('bufferShift')
 19const OBJECTMODE = Symbol('objectMode')
 20
 21// Buffer in node 4.x < 4.5.0 doesn't have working Buffer.from
 22// or Buffer.alloc, and Buffer in node 10 deprecated the ctor.
 23// .M, this is fine .\^/M..
 24let B = Buffer
 25/* istanbul ignore next */
 26if (!B.alloc) {
 27  B = require('safe-buffer').Buffer
 28}
 29
 30class MiniPass extends EE {
 31  constructor (options) {
 32    super()
 33    this[FLOWING] = false
 34    this.pipes = new Yallist()
 35    this.buffer = new Yallist()
 36    this[OBJECTMODE] = options && options.objectMode || false
 37    if (this[OBJECTMODE])
 38      this[ENCODING] = null
 39    else
 40      this[ENCODING] = options && options.encoding || null
 41    if (this[ENCODING] === 'buffer')
 42      this[ENCODING] = null
 43    this[DECODER] = this[ENCODING] ? new SD(this[ENCODING]) : null
 44    this[EOF] = false
 45    this[EMITTED_END] = false
 46    this[CLOSED] = false
 47    this.writable = true
 48    this.readable = true
 49    this[BUFFERLENGTH] = 0
 50  }
 51
 52  get bufferLength () { return this[BUFFERLENGTH] }
 53
 54  get encoding () { return this[ENCODING] }
 55  set encoding (enc) {
 56    if (this[OBJECTMODE])
 57      throw new Error('cannot set encoding in objectMode')
 58
 59    if (this[ENCODING] && enc !== this[ENCODING] &&
 60        (this[DECODER] && this[DECODER].lastNeed || this[BUFFERLENGTH]))
 61      throw new Error('cannot change encoding')
 62
 63    if (this[ENCODING] !== enc) {
 64      this[DECODER] = enc ? new SD(enc) : null
 65      if (this.buffer.length)
 66        this.buffer = this.buffer.map(chunk => this[DECODER].write(chunk))
 67    }
 68
 69    this[ENCODING] = enc
 70  }
 71
 72  setEncoding (enc) {
 73    this.encoding = enc
 74  }
 75
 76  write (chunk, encoding, cb) {
 77    if (this[EOF])
 78      throw new Error('write after end')
 79
 80    if (typeof encoding === 'function')
 81      cb = encoding, encoding = 'utf8'
 82
 83    if (!encoding)
 84      encoding = 'utf8'
 85
 86    // fast-path writing strings of same encoding to a stream with
 87    // an empty buffer, skipping the buffer/decoder dance
 88    if (typeof chunk === 'string' && !this[OBJECTMODE] &&
 89        // unless it is a string already ready for us to use
 90        !(encoding === this[ENCODING] && !this[DECODER].lastNeed)) {
 91      chunk = B.from(chunk, encoding)
 92    }
 93
 94    if (B.isBuffer(chunk) && this[ENCODING])
 95      chunk = this[DECODER].write(chunk)
 96
 97    try {
 98      return this.flowing
 99        ? (this.emit('data', chunk), this.flowing)
100        : (this[BUFFERPUSH](chunk), false)
101    } finally {
102      this.emit('readable')
103      if (cb)
104        cb()
105    }
106  }
107
108  read (n) {
109    try {
110      if (this[BUFFERLENGTH] === 0 || n === 0 || n > this[BUFFERLENGTH])
111        return null
112
113      if (this[OBJECTMODE])
114        n = null
115
116      if (this.buffer.length > 1 && !this[OBJECTMODE]) {
117        if (this.encoding)
118          this.buffer = new Yallist([
119            Array.from(this.buffer).join('')
120          ])
121        else
122          this.buffer = new Yallist([
123            B.concat(Array.from(this.buffer), this[BUFFERLENGTH])
124          ])
125      }
126
127      return this[READ](n || null, this.buffer.head.value)
128    } finally {
129      this[MAYBE_EMIT_END]()
130    }
131  }
132
133  [READ] (n, chunk) {
134    if (n === chunk.length || n === null)
135      this[BUFFERSHIFT]()
136    else {
137      this.buffer.head.value = chunk.slice(n)
138      chunk = chunk.slice(0, n)
139      this[BUFFERLENGTH] -= n
140    }
141
142    this.emit('data', chunk)
143
144    if (!this.buffer.length && !this[EOF])
145      this.emit('drain')
146
147    return chunk
148  }
149
150  end (chunk, encoding, cb) {
151    if (typeof chunk === 'function')
152      cb = chunk, chunk = null
153    if (typeof encoding === 'function')
154      cb = encoding, encoding = 'utf8'
155    if (chunk)
156      this.write(chunk, encoding)
157    if (cb)
158      this.once('end', cb)
159    this[EOF] = true
160    this.writable = false
161    if (this.flowing)
162      this[MAYBE_EMIT_END]()
163  }
164
165  // don't let the internal resume be overwritten
166  [RESUME] () {
167    this[FLOWING] = true
168    this.emit('resume')
169    if (this.buffer.length)
170      this[FLUSH]()
171    else if (this[EOF])
172      this[MAYBE_EMIT_END]()
173    else
174      this.emit('drain')
175  }
176
177  resume () {
178    return this[RESUME]()
179  }
180
181  pause () {
182    this[FLOWING] = false
183  }
184
185  get flowing () {
186    return this[FLOWING]
187  }
188
189  [BUFFERPUSH] (chunk) {
190    if (this[OBJECTMODE])
191      this[BUFFERLENGTH] += 1
192    else
193      this[BUFFERLENGTH] += chunk.length
194    return this.buffer.push(chunk)
195  }
196
197  [BUFFERSHIFT] () {
198    if (this.buffer.length) {
199      if (this[OBJECTMODE])
200        this[BUFFERLENGTH] -= 1
201      else
202        this[BUFFERLENGTH] -= this.buffer.head.value.length
203    }
204    return this.buffer.shift()
205  }
206
207  [FLUSH] () {
208    do {} while (this[FLUSHCHUNK](this[BUFFERSHIFT]()))
209
210    if (!this.buffer.length && !this[EOF])
211      this.emit('drain')
212  }
213
214  [FLUSHCHUNK] (chunk) {
215    return chunk ? (this.emit('data', chunk), this.flowing) : false
216  }
217
218  pipe (dest, opts) {
219    if (dest === process.stdout || dest === process.stderr)
220      (opts = opts || {}).end = false
221    const p = { dest: dest, opts: opts, ondrain: _ => this[RESUME]() }
222    this.pipes.push(p)
223
224    dest.on('drain', p.ondrain)
225    this[RESUME]()
226    return dest
227  }
228
229  addListener (ev, fn) {
230    return this.on(ev, fn)
231  }
232
233  on (ev, fn) {
234    try {
235      return super.on(ev, fn)
236    } finally {
237      if (ev === 'data' && !this.pipes.length && !this.flowing) {
238        this[RESUME]()
239      }
240    }
241  }
242
243  get emittedEnd () {
244    return this[EMITTED_END]
245  }
246
247  [MAYBE_EMIT_END] () {
248    if (!this[EMITTED_END] && this.buffer.length === 0 && this[EOF]) {
249      this.emit('end')
250      this.emit('prefinish')
251      this.emit('finish')
252      if (this[CLOSED])
253        this.emit('close')
254    }
255  }
256
257  emit (ev, data) {
258    if (ev === 'data') {
259      if (!data)
260        return
261
262      if (this.pipes.length)
263        this.pipes.forEach(p => p.dest.write(data) || this.pause())
264    } else if (ev === 'end') {
265      if (this[DECODER]) {
266        data = this[DECODER].end()
267        if (data) {
268          this.pipes.forEach(p => p.dest.write(data))
269          super.emit('data', data)
270        }
271      }
272      this.pipes.forEach(p => {
273        p.dest.removeListener('drain', p.ondrain)
274        if (!p.opts || p.opts.end !== false)
275          p.dest.end()
276      })
277      this[EMITTED_END] = true
278      this.readable = false
279    } else if (ev === 'close') {
280      this[CLOSED] = true
281      // don't emit close before 'end' and 'finish'
282      if (!this[EMITTED_END])
283        return
284    }
285
286    const args = new Array(arguments.length)
287    args[0] = ev
288    args[1] = data
289    if (arguments.length > 2) {
290      for (let i = 2; i < arguments.length; i++) {
291        args[i] = arguments[i]
292      }
293    }
294
295    try {
296      return super.emit.apply(this, args)
297    } finally {
298      if (ev !== 'end')
299        this[MAYBE_EMIT_END]()
300    }
301  }
302}
303
304module.exports = MiniPass