From 0d77912cccfaf0fe2ad6cb0f969f1dfae5d29345 Mon Sep 17 00:00:00 2001 From: Steven Hugg Date: Sat, 13 Jun 2020 20:28:58 -0500 Subject: [PATCH] x86: started using v86, freedos, fatfs, yasm, SmallerC --- .gitignore | 3 +- css/ui.css | 8 + index.html | 1 + lib/fatfs.js | 8275 +++++++++++++++++++++++++++++++++ lib/libv86.js | 1281 +++++ presets/x86/hello.asm | 13 + presets/x86/mandelg.asm | 152 + presets/x86/skeleton.yasm | 11 + presets/x86/snake.c | 418 ++ {wasm => res}/c64.bios | Bin {wasm => res}/c64.wasm | Bin res/freedos722.img | Bin 0 -> 737280 bytes res/seabios.bin | Bin 0 -> 131072 bytes res/vgabios.bin | Bin 0 -> 34816 bytes src/common/audio/z80worker.ts | 165 + src/common/baseplatform.ts | 4 +- src/ide/ui.ts | 10 +- src/platform/apple2.ts | 1 + src/platform/vectrex.ts | 1 + src/platform/x86.ts | 151 + src/worker/wasm/smlrc.js | 22 + src/worker/wasm/smlrc.wasm | Bin 0 -> 143889 bytes src/worker/wasm/yasm.js | 5051 ++++++++++++++++++++ src/worker/wasm/yasm.wasm | Bin 0 -> 2110468 bytes src/worker/workermain.ts | 121 + test/cli/testworker.js | 7 +- 26 files changed, 15685 insertions(+), 10 deletions(-) create mode 100644 lib/fatfs.js create mode 100644 lib/libv86.js create mode 100644 presets/x86/hello.asm create mode 100644 presets/x86/mandelg.asm create mode 100644 presets/x86/skeleton.yasm create mode 100644 presets/x86/snake.c rename {wasm => res}/c64.bios (100%) rename {wasm => res}/c64.wasm (100%) create mode 100644 res/freedos722.img create mode 100644 res/seabios.bin create mode 100644 res/vgabios.bin create mode 100644 src/common/audio/z80worker.ts create mode 100644 src/platform/x86.ts create mode 100644 src/worker/wasm/smlrc.js create mode 100644 src/worker/wasm/smlrc.wasm create mode 100644 src/worker/wasm/yasm.js create mode 100644 src/worker/wasm/yasm.wasm diff --git a/.gitignore b/.gitignore index 52ef0725..92a611b5 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ local ./test/output tests_output/ .DS_Store -tmp +tmp/ +web/ diff --git a/css/ui.css b/css/ui.css index 9565a069..8b8e0d3c 100644 --- a/css/ui.css +++ b/css/ui.css @@ -558,3 +558,11 @@ div.asset_toolbar { .book-title { font-size:12pt; } +.pc-console { + background-color: #000; + color: #7f7f7f; + white-space: pre; + font-family: "Andale Mono", "Menlo", "Lucida Console", monospace; + font-size: 10pt; + line-height: 1.2; +} \ No newline at end of file diff --git a/index.html b/index.html index b8cefa6b..667e9d26 100644 --- a/index.html +++ b/index.html @@ -516,6 +516,7 @@ if (window.location.host.endsWith('8bitworkshop.com')) { + diff --git a/lib/fatfs.js b/lib/fatfs.js new file mode 100644 index 00000000..9ffa7621 --- /dev/null +++ b/lib/fatfs.js @@ -0,0 +1,8275 @@ +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.fatfs = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i secSize) addToCache(i+1, data.slice(secSize)); + while (data.length > secSize) { + data = data.slice(secSize); + cache[++i] = data; + } + // simple highest-sectors-lose eviction policy for now + Object.keys(cache).sort().slice(opts.maxSectors).forEach(function (x) { + delete cache[x]; + }); + _.log(_.log.DBG, "Cache now contains:", Object.keys(cache).join(',')); + } + + return { + sectorSize: volume.sectorSize, + numSectors: volume.numSectors, + advice: function (val) { + if (!arguments.length) return advice; + else advice = val; + if (advice === 'SEQUENTIAL' || advice === 'NOREUSE') cache = {}; + return this; + }, + readSectors: function (i, dest, cb) { + // TODO: handle having partial parts of dest! + if (i in cache && dest.length === secSize) { + cache[i].copy(dest); + setImmediate(cb); + } else volume.readSectors(i, dest, function (e) { + if (e) cb(e); + else addToCache(i, dest), cb(); + }); + }, + writeSectors: (!volume.writeSectors) ? null : function (i, data, cb) { + volume.writeSectors(i, data, function (e) { + if (e) cb(e); + else addToCache(i, data), cb(); + }); + } + }; +}; + +}).call(this,require("timers").setImmediate) +},{"./helpers.js":4,"timers":35}],2:[function(require,module,exports){ +var S = require("./structs.js"), + _ = require("./helpers.js"); + +function _baseChain(vol) { + var chain = {}; + + chain.sectorSize = vol._sectorSize; + + function posFromOffset(off) { + var secSize = chain.sectorSize, + offset = off % secSize, + sector = (off - offset) / secSize; + return {sector:sector, offset:offset}; + } + + var sectorCache = vol._makeCache(); + Object.defineProperty(chain, 'cacheAdvice', { + enumerable: true, + get: function () { return sectorCache.advice(); }, + set: function (v) { sectorCache.advice(v); } + }); + chain._vol_readSectors = vol._readSectors.bind(vol, sectorCache); + chain._vol_writeSectors = vol._writeSectors.bind(vol, sectorCache); + + // cb(error, bytesRead, buffer) + chain.readFromPosition = function (targetPos, buffer, cb) { + if (typeof targetPos === 'number') targetPos = posFromOffset(targetPos); + if (typeof buffer === 'number') buffer = _.allocBuffer(buffer); + /* NOTE: to keep our contract with the volume driver, we need to read on _full_ sector boundaries! + So we divide the read into [up to] three parts: {preface, main, trailer} + This is kind of unfortunate, but in practice should often still be reasonably efficient. */ + if (targetPos.offset) chain.readSectors(targetPos.sector, _.allocBuffer(chain.sectorSize), function (e,d) { + if (e || !d) cb(e, 0, buffer); + else { // copy preface into `buffer` + var dBeg = targetPos.offset, + dEnd = dBeg + buffer.length; + d.copy(buffer, 0, dBeg, dEnd); + if (dEnd > d.length) readMain(); + else cb(null, buffer.length, buffer); + } + }); else readMain(); + function readMain() { + var prefaceLen = targetPos.offset && (chain.sectorSize - targetPos.offset), + trailerLen = (buffer.length - prefaceLen) % chain.sectorSize, + mainSector = (prefaceLen) ? targetPos.sector + 1 : targetPos.sector, + mainBuffer = (trailerLen) ? buffer.slice(prefaceLen, -trailerLen) : buffer.slice(prefaceLen); + if (mainBuffer.length) chain.readSectors(mainSector, mainBuffer, function (e,d) { + if (e || !d) cb(e, prefaceLen, buffer); + else if (!trailerLen) cb(null, buffer.length, buffer); + else readTrailer(); + }); else readTrailer(); + function readTrailer() { + var trailerSector = mainSector + (mainBuffer.length / chain.sectorSize); + chain.readSectors(trailerSector, _.allocBuffer(chain.sectorSize), function (e,d) { + if (e || !d) cb(e, buffer.length-trailerLen, buffer); + else { + d.copy(buffer, buffer.length-trailerLen, 0, trailerLen); + cb(null, buffer.length, buffer); + } + }); + } + } + }; + + // cb(error) + chain.writeToPosition = function (targetPos, data, cb) { + _.log(_.log.DBG, "WRITING", data.length, "bytes at", targetPos, "in", this.toJSON(), data); + if (typeof targetPos === 'number') targetPos = posFromOffset(targetPos); + + var prefaceBuffer = (targetPos.offset) ? data.slice(0, chain.sectorSize-targetPos.offset) : null; + if (prefaceBuffer) _modifySector(targetPos.sector, targetPos.offset, prefaceBuffer, function (e) { + if (e) cb(e); + else if (prefaceBuffer.length < data.length) writeMain(); + else cb(); + }); else writeMain(); + function writeMain() { + var prefaceLen = (prefaceBuffer) ? prefaceBuffer.length : 0, + trailerLen = (data.length - prefaceLen) % chain.sectorSize, + mainSector = (prefaceLen) ? targetPos.sector + 1 : targetPos.sector, + mainBuffer = (trailerLen) ? data.slice(prefaceLen, -trailerLen) : data.slice(prefaceLen); + if (mainBuffer.length) chain.writeSectors(mainSector, mainBuffer, function (e) { + if (e) cb(e); + else if (!trailerLen) cb(); + else writeTrailer(); + }); else writeTrailer(); + function writeTrailer() { + var trailerSector = mainSector + (mainBuffer.length / chain.sectorSize), + trailerBuffer = data.slice(data.length-trailerLen); // WORKAROUND: https://github.com/tessel/runtime/issues/721 + _modifySector(trailerSector, 0, trailerBuffer, cb); + } + } + function _modifySector(sec, off, data, cb) { + chain.readSectors(sec, _.allocBuffer(chain.sectorSize), function (e, orig) { + if (e) return cb(e); + orig || (orig = _.allocBuffer(chain.sectorSize, 0)); + //data.copy(orig, off); + orig.set(data, off); //SEH + chain.writeSectors(sec, orig, cb); + }); + } + }; + + return chain; +}; + + + +exports.clusterChain = function (vol, firstCluster, _parent) { + var chain = _baseChain(vol), + cache = [firstCluster]; + + chain.firstCluster = firstCluster; + + function _cacheIsComplete() { + return cache[cache.length-1] === 'eof'; + } + + function extendCacheToInclude(i, cb) { // NOTE: may `cb()` before returning! + if (i < cache.length) cb(null, cache[i]); + else if (_cacheIsComplete()) cb(null, 'eof'); + else vol.fetchFromFAT(cache[cache.length-1], function (e,d) { + if (e) cb(e); + else if (typeof d === 'string' && d !== 'eof') cb(S.err.IO()); + else { + cache.push(d); + extendCacheToInclude(i, cb); + } + }); + } + + function expandChainToLength(clusterCount, cb) { + if (!_cacheIsComplete()) throw Error("Must be called only when cache is complete!"); + else cache.pop(); // remove 'eof' entry until finished + + function addCluster(clustersNeeded, lastCluster) { + if (!clustersNeeded) cache.push('eof'), cb(); + else vol.allocateInFAT(lastCluster, function (e, newCluster) { + if (e) cb(e); + else vol.storeToFAT(lastCluster, newCluster, function (e) { + if (e) return cb(e); + + cache.push(newCluster); + addCluster(clustersNeeded-1, newCluster); + }); + }); + } + addCluster(clusterCount - cache.length, cache[cache.length - 1]); + } + + function shrinkChainToLength(clusterCount, cb) { + if (!_cacheIsComplete()) throw Error("Must be called only when cache is complete!"); + else cache.pop(); // remove 'eof' entry until finished + + function removeClusters(count, cb) { + if (!count) cache.push('eof'), cb(); + else vol.storeToFAT(cache.pop(), 'free', function (e) { + if (e) cb(e); + else removeClusters(count - 1, cb); + }); + } + // NOTE: for now, we don't remove the firstCluster ourselves; we should though! + if (clusterCount) removeClusters(cache.length - clusterCount, cb); + else removeClusters(cache.length - 1, cb); + } + + // [{firstSector,numSectors},{firstSector,numSectors},…] + function determineSectorGroups(sectorIdx, numSectors, alloc, cb) { + var sectorOffset = sectorIdx % vol._sectorsPerCluster, + clusterIdx = (sectorIdx - sectorOffset) / vol._sectorsPerCluster, + numClusters = Math.ceil((numSectors + sectorOffset) / vol._sectorsPerCluster), + chainLength = clusterIdx + numClusters; + extendCacheToInclude(chainLength-1, function (e,c) { + if (e) cb(e); + else if (c === 'eof' && alloc) expandChainToLength(chainLength, function (e) { + if (e) cb(e); + else _determineSectorGroups(); + }); + else _determineSectorGroups(); + }); + function _determineSectorGroups() { + // …now we have a complete cache + var groups = [], + _group = null; + for (var i = clusterIdx; i < chainLength; ++i) { + var c = (i < cache.length) ? cache[i] : 'eof'; + if (c === 'eof') break; + else if (_group && c !== _group._nextCluster) { + groups.push(_group); + _group = null; + } + if (!_group) _group = { + _nextCluster: c+1, + firstSector: vol._firstSectorOfCluster(c) + sectorOffset, + numSectors: vol._sectorsPerCluster - sectorOffset + }; else { + _group._nextCluster += 1; + _group.numSectors += vol._sectorsPerCluster; + } + sectorOffset = 0; // only first group is offset + } + if (_group) groups.push(_group); + cb(null, groups, i === chainLength); + } + } + + chain.readSectors = function (i, dest, cb) { + var groupOffset = 0, groupsPending; + determineSectorGroups(i, dest.length / chain.sectorSize, false, function (e, groups, complete) { + if (e) cb(e); + else if (!complete) groupsPending = -1, _pastEOF(cb); + else if ((groupsPending = groups.length)) groups.forEach(function (group) { + var groupLength = group.numSectors * chain.sectorSize, + groupBuffer = dest.slice(groupOffset, groupOffset += groupLength); + chain._vol_readSectors(group.firstSector, groupBuffer, function (e,d) { + if (e && groupsPending !== -1) groupsPending = -1, cb(e); + else if (--groupsPending === 0) cb(null, dest); + }); + }); + else cb(null, dest); // 0-length destination case + }); + }; + + // TODO: does this handle NOSPC condition? + chain.writeSectors = function (i, data, cb) { + var groupOffset = 0, groupsPending; + determineSectorGroups(i, data.length / chain.sectorSize, true, function (e, groups) { + if (e) cb(e); + else if ((groupsPending = groups.length)) groups.forEach(function (group) { + var groupLength = group.numSectors * chain.sectorSize, + groupBuffer = data.slice(groupOffset, groupOffset += groupLength); + chain._vol_writeSectors(group.firstSector, groupBuffer, function (e) { + if (e && groupsPending !== -1) groupsPending = -1, cb(e); + else if (--groupsPending === 0) cb(); + }); + }); + else cb(); // 0-length data case + }); + }; + + chain.truncate = function (numSectors, cb) { + extendCacheToInclude(Infinity, function (e,c) { + if (e) return cb(e); + + var currentLength = cache.length-1, + clustersNeeded = Math.ceil(numSectors / vol._sectorsPerCluster); + if (clustersNeeded < currentLength) shrinkChainToLength(clustersNeeded, cb); + else if (clustersNeeded > currentLength) expandChainToLength(clustersNeeded, cb); + else cb(); + }); + }; + + + chain.toJSON = function () { + return {firstCluster:firstCluster}; + }; + + return chain; +}; + +exports.sectorChain = function (vol, firstSector, numSectors) { + var chain = _baseChain(vol); + + chain.firstSector = firstSector; + chain.numSectors = numSectors; + + chain.readSectors = function (i, dest, cb) { + if (i < numSectors) chain._vol_readSectors(firstSector+i, dest, cb); + else _pastEOF(cb); + }; + + chain.writeSectors = function (i, data, cb) { + if (i < numSectors) chain._vol_writeSectors(firstSector+i, data, cb); + else _.delayedCall(cb, S.err.NOSPC()); + }; + + chain.truncate = function (i, cb) { + _.delayedCall(cb, S.err.INVAL()); + }; + + chain.toJSON = function () { + return {firstSector:firstSector, numSectors:numSectors}; + }; + + return chain; +}; + +// NOTE: used with mixed feelings, broken out to mark uses +function _pastEOF(cb) { _.delayedCall(cb, null, null); } + +},{"./helpers.js":4,"./structs.js":38}],3:[function(require,module,exports){ +var S = require("./structs.js"), + _ = require("./helpers.js"); + +var dir = exports; + +dir.iterator = function (dirChain, opts) { + opts || (opts = {}); + + var cache = {buffer:null, n: null}; + function getSectorBuffer(n, cb) { + if (cache.n === n) cb(null, cache.buffer); + else cache.n = cache.buffer = null, dirChain.readSectors(n, _.allocBuffer(dirChain.sectorSize), function (e,d) { + if (e) cb(e); + else if (!d) return cb(null, null); + else { + cache.n = n; + cache.buffer = d; + getSectorBuffer(n, cb); + } + }); + } + + var secIdx = 0, + off = {bytes:0}, + long = null; + function getNextEntry(cb) { + if (off.bytes >= dirChain.sectorSize) { + secIdx += 1; + off.bytes -= dirChain.sectorSize; + } + var entryPos = {chain:dirChain, sector:secIdx, offset:off.bytes}; + getSectorBuffer(secIdx, function (e, buf) { + if (e) return cb(S.err.IO()); + else if (!buf) return cb(null, null, entryPos); + + var entryIdx = off.bytes, + signalByte = buf[entryIdx]; + if (signalByte === S.entryDoneFlag) return cb(null, null, entryPos); + else if (signalByte === S.entryFreeFlag) { + off.bytes += S.dirEntry.size; + long = null; + if (opts.includeFree) return cb(null, {_free:true,_pos:entryPos}, entryPos); + else return getNextEntry(cb); // usually just skip these + } + + var attrByte = buf[entryIdx+S.dirEntry.fields.Attr.offset], + entryType = (attrByte === S.longDirFlag) ? S.longDirEntry : S.dirEntry_simple; + var entry = entryType.valueFromBytes(buf, off); + entry._pos = entryPos; + _.log(_.log.DBG, "entry:", entry, secIdx, entryIdx); + if (entryType === S.longDirEntry) { + var firstEntry; + if (entry.Ord & S.lastLongFlag) { + firstEntry = true; + entry.Ord &= ~S.lastLongFlag; + long = { + name: -1, + sum: entry.Chksum, + _rem: entry.Ord-1, + _arr: [] + } + } + if (firstEntry || long && entry.Chksum === long.sum && entry.Ord === long._rem--) { + var S_lde_f = S.longDirEntry.fields, + namepart = entry.Name1; + if (entry.Name1.length === S_lde_f.Name1.size/2) { + namepart += entry.Name2; + if (entry.Name2.length === S_lde_f.Name2.size/2) { + namepart += entry.Name3; + } + } + long._arr.push(namepart); + if (!long._rem) { + long.name = long._arr.reverse().join(''); + delete long._arr; + delete long._rem; + } + } else long = null; + } else if ((attrByte & 0x08) === 0) { // NOTE: checks `!entry.Attr.volume_id` + var bestName = null; + if (long && long.name) { + var pos = entryIdx + S.dirEntry.fields['Name'].offset, + sum = _.checksumName(buf, pos); + if (sum === long.sum) bestName = long.name; + } + if (!bestName) { + if (signalByte === S.entryIsE5Flag) entry.Name.filename = '\u00E5'+entry.Name.filename.slice(1); + + var nam = entry.Name.filename.replace(/ +$/, ''), + ext = entry.Name.extension.replace(/ +$/, ''); + // TODO: lowercase bits http://en.wikipedia.org/wiki/8.3_filename#Compatibility + // via NTRes, bits 0x08 and 0x10 http://www.fdos.org/kernel/fatplus.txt.1 + bestName = (ext) ? nam+'.'+ext : nam; + } + entry._name = bestName; + + // OPTIMIZATION: avoid processing any fields for non-matching entries + // TODO: we could make this automatic via getters, but…? + var _entryBuffer = buf.slice(off.bytes-S.dirEntry.size, off.bytes); + entry._full = function () { + var _entry = S.dirEntry.valueFromBytes(_entryBuffer); + _.extend(entry, _entry); + entry._size = entry.FileSize; + entry._firstCluster = (entry.FstClusHI << 16) + entry.FstClusLO; + return entry; + }; + + long = null; + return cb(null, entry, entryPos); + } else long = null; + getNextEntry(cb); + }); + } + + function iter(cb) { + getNextEntry(cb); + return iter; // TODO: previous value can't be re-used, so why make caller re-assign? + } + return iter; +}; + +function _updateEntry(vol, entry, newStats) { + if ('size' in newStats) entry._size = entry.FileSize = newStats.size; + + if ('_touch' in newStats) newStats.archive = newStats.atime = newStats.mtime = true; + if ('archive' in newStats) entry.Attr.archive = true; // TODO: also via newStats.mode? + + var _now; + function applyDate(d, prefix, timeToo, tenthToo) { + if (d === true) d = _now || (_now = new Date()); + entry[prefix+'Date'] = {year:d.getFullYear()-1980, month:d.getMonth()+1, day:d.getDate()}; + if (timeToo) { + entry[prefix+'Time'] = {hours:d.getHours(), minutes:d.getMinutes(), seconds_2:d.getSeconds()>>>1}; + if (tenthToo) { + var msec = (d.getSeconds() % 2)*1000 + d.getMilliseconds(); + entry[prefix+'TimeTenth'] = Math.floor(msec / 100); + } + } + } + if ('ctime' in newStats) applyDate(newStats.ctime, 'Crt', true, true); + if ('mtime' in newStats) applyDate(newStats.mtime, 'Wrt', true); + if ('atime' in newStats) applyDate(newStats.atime, 'LstAcc'); + + if ('mode' in newStats) { + entry.Attr.directory = (newStats.mode & S._I.FDIR) ? true : false; + entry.Attr.volume_id = (newStats.mode & S._I.FREG) ? false : true; + if (vol.opts.modmode === 0111) { + entry.Attr.archive = (newStats.mode & S._I.XUSR) ? true : false; + entry.Attr.system = (newStats.mode & S._I.XGRP) ? true : false; + entry.Attr.hidden = (newStats.mode & S._I.XOTH) ? true : false; + entry.Attr.readonly = (newStats.mode & S._I.WUSR) ? false : true; + } else if (vol.opts.modmode === 07000) { + entry.Attr.archive = (newStats.mode & S._I.SVTX) ? true : false; + entry.Attr.system = (newStats.mode & S._I.SGID) ? true : false; + entry.Attr.hidden = (newStats.mode & S._I.SUID) ? true : false; + entry.Attr.readonly = ( + newStats.mode & S._I.WUSR || + newStats.mode & S._I.WGRP || + newStats.mode & S._I.WOTH + ) ? false : true; + } + } + + if ('firstCluster' in newStats) { + entry.FstClusLO = newStats.firstCluster & 0xFFFF; + entry.FstClusHI = newStats.firstCluster >>> 16; + entry._firstCluster = newStats.firstCluster; + } + return entry; +} + +dir.makeStat = function (vol, entry) { + var stats = {}; // TODO: return an actual `instanceof fs.Stat` somehow? + + stats.isFile = function () { + return (!entry.Attr.volume_id && !entry.Attr.directory); + }; + stats.isDirectory = function () { + return entry.Attr.directory; + }; + stats.isBlockDevice = function () { return false; } + stats.isCharacterDevice = function () { return false; } + stats.isSymbolicLink = function () { return false; } + stats.isFIFO = function () { return false; } + stats.isSocket = function () { return false; } + stats.size = entry.FileSize; + stats.blksize = vol._sectorsPerCluster*vol._sectorSize; + stats.blocks = Math.ceil(stats.size / stats.blksize) || 1; + stats.nlink = 1; + + stats.mode = S._I.RUSR | S._I.RGRP | S._I.ROTH; + if (!entry.Attr.readonly) stats.mode |= S._I.WUSR | S._I.WGRP | S._I.WOTH; + if (entry.Attr.directory) stats.mode |= S._I.FDIR; + else if (!entry.Attr.volume_id) stats.mode |= S._I.FREG; + // NOTE: discussion at https://github.com/natevw/fatfs/issues/7 + if (vol.opts.modmode === 0111) { + // expose using executable bits, like Samba + if (entry.Attr.archive) stats.mode |= S._I.XUSR; + if (entry.Attr.system) stats.mode |= S._I.XGRP; + if (entry.Attr.hidden) stats.mode |= S._I.XOTH; + } else if (vol.opts.modmode === 07000) { + // expose using setXid/sticky bits, like MKS + if (entry.Attr.archive) stats.mode |= S._I.SVTX; + if (entry.Attr.system) stats.mode |= S._I.SGID; + if (entry.Attr.hidden) stats.mode |= S._I.SUID; + } + + stats.mode &= ~vol.opts.umask; + stats.uid = vol.opts.uid; + stats.gid = vol.opts.gid; + + function extractDate(prefix) { + var date = entry[prefix+'Date'], + time = entry[prefix+'Time'] || {hours:0, minutes:0, seconds_2:0}, + secs = time.seconds_2 * 2, + sect = entry[prefix+'TimeTenth'] || 0; + if (sect > 100) { + secs += 1; + sect -= 100; + } + return new Date(date.year+1980, date.month-1, date.day, time.hours, time.minutes, secs, sect*100); + } + stats.atime = extractDate('LstAcc'); + stats.mtime = extractDate('Wrt'); + stats.ctime = extractDate('Crt'); + + entry = { // keep immutable copy (with only the fields we need) + Attr: _.extend({},entry.Attr), + }; + + return stats; +}; + +dir.init = function (vol, dirInfo, cb) { + var dirChain = dirInfo.chain, + isRootDir = ('numSectors' in dirChain), // HACK: all others would be a clusterChain + initialCluster = _.allocBuffer(dirChain.sectorSize*vol._sectorsPerCluster), + entriesOffset = {bytes:0}; + initialCluster.fill(0); + function writeEntry(name, clusterNum) { + while (name.length < 8) name += " "; + S.dirEntry.bytesFromValue(_updateEntry(vol, { + Name: {filename:name, extension:" "}, + Attr: {directory:true} + }, {firstCluster:clusterNum, _touch:true,ctime:true}), initialCluster, entriesOffset); + } + if (!isRootDir) { + writeEntry(".", dirChain.firstCluster); + writeEntry("..", dirInfo.parent.chain.firstCluster); + }; + dirChain.writeToPosition(0, initialCluster, cb); +}; + +dir.addFile = function (vol, dirChain, entryInfo, opts, cb) { + if (typeof opts === 'function') { + cb = opts; + opts = {}; + } + var name = entryInfo.name, + entries = [], mainEntry; + entries.push(mainEntry = { + Name: _.shortname(name), + Attr: {directory:opts.dir||false}, + _name: name + }); + if (1 || mainEntry.Name._lossy) { // HACK: always write long names until `._lossy` is more useful! + var workaroundTessel427 = ('\uFFFF'.length !== 1); + if (workaroundTessel427) throw Error("Your JS runtime does not have proper Unicode string support. (If Tessel, is your firmware up-to-date?)"); + + // name entries should be 0x0000-terminated and 0xFFFF-filled + var S_lde_f = S.longDirEntry.fields, + ENTRY_CHUNK_LEN = (S_lde_f.Name1.size + S_lde_f.Name2.size + S_lde_f.Name3.size)/2, + partialLen = name.length % ENTRY_CHUNK_LEN, + paddingNeeded = partialLen && (ENTRY_CHUNK_LEN - partialLen); + if (paddingNeeded--) name += '\u0000'; + while (paddingNeeded-- > 0) name += '\uFFFF'; + // now fill in as many entries as it takes + var off = 0, + ord = 1; + while (off < name.length) entries.push({ + Ord: ord++, + Name1: name.slice(off, off+=S_lde_f.Name1.size/2), + Attr_raw: S.longDirFlag, + Chksum: null, + Name2: name.slice(off, off+=S_lde_f.Name2.size/2), + Name3: name.slice(off, off+=S_lde_f.Name3.size/2) + }); + entries[entries.length - 1].Ord |= S.lastLongFlag; + } + + if (entryInfo.tail) { + var name = mainEntry.Name.filename, + suffix = '~'+entryInfo.tail, + endIdx = name.indexOf(' '), + sufIdx = (~endIdx) ? Math.min(endIdx, name.length-suffix.length) : name.length-suffix.length; + if (sufIdx < 0) return cb(S.err.NAMETOOLONG()); // TODO: would EXIST be more correct? + mainEntry.Name.filename = name.slice(0,sufIdx)+suffix+name.slice(sufIdx+suffix.length); + _.log(_.log.DBG, "Shortname amended to:", mainEntry.Name); + } + + vol.allocateInFAT(dirChain.firstCluster || 2, function (e,fileCluster) { + if (e) return cb(e); + + var nameBuf = S.dirEntry.fields['Name'].bytesFromValue(mainEntry.Name), + nameSum = _.checksumName(nameBuf); + // TODO: finalize initial properties… (via `opts.mode` instead?) + _updateEntry(vol, mainEntry, {firstCluster:fileCluster, size:0, ctime:true,_touch:true}); + mainEntry._pos = _.adjustedPos(vol, entryInfo.target, S.dirEntry.size*(entries.length-1)); + entries.slice(1).forEach(function (entry) { + entry.Chksum = nameSum; + }); + entries.reverse(); + if (entryInfo.lastEntry) entries.push({}); + + var entriesData = _.allocBuffer(S.dirEntry.size*entries.length), + dataOffset = {bytes:0}; + entries.forEach(function (entry) { + var entryType = ('Ord' in entry) ? S.longDirEntry : S.dirEntry; + entryType.bytesFromValue(entry, entriesData, dataOffset); + }); + + _.log(_.log.DBG, "Writing", entriesData.length, "byte directory entry", mainEntry, "into", dirChain.toJSON(), "at", entryInfo.target); + dirChain.writeToPosition(entryInfo.target, entriesData, function (e) { + // TODO: if we get error, what/should we clean up? + if (e) cb(e); + else cb(null, mainEntry, vol.chainForCluster(fileCluster, dirChain)); + }); + }); +}; + +dir.findInDirectory = function (vol, dirChain, name, opts, cb) { + var matchName = name.toUpperCase(), + tailName = (opts.prepareForCreate) ? _.shortname(name) : null, + maxTail = 0; + + function processNext(next) { + next = next(function (e, d, entryPos) { + if (e) cb(e); + else if (!d) cb(S.err.NOENT(), {tail:maxTail, target:entryPos, lastEntry:true}); + else if (d._free) processNext(next); // TODO: look for long enough reusable run + else if (d._name.toUpperCase() === matchName) return cb(null, d._full()); + else if (!opts.prepareForCreate) processNext(next); + else { + var dNum = 1, + dName = d.Name.filename, + dTail = dName.match(/(.*)~(\d+)/); + if (dTail) { + dNum = +dTail[2]; + dName = dTail[1]; + } + if (tailName.extension === d.Name.extension && + tailName.filename.indexOf(dName) === 0) + { + maxTail = Math.max(dNum+1, maxTail); + } + processNext(next); + } + }); + } + processNext(dir.iterator(dirChain, {includeFree:(0 && opts.prepareForCreate)})); +}; + +dir.updateEntry = function (vol, entry, newStats, cb) { + if (!entry._pos || !entry._pos.chain) throw Error("Entry source unknown!"); + + var entryPos = entry._pos, + newEntry = _updateEntry(vol, entry, newStats), + data = S.dirEntry.bytesFromValue(newEntry); + _.log(_.log.DBG, "UPDATING ENTRY", newStats, newEntry, entryPos, data); + // TODO: if write fails, then entry becomes corrupt! + entryPos.chain.writeToPosition(entryPos, data, cb); +}; + +},{"./helpers.js":4,"./structs.js":38}],4:[function(require,module,exports){ +(function (Buffer,setImmediate){ +var S = require("./structs.js"), + _xok = require('xok'); + +// ponyfills for older node.js +exports.allocBuffer = Buffer.alloc || function (len, val) { + var b = Buffer(len); + if (arguments.length > 1) b.fill(val); + return b; +}; +exports.bufferFrom = Buffer.from || function (arg0, arg1) { + return (arguments.length > 1) ? Buffer(arg0, arg1) : Buffer(arg0); +}; + +// flag for WORKAROUND: https://github.com/tessel/beta/issues/380 +exports.workaroundTessel380 = !Buffer.from && function () { + var b = Buffer([0]), + s = b.slice(0); + return ((s[0] = 0xFF) !== b[0]); +}(); + + +// WORKAROUND: https://github.com/tessel/beta/issues/433 +var oldslice; +if (!Buffer.alloc && Buffer(5).slice(10).length < 0) oldslice = Buffer.prototype.slice, Buffer.prototype.slice = function (s, e) { + if (s > this.length) s = this.length; + // ~WORKAROUND: https://github.com/tessel/beta/issues/434 + return (arguments.length > 1) ? oldslice.call(this, s, e) : oldslice.call(this, s); +} + +exports.absoluteSteps = function (path) { + var steps = []; + path.split('/').forEach(function (str) { + // NOTE: these should actually be fine, just wasteful… + if (str === '..') steps.pop(); + else if (str && str !== '.') steps.push(str); + }); + return steps.map(exports.longname); +}; + +exports.absolutePath = function (path) { + return '/'+exports.absoluteSteps(path).join('/'); +}; + +exports.parseFlags = function (flags) { + // read, write, append, create, truncate, exclusive + var info, _dir; // NOTE: there might be more clever ways to "parse", but… + if (flags[0] === '\\') { + // internal flag used internally to `fs.open` directories without `S.err.ISDIR()` + flags = flags.slice(1); + _dir = true; + } + switch (flags) { + case 'r': info = {read:true, write:false, create:false}; break; + case 'r+': info = {read:true, write:true, create:false}; break; + case 'rs': info = {read:true, write:false, create:false, sync:true}; break; + case 'rs+': info = {read:true, write:true, create:false, sync:true}; break; + case 'w': info = {read:false, write:true, create:true, truncate:true}; break; + case 'wx': info = {read:false, write:true, create:true, exclusive:true}; break; + case 'w+': info = {read:true, write:true, create:true, truncate:true}; break; + case 'wx+': info = {read:true, write:true, create:true, exclusive:true}; break; + case 'a': info = {read:false, write:true, create:true, append:true}; break; + case 'ax': info = {read:false, write:true, create:true, append:true, exclusive:true}; break; + case 'a+': info = {read:true, write:true, create:true, append:true}; break; + case 'ax+': info = {read:true, write:true, create:true, append:true, exclusive:true}; break; + default: throw Error("Uknown mode: "+flags); // TODO: throw as `S.err.INVAL` + } + if (info.sync) throw Error("Mode not implemented."); // TODO: what would this require of us? + if (_dir) info._openDir = true; + return info; +}; + + +// TODO: these are great candidates for special test coverage! +var _snInvalid = /[^A-Z0-9$%'-_@~`!(){}^#&.]/g; // NOTE: '.' is not valid but we split it away +exports.shortname = function (name) { + var lossy = false; + // TODO: support preservation of case for otherwise non-lossy name! + name = name.toUpperCase().replace(/ /g, '').replace(/^\.+/, ''); + name = name.replace(_snInvalid, function () { + lossy = true; + return '_'; + }); + + var parts = name.split('.'), + basis3 = parts.pop(), + basis8 = parts.join(''); + if (!parts.length) { + basis8 = basis3; + basis3 = ' '; + } + if (basis8.length > 8) { + basis8 = basis8.slice(0,8); + // NOTE: technically, spec's "lossy conversion" flag is NOT set by excess length. + // But since lossy conversion and truncated names both need a numeric tail… + lossy = true; + } else while (basis8.length < 8) basis8 += ' '; + if (basis3.length > 3) { + basis3 = basis3.slice(0,3); + lossy = true; + } else while (basis3.length < 3) basis3 += ' '; + + return {filename:basis8, extension:basis3, _lossy:lossy}; + return {basis:[basis8,basis3], lossy:lossy}; +}; +//shortname("autoexec.bat") => {basis:['AUTOEXEC','BAT'],lossy:false} +//shortname("autoexecutable.batch") => {basis:['AUTOEXEC','BAT'],lossy:true} +// TODO: OS X stores `shortname("._.Trashes")` as ['~1', 'TRA'] — should we? + +var _lnInvalid = /[^a-zA-Z0-9$%'-_@~`!(){}^#&.+,;=[\] ]/g; +exports.longname = function (name) { + name = name.trim().replace(/\.+$/, '').replace(_lnInvalid, function (c) { + if (c.length > 1) throw Error("Internal problem: unexpected match length!"); + if (c.charCodeAt(0) > 127) return c; + else throw Error("Invalid character "+JSON.stringify(c)+" in name."); + lossy = true; + return '_'; + }); + if (name.length > 255) throw Error("Name is too long."); + return name; +}; + +function nameChkSum(sum, c) { + return ((sum & 1) ? 0x80 : 0) + (sum >>> 1) + c & 0xFF; +} + +// WORKAROUND: https://github.com/tessel/beta/issues/335 +function reduceBuffer(buf, start, end, fn, res) { + // NOTE: does not handle missing `res` like Array.prototype.reduce would + for (var i = start; i < end; ++i) { + res = fn(res, buf[i]); + } + return res; +} + +exports.checksumName = function (buf,off) { + off || (off = 0); + var len = S.dirEntry.fields['Name'].size; + return reduceBuffer(buf, off, off+len, nameChkSum, 0); +}; + + +/* comparing C rounding trick from FAT spec with Math.ceil +function tryBoth(d) { + var a = ((D.RootEntCnt * 32) + (D.BytsPerSec - 1)) / D.BytsPerSec >>> 0, + b = Math.ceil((D.RootEntCnt * 32) / D.BytsPerSec); + if (b !== a) console.log("try", b, a, (b === a) ? '' : '*'); + return (b === a); +} +// BytsPerSec — "may take on only the following values: 512, 1024, 2048 or 4096" +[512, 1024, 2048, 4096].forEach(function (bps) { + // RootEntCnt — "a count that when multiplied by 32 results in an even multiple of BPB_BytsPerSec" + for (var evenMultiplier = 0; evenMultiplier < 1024*1024*16; evenMultiplier += 2) { + var rec = (bps * evenMultiplier) / 32; + tryBoth({RootEntCnt:rec, BytsPerSec:bps}); + } +}); +*/ + +exports.fmtHex = function (n, ff) { + return (1+ff+n).toString(16).slice(1); +}; + +exports.delayedCall = function (fn) { + if (!fn) throw Error("No function provided!"); // debug aid + var ctx = this, + args = Array.prototype.slice.call(arguments, 1); + setImmediate(function () { + fn.apply(ctx, args); + }); +}; + +exports.adjustedPos = function (vol, pos, bytes) { + var _pos = { + chain: pos.chain, + sector: pos.sector, + offset: pos.offset + bytes + }, secSize = vol._sectorSize; + while (_pos.offset >= secSize) { + _pos.sector += 1; + _pos.offset -= secSize; + } + return _pos; +}; + +exports.extend = _xok; + +var _prevDbg = Date.now(), + _thresh = 50; + +function log(level) { + if (level < log.level) return; + + var now = Date.now(), + diff = now - _prevDbg; + arguments[0] = ((diff < _thresh) ? " " : '') + diff.toFixed(0) + "ms"; + console.log.apply(console, arguments); + _prevDbg = now; +} +log.DBG = -4; +log.INFO = -3; +log.WARN = -2; +log.ERR = -1; + +log.level = log.WARN; + +exports.log = log; + +}).call(this,require("buffer").Buffer,require("timers").setImmediate) +},{"./structs.js":38,"buffer":8,"timers":35,"xok":37}],5:[function(require,module,exports){ +(function (process){ +var events = require('events'), + streams = require('stream'), + fifolock = require('fifolock'), + S = require("./structs.js"), + _ = require("./helpers.js"); + +//_.log.level = _.log.DBG; + +exports.createFileSystem = function (volume, opts, cb) { + if (typeof opts === 'function') { + cb = opts; + opts = null; + } + opts = _.extend({ + // c.f. https://www.kernel.org/doc/Documentation/filesystems/vfat.txt + ro: false, + noatime: true, + modmode: 0111, // or `07000` + umask: ('umask' in process) ? process.umask() : 0022, + uid: ('getuid' in process) ? process.getuid() : 0, + gid: ('getgid' in process) ? process.getgid() : 0 + }, opts); + if (!volume.writeSectors) opts.ro = true; + if (opts.ro) opts.noatime = true; // natch + + var fs = new events.EventEmitter(), + vol = null, + dir = require("./dir.js"), + c = require("./chains.js"), + q = fifolock(); + + var GROUP = (_.log.level < _.log.INFO) ? q.TRANSACTION_WRAPPER.bind({ + postAcquire: function (proceed) { + _.log(_.log.DBG, "=== Starting GROUP ==="); + proceed(); + }, + preRelease: function (finish) { + _.log(_.log.DBG, "=== Finishing GROUP ==="); + finish(); + } + }) : q.TRANSACTION_WRAPPER; + + q.acquire(function (unlock) { // because of this, callers can start before 'ready' + var d = _.allocBuffer(volume.sectorSize); + volume.readSectors(0, d, function (e) { + if (e) fs.emit('error', e); + else { + try { + init(d); + } catch (e) { + fs.emit('error', e); + unlock(); + return; + } + fs.emit('ready'); + } + unlock(); + }); + }); + + if (cb) fs.on('error', cb).on('ready', cb.bind(null, null)); + + function init(bootSector) { + vol = require("./vol.js").init(volume, opts, bootSector); + fs._dirIterator = dir.iterator.bind(dir); + + var entryInfoByPath = {}, + baseEntry = { + _refs: 0, + _record: function () { + entryInfoByPath[this.path] = this; + if (this.parent) this.parent.retain(); + return this; + }, + retain: function () { + if (!this._refs) this._record(); + this._refs += 1; + return this; + }, + release: function () { + this._refs -= 1; + if (!this._refs) this._rescind(); + }, + _rescind: function () { + if (this.parent) this.parent.release(); + delete entryInfoByPath[this.path]; + } + }; + fs._createSharedEntry = function (path, entry, chain, parent) { + return _.extend(Object.create(baseEntry), { + _refs: 0, // WORKAROUND: https://github.com/tessel/beta/issues/455 + path: path, + entry: entry, + chain: chain, + parent: parent + }).retain(); + }; + fs._createSharedEntry("/", {Attr:{directory:true}}, vol.rootDirectoryChain); + fs._sharedEntryForSteps = function (steps, opts, cb) { // NOTE: may `cb` before returning! + var path = steps.join('/') || "/", + name = steps.pop(), // n.b. + info = entryInfoByPath[path]; + if (info) cb(null, info.retain()); + else fs._sharedEntryForSteps(steps, {}, function (e,parentInfo) { // n.b. `steps` don't include `name` + if (e) cb(e); + else if (!parentInfo.entry.Attr.directory) cb(S.err.NOTDIR()) + else dir.findInDirectory(vol, parentInfo.chain, name, opts, function (e,entry) { + if (e && !opts.prepareForCreate) cb(e); + else if (e) cb(e, {missingChild:_.extend(entry, {name:name}), parent:parentInfo}); + else cb(null, fs._createSharedEntry(path, entry, vol.chainForCluster(entry._firstCluster), parentInfo)); + }); + }); + } + + fs._updateEntry = dir.updateEntry.bind(dir, vol); + fs._makeStat = dir.makeStat.bind(dir, vol); + fs._addFile = dir.addFile.bind(dir, vol); + fs._initDir = dir.init.bind(dir, vol); + } + + + + /**** ---- CORE API ---- ****/ + + // NOTE: we really don't share namespace, but avoid first three anyway… + var fileDescriptors = [null,null,null]; + + fs.open = function (path, flags, mode, cb, _n_) { + if (typeof mode === 'function') { + _n_ = cb; + cb = mode; + mode = 0666; + } + cb = GROUP(cb, function () { + var _fd = {flags:null,entry:null,chain:null,pos:0}, + f = _.parseFlags(flags); + if (vol.opts.ro && (f.write || f.create || f.truncate)) return _.delayedCall(cb, S.err.ROFS()); + else _fd.flags = f; + + fs._sharedEntryForSteps(_.absoluteSteps(path), {prepareForCreate:f.create}, function (e,info) { + if (e && !(e.code === 'NOENT' && f.create && info)) cb(e); + else if (e) fs._addFile(info.parent.chain, info.missingChild, {dir:f._openDir}, function (e,newEntry,newChain) { + if (e) cb(e); + else finish(fs._createSharedEntry(_.absolutePath(path), newEntry, newChain, info.parent)); + }); + else if (info && f.exclusive) cb(S.err.EXIST()); + else if (info.entry.Attr.directory && !f._openDir) cb(S.err.ISDIR()); + else if (f.write && info.entry.Attr.readonly) cb(S.err.ACCES()); + else finish(info); + function finish(fileInfo) { + var fd = fileDescriptors.push(_fd)-1; + _fd.info = fileInfo; + _fd.entry = fileInfo.entry; + _fd.chain = fileInfo.chain; + if (f.append) _fd.pos = _fd.entry._size; + if (f._openDir) _fd.chain.cacheAdvice = 'WILLNEED'; + if (f.truncate && _fd.entry._size) fs.ftruncate(fd, 0, function (e) { + cb(e, fd); + }, '_nested_'); + else _.delayedCall(cb, null, fd); // (delay in case fs._sharedEntryForSteps all cached!) + } + }); + }, (_n_ === '_nested_')); }; + + fs.fstat = function (fd, cb, _n_) { cb = GROUP(cb, function () { + var _fd = fileDescriptors[fd]; + if (!_fd || !_fd.flags.read) _.delayedCall(cb, S.err.BADF()); + else _.delayedCall(cb, null, fs._makeStat(_fd.entry)); + }, (_n_ === '_nested_')); }; + + fs.futimes = function (fd, atime, mtime, cb, _n_) { cb = GROUP(cb, function () { + var _fd = fileDescriptors[fd]; + if (!_fd || !_fd.flags.write) _.delayedCall(cb, S.err.BADF()); + // NOTE: ctime would get touched on POSIX; but we map that to create time! + else fs._updateEntry(_fd.entry, {atime:atime||true,mtime:mtime||true}, cb); + }, (_n_ === '_nested_')); }; + + fs.fchmod = function (fd, mode, cb, _n_) { cb = GROUP(cb, function () { + var _fd = fileDescriptors[fd]; + if (!_fd || !_fd.flags.write) _.delayedCall(cb, S.err.BADF()); + else { + mode &= S._I._chmoddable; + if (_fd.entry.Attr.directory) mode |= S._I.FDIR; + else if (!_fd.entry.Attr.volume_id) mode |= S._I.FREG; + fs._updateEntry(_fd.entry, {mode:mode}, cb); + } + }, (_n_ === '_nested_')); }; + + fs.read = function (fd, buf, off, len, pos, cb, _n_) { cb = GROUP(cb, function () { + var _fd = fileDescriptors[fd]; + if (!_fd || !_fd.flags.read) _.delayedCall(cb, S.err.BADF()); + + var _pos = (pos === null) ? _fd.pos : pos, + _len = Math.min(len, _fd.entry._size - _pos), + _buf = buf.slice(off,off+_len); + _fd.chain.readFromPosition(_pos, _buf, function (e,bytes,slice) { + if (_.workaroundTessel380) _buf.copy(buf,off); // WORKAROUND: https://github.com/tessel/beta/issues/380 + _fd.pos = _pos + bytes; + if (e || vol.opts.noatime) finish(e); + else fs._updateEntry(_fd.entry, {atime:true}, finish); + function finish(e) { + cb(e,bytes,buf); + } + }); + }, (_n_ === '_nested_')); }; + + fs._readdir = function (fd, cb, _n_) { cb = GROUP(cb, function () { + var _fd = fileDescriptors[fd]; + if (!_fd || !_fd.flags.read) _.delayedCall(cb, S.err.BADF()); + else { + var entryNames = [], + getNextEntry = fs._dirIterator(_fd.chain); + function processNext() { + getNextEntry(function (e,d) { + if (e) cb(e); + else if (!d && !entryNames.length) cb(null, entryNames); // WORKAROUND: https://github.com/tessel/beta/issues/435 + else if (!d) cb(null, entryNames.sort()); // NOTE: sort not required, but… [simplifies tests for starters!] + else { + if (d._name !== "." && d._name !== "..") entryNames.push(d._name); + processNext(); + } + }); + } + processNext(); + } + }, (_n_ === '_nested_')); }; + + fs._mkdir = function (fd, cb, _n_) { cb = GROUP(cb, function () { + var _fd = fileDescriptors[fd]; + if (!_fd || !_fd.flags.write) _.delayedCall(cb, S.err.BADF()); + else fs._initDir(_fd.info, cb); + }, (_n_ === '_nested_')); }; + + fs.write = function (fd, buf, off, len, pos, cb, _n_) { cb = GROUP(cb, function () { + var _fd = fileDescriptors[fd]; + if (!_fd || !_fd.flags.write) _.delayedCall(cb, S.err.BADF()); + + var _pos = (pos === null || _fd.flags.append) ? _fd.pos : pos, + _buf = buf.slice(off,off+len); + if (_pos > _fd.entry._size) { + // TODO: handle huge jumps by zeroing clusters individually? + var padLen = _pos - _fd.entry._size, + padBuf = _.allocBuffer(padLen + _buf.length); + padBuf.fill(0x00, 0, padLen); + _buf.copy(padBuf, padLen); + _pos = _fd.entry._size; + _buf = padBuf; + } + _fd.chain.writeToPosition(_pos, _buf, function (e) { + _fd.pos = _pos + len; + var newSize = Math.max(_fd.entry._size, _fd.pos), + newInfo = {size:newSize,_touch:true}; + fs._updateEntry(_fd.entry, newInfo, function (ee) { + cb(e||ee, len, buf); + }); + }); + }, (_n_ === '_nested_')); }; + + fs.ftruncate = function (fd, len, cb, _n_) { cb = GROUP(cb, function () { + var _fd = fileDescriptors[fd]; + if (!_fd || !_fd.flags.write) _.delayedCall(cb, S.err.BADF()); + + var newStats = {size:len,_touch:true}; + // NOTE: we order operations for best state in case of only partial success + if (len === _fd.entry._size) _.delayedCall(cb); + else if (len < _fd.entry._size) fs._updateEntry(_fd.entry, newStats, function (e) { + if (e) cb(e); + else _fd.chain.truncate(Math.ceil(len / _fd.chain.sectorSize), cb); + }); // TODO: handle huge file expansions without as much memory pressure + else _fd.chain.writeToPosition(_fd.entry._size, _.allocBuffer(len-_fd.entry._size, 0x00), function (e) { + if (e) cb(e); + else fs._updateEntry(_fd.entry, newStats, cb); + }); + }, (_n_ === '_nested_')); }; + + // 'NORMAL', 'SEQUENTIAL', 'RANDOM', 'WILLNEED', 'DONTNEED', 'NOREUSE' + fs._fadviseSync = function (fd, off, len, advice) { + if (off !== 0 || len !== 0) throw Error("Cache advise can currently be given only for whole file!"); + var _fd = fileDescriptors[fd]; + if (!_fd) throw S.err.BADF(); + else _fd.chain.cacheAdvice = advice; + }; + + fs.fsync = function (fd, cb) { + // NOTE: we'll need to flush write cache here once we have one… + var _fd = fileDescriptors[fd]; + if (!_fd) _.delayedCall(cb, S.err.BADF()); + else _.delayedCall(cb); + }; + + fs.close = function (fd, cb) { + var _fd = fileDescriptors[fd]; + if (!_fd) _.delayedCall(cb, S.err.BADF()); + else setTimeout(_fd.info.release.bind(_fd.info), 500), _.delayedCall(cb, fileDescriptors[fd] = null); + }; + + + /* STREAM WRAPPERS */ + + var workaroundTessel436; + try { + new require('stream').Readable({encoding:'utf8'}); + new streams.Readable({encoding:'utf8'}); + } catch (e) { + workaroundTessel436 = true; + } + + function _createStream(StreamType, path, opts) { + // [NOT REALLY A] WORKAROUND: https://github.com/tessel/beta/issues/436 + if (workaroundTessel436 && 'encoding' in opts) { + console.warn("Tessel does not currently support encoding option for Readable streams, discarding!"); + delete opts.encoding; + } + + var fd = (opts.fd !== null) ? opts.fd : '_opening_', + pos = opts.start, + stream = new StreamType(opts); + + if (fd === '_opening_') fs.open(path, opts.flags, opts.mode, function (e,_fd) { + if (e) { + fd = '_open_error_'; + stream.emit('error', e); + } else { + fd = _fd; + fs._fadviseSync(fd, 0, 0, 'SEQUENTIAL'); + stream.emit('open', fd); + } + }); + + function autoClose(tombstone) { // NOTE: assumes caller will clear `fd` + if (opts.autoClose) fs.close(fd, function (e) { + if (e) stream.emit('error', e); + else stream.emit('close'); + }); + fd = tombstone; + } + + if (StreamType === streams.Readable) { + + stream._read = function (n) { + var buf; + // TODO: optimize to fetch at least a full sector regardless of `n`… + n = Math.min(n, opts.end-pos); + if (fd === '_opening_') stream.once('open', function () { stream._read(n); }); + else if (pos > opts.end) stream.push(null); + else if (n > 0) buf = _.allocBuffer(n), fs.read(fd, buf, 0, n, pos, function (e,n,d) { + if (e) { + autoClose('_read_error_'); + stream.emit('error', e); + } else stream.push((n) ? d.slice(0,n) : null); + }), pos += n; + else stream.push(null); + }; + + stream.once('end', function () { + autoClose('_ended_'); + }); + + } else if (StreamType === streams.Writable) { + + stream.bytesWritten = 0; + + stream._write = function (data, _enc, cb) { + if (fd === '_opening_') stream.once('open', function () { stream._write(data, null, cb); }); + else fs.write(fd, data, 0, data.length, pos, function (e,n) { + if (e) { + autoClose('_write_error_'); + cb(e); + } else { + stream.bytesWritten += n; + cb(); + } + }), pos += data.length; + }; + + stream.once('finish', function () { + autoClose('_finished_'); + }); + + } + + return stream; + } + + fs.createReadStream = function (path, opts) { + return _createStream(streams.Readable, path, _.extend({ + start: 0, + end: Infinity, + flags: 'r', + mode: 0666, + encoding: null, + fd: null, // ??? see https://github.com/joyent/node/issues/7708 + autoClose: true + }, opts)); + }; + + fs.createWriteStream = function (path, opts) { + return _createStream(streams.Writable, path, _.extend({ + start: 0, + flags: 'w', + mode: 0666, + //encoding: null, // see https://github.com/joyent/node/issues/7710 + fd: null, // ??? see https://github.com/joyent/node/issues/7708 + autoClose: true + }, opts, {decodeStrings:true, objectMode:false})); + }; + + + /* PATH WRAPPERS (albeit the only public interface for some folder operations) */ + + function _fdOperation(path, opts, fn, cb) { cb = GROUP(cb, function () { + opts.advice || (opts.advice = 'NORMAL'); + fs.open(path, opts.flag, function (e,fd) { + if (e) cb(e); + else fs._fadviseSync(fd, 0, 0, opts.advice), fn(fd, function () { + var ctx = this, args = arguments; + fs.close(fd, function (closeErr) { + cb.apply(ctx, args); + }, '_nested_'); + }); + }, '_nested_'); + }); } + + fs.stat = fs.lstat = function (path, cb) { + _fdOperation(path, {flag:'r'}, function (fd, cb) { + fs.fstat(fd, cb, '_nested_'); + }, cb); + }; + + fs.exists = function(path, cb){ + fs.stat(path, function(err){ + cb(err ? false : true); + }); + }; + + fs.readFile = function (path, opts, cb) { + if (typeof opts === 'function') { + cb = opts; + opts = {}; + } + opts.flag || (opts.flag = 'r'); + opts.advice || (opts.advice = 'NOREUSE'); + _fdOperation(path, opts, function (fd, cb) { + fs.fstat(fd, function (e,stat) { + if (e) return cb(e); + else { + var buffer = _.allocBuffer(stat.size); + fs.read(fd, buffer, 0, buffer.length, null, function (e) { + if (e) cb(e); + else cb(null, (opts.encoding) ? buffer.toString(opts.encoding) : buffer); + }, '_nested_'); + } + }, '_nested_'); + }, cb); + }; + + fs.writeFile = function (path, data, opts, cb) { + if (typeof opts === 'function') { + cb = opts; + opts = {}; + } + opts.flag || (opts.flag = 'w'); + opts.advice || (opts.advice = 'NOREUSE'); + _fdOperation(path, opts, function (fd, cb) { + if (typeof data === 'string') data = _.bufferFrom(data, opts.encoding || 'utf8'); + fs.write(fd, data, 0, data.length, null, function (e) { cb(e); }, '_nested_'); + }, cb); + }; + + fs.appendFile = function (path, data, opts, cb) { + if (typeof opts === 'function') { + cb = opts; + opts = {}; + } + opts.flag || (opts.flag = 'a'); + fs.writeFile(path, data, opts, cb); + }; + + fs.truncate = function (path, len, cb) { + _fdOperation(path, {flag:'r+'}, function (fd, cb) { + fs.ftruncate(fd, len, cb, '_nested_'); + }, cb); + }; + + fs.readdir = function (path, cb) { + _fdOperation(path, {flag:'\\r'}, function (fd, cb) { + fs._readdir(fd, cb, '_nested_'); + }, cb); + }; + + fs.mkdir = function (path, mode, cb) { + if (typeof mode === 'function') { + cb = mode; + mode = 0777; + } + _fdOperation(path, {flag:'\\wx'}, function (fd, cb) { + fs._mkdir(fd, cb, '_nested_'); + }, cb); + }; + + fs.utimes = function (path, atime, mtime, cb) { + _fdOperation(path, {flag:'r+'}, function (fd, cb) { + fs.futimes(fd, atime, mtime, cb, '_nested_'); + }, cb); + }; + + fs.chmod = fs.lchmod = function (path, mode, cb) { + _fdOperation(path, {flag:'\\r+'}, function (fd, cb) { + fs.fchmod(fd, mode, cb, '_nested_'); + }, cb); + }; + + fs.chown = fs.lchown = function (path, uid, gid, cb) { + _fdOperation(path, {flag:'\\r+'}, function (fd, cb) { + fs.fchown(fd, uid, gid, cb, '_nested_'); + }, cb); + }; + + + /* STUBS */ + + fs.link = function (src, dst, cb) { + // NOTE: theoretically we _could_ do hard links [with untracked `stat.nlink` count…] + _.delayedCall(cb, S.err.NOSYS()); + }; + + fs.symlink = function (src, dst, type, cb) { + if (typeof type === 'function') { + cb = type; + type = null; + } + _.delayedCall(cb, S.err.NOSYS()); + }; + + fs.readlink = function (path, cb) { + _fdOperation(path, {flag:'\\r'}, function (fd, cb) { + // the named file is *never* a symbolic link… + // NOTE: we still use _fdOperation for catching e.g. NOENT/NOTDIR errors… + cb(S.err.INVAL()); + }, cb); + }; + + fs.realpath = function (path, cache, cb) { + if (typeof cache === 'function') { + cb = cache; + cache = null; + } + if (cache) _.delayedCall(cb, S.err.NOSYS()); // TODO: what would be involved here? + else _fdOperation(path, {flag:'\\r'}, function (fd, cb) { + cb(null, _.absolutePath(path)); + }, cb); + }; + + fs.fchown = function (fd, uid, gid, cb, _n_) { cb = GROUP(cb, function () { + var _fd = fileDescriptors[fd]; + if (!_fd || !_fd.flags.write) _.delayedCall(cb, S.err.BADF()); + else _.delayedCall(cb, S.err.NOSYS()); + }, (_n_ === '_nested_')); }; + + + return fs; +} + +}).call(this,require('_process')) +},{"./chains.js":2,"./dir.js":3,"./helpers.js":4,"./structs.js":38,"./vol.js":39,"_process":17,"events":10,"fifolock":11,"stream":33}],6:[function(require,module,exports){ +'use strict' + +exports.byteLength = byteLength +exports.toByteArray = toByteArray +exports.fromByteArray = fromByteArray + +var lookup = [] +var revLookup = [] +var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array + +var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' +for (var i = 0, len = code.length; i < len; ++i) { + lookup[i] = code[i] + revLookup[code.charCodeAt(i)] = i +} + +// Support decoding URL-safe base64 strings, as Node.js does. +// See: https://en.wikipedia.org/wiki/Base64#URL_applications +revLookup['-'.charCodeAt(0)] = 62 +revLookup['_'.charCodeAt(0)] = 63 + +function getLens (b64) { + var len = b64.length + + if (len % 4 > 0) { + throw new Error('Invalid string. Length must be a multiple of 4') + } + + // Trim off extra bytes after placeholder bytes are found + // See: https://github.com/beatgammit/base64-js/issues/42 + var validLen = b64.indexOf('=') + if (validLen === -1) validLen = len + + var placeHoldersLen = validLen === len + ? 0 + : 4 - (validLen % 4) + + return [validLen, placeHoldersLen] +} + +// base64 is 4/3 + up to two characters of the original data +function byteLength (b64) { + var lens = getLens(b64) + var validLen = lens[0] + var placeHoldersLen = lens[1] + return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen +} + +function _byteLength (b64, validLen, placeHoldersLen) { + return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen +} + +function toByteArray (b64) { + var tmp + var lens = getLens(b64) + var validLen = lens[0] + var placeHoldersLen = lens[1] + + var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen)) + + var curByte = 0 + + // if there are placeholders, only get up to the last complete 4 chars + var len = placeHoldersLen > 0 + ? validLen - 4 + : validLen + + var i + for (i = 0; i < len; i += 4) { + tmp = + (revLookup[b64.charCodeAt(i)] << 18) | + (revLookup[b64.charCodeAt(i + 1)] << 12) | + (revLookup[b64.charCodeAt(i + 2)] << 6) | + revLookup[b64.charCodeAt(i + 3)] + arr[curByte++] = (tmp >> 16) & 0xFF + arr[curByte++] = (tmp >> 8) & 0xFF + arr[curByte++] = tmp & 0xFF + } + + if (placeHoldersLen === 2) { + tmp = + (revLookup[b64.charCodeAt(i)] << 2) | + (revLookup[b64.charCodeAt(i + 1)] >> 4) + arr[curByte++] = tmp & 0xFF + } + + if (placeHoldersLen === 1) { + tmp = + (revLookup[b64.charCodeAt(i)] << 10) | + (revLookup[b64.charCodeAt(i + 1)] << 4) | + (revLookup[b64.charCodeAt(i + 2)] >> 2) + arr[curByte++] = (tmp >> 8) & 0xFF + arr[curByte++] = tmp & 0xFF + } + + return arr +} + +function tripletToBase64 (num) { + return lookup[num >> 18 & 0x3F] + + lookup[num >> 12 & 0x3F] + + lookup[num >> 6 & 0x3F] + + lookup[num & 0x3F] +} + +function encodeChunk (uint8, start, end) { + var tmp + var output = [] + for (var i = start; i < end; i += 3) { + tmp = + ((uint8[i] << 16) & 0xFF0000) + + ((uint8[i + 1] << 8) & 0xFF00) + + (uint8[i + 2] & 0xFF) + output.push(tripletToBase64(tmp)) + } + return output.join('') +} + +function fromByteArray (uint8) { + var tmp + var len = uint8.length + var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes + var parts = [] + var maxChunkLength = 16383 // must be multiple of 3 + + // go through the array every three bytes, we'll deal with trailing stuff later + for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { + parts.push(encodeChunk( + uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength) + )) + } + + // pad the end with zeros, but make sure to not forget the extra bytes + if (extraBytes === 1) { + tmp = uint8[len - 1] + parts.push( + lookup[tmp >> 2] + + lookup[(tmp << 4) & 0x3F] + + '==' + ) + } else if (extraBytes === 2) { + tmp = (uint8[len - 2] << 8) + uint8[len - 1] + parts.push( + lookup[tmp >> 10] + + lookup[(tmp >> 4) & 0x3F] + + lookup[(tmp << 2) & 0x3F] + + '=' + ) + } + + return parts.join('') +} + +},{}],7:[function(require,module,exports){ + +},{}],8:[function(require,module,exports){ +(function (Buffer){ +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ +/* eslint-disable no-proto */ + +'use strict' + +var base64 = require('base64-js') +var ieee754 = require('ieee754') + +exports.Buffer = Buffer +exports.SlowBuffer = SlowBuffer +exports.INSPECT_MAX_BYTES = 50 + +var K_MAX_LENGTH = 0x7fffffff +exports.kMaxLength = K_MAX_LENGTH + +/** + * If `Buffer.TYPED_ARRAY_SUPPORT`: + * === true Use Uint8Array implementation (fastest) + * === false Print warning and recommend using `buffer` v4.x which has an Object + * implementation (most compatible, even IE6) + * + * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, + * Opera 11.6+, iOS 4.2+. + * + * We report that the browser does not support typed arrays if the are not subclassable + * using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array` + * (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support + * for __proto__ and has a buggy typed array implementation. + */ +Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport() + +if (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' && + typeof console.error === 'function') { + console.error( + 'This browser lacks typed array (Uint8Array) support which is required by ' + + '`buffer` v5.x. Use `buffer` v4.x if you require old browser support.' + ) +} + +function typedArraySupport () { + // Can typed array instances can be augmented? + try { + var arr = new Uint8Array(1) + arr.__proto__ = { __proto__: Uint8Array.prototype, foo: function () { return 42 } } + return arr.foo() === 42 + } catch (e) { + return false + } +} + +Object.defineProperty(Buffer.prototype, 'parent', { + enumerable: true, + get: function () { + if (!Buffer.isBuffer(this)) return undefined + return this.buffer + } +}) + +Object.defineProperty(Buffer.prototype, 'offset', { + enumerable: true, + get: function () { + if (!Buffer.isBuffer(this)) return undefined + return this.byteOffset + } +}) + +function createBuffer (length) { + if (length > K_MAX_LENGTH) { + throw new RangeError('The value "' + length + '" is invalid for option "size"') + } + // Return an augmented `Uint8Array` instance + var buf = new Uint8Array(length) + buf.__proto__ = Buffer.prototype + return buf +} + +/** + * The Buffer constructor returns instances of `Uint8Array` that have their + * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of + * `Uint8Array`, so the returned instances will have all the node `Buffer` methods + * and the `Uint8Array` methods. Square bracket notation works as expected -- it + * returns a single octet. + * + * The `Uint8Array` prototype remains unmodified. + */ + +function Buffer (arg, encodingOrOffset, length) { + // Common case. + if (typeof arg === 'number') { + if (typeof encodingOrOffset === 'string') { + throw new TypeError( + 'The "string" argument must be of type string. Received type number' + ) + } + return allocUnsafe(arg) + } + return from(arg, encodingOrOffset, length) +} + +// Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97 +if (typeof Symbol !== 'undefined' && Symbol.species != null && + Buffer[Symbol.species] === Buffer) { + Object.defineProperty(Buffer, Symbol.species, { + value: null, + configurable: true, + enumerable: false, + writable: false + }) +} + +Buffer.poolSize = 8192 // not used by this implementation + +function from (value, encodingOrOffset, length) { + if (typeof value === 'string') { + return fromString(value, encodingOrOffset) + } + + if (ArrayBuffer.isView(value)) { + return fromArrayLike(value) + } + + if (value == null) { + throw TypeError( + 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + + 'or Array-like Object. Received type ' + (typeof value) + ) + } + + if (isInstance(value, ArrayBuffer) || + (value && isInstance(value.buffer, ArrayBuffer))) { + return fromArrayBuffer(value, encodingOrOffset, length) + } + + if (typeof value === 'number') { + throw new TypeError( + 'The "value" argument must not be of type number. Received type number' + ) + } + + var valueOf = value.valueOf && value.valueOf() + if (valueOf != null && valueOf !== value) { + return Buffer.from(valueOf, encodingOrOffset, length) + } + + var b = fromObject(value) + if (b) return b + + if (typeof Symbol !== 'undefined' && Symbol.toPrimitive != null && + typeof value[Symbol.toPrimitive] === 'function') { + return Buffer.from( + value[Symbol.toPrimitive]('string'), encodingOrOffset, length + ) + } + + throw new TypeError( + 'The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + + 'or Array-like Object. Received type ' + (typeof value) + ) +} + +/** + * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError + * if value is a number. + * Buffer.from(str[, encoding]) + * Buffer.from(array) + * Buffer.from(buffer) + * Buffer.from(arrayBuffer[, byteOffset[, length]]) + **/ +Buffer.from = function (value, encodingOrOffset, length) { + return from(value, encodingOrOffset, length) +} + +// Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug: +// https://github.com/feross/buffer/pull/148 +Buffer.prototype.__proto__ = Uint8Array.prototype +Buffer.__proto__ = Uint8Array + +function assertSize (size) { + if (typeof size !== 'number') { + throw new TypeError('"size" argument must be of type number') + } else if (size < 0) { + throw new RangeError('The value "' + size + '" is invalid for option "size"') + } +} + +function alloc (size, fill, encoding) { + assertSize(size) + if (size <= 0) { + return createBuffer(size) + } + if (fill !== undefined) { + // Only pay attention to encoding if it's a string. This + // prevents accidentally sending in a number that would + // be interpretted as a start offset. + return typeof encoding === 'string' + ? createBuffer(size).fill(fill, encoding) + : createBuffer(size).fill(fill) + } + return createBuffer(size) +} + +/** + * Creates a new filled Buffer instance. + * alloc(size[, fill[, encoding]]) + **/ +Buffer.alloc = function (size, fill, encoding) { + return alloc(size, fill, encoding) +} + +function allocUnsafe (size) { + assertSize(size) + return createBuffer(size < 0 ? 0 : checked(size) | 0) +} + +/** + * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. + * */ +Buffer.allocUnsafe = function (size) { + return allocUnsafe(size) +} +/** + * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. + */ +Buffer.allocUnsafeSlow = function (size) { + return allocUnsafe(size) +} + +function fromString (string, encoding) { + if (typeof encoding !== 'string' || encoding === '') { + encoding = 'utf8' + } + + if (!Buffer.isEncoding(encoding)) { + throw new TypeError('Unknown encoding: ' + encoding) + } + + var length = byteLength(string, encoding) | 0 + var buf = createBuffer(length) + + var actual = buf.write(string, encoding) + + if (actual !== length) { + // Writing a hex string, for example, that contains invalid characters will + // cause everything after the first invalid character to be ignored. (e.g. + // 'abxxcd' will be treated as 'ab') + buf = buf.slice(0, actual) + } + + return buf +} + +function fromArrayLike (array) { + var length = array.length < 0 ? 0 : checked(array.length) | 0 + var buf = createBuffer(length) + for (var i = 0; i < length; i += 1) { + buf[i] = array[i] & 255 + } + return buf +} + +function fromArrayBuffer (array, byteOffset, length) { + if (byteOffset < 0 || array.byteLength < byteOffset) { + throw new RangeError('"offset" is outside of buffer bounds') + } + + if (array.byteLength < byteOffset + (length || 0)) { + throw new RangeError('"length" is outside of buffer bounds') + } + + var buf + if (byteOffset === undefined && length === undefined) { + buf = new Uint8Array(array) + } else if (length === undefined) { + buf = new Uint8Array(array, byteOffset) + } else { + buf = new Uint8Array(array, byteOffset, length) + } + + // Return an augmented `Uint8Array` instance + buf.__proto__ = Buffer.prototype + return buf +} + +function fromObject (obj) { + if (Buffer.isBuffer(obj)) { + var len = checked(obj.length) | 0 + var buf = createBuffer(len) + + if (buf.length === 0) { + return buf + } + + obj.copy(buf, 0, 0, len) + return buf + } + + if (obj.length !== undefined) { + if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) { + return createBuffer(0) + } + return fromArrayLike(obj) + } + + if (obj.type === 'Buffer' && Array.isArray(obj.data)) { + return fromArrayLike(obj.data) + } +} + +function checked (length) { + // Note: cannot use `length < K_MAX_LENGTH` here because that fails when + // length is NaN (which is otherwise coerced to zero.) + if (length >= K_MAX_LENGTH) { + throw new RangeError('Attempt to allocate Buffer larger than maximum ' + + 'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes') + } + return length | 0 +} + +function SlowBuffer (length) { + if (+length != length) { // eslint-disable-line eqeqeq + length = 0 + } + return Buffer.alloc(+length) +} + +Buffer.isBuffer = function isBuffer (b) { + return b != null && b._isBuffer === true && + b !== Buffer.prototype // so Buffer.isBuffer(Buffer.prototype) will be false +} + +Buffer.compare = function compare (a, b) { + if (isInstance(a, Uint8Array)) a = Buffer.from(a, a.offset, a.byteLength) + if (isInstance(b, Uint8Array)) b = Buffer.from(b, b.offset, b.byteLength) + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { + throw new TypeError( + 'The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array' + ) + } + + if (a === b) return 0 + + var x = a.length + var y = b.length + + for (var i = 0, len = Math.min(x, y); i < len; ++i) { + if (a[i] !== b[i]) { + x = a[i] + y = b[i] + break + } + } + + if (x < y) return -1 + if (y < x) return 1 + return 0 +} + +Buffer.isEncoding = function isEncoding (encoding) { + switch (String(encoding).toLowerCase()) { + case 'hex': + case 'utf8': + case 'utf-8': + case 'ascii': + case 'latin1': + case 'binary': + case 'base64': + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return true + default: + return false + } +} + +Buffer.concat = function concat (list, length) { + if (!Array.isArray(list)) { + throw new TypeError('"list" argument must be an Array of Buffers') + } + + if (list.length === 0) { + return Buffer.alloc(0) + } + + var i + if (length === undefined) { + length = 0 + for (i = 0; i < list.length; ++i) { + length += list[i].length + } + } + + var buffer = Buffer.allocUnsafe(length) + var pos = 0 + for (i = 0; i < list.length; ++i) { + var buf = list[i] + if (isInstance(buf, Uint8Array)) { + buf = Buffer.from(buf) + } + if (!Buffer.isBuffer(buf)) { + throw new TypeError('"list" argument must be an Array of Buffers') + } + buf.copy(buffer, pos) + pos += buf.length + } + return buffer +} + +function byteLength (string, encoding) { + if (Buffer.isBuffer(string)) { + return string.length + } + if (ArrayBuffer.isView(string) || isInstance(string, ArrayBuffer)) { + return string.byteLength + } + if (typeof string !== 'string') { + throw new TypeError( + 'The "string" argument must be one of type string, Buffer, or ArrayBuffer. ' + + 'Received type ' + typeof string + ) + } + + var len = string.length + var mustMatch = (arguments.length > 2 && arguments[2] === true) + if (!mustMatch && len === 0) return 0 + + // Use a for loop to avoid recursion + var loweredCase = false + for (;;) { + switch (encoding) { + case 'ascii': + case 'latin1': + case 'binary': + return len + case 'utf8': + case 'utf-8': + return utf8ToBytes(string).length + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return len * 2 + case 'hex': + return len >>> 1 + case 'base64': + return base64ToBytes(string).length + default: + if (loweredCase) { + return mustMatch ? -1 : utf8ToBytes(string).length // assume utf8 + } + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } +} +Buffer.byteLength = byteLength + +function slowToString (encoding, start, end) { + var loweredCase = false + + // No need to verify that "this.length <= MAX_UINT32" since it's a read-only + // property of a typed array. + + // This behaves neither like String nor Uint8Array in that we set start/end + // to their upper/lower bounds if the value passed is out of range. + // undefined is handled specially as per ECMA-262 6th Edition, + // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization. + if (start === undefined || start < 0) { + start = 0 + } + // Return early if start > this.length. Done here to prevent potential uint32 + // coercion fail below. + if (start > this.length) { + return '' + } + + if (end === undefined || end > this.length) { + end = this.length + } + + if (end <= 0) { + return '' + } + + // Force coersion to uint32. This will also coerce falsey/NaN values to 0. + end >>>= 0 + start >>>= 0 + + if (end <= start) { + return '' + } + + if (!encoding) encoding = 'utf8' + + while (true) { + switch (encoding) { + case 'hex': + return hexSlice(this, start, end) + + case 'utf8': + case 'utf-8': + return utf8Slice(this, start, end) + + case 'ascii': + return asciiSlice(this, start, end) + + case 'latin1': + case 'binary': + return latin1Slice(this, start, end) + + case 'base64': + return base64Slice(this, start, end) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return utf16leSlice(this, start, end) + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = (encoding + '').toLowerCase() + loweredCase = true + } + } +} + +// This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package) +// to detect a Buffer instance. It's not possible to use `instanceof Buffer` +// reliably in a browserify context because there could be multiple different +// copies of the 'buffer' package in use. This method works even for Buffer +// instances that were created from another copy of the `buffer` package. +// See: https://github.com/feross/buffer/issues/154 +Buffer.prototype._isBuffer = true + +function swap (b, n, m) { + var i = b[n] + b[n] = b[m] + b[m] = i +} + +Buffer.prototype.swap16 = function swap16 () { + var len = this.length + if (len % 2 !== 0) { + throw new RangeError('Buffer size must be a multiple of 16-bits') + } + for (var i = 0; i < len; i += 2) { + swap(this, i, i + 1) + } + return this +} + +Buffer.prototype.swap32 = function swap32 () { + var len = this.length + if (len % 4 !== 0) { + throw new RangeError('Buffer size must be a multiple of 32-bits') + } + for (var i = 0; i < len; i += 4) { + swap(this, i, i + 3) + swap(this, i + 1, i + 2) + } + return this +} + +Buffer.prototype.swap64 = function swap64 () { + var len = this.length + if (len % 8 !== 0) { + throw new RangeError('Buffer size must be a multiple of 64-bits') + } + for (var i = 0; i < len; i += 8) { + swap(this, i, i + 7) + swap(this, i + 1, i + 6) + swap(this, i + 2, i + 5) + swap(this, i + 3, i + 4) + } + return this +} + +Buffer.prototype.toString = function toString () { + var length = this.length + if (length === 0) return '' + if (arguments.length === 0) return utf8Slice(this, 0, length) + return slowToString.apply(this, arguments) +} + +Buffer.prototype.toLocaleString = Buffer.prototype.toString + +Buffer.prototype.equals = function equals (b) { + if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + if (this === b) return true + return Buffer.compare(this, b) === 0 +} + +Buffer.prototype.inspect = function inspect () { + var str = '' + var max = exports.INSPECT_MAX_BYTES + str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim() + if (this.length > max) str += ' ... ' + return '' +} + +Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) { + if (isInstance(target, Uint8Array)) { + target = Buffer.from(target, target.offset, target.byteLength) + } + if (!Buffer.isBuffer(target)) { + throw new TypeError( + 'The "target" argument must be one of type Buffer or Uint8Array. ' + + 'Received type ' + (typeof target) + ) + } + + if (start === undefined) { + start = 0 + } + if (end === undefined) { + end = target ? target.length : 0 + } + if (thisStart === undefined) { + thisStart = 0 + } + if (thisEnd === undefined) { + thisEnd = this.length + } + + if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) { + throw new RangeError('out of range index') + } + + if (thisStart >= thisEnd && start >= end) { + return 0 + } + if (thisStart >= thisEnd) { + return -1 + } + if (start >= end) { + return 1 + } + + start >>>= 0 + end >>>= 0 + thisStart >>>= 0 + thisEnd >>>= 0 + + if (this === target) return 0 + + var x = thisEnd - thisStart + var y = end - start + var len = Math.min(x, y) + + var thisCopy = this.slice(thisStart, thisEnd) + var targetCopy = target.slice(start, end) + + for (var i = 0; i < len; ++i) { + if (thisCopy[i] !== targetCopy[i]) { + x = thisCopy[i] + y = targetCopy[i] + break + } + } + + if (x < y) return -1 + if (y < x) return 1 + return 0 +} + +// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, +// OR the last index of `val` in `buffer` at offset <= `byteOffset`. +// +// Arguments: +// - buffer - a Buffer to search +// - val - a string, Buffer, or number +// - byteOffset - an index into `buffer`; will be clamped to an int32 +// - encoding - an optional encoding, relevant is val is a string +// - dir - true for indexOf, false for lastIndexOf +function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { + // Empty buffer means no match + if (buffer.length === 0) return -1 + + // Normalize byteOffset + if (typeof byteOffset === 'string') { + encoding = byteOffset + byteOffset = 0 + } else if (byteOffset > 0x7fffffff) { + byteOffset = 0x7fffffff + } else if (byteOffset < -0x80000000) { + byteOffset = -0x80000000 + } + byteOffset = +byteOffset // Coerce to Number. + if (numberIsNaN(byteOffset)) { + // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer + byteOffset = dir ? 0 : (buffer.length - 1) + } + + // Normalize byteOffset: negative offsets start from the end of the buffer + if (byteOffset < 0) byteOffset = buffer.length + byteOffset + if (byteOffset >= buffer.length) { + if (dir) return -1 + else byteOffset = buffer.length - 1 + } else if (byteOffset < 0) { + if (dir) byteOffset = 0 + else return -1 + } + + // Normalize val + if (typeof val === 'string') { + val = Buffer.from(val, encoding) + } + + // Finally, search either indexOf (if dir is true) or lastIndexOf + if (Buffer.isBuffer(val)) { + // Special case: looking for empty string/buffer always fails + if (val.length === 0) { + return -1 + } + return arrayIndexOf(buffer, val, byteOffset, encoding, dir) + } else if (typeof val === 'number') { + val = val & 0xFF // Search for a byte value [0-255] + if (typeof Uint8Array.prototype.indexOf === 'function') { + if (dir) { + return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset) + } else { + return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset) + } + } + return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir) + } + + throw new TypeError('val must be string, number or Buffer') +} + +function arrayIndexOf (arr, val, byteOffset, encoding, dir) { + var indexSize = 1 + var arrLength = arr.length + var valLength = val.length + + if (encoding !== undefined) { + encoding = String(encoding).toLowerCase() + if (encoding === 'ucs2' || encoding === 'ucs-2' || + encoding === 'utf16le' || encoding === 'utf-16le') { + if (arr.length < 2 || val.length < 2) { + return -1 + } + indexSize = 2 + arrLength /= 2 + valLength /= 2 + byteOffset /= 2 + } + } + + function read (buf, i) { + if (indexSize === 1) { + return buf[i] + } else { + return buf.readUInt16BE(i * indexSize) + } + } + + var i + if (dir) { + var foundIndex = -1 + for (i = byteOffset; i < arrLength; i++) { + if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { + if (foundIndex === -1) foundIndex = i + if (i - foundIndex + 1 === valLength) return foundIndex * indexSize + } else { + if (foundIndex !== -1) i -= i - foundIndex + foundIndex = -1 + } + } + } else { + if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength + for (i = byteOffset; i >= 0; i--) { + var found = true + for (var j = 0; j < valLength; j++) { + if (read(arr, i + j) !== read(val, j)) { + found = false + break + } + } + if (found) return i + } + } + + return -1 +} + +Buffer.prototype.includes = function includes (val, byteOffset, encoding) { + return this.indexOf(val, byteOffset, encoding) !== -1 +} + +Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) { + return bidirectionalIndexOf(this, val, byteOffset, encoding, true) +} + +Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) { + return bidirectionalIndexOf(this, val, byteOffset, encoding, false) +} + +function hexWrite (buf, string, offset, length) { + offset = Number(offset) || 0 + var remaining = buf.length - offset + if (!length) { + length = remaining + } else { + length = Number(length) + if (length > remaining) { + length = remaining + } + } + + var strLen = string.length + + if (length > strLen / 2) { + length = strLen / 2 + } + for (var i = 0; i < length; ++i) { + var parsed = parseInt(string.substr(i * 2, 2), 16) + if (numberIsNaN(parsed)) return i + buf[offset + i] = parsed + } + return i +} + +function utf8Write (buf, string, offset, length) { + return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) +} + +function asciiWrite (buf, string, offset, length) { + return blitBuffer(asciiToBytes(string), buf, offset, length) +} + +function latin1Write (buf, string, offset, length) { + return asciiWrite(buf, string, offset, length) +} + +function base64Write (buf, string, offset, length) { + return blitBuffer(base64ToBytes(string), buf, offset, length) +} + +function ucs2Write (buf, string, offset, length) { + return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) +} + +Buffer.prototype.write = function write (string, offset, length, encoding) { + // Buffer#write(string) + if (offset === undefined) { + encoding = 'utf8' + length = this.length + offset = 0 + // Buffer#write(string, encoding) + } else if (length === undefined && typeof offset === 'string') { + encoding = offset + length = this.length + offset = 0 + // Buffer#write(string, offset[, length][, encoding]) + } else if (isFinite(offset)) { + offset = offset >>> 0 + if (isFinite(length)) { + length = length >>> 0 + if (encoding === undefined) encoding = 'utf8' + } else { + encoding = length + length = undefined + } + } else { + throw new Error( + 'Buffer.write(string, encoding, offset[, length]) is no longer supported' + ) + } + + var remaining = this.length - offset + if (length === undefined || length > remaining) length = remaining + + if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { + throw new RangeError('Attempt to write outside buffer bounds') + } + + if (!encoding) encoding = 'utf8' + + var loweredCase = false + for (;;) { + switch (encoding) { + case 'hex': + return hexWrite(this, string, offset, length) + + case 'utf8': + case 'utf-8': + return utf8Write(this, string, offset, length) + + case 'ascii': + return asciiWrite(this, string, offset, length) + + case 'latin1': + case 'binary': + return latin1Write(this, string, offset, length) + + case 'base64': + // Warning: maxLength not taken into account in base64Write + return base64Write(this, string, offset, length) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return ucs2Write(this, string, offset, length) + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } +} + +Buffer.prototype.toJSON = function toJSON () { + return { + type: 'Buffer', + data: Array.prototype.slice.call(this._arr || this, 0) + } +} + +function base64Slice (buf, start, end) { + if (start === 0 && end === buf.length) { + return base64.fromByteArray(buf) + } else { + return base64.fromByteArray(buf.slice(start, end)) + } +} + +function utf8Slice (buf, start, end) { + end = Math.min(buf.length, end) + var res = [] + + var i = start + while (i < end) { + var firstByte = buf[i] + var codePoint = null + var bytesPerSequence = (firstByte > 0xEF) ? 4 + : (firstByte > 0xDF) ? 3 + : (firstByte > 0xBF) ? 2 + : 1 + + if (i + bytesPerSequence <= end) { + var secondByte, thirdByte, fourthByte, tempCodePoint + + switch (bytesPerSequence) { + case 1: + if (firstByte < 0x80) { + codePoint = firstByte + } + break + case 2: + secondByte = buf[i + 1] + if ((secondByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F) + if (tempCodePoint > 0x7F) { + codePoint = tempCodePoint + } + } + break + case 3: + secondByte = buf[i + 1] + thirdByte = buf[i + 2] + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F) + if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { + codePoint = tempCodePoint + } + } + break + case 4: + secondByte = buf[i + 1] + thirdByte = buf[i + 2] + fourthByte = buf[i + 3] + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F) + if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { + codePoint = tempCodePoint + } + } + } + } + + if (codePoint === null) { + // we did not generate a valid codePoint so insert a + // replacement char (U+FFFD) and advance only 1 byte + codePoint = 0xFFFD + bytesPerSequence = 1 + } else if (codePoint > 0xFFFF) { + // encode to utf16 (surrogate pair dance) + codePoint -= 0x10000 + res.push(codePoint >>> 10 & 0x3FF | 0xD800) + codePoint = 0xDC00 | codePoint & 0x3FF + } + + res.push(codePoint) + i += bytesPerSequence + } + + return decodeCodePointsArray(res) +} + +// Based on http://stackoverflow.com/a/22747272/680742, the browser with +// the lowest limit is Chrome, with 0x10000 args. +// We go 1 magnitude less, for safety +var MAX_ARGUMENTS_LENGTH = 0x1000 + +function decodeCodePointsArray (codePoints) { + var len = codePoints.length + if (len <= MAX_ARGUMENTS_LENGTH) { + return String.fromCharCode.apply(String, codePoints) // avoid extra slice() + } + + // Decode in chunks to avoid "call stack size exceeded". + var res = '' + var i = 0 + while (i < len) { + res += String.fromCharCode.apply( + String, + codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) + ) + } + return res +} + +function asciiSlice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i] & 0x7F) + } + return ret +} + +function latin1Slice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i]) + } + return ret +} + +function hexSlice (buf, start, end) { + var len = buf.length + + if (!start || start < 0) start = 0 + if (!end || end < 0 || end > len) end = len + + var out = '' + for (var i = start; i < end; ++i) { + out += toHex(buf[i]) + } + return out +} + +function utf16leSlice (buf, start, end) { + var bytes = buf.slice(start, end) + var res = '' + for (var i = 0; i < bytes.length; i += 2) { + res += String.fromCharCode(bytes[i] + (bytes[i + 1] * 256)) + } + return res +} + +Buffer.prototype.slice = function slice (start, end) { + var len = this.length + start = ~~start + end = end === undefined ? len : ~~end + + if (start < 0) { + start += len + if (start < 0) start = 0 + } else if (start > len) { + start = len + } + + if (end < 0) { + end += len + if (end < 0) end = 0 + } else if (end > len) { + end = len + } + + if (end < start) end = start + + var newBuf = this.subarray(start, end) + // Return an augmented `Uint8Array` instance + newBuf.__proto__ = Buffer.prototype + return newBuf +} + +/* + * Need to make sure that buffer isn't trying to write out of bounds. + */ +function checkOffset (offset, ext, length) { + if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') + if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') +} + +Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + + return val +} + +Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + checkOffset(offset, byteLength, this.length) + } + + var val = this[offset + --byteLength] + var mul = 1 + while (byteLength > 0 && (mul *= 0x100)) { + val += this[offset + --byteLength] * mul + } + + return val +} + +Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 1, this.length) + return this[offset] +} + +Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + return this[offset] | (this[offset + 1] << 8) +} + +Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + return (this[offset] << 8) | this[offset + 1] +} + +Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + + return ((this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16)) + + (this[offset + 3] * 0x1000000) +} + +Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset] * 0x1000000) + + ((this[offset + 1] << 16) | + (this[offset + 2] << 8) | + this[offset + 3]) +} + +Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + mul *= 0x80 + + if (val >= mul) val -= Math.pow(2, 8 * byteLength) + + return val +} + +Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var i = byteLength + var mul = 1 + var val = this[offset + --i] + while (i > 0 && (mul *= 0x100)) { + val += this[offset + --i] * mul + } + mul *= 0x80 + + if (val >= mul) val -= Math.pow(2, 8 * byteLength) + + return val +} + +Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 1, this.length) + if (!(this[offset] & 0x80)) return (this[offset]) + return ((0xff - this[offset] + 1) * -1) +} + +Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + var val = this[offset] | (this[offset + 1] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 2, this.length) + var val = this[offset + 1] | (this[offset] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16) | + (this[offset + 3] << 24) +} + +Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset] << 24) | + (this[offset + 1] << 16) | + (this[offset + 2] << 8) | + (this[offset + 3]) +} + +Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, true, 23, 4) +} + +Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, false, 23, 4) +} + +Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, true, 52, 8) +} + +Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { + offset = offset >>> 0 + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, false, 52, 8) +} + +function checkInt (buf, value, offset, ext, max, min) { + if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance') + if (value > max || value < min) throw new RangeError('"value" argument is out of bounds') + if (offset + ext > buf.length) throw new RangeError('Index out of range') +} + +Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + var maxBytes = Math.pow(2, 8 * byteLength) - 1 + checkInt(this, value, offset, byteLength, maxBytes, 0) + } + + var mul = 1 + var i = 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + byteLength = byteLength >>> 0 + if (!noAssert) { + var maxBytes = Math.pow(2, 8 * byteLength) - 1 + checkInt(this, value, offset, byteLength, maxBytes, 0) + } + + var i = byteLength - 1 + var mul = 1 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) + this[offset] = (value & 0xff) + return offset + 1 +} + +Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + return offset + 2 +} + +Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + this[offset] = (value >>> 8) + this[offset + 1] = (value & 0xff) + return offset + 2 +} + +Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + this[offset + 3] = (value >>> 24) + this[offset + 2] = (value >>> 16) + this[offset + 1] = (value >>> 8) + this[offset] = (value & 0xff) + return offset + 4 +} + +Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = (value & 0xff) + return offset + 4 +} + +Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + var limit = Math.pow(2, (8 * byteLength) - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + var i = 0 + var mul = 1 + var sub = 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) { + sub = 1 + } + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + var limit = Math.pow(2, (8 * byteLength) - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + var i = byteLength - 1 + var mul = 1 + var sub = 0 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) { + sub = 1 + } + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) + if (value < 0) value = 0xff + value + 1 + this[offset] = (value & 0xff) + return offset + 1 +} + +Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + return offset + 2 +} + +Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + this[offset] = (value >>> 8) + this[offset + 1] = (value & 0xff) + return offset + 2 +} + +Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + this[offset + 2] = (value >>> 16) + this[offset + 3] = (value >>> 24) + return offset + 4 +} + +Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (value < 0) value = 0xffffffff + value + 1 + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = (value & 0xff) + return offset + 4 +} + +function checkIEEE754 (buf, value, offset, ext, max, min) { + if (offset + ext > buf.length) throw new RangeError('Index out of range') + if (offset < 0) throw new RangeError('Index out of range') +} + +function writeFloat (buf, value, offset, littleEndian, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) + } + ieee754.write(buf, value, offset, littleEndian, 23, 4) + return offset + 4 +} + +Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { + return writeFloat(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { + return writeFloat(this, value, offset, false, noAssert) +} + +function writeDouble (buf, value, offset, littleEndian, noAssert) { + value = +value + offset = offset >>> 0 + if (!noAssert) { + checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) + } + ieee754.write(buf, value, offset, littleEndian, 52, 8) + return offset + 8 +} + +Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { + return writeDouble(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { + return writeDouble(this, value, offset, false, noAssert) +} + +// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) +Buffer.prototype.copy = function copy (target, targetStart, start, end) { + if (!Buffer.isBuffer(target)) throw new TypeError('argument should be a Buffer') + if (!start) start = 0 + if (!end && end !== 0) end = this.length + if (targetStart >= target.length) targetStart = target.length + if (!targetStart) targetStart = 0 + if (end > 0 && end < start) end = start + + // Copy 0 bytes; we're done + if (end === start) return 0 + if (target.length === 0 || this.length === 0) return 0 + + // Fatal error conditions + if (targetStart < 0) { + throw new RangeError('targetStart out of bounds') + } + if (start < 0 || start >= this.length) throw new RangeError('Index out of range') + if (end < 0) throw new RangeError('sourceEnd out of bounds') + + // Are we oob? + if (end > this.length) end = this.length + if (target.length - targetStart < end - start) { + end = target.length - targetStart + start + } + + var len = end - start + + if (this === target && typeof Uint8Array.prototype.copyWithin === 'function') { + // Use built-in when available, missing from IE11 + this.copyWithin(targetStart, start, end) + } else if (this === target && start < targetStart && targetStart < end) { + // descending copy from end + for (var i = len - 1; i >= 0; --i) { + target[i + targetStart] = this[i + start] + } + } else { + Uint8Array.prototype.set.call( + target, + this.subarray(start, end), + targetStart + ) + } + + return len +} + +// Usage: +// buffer.fill(number[, offset[, end]]) +// buffer.fill(buffer[, offset[, end]]) +// buffer.fill(string[, offset[, end]][, encoding]) +Buffer.prototype.fill = function fill (val, start, end, encoding) { + // Handle string cases: + if (typeof val === 'string') { + if (typeof start === 'string') { + encoding = start + start = 0 + end = this.length + } else if (typeof end === 'string') { + encoding = end + end = this.length + } + if (encoding !== undefined && typeof encoding !== 'string') { + throw new TypeError('encoding must be a string') + } + if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) { + throw new TypeError('Unknown encoding: ' + encoding) + } + if (val.length === 1) { + var code = val.charCodeAt(0) + if ((encoding === 'utf8' && code < 128) || + encoding === 'latin1') { + // Fast path: If `val` fits into a single byte, use that numeric value. + val = code + } + } + } else if (typeof val === 'number') { + val = val & 255 + } + + // Invalid ranges are not set to a default, so can range check early. + if (start < 0 || this.length < start || this.length < end) { + throw new RangeError('Out of range index') + } + + if (end <= start) { + return this + } + + start = start >>> 0 + end = end === undefined ? this.length : end >>> 0 + + if (!val) val = 0 + + var i + if (typeof val === 'number') { + for (i = start; i < end; ++i) { + this[i] = val + } + } else { + var bytes = Buffer.isBuffer(val) + ? val + : Buffer.from(val, encoding) + var len = bytes.length + if (len === 0) { + throw new TypeError('The value "' + val + + '" is invalid for argument "value"') + } + for (i = 0; i < end - start; ++i) { + this[i + start] = bytes[i % len] + } + } + + return this +} + +// HELPER FUNCTIONS +// ================ + +var INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g + +function base64clean (str) { + // Node takes equal signs as end of the Base64 encoding + str = str.split('=')[0] + // Node strips out invalid characters like \n and \t from the string, base64-js does not + str = str.trim().replace(INVALID_BASE64_RE, '') + // Node converts strings with length < 2 to '' + if (str.length < 2) return '' + // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not + while (str.length % 4 !== 0) { + str = str + '=' + } + return str +} + +function toHex (n) { + if (n < 16) return '0' + n.toString(16) + return n.toString(16) +} + +function utf8ToBytes (string, units) { + units = units || Infinity + var codePoint + var length = string.length + var leadSurrogate = null + var bytes = [] + + for (var i = 0; i < length; ++i) { + codePoint = string.charCodeAt(i) + + // is surrogate component + if (codePoint > 0xD7FF && codePoint < 0xE000) { + // last char was a lead + if (!leadSurrogate) { + // no lead yet + if (codePoint > 0xDBFF) { + // unexpected trail + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } else if (i + 1 === length) { + // unpaired lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } + + // valid lead + leadSurrogate = codePoint + + continue + } + + // 2 leads in a row + if (codePoint < 0xDC00) { + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + leadSurrogate = codePoint + continue + } + + // valid surrogate pair + codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000 + } else if (leadSurrogate) { + // valid bmp char, but last char was a lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + } + + leadSurrogate = null + + // encode utf8 + if (codePoint < 0x80) { + if ((units -= 1) < 0) break + bytes.push(codePoint) + } else if (codePoint < 0x800) { + if ((units -= 2) < 0) break + bytes.push( + codePoint >> 0x6 | 0xC0, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x10000) { + if ((units -= 3) < 0) break + bytes.push( + codePoint >> 0xC | 0xE0, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x110000) { + if ((units -= 4) < 0) break + bytes.push( + codePoint >> 0x12 | 0xF0, + codePoint >> 0xC & 0x3F | 0x80, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else { + throw new Error('Invalid code point') + } + } + + return bytes +} + +function asciiToBytes (str) { + var byteArray = [] + for (var i = 0; i < str.length; ++i) { + // Node's code seems to be doing this and not & 0x7F.. + byteArray.push(str.charCodeAt(i) & 0xFF) + } + return byteArray +} + +function utf16leToBytes (str, units) { + var c, hi, lo + var byteArray = [] + for (var i = 0; i < str.length; ++i) { + if ((units -= 2) < 0) break + + c = str.charCodeAt(i) + hi = c >> 8 + lo = c % 256 + byteArray.push(lo) + byteArray.push(hi) + } + + return byteArray +} + +function base64ToBytes (str) { + return base64.toByteArray(base64clean(str)) +} + +function blitBuffer (src, dst, offset, length) { + for (var i = 0; i < length; ++i) { + if ((i + offset >= dst.length) || (i >= src.length)) break + dst[i + offset] = src[i] + } + return i +} + +// ArrayBuffer or Uint8Array objects from other contexts (i.e. iframes) do not pass +// the `instanceof` check but they should be treated as of that type. +// See: https://github.com/feross/buffer/issues/166 +function isInstance (obj, type) { + return obj instanceof type || + (obj != null && obj.constructor != null && obj.constructor.name != null && + obj.constructor.name === type.name) +} +function numberIsNaN (obj) { + // For IE11 support + return obj !== obj // eslint-disable-line no-self-compare +} + +}).call(this,require("buffer").Buffer) +},{"base64-js":6,"buffer":8,"ieee754":12}],9:[function(require,module,exports){ +(function (Buffer){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. + +function isArray(arg) { + if (Array.isArray) { + return Array.isArray(arg); + } + return objectToString(arg) === '[object Array]'; +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; + +function isDate(d) { + return objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +exports.isBuffer = Buffer.isBuffer; + +function objectToString(o) { + return Object.prototype.toString.call(o); +} + +}).call(this,{"isBuffer":require("../../is-buffer/index.js")}) +},{"../../is-buffer/index.js":14}],10:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var objectCreate = Object.create || objectCreatePolyfill +var objectKeys = Object.keys || objectKeysPolyfill +var bind = Function.prototype.bind || functionBindPolyfill + +function EventEmitter() { + if (!this._events || !Object.prototype.hasOwnProperty.call(this, '_events')) { + this._events = objectCreate(null); + this._eventsCount = 0; + } + + this._maxListeners = this._maxListeners || undefined; +} +module.exports = EventEmitter; + +// Backwards-compat with node 0.10.x +EventEmitter.EventEmitter = EventEmitter; + +EventEmitter.prototype._events = undefined; +EventEmitter.prototype._maxListeners = undefined; + +// By default EventEmitters will print a warning if more than 10 listeners are +// added to it. This is a useful default which helps finding memory leaks. +var defaultMaxListeners = 10; + +var hasDefineProperty; +try { + var o = {}; + if (Object.defineProperty) Object.defineProperty(o, 'x', { value: 0 }); + hasDefineProperty = o.x === 0; +} catch (err) { hasDefineProperty = false } +if (hasDefineProperty) { + Object.defineProperty(EventEmitter, 'defaultMaxListeners', { + enumerable: true, + get: function() { + return defaultMaxListeners; + }, + set: function(arg) { + // check whether the input is a positive number (whose value is zero or + // greater and not a NaN). + if (typeof arg !== 'number' || arg < 0 || arg !== arg) + throw new TypeError('"defaultMaxListeners" must be a positive number'); + defaultMaxListeners = arg; + } + }); +} else { + EventEmitter.defaultMaxListeners = defaultMaxListeners; +} + +// Obviously not all Emitters should be limited to 10. This function allows +// that to be increased. Set to zero for unlimited. +EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) { + if (typeof n !== 'number' || n < 0 || isNaN(n)) + throw new TypeError('"n" argument must be a positive number'); + this._maxListeners = n; + return this; +}; + +function $getMaxListeners(that) { + if (that._maxListeners === undefined) + return EventEmitter.defaultMaxListeners; + return that._maxListeners; +} + +EventEmitter.prototype.getMaxListeners = function getMaxListeners() { + return $getMaxListeners(this); +}; + +// These standalone emit* functions are used to optimize calling of event +// handlers for fast cases because emit() itself often has a variable number of +// arguments and can be deoptimized because of that. These functions always have +// the same number of arguments and thus do not get deoptimized, so the code +// inside them can execute faster. +function emitNone(handler, isFn, self) { + if (isFn) + handler.call(self); + else { + var len = handler.length; + var listeners = arrayClone(handler, len); + for (var i = 0; i < len; ++i) + listeners[i].call(self); + } +} +function emitOne(handler, isFn, self, arg1) { + if (isFn) + handler.call(self, arg1); + else { + var len = handler.length; + var listeners = arrayClone(handler, len); + for (var i = 0; i < len; ++i) + listeners[i].call(self, arg1); + } +} +function emitTwo(handler, isFn, self, arg1, arg2) { + if (isFn) + handler.call(self, arg1, arg2); + else { + var len = handler.length; + var listeners = arrayClone(handler, len); + for (var i = 0; i < len; ++i) + listeners[i].call(self, arg1, arg2); + } +} +function emitThree(handler, isFn, self, arg1, arg2, arg3) { + if (isFn) + handler.call(self, arg1, arg2, arg3); + else { + var len = handler.length; + var listeners = arrayClone(handler, len); + for (var i = 0; i < len; ++i) + listeners[i].call(self, arg1, arg2, arg3); + } +} + +function emitMany(handler, isFn, self, args) { + if (isFn) + handler.apply(self, args); + else { + var len = handler.length; + var listeners = arrayClone(handler, len); + for (var i = 0; i < len; ++i) + listeners[i].apply(self, args); + } +} + +EventEmitter.prototype.emit = function emit(type) { + var er, handler, len, args, i, events; + var doError = (type === 'error'); + + events = this._events; + if (events) + doError = (doError && events.error == null); + else if (!doError) + return false; + + // If there is no 'error' event listener then throw. + if (doError) { + if (arguments.length > 1) + er = arguments[1]; + if (er instanceof Error) { + throw er; // Unhandled 'error' event + } else { + // At least give some kind of context to the user + var err = new Error('Unhandled "error" event. (' + er + ')'); + err.context = er; + throw err; + } + return false; + } + + handler = events[type]; + + if (!handler) + return false; + + var isFn = typeof handler === 'function'; + len = arguments.length; + switch (len) { + // fast cases + case 1: + emitNone(handler, isFn, this); + break; + case 2: + emitOne(handler, isFn, this, arguments[1]); + break; + case 3: + emitTwo(handler, isFn, this, arguments[1], arguments[2]); + break; + case 4: + emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]); + break; + // slower + default: + args = new Array(len - 1); + for (i = 1; i < len; i++) + args[i - 1] = arguments[i]; + emitMany(handler, isFn, this, args); + } + + return true; +}; + +function _addListener(target, type, listener, prepend) { + var m; + var events; + var existing; + + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + + events = target._events; + if (!events) { + events = target._events = objectCreate(null); + target._eventsCount = 0; + } else { + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (events.newListener) { + target.emit('newListener', type, + listener.listener ? listener.listener : listener); + + // Re-assign `events` because a newListener handler could have caused the + // this._events to be assigned to a new object + events = target._events; + } + existing = events[type]; + } + + if (!existing) { + // Optimize the case of one listener. Don't need the extra array object. + existing = events[type] = listener; + ++target._eventsCount; + } else { + if (typeof existing === 'function') { + // Adding the second element, need to change to array. + existing = events[type] = + prepend ? [listener, existing] : [existing, listener]; + } else { + // If we've already got an array, just append. + if (prepend) { + existing.unshift(listener); + } else { + existing.push(listener); + } + } + + // Check for listener leak + if (!existing.warned) { + m = $getMaxListeners(target); + if (m && m > 0 && existing.length > m) { + existing.warned = true; + var w = new Error('Possible EventEmitter memory leak detected. ' + + existing.length + ' "' + String(type) + '" listeners ' + + 'added. Use emitter.setMaxListeners() to ' + + 'increase limit.'); + w.name = 'MaxListenersExceededWarning'; + w.emitter = target; + w.type = type; + w.count = existing.length; + if (typeof console === 'object' && console.warn) { + console.warn('%s: %s', w.name, w.message); + } + } + } + } + + return target; +} + +EventEmitter.prototype.addListener = function addListener(type, listener) { + return _addListener(this, type, listener, false); +}; + +EventEmitter.prototype.on = EventEmitter.prototype.addListener; + +EventEmitter.prototype.prependListener = + function prependListener(type, listener) { + return _addListener(this, type, listener, true); + }; + +function onceWrapper() { + if (!this.fired) { + this.target.removeListener(this.type, this.wrapFn); + this.fired = true; + switch (arguments.length) { + case 0: + return this.listener.call(this.target); + case 1: + return this.listener.call(this.target, arguments[0]); + case 2: + return this.listener.call(this.target, arguments[0], arguments[1]); + case 3: + return this.listener.call(this.target, arguments[0], arguments[1], + arguments[2]); + default: + var args = new Array(arguments.length); + for (var i = 0; i < args.length; ++i) + args[i] = arguments[i]; + this.listener.apply(this.target, args); + } + } +} + +function _onceWrap(target, type, listener) { + var state = { fired: false, wrapFn: undefined, target: target, type: type, listener: listener }; + var wrapped = bind.call(onceWrapper, state); + wrapped.listener = listener; + state.wrapFn = wrapped; + return wrapped; +} + +EventEmitter.prototype.once = function once(type, listener) { + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + this.on(type, _onceWrap(this, type, listener)); + return this; +}; + +EventEmitter.prototype.prependOnceListener = + function prependOnceListener(type, listener) { + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + this.prependListener(type, _onceWrap(this, type, listener)); + return this; + }; + +// Emits a 'removeListener' event if and only if the listener was removed. +EventEmitter.prototype.removeListener = + function removeListener(type, listener) { + var list, events, position, i, originalListener; + + if (typeof listener !== 'function') + throw new TypeError('"listener" argument must be a function'); + + events = this._events; + if (!events) + return this; + + list = events[type]; + if (!list) + return this; + + if (list === listener || list.listener === listener) { + if (--this._eventsCount === 0) + this._events = objectCreate(null); + else { + delete events[type]; + if (events.removeListener) + this.emit('removeListener', type, list.listener || listener); + } + } else if (typeof list !== 'function') { + position = -1; + + for (i = list.length - 1; i >= 0; i--) { + if (list[i] === listener || list[i].listener === listener) { + originalListener = list[i].listener; + position = i; + break; + } + } + + if (position < 0) + return this; + + if (position === 0) + list.shift(); + else + spliceOne(list, position); + + if (list.length === 1) + events[type] = list[0]; + + if (events.removeListener) + this.emit('removeListener', type, originalListener || listener); + } + + return this; + }; + +EventEmitter.prototype.removeAllListeners = + function removeAllListeners(type) { + var listeners, events, i; + + events = this._events; + if (!events) + return this; + + // not listening for removeListener, no need to emit + if (!events.removeListener) { + if (arguments.length === 0) { + this._events = objectCreate(null); + this._eventsCount = 0; + } else if (events[type]) { + if (--this._eventsCount === 0) + this._events = objectCreate(null); + else + delete events[type]; + } + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + var keys = objectKeys(events); + var key; + for (i = 0; i < keys.length; ++i) { + key = keys[i]; + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = objectCreate(null); + this._eventsCount = 0; + return this; + } + + listeners = events[type]; + + if (typeof listeners === 'function') { + this.removeListener(type, listeners); + } else if (listeners) { + // LIFO order + for (i = listeners.length - 1; i >= 0; i--) { + this.removeListener(type, listeners[i]); + } + } + + return this; + }; + +function _listeners(target, type, unwrap) { + var events = target._events; + + if (!events) + return []; + + var evlistener = events[type]; + if (!evlistener) + return []; + + if (typeof evlistener === 'function') + return unwrap ? [evlistener.listener || evlistener] : [evlistener]; + + return unwrap ? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length); +} + +EventEmitter.prototype.listeners = function listeners(type) { + return _listeners(this, type, true); +}; + +EventEmitter.prototype.rawListeners = function rawListeners(type) { + return _listeners(this, type, false); +}; + +EventEmitter.listenerCount = function(emitter, type) { + if (typeof emitter.listenerCount === 'function') { + return emitter.listenerCount(type); + } else { + return listenerCount.call(emitter, type); + } +}; + +EventEmitter.prototype.listenerCount = listenerCount; +function listenerCount(type) { + var events = this._events; + + if (events) { + var evlistener = events[type]; + + if (typeof evlistener === 'function') { + return 1; + } else if (evlistener) { + return evlistener.length; + } + } + + return 0; +} + +EventEmitter.prototype.eventNames = function eventNames() { + return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : []; +}; + +// About 1.5x faster than the two-arg version of Array#splice(). +function spliceOne(list, index) { + for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1) + list[i] = list[k]; + list.pop(); +} + +function arrayClone(arr, n) { + var copy = new Array(n); + for (var i = 0; i < n; ++i) + copy[i] = arr[i]; + return copy; +} + +function unwrapListeners(arr) { + var ret = new Array(arr.length); + for (var i = 0; i < ret.length; ++i) { + ret[i] = arr[i].listener || arr[i]; + } + return ret; +} + +function objectCreatePolyfill(proto) { + var F = function() {}; + F.prototype = proto; + return new F; +} +function objectKeysPolyfill(obj) { + var keys = []; + for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k)) { + keys.push(k); + } + return k; +} +function functionBindPolyfill(context) { + var fn = this; + return function () { + return fn.apply(context, arguments); + }; +} + +},{}],11:[function(require,module,exports){ +(function (process){ +// very simple FIFO serial queue (plus callback wrapper), helps you call `fn`s in order + +module.exports = function SerialQueue() { + var q = {}, + tasks = []; + function runNext() { + tasks[0](function () { + tasks.shift(); // TODO: avoid? + if (tasks.length) runNext(); + }); + } + + // usage: `q.aquire(function (release) { … release(); });` + q.acquire = function (fn) { + var len = tasks.push(fn); + if (len === 1) process.nextTick(runNext); + }; + + // usage: `cb = q.TRANSACTION_WRAPPER(cb, function () { … cb(); });` + // (pass `true` for `nested` if your own caller already holds lock) + q.TRANSACTION_WRAPPER = function (cb, proceed, nested) { + if (nested) return process.nextTick(proceed), cb; + var _releaseQueue; + if ('postAcquire' in this) proceed = this.postAcquire.bind(q, proceed); + q.acquire(function (releaseQueue) { + _releaseQueue = releaseQueue; + proceed(); + }); + var capturedCB, finish = ('preRelease' in this) ? this.preRelease.bind(q, _finish) : _finish; + function _finish() { + capturedCB(); + _releaseQueue(); + } + return function () { + capturedCB = Function.prototype.apply.bind(cb, this, arguments); + finish.call(null, Array.prototype.slice.call(arguments, 0), this); + }; + }; + + return q; +}; + +}).call(this,require('_process')) +},{"_process":17}],12:[function(require,module,exports){ +exports.read = function (buffer, offset, isLE, mLen, nBytes) { + var e, m + var eLen = (nBytes * 8) - mLen - 1 + var eMax = (1 << eLen) - 1 + var eBias = eMax >> 1 + var nBits = -7 + var i = isLE ? (nBytes - 1) : 0 + var d = isLE ? -1 : 1 + var s = buffer[offset + i] + + i += d + + e = s & ((1 << (-nBits)) - 1) + s >>= (-nBits) + nBits += eLen + for (; nBits > 0; e = (e * 256) + buffer[offset + i], i += d, nBits -= 8) {} + + m = e & ((1 << (-nBits)) - 1) + e >>= (-nBits) + nBits += mLen + for (; nBits > 0; m = (m * 256) + buffer[offset + i], i += d, nBits -= 8) {} + + if (e === 0) { + e = 1 - eBias + } else if (e === eMax) { + return m ? NaN : ((s ? -1 : 1) * Infinity) + } else { + m = m + Math.pow(2, mLen) + e = e - eBias + } + return (s ? -1 : 1) * m * Math.pow(2, e - mLen) +} + +exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { + var e, m, c + var eLen = (nBytes * 8) - mLen - 1 + var eMax = (1 << eLen) - 1 + var eBias = eMax >> 1 + var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0) + var i = isLE ? 0 : (nBytes - 1) + var d = isLE ? 1 : -1 + var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0 + + value = Math.abs(value) + + if (isNaN(value) || value === Infinity) { + m = isNaN(value) ? 1 : 0 + e = eMax + } else { + e = Math.floor(Math.log(value) / Math.LN2) + if (value * (c = Math.pow(2, -e)) < 1) { + e-- + c *= 2 + } + if (e + eBias >= 1) { + value += rt / c + } else { + value += rt * Math.pow(2, 1 - eBias) + } + if (value * c >= 2) { + e++ + c /= 2 + } + + if (e + eBias >= eMax) { + m = 0 + e = eMax + } else if (e + eBias >= 1) { + m = ((value * c) - 1) * Math.pow(2, mLen) + e = e + eBias + } else { + m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen) + e = 0 + } + } + + for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} + + e = (e << mLen) | m + eLen += mLen + for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} + + buffer[offset + i - d] |= s * 128 +} + +},{}],13:[function(require,module,exports){ +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + if (superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }) + } + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + if (superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } + } +} + +},{}],14:[function(require,module,exports){ +/*! + * Determine if an object is a Buffer + * + * @author Feross Aboukhadijeh + * @license MIT + */ + +// The _isBuffer check is for Safari 5-7 support, because it's missing +// Object.prototype.constructor. Remove this eventually +module.exports = function (obj) { + return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer) +} + +function isBuffer (obj) { + return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj) +} + +// For Node v0.10 support. Remove this eventually. +function isSlowBuffer (obj) { + return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0)) +} + +},{}],15:[function(require,module,exports){ +var toString = {}.toString; + +module.exports = Array.isArray || function (arr) { + return toString.call(arr) == '[object Array]'; +}; + +},{}],16:[function(require,module,exports){ +(function (process){ +'use strict'; + +if (typeof process === 'undefined' || + !process.version || + process.version.indexOf('v0.') === 0 || + process.version.indexOf('v1.') === 0 && process.version.indexOf('v1.8.') !== 0) { + module.exports = { nextTick: nextTick }; +} else { + module.exports = process +} + +function nextTick(fn, arg1, arg2, arg3) { + if (typeof fn !== 'function') { + throw new TypeError('"callback" argument must be a function'); + } + var len = arguments.length; + var args, i; + switch (len) { + case 0: + case 1: + return process.nextTick(fn); + case 2: + return process.nextTick(function afterTickOne() { + fn.call(null, arg1); + }); + case 3: + return process.nextTick(function afterTickTwo() { + fn.call(null, arg1, arg2); + }); + case 4: + return process.nextTick(function afterTickThree() { + fn.call(null, arg1, arg2, arg3); + }); + default: + args = new Array(len - 1); + i = 0; + while (i < args.length) { + args[i++] = arguments[i]; + } + return process.nextTick(function afterTick() { + fn.apply(null, args); + }); + } +} + + +}).call(this,require('_process')) +},{"_process":17}],17:[function(require,module,exports){ +// shim for using process in browser +var process = module.exports = {}; + +// cached from whatever global is present so that test runners that stub it +// don't break things. But we need to wrap it in a try catch in case it is +// wrapped in strict mode code which doesn't define any globals. It's inside a +// function because try/catches deoptimize in certain engines. + +var cachedSetTimeout; +var cachedClearTimeout; + +function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); +} +function defaultClearTimeout () { + throw new Error('clearTimeout has not been defined'); +} +(function () { + try { + if (typeof setTimeout === 'function') { + cachedSetTimeout = setTimeout; + } else { + cachedSetTimeout = defaultSetTimout; + } + } catch (e) { + cachedSetTimeout = defaultSetTimout; + } + try { + if (typeof clearTimeout === 'function') { + cachedClearTimeout = clearTimeout; + } else { + cachedClearTimeout = defaultClearTimeout; + } + } catch (e) { + cachedClearTimeout = defaultClearTimeout; + } +} ()) +function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + //normal enviroments in sane situations + return setTimeout(fun, 0); + } + // if setTimeout wasn't available but was latter defined + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { + cachedSetTimeout = setTimeout; + return setTimeout(fun, 0); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedSetTimeout(fun, 0); + } catch(e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedSetTimeout.call(null, fun, 0); + } catch(e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error + return cachedSetTimeout.call(this, fun, 0); + } + } + + +} +function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + //normal enviroments in sane situations + return clearTimeout(marker); + } + // if clearTimeout wasn't available but was latter defined + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { + cachedClearTimeout = clearTimeout; + return clearTimeout(marker); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedClearTimeout(marker); + } catch (e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedClearTimeout.call(null, marker); + } catch (e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. + // Some versions of I.E. have different rules for clearTimeout vs setTimeout + return cachedClearTimeout.call(this, marker); + } + } + + + +} +var queue = []; +var draining = false; +var currentQueue; +var queueIndex = -1; + +function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } +} + +function drainQueue() { + if (draining) { + return; + } + var timeout = runTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + runClearTimeout(timeout); +} + +process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } +}; + +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; +process.prependListener = noop; +process.prependOnceListener = noop; + +process.listeners = function (name) { return [] } + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function() { return 0; }; + +},{}],18:[function(require,module,exports){ +module.exports = require('./lib/_stream_duplex.js'); + +},{"./lib/_stream_duplex.js":19}],19:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a duplex stream is just a stream that is both readable and writable. +// Since JS doesn't have multiple prototypal inheritance, this class +// prototypally inherits from Readable, and then parasitically from +// Writable. + +'use strict'; + +/**/ + +var pna = require('process-nextick-args'); +/**/ + +/**/ +var objectKeys = Object.keys || function (obj) { + var keys = []; + for (var key in obj) { + keys.push(key); + }return keys; +}; +/**/ + +module.exports = Duplex; + +/**/ +var util = Object.create(require('core-util-is')); +util.inherits = require('inherits'); +/**/ + +var Readable = require('./_stream_readable'); +var Writable = require('./_stream_writable'); + +util.inherits(Duplex, Readable); + +{ + // avoid scope creep, the keys array can then be collected + var keys = objectKeys(Writable.prototype); + for (var v = 0; v < keys.length; v++) { + var method = keys[v]; + if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method]; + } +} + +function Duplex(options) { + if (!(this instanceof Duplex)) return new Duplex(options); + + Readable.call(this, options); + Writable.call(this, options); + + if (options && options.readable === false) this.readable = false; + + if (options && options.writable === false) this.writable = false; + + this.allowHalfOpen = true; + if (options && options.allowHalfOpen === false) this.allowHalfOpen = false; + + this.once('end', onend); +} + +Object.defineProperty(Duplex.prototype, 'writableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function () { + return this._writableState.highWaterMark; + } +}); + +// the no-half-open enforcer +function onend() { + // if we allow half-open state, or if the writable side ended, + // then we're ok. + if (this.allowHalfOpen || this._writableState.ended) return; + + // no more data can be written. + // But allow more writes to happen in this tick. + pna.nextTick(onEndNT, this); +} + +function onEndNT(self) { + self.end(); +} + +Object.defineProperty(Duplex.prototype, 'destroyed', { + get: function () { + if (this._readableState === undefined || this._writableState === undefined) { + return false; + } + return this._readableState.destroyed && this._writableState.destroyed; + }, + set: function (value) { + // we ignore the value if the stream + // has not been initialized yet + if (this._readableState === undefined || this._writableState === undefined) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._readableState.destroyed = value; + this._writableState.destroyed = value; + } +}); + +Duplex.prototype._destroy = function (err, cb) { + this.push(null); + this.end(); + + pna.nextTick(cb, err); +}; +},{"./_stream_readable":21,"./_stream_writable":23,"core-util-is":9,"inherits":13,"process-nextick-args":16}],20:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a passthrough stream. +// basically just the most minimal sort of Transform stream. +// Every written chunk gets output as-is. + +'use strict'; + +module.exports = PassThrough; + +var Transform = require('./_stream_transform'); + +/**/ +var util = Object.create(require('core-util-is')); +util.inherits = require('inherits'); +/**/ + +util.inherits(PassThrough, Transform); + +function PassThrough(options) { + if (!(this instanceof PassThrough)) return new PassThrough(options); + + Transform.call(this, options); +} + +PassThrough.prototype._transform = function (chunk, encoding, cb) { + cb(null, chunk); +}; +},{"./_stream_transform":22,"core-util-is":9,"inherits":13}],21:[function(require,module,exports){ +(function (process,global){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; + +/**/ + +var pna = require('process-nextick-args'); +/**/ + +module.exports = Readable; + +/**/ +var isArray = require('isarray'); +/**/ + +/**/ +var Duplex; +/**/ + +Readable.ReadableState = ReadableState; + +/**/ +var EE = require('events').EventEmitter; + +var EElistenerCount = function (emitter, type) { + return emitter.listeners(type).length; +}; +/**/ + +/**/ +var Stream = require('./internal/streams/stream'); +/**/ + +/**/ + +var Buffer = require('safe-buffer').Buffer; +var OurUint8Array = global.Uint8Array || function () {}; +function _uint8ArrayToBuffer(chunk) { + return Buffer.from(chunk); +} +function _isUint8Array(obj) { + return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; +} + +/**/ + +/**/ +var util = Object.create(require('core-util-is')); +util.inherits = require('inherits'); +/**/ + +/**/ +var debugUtil = require('util'); +var debug = void 0; +if (debugUtil && debugUtil.debuglog) { + debug = debugUtil.debuglog('stream'); +} else { + debug = function () {}; +} +/**/ + +var BufferList = require('./internal/streams/BufferList'); +var destroyImpl = require('./internal/streams/destroy'); +var StringDecoder; + +util.inherits(Readable, Stream); + +var kProxyEvents = ['error', 'close', 'destroy', 'pause', 'resume']; + +function prependListener(emitter, event, fn) { + // Sadly this is not cacheable as some libraries bundle their own + // event emitter implementation with them. + if (typeof emitter.prependListener === 'function') return emitter.prependListener(event, fn); + + // This is a hack to make sure that our error handler is attached before any + // userland ones. NEVER DO THIS. This is here only because this code needs + // to continue to work with older versions of Node.js that do not include + // the prependListener() method. The goal is to eventually remove this hack. + if (!emitter._events || !emitter._events[event]) emitter.on(event, fn);else if (isArray(emitter._events[event])) emitter._events[event].unshift(fn);else emitter._events[event] = [fn, emitter._events[event]]; +} + +function ReadableState(options, stream) { + Duplex = Duplex || require('./_stream_duplex'); + + options = options || {}; + + // Duplex streams are both readable and writable, but share + // the same options object. + // However, some cases require setting options to different + // values for the readable and the writable sides of the duplex stream. + // These options can be provided separately as readableXXX and writableXXX. + var isDuplex = stream instanceof Duplex; + + // object stream flag. Used to make read(n) ignore n and to + // make all the buffer merging and length checks go away + this.objectMode = !!options.objectMode; + + if (isDuplex) this.objectMode = this.objectMode || !!options.readableObjectMode; + + // the point at which it stops calling _read() to fill the buffer + // Note: 0 is a valid value, means "don't call _read preemptively ever" + var hwm = options.highWaterMark; + var readableHwm = options.readableHighWaterMark; + var defaultHwm = this.objectMode ? 16 : 16 * 1024; + + if (hwm || hwm === 0) this.highWaterMark = hwm;else if (isDuplex && (readableHwm || readableHwm === 0)) this.highWaterMark = readableHwm;else this.highWaterMark = defaultHwm; + + // cast to ints. + this.highWaterMark = Math.floor(this.highWaterMark); + + // A linked list is used to store data chunks instead of an array because the + // linked list can remove elements from the beginning faster than + // array.shift() + this.buffer = new BufferList(); + this.length = 0; + this.pipes = null; + this.pipesCount = 0; + this.flowing = null; + this.ended = false; + this.endEmitted = false; + this.reading = false; + + // a flag to be able to tell if the event 'readable'/'data' is emitted + // immediately, or on a later tick. We set this to true at first, because + // any actions that shouldn't happen until "later" should generally also + // not happen before the first read call. + this.sync = true; + + // whenever we return null, then we set a flag to say + // that we're awaiting a 'readable' event emission. + this.needReadable = false; + this.emittedReadable = false; + this.readableListening = false; + this.resumeScheduled = false; + + // has it been destroyed + this.destroyed = false; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // the number of writers that are awaiting a drain event in .pipe()s + this.awaitDrain = 0; + + // if true, a maybeReadMore has been scheduled + this.readingMore = false; + + this.decoder = null; + this.encoding = null; + if (options.encoding) { + if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder; + this.decoder = new StringDecoder(options.encoding); + this.encoding = options.encoding; + } +} + +function Readable(options) { + Duplex = Duplex || require('./_stream_duplex'); + + if (!(this instanceof Readable)) return new Readable(options); + + this._readableState = new ReadableState(options, this); + + // legacy + this.readable = true; + + if (options) { + if (typeof options.read === 'function') this._read = options.read; + + if (typeof options.destroy === 'function') this._destroy = options.destroy; + } + + Stream.call(this); +} + +Object.defineProperty(Readable.prototype, 'destroyed', { + get: function () { + if (this._readableState === undefined) { + return false; + } + return this._readableState.destroyed; + }, + set: function (value) { + // we ignore the value if the stream + // has not been initialized yet + if (!this._readableState) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._readableState.destroyed = value; + } +}); + +Readable.prototype.destroy = destroyImpl.destroy; +Readable.prototype._undestroy = destroyImpl.undestroy; +Readable.prototype._destroy = function (err, cb) { + this.push(null); + cb(err); +}; + +// Manually shove something into the read() buffer. +// This returns true if the highWaterMark has not been hit yet, +// similar to how Writable.write() returns true if you should +// write() some more. +Readable.prototype.push = function (chunk, encoding) { + var state = this._readableState; + var skipChunkCheck; + + if (!state.objectMode) { + if (typeof chunk === 'string') { + encoding = encoding || state.defaultEncoding; + if (encoding !== state.encoding) { + chunk = Buffer.from(chunk, encoding); + encoding = ''; + } + skipChunkCheck = true; + } + } else { + skipChunkCheck = true; + } + + return readableAddChunk(this, chunk, encoding, false, skipChunkCheck); +}; + +// Unshift should *always* be something directly out of read() +Readable.prototype.unshift = function (chunk) { + return readableAddChunk(this, chunk, null, true, false); +}; + +function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) { + var state = stream._readableState; + if (chunk === null) { + state.reading = false; + onEofChunk(stream, state); + } else { + var er; + if (!skipChunkCheck) er = chunkInvalid(state, chunk); + if (er) { + stream.emit('error', er); + } else if (state.objectMode || chunk && chunk.length > 0) { + if (typeof chunk !== 'string' && !state.objectMode && Object.getPrototypeOf(chunk) !== Buffer.prototype) { + chunk = _uint8ArrayToBuffer(chunk); + } + + if (addToFront) { + if (state.endEmitted) stream.emit('error', new Error('stream.unshift() after end event'));else addChunk(stream, state, chunk, true); + } else if (state.ended) { + stream.emit('error', new Error('stream.push() after EOF')); + } else { + state.reading = false; + if (state.decoder && !encoding) { + chunk = state.decoder.write(chunk); + if (state.objectMode || chunk.length !== 0) addChunk(stream, state, chunk, false);else maybeReadMore(stream, state); + } else { + addChunk(stream, state, chunk, false); + } + } + } else if (!addToFront) { + state.reading = false; + } + } + + return needMoreData(state); +} + +function addChunk(stream, state, chunk, addToFront) { + if (state.flowing && state.length === 0 && !state.sync) { + stream.emit('data', chunk); + stream.read(0); + } else { + // update the buffer info. + state.length += state.objectMode ? 1 : chunk.length; + if (addToFront) state.buffer.unshift(chunk);else state.buffer.push(chunk); + + if (state.needReadable) emitReadable(stream); + } + maybeReadMore(stream, state); +} + +function chunkInvalid(state, chunk) { + var er; + if (!_isUint8Array(chunk) && typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { + er = new TypeError('Invalid non-string/buffer chunk'); + } + return er; +} + +// if it's past the high water mark, we can push in some more. +// Also, if we have no data yet, we can stand some +// more bytes. This is to work around cases where hwm=0, +// such as the repl. Also, if the push() triggered a +// readable event, and the user called read(largeNumber) such that +// needReadable was set, then we ought to push more, so that another +// 'readable' event will be triggered. +function needMoreData(state) { + return !state.ended && (state.needReadable || state.length < state.highWaterMark || state.length === 0); +} + +Readable.prototype.isPaused = function () { + return this._readableState.flowing === false; +}; + +// backwards compatibility. +Readable.prototype.setEncoding = function (enc) { + if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder; + this._readableState.decoder = new StringDecoder(enc); + this._readableState.encoding = enc; + return this; +}; + +// Don't raise the hwm > 8MB +var MAX_HWM = 0x800000; +function computeNewHighWaterMark(n) { + if (n >= MAX_HWM) { + n = MAX_HWM; + } else { + // Get the next highest power of 2 to prevent increasing hwm excessively in + // tiny amounts + n--; + n |= n >>> 1; + n |= n >>> 2; + n |= n >>> 4; + n |= n >>> 8; + n |= n >>> 16; + n++; + } + return n; +} + +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function howMuchToRead(n, state) { + if (n <= 0 || state.length === 0 && state.ended) return 0; + if (state.objectMode) return 1; + if (n !== n) { + // Only flow one buffer at a time + if (state.flowing && state.length) return state.buffer.head.data.length;else return state.length; + } + // If we're asking for more than the current hwm, then raise the hwm. + if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n); + if (n <= state.length) return n; + // Don't have enough + if (!state.ended) { + state.needReadable = true; + return 0; + } + return state.length; +} + +// you can override either this method, or the async _read(n) below. +Readable.prototype.read = function (n) { + debug('read', n); + n = parseInt(n, 10); + var state = this._readableState; + var nOrig = n; + + if (n !== 0) state.emittedReadable = false; + + // if we're doing read(0) to trigger a readable event, but we + // already have a bunch of data in the buffer, then just trigger + // the 'readable' event and move on. + if (n === 0 && state.needReadable && (state.length >= state.highWaterMark || state.ended)) { + debug('read: emitReadable', state.length, state.ended); + if (state.length === 0 && state.ended) endReadable(this);else emitReadable(this); + return null; + } + + n = howMuchToRead(n, state); + + // if we've ended, and we're now clear, then finish it up. + if (n === 0 && state.ended) { + if (state.length === 0) endReadable(this); + return null; + } + + // All the actual chunk generation logic needs to be + // *below* the call to _read. The reason is that in certain + // synthetic stream cases, such as passthrough streams, _read + // may be a completely synchronous operation which may change + // the state of the read buffer, providing enough data when + // before there was *not* enough. + // + // So, the steps are: + // 1. Figure out what the state of things will be after we do + // a read from the buffer. + // + // 2. If that resulting state will trigger a _read, then call _read. + // Note that this may be asynchronous, or synchronous. Yes, it is + // deeply ugly to write APIs this way, but that still doesn't mean + // that the Readable class should behave improperly, as streams are + // designed to be sync/async agnostic. + // Take note if the _read call is sync or async (ie, if the read call + // has returned yet), so that we know whether or not it's safe to emit + // 'readable' etc. + // + // 3. Actually pull the requested chunks out of the buffer and return. + + // if we need a readable event, then we need to do some reading. + var doRead = state.needReadable; + debug('need readable', doRead); + + // if we currently have less than the highWaterMark, then also read some + if (state.length === 0 || state.length - n < state.highWaterMark) { + doRead = true; + debug('length less than watermark', doRead); + } + + // however, if we've ended, then there's no point, and if we're already + // reading, then it's unnecessary. + if (state.ended || state.reading) { + doRead = false; + debug('reading or ended', doRead); + } else if (doRead) { + debug('do read'); + state.reading = true; + state.sync = true; + // if the length is currently zero, then we *need* a readable event. + if (state.length === 0) state.needReadable = true; + // call internal read method + this._read(state.highWaterMark); + state.sync = false; + // If _read pushed data synchronously, then `reading` will be false, + // and we need to re-evaluate how much data we can return to the user. + if (!state.reading) n = howMuchToRead(nOrig, state); + } + + var ret; + if (n > 0) ret = fromList(n, state);else ret = null; + + if (ret === null) { + state.needReadable = true; + n = 0; + } else { + state.length -= n; + } + + if (state.length === 0) { + // If we have nothing in the buffer, then we want to know + // as soon as we *do* get something into the buffer. + if (!state.ended) state.needReadable = true; + + // If we tried to read() past the EOF, then emit end on the next tick. + if (nOrig !== n && state.ended) endReadable(this); + } + + if (ret !== null) this.emit('data', ret); + + return ret; +}; + +function onEofChunk(stream, state) { + if (state.ended) return; + if (state.decoder) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) { + state.buffer.push(chunk); + state.length += state.objectMode ? 1 : chunk.length; + } + } + state.ended = true; + + // emit 'readable' now to make sure it gets picked up. + emitReadable(stream); +} + +// Don't emit readable right away in sync mode, because this can trigger +// another read() call => stack overflow. This way, it might trigger +// a nextTick recursion warning, but that's not so bad. +function emitReadable(stream) { + var state = stream._readableState; + state.needReadable = false; + if (!state.emittedReadable) { + debug('emitReadable', state.flowing); + state.emittedReadable = true; + if (state.sync) pna.nextTick(emitReadable_, stream);else emitReadable_(stream); + } +} + +function emitReadable_(stream) { + debug('emit readable'); + stream.emit('readable'); + flow(stream); +} + +// at this point, the user has presumably seen the 'readable' event, +// and called read() to consume some data. that may have triggered +// in turn another _read(n) call, in which case reading = true if +// it's in progress. +// However, if we're not ended, or reading, and the length < hwm, +// then go ahead and try to read some more preemptively. +function maybeReadMore(stream, state) { + if (!state.readingMore) { + state.readingMore = true; + pna.nextTick(maybeReadMore_, stream, state); + } +} + +function maybeReadMore_(stream, state) { + var len = state.length; + while (!state.reading && !state.flowing && !state.ended && state.length < state.highWaterMark) { + debug('maybeReadMore read 0'); + stream.read(0); + if (len === state.length) + // didn't get any data, stop spinning. + break;else len = state.length; + } + state.readingMore = false; +} + +// abstract method. to be overridden in specific implementation classes. +// call cb(er, data) where data is <= n in length. +// for virtual (non-string, non-buffer) streams, "length" is somewhat +// arbitrary, and perhaps not very meaningful. +Readable.prototype._read = function (n) { + this.emit('error', new Error('_read() is not implemented')); +}; + +Readable.prototype.pipe = function (dest, pipeOpts) { + var src = this; + var state = this._readableState; + + switch (state.pipesCount) { + case 0: + state.pipes = dest; + break; + case 1: + state.pipes = [state.pipes, dest]; + break; + default: + state.pipes.push(dest); + break; + } + state.pipesCount += 1; + debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts); + + var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr; + + var endFn = doEnd ? onend : unpipe; + if (state.endEmitted) pna.nextTick(endFn);else src.once('end', endFn); + + dest.on('unpipe', onunpipe); + function onunpipe(readable, unpipeInfo) { + debug('onunpipe'); + if (readable === src) { + if (unpipeInfo && unpipeInfo.hasUnpiped === false) { + unpipeInfo.hasUnpiped = true; + cleanup(); + } + } + } + + function onend() { + debug('onend'); + dest.end(); + } + + // when the dest drains, it reduces the awaitDrain counter + // on the source. This would be more elegant with a .once() + // handler in flow(), but adding and removing repeatedly is + // too slow. + var ondrain = pipeOnDrain(src); + dest.on('drain', ondrain); + + var cleanedUp = false; + function cleanup() { + debug('cleanup'); + // cleanup event handlers once the pipe is broken + dest.removeListener('close', onclose); + dest.removeListener('finish', onfinish); + dest.removeListener('drain', ondrain); + dest.removeListener('error', onerror); + dest.removeListener('unpipe', onunpipe); + src.removeListener('end', onend); + src.removeListener('end', unpipe); + src.removeListener('data', ondata); + + cleanedUp = true; + + // if the reader is waiting for a drain event from this + // specific writer, then it would cause it to never start + // flowing again. + // So, if this is awaiting a drain, then we just call it now. + // If we don't know, then assume that we are waiting for one. + if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) ondrain(); + } + + // If the user pushes more data while we're writing to dest then we'll end up + // in ondata again. However, we only want to increase awaitDrain once because + // dest will only emit one 'drain' event for the multiple writes. + // => Introduce a guard on increasing awaitDrain. + var increasedAwaitDrain = false; + src.on('data', ondata); + function ondata(chunk) { + debug('ondata'); + increasedAwaitDrain = false; + var ret = dest.write(chunk); + if (false === ret && !increasedAwaitDrain) { + // If the user unpiped during `dest.write()`, it is possible + // to get stuck in a permanently paused state if that write + // also returned false. + // => Check whether `dest` is still a piping destination. + if ((state.pipesCount === 1 && state.pipes === dest || state.pipesCount > 1 && indexOf(state.pipes, dest) !== -1) && !cleanedUp) { + debug('false write response, pause', src._readableState.awaitDrain); + src._readableState.awaitDrain++; + increasedAwaitDrain = true; + } + src.pause(); + } + } + + // if the dest has an error, then stop piping into it. + // however, don't suppress the throwing behavior for this. + function onerror(er) { + debug('onerror', er); + unpipe(); + dest.removeListener('error', onerror); + if (EElistenerCount(dest, 'error') === 0) dest.emit('error', er); + } + + // Make sure our error handler is attached before userland ones. + prependListener(dest, 'error', onerror); + + // Both close and finish should trigger unpipe, but only once. + function onclose() { + dest.removeListener('finish', onfinish); + unpipe(); + } + dest.once('close', onclose); + function onfinish() { + debug('onfinish'); + dest.removeListener('close', onclose); + unpipe(); + } + dest.once('finish', onfinish); + + function unpipe() { + debug('unpipe'); + src.unpipe(dest); + } + + // tell the dest that it's being piped to + dest.emit('pipe', src); + + // start the flow if it hasn't been started already. + if (!state.flowing) { + debug('pipe resume'); + src.resume(); + } + + return dest; +}; + +function pipeOnDrain(src) { + return function () { + var state = src._readableState; + debug('pipeOnDrain', state.awaitDrain); + if (state.awaitDrain) state.awaitDrain--; + if (state.awaitDrain === 0 && EElistenerCount(src, 'data')) { + state.flowing = true; + flow(src); + } + }; +} + +Readable.prototype.unpipe = function (dest) { + var state = this._readableState; + var unpipeInfo = { hasUnpiped: false }; + + // if we're not piping anywhere, then do nothing. + if (state.pipesCount === 0) return this; + + // just one destination. most common case. + if (state.pipesCount === 1) { + // passed in one, but it's not the right one. + if (dest && dest !== state.pipes) return this; + + if (!dest) dest = state.pipes; + + // got a match. + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + if (dest) dest.emit('unpipe', this, unpipeInfo); + return this; + } + + // slow case. multiple pipe destinations. + + if (!dest) { + // remove all. + var dests = state.pipes; + var len = state.pipesCount; + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + + for (var i = 0; i < len; i++) { + dests[i].emit('unpipe', this, unpipeInfo); + }return this; + } + + // try to find the right one. + var index = indexOf(state.pipes, dest); + if (index === -1) return this; + + state.pipes.splice(index, 1); + state.pipesCount -= 1; + if (state.pipesCount === 1) state.pipes = state.pipes[0]; + + dest.emit('unpipe', this, unpipeInfo); + + return this; +}; + +// set up data events if they are asked for +// Ensure readable listeners eventually get something +Readable.prototype.on = function (ev, fn) { + var res = Stream.prototype.on.call(this, ev, fn); + + if (ev === 'data') { + // Start flowing on next tick if stream isn't explicitly paused + if (this._readableState.flowing !== false) this.resume(); + } else if (ev === 'readable') { + var state = this._readableState; + if (!state.endEmitted && !state.readableListening) { + state.readableListening = state.needReadable = true; + state.emittedReadable = false; + if (!state.reading) { + pna.nextTick(nReadingNextTick, this); + } else if (state.length) { + emitReadable(this); + } + } + } + + return res; +}; +Readable.prototype.addListener = Readable.prototype.on; + +function nReadingNextTick(self) { + debug('readable nexttick read 0'); + self.read(0); +} + +// pause() and resume() are remnants of the legacy readable stream API +// If the user uses them, then switch into old mode. +Readable.prototype.resume = function () { + var state = this._readableState; + if (!state.flowing) { + debug('resume'); + state.flowing = true; + resume(this, state); + } + return this; +}; + +function resume(stream, state) { + if (!state.resumeScheduled) { + state.resumeScheduled = true; + pna.nextTick(resume_, stream, state); + } +} + +function resume_(stream, state) { + if (!state.reading) { + debug('resume read 0'); + stream.read(0); + } + + state.resumeScheduled = false; + state.awaitDrain = 0; + stream.emit('resume'); + flow(stream); + if (state.flowing && !state.reading) stream.read(0); +} + +Readable.prototype.pause = function () { + debug('call pause flowing=%j', this._readableState.flowing); + if (false !== this._readableState.flowing) { + debug('pause'); + this._readableState.flowing = false; + this.emit('pause'); + } + return this; +}; + +function flow(stream) { + var state = stream._readableState; + debug('flow', state.flowing); + while (state.flowing && stream.read() !== null) {} +} + +// wrap an old-style stream as the async data source. +// This is *not* part of the readable stream interface. +// It is an ugly unfortunate mess of history. +Readable.prototype.wrap = function (stream) { + var _this = this; + + var state = this._readableState; + var paused = false; + + stream.on('end', function () { + debug('wrapped end'); + if (state.decoder && !state.ended) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) _this.push(chunk); + } + + _this.push(null); + }); + + stream.on('data', function (chunk) { + debug('wrapped data'); + if (state.decoder) chunk = state.decoder.write(chunk); + + // don't skip over falsy values in objectMode + if (state.objectMode && (chunk === null || chunk === undefined)) return;else if (!state.objectMode && (!chunk || !chunk.length)) return; + + var ret = _this.push(chunk); + if (!ret) { + paused = true; + stream.pause(); + } + }); + + // proxy all the other methods. + // important when wrapping filters and duplexes. + for (var i in stream) { + if (this[i] === undefined && typeof stream[i] === 'function') { + this[i] = function (method) { + return function () { + return stream[method].apply(stream, arguments); + }; + }(i); + } + } + + // proxy certain important events. + for (var n = 0; n < kProxyEvents.length; n++) { + stream.on(kProxyEvents[n], this.emit.bind(this, kProxyEvents[n])); + } + + // when we try to consume some more bytes, simply unpause the + // underlying stream. + this._read = function (n) { + debug('wrapped _read', n); + if (paused) { + paused = false; + stream.resume(); + } + }; + + return this; +}; + +Object.defineProperty(Readable.prototype, 'readableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function () { + return this._readableState.highWaterMark; + } +}); + +// exposed for testing purposes only. +Readable._fromList = fromList; + +// Pluck off n bytes from an array of buffers. +// Length is the combined lengths of all the buffers in the list. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function fromList(n, state) { + // nothing buffered + if (state.length === 0) return null; + + var ret; + if (state.objectMode) ret = state.buffer.shift();else if (!n || n >= state.length) { + // read it all, truncate the list + if (state.decoder) ret = state.buffer.join('');else if (state.buffer.length === 1) ret = state.buffer.head.data;else ret = state.buffer.concat(state.length); + state.buffer.clear(); + } else { + // read part of list + ret = fromListPartial(n, state.buffer, state.decoder); + } + + return ret; +} + +// Extracts only enough buffered data to satisfy the amount requested. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function fromListPartial(n, list, hasStrings) { + var ret; + if (n < list.head.data.length) { + // slice is the same for buffers and strings + ret = list.head.data.slice(0, n); + list.head.data = list.head.data.slice(n); + } else if (n === list.head.data.length) { + // first chunk is a perfect match + ret = list.shift(); + } else { + // result spans more than one buffer + ret = hasStrings ? copyFromBufferString(n, list) : copyFromBuffer(n, list); + } + return ret; +} + +// Copies a specified amount of characters from the list of buffered data +// chunks. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function copyFromBufferString(n, list) { + var p = list.head; + var c = 1; + var ret = p.data; + n -= ret.length; + while (p = p.next) { + var str = p.data; + var nb = n > str.length ? str.length : n; + if (nb === str.length) ret += str;else ret += str.slice(0, n); + n -= nb; + if (n === 0) { + if (nb === str.length) { + ++c; + if (p.next) list.head = p.next;else list.head = list.tail = null; + } else { + list.head = p; + p.data = str.slice(nb); + } + break; + } + ++c; + } + list.length -= c; + return ret; +} + +// Copies a specified amount of bytes from the list of buffered data chunks. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function copyFromBuffer(n, list) { + var ret = Buffer.allocUnsafe(n); + var p = list.head; + var c = 1; + p.data.copy(ret); + n -= p.data.length; + while (p = p.next) { + var buf = p.data; + var nb = n > buf.length ? buf.length : n; + buf.copy(ret, ret.length - n, 0, nb); + n -= nb; + if (n === 0) { + if (nb === buf.length) { + ++c; + if (p.next) list.head = p.next;else list.head = list.tail = null; + } else { + list.head = p; + p.data = buf.slice(nb); + } + break; + } + ++c; + } + list.length -= c; + return ret; +} + +function endReadable(stream) { + var state = stream._readableState; + + // If we get here before consuming all the bytes, then that is a + // bug in node. Should never happen. + if (state.length > 0) throw new Error('"endReadable()" called on non-empty stream'); + + if (!state.endEmitted) { + state.ended = true; + pna.nextTick(endReadableNT, state, stream); + } +} + +function endReadableNT(state, stream) { + // Check that we didn't get one last unshift. + if (!state.endEmitted && state.length === 0) { + state.endEmitted = true; + stream.readable = false; + stream.emit('end'); + } +} + +function indexOf(xs, x) { + for (var i = 0, l = xs.length; i < l; i++) { + if (xs[i] === x) return i; + } + return -1; +} +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./_stream_duplex":19,"./internal/streams/BufferList":24,"./internal/streams/destroy":25,"./internal/streams/stream":26,"_process":17,"core-util-is":9,"events":10,"inherits":13,"isarray":15,"process-nextick-args":16,"safe-buffer":27,"string_decoder/":28,"util":7}],22:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a transform stream is a readable/writable stream where you do +// something with the data. Sometimes it's called a "filter", +// but that's not a great name for it, since that implies a thing where +// some bits pass through, and others are simply ignored. (That would +// be a valid example of a transform, of course.) +// +// While the output is causally related to the input, it's not a +// necessarily symmetric or synchronous transformation. For example, +// a zlib stream might take multiple plain-text writes(), and then +// emit a single compressed chunk some time in the future. +// +// Here's how this works: +// +// The Transform stream has all the aspects of the readable and writable +// stream classes. When you write(chunk), that calls _write(chunk,cb) +// internally, and returns false if there's a lot of pending writes +// buffered up. When you call read(), that calls _read(n) until +// there's enough pending readable data buffered up. +// +// In a transform stream, the written data is placed in a buffer. When +// _read(n) is called, it transforms the queued up data, calling the +// buffered _write cb's as it consumes chunks. If consuming a single +// written chunk would result in multiple output chunks, then the first +// outputted bit calls the readcb, and subsequent chunks just go into +// the read buffer, and will cause it to emit 'readable' if necessary. +// +// This way, back-pressure is actually determined by the reading side, +// since _read has to be called to start processing a new chunk. However, +// a pathological inflate type of transform can cause excessive buffering +// here. For example, imagine a stream where every byte of input is +// interpreted as an integer from 0-255, and then results in that many +// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in +// 1kb of data being output. In this case, you could write a very small +// amount of input, and end up with a very large amount of output. In +// such a pathological inflating mechanism, there'd be no way to tell +// the system to stop doing the transform. A single 4MB write could +// cause the system to run out of memory. +// +// However, even in such a pathological case, only a single written chunk +// would be consumed, and then the rest would wait (un-transformed) until +// the results of the previous transformed chunk were consumed. + +'use strict'; + +module.exports = Transform; + +var Duplex = require('./_stream_duplex'); + +/**/ +var util = Object.create(require('core-util-is')); +util.inherits = require('inherits'); +/**/ + +util.inherits(Transform, Duplex); + +function afterTransform(er, data) { + var ts = this._transformState; + ts.transforming = false; + + var cb = ts.writecb; + + if (!cb) { + return this.emit('error', new Error('write callback called multiple times')); + } + + ts.writechunk = null; + ts.writecb = null; + + if (data != null) // single equals check for both `null` and `undefined` + this.push(data); + + cb(er); + + var rs = this._readableState; + rs.reading = false; + if (rs.needReadable || rs.length < rs.highWaterMark) { + this._read(rs.highWaterMark); + } +} + +function Transform(options) { + if (!(this instanceof Transform)) return new Transform(options); + + Duplex.call(this, options); + + this._transformState = { + afterTransform: afterTransform.bind(this), + needTransform: false, + transforming: false, + writecb: null, + writechunk: null, + writeencoding: null + }; + + // start out asking for a readable event once data is transformed. + this._readableState.needReadable = true; + + // we have implemented the _read method, and done the other things + // that Readable wants before the first _read call, so unset the + // sync guard flag. + this._readableState.sync = false; + + if (options) { + if (typeof options.transform === 'function') this._transform = options.transform; + + if (typeof options.flush === 'function') this._flush = options.flush; + } + + // When the writable side finishes, then flush out anything remaining. + this.on('prefinish', prefinish); +} + +function prefinish() { + var _this = this; + + if (typeof this._flush === 'function') { + this._flush(function (er, data) { + done(_this, er, data); + }); + } else { + done(this, null, null); + } +} + +Transform.prototype.push = function (chunk, encoding) { + this._transformState.needTransform = false; + return Duplex.prototype.push.call(this, chunk, encoding); +}; + +// This is the part where you do stuff! +// override this function in implementation classes. +// 'chunk' is an input chunk. +// +// Call `push(newChunk)` to pass along transformed output +// to the readable side. You may call 'push' zero or more times. +// +// Call `cb(err)` when you are done with this chunk. If you pass +// an error, then that'll put the hurt on the whole operation. If you +// never call cb(), then you'll never get another chunk. +Transform.prototype._transform = function (chunk, encoding, cb) { + throw new Error('_transform() is not implemented'); +}; + +Transform.prototype._write = function (chunk, encoding, cb) { + var ts = this._transformState; + ts.writecb = cb; + ts.writechunk = chunk; + ts.writeencoding = encoding; + if (!ts.transforming) { + var rs = this._readableState; + if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark); + } +}; + +// Doesn't matter what the args are here. +// _transform does all the work. +// That we got here means that the readable side wants more data. +Transform.prototype._read = function (n) { + var ts = this._transformState; + + if (ts.writechunk !== null && ts.writecb && !ts.transforming) { + ts.transforming = true; + this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); + } else { + // mark that we need a transform, so that any data that comes in + // will get processed, now that we've asked for it. + ts.needTransform = true; + } +}; + +Transform.prototype._destroy = function (err, cb) { + var _this2 = this; + + Duplex.prototype._destroy.call(this, err, function (err2) { + cb(err2); + _this2.emit('close'); + }); +}; + +function done(stream, er, data) { + if (er) return stream.emit('error', er); + + if (data != null) // single equals check for both `null` and `undefined` + stream.push(data); + + // if there's nothing in the write buffer, then that means + // that nothing more will ever be provided + if (stream._writableState.length) throw new Error('Calling transform done when ws.length != 0'); + + if (stream._transformState.transforming) throw new Error('Calling transform done when still transforming'); + + return stream.push(null); +} +},{"./_stream_duplex":19,"core-util-is":9,"inherits":13}],23:[function(require,module,exports){ +(function (process,global,setImmediate){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// A bit simpler than readable streams. +// Implement an async ._write(chunk, encoding, cb), and it'll handle all +// the drain event emission and buffering. + +'use strict'; + +/**/ + +var pna = require('process-nextick-args'); +/**/ + +module.exports = Writable; + +/* */ +function WriteReq(chunk, encoding, cb) { + this.chunk = chunk; + this.encoding = encoding; + this.callback = cb; + this.next = null; +} + +// It seems a linked list but it is not +// there will be only 2 of these for each stream +function CorkedRequest(state) { + var _this = this; + + this.next = null; + this.entry = null; + this.finish = function () { + onCorkedFinish(_this, state); + }; +} +/* */ + +/**/ +var asyncWrite = !process.browser && ['v0.10', 'v0.9.'].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : pna.nextTick; +/**/ + +/**/ +var Duplex; +/**/ + +Writable.WritableState = WritableState; + +/**/ +var util = Object.create(require('core-util-is')); +util.inherits = require('inherits'); +/**/ + +/**/ +var internalUtil = { + deprecate: require('util-deprecate') +}; +/**/ + +/**/ +var Stream = require('./internal/streams/stream'); +/**/ + +/**/ + +var Buffer = require('safe-buffer').Buffer; +var OurUint8Array = global.Uint8Array || function () {}; +function _uint8ArrayToBuffer(chunk) { + return Buffer.from(chunk); +} +function _isUint8Array(obj) { + return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; +} + +/**/ + +var destroyImpl = require('./internal/streams/destroy'); + +util.inherits(Writable, Stream); + +function nop() {} + +function WritableState(options, stream) { + Duplex = Duplex || require('./_stream_duplex'); + + options = options || {}; + + // Duplex streams are both readable and writable, but share + // the same options object. + // However, some cases require setting options to different + // values for the readable and the writable sides of the duplex stream. + // These options can be provided separately as readableXXX and writableXXX. + var isDuplex = stream instanceof Duplex; + + // object stream flag to indicate whether or not this stream + // contains buffers or objects. + this.objectMode = !!options.objectMode; + + if (isDuplex) this.objectMode = this.objectMode || !!options.writableObjectMode; + + // the point at which write() starts returning false + // Note: 0 is a valid value, means that we always return false if + // the entire buffer is not flushed immediately on write() + var hwm = options.highWaterMark; + var writableHwm = options.writableHighWaterMark; + var defaultHwm = this.objectMode ? 16 : 16 * 1024; + + if (hwm || hwm === 0) this.highWaterMark = hwm;else if (isDuplex && (writableHwm || writableHwm === 0)) this.highWaterMark = writableHwm;else this.highWaterMark = defaultHwm; + + // cast to ints. + this.highWaterMark = Math.floor(this.highWaterMark); + + // if _final has been called + this.finalCalled = false; + + // drain event flag. + this.needDrain = false; + // at the start of calling end() + this.ending = false; + // when end() has been called, and returned + this.ended = false; + // when 'finish' is emitted + this.finished = false; + + // has it been destroyed + this.destroyed = false; + + // should we decode strings into buffers before passing to _write? + // this is here so that some node-core streams can optimize string + // handling at a lower level. + var noDecode = options.decodeStrings === false; + this.decodeStrings = !noDecode; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // not an actual buffer we keep track of, but a measurement + // of how much we're waiting to get pushed to some underlying + // socket or file. + this.length = 0; + + // a flag to see when we're in the middle of a write. + this.writing = false; + + // when true all writes will be buffered until .uncork() call + this.corked = 0; + + // a flag to be able to tell if the onwrite cb is called immediately, + // or on a later tick. We set this to true at first, because any + // actions that shouldn't happen until "later" should generally also + // not happen before the first write call. + this.sync = true; + + // a flag to know if we're processing previously buffered items, which + // may call the _write() callback in the same tick, so that we don't + // end up in an overlapped onwrite situation. + this.bufferProcessing = false; + + // the callback that's passed to _write(chunk,cb) + this.onwrite = function (er) { + onwrite(stream, er); + }; + + // the callback that the user supplies to write(chunk,encoding,cb) + this.writecb = null; + + // the amount that is being written when _write is called. + this.writelen = 0; + + this.bufferedRequest = null; + this.lastBufferedRequest = null; + + // number of pending user-supplied write callbacks + // this must be 0 before 'finish' can be emitted + this.pendingcb = 0; + + // emit prefinish if the only thing we're waiting for is _write cbs + // This is relevant for synchronous Transform streams + this.prefinished = false; + + // True if the error was already emitted and should not be thrown again + this.errorEmitted = false; + + // count buffered requests + this.bufferedRequestCount = 0; + + // allocate the first CorkedRequest, there is always + // one allocated and free to use, and we maintain at most two + this.corkedRequestsFree = new CorkedRequest(this); +} + +WritableState.prototype.getBuffer = function getBuffer() { + var current = this.bufferedRequest; + var out = []; + while (current) { + out.push(current); + current = current.next; + } + return out; +}; + +(function () { + try { + Object.defineProperty(WritableState.prototype, 'buffer', { + get: internalUtil.deprecate(function () { + return this.getBuffer(); + }, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.', 'DEP0003') + }); + } catch (_) {} +})(); + +// Test _writableState for inheritance to account for Duplex streams, +// whose prototype chain only points to Readable. +var realHasInstance; +if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') { + realHasInstance = Function.prototype[Symbol.hasInstance]; + Object.defineProperty(Writable, Symbol.hasInstance, { + value: function (object) { + if (realHasInstance.call(this, object)) return true; + if (this !== Writable) return false; + + return object && object._writableState instanceof WritableState; + } + }); +} else { + realHasInstance = function (object) { + return object instanceof this; + }; +} + +function Writable(options) { + Duplex = Duplex || require('./_stream_duplex'); + + // Writable ctor is applied to Duplexes, too. + // `realHasInstance` is necessary because using plain `instanceof` + // would return false, as no `_writableState` property is attached. + + // Trying to use the custom `instanceof` for Writable here will also break the + // Node.js LazyTransform implementation, which has a non-trivial getter for + // `_writableState` that would lead to infinite recursion. + if (!realHasInstance.call(Writable, this) && !(this instanceof Duplex)) { + return new Writable(options); + } + + this._writableState = new WritableState(options, this); + + // legacy. + this.writable = true; + + if (options) { + if (typeof options.write === 'function') this._write = options.write; + + if (typeof options.writev === 'function') this._writev = options.writev; + + if (typeof options.destroy === 'function') this._destroy = options.destroy; + + if (typeof options.final === 'function') this._final = options.final; + } + + Stream.call(this); +} + +// Otherwise people can pipe Writable streams, which is just wrong. +Writable.prototype.pipe = function () { + this.emit('error', new Error('Cannot pipe, not readable')); +}; + +function writeAfterEnd(stream, cb) { + var er = new Error('write after end'); + // TODO: defer error events consistently everywhere, not just the cb + stream.emit('error', er); + pna.nextTick(cb, er); +} + +// Checks that a user-supplied chunk is valid, especially for the particular +// mode the stream is in. Currently this means that `null` is never accepted +// and undefined/non-string values are only allowed in object mode. +function validChunk(stream, state, chunk, cb) { + var valid = true; + var er = false; + + if (chunk === null) { + er = new TypeError('May not write null values to stream'); + } else if (typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { + er = new TypeError('Invalid non-string/buffer chunk'); + } + if (er) { + stream.emit('error', er); + pna.nextTick(cb, er); + valid = false; + } + return valid; +} + +Writable.prototype.write = function (chunk, encoding, cb) { + var state = this._writableState; + var ret = false; + var isBuf = !state.objectMode && _isUint8Array(chunk); + + if (isBuf && !Buffer.isBuffer(chunk)) { + chunk = _uint8ArrayToBuffer(chunk); + } + + if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + + if (isBuf) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding; + + if (typeof cb !== 'function') cb = nop; + + if (state.ended) writeAfterEnd(this, cb);else if (isBuf || validChunk(this, state, chunk, cb)) { + state.pendingcb++; + ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb); + } + + return ret; +}; + +Writable.prototype.cork = function () { + var state = this._writableState; + + state.corked++; +}; + +Writable.prototype.uncork = function () { + var state = this._writableState; + + if (state.corked) { + state.corked--; + + if (!state.writing && !state.corked && !state.finished && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state); + } +}; + +Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) { + // node::ParseEncoding() requires lower case. + if (typeof encoding === 'string') encoding = encoding.toLowerCase(); + if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new TypeError('Unknown encoding: ' + encoding); + this._writableState.defaultEncoding = encoding; + return this; +}; + +function decodeChunk(state, chunk, encoding) { + if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') { + chunk = Buffer.from(chunk, encoding); + } + return chunk; +} + +Object.defineProperty(Writable.prototype, 'writableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function () { + return this._writableState.highWaterMark; + } +}); + +// if we're already writing something, then just put this +// in the queue, and wait our turn. Otherwise, call _write +// If we return false, then we need a drain event, so set that flag. +function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) { + if (!isBuf) { + var newChunk = decodeChunk(state, chunk, encoding); + if (chunk !== newChunk) { + isBuf = true; + encoding = 'buffer'; + chunk = newChunk; + } + } + var len = state.objectMode ? 1 : chunk.length; + + state.length += len; + + var ret = state.length < state.highWaterMark; + // we must ensure that previous needDrain will not be reset to false. + if (!ret) state.needDrain = true; + + if (state.writing || state.corked) { + var last = state.lastBufferedRequest; + state.lastBufferedRequest = { + chunk: chunk, + encoding: encoding, + isBuf: isBuf, + callback: cb, + next: null + }; + if (last) { + last.next = state.lastBufferedRequest; + } else { + state.bufferedRequest = state.lastBufferedRequest; + } + state.bufferedRequestCount += 1; + } else { + doWrite(stream, state, false, len, chunk, encoding, cb); + } + + return ret; +} + +function doWrite(stream, state, writev, len, chunk, encoding, cb) { + state.writelen = len; + state.writecb = cb; + state.writing = true; + state.sync = true; + if (writev) stream._writev(chunk, state.onwrite);else stream._write(chunk, encoding, state.onwrite); + state.sync = false; +} + +function onwriteError(stream, state, sync, er, cb) { + --state.pendingcb; + + if (sync) { + // defer the callback if we are being called synchronously + // to avoid piling up things on the stack + pna.nextTick(cb, er); + // this can emit finish, and it will always happen + // after error + pna.nextTick(finishMaybe, stream, state); + stream._writableState.errorEmitted = true; + stream.emit('error', er); + } else { + // the caller expect this to happen before if + // it is async + cb(er); + stream._writableState.errorEmitted = true; + stream.emit('error', er); + // this can emit finish, but finish must + // always follow error + finishMaybe(stream, state); + } +} + +function onwriteStateUpdate(state) { + state.writing = false; + state.writecb = null; + state.length -= state.writelen; + state.writelen = 0; +} + +function onwrite(stream, er) { + var state = stream._writableState; + var sync = state.sync; + var cb = state.writecb; + + onwriteStateUpdate(state); + + if (er) onwriteError(stream, state, sync, er, cb);else { + // Check if we're actually ready to finish, but don't emit yet + var finished = needFinish(state); + + if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) { + clearBuffer(stream, state); + } + + if (sync) { + /**/ + asyncWrite(afterWrite, stream, state, finished, cb); + /**/ + } else { + afterWrite(stream, state, finished, cb); + } + } +} + +function afterWrite(stream, state, finished, cb) { + if (!finished) onwriteDrain(stream, state); + state.pendingcb--; + cb(); + finishMaybe(stream, state); +} + +// Must force callback to be called on nextTick, so that we don't +// emit 'drain' before the write() consumer gets the 'false' return +// value, and has a chance to attach a 'drain' listener. +function onwriteDrain(stream, state) { + if (state.length === 0 && state.needDrain) { + state.needDrain = false; + stream.emit('drain'); + } +} + +// if there's something in the buffer waiting, then process it +function clearBuffer(stream, state) { + state.bufferProcessing = true; + var entry = state.bufferedRequest; + + if (stream._writev && entry && entry.next) { + // Fast case, write everything using _writev() + var l = state.bufferedRequestCount; + var buffer = new Array(l); + var holder = state.corkedRequestsFree; + holder.entry = entry; + + var count = 0; + var allBuffers = true; + while (entry) { + buffer[count] = entry; + if (!entry.isBuf) allBuffers = false; + entry = entry.next; + count += 1; + } + buffer.allBuffers = allBuffers; + + doWrite(stream, state, true, state.length, buffer, '', holder.finish); + + // doWrite is almost always async, defer these to save a bit of time + // as the hot path ends with doWrite + state.pendingcb++; + state.lastBufferedRequest = null; + if (holder.next) { + state.corkedRequestsFree = holder.next; + holder.next = null; + } else { + state.corkedRequestsFree = new CorkedRequest(state); + } + state.bufferedRequestCount = 0; + } else { + // Slow case, write chunks one-by-one + while (entry) { + var chunk = entry.chunk; + var encoding = entry.encoding; + var cb = entry.callback; + var len = state.objectMode ? 1 : chunk.length; + + doWrite(stream, state, false, len, chunk, encoding, cb); + entry = entry.next; + state.bufferedRequestCount--; + // if we didn't call the onwrite immediately, then + // it means that we need to wait until it does. + // also, that means that the chunk and cb are currently + // being processed, so move the buffer counter past them. + if (state.writing) { + break; + } + } + + if (entry === null) state.lastBufferedRequest = null; + } + + state.bufferedRequest = entry; + state.bufferProcessing = false; +} + +Writable.prototype._write = function (chunk, encoding, cb) { + cb(new Error('_write() is not implemented')); +}; + +Writable.prototype._writev = null; + +Writable.prototype.end = function (chunk, encoding, cb) { + var state = this._writableState; + + if (typeof chunk === 'function') { + cb = chunk; + chunk = null; + encoding = null; + } else if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + + if (chunk !== null && chunk !== undefined) this.write(chunk, encoding); + + // .end() fully uncorks + if (state.corked) { + state.corked = 1; + this.uncork(); + } + + // ignore unnecessary end() calls. + if (!state.ending && !state.finished) endWritable(this, state, cb); +}; + +function needFinish(state) { + return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing; +} +function callFinal(stream, state) { + stream._final(function (err) { + state.pendingcb--; + if (err) { + stream.emit('error', err); + } + state.prefinished = true; + stream.emit('prefinish'); + finishMaybe(stream, state); + }); +} +function prefinish(stream, state) { + if (!state.prefinished && !state.finalCalled) { + if (typeof stream._final === 'function') { + state.pendingcb++; + state.finalCalled = true; + pna.nextTick(callFinal, stream, state); + } else { + state.prefinished = true; + stream.emit('prefinish'); + } + } +} + +function finishMaybe(stream, state) { + var need = needFinish(state); + if (need) { + prefinish(stream, state); + if (state.pendingcb === 0) { + state.finished = true; + stream.emit('finish'); + } + } + return need; +} + +function endWritable(stream, state, cb) { + state.ending = true; + finishMaybe(stream, state); + if (cb) { + if (state.finished) pna.nextTick(cb);else stream.once('finish', cb); + } + state.ended = true; + stream.writable = false; +} + +function onCorkedFinish(corkReq, state, err) { + var entry = corkReq.entry; + corkReq.entry = null; + while (entry) { + var cb = entry.callback; + state.pendingcb--; + cb(err); + entry = entry.next; + } + if (state.corkedRequestsFree) { + state.corkedRequestsFree.next = corkReq; + } else { + state.corkedRequestsFree = corkReq; + } +} + +Object.defineProperty(Writable.prototype, 'destroyed', { + get: function () { + if (this._writableState === undefined) { + return false; + } + return this._writableState.destroyed; + }, + set: function (value) { + // we ignore the value if the stream + // has not been initialized yet + if (!this._writableState) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._writableState.destroyed = value; + } +}); + +Writable.prototype.destroy = destroyImpl.destroy; +Writable.prototype._undestroy = destroyImpl.undestroy; +Writable.prototype._destroy = function (err, cb) { + this.end(); + cb(err); +}; +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("timers").setImmediate) +},{"./_stream_duplex":19,"./internal/streams/destroy":25,"./internal/streams/stream":26,"_process":17,"core-util-is":9,"inherits":13,"process-nextick-args":16,"safe-buffer":27,"timers":35,"util-deprecate":36}],24:[function(require,module,exports){ +'use strict'; + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var Buffer = require('safe-buffer').Buffer; +var util = require('util'); + +function copyBuffer(src, target, offset) { + src.copy(target, offset); +} + +module.exports = function () { + function BufferList() { + _classCallCheck(this, BufferList); + + this.head = null; + this.tail = null; + this.length = 0; + } + + BufferList.prototype.push = function push(v) { + var entry = { data: v, next: null }; + if (this.length > 0) this.tail.next = entry;else this.head = entry; + this.tail = entry; + ++this.length; + }; + + BufferList.prototype.unshift = function unshift(v) { + var entry = { data: v, next: this.head }; + if (this.length === 0) this.tail = entry; + this.head = entry; + ++this.length; + }; + + BufferList.prototype.shift = function shift() { + if (this.length === 0) return; + var ret = this.head.data; + if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next; + --this.length; + return ret; + }; + + BufferList.prototype.clear = function clear() { + this.head = this.tail = null; + this.length = 0; + }; + + BufferList.prototype.join = function join(s) { + if (this.length === 0) return ''; + var p = this.head; + var ret = '' + p.data; + while (p = p.next) { + ret += s + p.data; + }return ret; + }; + + BufferList.prototype.concat = function concat(n) { + if (this.length === 0) return Buffer.alloc(0); + if (this.length === 1) return this.head.data; + var ret = Buffer.allocUnsafe(n >>> 0); + var p = this.head; + var i = 0; + while (p) { + copyBuffer(p.data, ret, i); + i += p.data.length; + p = p.next; + } + return ret; + }; + + return BufferList; +}(); + +if (util && util.inspect && util.inspect.custom) { + module.exports.prototype[util.inspect.custom] = function () { + var obj = util.inspect({ length: this.length }); + return this.constructor.name + ' ' + obj; + }; +} +},{"safe-buffer":27,"util":7}],25:[function(require,module,exports){ +'use strict'; + +/**/ + +var pna = require('process-nextick-args'); +/**/ + +// undocumented cb() API, needed for core, not for public API +function destroy(err, cb) { + var _this = this; + + var readableDestroyed = this._readableState && this._readableState.destroyed; + var writableDestroyed = this._writableState && this._writableState.destroyed; + + if (readableDestroyed || writableDestroyed) { + if (cb) { + cb(err); + } else if (err && (!this._writableState || !this._writableState.errorEmitted)) { + pna.nextTick(emitErrorNT, this, err); + } + return this; + } + + // we set destroyed to true before firing error callbacks in order + // to make it re-entrance safe in case destroy() is called within callbacks + + if (this._readableState) { + this._readableState.destroyed = true; + } + + // if this is a duplex stream mark the writable part as destroyed as well + if (this._writableState) { + this._writableState.destroyed = true; + } + + this._destroy(err || null, function (err) { + if (!cb && err) { + pna.nextTick(emitErrorNT, _this, err); + if (_this._writableState) { + _this._writableState.errorEmitted = true; + } + } else if (cb) { + cb(err); + } + }); + + return this; +} + +function undestroy() { + if (this._readableState) { + this._readableState.destroyed = false; + this._readableState.reading = false; + this._readableState.ended = false; + this._readableState.endEmitted = false; + } + + if (this._writableState) { + this._writableState.destroyed = false; + this._writableState.ended = false; + this._writableState.ending = false; + this._writableState.finished = false; + this._writableState.errorEmitted = false; + } +} + +function emitErrorNT(self, err) { + self.emit('error', err); +} + +module.exports = { + destroy: destroy, + undestroy: undestroy +}; +},{"process-nextick-args":16}],26:[function(require,module,exports){ +module.exports = require('events').EventEmitter; + +},{"events":10}],27:[function(require,module,exports){ +/* eslint-disable node/no-deprecated-api */ +var buffer = require('buffer') +var Buffer = buffer.Buffer + +// alternative to using Object.keys for old browsers +function copyProps (src, dst) { + for (var key in src) { + dst[key] = src[key] + } +} +if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) { + module.exports = buffer +} else { + // Copy properties from require('buffer') + copyProps(buffer, exports) + exports.Buffer = SafeBuffer +} + +function SafeBuffer (arg, encodingOrOffset, length) { + return Buffer(arg, encodingOrOffset, length) +} + +// Copy static methods from Buffer +copyProps(Buffer, SafeBuffer) + +SafeBuffer.from = function (arg, encodingOrOffset, length) { + if (typeof arg === 'number') { + throw new TypeError('Argument must not be a number') + } + return Buffer(arg, encodingOrOffset, length) +} + +SafeBuffer.alloc = function (size, fill, encoding) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + var buf = Buffer(size) + if (fill !== undefined) { + if (typeof encoding === 'string') { + buf.fill(fill, encoding) + } else { + buf.fill(fill) + } + } else { + buf.fill(0) + } + return buf +} + +SafeBuffer.allocUnsafe = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return Buffer(size) +} + +SafeBuffer.allocUnsafeSlow = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return buffer.SlowBuffer(size) +} + +},{"buffer":8}],28:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; + +/**/ + +var Buffer = require('safe-buffer').Buffer; +/**/ + +var isEncoding = Buffer.isEncoding || function (encoding) { + encoding = '' + encoding; + switch (encoding && encoding.toLowerCase()) { + case 'hex':case 'utf8':case 'utf-8':case 'ascii':case 'binary':case 'base64':case 'ucs2':case 'ucs-2':case 'utf16le':case 'utf-16le':case 'raw': + return true; + default: + return false; + } +}; + +function _normalizeEncoding(enc) { + if (!enc) return 'utf8'; + var retried; + while (true) { + switch (enc) { + case 'utf8': + case 'utf-8': + return 'utf8'; + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return 'utf16le'; + case 'latin1': + case 'binary': + return 'latin1'; + case 'base64': + case 'ascii': + case 'hex': + return enc; + default: + if (retried) return; // undefined + enc = ('' + enc).toLowerCase(); + retried = true; + } + } +}; + +// Do not cache `Buffer.isEncoding` when checking encoding names as some +// modules monkey-patch it to support additional encodings +function normalizeEncoding(enc) { + var nenc = _normalizeEncoding(enc); + if (typeof nenc !== 'string' && (Buffer.isEncoding === isEncoding || !isEncoding(enc))) throw new Error('Unknown encoding: ' + enc); + return nenc || enc; +} + +// StringDecoder provides an interface for efficiently splitting a series of +// buffers into a series of JS strings without breaking apart multi-byte +// characters. +exports.StringDecoder = StringDecoder; +function StringDecoder(encoding) { + this.encoding = normalizeEncoding(encoding); + var nb; + switch (this.encoding) { + case 'utf16le': + this.text = utf16Text; + this.end = utf16End; + nb = 4; + break; + case 'utf8': + this.fillLast = utf8FillLast; + nb = 4; + break; + case 'base64': + this.text = base64Text; + this.end = base64End; + nb = 3; + break; + default: + this.write = simpleWrite; + this.end = simpleEnd; + return; + } + this.lastNeed = 0; + this.lastTotal = 0; + this.lastChar = Buffer.allocUnsafe(nb); +} + +StringDecoder.prototype.write = function (buf) { + if (buf.length === 0) return ''; + var r; + var i; + if (this.lastNeed) { + r = this.fillLast(buf); + if (r === undefined) return ''; + i = this.lastNeed; + this.lastNeed = 0; + } else { + i = 0; + } + if (i < buf.length) return r ? r + this.text(buf, i) : this.text(buf, i); + return r || ''; +}; + +StringDecoder.prototype.end = utf8End; + +// Returns only complete characters in a Buffer +StringDecoder.prototype.text = utf8Text; + +// Attempts to complete a partial non-UTF-8 character using bytes from a Buffer +StringDecoder.prototype.fillLast = function (buf) { + if (this.lastNeed <= buf.length) { + buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, this.lastNeed); + return this.lastChar.toString(this.encoding, 0, this.lastTotal); + } + buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, buf.length); + this.lastNeed -= buf.length; +}; + +// Checks the type of a UTF-8 byte, whether it's ASCII, a leading byte, or a +// continuation byte. If an invalid byte is detected, -2 is returned. +function utf8CheckByte(byte) { + if (byte <= 0x7F) return 0;else if (byte >> 5 === 0x06) return 2;else if (byte >> 4 === 0x0E) return 3;else if (byte >> 3 === 0x1E) return 4; + return byte >> 6 === 0x02 ? -1 : -2; +} + +// Checks at most 3 bytes at the end of a Buffer in order to detect an +// incomplete multi-byte UTF-8 character. The total number of bytes (2, 3, or 4) +// needed to complete the UTF-8 character (if applicable) are returned. +function utf8CheckIncomplete(self, buf, i) { + var j = buf.length - 1; + if (j < i) return 0; + var nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) self.lastNeed = nb - 1; + return nb; + } + if (--j < i || nb === -2) return 0; + nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) self.lastNeed = nb - 2; + return nb; + } + if (--j < i || nb === -2) return 0; + nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) { + if (nb === 2) nb = 0;else self.lastNeed = nb - 3; + } + return nb; + } + return 0; +} + +// Validates as many continuation bytes for a multi-byte UTF-8 character as +// needed or are available. If we see a non-continuation byte where we expect +// one, we "replace" the validated continuation bytes we've seen so far with +// a single UTF-8 replacement character ('\ufffd'), to match v8's UTF-8 decoding +// behavior. The continuation byte check is included three times in the case +// where all of the continuation bytes for a character exist in the same buffer. +// It is also done this way as a slight performance increase instead of using a +// loop. +function utf8CheckExtraBytes(self, buf, p) { + if ((buf[0] & 0xC0) !== 0x80) { + self.lastNeed = 0; + return '\ufffd'; + } + if (self.lastNeed > 1 && buf.length > 1) { + if ((buf[1] & 0xC0) !== 0x80) { + self.lastNeed = 1; + return '\ufffd'; + } + if (self.lastNeed > 2 && buf.length > 2) { + if ((buf[2] & 0xC0) !== 0x80) { + self.lastNeed = 2; + return '\ufffd'; + } + } + } +} + +// Attempts to complete a multi-byte UTF-8 character using bytes from a Buffer. +function utf8FillLast(buf) { + var p = this.lastTotal - this.lastNeed; + var r = utf8CheckExtraBytes(this, buf, p); + if (r !== undefined) return r; + if (this.lastNeed <= buf.length) { + buf.copy(this.lastChar, p, 0, this.lastNeed); + return this.lastChar.toString(this.encoding, 0, this.lastTotal); + } + buf.copy(this.lastChar, p, 0, buf.length); + this.lastNeed -= buf.length; +} + +// Returns all complete UTF-8 characters in a Buffer. If the Buffer ended on a +// partial character, the character's bytes are buffered until the required +// number of bytes are available. +function utf8Text(buf, i) { + var total = utf8CheckIncomplete(this, buf, i); + if (!this.lastNeed) return buf.toString('utf8', i); + this.lastTotal = total; + var end = buf.length - (total - this.lastNeed); + buf.copy(this.lastChar, 0, end); + return buf.toString('utf8', i, end); +} + +// For UTF-8, a replacement character is added when ending on a partial +// character. +function utf8End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) return r + '\ufffd'; + return r; +} + +// UTF-16LE typically needs two bytes per character, but even if we have an even +// number of bytes available, we need to check if we end on a leading/high +// surrogate. In that case, we need to wait for the next two bytes in order to +// decode the last character properly. +function utf16Text(buf, i) { + if ((buf.length - i) % 2 === 0) { + var r = buf.toString('utf16le', i); + if (r) { + var c = r.charCodeAt(r.length - 1); + if (c >= 0xD800 && c <= 0xDBFF) { + this.lastNeed = 2; + this.lastTotal = 4; + this.lastChar[0] = buf[buf.length - 2]; + this.lastChar[1] = buf[buf.length - 1]; + return r.slice(0, -1); + } + } + return r; + } + this.lastNeed = 1; + this.lastTotal = 2; + this.lastChar[0] = buf[buf.length - 1]; + return buf.toString('utf16le', i, buf.length - 1); +} + +// For UTF-16LE we do not explicitly append special replacement characters if we +// end on a partial character, we simply let v8 handle that. +function utf16End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) { + var end = this.lastTotal - this.lastNeed; + return r + this.lastChar.toString('utf16le', 0, end); + } + return r; +} + +function base64Text(buf, i) { + var n = (buf.length - i) % 3; + if (n === 0) return buf.toString('base64', i); + this.lastNeed = 3 - n; + this.lastTotal = 3; + if (n === 1) { + this.lastChar[0] = buf[buf.length - 1]; + } else { + this.lastChar[0] = buf[buf.length - 2]; + this.lastChar[1] = buf[buf.length - 1]; + } + return buf.toString('base64', i, buf.length - n); +} + +function base64End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) return r + this.lastChar.toString('base64', 0, 3 - this.lastNeed); + return r; +} + +// Pass bytes on through for single-byte encodings (e.g. ascii, latin1, hex) +function simpleWrite(buf) { + return buf.toString(this.encoding); +} + +function simpleEnd(buf) { + return buf && buf.length ? this.write(buf) : ''; +} +},{"safe-buffer":27}],29:[function(require,module,exports){ +module.exports = require('./readable').PassThrough + +},{"./readable":30}],30:[function(require,module,exports){ +exports = module.exports = require('./lib/_stream_readable.js'); +exports.Stream = exports; +exports.Readable = exports; +exports.Writable = require('./lib/_stream_writable.js'); +exports.Duplex = require('./lib/_stream_duplex.js'); +exports.Transform = require('./lib/_stream_transform.js'); +exports.PassThrough = require('./lib/_stream_passthrough.js'); + +},{"./lib/_stream_duplex.js":19,"./lib/_stream_passthrough.js":20,"./lib/_stream_readable.js":21,"./lib/_stream_transform.js":22,"./lib/_stream_writable.js":23}],31:[function(require,module,exports){ +module.exports = require('./readable').Transform + +},{"./readable":30}],32:[function(require,module,exports){ +module.exports = require('./lib/_stream_writable.js'); + +},{"./lib/_stream_writable.js":23}],33:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +module.exports = Stream; + +var EE = require('events').EventEmitter; +var inherits = require('inherits'); + +inherits(Stream, EE); +Stream.Readable = require('readable-stream/readable.js'); +Stream.Writable = require('readable-stream/writable.js'); +Stream.Duplex = require('readable-stream/duplex.js'); +Stream.Transform = require('readable-stream/transform.js'); +Stream.PassThrough = require('readable-stream/passthrough.js'); + +// Backwards-compat with node 0.4.x +Stream.Stream = Stream; + + + +// old-style streams. Note that the pipe method (the only relevant +// part of this class) is overridden in the Readable class. + +function Stream() { + EE.call(this); +} + +Stream.prototype.pipe = function(dest, options) { + var source = this; + + function ondata(chunk) { + if (dest.writable) { + if (false === dest.write(chunk) && source.pause) { + source.pause(); + } + } + } + + source.on('data', ondata); + + function ondrain() { + if (source.readable && source.resume) { + source.resume(); + } + } + + dest.on('drain', ondrain); + + // If the 'end' option is not supplied, dest.end() will be called when + // source gets the 'end' or 'close' events. Only dest.end() once. + if (!dest._isStdio && (!options || options.end !== false)) { + source.on('end', onend); + source.on('close', onclose); + } + + var didOnEnd = false; + function onend() { + if (didOnEnd) return; + didOnEnd = true; + + dest.end(); + } + + + function onclose() { + if (didOnEnd) return; + didOnEnd = true; + + if (typeof dest.destroy === 'function') dest.destroy(); + } + + // don't leave dangling pipes when there are errors. + function onerror(er) { + cleanup(); + if (EE.listenerCount(this, 'error') === 0) { + throw er; // Unhandled stream error in pipe. + } + } + + source.on('error', onerror); + dest.on('error', onerror); + + // remove all the event listeners that were added. + function cleanup() { + source.removeListener('data', ondata); + dest.removeListener('drain', ondrain); + + source.removeListener('end', onend); + source.removeListener('close', onclose); + + source.removeListener('error', onerror); + dest.removeListener('error', onerror); + + source.removeListener('end', cleanup); + source.removeListener('close', cleanup); + + dest.removeListener('close', cleanup); + } + + source.on('end', cleanup); + source.on('close', cleanup); + + dest.on('close', cleanup); + + dest.emit('pipe', source); + + // Allow for unix-like usage: A.pipe(B).pipe(C) + return dest; +}; + +},{"events":10,"inherits":13,"readable-stream/duplex.js":18,"readable-stream/passthrough.js":29,"readable-stream/readable.js":30,"readable-stream/transform.js":31,"readable-stream/writable.js":32}],34:[function(require,module,exports){ +(function (Buffer){ +var _ = {}; + +// These functions approximately reproduce the (pre-node 10) noAssert functionality, +// which allowed reading/writing past the end of a buffer, but 0-padding/ignoring +// any extra content. + +function truncatedReadUInt32BE(buffer, offset) { + var availableBytes = buffer.length - offset; + + if (availableBytes >= 4) { + return buffer.readUInt32BE(offset); + } else if (availableBytes === 3) { + var first = buffer.readUInt16BE(offset); + var second = buffer.readUInt8(offset + 2); + return ((first << 8) + second) << 8 >>> 0; + } else if (availableBytes === 2) { + return buffer.readUInt16BE(offset) << 16 >>> 0; + } else if (availableBytes === 1) { + return buffer.readUInt8(offset) << 24 >>> 0; + } else if (availableBytes <= 0) { + return 0x0; + } +} + +function truncatedWriteUInt32BE(buffer, offset, data) { + var availableBytes = buffer.length - offset; + + if (availableBytes >= 4) { + buffer.writeUInt32BE(data, offset); + } else if (availableBytes === 3) { + buffer.writeUInt16BE(data >>> 16, offset); + buffer.writeUInt8((data >>> 8) & 0xff, offset + 2); + } else if (availableBytes === 2) { + buffer.writeUInt16BE(data >>> 16, offset); + } else if (availableBytes === 1) { + buffer.writeUInt8(data >>> 24, offset); + } +} + +// new Buffer() is deprecated in recent node. This ensures +// we always use the correct method for the current node. +function newBuffer(size) { + if (Buffer.alloc) { + return Buffer.alloc(size); + } else { + return new Buffer(size); + } +} + +function extend(obj) { + Array.prototype.slice.call(arguments, 1).forEach(function (ext) { + Object.keys(ext).forEach(function (key) { + obj[key] = ext[key]; + }); + }); + return obj; +} + +function addField(ctr, f) { + if ('width' in f) { + ctr.bits = (ctr.bits || 0) + f.width; + while (ctr.bits > 7) { + ctr.bytes += 1; + ctr.bits -= 8; + } + } else if (!ctr.bits) { + ctr.bytes += f.size; + } else { + throw Error("Improperly aligned bitfield before field: "+f.name); + } + return ctr; +} + +function arrayizeField(f, count) { + var f2 = (typeof count === 'number') ? extend({ + name: f.name, + field: f, + valueFromBytes: function (buf, off) { + off || (off = {bytes:0, bits:0}); + var arr = new Array(count); + for (var idx = 0, len = arr.length; idx < len; idx += 1) { + arr[idx] = f.valueFromBytes(buf, off); + } + return arr; + }, + bytesFromValue: function (arr, buf, off) { + arr || (arr = new Array(count)); + buf || (buf = newBuffer(this.size)); + off || (off = {bytes:0, bits:0}); + for (var idx = 0, len = Math.min(arr.length, count); idx < len; idx += 1) { + f.bytesFromValue(arr[idx], buf, off); + } + while (idx++ < count) addField(off, f); + return buf; + } + }, ('width' in f) ? {width: f.width * count} : {size: f.size * count}) : f; + f2.pack = f2.bytesFromValue; + f2.unpack = f2.valueFromBytes; + return f2; +} + +_.struct = function (name, fields, count) { + if (typeof name !== 'string') { + count = fields; + fields = name; + name = null; + } + + var _size = {bytes:0, bits:0}, + _padsById = Object.create(null), + fieldsObj = fields.reduce(function (obj, f, i) { + if ('_padTo' in f) { + // HACK: we really should just make local copy of *all* fields + f._id || (f._id = 'id'+Math.random().toFixed(20).slice(2)); // WORKAROUND: https://github.com/tessel/runtime/issues/716 + var _f = _padsById[f._id] = (_size.bits) ? { + width: 8*(f._padTo - _size.bytes) - _size.bits + } : { + size: f._padTo - _size.bytes + }; + if (_f.width < 0 || _f.size < 0) { + var xtraMsg = (_size.bits) ? (" and "+_size.bits+" bits") : ''; + throw Error("Invalid .padTo("+f._padTo+") field, struct is already "+_size.bytes+" byte(s)"+xtraMsg+"!"); + } + f = _f; + } + else if (f._hoistFields) Object.keys(f._hoistFields).forEach(function (name) { + var _f = Object.create(f._hoistFields[name]); + if ('width' in _f) _f.offset = {bytes:_f.offset.bytes+_size.bytes, bits:_f.offset.bits}; + else _f.offset += _size.bytes; + obj[name] = _f; + }); + else if (f.name) { + f = Object.create(f); // local overrides + f.offset = ('width' in f) ? {bytes:_size.bytes,bits:_size.bits} : _size.bytes, + obj[f.name] = f; + } + addField(_size, f); + return obj; + }, {}); + if (_size.bits) throw Error("Improperly aligned bitfield at end of struct: "+name); + + return arrayizeField({ + valueFromBytes: function (buf, off) { + off || (off = {bytes:0, bits:0}); + var obj = new Object(); + fields.forEach(function (f) { + if ('_padTo' in f) return addField(off, _padsById[f._id]); + + var value = f.valueFromBytes(buf, off); + if (f.name) obj[f.name] = value; + else if (typeof value === 'object') extend(obj, value); + }); + return obj; + }, + bytesFromValue: function (obj, buf, off) { + obj || (obj = {}); + buf || (buf = newBuffer(this.size)); + off || (off = {bytes:0, bits:0}); + fields.forEach(function (f) { + if ('_padTo' in f) return addField(off, _padsById[f._id]); + + var value = (f.name) ? obj[f.name] : obj; + f.bytesFromValue(value, buf, off); + }); + return buf; + }, + _hoistFields: (!name) ? fieldsObj : null, + fields: fieldsObj, + size: _size.bytes, + name: name + }, count); +}; + +_.padTo = function (off) { + return {_padTo:off}; +}; + + +// NOTE: bitfields must be embedded in a struct (C/C++ share this limitation) + +var FULL = 0xFFFFFFFF; +function bitfield(name, width, count) { + width || (width = 1); + // NOTE: width limitation is so all values will align *within* a 4-byte word + if (width > 24) throw Error("Bitfields support a maximum width of 24 bits."); + var impl = this, + mask = FULL >>> (32 - width); + return arrayizeField({ + valueFromBytes: function (buf, off) { + off || (off = {bytes:0, bits:0}); + var end = (off.bits || 0) + width, + word = truncatedReadUInt32BE(buf, off.bytes) || 0, + over = word >>> (32 - end); + addField(off, this); + return impl.b2v.call(this, over & mask); + }, + bytesFromValue: function (val, buf, off) { + val = impl.v2b.call(this, val || 0); + off || (off = {bytes:0, bits:0}); + var end = (off.bits || 0) + width, + word = truncatedReadUInt32BE(buf, off.bytes) || 0, + zero = mask << (32 - end), + over = (val & mask) << (32 - end); + word &= ~zero; + word |= over; + word >>>= 0; // WORKAROUND: https://github.com/tessel/runtime/issues/644 + truncatedWriteUInt32BE(buf, off.bytes, word); + addField(off, this); + return buf; + }, + width: width, + name: name + }, count); +} + +function swapBits(n, w) { + var o = 0; + while (w--) { + o <<= 1; + o |= n & 1; + n >>>= 1; + } + return o; +} + + +_.bool = function (name, count) { + return bitfield.call({ + b2v: function (b) { return Boolean(b); }, + v2b: function (v) { return (v) ? FULL : 0; } + }, name, 1, count); + +}; +_.ubit = bitfield.bind({ + b2v: function (b) { return b; }, + v2b: function (v) { return v; } +}); +_.ubitLE = bitfield.bind({ + b2v: function (b) { return swapBits(b, this.width); }, + v2b: function (v) { return swapBits(v, this.width); } +}); +_.sbit = bitfield.bind({ // TODO: handle sign bit… + b2v: function (b) { + var m = 1 << (this.width-1), + s = b & m; + return (s) ? -(b &= ~m) : b; + }, + v2b: function (v) { + var m = 1 << (this.width-1), + s = (v < 0); + return (s) ? (-v | m) : v; + } +}); + + +function bytefield(name, size, count) { + if (typeof name !== 'string') { + count = size; + size = name; + name = null; + } + size = (typeof size === 'number') ? size : 1; + var impl = this; + return arrayizeField({ + valueFromBytes: function (buf, off) { + off || (off = {bytes:0, bits:0}); + var val = buf.slice(off.bytes, off.bytes+this.size); + addField(off, this); + return impl.b2v.call(this, val); + }, + bytesFromValue: function (val, buf, off) { + off || (off = {bytes:0}); + buf || (buf = newBuffer(this.size)); + var blk = buf.slice(off.bytes, off.bytes+this.size), + len = impl.vTb.call(this, val, blk); + if (len < blk.length) blk.fill(0, len); + addField(off, this); + return buf; + }, + size: size, + name: name + }, count); +} + +// http://stackoverflow.com/a/7460958/72637 +function swapBytesPairs(fromBuffer, toBuffer) { + toBuffer = toBuffer || fromBuffer + var l = fromBuffer.length; + for (var i = 1; i < l; i += 2) { + var a = fromBuffer[i - 1]; + toBuffer[i - 1] = fromBuffer[i]; + toBuffer[i] = a; + } + return toBuffer +} + +_.byte = bytefield.bind({ + b2v: function (b) { return b; }, + vTb: function (v,b) { if (!v) return 0; v.copy(b); return v.length; } +}); + +_.char = bytefield.bind({ + b2v: function (b) { + var v = b.toString('utf8'), + z = v.indexOf('\0'); + return (~z) ? v.slice(0, z) : v; + }, + vTb: function (v,b) { + v || (v = ''); + return b.write(v, 'utf8'); + } +}); + +_.char16le = bytefield.bind({ + b2v: function (b) { + var v = b.toString('utf16le'), + z = v.indexOf('\0'); + return (~z) ? v.slice(0, z) : v; + }, + vTb: function (v,b) { + v || (v = ''); + return b.write(v, 'utf16le'); + } +}); + +_.char16be = bytefield.bind({ + b2v: function (b) { + var temp = newBuffer(b.length); + swapBytesPairs(b, temp); + var v = temp.toString('utf16le'), + z = v.indexOf('\0'); + return (~z) ? v.slice(0, z) : v; + }, + vTb: function (v,b) { + v || (v = ''); + var len = b.write(v, 'utf16le'); + swapBytesPairs(b) + return len; + } +}); + +function standardField(sig, size) { + var read = 'read'+sig, + dump = 'write'+sig; + size || (size = +sig.match(/\d+/)[0] >> 3); + return function (name, count) { + if (typeof name !== 'string') { + count = name; + name = null; + } + return arrayizeField({ + valueFromBytes: function (buf, off) { + off || (off = {bytes:0}); + var val = buf[read](off.bytes); + addField(off, this); + return val; + }, + bytesFromValue: function (val, buf, off) { + val || (val = 0); + buf || (buf = newBuffer(this.size)); + off || (off = {bytes:0}); + buf[dump](val, off.bytes); + addField(off, this); + return buf; + }, + size: size, + name: name + }, count); + }; +} + +_.float32 = standardField('FloatBE',4); +_.float64 = standardField('DoubleBE',8); +_.float32le = standardField('FloatLE',4); +_.float64le = standardField('DoubleLE',8); + +_.uint8 = standardField('UInt8'); +_.uint16 = standardField('UInt16BE'); +_.uint32 = standardField('UInt32BE'); +_.uint16le = standardField('UInt16LE'); +_.uint32le = standardField('UInt32LE'); + +_.int8 = standardField('Int8'); +_.int16 = standardField('Int16BE'); +_.int32 = standardField('Int32BE'); +_.int16le = standardField('Int16LE'); +_.int32le = standardField('Int32LE'); + + +_.derive = function (orig, pack, unpack) { + return function (name, count) { + if (typeof name !== 'string') { + count = name; + name = null; + } + return arrayizeField(extend({ + valueFromBytes: function (buf, off) { + return unpack(orig.valueFromBytes(buf, off)); + }, + bytesFromValue: function (val, buf, off) { + return orig.bytesFromValue(pack(val), buf, off); + }, + name: name + }, ('width' in orig) ? {width:orig.width} : {size:orig.size}), count); + } +}; + +module.exports = _; + +}).call(this,require("buffer").Buffer) +},{"buffer":8}],35:[function(require,module,exports){ +(function (setImmediate,clearImmediate){ +var nextTick = require('process/browser.js').nextTick; +var apply = Function.prototype.apply; +var slice = Array.prototype.slice; +var immediateIds = {}; +var nextImmediateId = 0; + +// DOM APIs, for completeness + +exports.setTimeout = function() { + return new Timeout(apply.call(setTimeout, window, arguments), clearTimeout); +}; +exports.setInterval = function() { + return new Timeout(apply.call(setInterval, window, arguments), clearInterval); +}; +exports.clearTimeout = +exports.clearInterval = function(timeout) { timeout.close(); }; + +function Timeout(id, clearFn) { + this._id = id; + this._clearFn = clearFn; +} +Timeout.prototype.unref = Timeout.prototype.ref = function() {}; +Timeout.prototype.close = function() { + this._clearFn.call(window, this._id); +}; + +// Does not start the time, just sets up the members needed. +exports.enroll = function(item, msecs) { + clearTimeout(item._idleTimeoutId); + item._idleTimeout = msecs; +}; + +exports.unenroll = function(item) { + clearTimeout(item._idleTimeoutId); + item._idleTimeout = -1; +}; + +exports._unrefActive = exports.active = function(item) { + clearTimeout(item._idleTimeoutId); + + var msecs = item._idleTimeout; + if (msecs >= 0) { + item._idleTimeoutId = setTimeout(function onTimeout() { + if (item._onTimeout) + item._onTimeout(); + }, msecs); + } +}; + +// That's not how node.js implements it but the exposed api is the same. +exports.setImmediate = typeof setImmediate === "function" ? setImmediate : function(fn) { + var id = nextImmediateId++; + var args = arguments.length < 2 ? false : slice.call(arguments, 1); + + immediateIds[id] = true; + + nextTick(function onNextTick() { + if (immediateIds[id]) { + // fn.call() is faster so we optimize for the common use-case + // @see http://jsperf.com/call-apply-segu + if (args) { + fn.apply(null, args); + } else { + fn.call(null); + } + // Prevent ids from leaking + exports.clearImmediate(id); + } + }); + + return id; +}; + +exports.clearImmediate = typeof clearImmediate === "function" ? clearImmediate : function(id) { + delete immediateIds[id]; +}; +}).call(this,require("timers").setImmediate,require("timers").clearImmediate) +},{"process/browser.js":17,"timers":35}],36:[function(require,module,exports){ +(function (global){ + +/** + * Module exports. + */ + +module.exports = deprecate; + +/** + * Mark that a method should not be used. + * Returns a modified function which warns once by default. + * + * If `localStorage.noDeprecation = true` is set, then it is a no-op. + * + * If `localStorage.throwDeprecation = true` is set, then deprecated functions + * will throw an Error when invoked. + * + * If `localStorage.traceDeprecation = true` is set, then deprecated functions + * will invoke `console.trace()` instead of `console.error()`. + * + * @param {Function} fn - the function to deprecate + * @param {String} msg - the string to print to the console when `fn` is invoked + * @returns {Function} a new "deprecated" version of `fn` + * @api public + */ + +function deprecate (fn, msg) { + if (config('noDeprecation')) { + return fn; + } + + var warned = false; + function deprecated() { + if (!warned) { + if (config('throwDeprecation')) { + throw new Error(msg); + } else if (config('traceDeprecation')) { + console.trace(msg); + } else { + console.warn(msg); + } + warned = true; + } + return fn.apply(this, arguments); + } + + return deprecated; +} + +/** + * Checks `localStorage` for boolean values for the given `name`. + * + * @param {String} name + * @returns {Boolean} + * @api private + */ + +function config (name) { + // accessing global.localStorage can trigger a DOMException in sandboxed iframes + try { + if (!global.localStorage) return false; + } catch (_) { + return false; + } + var val = global.localStorage[name]; + if (null == val) return false; + return String(val).toLowerCase() === 'true'; +} + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],37:[function(require,module,exports){ +module.exports = function (obj) { + Array.prototype.slice.call(arguments, 1).forEach(function (ext) { + if (ext) Object.keys(ext).forEach(function (key) { + obj[key] = ext[key]; + }); + }); + return obj; +}; +},{}],38:[function(require,module,exports){ +// see http://staff.washington.edu/dittrich/misc/fatgen103.pdf +// and http://www.cse.scu.edu/~tschwarz/COEN252_09/Lectures/FAT.html + +var _ = require('struct-fu'), + __ = require("./helpers.js"); + +var bootBase = _.struct([ + _.byte('jmpBoot', 3), + _.char('OEMName', 8), + _.uint16le('BytsPerSec'), + _.uint8('SecPerClus'), + _.uint16le('ResvdSecCnt'), // Rsvd in table, but Resvd in calcs… + _.uint8('NumFATs'), + _.uint16le('RootEntCnt'), + _.uint16le('TotSec16'), + _.uint8('Media'), + _.uint16le('FATSz16'), + _.uint16le('SecPerTrk'), + _.uint16le('NumHeads'), + _.uint32le('HiddSec'), + _.uint32le('TotSec32') +]); + +var bootInfo = _.struct([ + _.uint8('DrvNum'), + _.uint8('Reserved1'), + _.uint8('BootSig'), + _.uint32le('VolID'), + _.char('VolLab', 11), + _.char('FilSysType', 8) +]); + +exports.boot16 = _.struct([ + bootBase, + bootInfo +]); + +exports.boot32 = _.struct([ + bootBase, + _.uint32le('FATSz32'), + _.struct('ExtFlags', [ + _.ubit('NumActiveFAT', 4), + _.ubit('_reserved1', 3), + _.bool('MirroredFAT'), + _.ubit('_reserved2', 8) + ].reverse()), + _.struct('FSVer', [ + _.uint8('Major'), + _.uint8('Minor') + ]), + _.uint32le('RootClus'), + _.uint16le('FSInfo'), + _.uint16le('BkBootSec'), + _.byte('Reserved', 12), + bootInfo +]); + + +var _time = _.struct([ + _.ubit('hours',5), + _.ubit('minutes',6), + _.ubit('seconds_2',5) +]), time = { + valueFromBytes: function (buf, off) { + off || (off = {bytes:0}); + + var _buf = __.bufferFrom([buf[off.bytes+1], buf[off.bytes+0]]), + val = _time.valueFromBytes(_buf); + off.bytes += this.size; + return val; + }, + bytesFromValue: function (val, buf, off) { + val || (val = {hours:0, minutes:0, seconds_2:0}); + buf || (buf = __.allocBuffer(this.size)); + off || (off = {bytes:0}); + + var _buf = _time.bytesFromValue(val); + buf[off.bytes+1] = _buf[0]; + buf[off.bytes+0] = _buf[1]; + off.bytes += this.size; + return buf; + }, + size: _time.size +}; + +var _date = _.struct([ + _.ubit('year',7), + _.ubit('month',4), + _.ubit('day',5) +]), date = { + valueFromBytes: function (buf, off) { + off || (off = {bytes:0}); + + var _buf = __.bufferFrom([buf[off.bytes+1], buf[off.bytes+0]]), + val = _date.valueFromBytes(_buf); + off.bytes += this.size; + return val; + }, + bytesFromValue: function (val, buf, off) { + val || (val = {year:0, month:0, day:0}); + buf || (buf = __.allocBuffer(this.size)); + off || (off = {bytes:0}); + + var _buf = _date.bytesFromValue(val); + buf[off.bytes+1] = _buf[0]; + buf[off.bytes+0] = _buf[1]; + off.bytes += this.size; + return buf; + }, + size: _date.size +}; + +exports.dirEntry = _.struct([ + _.struct('Name', [ + _.char('filename',8), + _.char('extension',3) + ]), + _.struct('Attr', [ + _.bool('readonly'), + _.bool('hidden'), + _.bool('system'), + _.bool('volume_id'), + _.bool('directory'), + _.bool('archive'), + _.ubit('reserved', 2) + ].reverse()), + _.byte('NTRes', 1), + _.uint8('CrtTimeTenth'), + _.struct('CrtTime', [time]), + _.struct('CrtDate', [date]), + _.struct('LstAccDate', [date]), + _.uint16le('FstClusHI'), + _.struct('WrtTime', [time]), + _.struct('WrtDate', [date]), + _.uint16le('FstClusLO'), + _.uint32le('FileSize') +]); +exports.entryDoneFlag = 0x00; +exports.entryFreeFlag = 0xE5; +exports.entryIsE5Flag = 0x05; + +exports.dirEntry_simple = _.struct([ + _.struct('Name', [ + _.char('filename',8), + _.char('extension',3) + ]), + _.padTo(exports.dirEntry.size) + /* + _.uint8('Attr_raw'), + _.byte('NTRes', 1), + _.byte('Crt_raw', 1+2+2), + _.byte('Lst_raw', 2), + _.uint16le('FstClusHI'), + _.byte('Wrt_raw', 2+2), + _.uint16le('FstClusLO'), + _.uint32le('FileSize') + */ +]); + + +exports.lastLongFlag = 0x40; +exports.longDirFlag = 0x0F; +exports.longDirEntry = _.struct([ + _.uint8('Ord'), + _.char16le('Name1', 10), + _.uint8('Attr_raw'), + _.uint8('Type'), + _.uint8('Chksum'), + _.char16le('Name2', 12), + _.uint16le('FstClusLO'), + _.char16le('Name3', 4) +]); + +if (exports.longDirEntry.size !== exports.dirEntry.size) throw Error("Structs ain't right!"); + +exports.fatField = { + 'fat12': _.struct('Status', [ + _.ubit('field0bc', 8), + _.ubit('field1c', 4), + _.ubit('field0a', 4), + _.ubit('field1ab', 8), + ]), + 'fat16': _.uint16le('Status'), + 'fat32': _.uint32le('Status') // more properly this 4 bits reserved + uint28le +}; + +exports.fatPrefix = { + 'fat12': 0xF00, + 'fat16': 0xFF00, + 'fat32': 0x0FFFFF00 +}; + +exports.fatStat = { + free: 0x00, + _undef: 0x01, + rsvMin: 0xF0, + bad: 0xF7, + eofMin: 0xF8, + eof: 0xFF +}; + +exports._I = { + RUSR: 0400, + WUSR: 0200, + XUSR: 0100, + + RGRP: 0040, + WGRP: 0020, + XGRP: 0010, + + ROTH: 0004, + WOTH: 0002, + XOTH: 0001, + + SUID: 04000, + SGID: 02000, + SVTX: 01000, + + FDIR: 040000, + FREG: 0100000, +}; + +exports._I.RWXU = exports._I.RUSR | exports._I.WUSR | exports._I.XUSR; +exports._I.RWXG = exports._I.RGRP | exports._I.WGRP | exports._I.XGRP; +exports._I.RWXO = exports._I.ROTH | exports._I.WOTH | exports._I.XOTH; +exports._I._sss = exports._I.SUID | exports._I.SGID | exports._I.SVTX; +exports._I._chmoddable = exports._I.RWXU | exports._I.RWXG | exports._I.RWXO | exports._I._sss; + +var _errors = { + IO: "Input/output error", + NOENT: "No such file or directory", + INVAL: "Invalid argument", + EXIST: "File exists", + NAMETOOLONG: "Filename too long", + NOSPC: "No space left on device", + NOSYS: "Function not supported", + ROFS: "ROFLCopter file system", + NOTDIR: "Not a directory", + BADF: "Bad file descriptor", + EXIST: "File exists", + ISDIR: "Is a directory", + ACCES: "Permission denied", + NOSYS: "Function not implemented", + _TODO: "Not implemented yet!" +}; + +exports.err = {}; +Object.keys(_errors).forEach(function (sym) { + var msg = _errors[sym]; + exports.err[sym] = function () { + var e = new Error(msg); + e.code = sym; + return e; + }; +}); + +},{"./helpers.js":4,"struct-fu":34}],39:[function(require,module,exports){ +var S = require("./structs.js"), + c = require("./chains.js"), + $ = require("./cache.js"), + _ = require("./helpers.js"); + +exports.init = function (volume, opts, bootSector) { + if (bootSector[510] !== 0x55 || bootSector[511] !== 0xAA) throw Error("Invalid volume signature!"); + + var isFAT16 = bootSector.readUInt16LE(S.boot16.fields['FATSz16'].offset), + bootStruct = (isFAT16) ? S.boot16 : S.boot32, + BS = bootStruct.valueFromBytes(bootSector); + _.log(_.log.DBG, "Boot sector info:", BS); + bootSector = null; // allow GC + if (!BS.BytsPerSec) throw Error("This looks like an ExFAT volume! (unsupported)"); + else if (BS.BytsPerSec !== volume.sectorSize) throw Error("Sector size mismatch with FAT table."); + + var FATSz = (isFAT16) ? BS.FATSz16 : BS.FATSz32, + rootDirSectors = Math.ceil((BS.RootEntCnt * 32) / BS.BytsPerSec), + firstDataSector = BS.ResvdSecCnt + (BS.NumFATs * FATSz) + rootDirSectors, + totSec = (BS.TotSec16) ? BS.TotSec16 : BS.TotSec32, + dataSec = totSec - firstDataSector, + countofClusters = Math.floor(dataSec / BS.SecPerClus); + // avoid corrupting sectors from other partitions or whatnot + if (totSec > volume.numSectors) throw Error("Volume size mismatch!"); + + var fatType; + if (countofClusters < 4085) { + fatType = 'fat12'; + } else if (countofClusters < 65525) { + fatType = 'fat16'; + } else { + fatType = 'fat32'; + } + + _.log(_.log.DBG, "rootDirSectors", rootDirSectors, "firstDataSector", firstDataSector, "countofClusters", countofClusters, "=>", fatType); + + var vol = {}; + + vol.opts = opts; + + vol._sectorSize = BS.BytsPerSec; + vol._sectorsPerCluster = BS.SecPerClus; + vol._firstSectorOfCluster = function (n) { + return firstDataSector + (n-2)*vol._sectorsPerCluster; + }; + + vol._makeCache = function () { + return $.wrapDriver(volume); + }; + + vol._readSectors = function (cache, secNum, dest, cb) { + if (typeof dest === 'function') { + cb = dest; + dest = _.allocBuffer(vol._sectorSize); + } + _.log(_.log.DBG, "vol._readSectors", secNum, dest.length); + if (secNum < volume.numSectors) cache.readSectors(secNum, dest, function (e) { cb(e, dest); }); + else throw Error("Invalid sector number!"); + }; + + vol._writeSectors = function (cache, secNum, data, cb) { + _.log(_.log.DBG, "vol._writeSectors", secNum, data.length); + // NOTE: these are internal assertions, public API will get proper `S.err`s + if (data.length % volume.sectorSize) throw Error("Buffer length not a multiple of sector size"); + else if (opts.ro) throw Error("Read-only filesystem"); + else if (secNum < volume.numSectors) cache.writeSectors(secNum, data, cb); + else throw Error("Invalid sector number!"); + }; + + function fatInfoForCluster(n) { + var entryStruct = S.fatField[fatType], + FATOffset = (fatType === 'fat12') ? Math.floor(n/2) * entryStruct.size : n * entryStruct.size, + SecNum = BS.ResvdSecCnt + Math.floor(FATOffset / BS.BytsPerSec); + EntOffset = FATOffset % BS.BytsPerSec; + return {sector:SecNum-BS.ResvdSecCnt, offset:EntOffset, struct:entryStruct}; + } + + // TODO: all this FAT manipulation is crazy inefficient! needs read caching *and* write caching + // …the best place for cache might be in `volume` handler, though. add a `flush` method to that spec? + // TODO: how should we handle redundant FATs? mirror every write? just ignore completely? copy-on-eject? + + var fatChain = c.sectorChain(vol, BS.ResvdSecCnt, FATSz); + fatChain.cacheAdvice = 'RANDOM'; + + vol.fetchFromFAT = function (clusterNum, cb) { + var info = fatInfoForCluster(clusterNum); + fatChain.readFromPosition(info, info.struct.size, function (e,n,d) { + if (e) return cb(e); + var status = info.struct.valueFromBytes(d), prefix; + if (fatType === 'fat12') { + if (clusterNum % 2) { + status = (status.field1ab << 4) + status.field1c; + } else { + status = (status.field0a << 8) + status.field0bc; + } + } + else if (fatType === 'fat32') { + status &= 0x0FFFFFFF; + } + + var prefix = S.fatPrefix[fatType]; + if (status === S.fatStat.free) cb(null, 'free'); + else if (status === S.fatStat._undef) cb(null, '-invalid-'); + else if (status > prefix+S.fatStat.eofMin) cb(null, 'eof'); + else if (status === prefix+S.fatStat.bad) cb(null, 'bad'); + else if (status > prefix+S.fatStat.rsvMin) cb(null, 'reserved'); + else cb(null, status); + }); + }; + + vol.storeToFAT = function (clusterNum, status, cb) { + if (typeof status === 'string') { + status = S.fatStat[status]; + status += S.fatPrefix[fatType]; + } + var info = fatInfoForCluster(clusterNum); + // TODO: technically fat32 needs to *preserve* the high 4 bits + if (fatType === 'fat12') fatChain.readFromPosition(info, info.struct.size, function (e,n,d) { + var value = info.struct.valueFromBytes(d); + if (clusterNum % 2) { + value.field1ab = status >>> 4; + value.field1c = status & 0x0F; + } else { + value.field0a = status >>> 8; + value.field0bc = status & 0xFF; + } + var entry = info.struct.bytesFromValue(value); + fatChain.writeToPosition(info, entry, cb); + }); else { + var entry = info.struct.bytesFromValue(status); + fatChain.writeToPosition(info, entry, cb); + } + }; + + vol.allocateInFAT = function (hint, cb) { + if (typeof hint === 'function') { + cb = hint; + hint = 2; // TODO: cache a better starting point? + } + function searchForFreeCluster(num, cb) { + if (num < countofClusters) vol.fetchFromFAT(num, function (e, status) { + if (e) cb(e); + else if (status === 'free') cb(null, num); + else searchForFreeCluster(num+1, cb); + }); else cb(S.err.NOSPC()); // TODO: try searching backwards from hint… + } + searchForFreeCluster(hint, function (e, clusterNum) { + if (e) cb(e); + else vol.storeToFAT(clusterNum, 'eof', cb.bind(null,null,clusterNum)); + }); + }; + + vol.rootDirectoryChain = (isFAT16) ? + c.sectorChain(vol, firstDataSector - rootDirSectors, rootDirSectors) : + c.clusterChain(vol, BS.RootClus); + vol.rootDirectoryChain.cacheAdvice = 'WILLNEED'; + vol.chainForCluster = c.clusterChain.bind(c, vol); + vol.chainFromJSON = function (d) { + return ('numSectors' in d) ? + c.sectorChain(vol, d.firstSector, d.numSectors) : + c.clusterChain(vol, d.firstCluster); + }; + + return vol; +} + +},{"./cache.js":1,"./chains.js":2,"./helpers.js":4,"./structs.js":38}]},{},[5])(5) +}); diff --git a/lib/libv86.js b/lib/libv86.js new file mode 100644 index 00000000..f12dc344 --- /dev/null +++ b/lib/libv86.js @@ -0,0 +1,1281 @@ +;(function(){'use strict';var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.arrayIteratorImpl=function(a){var b=0;return function(){return ba?-b:b}},"es6","es3");$jscomp.SYMBOL_PREFIX="jscomp_symbol_"; +$jscomp.initSymbol=function(){$jscomp.initSymbol=function(){};$jscomp.global.Symbol||($jscomp.global.Symbol=$jscomp.Symbol)};$jscomp.SymbolClass=function(a,b){this.$jscomp$symbol$id_=a;$jscomp.defineProperty(this,"description",{configurable:!0,writable:!0,value:b})};$jscomp.SymbolClass.prototype.toString=function(){return this.$jscomp$symbol$id_}; +$jscomp.Symbol=function(){function a(c){if(this instanceof a)throw new TypeError("Symbol is not a constructor");return new $jscomp.SymbolClass($jscomp.SYMBOL_PREFIX+(c||"")+"_"+b++,c)}var b=0;return a}(); +$jscomp.initSymbolIterator=function(){$jscomp.initSymbol();var a=$jscomp.global.Symbol.iterator;a||(a=$jscomp.global.Symbol.iterator=$jscomp.global.Symbol("Symbol.iterator"));"function"!=typeof Array.prototype[a]&&$jscomp.defineProperty(Array.prototype,a,{configurable:!0,writable:!0,value:function(){return $jscomp.iteratorPrototype($jscomp.arrayIteratorImpl(this))}});$jscomp.initSymbolIterator=function(){}}; +$jscomp.initSymbolAsyncIterator=function(){$jscomp.initSymbol();var a=$jscomp.global.Symbol.asyncIterator;a||(a=$jscomp.global.Symbol.asyncIterator=$jscomp.global.Symbol("Symbol.asyncIterator"));$jscomp.initSymbolAsyncIterator=function(){}};$jscomp.iteratorPrototype=function(a){$jscomp.initSymbolIterator();a={next:a};a[$jscomp.global.Symbol.iterator]=function(){return this};return a}; +$jscomp.iteratorFromArray=function(a,b){$jscomp.initSymbolIterator();a instanceof String&&(a+="");var c=0,d={next:function(){if(c\x3c/script>')},goog.appendScriptSrcNode_= +function(a){var b=goog.global.document,c=b.createElement("script");c.type="text/javascript";c.src=a;c.defer=!1;c.async=!1;b.head.appendChild(c)},goog.writeScriptTag_=function(a,b){if(goog.inHtmlDocument_()){var c=goog.global.document;if(!goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING&&"complete"==c.readyState){if(/\bdeps.js$/.test(a))return!1;throw Error('Cannot write "'+a+'" after document load');}var d=goog.IS_OLD_IE_;void 0===b?d?(b=" onreadystatechange='goog.onScriptLoad_(this, "+ ++goog.lastNonModuleScriptIndex_+ +")' ",c.write('