diff --git a/.travis.yml b/.travis.yml index 2632ffab..3e1d0fe5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,20 +1,31 @@ language: node_js node_js: - "0.12" - - "iojs" + - "5" + - "6" matrix: include: - node_js: "0.10" - env: TEST="all" + env: + - TEST="all" + - CXX=g++-4.8 notifications: email: - jchan@linkedin.com - skinast@linkedin.com before_install: - - npm install -g npm@2 + - npm install -g npm@3 before_script: - npm update sudo: false cache: directories: - node_modules +env: + - CXX=g++-4.8 +addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-4.8 diff --git a/Gruntfile.js b/Gruntfile.js index 36a08ca7..eb3dd1d4 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -138,7 +138,7 @@ module.exports = function(grunt) { outfile: 'index.html', display: 'short', specs: ['test/templates/all.js', 'test/helpers/template.helper.js', 'test/templates.spec.js'], - vendor: ['node_modules/ayepromise/ayepromise.js', 'test/lib/highland.js', 'test/lib/jsreporter.js'] + vendor: ['node_modules/ayepromise/ayepromise.js', 'node_modules/highland/dist/highland.js', 'test/lib/jsreporter.js'] }, /*tests production (minified) code*/ testProd: { diff --git a/lib/compiler.js b/lib/compiler.js index b131e58f..286df45e 100644 --- a/lib/compiler.js +++ b/lib/compiler.js @@ -14,6 +14,9 @@ var compiler = {}, isArray = dust.isArray; + var escape = (typeof JSON === 'undefined') ? + function(str) { return '"' + escapeToJsSafeString(str) + '"';} : + JSON.stringify; compiler.compile = function(source, name) { // the name parameter is optional. @@ -430,10 +433,6 @@ .replace(TB, '\\t'); } - var escape = (typeof JSON === 'undefined') ? - function(str) { return '"' + escapeToJsSafeString(str) + '"';} : - JSON.stringify; - function renderSource(source, context, callback) { var tmpl = dust.loadSource(dust.compile(source)); return loaderFor(tmpl)(context, callback); diff --git a/package.json b/package.json index d3388512..d31aff13 100644 --- a/package.json +++ b/package.json @@ -39,30 +39,30 @@ "linkedin" ], "dependencies": { - "chokidar": "~1.0.1", - "cli": "~0.9.0" + "chokidar": "~1.5.1", + "cli": "~0.11.2" }, "devDependencies": { "ayepromise": "~1.1.1", - "grunt": "~0.4.2", - "grunt-bump": "~0.3.1", - "grunt-cli": "~0.1.13", - "grunt-contrib-clean": "~0.6.0", - "grunt-contrib-concat": "~0.5.1", - "grunt-contrib-connect": "~0.11.2", - "grunt-contrib-copy": "~0.8.0", - "grunt-contrib-jasmine": "~0.9.1", - "grunt-contrib-jshint": "~0.11.1", - "grunt-contrib-uglify": "~0.9.1", - "grunt-contrib-watch": "~0.6.1", + "grunt": "~1.0.1", + "grunt-bump": "~0.8.0", + "grunt-cli": "~1.2.0", + "grunt-contrib-clean": "~1.0.0", + "grunt-contrib-concat": "~1.0.1", + "grunt-contrib-connect": "~1.0.2", + "grunt-contrib-copy": "~1.0.0", + "grunt-contrib-jasmine": "~1.0.3", + "grunt-contrib-jshint": "~1.0.0", + "grunt-contrib-uglify": "~1.0.1", + "grunt-contrib-watch": "~1.0.0", "grunt-execute": "~0.2.2", - "grunt-github-changes": "~0.0.6", - "grunt-jasmine-nodejs": "~1.4.0", + "grunt-github-changes": "~0.1.0", + "grunt-jasmine-nodejs": "~1.5.3", "grunt-peg": "~2.0.0", "grunt-saucelabs": "~8.6.1", - "grunt-shell": "~1.1.2", - "grunt-template-jasmine-istanbul": "~0.3.3", - "highland": "2.4.0", + "grunt-shell": "~1.3.0", + "grunt-template-jasmine-istanbul": "~0.4.0", + "highland": "2.8.1", "pegjs": "0.9.0", "rhino-1_7r3-bin": "~1.0.1", "rhino-1_7r5-bin": "~1.0.1", diff --git a/test/lib/highland.js b/test/lib/highland.js deleted file mode 100644 index 3eee5bb0..00000000 --- a/test/lib/highland.js +++ /dev/null @@ -1,6207 +0,0 @@ -!function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.highland=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= n) { - return fn.apply(this, largs.slice(0, n)); - } - - return _.partial.apply(this, [_.ncurry, n, fn].concat(largs)); -}; - -/** - * Partially applies the function (regardless of whether it has had curry - * called on it). This will always postpone execution until at least the next - * call of the partially applied function. - * - * @id partial - * @name _.partial(fn, args...) - * @section Functions - * @param {Function} fn - function to partial apply - * @param args... - the arguments to apply to the function - * @api public - * - * var addAll = function () { - * var args = Array.prototype.slice.call(arguments); - * return foldl1(add, args); - * }; - * var f = partial(addAll, 1, 2); - * f(3, 4) == 10 - */ - -_.partial = function (f /* args... */) { - var args = slice.call(arguments, 1); - return function () { - return f.apply(this, args.concat(slice.call(arguments))); - }; -}; - -/** - * Evaluates the function `fn` with the argument positions swapped. Only - * works with functions that accept two arguments. - * - * @id flip - * @name _.flip(fn, [x, y]) - * @section Functions - * @param {Function} fn - function to flip argument application for - * @param x - parameter to apply to the right hand side of f - * @param y - parameter to apply to the left hand side of f - * @api public - * - * div(2, 4) == 0.5 - * flip(div, 2, 4) == 2 - * flip(div)(2, 4) == 2 - */ - -_.flip = _.curry(function (fn, x, y) { return fn(y, x); }); - -/** - * Creates a composite function, which is the application of function1 to - * the results of function2. You can pass an arbitrary number of arguments - * and have them composed. This means you can't partially apply the compose - * function itself. - * - * @id compose - * @name _.compose(fn1, fn2, ...) - * @section Functions - * @api public - * - * var add1 = add(1); - * var mul3 = mul(3); - * - * var add1mul3 = compose(mul3, add1); - * add1mul3(2) == 9 - */ - -_.compose = function (/*functions...*/) { - var fns = slice.call(arguments).reverse(); - return _.seq.apply(null, fns); -}; - -/** - * The reversed version of compose. Where arguments are in the order of - * application. - * - * @id seq - * @name _.seq(fn1, fn2, ...) - * @section Functions - * @api public - * - * var add1 = add(1); - * var mul3 = mul(3); - * - * var add1mul3 = seq(add1, mul3); - * add1mul3(2) == 9 - */ - -_.seq = function () { - var fns = slice.call(arguments); - return function () { - if (!fns.length) { - return null; - } - var r = fns[0].apply(this, arguments); - for (var i = 1; i < fns.length; i++) { - r = fns[i].call(this, r); - } - return r; - }; -}; - -/** - * Actual Stream constructor wrapped the the main exported function - */ - -/*eslint-disable no-multi-spaces */ -function Stream(/*optional*/xs, /*optional*/ee, /*optional*/mappingHint) { - /*eslint-enable no-multi-spaces */ - if (xs && _.isStream(xs)) { - // already a Stream - return xs; - } - - EventEmitter.call(this); - var self = this; - - // used to detect Highland Streams using isStream(x), this - // will work even in cases where npm has installed multiple - // versions, unlike an instanceof check - self.__HighlandStream__ = true; - - self.id = ('' + Math.random()).substr(2, 6); - this.paused = true; - this._incoming = []; - this._outgoing = []; - this._consumers = []; - this._observers = []; - this._destructors = []; - this._send_events = false; - this._nil_seen = false; - this._delegate = null; - this._is_observer = false; - this.source = null; - - // Old-style node Stream.pipe() checks for this - this.writable = true; - - self.on('newListener', function (ev) { - if (ev === 'data') { - self._send_events = true; - _.setImmediate(self.resume.bind(self)); - } - else if (ev === 'end') { - // this property avoids us checking the length of the - // listners subscribed to each event on each _send() call - self._send_events = true; - } - }); - - // TODO: write test to cover this removeListener code - self.on('removeListener', function (ev) { - if (ev === 'end' || ev === 'data') { - var end_listeners = self.listeners('end').length; - var data_listeners = self.listeners('data').length; - if (end_listeners + data_listeners === 0) { - // stop emitting events - self._send_events = false; - } - } - }); - - if (xs === undefined) { - // nothing else to do - return this; - } - else if (_.isArray(xs)) { - self._incoming = xs.concat([nil]); - } - else if (typeof xs === 'function') { - this._generator = xs; - this._generator_push = function (err, x) { - if (self._nil_seen) { - throw new Error('Can not write to stream after nil'); - } - - if (x === nil) { - self._nil_seen = true; - } - - self.write(err ? new StreamError(err) : x); - }; - this._generator_next = function (s) { - if (self._nil_seen) { - throw new Error('Can not call next after nil'); - } - - if (s) { - // we MUST pause to get the redirect object into the _incoming - // buffer otherwise it would be passed directly to _send(), - // which does not handle StreamRedirect objects! - var _paused = self.paused; - if (!_paused) { - self.pause(); - } - self.write(new StreamRedirect(s)); - if (!_paused) { - self.resume(); - } - } - else { - self._generator_running = false; - } - if (!self.paused) { - self.resume(); - } - }; - } - else if (_.isObject(xs)) { - if (_.isFunction(xs.then)) { - // probably a promise - return _(function (push) { - xs.then(function (value) { - push(null, value); - return push(null, nil); - }, - function (err) { - push(err); - return push(null, nil); - }); - }); - } - else { - // write any errors into the stream - xs.on('error', function (err) { - self.write(new StreamError(err)); - }); - // assume it's a pipeable stream as a source - xs.pipe(self); - } - } - else if (_.isString(xs)) { - var mappingHintType = (typeof mappingHint); - var mapper; - - if (mappingHintType === 'function') { - mapper = mappingHint; - } - else if (mappingHintType === 'number') { - mapper = function () { - return slice.call(arguments, 0, mappingHint); - }; - } - else if (_.isArray(mappingHint)) { - mapper = function () { - var args = arguments; - return mappingHint.reduce(function (ctx, hint, idx) { - ctx[hint] = args[idx]; - return ctx; - }, {}); - }; - } - else { - mapper = function (x) { return x; }; - } - - ee.on(xs, function () { - var ctx = mapper.apply(this, arguments); - self.write(ctx); - }); - } - else { - throw new Error( - 'Unexpected argument type to Stream(): ' + (typeof xs) - ); - } -} -inherits(Stream, EventEmitter); - -/** - * adds a top-level _.foo(mystream) style export for Stream methods - */ - -function exposeMethod(name) { - var f = Stream.prototype[name]; - var n = f.length; - _[name] = _.ncurry(n + 1, function () { - var args = slice.call(arguments); - var s = _(args.pop()); - return f.apply(s, args); - }); -} - -/** - * Used as an Error marker when writing to a Stream's incoming buffer - */ - -function StreamError(err) { - this.__HighlandStreamError__ = true; - this.error = err; -} - -/** - * Used as a Redirect marker when writing to a Stream's incoming buffer - */ - -function StreamRedirect(to) { - this.__HighlandStreamRedirect__ = true; - this.to = to; -} - -/** - * Returns true if `x` is a Highland Stream. - * - * @id isStream - * @section Utils - * @name _.isStream(x) - * @param x - the object to test - * @api public - * - * _.isStream('foo') // => false - * _.isStream(_([1,2,3])) // => true - */ - -_.isStream = function (x) { - return _.isObject(x) && x.__HighlandStream__; -}; - -_._isStreamError = function (x) { - return _.isObject(x) && x.__HighlandStreamError__; -}; - -_._isStreamRedirect = function (x) { - return _.isObject(x) && x.__HighlandStreamRedirect__; -}; - -/** - * Sends errors / data to consumers, observers and event handlers - */ - -Stream.prototype._send = function (err, x) { - //console.log(['_send', this.id, err, x]); - var token; - - if (x === nil) { - this.ended = true; - } - if (this._consumers.length) { - token = err ? new StreamError(err) : x; - for (var i = 0, len = this._consumers.length; i < len; i++) { - this._consumers[i].write(token); - } - } - if (this._observers.length) { - token = err ? new StreamError(err) : x; - for (var j = 0, len2 = this._observers.length; j < len2; j++) { - this._observers[j].write(token); - } - } - if (this._send_events) { - if (err) { - this.emit('error', err); - } - else if (x === nil) { - this.emit('end'); - } - else { - this.emit('data', x); - } - } -}; - -/** - * Pauses the stream. All Highland Streams start in the paused state. - * - * @id pause - * @section Stream Objects - * @name Stream.pause() - * @api public - * - * var xs = _(generator); - * xs.pause(); - */ - -Stream.prototype.pause = function () { - //console.log(['pause', this.id]); - this.paused = true; - if (!this._is_observer && this.source) { - this.source._checkBackPressure(); - } -}; - -/** - * When there is a change in downstream consumers, it will often ask - * the parent Stream to re-check it's state and pause/resume accordingly. - */ - -Stream.prototype._checkBackPressure = function () { - if (!this._consumers.length) { - return this.pause(); - } - for (var i = 0, len = this._consumers.length; i < len; i++) { - if (this._consumers[i].paused) { - return this.pause(); - } - } - return this.resume(); -}; - -/** - * Starts pull values out of the incoming buffer and sending them downstream, - * this will exit early if this causes a downstream consumer to pause. - */ - -Stream.prototype._readFromBuffer = function () { - //console.log(['_readFromBuffer', this.id, this.paused, this._incoming]); - var len = this._incoming.length; - var i = 0; - while (i < len && !this.paused) { - var x = this._incoming[i]; - if (_._isStreamError(x)) { - this._send(x.error); - } - else if (_._isStreamRedirect(x)) { - this._redirect(x.to); - } - else { - this._send(null, x); - } - i++; - } - // remove processed data from _incoming buffer - this._incoming.splice(0, i); -}; - -/** - * Starts pull values out of the incoming buffer and sending them downstream, - * this will exit early if this causes a downstream consumer to pause. - */ - -Stream.prototype._sendOutgoing = function () { - //console.log(['_sendOutgoing', this.id, this.paused, this._outgoing]); - var len = this._outgoing.length; - var i = 0; - while (i < len && !this.paused) { - var x = this._outgoing[i]; - if (_._isStreamError(x)) { - Stream.prototype._send.call(this, x.error); - } - else if (_._isStreamRedirect(x)) { - this._redirect(x.to); - } - else { - Stream.prototype._send.call(this, null, x); - } - i++; - } - // remove processed data from _outgoing buffer - this._outgoing.splice(0, i); -}; - -/** - * Resumes a paused Stream. This will either read from the Stream's incoming - * buffer or request more data from an upstream source. - * - * @id resume - * @section Stream Objects - * @name Stream.resume() - * @api public - * - * var xs = _(generator); - * xs.resume(); - */ - -Stream.prototype.resume = function () { - //console.log(['resume', this.id]); - if (this._resume_running) { - //console.log(['resume already processing _incoming buffer, ignore resume call']); - // already processing _incoming buffer, ignore resume call - this._repeat_resume = true; - return; - } - this._resume_running = true; - do { - // use a repeat flag to avoid recursing resume() calls - this._repeat_resume = false; - this.paused = false; - - // send values from outgoing buffer first - this._sendOutgoing(); - - // send values from incoming buffer before reading from source - this._readFromBuffer(); - - // we may have paused while reading from buffer - if (!this.paused && !this._is_observer) { - // ask parent for more data - if (this.source) { - //console.log(['ask parent for more data']); - this.source._checkBackPressure(); - } - // run _generator to fill up _incoming buffer - else if (this._generator) { - //console.log(['run generator to fill up _incoming buffer']); - this._runGenerator(); - } - else { - // perhaps a node stream is being piped in - this.emit('drain'); - } - } - } while (this._repeat_resume); - this._resume_running = false; -}; - -/** - * Ends a Stream. This is the same as sending a [nil](#nil) value as data. - * You shouldn't need to call this directly, rather it will be called by - * any [Node Readable Streams](http://nodejs.org/api/stream.html#stream_class_stream_readable) - * you pipe in. - * - * @id end - * @section Stream Objects - * @name Stream.end() - * @api public - * - * mystream.end(); - */ - -Stream.prototype.end = function () { - this.write(nil); -}; - -/** - * Pipes a Highland Stream to a [Node Writable Stream](http://nodejs.org/api/stream.html#stream_class_stream_writable) - * (Highland Streams are also Node Writable Streams). This will pull all the - * data from the source Highland Stream and write it to the destination, - * automatically managing flow so that the destination is not overwhelmed - * by a fast source. - * - * This function returns the destination so you can chain together pipe calls. - * - * @id pipe - * @section Consumption - * @name Stream.pipe(dest) - * @param {Writable Stream} dest - the destination to write all data to - * @api public - * - * var source = _(generator); - * var dest = fs.createWriteStream('myfile.txt') - * source.pipe(dest); - * - * // chained call - * source.pipe(through).pipe(dest); - */ - -Stream.prototype.pipe = function (dest) { - var self = this; - - // stdout and stderr are special case writables that cannot be closed - var canClose = dest !== process.stdout && dest !== process.stderr; - - var s = self.consume(function (err, x, push, next) { - if (err) { - self.emit('error', err); - return; - } - if (x === nil) { - if (canClose) { - dest.end(); - } - } - else if (dest.write(x) !== false) { - next(); - } - }); - - dest.on('drain', onConsumerDrain); - - // Since we don't keep a reference to piped-to streams, - // save a callback that will unbind the event handler. - this._destructors.push(function () { - dest.removeListener('drain', onConsumerDrain); - }); - - s.resume(); - return dest; - - function onConsumerDrain() { - s.resume(); - } -}; - -/** - * Destroys a stream by unlinking it from any consumers and sources. This will - * stop all consumers from receiving events from this stream and removes this - * stream as a consumer of any source stream. - * - * This function calls end() on the stream and unlinks it from any piped-to streams. - * - * @id destroy - * @section Stream Objects - * @name Stream.destroy() - * @api public - */ - -Stream.prototype.destroy = function () { - var self = this; - this.end(); - _(this._consumers).each(function (consumer) { - self._removeConsumer(consumer); - }); - _(this._observers).each(function (observer) { - self._removeObserver(observer); - }); - - if (this.source) { - var source = this.source; - source._removeConsumer(this); - source._removeObserver(this); - } - _(this._destructors).each(function (destructor) { - destructor(); - }); -}; - -/** - * Runs the generator function for this Stream. If the generator is already - * running (it has been called and not called next() yet) then this function - * will do nothing. - */ - -Stream.prototype._runGenerator = function () { - //console.log(['_runGenerator', this.id]); - // if _generator already running, exit - if (this._generator_running) { - return; - } - this._generator_running = true; - this._generator(this._generator_push, this._generator_next); -}; - -/** - * Performs the redirect from one Stream to another. In order for the - * redirect to happen at the appropriate time, it is put on the incoming - * buffer as a StreamRedirect object, and this function is called - * once it is read from the buffer. - */ - -Stream.prototype._redirect = function (to) { - //console.log(['_redirect', this.id, '=>', to.id]); - // coerce to Stream - to = _(to); - - while (to._delegate) { - to = to._delegate; - } - - to._consumers = this._consumers.map(function (c) { - c.source = to; - return c; - }); - - // TODO: copy _observers - this._consumers = []; - //[this.consume = function () { - // return to.consume.apply(to, arguments); - //}; - //this._removeConsumer = function () { - // return to._removeConsumer.apply(to, arguments); - //}; - - // this will cause a memory leak as long as the root object is around - to._delegate_source = this._delegate_source || this; - to._delegate_source._delegate = to; - - if (this.paused) { - to.pause(); - } - else { - this.pause(); - to._checkBackPressure(); - } -}; - -/** - * Adds a new consumer Stream, which will accept data and provide backpressure - * to this Stream. Adding more than one consumer will cause an exception to be - * thrown as the backpressure strategy must be explicitly chosen by the - * developer (through calling fork or observe). - */ - -Stream.prototype._addConsumer = function (s) { - if (this._consumers.length) { - throw new Error( - 'Stream already being consumed, you must either fork() or observe()' - ); - } - s.source = this; - this._consumers.push(s); - this._checkBackPressure(); -}; - -/** - * Removes a consumer from this Stream. - */ - -Stream.prototype._removeConsumer = function (s) { - var src = this; - while (src._delegate) { - src = src._delegate; - } - src._consumers = src._consumers.filter(function (c) { - return c !== s; - }); - if (s.source === src) { - s.source = null; - } - src._checkBackPressure(); -}; - -/** - * Removes an observer from this Stream. - */ - -Stream.prototype._removeObserver = function (s) { - this._observers = this._observers.filter(function (o) { - return o !== s; - }); - if (s.source === this) { - s.source = null; - } -}; - -/** - * Consumes values from a Stream (once resumed) and returns a new Stream for - * you to optionally push values onto using the provided push / next functions. - * - * This function forms the basis of many higher-level Stream operations. - * It will not cause a paused stream to immediately resume, but behaves more - * like a 'through' stream, handling values as they are read. - * - * @id consume - * @section Transforms - * @name Stream.consume(f) - * @param {Function} f - the function to handle errors and values - * @api public - * - * var filter = function (f, source) { - * return source.consume(function (err, x, push, next) { - * if (err) { - * // pass errors along the stream and consume next value - * push(err); - * next(); - * } - * else if (x === _.nil) { - * // pass nil (end event) along the stream - * push(null, x); - * } - * else { - * // pass on the value only if the value passes the predicate - * if (f(x)) { - * push(null, x); - * } - * next(); - * } - * }); - * }; - */ - -Stream.prototype.consume = function (f) { - var self = this; - while (self._delegate) { - self = self._delegate; - } - var s = new Stream(); - var _send = s._send; - var push = function (err, x) { - //console.log(['push', err, x, s.paused]); - if (s._nil_seen) { - throw new Error('Can not write to stream after nil'); - } - if (x === nil) { - // ended, remove consumer from source - s._nil_seen = true; - self._removeConsumer(s); - } - if (s.paused) { - if (err) { - s._outgoing.push(new StreamError(err)); - } - else { - s._outgoing.push(x); - } - } - else { - _send.call(s, err, x); - } - }; - var async; - var next_called; - var next = function (s2) { - //console.log(['next', async]); - if (s._nil_seen) { - throw new Error('Can not call next after nil'); - } - if (s2) { - // we MUST pause to get the redirect object into the _incoming - // buffer otherwise it would be passed directly to _send(), - // which does not handle StreamRedirect objects! - var _paused = s.paused; - if (!_paused) { - s.pause(); - } - s.write(new StreamRedirect(s2)); - if (!_paused) { - s.resume(); - } - } - else if (async) { - s.resume(); - } - else { - next_called = true; - } - }; - s._send = function (err, x) { - async = false; - next_called = false; - f(err, x, push, next); - async = true; - // Don't pause if x is nil -- as next will never be called after - if (!next_called && x !== nil) { - s.pause(); - } - }; - self._addConsumer(s); - return s; -}; -exposeMethod('consume'); - -/** - * Consumes a single item from the Stream. Unlike consume, this function will - * not provide a new stream for you to push values onto, and it will unsubscribe - * as soon as it has a single error, value or nil from the source. - * - * You probably won't need to use this directly, but it is used internally by - * some functions in the Highland library. - * - * @id pull - * @section Consumption - * @name Stream.pull(f) - * @param {Function} f - the function to handle data - * @api public - * - * xs.pull(function (err, x) { - * // do something - * }); - */ - -Stream.prototype.pull = function (f) { - var s = this.consume(function (err, x) { - s.source._removeConsumer(s); - f(err, x); - }); - s.id = 'pull:' + s.id; - s.resume(); -}; - -/** - * Writes a value to the Stream. If the Stream is paused it will go into the - * Stream's incoming buffer, otherwise it will be immediately processed and - * sent to the Stream's consumers (if any). Returns false if the Stream is - * paused, true otherwise. This lets Node's pipe method handle back-pressure. - * - * You shouldn't need to call this yourself, but it may be called by Node - * functions which treat Highland Streams as a [Node Writable Stream](http://nodejs.org/api/stream.html#stream_class_stream_writable). - * - * @id write - * @section Stream Objects - * @name Stream.write(x) - * @param x - the value to write to the Stream - * @api public - * - * var xs = _(); - * xs.write(1); - * xs.write(2); - * xs.end(); - * - * xs.toArray(function (ys) { - * // ys will be [1, 2] - * }); - */ - -Stream.prototype.write = function (x) { - if (this.paused) { - this._incoming.push(x); - } - else { - if (_._isStreamError(x)) { - this._send(x.error); - } - else { - this._send(null, x); - } - } - return !this.paused; -}; - -/** - * Forks a stream, allowing you to add additional consumers with shared - * back-pressure. A stream forked to multiple consumers will only pull values - * from it's source as fast as the slowest consumer can handle them. - * - * @id fork - * @section Higher-order Streams - * @name Stream.fork() - * @api public - * - * var xs = _([1, 2, 3, 4]); - * var ys = xs.fork(); - * var zs = xs.fork(); - * - * // no values will be pulled from xs until zs also resume - * ys.resume(); - * - * // now both ys and zs will get values from xs - * zs.resume(); - */ - -Stream.prototype.fork = function () { - var s = new Stream(); - s.id = 'fork:' + s.id; - s.source = this; - this._consumers.push(s); - this._checkBackPressure(); - return s; -}; - -/** - * Observes a stream, allowing you to handle values as they are emitted, without - * adding back-pressure or causing data to be pulled from the source. This can - * be useful when you are performing two related queries on a stream where one - * would block the other. Just be aware that a slow observer could fill up it's - * buffer and cause memory issues. Where possible, you should use [fork](#fork). - * - * @id observe - * @section Higher-order Streams - * @name Stream.observe() - * @api public - * - * var xs = _([1, 2, 3, 4]); - * var ys = xs.fork(); - * var zs = xs.observe(); - * - * // now both zs and ys will receive data as fast as ys can handle it - * ys.resume(); - */ - -Stream.prototype.observe = function () { - var s = new Stream(); - s.id = 'observe:' + s.id; - s.source = this; - s._is_observer = true; - this._observers.push(s); - return s; -}; - -/** - * Extracts errors from a Stream and applies them to an error handler - * function. Returns a new Stream with the errors removed (unless the error - * handler chooses to rethrow them using `push`). Errors can also be - * transformed and put back onto the Stream as values. - * - * @id errors - * @section Transforms - * @name Stream.errors(f) - * @param {Function} f - the function to pass all errors to - * @api public - * - * getDocument.errors(function (err, push) { - * if (err.statusCode === 404) { - * // not found, return empty doc - * push(null, {}); - * } - * else { - * // otherwise, re-throw the error - * push(err); - * } - * }); - */ - -Stream.prototype.errors = function (f) { - return this.consume(function (err, x, push, next) { - if (err) { - f(err, push); - next(); - } - else if (x === nil) { - push(null, nil); - } - else { - push(null, x); - next(); - } - }); -}; -exposeMethod('errors'); - -/** - * Like the [errors](#errors) method, but emits a Stream end marker after - * an Error is encountered. - * - * @id stopOnError - * @section Transforms - * @name Stream.stopOnError(f) - * @param {Function} f - the function to handle an error - * @api public - * - * brokenStream.stopOnError(function (err) { - * //console.error('Something broke: ' + err); - * }); - */ - -Stream.prototype.stopOnError = function (f) { - return this.consume(function (err, x, push, next) { - if (err) { - f(err, push); - push(null, nil); - } - else if (x === nil) { - push(null, nil); - } - else { - push(null, x); - next(); - } - }); -}; -exposeMethod('stopOnError'); - -/** - * Iterates over every value from the Stream, calling the iterator function - * on each of them. This function causes a **thunk**. - * - * If an error from the Stream reaches the `each` call, it will emit an - * error event (which will cause it to throw if unhandled). - * - * @id each - * @section Consumption - * @name Stream.each(f) - * @param {Function} f - the iterator function - * @api public - * - * _([1, 2, 3, 4]).each(function (x) { - * // will be called 4 times with x being 1, 2, 3 and 4 - * }); - */ - -Stream.prototype.each = function (f) { - var self = this; - return this.consume(function (err, x, push, next) { - if (err) { - self.emit('error', err); - } - else if (x !== nil) { - f(x); - next(); - } - }).resume(); -}; -exposeMethod('each'); - -/** - * Applies all values from a Stream as arguments to a function. This function causes a **thunk**. - * `f` will always be called when the `nil` token is encountered, even when the stream is empty. - * - * @id apply - * @section Consumption - * @name Stream.apply(f) - * @param {Function} f - the function to apply arguments to - * @api public - * - * _([1, 2, 3]).apply(function (a, b, c) { - * // a === 1 - * // b === 2 - * // c === 3 - * }); - * - * _([1, 2, 3]).apply(function (a) { - * // arguments.length === 3 - * // a === 1 - * }); - */ - -Stream.prototype.apply = function (f) { - return this.toArray(function (args) { - f.apply(null, args); - }); -}; -exposeMethod('apply'); - -/** - * Collects all values from a Stream into an Array and calls a function with - * once with the result. This function causes a **thunk**. - * - * If an error from the Stream reaches the `toArray` call, it will emit an - * error event (which will cause it to throw if unhandled). - * - * @id toArray - * @section Consumption - * @name Stream.toArray(f) - * @param {Function} f - the callback to provide the completed Array to - * @api public - * - * _([1, 2, 3, 4]).toArray(function (x) { - * // parameter x will be [1,2,3,4] - * }); - */ - -Stream.prototype.toArray = function (f) { - var self = this; - return this.collect().pull(function (err, x) { - if (err) { - self.emit('error', err); - } - else { - f(x); - } - }); -}; - -/** - * Creates a new Stream of transformed values by applying a function to each - * value from the source. The transformation function can be replaced with - * a non-function value for convenience, and it will emit that value - * for every data event on the source Stream. - * - * @id map - * @section Transforms - * @name Stream.map(f) - * @param f - the transformation function or value to map to - * @api public - * - * var doubled = _([1, 2, 3, 4]).map(function (x) { - * return x * 2; - * }); - * - * _([1, 2, 3]).map('hi') // => 'hi', 'hi', 'hi' - */ - -Stream.prototype.map = function (f) { - if (!_.isFunction(f)) { - var val = f; - f = function () { - return val; - }; - } - return this.consume(function (err, x, push, next) { - if (err) { - push(err); - next(); - } - else if (x === nil) { - push(err, x); - } - else { - var fnVal, fnErr; - try { - fnVal = f(x); - } - catch (e) { - fnErr = e; - } - push(fnErr, fnVal); - next(); - } - }); -}; -exposeMethod('map'); - -/** - * Creates a new Stream which applies a function to each value from the source - * and re-emits the source value. Useful when you want to mutate the value or - * perform side effects - * - * @id doto - * @section Transforms - * @name Stream.doto(f) - * @param f - the function to apply - * @api public - * - * var appended = _([[1], [2], [3], [4]]).doto(function (x) { - * x.push(1); - * }); - * - * _([1, 2, 3]).doto(console.log) - * // 1 - * // 2 - * // 3 - * // => 1, 2, 3 - */ - -Stream.prototype.doto = function (f) { - return this.map(function (x) { - f(x); - return x; - }); -}; -exposeMethod('doto'); - -/** - * An alias for the [doto](#doto) method. - * - * @id tap - * @section Transforms - * @name Stream.tap(f) - * @param f - the function to apply - * @api public - * - * _([1, 2, 3]).tap(console.log) - */ - -Stream.prototype.tap = Stream.prototype.doto; -_.tap = _.doto; - -/** - * Limits number of values through the stream to a maximum of number of values - * per window. Errors are not limited but allowed to pass through as soon as - * they are read from the source. - * - * @id ratelimit - * @section Transforms - * @name Stream.ratelimit(num, ms) - * @param {Number} num - the number of operations to perform per window - * @param {Number} ms - the window of time to limit the operations in (in ms) - * @api public - * - * _([1, 2, 3, 4, 5]).ratelimit(2, 100); - * - * // after 0ms => 1, 2 - * // after 100ms => 1, 2, 3, 4 - * // after 200ms => 1, 2, 3, 4, 5 - */ - -Stream.prototype.ratelimit = function (num, ms) { - if (num < 1) { - throw new Error('Invalid number of operations per ms: ' + num); - } - var sent = 0; - return this.consume(function (err, x, push, next) { - if (err) { - push(err); - next(); - } - else if (x === nil) { - push(null, nil); - } - else { - if (sent < num) { - sent++; - push(null, x); - next(); - } - else { - setTimeout(function () { - sent = 1; - push(null, x); - next(); - }, ms); - } - } - }); -}; -exposeMethod('ratelimit'); - -/** - * Creates a new Stream of values by applying each item in a Stream to an - * iterator function which must return a (possibly empty) Stream. Each item on - * these result Streams are then emitted on a single output Stream. - * - * @id flatMap - * @section Higher-order Streams - * @name Stream.flatMap(f) - * @param {Function} f - the iterator function - * @api public - * - * filenames.flatMap(readFile) - */ - -Stream.prototype.flatMap = function (f) { - return this.map(f).sequence(); -}; -exposeMethod('flatMap'); - -/** - * Retrieves values associated with a given property from all elements in - * the collection. - * - * @id pluck - * @section Transforms - * @name Stream.pluck(property) - * @param {String} prop - the property to which values should be associated - * @api public - * - * var docs = [ - * {type: 'blogpost', title: 'foo'}, - * {type: 'blogpost', title: 'bar'}, - * {type: 'comment', title: 'baz'} - * ]; - * - * _(docs).pluck('title').toArray(function (xs) { - * // xs is now ['foo', 'bar', 'baz'] - * }); - */ - -Stream.prototype.pluck = function (prop) { - return this.consume(function (err, x, push, next) { - if (err) { - push(err); - next(); - } - else if (x === nil) { - push(err, x); - } - else if (_.isObject(x)) { - push(null, x[prop]); - next(); - } - else { - push(new Error( - 'Expected Object, got ' + (typeof x) - )); - next(); - } - }); -}; -exposeMethod('pluck'); - -/** - * - * Retrieves copies of all the enumerable elements in the collection - * that satisfy a given predicate. - * - * @id pickBy - * @section Transforms - * @name Stream.pickBy(f) - * @param {Function} f - the predicate function - * @api public - * - * var dogs = [ - * {breed: 'chihuahua', name: 'Princess', age: 5}, - * {breed: 'labrador', name: 'Rocky', age: 3}, - * {breed: 'german-shepherd', name: 'Waffles', age: 9} - * ]; - - * _(dogs).pickBy(function (key, value) { - * return value > 4; - * }).toArray(function (xs) { - * // xs is now: - * [ - * { age: 5 }, - * {}, - * { age: 9 } - * ] - * }); - */ - -Stream.prototype.pickBy = function (f) { - - return this.consume(function (err, x, push, next) { - var out = {}; - if (err) { - push(err); - next(); - } - else if (x === nil) { - push(err, x); - } - else if (_.isObject(x)) { - for (var k in x) { - if (f(k, x[k])) { - out[k] = x[k]; - } - } - push(null, out); - next(); - } - else { - push(new Error( - 'Expected Object, got ' + (typeof x) - )); - next(); - } - }); -}; -exposeMethod('pickBy'); - -/** - * - * Retrieves copies of all enumerable elements in the collection, - * with only the whitelisted keys. If one of the whitelisted - * keys does not exist, it will be ignored. - * - * @id pick - * @section Transforms - * @name Stream.pick(properties) - * @param {Array} properties - property names to white filter - * @api public - * - * var dogs = [ - * {breed: 'chihuahua', name: 'Princess', age: 5}, - * {breed: 'labrador', name: 'Rocky', age: 3}, - * {breed: 'german-shepherd', name: 'Waffles', age: 9} - * ]; - * - * _(dogs).pick(['breed', 'age']).toArray(function (xs) { - * // xs is now: - * [ - * {breed: 'chihuahua', age: 5}, - * {breed: 'labrador', age: 3}, - * {breed: 'german-shepherd', age: 9} - * ] - * }); - * - * _(dogs).pick(['owner']).toArray(function (xs) { - * // xs is now: - * [ - * {}, - * {}, - * {} - * ] - * });*/ - -Stream.prototype.pick = function (properties) { - return this.pickBy(function (key) { - for (var i = 0, length = properties.length; i < length; i++) { - if (properties[i] === key) { - return true; - } - } - return false; - }); -}; -exposeMethod('pick'); - -/** - * Creates a new Stream including only the values which pass a truth test. - * - * @id filter - * @section Transforms - * @name Stream.filter(f) - * @param f - the truth test function - * @api public - * - * var evens = _([1, 2, 3, 4]).filter(function (x) { - * return x % 2 === 0; - * }); - */ - -Stream.prototype.filter = function (f) { - return this.consume(function (err, x, push, next) { - if (err) { - push(err); - next(); - } - else if (x === nil) { - push(err, x); - } - else { - var fnVal, fnErr; - try { - fnVal = f(x); - } - catch (e) { - fnErr = e; - } - - if (fnErr) { - push(fnErr); - } - else if (fnVal) { - push(null, x); - } - next(); - } - }); -}; -exposeMethod('filter'); - -/** - * Filters using a predicate which returns a Stream. If you need to check - * against an asynchronous data source when filtering a Stream, this can - * be convenient. The Stream returned from the filter function should have - * a Boolean as it's first value (all other values on the Stream will be - * disregarded). - * - * @id flatFilter - * @section Higher-order Streams - * @name Stream.flatFilter(f) - * @param {Function} f - the truth test function which returns a Stream - * @api public - * - * var checkExists = _.wrapCallback(fs.exists); - * filenames.flatFilter(checkExists) - */ - -Stream.prototype.flatFilter = function (f) { - return this.flatMap(function (x) { - return f(x).take(1).otherwise(errorStream()) - .flatMap(function (bool) { - return _(bool ? [x] : []); - }); - }); - - function errorStream() { - return _(function (push) { - push(new Error('Stream returned by function was empty.')); - push(null, _.nil); - }); - } -}; -exposeMethod('flatFilter'); - -/** - * The inverse of [filter](#filter). - * - * @id reject - * @section Transforms - * @name Stream.reject(f) - * @param {Function} f - the truth test function - * @api public - * - * var odds = _([1, 2, 3, 4]).reject(function (x) { - * return x % 2 === 0; - * }); - */ - -Stream.prototype.reject = function (f) { - return this.filter(_.compose(_.not, f)); -}; -exposeMethod('reject'); - -/** - * A convenient form of [filter](#filter), which returns the first object from a - * Stream that passes the provided truth test - * - * @id find - * @section Transforms - * @name Stream.find(f) - * @param {Function} f - the truth test function which returns a Stream - * @api public - * - * var docs = [ - * {type: 'blogpost', title: 'foo'}, - * {type: 'blogpost', title: 'bar'}, - * {type: 'comment', title: 'foo'} - * ]; - * - * var f = function (x) { - * return x.type == 'blogpost'; - * }; - * - * _(docs).find(f); - * // => {type: 'blogpost', title: 'foo'} - * - * // example with partial application - * var firstBlogpost = _.find(f); - * - * firstBlogpost(docs) - * // => {type: 'blogpost', title: 'foo'} - */ - -Stream.prototype.find = function (f) { - return this.filter(f).take(1); -}; -exposeMethod('find'); - -/** - * A convenient form of [where](#where), which returns the first object from a - * Stream that matches a set of property values. findWhere is to [where](#where) as [find](#find) is to [filter](#filter). - * - * @id findWhere - * @section Transforms - * @name Stream.findWhere(props) - * @param {Object} props - the properties to match against - * @api public - * - * var docs = [ - * {type: 'blogpost', title: 'foo'}, - * {type: 'blogpost', title: 'bar'}, - * {type: 'comment', title: 'foo'} - * ]; - * - * _(docs).findWhere({type: 'blogpost'}) - * // => {type: 'blogpost', title: 'foo'} - * - * // example with partial application - * var firstBlogpost = _.findWhere({type: 'blogpost'}); - * - * firstBlogpost(docs) - * // => {type: 'blogpost', title: 'foo'} - */ - -Stream.prototype.findWhere = function (props) { - return this.where(props).take(1); -}; -exposeMethod('findWhere'); - - -/** - * A convenient form of [reduce](#reduce), which groups items based on a function or property name - * - * @id group - * @section Transforms - * @name Stream.group(f) - * @param {Function|String} f - the function or property name on which to group, - * toString() is called on the result of a function. - * @api public - * - * var docs = [ - * {type: 'blogpost', title: 'foo'}, - * {type: 'blogpost', title: 'bar'}, - * {type: 'comment', title: 'foo'} - * ]; - * - * var f = function (x) { - * return x.type; - * }; - * - * _(docs).group(f); OR _(docs).group('type'); - * // => { - * // => 'blogpost': [{type: 'blogpost', title: 'foo'}, {type: 'blogpost', title: 'bar'}] - * // => 'comment': [{type: 'comment', title: 'foo'}] - * // => } - * - */ - -Stream.prototype.group = function (f) { - var lambda = _.isString(f) ? _.get(f) : f; - return this.reduce({}, function (m, o) { - var key = lambda(o); - if (!hasOwn.call(m, key)) { m[key] = []; } - m[key].push(o); - return m; - }); -}; -exposeMethod('group'); - -/** - * Filters a Stream to drop all non-truthy values. - * - * @id compact - * @section Transforms - * @name Stream.compact() - * @api public - * - * var compacted = _([0, 1, false, 3, null, undefined, 6]).compact(); - * // => 1, 3, 6 - */ - -Stream.prototype.compact = function () { - return this.filter(function (x) { - return x; - }); -}; -exposeMethod('compact'); - -/** - * A convenient form of [filter](#filter), which returns all objects from a Stream - * which match a set of property values. - * - * @id where - * @section Transforms - * @name Stream.where(props) - * @param {Object} props - the properties to match against - * @api public - * - * var docs = [ - * {type: 'blogpost', title: 'foo'}, - * {type: 'blogpost', title: 'bar'}, - * {type: 'comment', title: 'foo'} - * ]; - * - * _(docs).where({title: 'foo'}) - * // => {type: 'blogpost', title: 'foo'} - * // => {type: 'comment', title: 'foo'} - * - * // example with partial application - * var getBlogposts = _.where({type: 'blogpost'}); - * - * getBlogposts(docs) - * // => {type: 'blogpost', title: 'foo'} - * // => {type: 'blogpost', title: 'bar'} - */ - -Stream.prototype.where = function (props) { - return this.filter(function (x) { - for (var k in props) { - if (x[k] !== props[k]) { - return false; - } - } - return true; - }); -}; -exposeMethod('where'); - -/** - * A way to keep only unique objects from a Stream - * The definition of 'unicity' is given by a Function argument. - * - * Note: - * - memory: in order to guarantee that each unique item is chosen only once, we need to keep an - * internal buffer of all unique values. This may outgrow the available memory if you are not - * cautious about the size of your stream and the number of unique objects you may receive on that - * stream - * - errors: the transformation will emit an error for each comparison that throws an error - * - * @id uniqBy - * @section Transforms - * @name Stream.uniqBy(compare) - * @param {Function} compare - custom equality predicate - * @api public - * - * var colors = [ 'blue', 'red', 'red', 'yellow', 'blue', 'red' ] - * - * _(colors).uniqBy(function(a,b) { return a[1] === b[1] }) - * // => 'blue' - * // => 'red' - * - */ - -Stream.prototype.uniqBy = function (compare) { - var uniques = []; - return this.consume(function (err, x, push, next) { - if (err) { - push(err); - next(); - } - else if (x === nil) { - push(err, x); - } - else { - var seen = false; - var hasErr; - for (var i = 0, len = uniques.length; i < len; i++) { - try { - seen = compare(x, uniques[i]); - } - catch (e) { - hasErr = e; - seen = true; - } - if (seen) { - break; - } - } - if (!seen) { - uniques.push(x); - push(null, x); - } - if (hasErr) { - push(hasErr); - } - next(); - } - }); -}; -exposeMethod('uniqBy'); - -/** - * Takes all unique values in a stream. - * It uses uniqBy internally, using the strict equality === operator to define unicity - * - * @id uniq - * @section Transforms - * @name Stream.uniq() - * @api public - * - * var colors = [ 'blue', 'red', 'red', 'yellow', 'blue', 'red' ] - * - * _(colors).uniq() - * // => 'blue' - * // => 'red' - * // => 'yellow' - */ - -Stream.prototype.uniq = function () { - return this.uniqBy(function (a, b) { - return a === b; - }); -}; -exposeMethod('uniq'); - -/** - * Takes a stream and a `finite` stream of `N` streams - * and returns a stream where the first element from each - * separate stream is combined into a single data event, - * followed by the second elements of each stream and so on - * until the shortest input stream is exhausted. - * - * @id zipAll - * @section Higher-order Streams - * @name Stream.zipAll(ys) - * @param {Array | Stream} ys - the array of streams to combine values with - * @api public - * - * _([1,2,3]).zipAll([[4, 5, 6], [7, 8, 9], [10, 11, 12]]) - * // => [ [ 1, 4, 7, 10 ], [ 2, 5, 8, 11 ], [ 3, 6, 9, 12 ] ] - * - * // shortest stream determines length of output stream - * _([1, 2, 3, 4]).zipAll([[5, 6, 7, 8], [9, 10, 11, 12], [13, 14]]) - * // => [ [ 1, 5, 9, 13 ], [ 2, 6, 10, 14 ] ] - */ - -Stream.prototype.zipAll = function (ys) { - var self = this; - ys = _(ys).map(_); - - var returned = 0; - var z = []; - var finished = false; - - function nextValue(index, max, src, push, next) { - src.pull(function (err, x) { - if (err) { - push(err); - nextValue(index, max, src, push, next); - } - else if (x === _.nil) { - if (!finished) { - finished = true; - push(null, nil); - } - } - else { - returned++; - z[index] = x; - if (returned === max) { - push(null, z); - next(); - } - } - }); - } - - return ys.collect().flatMap(function (array) { - array.unshift(self); - return _(function (push, next) { - returned = 0; - z = []; - for (var i = 0, length = array.length; i < length; i++) { - nextValue(i, length, array[i], push, next); - } - }); - }); - -}; -exposeMethod('zipAll'); - -/** - * Takes two Streams and returns a Stream of corresponding pairs. - * - * @id zip - * @section Higher-order Streams - * @name Stream.zip(ys) - * @param {Array | Stream} ys - the other stream to combine values with - * @api public - * - * _(['a', 'b', 'c']).zip([1, 2, 3]) // => ['a', 1], ['b', 2], ['c', 3] - */ - -Stream.prototype.zip = function (ys) { - return this.zipAll([ys]); -}; -exposeMethod('zip'); - -/** - * Takes one Stream and batches incoming data into arrays of given length - * - * @id batch - * @section Transforms - * @name Stream.batch(n) - * @param {Number} n - length of the array to batch - * @api public - * - * _([1, 2, 3, 4, 5]).batch(2) // => [1, 2], [3, 4], [5] - */ - -Stream.prototype.batch = function (n) { - var batched = []; - - return this.consume(function (err, x, push, next) { - if (err) { - push(err); - next(); - } - else if (x === nil) { - if (batched.length > 0) { - push(null, batched); - } - - push(null, nil); - } - else { - batched.push(x); - - if (batched.length === n) { - push(null, batched); - batched = []; - } - - next(); - } - }); -}; -exposeMethod('batch'); - -/** - * Creates a new Stream with the separator interspersed between the elements of the source. - * - * intersperse is effectively the inverse of [splitBy](#splitBy). - * - * @id intersperse - * @section Transforms - * @name Stream.intersperse(sep) - * @param sep - the value to intersperse between the source elements - * @api public - * - * _(['ba', 'a', 'a']).intersperse('n') // => ba, n, a, n, a - * _(['mississippi']).splitBy('ss').intersperse('ss') // => mi, ss, i, ss, ippi - * _(['foo']).intersperse('bar') // => foo - */ - -Stream.prototype.intersperse = function (separator) { - var started = false; - return this.consume(function (err, x, push, next) { - if (err) { - push(err); - next(); - } - else if (x === nil) { - push(null, nil); - } - else { - if (started) { - push(null, separator); - } - else { - started = true; - } - push(null, x); - next(); - } - }); -}; -exposeMethod('intersperse'); - -/** - * Splits the source Stream by a separator and emits the pieces in between, much like splitting a string. - * - * splitBy is effectively the inverse of [intersperse](#intersperse). - * - * @id splitBy - * @section Transforms - * @name Stream.splitBy(sep) - * @param sep - the separator to split on - * @api public - * - * _(['mis', 'si', 's', 'sippi']).splitBy('ss') // => mi, i, ippi - * _(['ba', 'a', 'a']).intersperse('n').splitBy('n') // => ba, a, a - * _(['foo']).splitBy('bar') // => foo - */ - -Stream.prototype.splitBy = function (sep) { - var decoder = new Decoder(); - var buffer = false; - - function drain(x, push) { - buffer = (buffer || '') + decoder.write(x); - var pieces = buffer.split(sep); - buffer = pieces.pop(); - - pieces.forEach(function (piece) { - push(null, piece); - }); - } - - return this.consume(function (err, x, push, next) { - if (err) { - push(err); - next(); - } - else if (x === nil) { - if (_.isString(buffer)) { - drain(decoder.end(), push); - push(null, buffer); - } - push(null, nil); - } - else { - drain(x, push); - next(); - } - }); -}; -exposeMethod('splitBy'); - -/** - * [splitBy](#splitBy) over newlines. - * - * @id split - * @section Transforms - * @name Stream.split() - * @api public - * - * _(['a\n', 'b\nc\n', 'd', '\ne']).split() // => a, b, c, d, e - * _(['a\r\nb\nc']]).split() // => a, b, c - */ - -Stream.prototype.split = function () { - return this.splitBy(/\r?\n/); -}; -exposeMethod('split'); - -/** - * Creates a new Stream with the first `n` values from the source. - * - * @id take - * @section Transforms - * @name Stream.take(n) - * @param {Number} n - integer representing number of values to read from source - * @api public - * - * _([1, 2, 3, 4]).take(2) // => 1, 2 - */ - -Stream.prototype.take = function (n) { - if (n === 0) { - return _([]); - } - var s = this.consume(function (err, x, push, next) { - //console.log(['take', err, x, n]); - if (err) { - push(err); - if (n > 0) { - next(); - } - else { - push(null, nil); - } - } - else if (x === nil) { - push(null, nil); - } - else { - n--; - push(null, x); - if (n > 0) { - next(); - } - else { - push(null, nil); - } - } - }); - s.id = 'take:' + s.id; - return s; -}; -exposeMethod('take'); - -/** - * Creates a new Stream with only the first value from the source. - * - * @id head - * @section Transforms - * @name Stream.head() - * @api public - * - * _([1, 2, 3, 4]).head() // => 1 - */ - -Stream.prototype.head = function () { - return this.take(1); -}; -exposeMethod('head'); - -/** - * Drops all values from the Stream apart from the last one (if any). - * - * @id last - * @section Transforms - * @name Stream.last() - * @api public - * - * _([1, 2, 3, 4]).last() // => 4 - */ - -Stream.prototype.last = function () { - var nothing = {}; - var prev = nothing; - return this.consume(function (err, x, push, next) { - if (err) { - push(err); - next(); - } - else if (x === nil) { - if (prev !== nothing) { - push(null, prev); - } - push(null, nil); - } - else { - prev = x; - next(); - } - }); -}; -exposeMethod('last'); - -/** - * Passes the current Stream to a function, returning the result. Can also - * be used to pipe the current Stream through another Stream. It will always - * return a Highland Stream (instead of the piped to target directly as in - * Node.js). - * - * @id through - * @section Higher-order Streams - * @name Stream.through(target) - * @api public - * - * function oddDoubler(s) { - * return s.filter(function (x) { - * return x % 2; // odd numbers only - * }) - * .map(function (x) { - * return x * 2; - * }); - * } - * - * _([1, 2, 3, 4]).through(oddDoubler).toArray(function (xs) { - * // xs will be [2, 6] - * }); - * - * // Can also be used with Node Through Streams - * _(filenames).through(jsonParser).map(function (obj) { - * // ... - * }); - */ - -Stream.prototype.through = function (target) { - if (_.isFunction(target)) { - return target(this); - } - else { - var output = _(); - target.pause(); - this.pipe(target).pipe(output); - return output; - } -}; -exposeMethod('through'); - -/** - * Creates a 'Through Stream', which passes data through a pipeline - * of functions or other through Streams. This is particularly useful - * when combined with partial application of Highland functions to expose a - * Node-compatible Through Stream. - * - * This is not a method on a Stream, and it only exposed at the top-level - * as `_.pipeline`. It takes an arbitrary number of arguments. - * - * @id pipeline - * @section Higher-order Streams - * @name _.pipeline(...) - * @api public - * - * var through = _.pipeline( - * _.map(parseJSON), - * _.filter(isBlogpost), - * _.reduce(collectCategories) - * _.through(otherPipeline) - * ); - * - * readStream.pipe(through).pipe(outStream); - * - * // Alternatively, you can use pipeline to manipulate a stream in - * // the chained method call style: - * - * var through2 = _.pipeline(function (s) { - * return s.map(parseJSON).filter(isBlogpost); // etc. - * }); - */ - -_.pipeline = function (/*through...*/) { - if (!arguments.length) { - return _(); - } - var start = arguments[0], rest; - if (!_.isStream(start) && !_.isFunction(start.resume)) { - // not a Highland stream or Node stream, start with empty stream - start = _(); - rest = slice.call(arguments); - } - else { - // got a stream as first argument, co-erce to Highland stream - start = _(start); - rest = slice.call(arguments, 1); - } - var end = rest.reduce(function (src, dest) { - return src.through(dest); - }, start); - var wrapper = _(function (push, next) { - end.pull(function (err, x) { - if (err) { - wrapper._send(err); - next(); - } - else if (x === nil) { - wrapper._send(null, nil); - } - else { - wrapper._send(null, x); - next(); - } - }); - }); - wrapper.write = function (x) { - start.write(x); - }; - return wrapper; -}; - -/** - * Reads values from a Stream of Streams, emitting them on a single output - * Stream. This can be thought of as a flatten, just one level deep. Often - * used for resolving asynchronous actions such as a HTTP request or reading - * a file. - * - * @id sequence - * @section Higher-order Streams - * @name Stream.sequence() - * @api public - * - * var nums = _([ - * _([1, 2, 3]), - * _([4, 5, 6]) - * ]); - * - * nums.sequence() // => 1, 2, 3, 4, 5, 6 - * - * // using sequence to read from files in series - * filenames.map(readFile).sequence() - */ - -Stream.prototype.sequence = function () { - var original = this; - var curr = this; - return _(function (push, next) { - curr.pull(function (err, x) { - if (err) { - push(err); - return next(); - } - else if (_.isArray(x)) { - if (onOriginalStream()) { - // just send all values from array directly - x.forEach(function (y) { - push(null, y); - }); - } - else { - push(null, x); - } - return next(); - } - else if (_.isStream(x)) { - if (onOriginalStream()) { - // switch to reading new stream - curr = x; - return next(); - } - else { - // sequence only goes 1 level deep - push(null, x); - return next(); - } - } - else if (x === nil) { - if (onOriginalStream()) { - push(null, nil); - } - else { - // resume reading from original - curr = original; - return next(); - } - } - else { - if (onOriginalStream()) { - // we shouldn't be getting non-stream (or array) - // values from the top-level stream - push(new Error( - 'Expected Stream, got ' + (typeof x) - )); - return next(); - } - else { - push(null, x); - return next(); - } - } - }); - }); - - function onOriginalStream() { - return curr === original; - } -}; -exposeMethod('sequence'); - -/** - * An alias for the [sequence](#sequence) method. - * - * @id series - * @section Higher-order Streams - * @name Stream.series() - * @api public - * - * filenames.map(readFile).series() - */ - -Stream.prototype.series = Stream.prototype.sequence; -_.series = _.sequence; - -/** - * Recursively reads values from a Stream which may contain nested Streams - * or Arrays. As values or errors are encountered, they are emitted on a - * single output Stream. - * - * @id flatten - * @section Higher-order Streams - * @name Stream.flatten() - * @api public - * - * _([1, [2, 3], [[4]]]).flatten(); // => 1, 2, 3, 4 - * - * var nums = _( - * _([1, 2, 3]), - * _([4, _([5, 6]) ]) - * ); - * - * nums.flatten(); // => 1, 2, 3, 4, 5, 6 - */ - -Stream.prototype.flatten = function () { - var curr = this; - var stack = []; - return _(function (push, next) { - curr.pull(function (err, x) { - if (err) { - push(err); - return next(); - } - if (_.isArray(x)) { - x = _(x); - } - if (_.isStream(x)) { - stack.push(curr); - curr = x; - next(); - } - else if (x === nil) { - if (stack.length) { - curr = stack.pop(); - next(); - } - else { - push(null, nil); - } - } - else { - push(null, x); - next(); - } - }); - }); -}; -exposeMethod('flatten'); - -/** - * Takes a Stream of Streams and reads from them in parallel, buffering - * the results until they can be returned to the consumer in their original - * order. - * - * @id parallel - * @section Higher-order Streams - * @name Stream.parallel(n) - * @param {Number} n - the maximum number of concurrent reads/buffers - * @api public - * - * var readFile = _.wrapCallback(fs.readFile); - * var filenames = _(['foo.txt', 'bar.txt', 'baz.txt']); - * - * // read from up to 10 files at once - * filenames.map(readFile).parallel(10); - */ - -Stream.prototype.parallel = function (n) { - var source = this; - var running = []; - var ended = false; - var reading_source = false; - - return _(function (push, next) { - if (running.length && running[0].buffer.length) { - // send buffered data - var buf = running[0].buffer; - for (var i = 0; i < buf.length; i++) { - if (buf[i][1] === nil) { - // this stream has ended - running.shift(); - return next(); - } - else { - // send the buffered output - push.apply(null, buf[i]); - } - } - // still waiting for more data before we can shift - // the running array... - } - else if (running.length < n && !ended && !reading_source) { - // get another stream if not already waiting for one - reading_source = true; - source.pull(function (err, x) { - reading_source = false; - if (err) { - push(err); - } - else if (x === nil) { - ended = true; - } - else { - // got a new source, add it to the running array - var run = {stream: x, buffer: []}; - running.push(run); - x.consume(function (err, y, _push, _next) { - if (running[0] === run) { - // current output stream - if (y === nil) { - // remove self from running and check - // to see if we need to read from source again - running.shift(); - next(); - } - else { - // push directly onto parallel output stream - push(err, y); - } - } - else { - // we're reading ahead, buffer the output - run.buffer.push([err, y]); - } - if (y !== nil) { - // keep reading until we hit nil - _next(); - } - }).resume(); - } - // check if we need to get any more streams - return next(); - }); - } - else if (!running.length && ended) { - // nothing more to do - push(null, nil); - } - // else wait for more data to arrive from running streams - }); -}; -exposeMethod('parallel'); - -/** - * Switches source to an alternate Stream if the current Stream is empty. - * - * @id otherwise - * @section Higher-order Streams - * @name Stream.otherwise(ys) - * @param {Stream | Function} ys - alternate stream (or stream-returning function) to use if this stream is empty - * @api public - * - * _([1,2,3]).otherwise(['foo']) // => 1, 2, 3 - * _([]).otherwise(['foo']) // => 'foo' - * - * _.otherwise(_(['foo']), _([1,2,3])) // => 1, 2, 3 - * _.otherwise(_(['foo']), _([])) // => 'foo' - */ - -Stream.prototype.otherwise = function (ys) { - var xs = this; - return xs.consume(function (err, x, push, next) { - if (err) { - // got an error, just keep going - push(err); - next(); - } - else if (x === nil) { - // hit the end without redirecting to xs, use alternative - if (_.isFunction(ys)) { - next(ys()); - } - else { - next(ys); - } - } - else { - // got a value, push it, then redirect to xs - push(null, x); - next(xs); - } - }); -}; -exposeMethod('otherwise'); - -/** - * Adds a value to the end of a Stream. - * - * @id append - * @section Transforms - * @name Stream.append(y) - * @param y - the value to append to the Stream - * @api public - * - * _([1, 2, 3]).append(4) // => 1, 2, 3, 4 - */ - -Stream.prototype.append = function (y) { - return this.consume(function (err, x, push, next) { - if (x === nil) { - push(null, y); - push(null, _.nil); - } - else { - push(err, x); - next(); - } - }); -}; -exposeMethod('append'); - -/** - * Boils down a Stream to a single value. The memo is the initial state - * of the reduction, and each successive step of it should be returned by - * the iterator function. The iterator is passed two arguments: - * the memo and the next value. - * - * If the iterator throws an error, the reduction stops and the resulting - * stream will emit that error instead of a value. - * - * @id reduce - * @section Transforms - * @name Stream.reduce(memo, iterator) - * @param memo - the initial state of the reduction - * @param {Function} iterator - the function which reduces the values - * @api public - * - * var add = function (a, b) { - * return a + b; - * }; - * - * _([1, 2, 3, 4]).reduce(0, add) // => 10 - */ - -Stream.prototype.reduce = function (z, f) { - // This can't be implemented with scan(), because we don't know if the - // errors that we see from the scan were thrown by the iterator or just - // passed through from the source stream. - return this.consume(function (err, x, push, next) { - if (x === nil) { - push(null, z); - push(null, _.nil); - } - else if (err) { - push(err); - next(); - } - else { - try { - z = f(z, x); - } - catch (e) { - push(e); - push(null, _.nil); - return; - } - - next(); - } - }); -}; -exposeMethod('reduce'); - -/** - * Same as [reduce](#reduce), but uses the first element as the initial - * state instead of passing in a `memo` value. - * - * @id reduce1 - * @section Transforms - * @name Stream.reduce1(iterator) - * @param {Function} iterator - the function which reduces the values - * @api public - * - * _([1, 2, 3, 4]).reduce1(add) // => 10 - */ - -Stream.prototype.reduce1 = function (f) { - var self = this; - return _(function (push, next) { - self.pull(function (err, x) { - if (err) { - push(err); - next(); - } - else if (x === nil) { - push(null, nil); - } - else { - next(self.reduce(x, f)); - } - }); - }); -}; -exposeMethod('reduce1'); - -/** - * Groups all values into an Array and passes down the stream as a single - * data event. This is a bit like doing [toArray](#toArray), but instead - * of accepting a callback and causing a *thunk*, it passes the value on. - * - * @id collect - * @section Transforms - * @name Stream.collect() - * @api public - * - * _(['foo', 'bar']).collect().toArray(function (xs) { - * // xs will be [['foo', 'bar']] - * }); - */ - -Stream.prototype.collect = function () { - var xs = []; - return this.consume(function (err, x, push, next) { - if (err) { - push(err); - next(); - } - else if (x === nil) { - push(null, xs); - push(null, nil); - } - else { - xs.push(x); - next(); - } - }); -}; -exposeMethod('collect'); - -/** - * Like [reduce](#reduce), but emits each intermediate value of the - * reduction as it is calculated. - * - * If the iterator throws an error, the scan will stop and the stream will - * emit that error. Any intermediate values that were produced before the - * error will still be emitted. - * - * @id scan - * @section Transforms - * @name Stream.scan(memo, iterator) - * @param memo - the initial state of the reduction - * @param {Function} iterator - the function which reduces the values - * @api public - * - * _([1, 2, 3, 4]).scan(0, add) // => 0, 1, 3, 6, 10 - */ - -Stream.prototype.scan = function (z, f) { - var self = this; - return _([z]).concat( - self.consume(function (err, x, push, next) { - if (x === nil) { - push(null, _.nil); - } - else if (err) { - push(err); - next(); - } - else { - try { - z = f(z, x); - } - catch (e) { - push(e); - push(null, _.nil); - return; - } - - push(null, z); - next(); - } - }) - ); -}; -exposeMethod('scan'); - -/** - * Same as [scan](#scan), but uses the first element as the initial - * state instead of passing in a `memo` value. - * - * @id scan1 - * @section Transforms - * @name Stream.scan1(iterator) - * @param {Function} iterator - the function which reduces the values - * @api public - * - * _([1, 2, 3, 4]).scan1(add) // => 1, 3, 6, 10 - */ - -Stream.prototype.scan1 = function (f) { - var self = this; - return _(function (push, next) { - self.pull(function (err, x) { - if (err) { - push(err); - next(); - } - else if (x === nil) { - push(null, nil); - } - else { - next(self.scan(x, f)); - } - }); - }); -}; -exposeMethod('scan1'); - -var highlandTransform = { - init: function () { }, - result: function (push) { - // Don't push nil here. Otherwise, we can't catch errors from `result` - // and propagate them. The `transduce` implementation will do it. - return push; - }, - step: function (push, input) { - push(null, input); - return push; - } -}; - -/** - * Applies the transformation defined by the the given *transducer* to the - * stream. A transducer is any function that follows the - * [Transducer Protocol](https://github.com/cognitect-labs/transducers-js#transformer-protocol). - * See - * [transduce-js](https://github.com/cognitect-labs/transducers-js#transducers-js) - * for more details on what transducers actually are. - * - * The `result` object that is passed in through the - * [Transformer Protocol](https://github.com/cognitect-labs/transducers-js#transformer-protocol) - * will be the `push` function provided by the [consume](#consume) transform. - * - * Like [scan](#scan), if the transducer throws an exception, the transform - * will stop and emit that error. Any intermediate values that were produced - * before the error will still be emitted. - * - * @id transduce - * @section Transforms - * @name Stream.transduce(xf) - * @param {Function} xf - The transducer. - * @api public - * - * var xf = require('transducer-js').map(_.add(1)); - * _([1, 2, 3, 4]).transduce(xf); - * // => [2, 3, 4, 5] - */ - -Stream.prototype.transduce = function transduce(xf) { - var transform = xf(highlandTransform); - - return this.consume(function (err, x, push, next) { - if (err) { - // Pass through errors, like we always do. - push(err); - next(); - } - else if (x === _.nil) { - runResult(push); - } - else { - var res = runStep(push, x); - - if (!res) { - return; - } - - if (res.__transducers_reduced__) { - runResult(res.value); - } - else { - next(); - } - } - }); - - function runResult(push) { - try { - transform.result(push); - } - catch (e) { - push(e); - } - push(null, _.nil); - } - - function runStep(push, x) { - try { - return transform.step(push, x); - } - catch (e) { - push(e); - push(null, _.nil); - return null; - } - } -}; -exposeMethod('transduce'); - -/** - * Concatenates a Stream to the end of this Stream. - * - * Be aware that in the top-level export, the args may be in the reverse - * order to what you'd expect `_([a], [b]) => b, a`, as this follows the - * convention of other top-level exported functions which do `x` to `y`. - * - * @id concat - * @section Higher-order Streams - * @name Stream.concat(ys) - * @param {Stream | Array} ys - the values to concatenate onto this Stream - * @api public - * - * _([1, 2]).concat([3, 4]) // => 1, 2, 3, 4 - * _.concat([3, 4], [1, 2]) // => 1, 2, 3, 4 - */ - -Stream.prototype.concat = function (ys) { - ys = _(ys); - return this.consume(function (err, x, push, next) { - if (x === nil) { - next(ys); - } - else { - push(err, x); - next(); - } - }); -}; -exposeMethod('concat'); - -/** - * Takes a Stream of Streams and merges their values and errors into a - * single new Stream. The merged stream ends when all source streams have - * ended. - * - * Note that no guarantee is made with respect to the order in which - * values for each stream end up in the merged stream. Values in the - * merged stream will, however, respect the order they were emitted from - * their respective streams. - * - * @id merge - * @section Higher-order Streams - * @name Stream.merge() - * @api public - * - * var txt = _(['foo.txt', 'bar.txt']).map(readFile) - * var md = _(['baz.md']).map(readFile) - * - * _([txt, md]).merge(); - * // => contents of foo.txt, bar.txt and baz.txt in the order they were read - */ - -Stream.prototype.merge = function () { - var self = this; - var srcs = []; - - var srcsNeedPull = [], - first = true, - async = false; - - return _(function (push, next) { - if (first) { - first = false; - getSourcesSync(push, next); - } - - if (srcs.length === 0) { - push(null, nil); - } - else if (srcsNeedPull.length) { - pullFromAllSources(push, next); - next(); - } - else { - async = true; - } - }); - - // Make a handler for the main merge loop. - function srcPullHandler(push, next, src) { - return function (err, x) { - if (err) { - push(err); - srcsNeedPull.push(src); - } - else if (x === nil) { - srcs = srcs.filter(function (s) { - return s !== src; - }); - } - else { - if (src === self) { - srcs.push(x); - srcsNeedPull.push(x); - srcsNeedPull.unshift(self); - } - else { - push(null, x); - srcsNeedPull.push(src); - } - } - - if (async) { - async = false; - next(); - } - }; - } - - - function pullFromAllSources(push, next) { - var _srcs = srcsNeedPull; - srcsNeedPull = []; - _srcs.forEach(function (src) { - src.pull(srcPullHandler(push, next, src)); - }); - } - - // Pulls as many sources as possible from self synchronously. - function getSourcesSync(push, next) { - // Shadows the outer async variable. - var asynchronous; - var done = false; - - var pull_cb = function(err, x) { - asynchronous = false; - if (done) { - // This means the pull was async. Handle like - // regular async. - srcPullHandler(push, next, self)(err, x); - } - else { - if (err) { - push(err); - } - else if (x === nil) { - done = true; - } - else { - srcs.push(x); - srcsNeedPull.push(x); - } - } - }; - - while (!done) { - asynchronous = true; - self.pull(pull_cb); - - // Async behavior, record self as a src and return. - if (asynchronous) { - done = true; - srcs.unshift(self); - } - } - } - -}; -exposeMethod('merge'); - -/** - * Calls a named method on each object from the Stream - returning - * a new stream with the result of those calls. - * - * @id invoke - * @section Transforms - * @name Stream.invoke(method, args) - * @param {String} method - the method name to call - * @param {Array} args - the arguments to call the method with - * @api public - * - * _(['foo', 'bar']).invoke('toUpperCase', []) // => FOO, BAR - * - * filenames.map(readFile).sequence().invoke('toString', ['utf8']); - */ - -Stream.prototype.invoke = function (method, args) { - return this.map(function (x) { - return x[method].apply(x, args); - }); -}; -exposeMethod('invoke'); - -/** - * Takes a Stream of callback-accepting node-style functions, - * [wraps](#wrapCallback) each one into a stream-returning function, - * calls them with the arguments provided, and returns the results - * as a Stream. - * - * This can be used as a control flow shortcut and draws parallels - * with some control flow functions from [async](https://github.com/caolan/async). - * A few rough correspondences include: - * - * - `.nfcall([]).series()` to `async.series()` - * - `.nfcall([]).parallel(n)` to `async.parallelLimit(n)` - * - `.nfcall(args)` to `async.applyEach(..., args)` - * - `.nfcall(args).series()` to `async.applyEachSeries(..., args)` - * - * @id nfcall - * @section Transforms - * @name Stream.nfcall(args) - * @param {Array} args - the arguments to call each function with - * @api public - * - * _([ - * function (callback) { - * setTimeout(function () { - * callback(null, 'one'); - * }, 200); - * }, - * function (callback) { - * setTimeout(function () { - * callback(null, 'two'); - * }, 100); - * } - * ]).nfcall([]).parallel(2).toArray(function (xs) { - * // xs is ['one', 'two'] even though second function had a shorter timeout - * }); - * - * _([enableSearch, updateSchema]).nfcall(['bucket']).toArray(callback); - * // does roughly the same as - * async.applyEach([enableSearch, updateSchema], 'bucket', callback); - * - * _([ - * fs.appendFile, - * fs.appendFile - * ]).nfcall(['example.txt', 'hello']).series().toArray(function() { - * // example.txt now contains 'hellohello' - * }); - * - */ - -Stream.prototype.nfcall = function (args) { - return this.map(function (x) { - return _.wrapCallback(x).apply(x, args); - }); -}; -exposeMethod('nfcall'); - -/** - * Ensures that only one data event is push downstream (or into the buffer) - * every `ms` milliseconds, any other values are dropped. - * - * @id throttle - * @section Transforms - * @name Stream.throttle(ms) - * @param {Number} ms - the minimum milliseconds between each value - * @api public - * - * _('mousemove', document).throttle(1000); - */ - -Stream.prototype.throttle = function (ms) { - var last = 0 - ms; - return this.consume(function (err, x, push, next) { - var now = new Date().getTime(); - if (err) { - push(err); - next(); - } - else if (x === nil) { - push(null, nil); - } - else if (now - ms >= last) { - last = now; - push(null, x); - next(); - } - else { - next(); - } - }); -}; -exposeMethod('throttle'); - -/** - * Holds off pushing data events downstream until there has been no more - * data for `ms` milliseconds. Sends the last value that occurred before - * the delay, discarding all other values. - * - * @id debounce - * @section Transforms - * @name Stream.debounce(ms) - * @param {Number} ms - the milliseconds to wait before sending data - * @api public - * - * // sends last keyup event after user has stopped typing for 1 second - * $('keyup', textbox).debounce(1000); - */ - -Stream.prototype.debounce = function (ms) { - var t = null; - var nothing = {}; - var last = nothing; - - return this.consume(function (err, x, push, next) { - if (err) { - // let errors through regardless - push(err); - next(); - } - else if (x === nil) { - if (t) { - clearTimeout(t); - } - if (last !== nothing) { - push(null, last); - } - push(null, nil); - } - else { - last = x; - if (t) { - clearTimeout(t); - } - t = setTimeout(push.bind(this, null, x), ms); - next(); - } - }); -}; -exposeMethod('debounce'); - -/** - * Creates a new Stream, which when read from, only returns the last - * seen value from the source. The source stream does not experience - * back-pressure. Useful if you're using a Stream to model a changing - * property which you need to query periodically. - * - * @id latest - * @section Transforms - * @name Stream.latest() - * @api public - * - * // slowThing will always get the last known mouse position - * // when it asks for more data from the mousePosition stream - * mousePosition.latest().map(slowThing) - */ - -Stream.prototype.latest = function () { - var nothing = {}, - latest = nothing, - errors = [], - ended = false, - onValue = null; - - this.consume(function (err, x, push, next) { - if (onValue != null) { - var cb = onValue; - onValue = null; - cb(err, x); - } - - if (err) { - errors.push(err); - next(); - } - else if (x === nil) { - ended = true; - } - else { - latest = x; - next(); - } - }).resume(); - - return _(function (push, next) { - var oldErrors = errors; - errors = []; - - if (!oldErrors.length && latest === nothing && !ended) { - // We haven't gotten any data yet. We can't call next - // because that might cause the stream to call the generator - // again, resulting in an infinite loop. Thus, we stick a - // a callback to be called whenever we get a value. - onValue = function (err, x) { - push(err, x); - if (x !== nil) { - next(); - } - }; - } - else { - oldErrors.forEach(push); - if (latest !== nothing) { - push(null, latest); - } - if (ended) { - push(null, nil); - } - else { - next(); - } - } - }); -}; -exposeMethod('latest'); - -/** - * Returns values from an Object as a Stream. Reads properties - * lazily, so if you don't read from all keys on an object, not - * all properties will be read from (may have an effect where getters - * are used). - * - * @id values - * @section Objects - * @name _.values(obj) - * @param {Object} obj - the object to return values from - * @api public - * - * _.values({foo: 1, bar: 2, baz: 3}) // => 1, 2, 3 - */ - -_.values = function (obj) { - return _.keys(obj).map(function (k) { - return obj[k]; - }); -}; - -/** - * Returns keys from an Object as a Stream. - * - * @id keys - * @section Objects - * @name _.keys(obj) - * @param {Object} obj - the object to return keys from - * @api public - * - * _.keys({foo: 1, bar: 2, baz: 3}) // => 'foo', 'bar', 'baz' - */ - -_.keys = function (obj) { - var keys = []; - for (var k in obj) { - if (hasOwn.call(obj, k)) { - keys.push(k); - } - } - return _(keys); -}; - -/** - * Returns key/value pairs for an Object as a Stream. Reads properties - * lazily, so if you don't read from all keys on an object, not - * all properties will be read from (may have an effect where getters - * are used). - * - * @id pairs - * @section Objects - * @name _.pairs(obj) - * @param {Object} obj - the object to return key/value pairs from - * @api public - * - * _.pairs({foo: 1, bar: 2}) // => ['foo', 1], ['bar', 2] - */ - -_.pairs = function (obj) { - return _.keys(obj).map(function (k) { - return [k, obj[k]]; - }); -}; - -/** - * Extends one object with the properties of another. **Note:** The - * arguments are in the reverse order of other libraries such as - * underscore. This is so it follows the convention of other functions in - * this library and so you can more meaningfully partially apply it. - * - * @id extend - * @section Objects - * @name _.extend(a, b) - * @param {Object} a - the properties to extend b with - * @param {Object} b - the original object to extend - * @api public - * - * _.extend({name: 'bar'}, {name: 'foo', price: 20}) - * // => {name: 'bar', price: 20} - * - * // example of partial application - * var publish = _.extend({published: true}); - * - * publish({title: 'test post'}) - * // => {title: 'test post', published: true} - */ - -_.extend = _.curry(function (extensions, target) { - for (var k in extensions) { - if (hasOwn.call(extensions, k)) { - target[k] = extensions[k]; - } - } - return target; -}); - -/** - * Returns a property from an object. - * - * @id get - * @section Objects - * @name _.get(prop, obj) - * @param {String} prop - the property to return - * @param {Object} obj - the object to read properties from - * @api public - * - * var obj = {foo: 'bar', baz: 123}; - * _.get('foo', obj) // => 'bar' - * - * // making use of partial application - * var posts = [ - * {title: 'one'}, - * {title: 'two'}, - * {title: 'three'} - * ]; - * - * _(posts).map(_.get('title')) // => 'one', 'two', 'three' - */ - -_.get = _.curry(function (prop, obj) { - return obj[prop]; -}); - -/** - * Updates a property on an object, returning the updated object. - * - * @id set - * @section Objects - * @name _.set(prop, value, obj) - * @param {String} prop - the property to return - * @param value - the value to set the property to - * @param {Object} obj - the object to set properties on - * @api public - * - * var obj = {foo: 'bar', baz: 123}; - * _.set('foo', 'wheeee', obj) // => {foo: 'wheeee', baz: 123} - * - * // making use of partial application - * var publish = _.set('published', true); - * - * publish({title: 'example'}) // => {title: 'example', published: true} - */ - -_.set = _.curry(function (prop, val, obj) { - obj[prop] = val; - return obj; -}); - -/** - * Logs values to the console, a simple wrapper around `console.log` that - * it suitable for passing to other functions by reference without having to - * call `bind`. - * - * @id log - * @section Utils - * @name _.log(args..) - * @api public - * - * _.log('Hello, world!'); - * - * _([1, 2, 3, 4]).each(_.log); - */ - -_.log = function () { - console.log.apply(console, arguments); -}; - -/** - * Wraps a node-style async function which accepts a callback, transforming - * it to a function which accepts the same arguments minus the callback and - * returns a Highland Stream instead. Only the first argument to the - * callback (or an error) will be pushed onto the Stream. - * - * @id wrapCallback - * @section Utils - * @name _.wrapCallback(f) - * @param {Function} f - the node-style function to wrap - * @api public - * - * var fs = require('fs'); - * - * var readFile = _.wrapCallback(fs.readFile); - * - * readFile('example.txt').apply(function (data) { - * // data is now the contents of example.txt - * }); - */ - -_.wrapCallback = function (f) { - return function () { - var args = slice.call(arguments); - return _(function (push) { - var cb = function (err, x) { - if (err) { - push(err); - } - else { - push(null, x); - } - push(null, nil); - }; - f.apply(null, args.concat([cb])); - }); - }; -}; - -/** - * Add two values. Can be partially applied. - * - * @id add - * @section Operators - * @name _.add(a, b) - * @api public - * - * _.add(1, 2) === 3 - * _.add(1)(5) === 6 - */ - -_.add = _.curry(function (a, b) { - return a + b; -}); - -/** - * Perform logical negation on a value. If `x` is truthy then returns false, - * otherwise returns true. - * - * @id not - * @section Operators - * @name _.not(x) - * @param x - the value to negate - * @api public - * - * _.not(true) // => false - * _.not(false) // => true - */ - -_.not = function (x) { - return !x; -}; - -}).call(this,_dereq_("/home/jwagner/gh-highland/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"/home/jwagner/gh-highland/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":7,"events":5,"string_decoder":8,"util":10}],2:[function(_dereq_,module,exports){ -/*! - * The buffer module from node.js, for the browser. - * - * @author Feross Aboukhadijeh - * @license MIT - */ - -var base64 = _dereq_('base64-js') -var ieee754 = _dereq_('ieee754') - -exports.Buffer = Buffer -exports.SlowBuffer = Buffer -exports.INSPECT_MAX_BYTES = 50 -Buffer.poolSize = 8192 - -/** - * If `Buffer._useTypedArrays`: - * === true Use Uint8Array implementation (fastest) - * === false Use Object implementation (compatible down to IE6) - */ -Buffer._useTypedArrays = (function () { - // Detect if browser supports Typed Arrays. Supported browsers are IE 10+, Firefox 4+, - // Chrome 7+, Safari 5.1+, Opera 11.6+, iOS 4.2+. If the browser does not support adding - // properties to `Uint8Array` instances, then that's the same as no `Uint8Array` support - // because we need to be able to add all the node Buffer API methods. This is an issue - // in Firefox 4-29. Now fixed: https://bugzilla.mozilla.org/show_bug.cgi?id=695438 - try { - var buf = new ArrayBuffer(0) - var arr = new Uint8Array(buf) - arr.foo = function () { return 42 } - return 42 === arr.foo() && - typeof arr.subarray === 'function' // Chrome 9-10 lack `subarray` - } catch (e) { - return false - } -})() - -/** - * Class: Buffer - * ============= - * - * The Buffer constructor returns instances of `Uint8Array` that are augmented - * with function properties for all the node `Buffer` API functions. We use - * `Uint8Array` so that square bracket notation works as expected -- it returns - * a single octet. - * - * By augmenting the instances, we can avoid modifying the `Uint8Array` - * prototype. - */ -function Buffer (subject, encoding, noZero) { - if (!(this instanceof Buffer)) - return new Buffer(subject, encoding, noZero) - - var type = typeof subject - - // Workaround: node's base64 implementation allows for non-padded strings - // while base64-js does not. - if (encoding === 'base64' && type === 'string') { - subject = stringtrim(subject) - while (subject.length % 4 !== 0) { - subject = subject + '=' - } - } - - // Find the length - var length - if (type === 'number') - length = coerce(subject) - else if (type === 'string') - length = Buffer.byteLength(subject, encoding) - else if (type === 'object') - length = coerce(subject.length) // assume that object is array-like - else - throw new Error('First argument needs to be a number, array or string.') - - var buf - if (Buffer._useTypedArrays) { - // Preferred: Return an augmented `Uint8Array` instance for best performance - buf = Buffer._augment(new Uint8Array(length)) - } else { - // Fallback: Return THIS instance of Buffer (created by `new`) - buf = this - buf.length = length - buf._isBuffer = true - } - - var i - if (Buffer._useTypedArrays && typeof subject.byteLength === 'number') { - // Speed optimization -- use set if we're copying from a typed array - buf._set(subject) - } else if (isArrayish(subject)) { - // Treat array-ish objects as a byte array - for (i = 0; i < length; i++) { - if (Buffer.isBuffer(subject)) - buf[i] = subject.readUInt8(i) - else - buf[i] = subject[i] - } - } else if (type === 'string') { - buf.write(subject, 0, encoding) - } else if (type === 'number' && !Buffer._useTypedArrays && !noZero) { - for (i = 0; i < length; i++) { - buf[i] = 0 - } - } - - return buf -} - -// STATIC METHODS -// ============== - -Buffer.isEncoding = function (encoding) { - switch (String(encoding).toLowerCase()) { - case 'hex': - case 'utf8': - case 'utf-8': - case 'ascii': - case 'binary': - case 'base64': - case 'raw': - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - return true - default: - return false - } -} - -Buffer.isBuffer = function (b) { - return !!(b !== null && b !== undefined && b._isBuffer) -} - -Buffer.byteLength = function (str, encoding) { - var ret - str = str + '' - switch (encoding || 'utf8') { - case 'hex': - ret = str.length / 2 - break - case 'utf8': - case 'utf-8': - ret = utf8ToBytes(str).length - break - case 'ascii': - case 'binary': - case 'raw': - ret = str.length - break - case 'base64': - ret = base64ToBytes(str).length - break - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - ret = str.length * 2 - break - default: - throw new Error('Unknown encoding') - } - return ret -} - -Buffer.concat = function (list, totalLength) { - assert(isArray(list), 'Usage: Buffer.concat(list, [totalLength])\n' + - 'list should be an Array.') - - if (list.length === 0) { - return new Buffer(0) - } else if (list.length === 1) { - return list[0] - } - - var i - if (typeof totalLength !== 'number') { - totalLength = 0 - for (i = 0; i < list.length; i++) { - totalLength += list[i].length - } - } - - var buf = new Buffer(totalLength) - var pos = 0 - for (i = 0; i < list.length; i++) { - var item = list[i] - item.copy(buf, pos) - pos += item.length - } - return buf -} - -// BUFFER INSTANCE METHODS -// ======================= - -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 - } - } - - // must be an even number of digits - var strLen = string.length - assert(strLen % 2 === 0, 'Invalid hex string') - - if (length > strLen / 2) { - length = strLen / 2 - } - for (var i = 0; i < length; i++) { - var byte = parseInt(string.substr(i * 2, 2), 16) - assert(!isNaN(byte), 'Invalid hex string') - buf[offset + i] = byte - } - Buffer._charsWritten = i * 2 - return i -} - -function _utf8Write (buf, string, offset, length) { - var charsWritten = Buffer._charsWritten = - blitBuffer(utf8ToBytes(string), buf, offset, length) - return charsWritten -} - -function _asciiWrite (buf, string, offset, length) { - var charsWritten = Buffer._charsWritten = - blitBuffer(asciiToBytes(string), buf, offset, length) - return charsWritten -} - -function _binaryWrite (buf, string, offset, length) { - return _asciiWrite(buf, string, offset, length) -} - -function _base64Write (buf, string, offset, length) { - var charsWritten = Buffer._charsWritten = - blitBuffer(base64ToBytes(string), buf, offset, length) - return charsWritten -} - -function _utf16leWrite (buf, string, offset, length) { - var charsWritten = Buffer._charsWritten = - blitBuffer(utf16leToBytes(string), buf, offset, length) - return charsWritten -} - -Buffer.prototype.write = function (string, offset, length, encoding) { - // Support both (string, offset, length, encoding) - // and the legacy (string, encoding, offset, length) - if (isFinite(offset)) { - if (!isFinite(length)) { - encoding = length - length = undefined - } - } else { // legacy - var swap = encoding - encoding = offset - offset = length - length = swap - } - - offset = Number(offset) || 0 - var remaining = this.length - offset - if (!length) { - length = remaining - } else { - length = Number(length) - if (length > remaining) { - length = remaining - } - } - encoding = String(encoding || 'utf8').toLowerCase() - - var ret - switch (encoding) { - case 'hex': - ret = _hexWrite(this, string, offset, length) - break - case 'utf8': - case 'utf-8': - ret = _utf8Write(this, string, offset, length) - break - case 'ascii': - ret = _asciiWrite(this, string, offset, length) - break - case 'binary': - ret = _binaryWrite(this, string, offset, length) - break - case 'base64': - ret = _base64Write(this, string, offset, length) - break - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - ret = _utf16leWrite(this, string, offset, length) - break - default: - throw new Error('Unknown encoding') - } - return ret -} - -Buffer.prototype.toString = function (encoding, start, end) { - var self = this - - encoding = String(encoding || 'utf8').toLowerCase() - start = Number(start) || 0 - end = (end !== undefined) - ? Number(end) - : end = self.length - - // Fastpath empty strings - if (end === start) - return '' - - var ret - switch (encoding) { - case 'hex': - ret = _hexSlice(self, start, end) - break - case 'utf8': - case 'utf-8': - ret = _utf8Slice(self, start, end) - break - case 'ascii': - ret = _asciiSlice(self, start, end) - break - case 'binary': - ret = _binarySlice(self, start, end) - break - case 'base64': - ret = _base64Slice(self, start, end) - break - case 'ucs2': - case 'ucs-2': - case 'utf16le': - case 'utf-16le': - ret = _utf16leSlice(self, start, end) - break - default: - throw new Error('Unknown encoding') - } - return ret -} - -Buffer.prototype.toJSON = function () { - return { - type: 'Buffer', - data: Array.prototype.slice.call(this._arr || this, 0) - } -} - -// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) -Buffer.prototype.copy = function (target, target_start, start, end) { - var source = this - - if (!start) start = 0 - if (!end && end !== 0) end = this.length - if (!target_start) target_start = 0 - - // Copy 0 bytes; we're done - if (end === start) return - if (target.length === 0 || source.length === 0) return - - // Fatal error conditions - assert(end >= start, 'sourceEnd < sourceStart') - assert(target_start >= 0 && target_start < target.length, - 'targetStart out of bounds') - assert(start >= 0 && start < source.length, 'sourceStart out of bounds') - assert(end >= 0 && end <= source.length, 'sourceEnd out of bounds') - - // Are we oob? - if (end > this.length) - end = this.length - if (target.length - target_start < end - start) - end = target.length - target_start + start - - var len = end - start - - if (len < 100 || !Buffer._useTypedArrays) { - for (var i = 0; i < len; i++) - target[i + target_start] = this[i + start] - } else { - target._set(this.subarray(start, start + len), target_start) - } -} - -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) { - var res = '' - var tmp = '' - end = Math.min(buf.length, end) - - for (var i = start; i < end; i++) { - if (buf[i] <= 0x7F) { - res += decodeUtf8Char(tmp) + String.fromCharCode(buf[i]) - tmp = '' - } else { - tmp += '%' + buf[i].toString(16) - } - } - - return res + decodeUtf8Char(tmp) -} - -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]) - return ret -} - -function _binarySlice (buf, start, end) { - return _asciiSlice(buf, start, end) -} - -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 (start, end) { - var len = this.length - start = clamp(start, len, 0) - end = clamp(end, len, len) - - if (Buffer._useTypedArrays) { - return Buffer._augment(this.subarray(start, end)) - } else { - var sliceLen = end - start - var newBuf = new Buffer(sliceLen, undefined, true) - for (var i = 0; i < sliceLen; i++) { - newBuf[i] = this[i + start] - } - return newBuf - } -} - -// `get` will be removed in Node 0.13+ -Buffer.prototype.get = function (offset) { - console.log('.get() is deprecated. Access using array indexes instead.') - return this.readUInt8(offset) -} - -// `set` will be removed in Node 0.13+ -Buffer.prototype.set = function (v, offset) { - console.log('.set() is deprecated. Access using array indexes instead.') - return this.writeUInt8(v, offset) -} - -Buffer.prototype.readUInt8 = function (offset, noAssert) { - if (!noAssert) { - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset < this.length, 'Trying to read beyond buffer length') - } - - if (offset >= this.length) - return - - return this[offset] -} - -function _readUInt16 (buf, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset + 1 < buf.length, 'Trying to read beyond buffer length') - } - - var len = buf.length - if (offset >= len) - return - - var val - if (littleEndian) { - val = buf[offset] - if (offset + 1 < len) - val |= buf[offset + 1] << 8 - } else { - val = buf[offset] << 8 - if (offset + 1 < len) - val |= buf[offset + 1] - } - return val -} - -Buffer.prototype.readUInt16LE = function (offset, noAssert) { - return _readUInt16(this, offset, true, noAssert) -} - -Buffer.prototype.readUInt16BE = function (offset, noAssert) { - return _readUInt16(this, offset, false, noAssert) -} - -function _readUInt32 (buf, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset + 3 < buf.length, 'Trying to read beyond buffer length') - } - - var len = buf.length - if (offset >= len) - return - - var val - if (littleEndian) { - if (offset + 2 < len) - val = buf[offset + 2] << 16 - if (offset + 1 < len) - val |= buf[offset + 1] << 8 - val |= buf[offset] - if (offset + 3 < len) - val = val + (buf[offset + 3] << 24 >>> 0) - } else { - if (offset + 1 < len) - val = buf[offset + 1] << 16 - if (offset + 2 < len) - val |= buf[offset + 2] << 8 - if (offset + 3 < len) - val |= buf[offset + 3] - val = val + (buf[offset] << 24 >>> 0) - } - return val -} - -Buffer.prototype.readUInt32LE = function (offset, noAssert) { - return _readUInt32(this, offset, true, noAssert) -} - -Buffer.prototype.readUInt32BE = function (offset, noAssert) { - return _readUInt32(this, offset, false, noAssert) -} - -Buffer.prototype.readInt8 = function (offset, noAssert) { - if (!noAssert) { - assert(offset !== undefined && offset !== null, - 'missing offset') - assert(offset < this.length, 'Trying to read beyond buffer length') - } - - if (offset >= this.length) - return - - var neg = this[offset] & 0x80 - if (neg) - return (0xff - this[offset] + 1) * -1 - else - return this[offset] -} - -function _readInt16 (buf, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset + 1 < buf.length, 'Trying to read beyond buffer length') - } - - var len = buf.length - if (offset >= len) - return - - var val = _readUInt16(buf, offset, littleEndian, true) - var neg = val & 0x8000 - if (neg) - return (0xffff - val + 1) * -1 - else - return val -} - -Buffer.prototype.readInt16LE = function (offset, noAssert) { - return _readInt16(this, offset, true, noAssert) -} - -Buffer.prototype.readInt16BE = function (offset, noAssert) { - return _readInt16(this, offset, false, noAssert) -} - -function _readInt32 (buf, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset + 3 < buf.length, 'Trying to read beyond buffer length') - } - - var len = buf.length - if (offset >= len) - return - - var val = _readUInt32(buf, offset, littleEndian, true) - var neg = val & 0x80000000 - if (neg) - return (0xffffffff - val + 1) * -1 - else - return val -} - -Buffer.prototype.readInt32LE = function (offset, noAssert) { - return _readInt32(this, offset, true, noAssert) -} - -Buffer.prototype.readInt32BE = function (offset, noAssert) { - return _readInt32(this, offset, false, noAssert) -} - -function _readFloat (buf, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset + 3 < buf.length, 'Trying to read beyond buffer length') - } - - return ieee754.read(buf, offset, littleEndian, 23, 4) -} - -Buffer.prototype.readFloatLE = function (offset, noAssert) { - return _readFloat(this, offset, true, noAssert) -} - -Buffer.prototype.readFloatBE = function (offset, noAssert) { - return _readFloat(this, offset, false, noAssert) -} - -function _readDouble (buf, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset + 7 < buf.length, 'Trying to read beyond buffer length') - } - - return ieee754.read(buf, offset, littleEndian, 52, 8) -} - -Buffer.prototype.readDoubleLE = function (offset, noAssert) { - return _readDouble(this, offset, true, noAssert) -} - -Buffer.prototype.readDoubleBE = function (offset, noAssert) { - return _readDouble(this, offset, false, noAssert) -} - -Buffer.prototype.writeUInt8 = function (value, offset, noAssert) { - if (!noAssert) { - assert(value !== undefined && value !== null, 'missing value') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset < this.length, 'trying to write beyond buffer length') - verifuint(value, 0xff) - } - - if (offset >= this.length) return - - this[offset] = value -} - -function _writeUInt16 (buf, value, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(value !== undefined && value !== null, 'missing value') - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset + 1 < buf.length, 'trying to write beyond buffer length') - verifuint(value, 0xffff) - } - - var len = buf.length - if (offset >= len) - return - - for (var i = 0, j = Math.min(len - offset, 2); i < j; i++) { - buf[offset + i] = - (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> - (littleEndian ? i : 1 - i) * 8 - } -} - -Buffer.prototype.writeUInt16LE = function (value, offset, noAssert) { - _writeUInt16(this, value, offset, true, noAssert) -} - -Buffer.prototype.writeUInt16BE = function (value, offset, noAssert) { - _writeUInt16(this, value, offset, false, noAssert) -} - -function _writeUInt32 (buf, value, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(value !== undefined && value !== null, 'missing value') - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset + 3 < buf.length, 'trying to write beyond buffer length') - verifuint(value, 0xffffffff) - } - - var len = buf.length - if (offset >= len) - return - - for (var i = 0, j = Math.min(len - offset, 4); i < j; i++) { - buf[offset + i] = - (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff - } -} - -Buffer.prototype.writeUInt32LE = function (value, offset, noAssert) { - _writeUInt32(this, value, offset, true, noAssert) -} - -Buffer.prototype.writeUInt32BE = function (value, offset, noAssert) { - _writeUInt32(this, value, offset, false, noAssert) -} - -Buffer.prototype.writeInt8 = function (value, offset, noAssert) { - if (!noAssert) { - assert(value !== undefined && value !== null, 'missing value') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset < this.length, 'Trying to write beyond buffer length') - verifsint(value, 0x7f, -0x80) - } - - if (offset >= this.length) - return - - if (value >= 0) - this.writeUInt8(value, offset, noAssert) - else - this.writeUInt8(0xff + value + 1, offset, noAssert) -} - -function _writeInt16 (buf, value, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(value !== undefined && value !== null, 'missing value') - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset + 1 < buf.length, 'Trying to write beyond buffer length') - verifsint(value, 0x7fff, -0x8000) - } - - var len = buf.length - if (offset >= len) - return - - if (value >= 0) - _writeUInt16(buf, value, offset, littleEndian, noAssert) - else - _writeUInt16(buf, 0xffff + value + 1, offset, littleEndian, noAssert) -} - -Buffer.prototype.writeInt16LE = function (value, offset, noAssert) { - _writeInt16(this, value, offset, true, noAssert) -} - -Buffer.prototype.writeInt16BE = function (value, offset, noAssert) { - _writeInt16(this, value, offset, false, noAssert) -} - -function _writeInt32 (buf, value, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(value !== undefined && value !== null, 'missing value') - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset + 3 < buf.length, 'Trying to write beyond buffer length') - verifsint(value, 0x7fffffff, -0x80000000) - } - - var len = buf.length - if (offset >= len) - return - - if (value >= 0) - _writeUInt32(buf, value, offset, littleEndian, noAssert) - else - _writeUInt32(buf, 0xffffffff + value + 1, offset, littleEndian, noAssert) -} - -Buffer.prototype.writeInt32LE = function (value, offset, noAssert) { - _writeInt32(this, value, offset, true, noAssert) -} - -Buffer.prototype.writeInt32BE = function (value, offset, noAssert) { - _writeInt32(this, value, offset, false, noAssert) -} - -function _writeFloat (buf, value, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(value !== undefined && value !== null, 'missing value') - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset + 3 < buf.length, 'Trying to write beyond buffer length') - verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38) - } - - var len = buf.length - if (offset >= len) - return - - ieee754.write(buf, value, offset, littleEndian, 23, 4) -} - -Buffer.prototype.writeFloatLE = function (value, offset, noAssert) { - _writeFloat(this, value, offset, true, noAssert) -} - -Buffer.prototype.writeFloatBE = function (value, offset, noAssert) { - _writeFloat(this, value, offset, false, noAssert) -} - -function _writeDouble (buf, value, offset, littleEndian, noAssert) { - if (!noAssert) { - assert(value !== undefined && value !== null, 'missing value') - assert(typeof littleEndian === 'boolean', 'missing or invalid endian') - assert(offset !== undefined && offset !== null, 'missing offset') - assert(offset + 7 < buf.length, - 'Trying to write beyond buffer length') - verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308) - } - - var len = buf.length - if (offset >= len) - return - - ieee754.write(buf, value, offset, littleEndian, 52, 8) -} - -Buffer.prototype.writeDoubleLE = function (value, offset, noAssert) { - _writeDouble(this, value, offset, true, noAssert) -} - -Buffer.prototype.writeDoubleBE = function (value, offset, noAssert) { - _writeDouble(this, value, offset, false, noAssert) -} - -// fill(value, start=0, end=buffer.length) -Buffer.prototype.fill = function (value, start, end) { - if (!value) value = 0 - if (!start) start = 0 - if (!end) end = this.length - - if (typeof value === 'string') { - value = value.charCodeAt(0) - } - - assert(typeof value === 'number' && !isNaN(value), 'value is not a number') - assert(end >= start, 'end < start') - - // Fill 0 bytes; we're done - if (end === start) return - if (this.length === 0) return - - assert(start >= 0 && start < this.length, 'start out of bounds') - assert(end >= 0 && end <= this.length, 'end out of bounds') - - for (var i = start; i < end; i++) { - this[i] = value - } -} - -Buffer.prototype.inspect = function () { - var out = [] - var len = this.length - for (var i = 0; i < len; i++) { - out[i] = toHex(this[i]) - if (i === exports.INSPECT_MAX_BYTES) { - out[i + 1] = '...' - break - } - } - return '' -} - -/** - * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance. - * Added in Node 0.12. Only available in browsers that support ArrayBuffer. - */ -Buffer.prototype.toArrayBuffer = function () { - if (typeof Uint8Array !== 'undefined') { - if (Buffer._useTypedArrays) { - return (new Buffer(this)).buffer - } else { - var buf = new Uint8Array(this.length) - for (var i = 0, len = buf.length; i < len; i += 1) - buf[i] = this[i] - return buf.buffer - } - } else { - throw new Error('Buffer.toArrayBuffer not supported in this browser') - } -} - -// HELPER FUNCTIONS -// ================ - -function stringtrim (str) { - if (str.trim) return str.trim() - return str.replace(/^\s+|\s+$/g, '') -} - -var BP = Buffer.prototype - -/** - * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods - */ -Buffer._augment = function (arr) { - arr._isBuffer = true - - // save reference to original Uint8Array get/set methods before overwriting - arr._get = arr.get - arr._set = arr.set - - // deprecated, will be removed in node 0.13+ - arr.get = BP.get - arr.set = BP.set - - arr.write = BP.write - arr.toString = BP.toString - arr.toLocaleString = BP.toString - arr.toJSON = BP.toJSON - arr.copy = BP.copy - arr.slice = BP.slice - arr.readUInt8 = BP.readUInt8 - arr.readUInt16LE = BP.readUInt16LE - arr.readUInt16BE = BP.readUInt16BE - arr.readUInt32LE = BP.readUInt32LE - arr.readUInt32BE = BP.readUInt32BE - arr.readInt8 = BP.readInt8 - arr.readInt16LE = BP.readInt16LE - arr.readInt16BE = BP.readInt16BE - arr.readInt32LE = BP.readInt32LE - arr.readInt32BE = BP.readInt32BE - arr.readFloatLE = BP.readFloatLE - arr.readFloatBE = BP.readFloatBE - arr.readDoubleLE = BP.readDoubleLE - arr.readDoubleBE = BP.readDoubleBE - arr.writeUInt8 = BP.writeUInt8 - arr.writeUInt16LE = BP.writeUInt16LE - arr.writeUInt16BE = BP.writeUInt16BE - arr.writeUInt32LE = BP.writeUInt32LE - arr.writeUInt32BE = BP.writeUInt32BE - arr.writeInt8 = BP.writeInt8 - arr.writeInt16LE = BP.writeInt16LE - arr.writeInt16BE = BP.writeInt16BE - arr.writeInt32LE = BP.writeInt32LE - arr.writeInt32BE = BP.writeInt32BE - arr.writeFloatLE = BP.writeFloatLE - arr.writeFloatBE = BP.writeFloatBE - arr.writeDoubleLE = BP.writeDoubleLE - arr.writeDoubleBE = BP.writeDoubleBE - arr.fill = BP.fill - arr.inspect = BP.inspect - arr.toArrayBuffer = BP.toArrayBuffer - - return arr -} - -// slice(start, end) -function clamp (index, len, defaultValue) { - if (typeof index !== 'number') return defaultValue - index = ~~index; // Coerce to integer. - if (index >= len) return len - if (index >= 0) return index - index += len - if (index >= 0) return index - return 0 -} - -function coerce (length) { - // Coerce length to a number (possibly NaN), round up - // in case it's fractional (e.g. 123.456) then do a - // double negate to coerce a NaN to 0. Easy, right? - length = ~~Math.ceil(+length) - return length < 0 ? 0 : length -} - -function isArray (subject) { - return (Array.isArray || function (subject) { - return Object.prototype.toString.call(subject) === '[object Array]' - })(subject) -} - -function isArrayish (subject) { - return isArray(subject) || Buffer.isBuffer(subject) || - subject && typeof subject === 'object' && - typeof subject.length === 'number' -} - -function toHex (n) { - if (n < 16) return '0' + n.toString(16) - return n.toString(16) -} - -function utf8ToBytes (str) { - var byteArray = [] - for (var i = 0; i < str.length; i++) { - var b = str.charCodeAt(i) - if (b <= 0x7F) - byteArray.push(str.charCodeAt(i)) - else { - var start = i - if (b >= 0xD800 && b <= 0xDFFF) i++ - var h = encodeURIComponent(str.slice(start, i+1)).substr(1).split('%') - for (var j = 0; j < h.length; j++) - byteArray.push(parseInt(h[j], 16)) - } - } - return byteArray -} - -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) { - var c, hi, lo - var byteArray = [] - for (var i = 0; i < str.length; i++) { - c = str.charCodeAt(i) - hi = c >> 8 - lo = c % 256 - byteArray.push(lo) - byteArray.push(hi) - } - - return byteArray -} - -function base64ToBytes (str) { - return base64.toByteArray(str) -} - -function blitBuffer (src, dst, offset, length) { - var pos - for (var i = 0; i < length; i++) { - if ((i + offset >= dst.length) || (i >= src.length)) - break - dst[i + offset] = src[i] - } - return i -} - -function decodeUtf8Char (str) { - try { - return decodeURIComponent(str) - } catch (err) { - return String.fromCharCode(0xFFFD) // UTF 8 invalid char - } -} - -/* - * We have to make sure that the value is a valid integer. This means that it - * is non-negative. It has no fractional component and that it does not - * exceed the maximum allowed value. - */ -function verifuint (value, max) { - assert(typeof value === 'number', 'cannot write a non-number as a number') - assert(value >= 0, 'specified a negative value for writing an unsigned value') - assert(value <= max, 'value is larger than maximum value for type') - assert(Math.floor(value) === value, 'value has a fractional component') -} - -function verifsint (value, max, min) { - assert(typeof value === 'number', 'cannot write a non-number as a number') - assert(value <= max, 'value larger than maximum allowed value') - assert(value >= min, 'value smaller than minimum allowed value') - assert(Math.floor(value) === value, 'value has a fractional component') -} - -function verifIEEE754 (value, max, min) { - assert(typeof value === 'number', 'cannot write a non-number as a number') - assert(value <= max, 'value larger than maximum allowed value') - assert(value >= min, 'value smaller than minimum allowed value') -} - -function assert (test, message) { - if (!test) throw new Error(message || 'Failed assertion') -} - -},{"base64-js":3,"ieee754":4}],3:[function(_dereq_,module,exports){ -var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; - -;(function (exports) { - 'use strict'; - - var Arr = (typeof Uint8Array !== 'undefined') - ? Uint8Array - : Array - - var PLUS = '+'.charCodeAt(0) - var SLASH = '/'.charCodeAt(0) - var NUMBER = '0'.charCodeAt(0) - var LOWER = 'a'.charCodeAt(0) - var UPPER = 'A'.charCodeAt(0) - - function decode (elt) { - var code = elt.charCodeAt(0) - if (code === PLUS) - return 62 // '+' - if (code === SLASH) - return 63 // '/' - if (code < NUMBER) - return -1 //no match - if (code < NUMBER + 10) - return code - NUMBER + 26 + 26 - if (code < UPPER + 26) - return code - UPPER - if (code < LOWER + 26) - return code - LOWER + 26 - } - - function b64ToByteArray (b64) { - var i, j, l, tmp, placeHolders, arr - - if (b64.length % 4 > 0) { - throw new Error('Invalid string. Length must be a multiple of 4') - } - - // the number of equal signs (place holders) - // if there are two placeholders, than the two characters before it - // represent one byte - // if there is only one, then the three characters before it represent 2 bytes - // this is just a cheap hack to not do indexOf twice - var len = b64.length - placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0 - - // base64 is 4/3 + up to two characters of the original data - arr = new Arr(b64.length * 3 / 4 - placeHolders) - - // if there are placeholders, only get up to the last complete 4 chars - l = placeHolders > 0 ? b64.length - 4 : b64.length - - var L = 0 - - function push (v) { - arr[L++] = v - } - - for (i = 0, j = 0; i < l; i += 4, j += 3) { - tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3)) - push((tmp & 0xFF0000) >> 16) - push((tmp & 0xFF00) >> 8) - push(tmp & 0xFF) - } - - if (placeHolders === 2) { - tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4) - push(tmp & 0xFF) - } else if (placeHolders === 1) { - tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2) - push((tmp >> 8) & 0xFF) - push(tmp & 0xFF) - } - - return arr - } - - function uint8ToBase64 (uint8) { - var i, - extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes - output = "", - temp, length - - function encode (num) { - return lookup.charAt(num) - } - - function tripletToBase64 (num) { - return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F) - } - - // go through the array every three bytes, we'll deal with trailing stuff later - for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) { - temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) - output += tripletToBase64(temp) - } - - // pad the end with zeros, but make sure to not forget the extra bytes - switch (extraBytes) { - case 1: - temp = uint8[uint8.length - 1] - output += encode(temp >> 2) - output += encode((temp << 4) & 0x3F) - output += '==' - break - case 2: - temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]) - output += encode(temp >> 10) - output += encode((temp >> 4) & 0x3F) - output += encode((temp << 2) & 0x3F) - output += '=' - break - } - - return output - } - - exports.toByteArray = b64ToByteArray - exports.fromByteArray = uint8ToBase64 -}(typeof exports === 'undefined' ? (this.base64js = {}) : exports)) - -},{}],4:[function(_dereq_,module,exports){ -exports.read = function(buffer, offset, isLE, mLen, nBytes) { - var e, m, - eLen = nBytes * 8 - mLen - 1, - eMax = (1 << eLen) - 1, - eBias = eMax >> 1, - nBits = -7, - i = isLE ? (nBytes - 1) : 0, - d = isLE ? -1 : 1, - 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, - eLen = nBytes * 8 - mLen - 1, - eMax = (1 << eLen) - 1, - eBias = eMax >> 1, - rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0), - i = isLE ? 0 : (nBytes - 1), - d = isLE ? 1 : -1, - 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; -}; - -},{}],5:[function(_dereq_,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. - -function EventEmitter() { - this._events = this._events || {}; - 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. -EventEmitter.defaultMaxListeners = 10; - -// 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(n) { - if (!isNumber(n) || n < 0 || isNaN(n)) - throw TypeError('n must be a positive number'); - this._maxListeners = n; - return this; -}; - -EventEmitter.prototype.emit = function(type) { - var er, handler, len, args, i, listeners; - - if (!this._events) - this._events = {}; - - // If there is no 'error' event listener then throw. - if (type === 'error') { - if (!this._events.error || - (isObject(this._events.error) && !this._events.error.length)) { - er = arguments[1]; - if (er instanceof Error) { - throw er; // Unhandled 'error' event - } - throw TypeError('Uncaught, unspecified "error" event.'); - } - } - - handler = this._events[type]; - - if (isUndefined(handler)) - return false; - - if (isFunction(handler)) { - switch (arguments.length) { - // fast cases - case 1: - handler.call(this); - break; - case 2: - handler.call(this, arguments[1]); - break; - case 3: - handler.call(this, arguments[1], arguments[2]); - break; - // slower - default: - len = arguments.length; - args = new Array(len - 1); - for (i = 1; i < len; i++) - args[i - 1] = arguments[i]; - handler.apply(this, args); - } - } else if (isObject(handler)) { - len = arguments.length; - args = new Array(len - 1); - for (i = 1; i < len; i++) - args[i - 1] = arguments[i]; - - listeners = handler.slice(); - len = listeners.length; - for (i = 0; i < len; i++) - listeners[i].apply(this, args); - } - - return true; -}; - -EventEmitter.prototype.addListener = function(type, listener) { - var m; - - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - if (!this._events) - this._events = {}; - - // To avoid recursion in the case that type === "newListener"! Before - // adding it to the listeners, first emit "newListener". - if (this._events.newListener) - this.emit('newListener', type, - isFunction(listener.listener) ? - listener.listener : listener); - - if (!this._events[type]) - // Optimize the case of one listener. Don't need the extra array object. - this._events[type] = listener; - else if (isObject(this._events[type])) - // If we've already got an array, just append. - this._events[type].push(listener); - else - // Adding the second element, need to change to array. - this._events[type] = [this._events[type], listener]; - - // Check for listener leak - if (isObject(this._events[type]) && !this._events[type].warned) { - var m; - if (!isUndefined(this._maxListeners)) { - m = this._maxListeners; - } else { - m = EventEmitter.defaultMaxListeners; - } - - if (m && m > 0 && this._events[type].length > m) { - this._events[type].warned = true; - console.error('(node) warning: possible EventEmitter memory ' + - 'leak detected. %d listeners added. ' + - 'Use emitter.setMaxListeners() to increase limit.', - this._events[type].length); - if (typeof console.trace === 'function') { - // not supported in IE 10 - console.trace(); - } - } - } - - return this; -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -EventEmitter.prototype.once = function(type, listener) { - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - var fired = false; - - function g() { - this.removeListener(type, g); - - if (!fired) { - fired = true; - listener.apply(this, arguments); - } - } - - g.listener = listener; - this.on(type, g); - - return this; -}; - -// emits a 'removeListener' event iff the listener was removed -EventEmitter.prototype.removeListener = function(type, listener) { - var list, position, length, i; - - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - if (!this._events || !this._events[type]) - return this; - - list = this._events[type]; - length = list.length; - position = -1; - - if (list === listener || - (isFunction(list.listener) && list.listener === listener)) { - delete this._events[type]; - if (this._events.removeListener) - this.emit('removeListener', type, listener); - - } else if (isObject(list)) { - for (i = length; i-- > 0;) { - if (list[i] === listener || - (list[i].listener && list[i].listener === listener)) { - position = i; - break; - } - } - - if (position < 0) - return this; - - if (list.length === 1) { - list.length = 0; - delete this._events[type]; - } else { - list.splice(position, 1); - } - - if (this._events.removeListener) - this.emit('removeListener', type, listener); - } - - return this; -}; - -EventEmitter.prototype.removeAllListeners = function(type) { - var key, listeners; - - if (!this._events) - return this; - - // not listening for removeListener, no need to emit - if (!this._events.removeListener) { - if (arguments.length === 0) - this._events = {}; - else if (this._events[type]) - delete this._events[type]; - return this; - } - - // emit removeListener for all listeners on all events - if (arguments.length === 0) { - for (key in this._events) { - if (key === 'removeListener') continue; - this.removeAllListeners(key); - } - this.removeAllListeners('removeListener'); - this._events = {}; - return this; - } - - listeners = this._events[type]; - - if (isFunction(listeners)) { - this.removeListener(type, listeners); - } else { - // LIFO order - while (listeners.length) - this.removeListener(type, listeners[listeners.length - 1]); - } - delete this._events[type]; - - return this; -}; - -EventEmitter.prototype.listeners = function(type) { - var ret; - if (!this._events || !this._events[type]) - ret = []; - else if (isFunction(this._events[type])) - ret = [this._events[type]]; - else - ret = this._events[type].slice(); - return ret; -}; - -EventEmitter.listenerCount = function(emitter, type) { - var ret; - if (!emitter._events || !emitter._events[type]) - ret = 0; - else if (isFunction(emitter._events[type])) - ret = 1; - else - ret = emitter._events[type].length; - return ret; -}; - -function isFunction(arg) { - return typeof arg === 'function'; -} - -function isNumber(arg) { - return typeof arg === 'number'; -} - -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} - -function isUndefined(arg) { - return arg === void 0; -} - -},{}],6:[function(_dereq_,module,exports){ -if (typeof Object.create === 'function') { - // implementation from standard node.js 'util' module - module.exports = function inherits(ctor, 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) { - ctor.super_ = superCtor - var TempCtor = function () {} - TempCtor.prototype = superCtor.prototype - ctor.prototype = new TempCtor() - ctor.prototype.constructor = ctor - } -} - -},{}],7:[function(_dereq_,module,exports){ -// shim for using process in browser - -var process = module.exports = {}; - -process.nextTick = (function () { - var canSetImmediate = typeof window !== 'undefined' - && window.setImmediate; - var canPost = typeof window !== 'undefined' - && window.postMessage && window.addEventListener - ; - - if (canSetImmediate) { - return function (f) { return window.setImmediate(f) }; - } - - if (canPost) { - var queue = []; - window.addEventListener('message', function (ev) { - var source = ev.source; - if ((source === window || source === null) && ev.data === 'process-tick') { - ev.stopPropagation(); - if (queue.length > 0) { - var fn = queue.shift(); - fn(); - } - } - }, true); - - return function nextTick(fn) { - queue.push(fn); - window.postMessage('process-tick', '*'); - }; - } - - return function nextTick(fn) { - setTimeout(fn, 0); - }; -})(); - -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; - -process.binding = function (name) { - throw new Error('process.binding is not supported'); -} - -// TODO(shtylman) -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; - -},{}],8:[function(_dereq_,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 Buffer = _dereq_('buffer').Buffer; - -function assertEncoding(encoding) { - if (encoding && !Buffer.isEncoding(encoding)) { - throw new Error('Unknown encoding: ' + encoding); - } -} - -var StringDecoder = exports.StringDecoder = function(encoding) { - this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, ''); - assertEncoding(encoding); - switch (this.encoding) { - case 'utf8': - // CESU-8 represents each of Surrogate Pair by 3-bytes - this.surrogateSize = 3; - break; - case 'ucs2': - case 'utf16le': - // UTF-16 represents each of Surrogate Pair by 2-bytes - this.surrogateSize = 2; - this.detectIncompleteChar = utf16DetectIncompleteChar; - break; - case 'base64': - // Base-64 stores 3 bytes in 4 chars, and pads the remainder. - this.surrogateSize = 3; - this.detectIncompleteChar = base64DetectIncompleteChar; - break; - default: - this.write = passThroughWrite; - return; - } - - this.charBuffer = new Buffer(6); - this.charReceived = 0; - this.charLength = 0; -}; - - -StringDecoder.prototype.write = function(buffer) { - var charStr = ''; - var offset = 0; - - // if our last write ended with an incomplete multibyte character - while (this.charLength) { - // determine how many remaining bytes this buffer has to offer for this char - var i = (buffer.length >= this.charLength - this.charReceived) ? - this.charLength - this.charReceived : - buffer.length; - - // add the new bytes to the char buffer - buffer.copy(this.charBuffer, this.charReceived, offset, i); - this.charReceived += (i - offset); - offset = i; - - if (this.charReceived < this.charLength) { - // still not enough chars in this buffer? wait for more ... - return ''; - } - - // get the character that was split - charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding); - - // lead surrogate (D800-DBFF) is also the incomplete character - var charCode = charStr.charCodeAt(charStr.length - 1); - if (charCode >= 0xD800 && charCode <= 0xDBFF) { - this.charLength += this.surrogateSize; - charStr = ''; - continue; - } - this.charReceived = this.charLength = 0; - - // if there are no more bytes in this buffer, just emit our char - if (i == buffer.length) return charStr; - - // otherwise cut off the characters end from the beginning of this buffer - buffer = buffer.slice(i, buffer.length); - break; - } - - var lenIncomplete = this.detectIncompleteChar(buffer); - - var end = buffer.length; - if (this.charLength) { - // buffer the incomplete character bytes we got - buffer.copy(this.charBuffer, 0, buffer.length - lenIncomplete, end); - this.charReceived = lenIncomplete; - end -= lenIncomplete; - } - - charStr += buffer.toString(this.encoding, 0, end); - - var end = charStr.length - 1; - var charCode = charStr.charCodeAt(end); - // lead surrogate (D800-DBFF) is also the incomplete character - if (charCode >= 0xD800 && charCode <= 0xDBFF) { - var size = this.surrogateSize; - this.charLength += size; - this.charReceived += size; - this.charBuffer.copy(this.charBuffer, size, 0, size); - this.charBuffer.write(charStr.charAt(charStr.length - 1), this.encoding); - return charStr.substring(0, end); - } - - // or just emit the charStr - return charStr; -}; - -StringDecoder.prototype.detectIncompleteChar = function(buffer) { - // determine how many bytes we have to check at the end of this buffer - var i = (buffer.length >= 3) ? 3 : buffer.length; - - // Figure out if one of the last i bytes of our buffer announces an - // incomplete char. - for (; i > 0; i--) { - var c = buffer[buffer.length - i]; - - // See http://en.wikipedia.org/wiki/UTF-8#Description - - // 110XXXXX - if (i == 1 && c >> 5 == 0x06) { - this.charLength = 2; - break; - } - - // 1110XXXX - if (i <= 2 && c >> 4 == 0x0E) { - this.charLength = 3; - break; - } - - // 11110XXX - if (i <= 3 && c >> 3 == 0x1E) { - this.charLength = 4; - break; - } - } - - return i; -}; - -StringDecoder.prototype.end = function(buffer) { - var res = ''; - if (buffer && buffer.length) - res = this.write(buffer); - - if (this.charReceived) { - var cr = this.charReceived; - var buf = this.charBuffer; - var enc = this.encoding; - res += buf.slice(0, cr).toString(enc); - } - - return res; -}; - -function passThroughWrite(buffer) { - return buffer.toString(this.encoding); -} - -function utf16DetectIncompleteChar(buffer) { - var incomplete = this.charReceived = buffer.length % 2; - this.charLength = incomplete ? 2 : 0; - return incomplete; -} - -function base64DetectIncompleteChar(buffer) { - var incomplete = this.charReceived = buffer.length % 3; - this.charLength = incomplete ? 3 : 0; - return incomplete; -} - -},{"buffer":2}],9:[function(_dereq_,module,exports){ -module.exports = function isBuffer(arg) { - return arg && typeof arg === 'object' - && typeof arg.copy === 'function' - && typeof arg.fill === 'function' - && typeof arg.readUInt8 === 'function'; -} -},{}],10:[function(_dereq_,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. - -var formatRegExp = /%[sdj%]/g; -exports.format = function(f) { - if (!isString(f)) { - var objects = []; - for (var i = 0; i < arguments.length; i++) { - objects.push(inspect(arguments[i])); - } - return objects.join(' '); - } - - var i = 1; - var args = arguments; - var len = args.length; - var str = String(f).replace(formatRegExp, function(x) { - if (x === '%%') return '%'; - if (i >= len) return x; - switch (x) { - case '%s': return String(args[i++]); - case '%d': return Number(args[i++]); - case '%j': - try { - return JSON.stringify(args[i++]); - } catch (_) { - return '[Circular]'; - } - default: - return x; - } - }); - for (var x = args[i]; i < len; x = args[++i]) { - if (isNull(x) || !isObject(x)) { - str += ' ' + x; - } else { - str += ' ' + inspect(x); - } - } - return str; -}; - - -// Mark that a method should not be used. -// Returns a modified function which warns once by default. -// If --no-deprecation is set, then it is a no-op. -exports.deprecate = function(fn, msg) { - // Allow for deprecating things in the process of starting up. - if (isUndefined(global.process)) { - return function() { - return exports.deprecate(fn, msg).apply(this, arguments); - }; - } - - if (process.noDeprecation === true) { - return fn; - } - - var warned = false; - function deprecated() { - if (!warned) { - if (process.throwDeprecation) { - throw new Error(msg); - } else if (process.traceDeprecation) { - console.trace(msg); - } else { - console.error(msg); - } - warned = true; - } - return fn.apply(this, arguments); - } - - return deprecated; -}; - - -var debugs = {}; -var debugEnviron; -exports.debuglog = function(set) { - if (isUndefined(debugEnviron)) - debugEnviron = process.env.NODE_DEBUG || ''; - set = set.toUpperCase(); - if (!debugs[set]) { - if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { - var pid = process.pid; - debugs[set] = function() { - var msg = exports.format.apply(exports, arguments); - console.error('%s %d: %s', set, pid, msg); - }; - } else { - debugs[set] = function() {}; - } - } - return debugs[set]; -}; - - -/** - * Echos the value of a value. Trys to print the value out - * in the best way possible given the different types. - * - * @param {Object} obj The object to print out. - * @param {Object} opts Optional options object that alters the output. - */ -/* legacy: obj, showHidden, depth, colors*/ -function inspect(obj, opts) { - // default options - var ctx = { - seen: [], - stylize: stylizeNoColor - }; - // legacy... - if (arguments.length >= 3) ctx.depth = arguments[2]; - if (arguments.length >= 4) ctx.colors = arguments[3]; - if (isBoolean(opts)) { - // legacy... - ctx.showHidden = opts; - } else if (opts) { - // got an "options" object - exports._extend(ctx, opts); - } - // set default options - if (isUndefined(ctx.showHidden)) ctx.showHidden = false; - if (isUndefined(ctx.depth)) ctx.depth = 2; - if (isUndefined(ctx.colors)) ctx.colors = false; - if (isUndefined(ctx.customInspect)) ctx.customInspect = true; - if (ctx.colors) ctx.stylize = stylizeWithColor; - return formatValue(ctx, obj, ctx.depth); -} -exports.inspect = inspect; - - -// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics -inspect.colors = { - 'bold' : [1, 22], - 'italic' : [3, 23], - 'underline' : [4, 24], - 'inverse' : [7, 27], - 'white' : [37, 39], - 'grey' : [90, 39], - 'black' : [30, 39], - 'blue' : [34, 39], - 'cyan' : [36, 39], - 'green' : [32, 39], - 'magenta' : [35, 39], - 'red' : [31, 39], - 'yellow' : [33, 39] -}; - -// Don't use 'blue' not visible on cmd.exe -inspect.styles = { - 'special': 'cyan', - 'number': 'yellow', - 'boolean': 'yellow', - 'undefined': 'grey', - 'null': 'bold', - 'string': 'green', - 'date': 'magenta', - // "name": intentionally not styling - 'regexp': 'red' -}; - - -function stylizeWithColor(str, styleType) { - var style = inspect.styles[styleType]; - - if (style) { - return '\u001b[' + inspect.colors[style][0] + 'm' + str + - '\u001b[' + inspect.colors[style][1] + 'm'; - } else { - return str; - } -} - - -function stylizeNoColor(str, styleType) { - return str; -} - - -function arrayToHash(array) { - var hash = {}; - - array.forEach(function(val, idx) { - hash[val] = true; - }); - - return hash; -} - - -function formatValue(ctx, value, recurseTimes) { - // Provide a hook for user-specified inspect functions. - // Check that value is an object with an inspect function on it - if (ctx.customInspect && - value && - isFunction(value.inspect) && - // Filter out the util module, it's inspect function is special - value.inspect !== exports.inspect && - // Also filter out any prototype objects using the circular check. - !(value.constructor && value.constructor.prototype === value)) { - var ret = value.inspect(recurseTimes, ctx); - if (!isString(ret)) { - ret = formatValue(ctx, ret, recurseTimes); - } - return ret; - } - - // Primitive types cannot have properties - var primitive = formatPrimitive(ctx, value); - if (primitive) { - return primitive; - } - - // Look up the keys of the object. - var keys = Object.keys(value); - var visibleKeys = arrayToHash(keys); - - if (ctx.showHidden) { - keys = Object.getOwnPropertyNames(value); - } - - // IE doesn't make error fields non-enumerable - // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx - if (isError(value) - && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { - return formatError(value); - } - - // Some type of object without properties can be shortcutted. - if (keys.length === 0) { - if (isFunction(value)) { - var name = value.name ? ': ' + value.name : ''; - return ctx.stylize('[Function' + name + ']', 'special'); - } - if (isRegExp(value)) { - return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); - } - if (isDate(value)) { - return ctx.stylize(Date.prototype.toString.call(value), 'date'); - } - if (isError(value)) { - return formatError(value); - } - } - - var base = '', array = false, braces = ['{', '}']; - - // Make Array say that they are Array - if (isArray(value)) { - array = true; - braces = ['[', ']']; - } - - // Make functions say that they are functions - if (isFunction(value)) { - var n = value.name ? ': ' + value.name : ''; - base = ' [Function' + n + ']'; - } - - // Make RegExps say that they are RegExps - if (isRegExp(value)) { - base = ' ' + RegExp.prototype.toString.call(value); - } - - // Make dates with properties first say the date - if (isDate(value)) { - base = ' ' + Date.prototype.toUTCString.call(value); - } - - // Make error with message first say the error - if (isError(value)) { - base = ' ' + formatError(value); - } - - if (keys.length === 0 && (!array || value.length == 0)) { - return braces[0] + base + braces[1]; - } - - if (recurseTimes < 0) { - if (isRegExp(value)) { - return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); - } else { - return ctx.stylize('[Object]', 'special'); - } - } - - ctx.seen.push(value); - - var output; - if (array) { - output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); - } else { - output = keys.map(function(key) { - return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); - }); - } - - ctx.seen.pop(); - - return reduceToSingleString(output, base, braces); -} - - -function formatPrimitive(ctx, value) { - if (isUndefined(value)) - return ctx.stylize('undefined', 'undefined'); - if (isString(value)) { - var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') - .replace(/'/g, "\\'") - .replace(/\\"/g, '"') + '\''; - return ctx.stylize(simple, 'string'); - } - if (isNumber(value)) - return ctx.stylize('' + value, 'number'); - if (isBoolean(value)) - return ctx.stylize('' + value, 'boolean'); - // For some reason typeof null is "object", so special case here. - if (isNull(value)) - return ctx.stylize('null', 'null'); -} - - -function formatError(value) { - return '[' + Error.prototype.toString.call(value) + ']'; -} - - -function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { - var output = []; - for (var i = 0, l = value.length; i < l; ++i) { - if (hasOwnProperty(value, String(i))) { - output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, - String(i), true)); - } else { - output.push(''); - } - } - keys.forEach(function(key) { - if (!key.match(/^\d+$/)) { - output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, - key, true)); - } - }); - return output; -} - - -function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { - var name, str, desc; - desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; - if (desc.get) { - if (desc.set) { - str = ctx.stylize('[Getter/Setter]', 'special'); - } else { - str = ctx.stylize('[Getter]', 'special'); - } - } else { - if (desc.set) { - str = ctx.stylize('[Setter]', 'special'); - } - } - if (!hasOwnProperty(visibleKeys, key)) { - name = '[' + key + ']'; - } - if (!str) { - if (ctx.seen.indexOf(desc.value) < 0) { - if (isNull(recurseTimes)) { - str = formatValue(ctx, desc.value, null); - } else { - str = formatValue(ctx, desc.value, recurseTimes - 1); - } - if (str.indexOf('\n') > -1) { - if (array) { - str = str.split('\n').map(function(line) { - return ' ' + line; - }).join('\n').substr(2); - } else { - str = '\n' + str.split('\n').map(function(line) { - return ' ' + line; - }).join('\n'); - } - } - } else { - str = ctx.stylize('[Circular]', 'special'); - } - } - if (isUndefined(name)) { - if (array && key.match(/^\d+$/)) { - return str; - } - name = JSON.stringify('' + key); - if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { - name = name.substr(1, name.length - 2); - name = ctx.stylize(name, 'name'); - } else { - name = name.replace(/'/g, "\\'") - .replace(/\\"/g, '"') - .replace(/(^"|"$)/g, "'"); - name = ctx.stylize(name, 'string'); - } - } - - return name + ': ' + str; -} - - -function reduceToSingleString(output, base, braces) { - var numLinesEst = 0; - var length = output.reduce(function(prev, cur) { - numLinesEst++; - if (cur.indexOf('\n') >= 0) numLinesEst++; - return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; - }, 0); - - if (length > 60) { - return braces[0] + - (base === '' ? '' : base + '\n ') + - ' ' + - output.join(',\n ') + - ' ' + - braces[1]; - } - - return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; -} - - -// NOTE: These type checking functions intentionally don't use `instanceof` -// because it is fragile and can be easily faked with `Object.create()`. -function isArray(ar) { - return Array.isArray(ar); -} -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 isObject(re) && objectToString(re) === '[object RegExp]'; -} -exports.isRegExp = isRegExp; - -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} -exports.isObject = isObject; - -function isDate(d) { - return isObject(d) && objectToString(d) === '[object Date]'; -} -exports.isDate = isDate; - -function isError(e) { - return isObject(e) && - (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 = _dereq_('./support/isBuffer'); - -function objectToString(o) { - return Object.prototype.toString.call(o); -} - - -function pad(n) { - return n < 10 ? '0' + n.toString(10) : n.toString(10); -} - - -var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', - 'Oct', 'Nov', 'Dec']; - -// 26 Feb 16:19:34 -function timestamp() { - var d = new Date(); - var time = [pad(d.getHours()), - pad(d.getMinutes()), - pad(d.getSeconds())].join(':'); - return [d.getDate(), months[d.getMonth()], time].join(' '); -} - - -// log is just a thin wrapper to console.log that prepends a timestamp -exports.log = function() { - console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); -}; - - -/** - * Inherit the prototype methods from one constructor into another. - * - * The Function.prototype.inherits from lang.js rewritten as a standalone - * function (not on Function.prototype). NOTE: If this file is to be loaded - * during bootstrapping this function needs to be rewritten using some native - * functions as prototype setup using normal JavaScript does not work as - * expected during bootstrapping (see mirror.js in r114903). - * - * @param {function} ctor Constructor function which needs to inherit the - * prototype. - * @param {function} superCtor Constructor function to inherit prototype from. - */ -exports.inherits = _dereq_('inherits'); - -exports._extend = function(origin, add) { - // Don't do anything if add isn't an object - if (!add || !isObject(add)) return origin; - - var keys = Object.keys(add); - var i = keys.length; - while (i--) { - origin[keys[i]] = add[keys[i]]; - } - return origin; -}; - -function hasOwnProperty(obj, prop) { - return Object.prototype.hasOwnProperty.call(obj, prop); -} - -}).call(this,_dereq_("/home/jwagner/gh-highland/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./support/isBuffer":9,"/home/jwagner/gh-highland/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":7,"inherits":6}]},{},[1]) -(1) -}); diff --git a/test/rhino.spec.js b/test/rhino.spec.js index 83270b5b..e8783a0f 100644 --- a/test/rhino.spec.js +++ b/test/rhino.spec.js @@ -5,10 +5,10 @@ var isRhino = true; print('Running unit tests with ' + environment['java.class.path']); var requiredFiles = [ - 'node_modules/grunt-contrib-jasmine/node_modules/jasmine-core/lib/jasmine-core/jasmine.js', + 'node_modules/jasmine-core/lib/jasmine-core/jasmine.js', 'test/lib/rhino-bootstrap.js', 'node_modules/ayepromise/ayepromise.js', - 'test/lib/highland.js', + 'node_modules/highland/dist/highland.js', 'tmp/dust-full.min.js', 'test/helpers/template.helper.js', 'test/templates/all.js', diff --git a/test/templates/all.js b/test/templates/all.js index 36536104..664d8e82 100755 --- a/test/templates/all.js +++ b/test/templates/all.js @@ -44,7 +44,7 @@ function DreamStream(arr) { }); push(null, highland.nil); }); - } + }; } return [ @@ -57,7 +57,7 @@ return [ { name: "streaming render", source: "{#stream}{#delay}{.}{/delay}{/stream}", - context: (function(){ + context: function(){ var d = 1; return { stream: function() { @@ -71,7 +71,7 @@ return [ }); } }; - }), + }, expected: '', message: "should test the stream rendering" }, @@ -106,7 +106,7 @@ return [ context: { "helper": function(chunk, context, bodies, params) { // top of the current stack - currentTemplateName = context.getTemplateName(); + var currentTemplateName = context.getTemplateName(); return chunk.write(currentTemplateName); } }, @@ -178,7 +178,7 @@ return [ name: "functions in context", source: "Hello {type} World!", context: { - type: function(chunk) { + type: function() { return "Sync"; } }, @@ -1360,7 +1360,7 @@ return [ { name: "partial with async ref as name", source: '{>"{ref}" /}', - context: { ref: function(chunk, context) { return chunk.map(function(chunk) { setTimeout(function() { chunk.end('hello_world'); }, 0) }); }}, + context: { ref: function(chunk, context) { return chunk.map(function(chunk) { setTimeout(function() { chunk.end('hello_world'); }, 0); }); }}, expected: "Hello World!", message: "should test partial with an asynchronously-resolved template name" }, @@ -1486,7 +1486,7 @@ return [ source: '{>partial_print_name/}', context: { "helper": function(chunk, context, bodies, params) { - currentTemplateName = context.getTemplateName(); + var currentTemplateName = context.getTemplateName(); return chunk.write(currentTemplateName); } }, @@ -1498,7 +1498,7 @@ return [ source: '{>"{partial_print_name}"/}', context: { "helper": function(chunk, context, bodies, params) { - currentTemplateName = context.getTemplateName(); + var currentTemplateName = context.getTemplateName(); return chunk.write(currentTemplateName); }, "partial_print_name" : "partial prints the current template name" @@ -1511,7 +1511,7 @@ return [ source: '{>nested_partial_print_name/}', context: { "helper": function(chunk, context, bodies, params) { - currentTemplateName = context.getTemplateName(); + var currentTemplateName = context.getTemplateName(); return chunk.write(currentTemplateName); } }, @@ -1562,7 +1562,7 @@ return [ '{>partialTl:contextDoesNotExist/}' ].join('\n'), context: { - loadPartialTl : function(chunk, context, bodies, params) { + loadPartialTl: function(chunk) { dust.loadSource(dust.compile('{.value}{.value.childValue.anotherChild}{name.nested}{$idx} ', 'partialTl')); return chunk; } @@ -2062,7 +2062,7 @@ return [ { name: "Helper syntax error. async TypeError", source:"{#hello/}", - context: {"hello":function(chunk, context, bodies, params) { return chunk.map(function(chunk) { var a; a.slice(1); chunk.end(); })}}, + context: {"hello":function(chunk, context, bodies, params) { return chunk.map(function(chunk) { var a; a.slice(1); chunk.end(); }); }}, error: "undefined", message: "should test helper syntax errors inside an async block being handled gracefully" }