diff --git a/bin/pixi.js b/bin/pixi.js index 33edaea..5896e1a 100644 --- a/bin/pixi.js +++ b/bin/pixi.js @@ -9455,7 +9455,7 @@ * @class * @memberof PIXI */ -function BoundsBuilder() +function Bounds() { /** * @member {number} @@ -9480,18 +9480,22 @@ * @default 0 */ this.maxY = -Infinity; + + this.rect = null; } -BoundsBuilder.prototype.constructor = BoundsBuilder; -module.exports = BoundsBuilder; +Bounds.prototype.constructor = Bounds; +module.exports = Bounds; -BoundsBuilder.prototype.isEmpty = function() +Bounds.prototype.isEmpty = function() { return this.minX > this.maxX || this.minY > this.maxY; }; -BoundsBuilder.prototype.clear = function() +Bounds.prototype.clear = function() { + this.updateID++; + this.minX = Infinity; this.minY = Infinity; this.maxX = -Infinity; @@ -9504,24 +9508,30 @@ * @param tempRect {PIXI.Rectangle} temporary object will be used if AABB is not empty * @returns {PIXI.Rectangle} */ -BoundsBuilder.prototype.getRectangle = function(tempRect) +Bounds.prototype.getRectangle = function() { if (this.minX > this.maxX || this.minY > this.maxY) { return Rectangle.EMPTY; } - tempRect = tempRect || new Rectangle(0, 0, 1, 1); - tempRect.x = this.minX; - tempRect.y = this.minY; - tempRect.width = this.maxX - this.minX; - tempRect.height = this.maxY - this.minY; - return tempRect; + + if(!this.rect) + { + this.rect = new Rectangle(0, 0, 1, 1); + } + + this.rect.x = this.minX; + this.rect.y = this.minY; + this.rect.width = this.maxX - this.minX; + this.rect.height = this.maxY - this.minY; + + return this.rect; }; /** * This function should be inlined when its possible * @param point {PIXI.Point} */ -BoundsBuilder.prototype.addPoint = function (point) +Bounds.prototype.addPoint = function (point) { this.minX = Math.min(this.minX, point.x); this.maxX = Math.max(this.maxX, point.x); @@ -9532,9 +9542,9 @@ /** * Adds a quad, not transformed * @param vertices {Float32Array} - * @returns {PIXI.BoundsBuilder} + * @returns {PIXI.Bounds} */ -BoundsBuilder.prototype.addQuad = function(vertices) +Bounds.prototype.addQuad = function(vertices) { var minX = this.minX, minY = this.minY, maxX = this.maxX, maxY = this.maxY; @@ -9580,7 +9590,7 @@ * @param x1 {number} * @param y1 {number} */ -BoundsBuilder.prototype.addFrame = function(transform, x0, y0, x1, y1) +Bounds.prototype.addFrame = function(transform, x0, y0, x1, y1) { var matrix = transform.worldTransform; var a = matrix.a, b = matrix.b, c = matrix.c, d = matrix.d, tx = matrix.tx, ty = matrix.ty; @@ -9627,7 +9637,7 @@ * @param beginOffset {number} * @param endOffset {number} */ -BoundsBuilder.prototype.addVertices = function(transform, vertices, beginOffset, endOffset) +Bounds.prototype.addVertices = function(transform, vertices, beginOffset, endOffset) { var matrix = transform.worldTransform; var a = matrix.a, b = matrix.b, c = matrix.c, d = matrix.d, tx = matrix.tx, ty = matrix.ty; @@ -9651,7 +9661,7 @@ this.maxY = maxY; }; -BoundsBuilder.prototype.addBounds = function(bounds) +Bounds.prototype.addBounds = function(bounds) { var minX = this.minX, minY = this.minY, maxX = this.maxX, maxY = this.maxY; @@ -10027,7 +10037,7 @@ */ Container.prototype.updateTransform = function () { - this._currentBounds = null; + this._boundsID++; if (!this.visible) { @@ -10043,8 +10053,6 @@ { this.children[i].updateTransform(); } - - }; // performance increase to avoid using call.. (10x faster) @@ -10053,15 +10061,13 @@ Container.prototype.calculateBounds = function () { - this._bounds_.clear(); - // if we have already done this on THIS frame. + this._bounds.clear(); if(!this.visible) { return; } - this._calculateBounds(); for (var i = 0; i < this.children.length; i++) @@ -10070,8 +10076,10 @@ child.calculateBounds(); - this._bounds_.addBounds(child._bounds_); + this._bounds.addBounds(child._bounds); } + + this._boundsID = this._lastBoundsID; }; Container.prototype._calculateBounds = function () @@ -10227,12 +10235,11 @@ }; },{"../utils":114,"./DisplayObject":44}],44:[function(require,module,exports){ -var math = require('../math'), - EventEmitter = require('eventemitter3'), +var EventEmitter = require('eventemitter3'), CONST = require('../const'), TransformStatic = require('./TransformStatic'), Transform = require('./Transform'), - BoundsBulder = require('./BoundsBuilder'), + Bounds = require('./BoundsBuilder'), _tempDisplayObjectParent = new DisplayObject(); /** @@ -10309,20 +10316,14 @@ this.filterArea = null; /** - * The original, cached bounds of the object + * The bounds object, this is used to calculate and store the bounds of the displayObject * * @member {PIXI.Rectangle} * @private */ - this._bounds = new math.Rectangle(0, 0, 1, 1); - - /** - * The most up-to-date bounds of the object - * - * @member {PIXI.Rectangle} - * @private - */ - this._currentBounds = null; + this._bounds = new Bounds(); + this._boundsID = 0; + this._lastBoundsID = -1; /** * The original, cached mask of the object @@ -10332,7 +10333,7 @@ */ this._mask = null; - this._bounds_ = new BoundsBulder(); + } // constructor @@ -10575,6 +10576,8 @@ this.transform.updateTransform(this.parent.transform); // multiply the alphas.. this.worldAlpha = this.alpha * this.parent.worldAlpha; + + this._bounds.updateID++; }; // performance increase to avoid using call.. (10x faster) @@ -10621,13 +10624,12 @@ } } - if(!this._currentBounds) + if(this._boundsID !== this._lastBoundsID) { this.calculateBounds(); - this._currentBounds = this._bounds_.getRectangle(this._bounds); } - return this._currentBounds; + return this._bounds.getRectangle(this._bounds); }; /** @@ -10802,7 +10804,7 @@ this.filterArea = null; }; -},{"../const":41,"../math":65,"./BoundsBuilder":42,"./Transform":45,"./TransformStatic":47,"eventemitter3":11}],45:[function(require,module,exports){ +},{"../const":41,"./BoundsBuilder":42,"./Transform":45,"./TransformStatic":47,"eventemitter3":11}],45:[function(require,module,exports){ var math = require('../math'), TransformBase = require('./TransformBase'); @@ -12008,7 +12010,7 @@ } var lb = this._localBounds; - this._bounds_.addFrame(this.transform, lb.minX, lb.minY, lb.maxX, lb.maxY); + this._bounds.addFrame(this.transform, lb.minX, lb.minY, lb.maxX, lb.maxY); }; /** @@ -18170,6 +18172,7 @@ alphaMaskFilter = this.alphaMaskPool[this.alphaMaskIndex] = [new AlphaMaskFilter(maskData)]; } + alphaMaskFilter[0].resolution = this.renderer.resolution; alphaMaskFilter[0].maskSprite = maskData; //TODO - may cause issues! @@ -19471,20 +19474,23 @@ { this.calculateVertices(); // if we have already done this on THIS frame. - this._bounds_.addQuad(this.vertexData); + this._bounds.addQuad(this.vertexData); }; /** * Gets the local bounds of the sprite object. * */ + Sprite.prototype.getLocalBounds = function () { - this._bounds.x = -this._texture.orig.width * this.anchor.x; - this._bounds.y = -this._texture.orig.height * this.anchor.y; - this._bounds.width = this._texture.orig.width; - this._bounds.height = this._texture.orig.height; - return this._bounds; + + this._bounds.minX = -this._texture.orig.width * this.anchor.x; + this._bounds.minY = -this._texture.orig.height * this.anchor.y; + this._bounds.maxX = this._texture.orig.width; + this._bounds.maxY = this._texture.orig.height; + + return this._bounds.getRectangle(this._bounds); }; /** @@ -21179,7 +21185,7 @@ this.updateText(true); this.calculateVertices(); // if we have already done this on THIS frame. - this._bounds_.addQuad(this.vertexData); + this._bounds.addQuad(this.vertexData); }; /** @@ -26577,7 +26583,7 @@ DisplayObject.prototype._cacheAsBitmapDestroy = function () { this.cacheAsBitmap = false; - this._cacheData.originalDestroy(); + this.destroy(); }; },{"../core":60}],125:[function(require,module,exports){ @@ -29970,7 +29976,7 @@ Mesh.prototype._calculateBounds = function () { //TODO - we can cache local bounds and use them if they are dirty (like graphics) - this._bounds_.addVertices(this.transform, this.vertices, 0, this.vertices.length); + this._bounds.addVertices(this.transform, this.vertices, 0, this.vertices.length); }; /** diff --git a/bin/pixi.js b/bin/pixi.js index 33edaea..5896e1a 100644 --- a/bin/pixi.js +++ b/bin/pixi.js @@ -9455,7 +9455,7 @@ * @class * @memberof PIXI */ -function BoundsBuilder() +function Bounds() { /** * @member {number} @@ -9480,18 +9480,22 @@ * @default 0 */ this.maxY = -Infinity; + + this.rect = null; } -BoundsBuilder.prototype.constructor = BoundsBuilder; -module.exports = BoundsBuilder; +Bounds.prototype.constructor = Bounds; +module.exports = Bounds; -BoundsBuilder.prototype.isEmpty = function() +Bounds.prototype.isEmpty = function() { return this.minX > this.maxX || this.minY > this.maxY; }; -BoundsBuilder.prototype.clear = function() +Bounds.prototype.clear = function() { + this.updateID++; + this.minX = Infinity; this.minY = Infinity; this.maxX = -Infinity; @@ -9504,24 +9508,30 @@ * @param tempRect {PIXI.Rectangle} temporary object will be used if AABB is not empty * @returns {PIXI.Rectangle} */ -BoundsBuilder.prototype.getRectangle = function(tempRect) +Bounds.prototype.getRectangle = function() { if (this.minX > this.maxX || this.minY > this.maxY) { return Rectangle.EMPTY; } - tempRect = tempRect || new Rectangle(0, 0, 1, 1); - tempRect.x = this.minX; - tempRect.y = this.minY; - tempRect.width = this.maxX - this.minX; - tempRect.height = this.maxY - this.minY; - return tempRect; + + if(!this.rect) + { + this.rect = new Rectangle(0, 0, 1, 1); + } + + this.rect.x = this.minX; + this.rect.y = this.minY; + this.rect.width = this.maxX - this.minX; + this.rect.height = this.maxY - this.minY; + + return this.rect; }; /** * This function should be inlined when its possible * @param point {PIXI.Point} */ -BoundsBuilder.prototype.addPoint = function (point) +Bounds.prototype.addPoint = function (point) { this.minX = Math.min(this.minX, point.x); this.maxX = Math.max(this.maxX, point.x); @@ -9532,9 +9542,9 @@ /** * Adds a quad, not transformed * @param vertices {Float32Array} - * @returns {PIXI.BoundsBuilder} + * @returns {PIXI.Bounds} */ -BoundsBuilder.prototype.addQuad = function(vertices) +Bounds.prototype.addQuad = function(vertices) { var minX = this.minX, minY = this.minY, maxX = this.maxX, maxY = this.maxY; @@ -9580,7 +9590,7 @@ * @param x1 {number} * @param y1 {number} */ -BoundsBuilder.prototype.addFrame = function(transform, x0, y0, x1, y1) +Bounds.prototype.addFrame = function(transform, x0, y0, x1, y1) { var matrix = transform.worldTransform; var a = matrix.a, b = matrix.b, c = matrix.c, d = matrix.d, tx = matrix.tx, ty = matrix.ty; @@ -9627,7 +9637,7 @@ * @param beginOffset {number} * @param endOffset {number} */ -BoundsBuilder.prototype.addVertices = function(transform, vertices, beginOffset, endOffset) +Bounds.prototype.addVertices = function(transform, vertices, beginOffset, endOffset) { var matrix = transform.worldTransform; var a = matrix.a, b = matrix.b, c = matrix.c, d = matrix.d, tx = matrix.tx, ty = matrix.ty; @@ -9651,7 +9661,7 @@ this.maxY = maxY; }; -BoundsBuilder.prototype.addBounds = function(bounds) +Bounds.prototype.addBounds = function(bounds) { var minX = this.minX, minY = this.minY, maxX = this.maxX, maxY = this.maxY; @@ -10027,7 +10037,7 @@ */ Container.prototype.updateTransform = function () { - this._currentBounds = null; + this._boundsID++; if (!this.visible) { @@ -10043,8 +10053,6 @@ { this.children[i].updateTransform(); } - - }; // performance increase to avoid using call.. (10x faster) @@ -10053,15 +10061,13 @@ Container.prototype.calculateBounds = function () { - this._bounds_.clear(); - // if we have already done this on THIS frame. + this._bounds.clear(); if(!this.visible) { return; } - this._calculateBounds(); for (var i = 0; i < this.children.length; i++) @@ -10070,8 +10076,10 @@ child.calculateBounds(); - this._bounds_.addBounds(child._bounds_); + this._bounds.addBounds(child._bounds); } + + this._boundsID = this._lastBoundsID; }; Container.prototype._calculateBounds = function () @@ -10227,12 +10235,11 @@ }; },{"../utils":114,"./DisplayObject":44}],44:[function(require,module,exports){ -var math = require('../math'), - EventEmitter = require('eventemitter3'), +var EventEmitter = require('eventemitter3'), CONST = require('../const'), TransformStatic = require('./TransformStatic'), Transform = require('./Transform'), - BoundsBulder = require('./BoundsBuilder'), + Bounds = require('./BoundsBuilder'), _tempDisplayObjectParent = new DisplayObject(); /** @@ -10309,20 +10316,14 @@ this.filterArea = null; /** - * The original, cached bounds of the object + * The bounds object, this is used to calculate and store the bounds of the displayObject * * @member {PIXI.Rectangle} * @private */ - this._bounds = new math.Rectangle(0, 0, 1, 1); - - /** - * The most up-to-date bounds of the object - * - * @member {PIXI.Rectangle} - * @private - */ - this._currentBounds = null; + this._bounds = new Bounds(); + this._boundsID = 0; + this._lastBoundsID = -1; /** * The original, cached mask of the object @@ -10332,7 +10333,7 @@ */ this._mask = null; - this._bounds_ = new BoundsBulder(); + } // constructor @@ -10575,6 +10576,8 @@ this.transform.updateTransform(this.parent.transform); // multiply the alphas.. this.worldAlpha = this.alpha * this.parent.worldAlpha; + + this._bounds.updateID++; }; // performance increase to avoid using call.. (10x faster) @@ -10621,13 +10624,12 @@ } } - if(!this._currentBounds) + if(this._boundsID !== this._lastBoundsID) { this.calculateBounds(); - this._currentBounds = this._bounds_.getRectangle(this._bounds); } - return this._currentBounds; + return this._bounds.getRectangle(this._bounds); }; /** @@ -10802,7 +10804,7 @@ this.filterArea = null; }; -},{"../const":41,"../math":65,"./BoundsBuilder":42,"./Transform":45,"./TransformStatic":47,"eventemitter3":11}],45:[function(require,module,exports){ +},{"../const":41,"./BoundsBuilder":42,"./Transform":45,"./TransformStatic":47,"eventemitter3":11}],45:[function(require,module,exports){ var math = require('../math'), TransformBase = require('./TransformBase'); @@ -12008,7 +12010,7 @@ } var lb = this._localBounds; - this._bounds_.addFrame(this.transform, lb.minX, lb.minY, lb.maxX, lb.maxY); + this._bounds.addFrame(this.transform, lb.minX, lb.minY, lb.maxX, lb.maxY); }; /** @@ -18170,6 +18172,7 @@ alphaMaskFilter = this.alphaMaskPool[this.alphaMaskIndex] = [new AlphaMaskFilter(maskData)]; } + alphaMaskFilter[0].resolution = this.renderer.resolution; alphaMaskFilter[0].maskSprite = maskData; //TODO - may cause issues! @@ -19471,20 +19474,23 @@ { this.calculateVertices(); // if we have already done this on THIS frame. - this._bounds_.addQuad(this.vertexData); + this._bounds.addQuad(this.vertexData); }; /** * Gets the local bounds of the sprite object. * */ + Sprite.prototype.getLocalBounds = function () { - this._bounds.x = -this._texture.orig.width * this.anchor.x; - this._bounds.y = -this._texture.orig.height * this.anchor.y; - this._bounds.width = this._texture.orig.width; - this._bounds.height = this._texture.orig.height; - return this._bounds; + + this._bounds.minX = -this._texture.orig.width * this.anchor.x; + this._bounds.minY = -this._texture.orig.height * this.anchor.y; + this._bounds.maxX = this._texture.orig.width; + this._bounds.maxY = this._texture.orig.height; + + return this._bounds.getRectangle(this._bounds); }; /** @@ -21179,7 +21185,7 @@ this.updateText(true); this.calculateVertices(); // if we have already done this on THIS frame. - this._bounds_.addQuad(this.vertexData); + this._bounds.addQuad(this.vertexData); }; /** @@ -26577,7 +26583,7 @@ DisplayObject.prototype._cacheAsBitmapDestroy = function () { this.cacheAsBitmap = false; - this._cacheData.originalDestroy(); + this.destroy(); }; },{"../core":60}],125:[function(require,module,exports){ @@ -29970,7 +29976,7 @@ Mesh.prototype._calculateBounds = function () { //TODO - we can cache local bounds and use them if they are dirty (like graphics) - this._bounds_.addVertices(this.transform, this.vertices, 0, this.vertices.length); + this._bounds.addVertices(this.transform, this.vertices, 0, this.vertices.length); }; /** diff --git a/bin/pixi.js.map b/bin/pixi.js.map index 2b4b808..f2cbe3e 100644 --- a/bin/pixi.js.map +++ b/bin/pixi.js.map @@ -1 +1 @@ -{"version":3,"names":[],"mappings":"","sources":["pixi.js"],"sourcesContent":["(function(f){if(typeof exports===\"object\"&&typeof module!==\"undefined\"){module.exports=f()}else if(typeof define===\"function\"&&define.amd){define([],f)}else{var g;if(typeof window!==\"undefined\"){g=window}else if(typeof global!==\"undefined\"){g=global}else if(typeof self!==\"undefined\"){g=self}else{g=this}g.PIXI = f()}})(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);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o= 0 &&\n arr.length % 1 === 0\n );\n }\n\n function _arrayEach(arr, iterator) {\n var index = -1,\n length = arr.length;\n\n while (++index < length) {\n iterator(arr[index], index, arr);\n }\n }\n\n function _map(arr, iterator) {\n var index = -1,\n length = arr.length,\n result = Array(length);\n\n while (++index < length) {\n result[index] = iterator(arr[index], index, arr);\n }\n return result;\n }\n\n function _range(count) {\n return _map(Array(count), function (v, i) { return i; });\n }\n\n function _reduce(arr, iterator, memo) {\n _arrayEach(arr, function (x, i, a) {\n memo = iterator(memo, x, i, a);\n });\n return memo;\n }\n\n function _forEachOf(object, iterator) {\n _arrayEach(_keys(object), function (key) {\n iterator(object[key], key);\n });\n }\n\n function _indexOf(arr, item) {\n for (var i = 0; i < arr.length; i++) {\n if (arr[i] === item) return i;\n }\n return -1;\n }\n\n var _keys = Object.keys || function (obj) {\n var keys = [];\n for (var k in obj) {\n if (obj.hasOwnProperty(k)) {\n keys.push(k);\n }\n }\n return keys;\n };\n\n function _keyIterator(coll) {\n var i = -1;\n var len;\n var keys;\n if (_isArrayLike(coll)) {\n len = coll.length;\n return function next() {\n i++;\n return i < len ? i : null;\n };\n } else {\n keys = _keys(coll);\n len = keys.length;\n return function next() {\n i++;\n return i < len ? keys[i] : null;\n };\n }\n }\n\n // Similar to ES6's rest param (http://ariya.ofilabs.com/2013/03/es6-and-rest-parameter.html)\n // This accumulates the arguments passed into an array, after a given index.\n // From underscore.js (https://github.com/jashkenas/underscore/pull/2140).\n function _restParam(func, startIndex) {\n startIndex = startIndex == null ? func.length - 1 : +startIndex;\n return function() {\n var length = Math.max(arguments.length - startIndex, 0);\n var rest = Array(length);\n for (var index = 0; index < length; index++) {\n rest[index] = arguments[index + startIndex];\n }\n switch (startIndex) {\n case 0: return func.call(this, rest);\n case 1: return func.call(this, arguments[0], rest);\n }\n // Currently unused but handle cases outside of the switch statement:\n // var args = Array(startIndex + 1);\n // for (index = 0; index < startIndex; index++) {\n // args[index] = arguments[index];\n // }\n // args[startIndex] = rest;\n // return func.apply(this, args);\n };\n }\n\n function _withoutIndex(iterator) {\n return function (value, index, callback) {\n return iterator(value, callback);\n };\n }\n\n //// exported async module functions ////\n\n //// nextTick implementation with browser-compatible fallback ////\n\n // capture the global reference to guard against fakeTimer mocks\n var _setImmediate = typeof setImmediate === 'function' && setImmediate;\n\n var _delay = _setImmediate ? function(fn) {\n // not a direct alias for IE10 compatibility\n _setImmediate(fn);\n } : function(fn) {\n setTimeout(fn, 0);\n };\n\n if (typeof process === 'object' && typeof process.nextTick === 'function') {\n async.nextTick = process.nextTick;\n } else {\n async.nextTick = _delay;\n }\n async.setImmediate = _setImmediate ? _delay : async.nextTick;\n\n\n async.forEach =\n async.each = function (arr, iterator, callback) {\n return async.eachOf(arr, _withoutIndex(iterator), callback);\n };\n\n async.forEachSeries =\n async.eachSeries = function (arr, iterator, callback) {\n return async.eachOfSeries(arr, _withoutIndex(iterator), callback);\n };\n\n\n async.forEachLimit =\n async.eachLimit = function (arr, limit, iterator, callback) {\n return _eachOfLimit(limit)(arr, _withoutIndex(iterator), callback);\n };\n\n async.forEachOf =\n async.eachOf = function (object, iterator, callback) {\n callback = _once(callback || noop);\n object = object || [];\n\n var iter = _keyIterator(object);\n var key, completed = 0;\n\n while ((key = iter()) != null) {\n completed += 1;\n iterator(object[key], key, only_once(done));\n }\n\n if (completed === 0) callback(null);\n\n function done(err) {\n completed--;\n if (err) {\n callback(err);\n }\n // Check key is null in case iterator isn't exhausted\n // and done resolved synchronously.\n else if (key === null && completed <= 0) {\n callback(null);\n }\n }\n };\n\n async.forEachOfSeries =\n async.eachOfSeries = function (obj, iterator, callback) {\n callback = _once(callback || noop);\n obj = obj || [];\n var nextKey = _keyIterator(obj);\n var key = nextKey();\n function iterate() {\n var sync = true;\n if (key === null) {\n return callback(null);\n }\n iterator(obj[key], key, only_once(function (err) {\n if (err) {\n callback(err);\n }\n else {\n key = nextKey();\n if (key === null) {\n return callback(null);\n } else {\n if (sync) {\n async.setImmediate(iterate);\n } else {\n iterate();\n }\n }\n }\n }));\n sync = false;\n }\n iterate();\n };\n\n\n\n async.forEachOfLimit =\n async.eachOfLimit = function (obj, limit, iterator, callback) {\n _eachOfLimit(limit)(obj, iterator, callback);\n };\n\n function _eachOfLimit(limit) {\n\n return function (obj, iterator, callback) {\n callback = _once(callback || noop);\n obj = obj || [];\n var nextKey = _keyIterator(obj);\n if (limit <= 0) {\n return callback(null);\n }\n var done = false;\n var running = 0;\n var errored = false;\n\n (function replenish () {\n if (done && running <= 0) {\n return callback(null);\n }\n\n while (running < limit && !errored) {\n var key = nextKey();\n if (key === null) {\n done = true;\n if (running <= 0) {\n callback(null);\n }\n return;\n }\n running += 1;\n iterator(obj[key], key, only_once(function (err) {\n running -= 1;\n if (err) {\n callback(err);\n errored = true;\n }\n else {\n replenish();\n }\n }));\n }\n })();\n };\n }\n\n\n function doParallel(fn) {\n return function (obj, iterator, callback) {\n return fn(async.eachOf, obj, iterator, callback);\n };\n }\n function doParallelLimit(fn) {\n return function (obj, limit, iterator, callback) {\n return fn(_eachOfLimit(limit), obj, iterator, callback);\n };\n }\n function doSeries(fn) {\n return function (obj, iterator, callback) {\n return fn(async.eachOfSeries, obj, iterator, callback);\n };\n }\n\n function _asyncMap(eachfn, arr, iterator, callback) {\n callback = _once(callback || noop);\n arr = arr || [];\n var results = _isArrayLike(arr) ? [] : {};\n eachfn(arr, function (value, index, callback) {\n iterator(value, function (err, v) {\n results[index] = v;\n callback(err);\n });\n }, function (err) {\n callback(err, results);\n });\n }\n\n async.map = doParallel(_asyncMap);\n async.mapSeries = doSeries(_asyncMap);\n async.mapLimit = doParallelLimit(_asyncMap);\n\n // reduce only has a series version, as doing reduce in parallel won't\n // work in many situations.\n async.inject =\n async.foldl =\n async.reduce = function (arr, memo, iterator, callback) {\n async.eachOfSeries(arr, function (x, i, callback) {\n iterator(memo, x, function (err, v) {\n memo = v;\n callback(err);\n });\n }, function (err) {\n callback(err, memo);\n });\n };\n\n async.foldr =\n async.reduceRight = function (arr, memo, iterator, callback) {\n var reversed = _map(arr, identity).reverse();\n async.reduce(reversed, memo, iterator, callback);\n };\n\n async.transform = function (arr, memo, iterator, callback) {\n if (arguments.length === 3) {\n callback = iterator;\n iterator = memo;\n memo = _isArray(arr) ? [] : {};\n }\n\n async.eachOf(arr, function(v, k, cb) {\n iterator(memo, v, k, cb);\n }, function(err) {\n callback(err, memo);\n });\n };\n\n function _filter(eachfn, arr, iterator, callback) {\n var results = [];\n eachfn(arr, function (x, index, callback) {\n iterator(x, function (v) {\n if (v) {\n results.push({index: index, value: x});\n }\n callback();\n });\n }, function () {\n callback(_map(results.sort(function (a, b) {\n return a.index - b.index;\n }), function (x) {\n return x.value;\n }));\n });\n }\n\n async.select =\n async.filter = doParallel(_filter);\n\n async.selectLimit =\n async.filterLimit = doParallelLimit(_filter);\n\n async.selectSeries =\n async.filterSeries = doSeries(_filter);\n\n function _reject(eachfn, arr, iterator, callback) {\n _filter(eachfn, arr, function(value, cb) {\n iterator(value, function(v) {\n cb(!v);\n });\n }, callback);\n }\n async.reject = doParallel(_reject);\n async.rejectLimit = doParallelLimit(_reject);\n async.rejectSeries = doSeries(_reject);\n\n function _createTester(eachfn, check, getResult) {\n return function(arr, limit, iterator, cb) {\n function done() {\n if (cb) cb(getResult(false, void 0));\n }\n function iteratee(x, _, callback) {\n if (!cb) return callback();\n iterator(x, function (v) {\n if (cb && check(v)) {\n cb(getResult(true, x));\n cb = iterator = false;\n }\n callback();\n });\n }\n if (arguments.length > 3) {\n eachfn(arr, limit, iteratee, done);\n } else {\n cb = iterator;\n iterator = limit;\n eachfn(arr, iteratee, done);\n }\n };\n }\n\n async.any =\n async.some = _createTester(async.eachOf, toBool, identity);\n\n async.someLimit = _createTester(async.eachOfLimit, toBool, identity);\n\n async.all =\n async.every = _createTester(async.eachOf, notId, notId);\n\n async.everyLimit = _createTester(async.eachOfLimit, notId, notId);\n\n function _findGetResult(v, x) {\n return x;\n }\n async.detect = _createTester(async.eachOf, identity, _findGetResult);\n async.detectSeries = _createTester(async.eachOfSeries, identity, _findGetResult);\n async.detectLimit = _createTester(async.eachOfLimit, identity, _findGetResult);\n\n async.sortBy = function (arr, iterator, callback) {\n async.map(arr, function (x, callback) {\n iterator(x, function (err, criteria) {\n if (err) {\n callback(err);\n }\n else {\n callback(null, {value: x, criteria: criteria});\n }\n });\n }, function (err, results) {\n if (err) {\n return callback(err);\n }\n else {\n callback(null, _map(results.sort(comparator), function (x) {\n return x.value;\n }));\n }\n\n });\n\n function comparator(left, right) {\n var a = left.criteria, b = right.criteria;\n return a < b ? -1 : a > b ? 1 : 0;\n }\n };\n\n async.auto = function (tasks, concurrency, callback) {\n if (typeof arguments[1] === 'function') {\n // concurrency is optional, shift the args.\n callback = concurrency;\n concurrency = null;\n }\n callback = _once(callback || noop);\n var keys = _keys(tasks);\n var remainingTasks = keys.length;\n if (!remainingTasks) {\n return callback(null);\n }\n if (!concurrency) {\n concurrency = remainingTasks;\n }\n\n var results = {};\n var runningTasks = 0;\n\n var hasError = false;\n\n var listeners = [];\n function addListener(fn) {\n listeners.unshift(fn);\n }\n function removeListener(fn) {\n var idx = _indexOf(listeners, fn);\n if (idx >= 0) listeners.splice(idx, 1);\n }\n function taskComplete() {\n remainingTasks--;\n _arrayEach(listeners.slice(0), function (fn) {\n fn();\n });\n }\n\n addListener(function () {\n if (!remainingTasks) {\n callback(null, results);\n }\n });\n\n _arrayEach(keys, function (k) {\n if (hasError) return;\n var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]];\n var taskCallback = _restParam(function(err, args) {\n runningTasks--;\n if (args.length <= 1) {\n args = args[0];\n }\n if (err) {\n var safeResults = {};\n _forEachOf(results, function(val, rkey) {\n safeResults[rkey] = val;\n });\n safeResults[k] = args;\n hasError = true;\n\n callback(err, safeResults);\n }\n else {\n results[k] = args;\n async.setImmediate(taskComplete);\n }\n });\n var requires = task.slice(0, task.length - 1);\n // prevent dead-locks\n var len = requires.length;\n var dep;\n while (len--) {\n if (!(dep = tasks[requires[len]])) {\n throw new Error('Has nonexistent dependency in ' + requires.join(', '));\n }\n if (_isArray(dep) && _indexOf(dep, k) >= 0) {\n throw new Error('Has cyclic dependencies');\n }\n }\n function ready() {\n return runningTasks < concurrency && _reduce(requires, function (a, x) {\n return (a && results.hasOwnProperty(x));\n }, true) && !results.hasOwnProperty(k);\n }\n if (ready()) {\n runningTasks++;\n task[task.length - 1](taskCallback, results);\n }\n else {\n addListener(listener);\n }\n function listener() {\n if (ready()) {\n runningTasks++;\n removeListener(listener);\n task[task.length - 1](taskCallback, results);\n }\n }\n });\n };\n\n\n\n async.retry = function(times, task, callback) {\n var DEFAULT_TIMES = 5;\n var DEFAULT_INTERVAL = 0;\n\n var attempts = [];\n\n var opts = {\n times: DEFAULT_TIMES,\n interval: DEFAULT_INTERVAL\n };\n\n function parseTimes(acc, t){\n if(typeof t === 'number'){\n acc.times = parseInt(t, 10) || DEFAULT_TIMES;\n } else if(typeof t === 'object'){\n acc.times = parseInt(t.times, 10) || DEFAULT_TIMES;\n acc.interval = parseInt(t.interval, 10) || DEFAULT_INTERVAL;\n } else {\n throw new Error('Unsupported argument type for \\'times\\': ' + typeof t);\n }\n }\n\n var length = arguments.length;\n if (length < 1 || length > 3) {\n throw new Error('Invalid arguments - must be either (task), (task, callback), (times, task) or (times, task, callback)');\n } else if (length <= 2 && typeof times === 'function') {\n callback = task;\n task = times;\n }\n if (typeof times !== 'function') {\n parseTimes(opts, times);\n }\n opts.callback = callback;\n opts.task = task;\n\n function wrappedTask(wrappedCallback, wrappedResults) {\n function retryAttempt(task, finalAttempt) {\n return function(seriesCallback) {\n task(function(err, result){\n seriesCallback(!err || finalAttempt, {err: err, result: result});\n }, wrappedResults);\n };\n }\n\n function retryInterval(interval){\n return function(seriesCallback){\n setTimeout(function(){\n seriesCallback(null);\n }, interval);\n };\n }\n\n while (opts.times) {\n\n var finalAttempt = !(opts.times-=1);\n attempts.push(retryAttempt(opts.task, finalAttempt));\n if(!finalAttempt && opts.interval > 0){\n attempts.push(retryInterval(opts.interval));\n }\n }\n\n async.series(attempts, function(done, data){\n data = data[data.length - 1];\n (wrappedCallback || opts.callback)(data.err, data.result);\n });\n }\n\n // If a callback is passed, run this as a controll flow\n return opts.callback ? wrappedTask() : wrappedTask;\n };\n\n async.waterfall = function (tasks, callback) {\n callback = _once(callback || noop);\n if (!_isArray(tasks)) {\n var err = new Error('First argument to waterfall must be an array of functions');\n return callback(err);\n }\n if (!tasks.length) {\n return callback();\n }\n function wrapIterator(iterator) {\n return _restParam(function (err, args) {\n if (err) {\n callback.apply(null, [err].concat(args));\n }\n else {\n var next = iterator.next();\n if (next) {\n args.push(wrapIterator(next));\n }\n else {\n args.push(callback);\n }\n ensureAsync(iterator).apply(null, args);\n }\n });\n }\n wrapIterator(async.iterator(tasks))();\n };\n\n function _parallel(eachfn, tasks, callback) {\n callback = callback || noop;\n var results = _isArrayLike(tasks) ? [] : {};\n\n eachfn(tasks, function (task, key, callback) {\n task(_restParam(function (err, args) {\n if (args.length <= 1) {\n args = args[0];\n }\n results[key] = args;\n callback(err);\n }));\n }, function (err) {\n callback(err, results);\n });\n }\n\n async.parallel = function (tasks, callback) {\n _parallel(async.eachOf, tasks, callback);\n };\n\n async.parallelLimit = function(tasks, limit, callback) {\n _parallel(_eachOfLimit(limit), tasks, callback);\n };\n\n async.series = function(tasks, callback) {\n _parallel(async.eachOfSeries, tasks, callback);\n };\n\n async.iterator = function (tasks) {\n function makeCallback(index) {\n function fn() {\n if (tasks.length) {\n tasks[index].apply(null, arguments);\n }\n return fn.next();\n }\n fn.next = function () {\n return (index < tasks.length - 1) ? makeCallback(index + 1): null;\n };\n return fn;\n }\n return makeCallback(0);\n };\n\n async.apply = _restParam(function (fn, args) {\n return _restParam(function (callArgs) {\n return fn.apply(\n null, args.concat(callArgs)\n );\n });\n });\n\n function _concat(eachfn, arr, fn, callback) {\n var result = [];\n eachfn(arr, function (x, index, cb) {\n fn(x, function (err, y) {\n result = result.concat(y || []);\n cb(err);\n });\n }, function (err) {\n callback(err, result);\n });\n }\n async.concat = doParallel(_concat);\n async.concatSeries = doSeries(_concat);\n\n async.whilst = function (test, iterator, callback) {\n callback = callback || noop;\n if (test()) {\n var next = _restParam(function(err, args) {\n if (err) {\n callback(err);\n } else if (test.apply(this, args)) {\n iterator(next);\n } else {\n callback.apply(null, [null].concat(args));\n }\n });\n iterator(next);\n } else {\n callback(null);\n }\n };\n\n async.doWhilst = function (iterator, test, callback) {\n var calls = 0;\n return async.whilst(function() {\n return ++calls <= 1 || test.apply(this, arguments);\n }, iterator, callback);\n };\n\n async.until = function (test, iterator, callback) {\n return async.whilst(function() {\n return !test.apply(this, arguments);\n }, iterator, callback);\n };\n\n async.doUntil = function (iterator, test, callback) {\n return async.doWhilst(iterator, function() {\n return !test.apply(this, arguments);\n }, callback);\n };\n\n async.during = function (test, iterator, callback) {\n callback = callback || noop;\n\n var next = _restParam(function(err, args) {\n if (err) {\n callback(err);\n } else {\n args.push(check);\n test.apply(this, args);\n }\n });\n\n var check = function(err, truth) {\n if (err) {\n callback(err);\n } else if (truth) {\n iterator(next);\n } else {\n callback(null);\n }\n };\n\n test(check);\n };\n\n async.doDuring = function (iterator, test, callback) {\n var calls = 0;\n async.during(function(next) {\n if (calls++ < 1) {\n next(null, true);\n } else {\n test.apply(this, arguments);\n }\n }, iterator, callback);\n };\n\n function _queue(worker, concurrency, payload) {\n if (concurrency == null) {\n concurrency = 1;\n }\n else if(concurrency === 0) {\n throw new Error('Concurrency must not be zero');\n }\n function _insert(q, data, pos, callback) {\n if (callback != null && typeof callback !== \"function\") {\n throw new Error(\"task callback must be a function\");\n }\n q.started = true;\n if (!_isArray(data)) {\n data = [data];\n }\n if(data.length === 0 && q.idle()) {\n // call drain immediately if there are no tasks\n return async.setImmediate(function() {\n q.drain();\n });\n }\n _arrayEach(data, function(task) {\n var item = {\n data: task,\n callback: callback || noop\n };\n\n if (pos) {\n q.tasks.unshift(item);\n } else {\n q.tasks.push(item);\n }\n\n if (q.tasks.length === q.concurrency) {\n q.saturated();\n }\n });\n async.setImmediate(q.process);\n }\n function _next(q, tasks) {\n return function(){\n workers -= 1;\n\n var removed = false;\n var args = arguments;\n _arrayEach(tasks, function (task) {\n _arrayEach(workersList, function (worker, index) {\n if (worker === task && !removed) {\n workersList.splice(index, 1);\n removed = true;\n }\n });\n\n task.callback.apply(task, args);\n });\n if (q.tasks.length + workers === 0) {\n q.drain();\n }\n q.process();\n };\n }\n\n var workers = 0;\n var workersList = [];\n var q = {\n tasks: [],\n concurrency: concurrency,\n payload: payload,\n saturated: noop,\n empty: noop,\n drain: noop,\n started: false,\n paused: false,\n push: function (data, callback) {\n _insert(q, data, false, callback);\n },\n kill: function () {\n q.drain = noop;\n q.tasks = [];\n },\n unshift: function (data, callback) {\n _insert(q, data, true, callback);\n },\n process: function () {\n while(!q.paused && workers < q.concurrency && q.tasks.length){\n\n var tasks = q.payload ?\n q.tasks.splice(0, q.payload) :\n q.tasks.splice(0, q.tasks.length);\n\n var data = _map(tasks, function (task) {\n return task.data;\n });\n\n if (q.tasks.length === 0) {\n q.empty();\n }\n workers += 1;\n workersList.push(tasks[0]);\n var cb = only_once(_next(q, tasks));\n worker(data, cb);\n }\n },\n length: function () {\n return q.tasks.length;\n },\n running: function () {\n return workers;\n },\n workersList: function () {\n return workersList;\n },\n idle: function() {\n return q.tasks.length + workers === 0;\n },\n pause: function () {\n q.paused = true;\n },\n resume: function () {\n if (q.paused === false) { return; }\n q.paused = false;\n var resumeCount = Math.min(q.concurrency, q.tasks.length);\n // Need to call q.process once per concurrent\n // worker to preserve full concurrency after pause\n for (var w = 1; w <= resumeCount; w++) {\n async.setImmediate(q.process);\n }\n }\n };\n return q;\n }\n\n async.queue = function (worker, concurrency) {\n var q = _queue(function (items, cb) {\n worker(items[0], cb);\n }, concurrency, 1);\n\n return q;\n };\n\n async.priorityQueue = function (worker, concurrency) {\n\n function _compareTasks(a, b){\n return a.priority - b.priority;\n }\n\n function _binarySearch(sequence, item, compare) {\n var beg = -1,\n end = sequence.length - 1;\n while (beg < end) {\n var mid = beg + ((end - beg + 1) >>> 1);\n if (compare(item, sequence[mid]) >= 0) {\n beg = mid;\n } else {\n end = mid - 1;\n }\n }\n return beg;\n }\n\n function _insert(q, data, priority, callback) {\n if (callback != null && typeof callback !== \"function\") {\n throw new Error(\"task callback must be a function\");\n }\n q.started = true;\n if (!_isArray(data)) {\n data = [data];\n }\n if(data.length === 0) {\n // call drain immediately if there are no tasks\n return async.setImmediate(function() {\n q.drain();\n });\n }\n _arrayEach(data, function(task) {\n var item = {\n data: task,\n priority: priority,\n callback: typeof callback === 'function' ? callback : noop\n };\n\n q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item);\n\n if (q.tasks.length === q.concurrency) {\n q.saturated();\n }\n async.setImmediate(q.process);\n });\n }\n\n // Start with a normal queue\n var q = async.queue(worker, concurrency);\n\n // Override push to accept second parameter representing priority\n q.push = function (data, priority, callback) {\n _insert(q, data, priority, callback);\n };\n\n // Remove unshift function\n delete q.unshift;\n\n return q;\n };\n\n async.cargo = function (worker, payload) {\n return _queue(worker, 1, payload);\n };\n\n function _console_fn(name) {\n return _restParam(function (fn, args) {\n fn.apply(null, args.concat([_restParam(function (err, args) {\n if (typeof console === 'object') {\n if (err) {\n if (console.error) {\n console.error(err);\n }\n }\n else if (console[name]) {\n _arrayEach(args, function (x) {\n console[name](x);\n });\n }\n }\n })]));\n });\n }\n async.log = _console_fn('log');\n async.dir = _console_fn('dir');\n /*async.info = _console_fn('info');\n async.warn = _console_fn('warn');\n async.error = _console_fn('error');*/\n\n async.memoize = function (fn, hasher) {\n var memo = {};\n var queues = {};\n var has = Object.prototype.hasOwnProperty;\n hasher = hasher || identity;\n var memoized = _restParam(function memoized(args) {\n var callback = args.pop();\n var key = hasher.apply(null, args);\n if (has.call(memo, key)) { \n async.setImmediate(function () {\n callback.apply(null, memo[key]);\n });\n }\n else if (has.call(queues, key)) {\n queues[key].push(callback);\n }\n else {\n queues[key] = [callback];\n fn.apply(null, args.concat([_restParam(function (args) {\n memo[key] = args;\n var q = queues[key];\n delete queues[key];\n for (var i = 0, l = q.length; i < l; i++) {\n q[i].apply(null, args);\n }\n })]));\n }\n });\n memoized.memo = memo;\n memoized.unmemoized = fn;\n return memoized;\n };\n\n async.unmemoize = function (fn) {\n return function () {\n return (fn.unmemoized || fn).apply(null, arguments);\n };\n };\n\n function _times(mapper) {\n return function (count, iterator, callback) {\n mapper(_range(count), iterator, callback);\n };\n }\n\n async.times = _times(async.map);\n async.timesSeries = _times(async.mapSeries);\n async.timesLimit = function (count, limit, iterator, callback) {\n return async.mapLimit(_range(count), limit, iterator, callback);\n };\n\n async.seq = function (/* functions... */) {\n var fns = arguments;\n return _restParam(function (args) {\n var that = this;\n\n var callback = args[args.length - 1];\n if (typeof callback == 'function') {\n args.pop();\n } else {\n callback = noop;\n }\n\n async.reduce(fns, args, function (newargs, fn, cb) {\n fn.apply(that, newargs.concat([_restParam(function (err, nextargs) {\n cb(err, nextargs);\n })]));\n },\n function (err, results) {\n callback.apply(that, [err].concat(results));\n });\n });\n };\n\n async.compose = function (/* functions... */) {\n return async.seq.apply(null, Array.prototype.reverse.call(arguments));\n };\n\n\n function _applyEach(eachfn) {\n return _restParam(function(fns, args) {\n var go = _restParam(function(args) {\n var that = this;\n var callback = args.pop();\n return eachfn(fns, function (fn, _, cb) {\n fn.apply(that, args.concat([cb]));\n },\n callback);\n });\n if (args.length) {\n return go.apply(this, args);\n }\n else {\n return go;\n }\n });\n }\n\n async.applyEach = _applyEach(async.eachOf);\n async.applyEachSeries = _applyEach(async.eachOfSeries);\n\n\n async.forever = function (fn, callback) {\n var done = only_once(callback || noop);\n var task = ensureAsync(fn);\n function next(err) {\n if (err) {\n return done(err);\n }\n task(next);\n }\n next();\n };\n\n function ensureAsync(fn) {\n return _restParam(function (args) {\n var callback = args.pop();\n args.push(function () {\n var innerArgs = arguments;\n if (sync) {\n async.setImmediate(function () {\n callback.apply(null, innerArgs);\n });\n } else {\n callback.apply(null, innerArgs);\n }\n });\n var sync = true;\n fn.apply(this, args);\n sync = false;\n });\n }\n\n async.ensureAsync = ensureAsync;\n\n async.constant = _restParam(function(values) {\n var args = [null].concat(values);\n return function (callback) {\n return callback.apply(this, args);\n };\n });\n\n async.wrapSync =\n async.asyncify = function asyncify(func) {\n return _restParam(function (args) {\n var callback = args.pop();\n var result;\n try {\n result = func.apply(this, args);\n } catch (e) {\n return callback(e);\n }\n // if result is Promise object\n if (_isObject(result) && typeof result.then === \"function\") {\n result.then(function(value) {\n callback(null, value);\n })[\"catch\"](function(err) {\n callback(err.message ? err : new Error(err));\n });\n } else {\n callback(null, result);\n }\n });\n };\n\n // Node.js\n if (typeof module === 'object' && module.exports) {\n module.exports = async;\n }\n // AMD / RequireJS\n else if (typeof define === 'function' && define.amd) {\n define([], function () {\n return async;\n });\n }\n // included directly via