diff --git a/bin/pixi.js b/bin/pixi.js index 79c8df2..c5c9bf0 100644 --- a/bin/pixi.js +++ b/bin/pixi.js @@ -5157,21 +5157,23 @@ */ function VertexArrayObject(gl, state) { + this.nativeVaoExtension = null; - this.nativeVaoExtension = ( - gl.getExtension('OES_vertex_array_object') || - gl.getExtension('MOZ_OES_vertex_array_object') || - gl.getExtension('WEBKIT_OES_vertex_array_object') - ); + if(!VertexArrayObject.FORCE_NATIVE) + { + this.nativeVaoExtension = gl.getExtension('OES_vertex_array_object') || + gl.getExtension('MOZ_OES_vertex_array_object') || + gl.getExtension('WEBKIT_OES_vertex_array_object'); + } this.nativeState = state; if(this.nativeVaoExtension) { this.nativeVao = this.nativeVaoExtension.createVertexArrayOES(); - + var maxAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS); - + // VAO - overwrite the state.. this.nativeState = { tempAttribState: new Array(maxAttribs), @@ -5211,6 +5213,18 @@ VertexArrayObject.prototype.constructor = VertexArrayObject; module.exports = VertexArrayObject; +/** +* Some devices behave a bit funny when using the newer extensions (im looking at you ipad 2!) +* If you find on older devices that things have gone a bit weird then set this to true. +*/ +/** + * Lets the VAO know if you should use the WebGL extension or the native methods. + * Some devices behave a bit funny when using the newer extensions (im looking at you ipad 2!) + * If you find on older devices that things have gone a bit weird then set this to true. + * @static + * @property {Boolean} FORCE_NATIVE + */ +VertexArrayObject.FORCE_NATIVE = false; /** * Binds the buffer @@ -5229,7 +5243,7 @@ } else { - + this.activate(); } @@ -5254,7 +5268,7 @@ */ VertexArrayObject.prototype.activate = function() { - + var gl = this.gl; var lastBuffer = null; @@ -5279,7 +5293,7 @@ } setVertexAttribArrays(gl, this.attributes, this.nativeState); - + this.indexBuffer.bind(); return this; @@ -7304,7 +7318,7 @@ var parsedUrl = urlParser.parse(url); // absolute url, just use it as is. - if (parsedUrl.protocol || parsedUrl.pathname.indexOf('//') === 0) { + if (parsedUrl.protocol || !parsedUrl.pathname || parsedUrl.pathname.indexOf('//') === 0) { return url; } @@ -7456,18 +7470,18 @@ this._numToLoad--; - // do completion check - if (this._numToLoad === 0) { - this.progress = 100; - this._onComplete(); - } - if (resource.error) { this.emit('error', resource.error, this, resource); } else { this.emit('load', this, resource); } + + // do completion check + if (this._numToLoad === 0) { + this.progress = 100; + this._onComplete(); + } }); @@ -8127,7 +8141,7 @@ ext = url.substring(url.lastIndexOf('.') + 1); } - return ext; + return ext.toLowerCase(); }; /** @@ -8229,7 +8243,8 @@ 'tif': Resource.LOAD_TYPE.IMAGE, 'tiff': Resource.LOAD_TYPE.IMAGE, 'webp': Resource.LOAD_TYPE.IMAGE, - 'tga': Resource.LOAD_TYPE.IMAGE + 'tga': Resource.LOAD_TYPE.IMAGE, + 'svg+xml': Resource.LOAD_TYPE.IMAGE }; Resource._xhrTypeMap = { @@ -8401,7 +8416,7 @@ var Resource = require('../../Resource'), b64 = require('../../b64'); -window.URL = window.URL || window.webkitURL; +var Url = window.URL || window.webkitURL; // a middleware for transforming XHR loaded Blobs into more useful objects @@ -8434,7 +8449,7 @@ } // if content type says this is an image, then we should transform the blob into an Image object else if (resource.data.type.indexOf('image') === 0) { - var src = URL.createObjectURL(resource.data); + var src = Url.createObjectURL(resource.data); resource.blob = resource.data; resource.data = new Image(); @@ -8444,7 +8459,7 @@ // cleanup the no longer used blob after the image loads resource.data.onload = function () { - URL.revokeObjectURL(src); + Url.revokeObjectURL(src); resource.data.onload = null; next(); @@ -17107,14 +17122,6 @@ // know about sprites! this.quad = new Quad(this.gl, renderer.state.attribState); - var rootState = new FilterState(); - rootState.sourceFrame = rootState.destinationFrame = this.renderer.rootRenderTarget.size; - rootState.renderTarget = renderer.rootRenderTarget; - - this.stack = [rootState]; - - this.stackIndex = 0; - this.shaderCache = {}; // todo add default! this.pool = {}; @@ -17128,11 +17135,28 @@ { var renderer = this.renderer; + var filterData = this.renderer._activeRenderTarget.filterStack; + + if(!filterData) + { + // add new stack + var filterState = new FilterState(); + filterState.sourceFrame = filterState.destinationFrame = this.renderer._activeRenderTarget.size; + filterState.renderTarget = renderer._activeRenderTarget; + + this.renderer._activeRenderTarget.filterData = filterData = { + index:0, + stack:[filterState] + }; + } + + this.filterData = filterData; + // get the current filter state.. - var currentState = this.stack[++this.stackIndex]; + var currentState = filterData.stack[++filterData.index]; if(!currentState) { - currentState = this.stack[this.stackIndex] = new FilterState(); + currentState = filterData.stack[filterData.index] = new FilterState(); } // for now we go off the filter of the first resolution.. @@ -17148,7 +17172,7 @@ sourceFrame.width = (((targetBounds.width + padding*2) * resolution) | 0) / resolution; sourceFrame.height = (((targetBounds.height + padding*2)* resolution) | 0) / resolution; - sourceFrame.fit(this.stack[0].destinationFrame); + sourceFrame.fit(filterData.stack[0].destinationFrame); destinationFrame.width = sourceFrame.width; destinationFrame.height = sourceFrame.height; @@ -17172,8 +17196,10 @@ FilterManager.prototype.popFilter = function() { - var lastState = this.stack[this.stackIndex-1]; - var currentState = this.stack[this.stackIndex]; + var filterData = this.filterData; + + var lastState = filterData.stack[filterData.index-1]; + var currentState = filterData.stack[filterData.index]; this.quad.map(currentState.renderTarget.size, currentState.sourceFrame).upload(); @@ -17205,7 +17231,7 @@ this.freePotRenderTarget(flop); } - this.stackIndex--; + filterData.index--; }; FilterManager.prototype.applyFilter = function (filter, input, output, clear) @@ -17277,7 +17303,7 @@ if(shader.uniforms.data.filterArea) { - var currentState = this.stack[this.stackIndex]; + var currentState = this.filterData.stack[this.filterData.index]; var filterArea = shader.uniforms.filterArea; filterArea[0] = currentState.renderTarget.size.width; @@ -17343,7 +17369,7 @@ FilterManager.prototype.getRenderTarget = function() { - var currentState = this.stack[this.stackIndex]; + var currentState = this.filterData.stack[this.filterData.index]; var renderTarget = this.getPotRenderTarget(this.renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, currentState.resolution); renderTarget.setFrame(currentState.destinationFrame, currentState.sourceFrame); @@ -17365,13 +17391,13 @@ // thia returns a matrix that will normalise map filter cords in the filter to screen space FilterManager.prototype.calculateScreenSpaceMatrix = function (outputMatrix) { - var currentState = this.stack[this.stackIndex]; + var currentState = this.filterData.stack[this.filterData.index]; return filterTransforms.calculateScreenSpaceMatrix(outputMatrix, currentState.sourceFrame, currentState.renderTarget.size); }; FilterManager.prototype.calculateNormalisedScreenSpaceMatrix = function (outputMatrix) { - var currentState = this.stack[this.stackIndex]; + var currentState = this.filterData.stack[this.filterData.index]; @@ -17381,7 +17407,7 @@ // this will map the filter coord so that a texture can be used based on the transform of a sprite FilterManager.prototype.calculateSpriteMatrix = function (outputMatrix, sprite) { - var currentState = this.stack[this.stackIndex]; + var currentState = this.filterData.stack[this.filterData.index]; return filterTransforms.calculateSpriteMatrix(outputMatrix, currentState.sourceFrame, currentState.renderTarget.size, sprite); }; @@ -18131,14 +18157,7 @@ * * @member {object[]} */ - this.filterStack = [ - { - renderTarget:this, - filter:[], - bounds:this.size - } - ]; - + this.filterData = null; /** * The scale mode. @@ -23160,7 +23179,12 @@ var success = !!(gl && gl.getContextAttributes().stencil); if (gl) { - gl.getExtension('WEBGL_lose_context').loseContext(); + var loseContext = gl.getExtension('WEBGL_lose_context'); + + if(loseContext) + { + loseContext.loseContext(); + } } gl = null; diff --git a/bin/pixi.js b/bin/pixi.js index 79c8df2..c5c9bf0 100644 --- a/bin/pixi.js +++ b/bin/pixi.js @@ -5157,21 +5157,23 @@ */ function VertexArrayObject(gl, state) { + this.nativeVaoExtension = null; - this.nativeVaoExtension = ( - gl.getExtension('OES_vertex_array_object') || - gl.getExtension('MOZ_OES_vertex_array_object') || - gl.getExtension('WEBKIT_OES_vertex_array_object') - ); + if(!VertexArrayObject.FORCE_NATIVE) + { + this.nativeVaoExtension = gl.getExtension('OES_vertex_array_object') || + gl.getExtension('MOZ_OES_vertex_array_object') || + gl.getExtension('WEBKIT_OES_vertex_array_object'); + } this.nativeState = state; if(this.nativeVaoExtension) { this.nativeVao = this.nativeVaoExtension.createVertexArrayOES(); - + var maxAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS); - + // VAO - overwrite the state.. this.nativeState = { tempAttribState: new Array(maxAttribs), @@ -5211,6 +5213,18 @@ VertexArrayObject.prototype.constructor = VertexArrayObject; module.exports = VertexArrayObject; +/** +* Some devices behave a bit funny when using the newer extensions (im looking at you ipad 2!) +* If you find on older devices that things have gone a bit weird then set this to true. +*/ +/** + * Lets the VAO know if you should use the WebGL extension or the native methods. + * Some devices behave a bit funny when using the newer extensions (im looking at you ipad 2!) + * If you find on older devices that things have gone a bit weird then set this to true. + * @static + * @property {Boolean} FORCE_NATIVE + */ +VertexArrayObject.FORCE_NATIVE = false; /** * Binds the buffer @@ -5229,7 +5243,7 @@ } else { - + this.activate(); } @@ -5254,7 +5268,7 @@ */ VertexArrayObject.prototype.activate = function() { - + var gl = this.gl; var lastBuffer = null; @@ -5279,7 +5293,7 @@ } setVertexAttribArrays(gl, this.attributes, this.nativeState); - + this.indexBuffer.bind(); return this; @@ -7304,7 +7318,7 @@ var parsedUrl = urlParser.parse(url); // absolute url, just use it as is. - if (parsedUrl.protocol || parsedUrl.pathname.indexOf('//') === 0) { + if (parsedUrl.protocol || !parsedUrl.pathname || parsedUrl.pathname.indexOf('//') === 0) { return url; } @@ -7456,18 +7470,18 @@ this._numToLoad--; - // do completion check - if (this._numToLoad === 0) { - this.progress = 100; - this._onComplete(); - } - if (resource.error) { this.emit('error', resource.error, this, resource); } else { this.emit('load', this, resource); } + + // do completion check + if (this._numToLoad === 0) { + this.progress = 100; + this._onComplete(); + } }); @@ -8127,7 +8141,7 @@ ext = url.substring(url.lastIndexOf('.') + 1); } - return ext; + return ext.toLowerCase(); }; /** @@ -8229,7 +8243,8 @@ 'tif': Resource.LOAD_TYPE.IMAGE, 'tiff': Resource.LOAD_TYPE.IMAGE, 'webp': Resource.LOAD_TYPE.IMAGE, - 'tga': Resource.LOAD_TYPE.IMAGE + 'tga': Resource.LOAD_TYPE.IMAGE, + 'svg+xml': Resource.LOAD_TYPE.IMAGE }; Resource._xhrTypeMap = { @@ -8401,7 +8416,7 @@ var Resource = require('../../Resource'), b64 = require('../../b64'); -window.URL = window.URL || window.webkitURL; +var Url = window.URL || window.webkitURL; // a middleware for transforming XHR loaded Blobs into more useful objects @@ -8434,7 +8449,7 @@ } // if content type says this is an image, then we should transform the blob into an Image object else if (resource.data.type.indexOf('image') === 0) { - var src = URL.createObjectURL(resource.data); + var src = Url.createObjectURL(resource.data); resource.blob = resource.data; resource.data = new Image(); @@ -8444,7 +8459,7 @@ // cleanup the no longer used blob after the image loads resource.data.onload = function () { - URL.revokeObjectURL(src); + Url.revokeObjectURL(src); resource.data.onload = null; next(); @@ -17107,14 +17122,6 @@ // know about sprites! this.quad = new Quad(this.gl, renderer.state.attribState); - var rootState = new FilterState(); - rootState.sourceFrame = rootState.destinationFrame = this.renderer.rootRenderTarget.size; - rootState.renderTarget = renderer.rootRenderTarget; - - this.stack = [rootState]; - - this.stackIndex = 0; - this.shaderCache = {}; // todo add default! this.pool = {}; @@ -17128,11 +17135,28 @@ { var renderer = this.renderer; + var filterData = this.renderer._activeRenderTarget.filterStack; + + if(!filterData) + { + // add new stack + var filterState = new FilterState(); + filterState.sourceFrame = filterState.destinationFrame = this.renderer._activeRenderTarget.size; + filterState.renderTarget = renderer._activeRenderTarget; + + this.renderer._activeRenderTarget.filterData = filterData = { + index:0, + stack:[filterState] + }; + } + + this.filterData = filterData; + // get the current filter state.. - var currentState = this.stack[++this.stackIndex]; + var currentState = filterData.stack[++filterData.index]; if(!currentState) { - currentState = this.stack[this.stackIndex] = new FilterState(); + currentState = filterData.stack[filterData.index] = new FilterState(); } // for now we go off the filter of the first resolution.. @@ -17148,7 +17172,7 @@ sourceFrame.width = (((targetBounds.width + padding*2) * resolution) | 0) / resolution; sourceFrame.height = (((targetBounds.height + padding*2)* resolution) | 0) / resolution; - sourceFrame.fit(this.stack[0].destinationFrame); + sourceFrame.fit(filterData.stack[0].destinationFrame); destinationFrame.width = sourceFrame.width; destinationFrame.height = sourceFrame.height; @@ -17172,8 +17196,10 @@ FilterManager.prototype.popFilter = function() { - var lastState = this.stack[this.stackIndex-1]; - var currentState = this.stack[this.stackIndex]; + var filterData = this.filterData; + + var lastState = filterData.stack[filterData.index-1]; + var currentState = filterData.stack[filterData.index]; this.quad.map(currentState.renderTarget.size, currentState.sourceFrame).upload(); @@ -17205,7 +17231,7 @@ this.freePotRenderTarget(flop); } - this.stackIndex--; + filterData.index--; }; FilterManager.prototype.applyFilter = function (filter, input, output, clear) @@ -17277,7 +17303,7 @@ if(shader.uniforms.data.filterArea) { - var currentState = this.stack[this.stackIndex]; + var currentState = this.filterData.stack[this.filterData.index]; var filterArea = shader.uniforms.filterArea; filterArea[0] = currentState.renderTarget.size.width; @@ -17343,7 +17369,7 @@ FilterManager.prototype.getRenderTarget = function() { - var currentState = this.stack[this.stackIndex]; + var currentState = this.filterData.stack[this.filterData.index]; var renderTarget = this.getPotRenderTarget(this.renderer.gl, currentState.sourceFrame.width, currentState.sourceFrame.height, currentState.resolution); renderTarget.setFrame(currentState.destinationFrame, currentState.sourceFrame); @@ -17365,13 +17391,13 @@ // thia returns a matrix that will normalise map filter cords in the filter to screen space FilterManager.prototype.calculateScreenSpaceMatrix = function (outputMatrix) { - var currentState = this.stack[this.stackIndex]; + var currentState = this.filterData.stack[this.filterData.index]; return filterTransforms.calculateScreenSpaceMatrix(outputMatrix, currentState.sourceFrame, currentState.renderTarget.size); }; FilterManager.prototype.calculateNormalisedScreenSpaceMatrix = function (outputMatrix) { - var currentState = this.stack[this.stackIndex]; + var currentState = this.filterData.stack[this.filterData.index]; @@ -17381,7 +17407,7 @@ // this will map the filter coord so that a texture can be used based on the transform of a sprite FilterManager.prototype.calculateSpriteMatrix = function (outputMatrix, sprite) { - var currentState = this.stack[this.stackIndex]; + var currentState = this.filterData.stack[this.filterData.index]; return filterTransforms.calculateSpriteMatrix(outputMatrix, currentState.sourceFrame, currentState.renderTarget.size, sprite); }; @@ -18131,14 +18157,7 @@ * * @member {object[]} */ - this.filterStack = [ - { - renderTarget:this, - filter:[], - bounds:this.size - } - ]; - + this.filterData = null; /** * The scale mode. @@ -23160,7 +23179,12 @@ var success = !!(gl && gl.getContextAttributes().stencil); if (gl) { - gl.getExtension('WEBGL_lose_context').loseContext(); + var loseContext = gl.getExtension('WEBGL_lose_context'); + + if(loseContext) + { + loseContext.loseContext(); + } } gl = null; diff --git a/bin/pixi.js.map b/bin/pixi.js.map index b4f59a8..fbcef90 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