vis.js is a dynamic, browser-based visualization library
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

31161 lines
930 KiB

!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.eve=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<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
exports.Agent = _dereq_('./lib/Agent');
exports.ServiceManager = _dereq_('./lib/ServiceManager');
exports.TransportManager = _dereq_('./lib/TransportManager');
exports.module = {
BabbleModule: _dereq_('./lib/module/BabbleModule'),
PatternModule: _dereq_('./lib/module/PatternModule'),
RequestModule: _dereq_('./lib/module/RequestModule'),
RPCModule: _dereq_('./lib/module/RPCModule')
};
exports.transport = {
Transport: _dereq_('./lib/transport/Transport'),
AMQPTransport: _dereq_('./lib/transport/amqp/AMQPTransport'),
DistribusTransport: _dereq_('./lib/transport/distribus/DistribusTransport'),
HTTPTransport: _dereq_('./lib/transport/http/HTTPTransport'),
LocalTransport: _dereq_('./lib/transport/local/LocalTransport'),
PubNubTransport: _dereq_('./lib/transport/pubnub/PubNubTransport'),
WebSocketTransport: _dereq_('./lib/transport/websocket/WebSocketTransport'),
connection: {
Connection: _dereq_('./lib/transport/Connection'),
AMQPConnection: _dereq_('./lib/transport/amqp/AMQPConnection'),
DistribusConnection: _dereq_('./lib/transport/distribus/DistribusConnection'),
HTTPConnection: _dereq_('./lib/transport/http/HTTPConnection'),
LocalConnection: _dereq_('./lib/transport/local/LocalConnection'),
PubNubConnection: _dereq_('./lib/transport/pubnub/PubNubConnection'),
WebSocketConnection: _dereq_('./lib/transport/websocket/WebSocketConnection')
}
};
exports.hypertimer = _dereq_('hypertimer');
exports.util = _dereq_('./lib/util');
// register all modules at the Agent
exports.Agent.registerModule(exports.module.BabbleModule);
exports.Agent.registerModule(exports.module.PatternModule);
exports.Agent.registerModule(exports.module.RequestModule);
exports.Agent.registerModule(exports.module.RPCModule);
// register all transports at the TransportManager
exports.TransportManager.registerType(exports.transport.AMQPTransport);
exports.TransportManager.registerType(exports.transport.DistribusTransport);
exports.TransportManager.registerType(exports.transport.HTTPTransport);
exports.TransportManager.registerType(exports.transport.LocalTransport);
exports.TransportManager.registerType(exports.transport.PubNubTransport);
exports.TransportManager.registerType(exports.transport.WebSocketTransport);
// load the default ServiceManager, a singleton, initialized with a LocalTransport
exports.system = new exports.ServiceManager();
exports.system.transports.add(new exports.transport.LocalTransport());
// override Agent.getTransportById in order to support Agent.connect(transportId)
exports.Agent.getTransportById = function (id) {
return exports.system.transports.get(id);
};
},{"./lib/Agent":2,"./lib/ServiceManager":3,"./lib/TransportManager":4,"./lib/module/BabbleModule":5,"./lib/module/PatternModule":6,"./lib/module/RPCModule":7,"./lib/module/RequestModule":8,"./lib/transport/Connection":9,"./lib/transport/Transport":10,"./lib/transport/amqp/AMQPConnection":11,"./lib/transport/amqp/AMQPTransport":12,"./lib/transport/distribus/DistribusConnection":13,"./lib/transport/distribus/DistribusTransport":14,"./lib/transport/http/HTTPConnection":15,"./lib/transport/http/HTTPTransport":16,"./lib/transport/local/LocalConnection":17,"./lib/transport/local/LocalTransport":18,"./lib/transport/pubnub/PubNubConnection":19,"./lib/transport/pubnub/PubNubTransport":20,"./lib/transport/websocket/WebSocketConnection":21,"./lib/transport/websocket/WebSocketTransport":22,"./lib/util":23,"hypertimer":110}],2:[function(_dereq_,module,exports){
'use strict';
var Promise = _dereq_('promise');
var uuid = _dereq_('uuid-v4');
var util = _dereq_('./util');
/**
* Agent
* @param {string} [id] Id for the agent. If not provided, the agent
* will be given a uuid.
* @constructor
*/
function Agent (id) {
this.id = id ? id.toString() : uuid();
// a list with all connected transports
this.connections = [];
this.defaultConnection = null;
this.ready = Promise.resolve([]);
}
// an object with modules which can be used to extend the agent
Agent.modules = {};
/**
* Register a new type of module. This module can then be loaded via
* Agent.extend() and Agent.loadModule().
* @param {Function} constructor A module constructor
*/
Agent.registerModule = function (constructor) {
var type = constructor.prototype.type;
if (typeof constructor !== 'function') {
throw new Error('Constructor function expected');
}
if (!type) {
throw new Error('Field "prototype.type" missing in transport constructor');
}
if (type in Agent.modules) {
if (Agent.modules[type] !== constructor) {
throw new Error('Module of type "' + type + '" already exists');
}
}
Agent.modules[type] = constructor;
};
/**
* Get a transport by id.
* This static method can be overloaded for example by the get function of
* a singleton TransportManager.
* @param {string} id
* @return {Transport}
*/
Agent.getTransportById = function (id) {
throw new Error('Transport with id "' + id + '" not found');
};
/**
* Extend an agent with modules (mixins).
* The modules new functions are added to the Agent itself.
* See also function `loadModule`.
* @param {string | string[]} module A module name or an Array with module
* names. Available modules:
* 'pattern', 'request', 'babble'
* @param {Object} [options] Additional options for loading the module
* @return {Agent} Returns the agent itself
*/
Agent.prototype.extend = function (module, options) {
if (Array.isArray(module)) {
var modules = [].concat(module);
// order the modules such that 'pattern' comes first, this module must be
// loaded before other modules ('request' specifically)
modules.sort(function (a, b) {
if (a == 'pattern') return -1;
if (b == 'pattern') return 1;
return 0;
});
// an array with module names
for (var i = 0; i < modules.length; i++) {
this.extend(modules[i], options)
}
}
else {
// a single module name
var constructor = _getModuleConstructor(module);
var instance = new constructor(this, options);
var mixin = instance.mixin();
// check for conflicts in the modules mixin functions
var me = this;
Object.keys(mixin).forEach(function (name) {
if (me[name] !== undefined && name !== '_receive') {
throw new Error('Conflict: agent already has a property "' + prop + '"');
}
});
// extend the agent with all mixin functions provided by the module
Object.keys(mixin).forEach(function (name) {
me[name] = mixin[name];
});
}
return this;
};
/**
* Load a module onto an agent.
* See also function `extend`.
* @param {string | string[]} module A module name or an Array with module
* names. Available modules:
* 'pattern', 'request', 'babble'
* @param {Object} [options] Additional options for loading the module
* @return {Object} Returns the created module
*/
Agent.prototype.loadModule = function (module, options) {
var _options = options !== undefined ? Object.create(options) : {};
_options.extend = false;
var constructor = _getModuleConstructor(module);
var instance = new constructor(this, options);
var mixin = instance.mixin();
// only replace the _receive function, do not add other mixin functions
this._receive = mixin._receive;
return instance;
};
/**
* Get a module constructor by it's name.
* Throws an error when the module is not found.
* @param {string} name
* @return {function} Returns the modules constructor function
* @private
*/
function _getModuleConstructor(name) {
var constructor = Agent.modules[name];
if (!constructor) {
throw new Error('Unknown module "' + name + '". ' +
'Choose from: ' + Object.keys(Agent.modules).map(JSON.stringify).join(', '));
}
return constructor;
}
/**
* Send a message to an agent
* @param {string} to
* to is either:
* - A string "agentId", the id of the recipient. Will be send
* via the default transport or when there is no default
* transport via the first connected transport.
* - A string "agentId@transportId" Only usable locally, not
* for sharing an address with remote agents.
* - A string "protocol://networkId/agentId". This is a sharable
* identifier for an agent.
* @param {*} message Message to be send
* @return {Promise} Returns a promise which resolves when the message as
* successfully been sent, or rejected when sending the
* message failed
*/
Agent.prototype.send = function(to, message) {
var colon = to.indexOf('://');
if (colon !== -1) {
// to is an url like "protocol://networkId/agentId"
var url = util.parseUrl(to);
if (url.protocol == 'http' || url.protocol == 'ws' || url.protocol == 'https') { // TODO: ugly fixed listing here...
return this._sendByProtocol(url.protocol, to, message);
}
else {
return this._sendByNetworkId(url.domain, url.path, message);
}
}
// TODO: deprecate this notation "agentId@transportId"?
var at = to.indexOf('@');
if (at != -1) {
// to is an id like "agentId@transportId"
var _to = to.substring(0, at);
var _transportId = to.substring(at + 1);
return this._sendByTransportId(_transportId, _to, message);
}
// to is an id like "agentId". Send via the default transport
var conn = this.defaultConnection;
if (conn) {
return conn.send(to, message);
}
else {
return Promise.reject(new Error('No transport found'));
}
};
/**
* Send a transport to an agent given a networkId
* @param {string} networkId A network id
* @param {string} to An agents id
* @param {string} message Message to be send
* @return {Promise} Returns a promise which resolves when the message as
* successfully been sent, or rejected when sending the
* message failed
* @private
*/
Agent.prototype._sendByNetworkId = function(networkId, to, message) {
// TODO: change this.connections to a map with networkId as keys, much faster
for (var i = 0; i < this.connections.length; i++) {
var connection = this.connections[i];
if (connection.transport.networkId == networkId) {
return connection.send(to, message);
}
}
return Promise.reject(new Error('No transport found with networkId "' + networkId + '"'));
};
/**
* Send a message by a transport by protocol.
* The message will be send via the first found transport having the specified
* protocol.
* @param {string} protocol A protocol, for example 'http' or 'ws'
* @param {string} to An agents id
* @param {string} message Message to be send
* @return {Promise} Returns a promise which resolves when the message as
* successfully been sent, or rejected when sending the
* message failed
* @private
*/
Agent.prototype._sendByProtocol = function(protocol, to, message) {
for (var i = 0; i < this.connections.length; i++) {
var connection = this.connections[i];
if (connection.transport.type == protocol) {
return connection.send(to, message);
}
}
return Promise.reject(new Error('No transport found for protocol "' + protocol + '"'));
};
/**
* Send a transport to an agent via a specific transport
* @param {string} transportId The configured id of a transport.
* @param {string} to An agents id
* @param {string} message Message to be send
* @return {Promise} Returns a promise which resolves when the message as
* successfully been sent, or rejected when sending the
* message failed
* @private
*/
Agent.prototype._sendByTransportId = function(transportId, to, message) {
for (var i = 0; i < this.connections.length; i++) {
var connection = this.connections[i];
if (connection.transport.id == transportId) {
return connection.send(to, message);
}
}
return Promise.reject(new Error('No transport found with id "' + transportId + '"'));
};
/**
* Receive a message.
* @param {string} from Id of sender
* @param {*} message Received message, a JSON object (often a string)
*/
Agent.prototype.receive = function(from, message) {
// ... to be overloaded
};
/**
* The method _receive is overloaded in a cascaded way by modules, and calls
* the public method Agent.receive at the end of the chain.
* @param {string} from Id of sender
* @param {*} message Received message, a JSON object (often a string)
* @returns {*} Returns the return value of Agent.receive
* @private
*/
Agent.prototype._receive = function (from, message) {
return this.receive(from, message);
};
/**
* Connect to a transport. The agent will subscribe itself to
* messages sent to his id.
* @param {string | Transport | Transport[] | string[]} transport
* A Transport instance, or the id of a
* transport loaded in eve.system.
* @param {string} [id] An optional alternative id to be used
* for the connection. By default, the agents
* own id is used.
* @return {Connection | Connection[]} Returns a connection or, in case of
* multiple transports, returns an
* array with connections. The connections
* have a promise .ready which resolves
* as soon as the connection is ready for
* use.
*/
Agent.prototype.connect = function(transport, id) {
if (Array.isArray(transport)) {
var me = this;
return transport.map(function (_transport) {
return me._connect(_transport, id);
});
}
else if (typeof transport === 'string') {
// get transport by id
return this._connect(Agent.getTransportById(transport), id);
}
else {
// a transport instance
return this._connect(transport, id);
}
};
/**
* Connect to a transport
* @param {Transport} transport A Transport instance
* @param {string} [id] An optional alternative id to be used
* for the connection. By default, the agents
* own id is used.
* @return {Connection} Returns a connection.
* @private
*/
Agent.prototype._connect = function (transport, id) {
// create a receive function which is bound to the _receive function.
// the _receive function can be replaced in by modules in a cascaded way,
// and in the end calls this.receive of the agent.
// note: we don't do receive = this._receive.bind(this) as the _receive
// function can be overloaded after a connection is made.
var me = this;
var receive = function (from, message) {
return me._receive(from, message);
};
var connection = transport.connect(id || this.id, receive);
this.connections.push(connection);
// set or replace the defaultConnection
if (!this.defaultConnection) {
this.defaultConnection = connection;
}
else if (transport['default']) {
if (this.defaultConnection['default']) {
throw new Error('Cannot connect to a second default transport');
}
this.defaultConnection = connection;
}
this._updateReady();
return connection;
};
/**
* Disconnect from one or multiple transports
* @param {string | Transport | string[] | Transport[]} [transport]
* A transport or an array with transports.
* parameter transport can be an instance of a Transport, or the
* id of a transport.
* When transport is undefined, the agent will be disconnected
* from all connected transports.
*/
Agent.prototype.disconnect = function(transport) {
var i, connection;
if (!transport) {
// disconnect all transports
while (connection = this.connections[0]) {
this._disconnect(connection);
}
}
else if (Array.isArray(transport)) {
// an array with transports
i = 0;
while (i < this.connections.length) {
connection = this.connections[i];
if (transport.indexOf(connection.transport) !== -1) {
this._disconnect(connection);
}
else {
i++;
}
}
}
else if (typeof transport === 'string') {
// transport by id
this.disconnect(Agent.getTransportById(transport));
}
else {
// a single transport
for (i = 0; i < this.connections.length; i++) {
connection = this.connections[i];
if (connection.transport === transport) {
this._disconnect(connection);
break;
}
}
}
};
/**
* Close a connection
* @param {Connection} connection
* @private
*/
Agent.prototype._disconnect = function (connection) {
// find the connection
var index = this.connections.indexOf(connection);
if (index !== -1) {
// close the connection
connection.close();
// remove from the list with connections
this.connections.splice(index, 1);
// replace the defaultConnection if needed
if (this.defaultConnection === connection) {
this.defaultConnection = this.connections[this.connections.length - 1] || null;
}
}
this._updateReady();
};
/**
* Update the ready state of the agent
* @private
*/
Agent.prototype._updateReady = function () {
// FIXME: we should not replace with a new Promise,
// we have a problem when this.ready is requested before ready,
// and another connection is opened before ready
this.ready = Promise.all(this.connections.map(function (connection) {
return connection.ready;
}));
};
module.exports = Agent;
},{"./util":23,"promise":114,"uuid-v4":125}],3:[function(_dereq_,module,exports){
'use strict';
var seed = _dereq_('seed-random');
var hypertimer = _dereq_('hypertimer');
var TransportManager = _dereq_('./TransportManager');
// map with known configuration properties
var KNOWN_PROPERTIES = {
transports: true,
timer: true,
random: true
};
function ServiceManager(config) {
this.transports = new TransportManager();
this.timer = hypertimer();
this.random = Math.random;
this.init(config);
}
/**
* Initialize the service manager with services loaded from a configuration
* object. All current services are unloaded and removed.
* @param {Object} config
*/
ServiceManager.prototype.init = function (config) {
this.transports.clear();
if (config) {
if (config.transports) {
this.transports.load(config.transports);
}
if (config.timer) {
this.timer.config(config.timer);
}
if (config.random) {
if (config.random.deterministic) {
var key = config.random.seed || 'random seed';
this.random = seed(key, config.random);
}
else {
this.random = Math.random;
}
}
for (var prop in config) {
if (config.hasOwnProperty(prop) && !KNOWN_PROPERTIES[prop]) {
// TODO: should log this warning via a configured logger
console.log('WARNING: Unknown configuration option "' + prop + '"')
}
}
}
};
/**
* Clear all configured services
*/
ServiceManager.prototype.clear = function () {
this.transports.clear();
};
module.exports = ServiceManager;
},{"./TransportManager":4,"hypertimer":110,"seed-random":124}],4:[function(_dereq_,module,exports){
'use strict';
/**
* A manager for loading and finding transports.
* @param {Array} [config] Optional array containing configuration objects
* for transports.
* @constructor
*/
function TransportManager(config) {
this.transports = [];
if (config) {
this.load(config);
}
}
// map with all registered types of transports
// each transport must register itself at the TransportManager using registerType.
TransportManager.types = {};
/**
* Register a new type of transport. This transport can then be loaded via
* configuration.
* @param {Transport.prototype} constructor A transport constructor
*/
TransportManager.registerType = function (constructor) {
var type = constructor.prototype.type;
if (typeof constructor !== 'function') {
throw new Error('Constructor function expected');
}
if (!type) {
throw new Error('Field "prototype.type" missing in transport constructor');
}
if (type in TransportManager.types) {
if (TransportManager.types[type] !== constructor) {
throw new Error('Transport type "' + type + '" already exists');
}
}
TransportManager.types[type] = constructor;
};
/**
* Add a loaded transport to the manager
* @param {Transport} transport
* @return {Transport} returns the transport itself
*/
TransportManager.prototype.add = function (transport) {
this.transports.push(transport);
return transport;
};
/**
* Load one or multiple transports based on JSON configuration.
* New transports will be appended to current transports.
* @param {Object | Array} config
* @return {Transport | Transport[]} Returns the loaded transport(s)
*/
TransportManager.prototype.load = function (config) {
if (Array.isArray(config)) {
return config.map(this.load.bind(this));
}
var type = config.type;
if (!type) {
throw new Error('Property "type" missing');
}
var constructor = TransportManager.types[type];
if (!constructor) {
throw new Error('Unknown type of transport "' + type + '". ' +
'Choose from: ' + Object.keys(TransportManager.types).join(','))
}
var transport = new constructor(config);
this.transports.push(transport);
return transport;
};
/**
* Unload a transport.
* @param {Transport | Transport[] | string | string[]} transport
* A Transport instance or the id of a transport, or an Array
* with transports or transport ids.
*/
TransportManager.prototype.unload = function (transport) {
var _transport;
if (typeof transport === 'string') {
_transport = this.get(transport);
}
else if (Array.isArray(transport)) {
for (var i = 0; i < transport.length; i++) {
this.unload(transport[i]);
}
}
else {
_transport = transport;
}
if (_transport) {
_transport.close();
var index = this.transports.indexOf(_transport);
if (index !== -1) {
this.transports.splice(index, 1);
}
}
};
/**
* Get a transport by its id. The transport must have been created with an id
* @param {string} [id] The id of a transport
* @return {Transport} Returns the transport when found. Throws an error
* when not found.
*/
TransportManager.prototype.get = function (id) {
for (var i = 0; i < this.transports.length; i++) {
var transport = this.transports[i];
if (transport.id === id) {
return transport;
}
}
throw new Error('Transport with id "' + id + '" not found');
};
/**
* Get all transports.
* @return {Transport[]} Returns an array with all loaded transports.
*/
TransportManager.prototype.getAll = function () {
return this.transports.concat([]);
};
/**
* Find transports by type.
* @param {string} [type] Type of the transport. Choose from 'amqp',
* 'distribus', 'local', 'pubnub'.
* @return {Transport[]} When type is defined, the all transports of this
* type are returned. When undefined, all transports
* are returned.
*/
TransportManager.prototype.getByType = function (type) {
if (type) {
if (!(type in TransportManager.types)) {
throw new Error('Unknown type of transport "' + type + '". ' +
'Choose from: ' + Object.keys(TransportManager.types).join(','))
}
return this.transports.filter(function (transport) {
return transport.type === type;
});
}
else {
return [].concat(this.transports);
}
};
/**
* Close all configured transports and remove them from the manager.
*/
TransportManager.prototype.clear = function () {
this.transports.forEach(function (transport) {
transport.close();
});
this.transports = [];
};
module.exports = TransportManager;
},{}],5:[function(_dereq_,module,exports){
'use strict';
var babble = _dereq_('babble');
/**
* Create a Babble module for an agent.
* The agents _receive function is wrapped into a new handler.
* Creates a Babble instance with function `ask`, `tell`, `listen`, `listenOnce`
* @param {Agent} agent
* @param {Object} [options] Optional parameters. Not applicable for BabbleModule
* @constructor
*/
function BabbleModule(agent, options) {
// create a new babbler
var babbler = babble.babbler(agent.id);
babbler.connect({
connect: function (params) {},
disconnect: function(token) {},
send: function (to, message) {
agent.send(to, message);
}
});
this.babbler = babbler;
// create a receive function for the agent
var receiveOriginal = agent._receive;
this._receive = function (from, message) {
babbler._receive(message);
// TODO: only propagate to receiveOriginal if the message is not handled by the babbler
return receiveOriginal.call(agent, from, message);
};
}
BabbleModule.prototype.type = 'babble';
/**
* Get a map with mixin functions
* @return {{_receive: function, ask: function, tell: function, listen: function, listenOnce: function}}
* Returns mixin function, which can be used to extend the agent.
*/
BabbleModule.prototype.mixin = function () {
var babbler = this.babbler;
return {
_receive: this._receive,
ask: babbler.ask.bind(babbler),
tell: babbler.tell.bind(babbler),
listen: babbler.listen.bind(babbler),
listenOnce: babbler.listenOnce.bind(babbler)
}
};
module.exports = BabbleModule;
},{"babble":40}],6:[function(_dereq_,module,exports){
'use strict';
/**
* Create a pattern listener onto an Agent.
* A new handler is added to the agents _receiver function.
* Creates a Pattern instance with functions `listen` and `unlisten`.
* @param {Agent} agent
* @param {Object} [options] Optional parameters. Can contain properties:
* - stopPropagation: boolean
* When false (default), a message
* will be delivered at all
* matching pattern listeners.
* When true, a message will be
* be delivered at the first
* matching pattern listener only.
*/
function PatternModule(agent, options) {
this.agent = agent;
this.stopPropagation = options && options.stopPropagation || false;
this.receiveOriginal = agent._receive;
this.listeners = [];
}
PatternModule.prototype.type = 'pattern';
/**
* Receive a message.
* All pattern listeners will be checked against their patterns, and if there
* is a match, the pattern listeners callback function is invoked.
* @param {string} from Id of sender
* @param {*} message Received message, a JSON object (often a string)
*/
PatternModule.prototype.receive = function(from, message) {
var response;
var responses = [];
for (var i = 0, ii = this.listeners.length; i < ii; i++) {
var listener = this.listeners[i];
var pattern = listener.pattern;
var match = (pattern instanceof Function && pattern(message)) ||
(pattern instanceof RegExp && pattern.test(message)) ||
(pattern == message);
if (match) {
response = listener.callback.call(this.agent, from, message);
responses.push(response);
if (this.stopPropagation) {
return responses[0];
}
}
}
response = this.receiveOriginal.call(this.agent, from, message);
responses.push(response);
return responses[0];
};
/**
* Add a pattern listener for incoming messages
* @param {string | RegExp | Function} pattern Message pattern
* @param {Function} callback Callback function invoked when
* a message matching the pattern
* is received.
* Invoked as callback(from, message)
*/
PatternModule.prototype.listen = function(pattern, callback) {
this.listeners.push({
pattern: pattern,
callback: callback
});
};
/**
* Remove a pattern listener for incoming messages
* @param {string | RegExp | Function} pattern Message pattern
* @param {Function} callback
*/
PatternModule.prototype.unlisten = function(pattern, callback) {
for (var i = 0, ii = this.listeners.length; i < ii; i++) {
var listener = this.listeners[i];
if (listener.pattern === pattern && listener.callback === callback) {
this.listeners.splice(i, 1);
break;
}
}
};
/**
* Get a map with mixin functions
* @return {{_receive: function, listen: function, unlisten: function}}
* Returns mixin function, which can be used to extend the agent.
*/
PatternModule.prototype.mixin = function () {
return {
_receive: this.receive.bind(this),
listen: this.listen.bind(this),
unlisten: this.unlisten.bind(this)
}
};
module.exports = PatternModule;
},{}],7:[function(_dereq_,module,exports){
'use strict';
var uuid = _dereq_('uuid-v4');
var Promise = _dereq_('promise');
var util = _dereq_('../util');
/**
*
* @param {Agent} agent
* @param {Object} availableFunctions
* @constructor
*/
function RPCModule(agent, availableFunctions) {
this.agent = agent;
this.receiveOriginal = agent._receive;
this.queue = {};
this.promiseTimeout = 1500; // 1 second
// check the available functions
if (availableFunctions instanceof Array) {
this.functionsFromArray(availableFunctions);
}
else if (availableFunctions instanceof Object) {
this.availableFunctions = availableFunctions;
}
else {
console.log('cannot use RPC with the supplied functions', availableFunctions);
}
}
RPCModule.prototype.type = 'rpc';
/**
*
* @param availableFunctions
*/
RPCModule.prototype.functionsFromArray = function (availableFunctions) {
this.availableFunctions = {};
for (var i = 0; i < availableFunctions.length; i++) {
var fn = availableFunctions[i];
this.availableFunctions[fn] = this.agent[fn];
}
};
/**
*
* @param to
* @param message
* @returns {Promise}
*/
RPCModule.prototype.request = function (to, message) {
var me = this;
return new Promise(function (resolve, reject) {
// prepare the envelope
if (typeof message != 'object' ) {reject(new TypeError('Message must be an object'));}
if (message.jsonrpc !== '2.0' ) {message.jsonrpc = '2.0';}
if (message.id === undefined) {message.id = uuid();}
if (message.method === undefined) {reject(new Error('Property "method" expected'));}
if (message.params === undefined) {message.params = {};}
// add the request to the list with requests in progress
me.queue[message.id] = {
resolve: resolve,
reject: reject,
timeout: setTimeout(function () {
delete me.queue[message.id];
reject(new Error('Timeout'));
}, me.promiseTimeout)
};
var sendRequest = me.agent.send(to, message);
if (util.isPromise(sendRequest) == true) {
sendRequest.catch(function (err) {reject(err);});
}
});
};
/**
*
* @param from
* @param message
* @returns {*}
*/
RPCModule.prototype.receive = function (from, message) {
if (typeof message == 'object') {
if (message.jsonrpc == '2.0') {
this._receive(from, message);
}
else {
this.receiveOriginal.call(this.agent, from, message);
}
}
else {
this.receiveOriginal.call(this.agent, from, message);
}
};
/**
*
* @param from
* @param message
* @returns {*}
* @private
*/
RPCModule.prototype._receive = function (from, message) {
// define structure of return message
var returnMessage = {jsonrpc:'2.0', id:message.id};
// check if this is a request
if (message.method !== undefined) {
// check is method is available for this agent
var method = this.availableFunctions[message.method];
if (method !== undefined) {
var response = method.call(this.agent, message.params, from) || null;
// check if response is a promise
if (util.isPromise(response)) {
var me = this;
response
.then(function (result) {
returnMessage.result = result;
me.agent.send(from, returnMessage)
})
.catch(function (error) {
returnMessage.error = error.message || error.toString();
me.agent.send(from, returnMessage);
})
}
else {
returnMessage.result = response;
this.agent.send(from, returnMessage);
}
}
else {
var error = new Error('Cannot find function: ' + message.method);
returnMessage.error = error.message || error.toString();
this.agent.send(from, returnMessage);
}
}
// check if this is a response
else if (message.result !== undefined || message.error !== undefined) {
var request = this.queue[message.id];
if (request !== undefined) {
// if an error is defined, reject promise
if (message.error != undefined) { // null or undefined
// FIXME: returned error should be an object {code: number, message: string}
request.reject(new Error(message.error));
}
else {
request.resolve(message.result);
}
}
}
else {
// send error back to sender.
var error = new Error('No method or result defined. Message:' + JSON.stringify(message));
returnMessage.error = error.message || error.toString();
// FIXME: returned error should be an object {code: number, message: string}
this.agent.send(from, returnMessage);
}
};
/**
* Get a map with mixin functions
* @return {{_receive: function, request: function}}
* Returns mixin function, which can be used to extend the agent.
*/
RPCModule.prototype.mixin = function () {
return {
_receive: this.receive.bind(this),
request: this.request.bind(this)
}
};
module.exports = RPCModule;
},{"../util":23,"promise":114,"uuid-v4":125}],8:[function(_dereq_,module,exports){
'use strict';
var uuid = _dereq_('uuid-v4');
var Promise = _dereq_('promise');
var util = _dereq_('../util');
var TIMEOUT = 60000; // ms
/**
* Create a Request module.
* The module attaches a handler to the agents _receive function.
* Creates a Request instance with function `request`.
* @param {Agent} agent
* @param {Object} [options] Optional parameters. Can contain properties:
* - timeout: number A timeout for responses in
* milliseconds. 60000 ms by
* default.
*/
function RequestModule(agent, options) {
this.agent = agent;
this.receiveOriginal = agent._receive;
this.timeout = options && options.timeout || TIMEOUT;
this.queue = [];
}
RequestModule.prototype.type = 'request';
/**
* Event handler, handles incoming messages
* @param {String} from Id of the sender
* @param {*} message
* @return {boolean} Returns true when a message is handled, else returns false
*/
RequestModule.prototype.receive = function (from, message) {
var agent = this.agent;
if (typeof message === 'object') {
var envelope = message;
// match the request from the id in the response
var request = this.queue[envelope.id];
if (request) {
// remove the request from the queue
clearTimeout(request.timeout);
delete this.queue[envelope.id];
// resolve the requests promise with the response message
if (envelope.error) {
// TODO: turn this into an Error instance again
request.reject(new Error(envelope.error));
}
else {
request.resolve(envelope.message);
}
return true;
}
else if (message.type == 'request') {
try {
var response = this.receiveOriginal.call(agent, from, message.message);
if (util.isPromise(response)) {
// wait until the promise resolves
response
.then(function (result) {
agent.send(from, {type: 'request', id: message.id, message: result});
})
.catch(function (err) {
agent.send(from, {type: 'request', id: message.id, error: err.message || err.toString()});
});
}
else {
// immediately send a result
agent.send(from, {type: 'request', id: message.id, message: response });
}
}
catch (err) {
agent.send(from, {type: 'request', id: message.id, error: err.message || err.toString()});
}
}
}
else {
if (this.receiveOriginal) {
this.receiveOriginal.call(agent, from, message);
}
}
};
/**
* Send a request
* @param {string} to Id of the recipient
* @param {*} message
* @returns {Promise.<*, Error>} Returns a promise resolving with the response message
*/
RequestModule.prototype.request = function (to, message) {
var me = this;
return new Promise(function (resolve, reject) {
// put the data in an envelope with id
var id = uuid();
var envelope = {
type: 'request',
id: id,
message: message
};
// add the request to the list with requests in progress
me.queue[id] = {
resolve: resolve,
reject: reject,
timeout: setTimeout(function () {
delete me.queue[id];
reject(new Error('Timeout'));
}, me.timeout)
};
me.agent.send(to, envelope)
.catch(function (err) {
reject(err);
});
});
};
/**
* Get a map with mixin functions
* @return {{_receive: function, request: function}}
* Returns mixin function, which can be used to extend the agent.
*/
RequestModule.prototype.mixin = function () {
return {
_receive: this.receive.bind(this),
request: this.request.bind(this)
}
};
module.exports = RequestModule;
},{"../util":23,"promise":114,"uuid-v4":125}],9:[function(_dereq_,module,exports){
'use strict';
var Promise = _dereq_('promise');
/**
* An abstract Transport connection
* @param {Transport} transport
* @param {string} id
* @param {function} receive
* @constructor
* @abstract
*/
function Connection (transport, id, receive) {
throw new Error('Cannot create an abstract Connection');
}
Connection.prototype.ready = Promise.reject(new Error('Cannot get abstract property ready'));
/**
* Send a message to an agent.
* @param {string} to
* @param {*} message
* @return {Promise} returns a promise which resolves when the message has been sent
*/
Connection.prototype.send = function (to, message) {
throw new Error('Cannot call abstract function send');
};
/**
* Close the connection, disconnect from the transport.
*/
Connection.prototype.close = function () {
throw new Error('Cannot call abstract function "close"');
};
module.exports = Connection;
},{"promise":114}],10:[function(_dereq_,module,exports){
'use strict';
/**
* Abstract prototype of a transport
* @param {Object} [config]
* @constructor
*/
function Transport(config) {
this.id = config && config.id || null;
this['default'] = config && config['default'] || false;
}
Transport.prototype.type = null;
/**
* Connect an agent
* @param {String} id
* @param {Function} receive Invoked as receive(from, message)
* @return {Connection} Returns a connection
*/
Transport.prototype.connect = function(id, receive) {
throw new Error('Cannot invoke abstract function "connect"');
};
/**
* Close the transport
*/
Transport.prototype.close = function() {
throw new Error('Cannot invoke abstract function "close"');
};
module.exports = Transport;
},{}],11:[function(_dereq_,module,exports){
'use strict';
var Promise = _dereq_('promise');
var Connection = _dereq_('../Connection');
/**
* A local connection.
* @param {AMQPTransport} transport
* @param {string | number} id
* @param {function} receive
* @constructor
*/
function AMQPConnection(transport, id, receive) {
this.transport = transport;
this.id = id;
// ready state
this.ready = this.transport._connect(id, receive);
}
/**
* Send a message to an agent.
* @param {string} to
* @param {*} message
* @return {Promise} returns a promise which resolves when the message has been sent
*/
AMQPConnection.prototype.send = function (to, message) {
var me = this;
return new Promise(function (resolve, reject) {
var msg = {
body: {
from: me.id,
to: to,
message: message
}
};
var options = {
//immediate: true
};
me.transport.exchange.publish(to, msg, options, function () {
// FIXME: callback is not called.
//console.log('sent', arguments)
});
resolve();
});
};
/**
* Close the connection
*/
AMQPConnection.prototype.close = function () {
this.transport._close(this.id);
};
module.exports = AMQPConnection;
},{"../Connection":9,"promise":114}],12:[function(_dereq_,module,exports){
'use strict';
var Promise = _dereq_('promise');
var Transport = _dereq_('./../Transport');
var AMQPConnection = _dereq_('./AMQPConnection');
/**
* Use AMQP as transport
* @param {Object} config Config can contain the following properties:
* - `id: string`
* - `url: string`
* - `host: string`
* The config must contain either `url` or `host`.
* For example: {url: 'amqp://localhost'} or
* {host: 'dev.rabbitmq.com'}
* @constructor
*/
function AMQPTransport(config) {
this.id = config.id || null;
this.networkId = config.url || config.host || null;
this['default'] = config['default'] || false;
this.config = config;
this.connection = null;
this.exchange = null;
this.subscriptions = [];
}
AMQPTransport.prototype = new Transport();
AMQPTransport.prototype.type = 'amqp';
/**
* Connect an agent
* @param {String} id
* @param {Function} receive Invoked as receive(from, message)
* @return {AMQPConnection} Returns a connection.
*/
AMQPTransport.prototype.connect = function(id, receive) {
return new AMQPConnection(this, id, receive);
};
/**
* Get an AMQP connection. If there is not yet a connection, a connection will
* be made.
* @param {Function} callback Invoked as callback(connection)
* @private
*/
AMQPTransport.prototype._getConnection = function(callback) {
var me = this;
if (this.connection) {
// connection is available
callback(this.connection);
}
else {
if (this._onConnected) {
// connection is being opened but not yet ready
this._onConnected.push(callback);
}
else {
// no connection, create one
this._onConnected = [callback];
var amqp = _dereq_('amqp'); // lazy load the amqp library
var connection = amqp.createConnection(this.config);
connection.on('ready', function () {
var exchange = connection.exchange('', {confirm: true}, function () {
var _onConnected = me._onConnected;
delete me._onConnected;
me.connection = connection;
me.exchange = exchange;
_onConnected.forEach(function (callback) {
callback(me.connection);
});
});
});
}
}
};
/**
* Open a connection
* @param {string} id
* @param {Function} receive Invoked as receive(from, message)
*/
AMQPTransport.prototype._connect = function(id, receive) {
var me = this;
return new Promise(function (resolve, reject) {
function subscribe(connection) {
var queue = connection.queue(id, {}, function() {
queue
.subscribe(function(message) {
var body = message.body;
receive(body.from, body.message);
})
.addCallback(function (ok) {
// register this subscription
me.subscriptions.push({
id: id,
consumerTag: ok.consumerTag
});
resolve(me);
});
});
}
me._getConnection(subscribe);
});
};
/**
* Close a connection an agent by its id
* @param {String} id
*/
AMQPTransport.prototype._close = function(id) {
var i = 0;
while (i < this.subscriptions.length) {
var subscription = this.subscriptions[i];
if (subscription.id == id) {
// remove this entry
this.subscriptions.splice(i, 1);
}
else {
i++;
}
}
if (this.subscriptions.length == 0) {
// fully disconnect if there are no subscribers left
this.exchange.destroy();
this.connection.disconnect();
this.connection = null;
this.exchange = null;
}
};
/**
* Close the transport.
*/
AMQPTransport.prototype.close = function() {
this.connection.destroy();
this.connection = null;
};
module.exports = AMQPTransport;
},{"./../Transport":10,"./AMQPConnection":11,"amqp":24,"promise":114}],13:[function(_dereq_,module,exports){
'use strict';
var Promise = _dereq_('promise');
var Connection = _dereq_('../Connection');
/**
* A local connection.
* @param {DistribusTransport} transport
* @param {string | number} id
* @param {function} receive
* @constructor
*/
function DistribusConnection(transport, id, receive) {
this.transport = transport;
this.id = id;
// create a peer
var peer = this.transport.host.create(id);
peer.on('message', receive);
// ready state
this.ready = Promise.resolve(this);
}
/**
* Send a message to an agent.
* @param {string} to
* @param {*} message
* @return {Promise} returns a promise which resolves when the message has been sent
*/
DistribusConnection.prototype.send = function (to, message) {
return this.transport.host.send(this.id, to, message);
};
/**
* Close the connection
*/
DistribusConnection.prototype.close = function () {
this.transport.host.remove(this.id);
};
module.exports = DistribusConnection;
},{"../Connection":9,"promise":114}],14:[function(_dereq_,module,exports){
'use strict';
var distribus = _dereq_('distribus');
var Transport = _dereq_('./../Transport');
var DistribusConnection = _dereq_('./DistribusConnection');
/**
* Use distribus as transport
* @param {Object} config Config can contain the following properties:
* - `id: string`. Optional
* - `host: distribus.Host`. Optional
* If `host` is not provided,
* a new local distribus Host is created.
* @constructor
*/
function DistribusTransport(config) {
this.id = config && config.id || null;
this['default'] = config && config['default'] || false;
this.host = config && config.host || new distribus.Host(config);
this.networkId = this.host.networkId; // FIXME: networkId can change when host connects to another host.
}
DistribusTransport.prototype = new Transport();
DistribusTransport.prototype.type = 'distribus';
/**
* Connect an agent
* @param {String} id
* @param {Function} receive Invoked as receive(from, message)
* @return {DistribusConnection} Returns a connection.
*/
DistribusTransport.prototype.connect = function(id, receive) {
return new DistribusConnection(this, id, receive);
};
/**
* Close the transport.
*/
DistribusTransport.prototype.close = function() {
this.host.close();
this.host = null;
};
module.exports = DistribusTransport;
},{"./../Transport":10,"./DistribusConnection":13,"distribus":67}],15:[function(_dereq_,module,exports){
'use strict';
var Promise = _dereq_('promise');
var Connection = _dereq_('../Connection');
/**
* A HTTP connection.
* @param {HTTPTransport} transport
* @param {string | number} id
* @param {function} receive
* @constructor
*/
function HTTPConnection(transport, id, receive) {
this.transport = transport;
this.id = id;
// register the agents receive function
if (this.id in this.transport.agents) {
throw new Error('Agent with id ' + id + ' already exists');
}
this.transport.agents[this.id] = receive;
// ready state
this.ready = Promise.resolve(this);
}
/**
* Send a message to an agent.
* @param {string} to
* @param {*} message
*/
HTTPConnection.prototype.send = function (to, message) {
var fromURL = this.transport.url.replace(':id', this.id);
var isURL = to.indexOf('://') !== -1;
var toURL;
if (isURL) {
toURL = to;
}
else {
if (this.transport.remoteUrl !== undefined) {
toURL = this.transport.remoteUrl.replace(':id', to);
}
else {
console.log('ERROR: no remote URL specified. Cannot send over HTTP.', to);
}
}
return this.transport.send(fromURL, toURL, message);
};
/**
* Close the connection
*/
HTTPConnection.prototype.close = function () {
delete this.transport.agents[this.id];
};
module.exports = HTTPConnection;
},{"../Connection":9,"promise":114}],16:[function(_dereq_,module,exports){
'use strict';
var http = _dereq_('http');
var Promise = _dereq_('promise');
var Transport = _dereq_('./../Transport');
var HTTPConnection = _dereq_('./HTTPConnection');
var uuid = _dereq_('uuid-v4');
/**
* HTTP Transport layer:
*
* Supported Options:
*
* {Number} config.port Port to listen on.
* {String} config.path Path, with or without leading and trailing slash (/)
* {Boolean} config.localShortcut If the agentId exists locally, use local transport. (local)
*
* Address: http://127.0.0.1:PORTNUMBER/PATH
*/
function HTTPTransport(config) {
this.id = config && config.id || null;
this.networkId = null;
this.agents = {};
this.outstandingRequests = {}; // these are received messages that are expecting a response
this.outstandingMessages = {};
this.url = config && config.url || "http://127.0.0.1:3000/agents/:id";
this.remoteUrl = config && config.remoteUrl;
this.localShortcut = (config && config.localShortcut === false) ? false : true;
this.httpTimeout = config && config.httpTimeout || 2000; // 1 second - timeout to send message
this.httpResponseTimeout = config && config.httpResponseTimeout || 200; // 0.5 second - timeout to expect reply after delivering request
this.regexHosts = /[http]{4}s?:\/\/([a-z\-\.A-Z0-9]*):?([0-9]*)(\/[a-z\/:A-Z0-9._\-% \\\(\)\*\+\.\^\$]*)/;
this.urlHostData = this.regexHosts.exec(this.url);
this.regexPath = this.getRegEx(this.urlHostData[3]);
this.port = config && config.port || this.urlHostData[2] || 3000;
this.path = this.urlHostData[3].replace(':id', '');
}
HTTPTransport.prototype = new Transport();
HTTPTransport.prototype.type = 'http';
HTTPTransport.prototype.getRegEx = function(url) {
return new RegExp(url.replace(/[\\\(\)\*\+\.\^\$]/g,function(match) {return '\\' + match;}).replace(':id','([:a-zA-Z_0-9]*)'));
};
function askAgent(url,method,params,callback, async) {
if (async === undefined) {
async = true;
}
// create post request
var POSTrequest = JSON.stringify({"id":0, "method": method, "params": params});
// create XMLHttpRequest object to send the POST request
var http = new XMLHttpRequest();
// insert the callback function. This is called when the message has been delivered and a response has been received
http.onreadystatechange = function () {
if (http.readyState == 4 && http.status == 200) {
if (callback === undefined || callback === null) {
}
else {
// launch callback function
callback(JSON.parse(http.responseText));
}
}
else if (http.readyState == 4 && http.status != 200) {
console.log("Make sure that the Node server has started.");
}
};
// open an asynchronous POST connection
http.open("POST", url, async);
// include header so the receiving code knows its a JSON object
http.setRequestHeader("Content-type", "application/json");
// send
http.send(POSTrequest);
}
/**
* Connect an agent
* @param {String} id
* @param {Function} receive Invoked as receive(from, message)
* @return {HTTPConnection} Returns a connection.
*/
HTTPTransport.prototype.connect = function(id, receive) {
if (this.server === undefined) {
this.initiateServer();
}
this.outstandingRequests[id] = {};
this.outstandingMessages[id] = {};
return new HTTPConnection(this, id, receive);
};
/**
* Send a message to an agent
* @param {String} from Id of sender
* @param {String} to Id of addressed peer
* @param {String} message
*/
HTTPTransport.prototype.send = function(from, to, message) {
var me = this;
return new Promise(function (resolve,reject) {
var hostData = me.regexHosts.exec(to);
var fromRegexpCheck = me.regexPath.exec(from);
var fromAgentId = fromRegexpCheck[1];
var outstandingMessageID = uuid();
// check for local shortcut possibility
if (me.localShortcut == true) {
var toRegexpCheck = me.regexPath.exec(to);
var toAgentId = toRegexpCheck[1];
var toPath = hostData[3].replace(toAgentId,"");
// check if the "to" address is on the same URL, port and path as the "from"
if ((hostData[1] == '127.0.0.1' && hostData[2] == me.urlHostData[2] && toPath == me.path) ||
(me.urlHostData[1] == hostData[1] && hostData[2] == me.urlHostData[2] && toPath == me.path)) {
// by definition true but check anyway
if (me.agents[toAgentId] !== undefined) {
me.agents[toAgentId](fromAgentId, message);
resolve();
return;
}
}
}
// stringify the message. If the message is an object, it can have an ID so it may be part of a req/rep.
if (typeof message == 'object') {
// check if the send is a reply to an outstanding request and if so, deliver
var outstanding = me.outstandingRequests[fromAgentId];
if (outstanding[message.id] !== undefined) {
var callback = outstanding[message.id];
callback.response.end(JSON.stringify(message));
clearTimeout(callback.timeout);
delete outstanding[message.id];
resolve();
return;
}
// stringify the message.
message = JSON.stringify(message)
}
// all post options
var options = {
host: hostData[1],
port: hostData[2],
path: hostData[3],
method: 'POST',
headers: {
'x-eve-senderurl' : from, // used to get senderID
'Content-type' : 'text/plain'
}
};
var request = http.request(options, function(res) {
res.setEncoding('utf8');
// message was delivered, clear the cannot deliver timeout.
clearTimeout(me.outstandingMessages[fromAgentId][outstandingMessageID].timeout);
// listen to incoming data
res.on('data', function (response) {
var parsedResponse;
try {parsedResponse = JSON.parse(response);} catch (err) {parsedResponse = response;}
if (typeof parsedResponse == 'object') {
if (parsedResponse.__httpError__ !== undefined) {
reject(new Error(parsedResponse.__httpError__));
return;
}
}
me.agents[fromAgentId](to, parsedResponse);
resolve();
});
});
me.outstandingMessages[fromAgentId][outstandingMessageID] = {
timeout: setTimeout(function () {
request.abort();
reject(new Error("Cannot connect to " + to))
}, me.httpTimeout),
reject: reject
};
request.on('error', function(e) {
reject(e);
});
// write data to request body
request.write(message);
request.end();
});
};
/**
* This is the HTTP equivalent of receiveMessage.
*
* @param request
* @param response
*/
HTTPTransport.prototype.processRequest = function(request, response) {
var url = request.url;
// define headers
var headers = {};
headers['Access-Control-Allow-Origin'] = '*';
headers['Access-Control-Allow-Credentials'] = true;
headers['Content-Type'] = 'text/plain';
var regexpCheck = this.regexPath.exec(url);
if (regexpCheck !== null) {
var agentId = regexpCheck[1];
var senderId = 'unknown';
if (request.headers['x-eve-senderurl'] !== undefined) {
senderId = request.headers['x-eve-senderurl'];
}
var body = '';
request.on('data', function (data) {
body += data;
if (body.length > 1e6) { // 1e6 == 1MB
request.connection.destroy(); // FLOOD ATTACK OR FAULTY CLIENT, NUKE REQUEST
}
});
var me = this;
request.on('end', function () {
var expectReply = false;
var message;
try {message = JSON.parse(body);} catch (err) {message = body;}
// check if JSON RPC
expectReply = message.jsonrpc && message.jsonrpc == '2.0' || expectReply;
// check if type == 'request'
expectReply = message.type && message.type == 'request' || expectReply;
response.writeHead(200, headers);
// construct callback
var callback = me.agents[agentId];
if (callback === undefined) {
var error = new Error('Agent: "' + agentId + '" does not exist.');
response.end(JSON.stringify({__httpError__:error.message || error.toString()}));
}
else {
if (expectReply == true) {
me.outstandingRequests[agentId][message.id] = {
response: response,
timeout: setTimeout(function () {
response.end("timeout");
delete me.outstandingRequests[agentId][message.id];
}, me.httpResponseTimeout)
};
callback(senderId, message);
}
else {
// if we're not expecting a response, we first close the connection, then receive the message
response.end('');
if (callback !== undefined) {
callback(senderId, message);
}
}
}
});
}
};
/**
* Configure a HTTP server listener
*/
HTTPTransport.prototype.initiateServer = function() {
if (this.server === undefined) {
var me = this;
this.server = http.createServer(function (request, response) {
if (request.method == 'OPTIONS') {
var headers = {};
headers['Access-Control-Allow-Origin'] = '*';
headers['Access-Control-Allow-Methods'] = 'POST, OPTIONS';
headers['Access-Control-Allow-Credentials'] = true;
headers['Access-Control-Max-Age'] = '86400'; // 24 hours
headers['Access-Control-Allow-Headers'] = 'X-Requested-With, Access-Control-Allow-Origin, X-HTTP-Method-Override, Content-Type, Authorization, Accept';
// respond to the request
response.writeHead(200, headers);
response.end();
}
else if (request.method == 'POST') {
me.processRequest(request, response);
}
});
this.server.on('error', function(err) {
if (err.code == 'EADDRINUSE') {
throw new Error('ERROR: Could not start HTTP server. Port ' + me.port + ' is occupied.');
}
else {
throw new Error(err);
}
});
// Listen on port (default: 3000), IP defaults to 127.0.0.1
this.server.listen(this.port, function() {
// Put a friendly message on the terminal
console.log('Server listening at ', me.url);
});
}
else {
this.server.close();
this.server = undefined;
this.initiateServer();
}
};
/**
* Close the HTTP server
*/
HTTPTransport.prototype.close = function() {
// close all open connections
for (var agentId in this.outstandingRequests) {
if (this.outstandingRequests.hasOwnProperty(agentId)) {
var agentRequests = this.outstandingRequests[agentId];
for (var messageId in agentRequests) {
if (agentRequests.hasOwnProperty(messageId)) {
var openMessage = agentRequests[messageId];
var error = new Error('Server shutting down.');
openMessage.response.end(JSON.stringify({__httpError__:error.message || error.toString()}));
}
}
}
}
// close server
if (this.server) {
this.server.close();
}
this.server = null;
};
module.exports = HTTPTransport;
},{"./../Transport":10,"./HTTPConnection":15,"http":138,"promise":114,"uuid-v4":125}],17:[function(_dereq_,module,exports){
'use strict';
var Promise = _dereq_('promise');
var Connection = _dereq_('../Connection');
/**
* A local connection.
* @param {LocalTransport} transport
* @param {string | number} id
* @param {function} receive
* @constructor
*/
function LocalConnection(transport, id, receive) {
this.transport = transport;
this.id = id;
// register the agents receive function
if (this.id in this.transport.agents) {
throw new Error('Agent with id ' + id + ' already exists');
}
this.transport.agents[this.id] = receive;
// ready state
this.ready = Promise.resolve(this);
}
/**
* Send a message to an agent.
* @param {string} to
* @param {*} message
* @return {Promise} returns a promise which resolves when the message has been sent
*/
LocalConnection.prototype.send = function (to, message) {
var callback = this.transport.agents[to];
if (!callback) {
throw new Error('Agent with id ' + to + ' not found');
}
// invoke the agents receiver as callback(from, message)
callback(this.id, message);
return Promise.resolve();
};
/**
* Close the connection
*/
LocalConnection.prototype.close = function () {
delete this.transport.agents[this.id];
};
module.exports = LocalConnection;
},{"../Connection":9,"promise":114}],18:[function(_dereq_,module,exports){
'use strict';
var Transport = _dereq_('./../Transport');
var LocalConnection = _dereq_('./LocalConnection');
/**
* Create a local transport.
* @param {Object} config Config can contain the following properties:
* - `id: string`. Optional
* @constructor
*/
function LocalTransport(config) {
this.id = config && config.id || null;
this.networkId = this.id || null;
this['default'] = config && config['default'] || false;
this.agents = {};
}
LocalTransport.prototype = new Transport();
LocalTransport.prototype.type = 'local';
/**
* Connect an agent
* @param {String} id
* @param {Function} receive Invoked as receive(from, message)
* @return {LocalConnection} Returns a promise which resolves when
* connected.
*/
LocalTransport.prototype.connect = function(id, receive) {
return new LocalConnection(this, id, receive);
};
/**
* Close the transport. Removes all agent connections.
*/
LocalTransport.prototype.close = function() {
this.agents = {};
};
module.exports = LocalTransport;
},{"./../Transport":10,"./LocalConnection":17}],19:[function(_dereq_,module,exports){
'use strict';
var Promise = _dereq_('promise');
var Connection = _dereq_('../Connection');
/**
* A connection. The connection is ready when the property .ready resolves.
* @param {PubNubTransport} transport
* @param {string | number} id
* @param {function} receive
* @constructor
*/
function PubNubConnection(transport, id, receive) {
this.id = id;
this.transport = transport;
// ready state
var me = this;
this.ready = new Promise(function (resolve, reject) {
transport.pubnub.subscribe({
channel: id,
message: function (message) {
receive(message.from, message.message);
},
connect: function () {
resolve(me);
}
});
});
}
/**
* Send a message to an agent.
* @param {string} to
* @param {*} message
* @return {Promise} returns a promise which resolves when the message has been sent
*/
PubNubConnection.prototype.send = function (to, message) {
var me = this;
return new Promise(function (resolve, reject) {
me.transport.pubnub.publish({
channel: to,
message: {
from: me.id,
to: to,
message: message
},
callback: resolve,
error: reject
});
});
};
/**
* Close the connection
*/
PubNubConnection.prototype.close = function () {
this.transport.pubnub.unsubscribe({
channel: this.id
});
};
module.exports = PubNubConnection;
},{"../Connection":9,"promise":114}],20:[function(_dereq_,module,exports){
'use strict';
var Transport = _dereq_('./../Transport');
var PubNubConnection = _dereq_('./PubNubConnection');
/**
* Use pubnub as transport
* @param {Object} config Config can contain the following properties:
* - `id: string`. Optional
* - `publish_key: string`. Required
* - `subscribe_key: string`. Required
* @constructor
*/
function PubNubTransport(config) {
this.id = config.id || null;
this.networkId = config.publish_key || null;
this['default'] = config['default'] || false;
this.pubnub = PUBNUB().init(config);
}
PubNubTransport.prototype = new Transport();
PubNubTransport.prototype.type = 'pubnub';
/**
* Connect an agent
* @param {String} id
* @param {Function} receive Invoked as receive(from, message)
* @return {PubNubConnection} Returns a connection
*/
PubNubTransport.prototype.connect = function(id, receive) {
return new PubNubConnection(this, id, receive)
};
/**
* Close the transport.
*/
PubNubTransport.prototype.close = function() {
// FIXME: how to correctly close a pubnub connection?
this.pubnub = null;
};
/**
* Load the PubNub library
* @returns {Object} PUBNUB
*/
function PUBNUB() {
if (typeof window !== 'undefined') {
// browser
if (typeof window['PUBNUB'] === 'undefined') {
throw new Error('Please load pubnub first in the browser');
}
return window['PUBNUB'];
}
else {
// node.js
return _dereq_('pubnub');
}
}
module.exports = PubNubTransport;
},{"./../Transport":10,"./PubNubConnection":19,"pubnub":123}],21:[function(_dereq_,module,exports){
'use strict';
var uuid = _dereq_('uuid-v4');
var Promise = _dereq_('promise');
var WebSocket = (typeof window !== 'undefined' && typeof window.WebSocket !== 'undefined') ?
window.WebSocket :
_dereq_('ws');
var util = _dereq_('../../util');
var Connection = _dereq_('../Connection');
/**
* A websocket connection.
* @param {WebSocketTransport} transport
* @param {string | number | null} url The url of the agent. The url must match
* the url of the WebSocket server.
* If url is null, a UUID id is generated as url.
* @param {function} receive
* @constructor
*/
function WebSocketConnection(transport, url, receive) {
this.transport = transport;
this.url = url ? util.normalizeURL(url) : uuid();
this.receive = receive;
this.sockets = {};
this.closed = false;
this.reconnectTimers = {};
// ready state
this.ready = Promise.resolve(this);
}
/**
* Send a message to an agent.
* @param {string} to The WebSocket url of the receiver
* @param {*} message
* @return {Promise} Returns a promise which resolves when the message is sent,
* and rejects when sending the message failed
*/
WebSocketConnection.prototype.send = function (to, message) {
//console.log('send', this.url, to, message); // TODO: cleanup
// deliver locally when possible
if (this.transport.localShortcut) {
var agent = this.transport.agents[to];
if (agent) {
try {
agent.receive(this.url, message);
return Promise.resolve();
}
catch (err) {
return Promise.reject(err);
}
}
}
// get or create a connection
var conn = this.sockets[to];
if (conn) {
try {
if (conn.readyState == conn.CONNECTING) {
// the connection is still opening
return new Promise(function (resolve, reject) {
conn.onopen.callback.push(function () {
conn.send(JSON.stringify(message));
resolve();
})
});
}
else if (conn.readyState == conn.OPEN) {
conn.send(JSON.stringify(message));
return Promise.resolve();
}
else {
// remove the connection
conn = null;
}
}
catch (err) {
return Promise.reject(err);
}
}
if (!conn) {
// try to open a connection
var me = this;
return new Promise(function (resolve, reject) {
me._connect(to, function (conn) {
conn.send(JSON.stringify(message));
resolve();
}, function (err) {
reject(new Error('Failed to connect to agent "' + to + '"'));
});
})
}
};
/**
* Open a websocket connection to an other agent. No messages are sent.
* @param {string} to Url of the remote agent.
* @returns {Promise.<WebSocketConnection, Error>}
* Returns a promise which resolves when the connection is
* established and rejects in case of an error.
*/
WebSocketConnection.prototype.connect = function (to) {
var me = this;
return new Promise(function (resolve, reject) {
me._connect(to, function () {
resolve(me);
}, reject);
});
};
/**
* Open a websocket connection
* @param {String} to Url of the remote agent
* @param {function} [callback]
* @param {function} [errback]
* @param {boolean} [doReconnect=false]
* @returns {WebSocket}
* @private
*/
WebSocketConnection.prototype._connect = function (to, callback, errback, doReconnect) {
var me = this;
var conn = new WebSocket(to + '?id=' + this.url);
// register the new socket
me.sockets[to] = conn;
conn.onopen = function () {
// Change doReconnect to true as soon as we have had an open connection
doReconnect = true;
conn.onopen.callbacks.forEach(function (cb) {
cb(conn);
});
conn.onopen.callbacks = [];
};
conn.onopen.callbacks = callback ? [callback] : [];
conn.onmessage = function (event) {
me.receive(to, JSON.parse(event.data));
};
conn.onclose = function () {
delete me.sockets[to];
if (doReconnect) {
me._reconnect(to);
}
};
conn.onerror = function (err) {
delete me.sockets[to];
if (errback) {
errback(err);
}
};
return conn;
};
/**
* Auto reconnect a broken connection
* @param {String} to Url of the remote agent
* @private
*/
WebSocketConnection.prototype._reconnect = function (to) {
var me = this;
var doReconnect = true;
if (me.closed == false && me.reconnectTimers[to] == null) {
me.reconnectTimers[to] = setTimeout(function () {
delete me.reconnectTimers[to];
me._connect(to, null, null, doReconnect);
}, me.transport.reconnectDelay);
}
};
/**
* Register a websocket connection
* @param {String} from Url of the remote agent
* @param {WebSocket} conn WebSocket connection
* @returns {WebSocket} Returns the websocket itself
* @private
*/
WebSocketConnection.prototype._onConnection = function (from, conn) {
var me = this;
conn.onmessage = function (event) {
me.receive(from, JSON.parse(event.data));
};
conn.onclose = function () {
// remove this connection from the sockets list
delete me.sockets[from];
};
conn.onerror = function (err) {
// TODO: what to do with errors?
delete me.sockets[from];
};
if (this.sockets[from]) {
// there is already a connection open with remote agent
// TODO: what to do with overwriting existing sockets?
this.sockets[from].close();
}
// register new connection
this.sockets[from] = conn;
return conn;
};
/**
* Get a list with all open sockets
* @return {String[]} Returns all open sockets
*/
WebSocketConnection.prototype.list = function () {
return Object.keys(this.sockets);
};
/**
* Close the connection. All open sockets will be closed and the agent will
* be unregistered from the WebSocketTransport.
*/
WebSocketConnection.prototype.close = function () {
this.closed = true;
// close all connections
for (var id in this.sockets) {
if (this.sockets.hasOwnProperty(id)) {
this.sockets[id].close();
}
}
this.sockets = {};
delete this.transport.agents[this.url];
};
module.exports = WebSocketConnection;
},{"../../util":23,"../Connection":9,"promise":114,"uuid-v4":125,"ws":126}],22:[function(_dereq_,module,exports){
'use strict';
var urlModule = _dereq_('url');
var uuid = _dereq_('uuid-v4');
var Promise = _dereq_('promise');
var WebSocketServer = _dereq_('ws').Server;
var util = _dereq_('../../util');
var Transport = _dereq_('../Transport');
var WebSocketConnection = _dereq_('./WebSocketConnection');
/**
* Create a web socket transport.
* @param {Object} config Config can contain the following properties:
* - `id: string`. Optional
* - `default: boolean`. Optional
* - `url: string`. Optional. If provided,
* A WebSocket server is started on given
* url.
* - `localShortcut: boolean`. Optional. If true
* (default), messages to local agents are not
* send via WebSocket but delivered immediately
* - `reconnectDelay: number` Optional. Delay in
* milliseconds for reconnecting a broken
* connection. 10000 ms by default. Connections
* are only automatically reconnected after
* there has been an established connection.
* @constructor
*/
function WebSocketTransport(config) {
this.id = config && config.id || null;
this.networkId = this.id || null;
this['default'] = config && config['default'] || false;
this.localShortcut = (config && config.localShortcut === false) ? false : true;
this.reconnectDelay = config && config.reconnectDelay || 10000;
this.url = config && config.url || null;
this.server = null;
if (this.url != null) {
var urlParts = urlModule.parse(this.url);
if (urlParts.protocol != 'ws:') throw new Error('Invalid protocol, "ws:" expected');
if (this.url.indexOf(':id') == -1) throw new Error('":id" placeholder missing in url');
this.address = urlParts.protocol + '//' + urlParts.host; // the url without path, for example 'ws://localhost:3000'
this.ready = this._initServer(this.url);
}
else {
this.address = null;
this.ready = Promise.resolve(this);
}
this.agents = {}; // WebSocketConnections of all registered agents. The keys are the urls of the agents
}
WebSocketTransport.prototype = new Transport();
WebSocketTransport.prototype.type = 'ws';
/**
* Build an url for given id. Example:
* var url = getUrl('agent1'); // 'ws://localhost:3000/agents/agent1'
* @param {String} id
* @return {String} Returns the url, or returns null when no url placeholder
* is defined.
*/
WebSocketTransport.prototype.getUrl = function (id) {
return this.url ? this.url.replace(':id', id) : null;
};
/**
* Initialize a server on given url
* @param {String} url For example 'http://localhost:3000'
* @return {Promise} Returns a promise which resolves when the server is up
* and running
* @private
*/
WebSocketTransport.prototype._initServer = function (url) {
var urlParts = urlModule.parse(url);
var port = urlParts.port || 80;
var me = this;
return new Promise(function (resolve, reject) {
me.server = new WebSocketServer({port: port}, function () {
resolve(me);
});
me.server.on('connection', me._onConnection.bind(me));
me.server.on('error', function (err) {
reject(err)
});
})
};
/**
* Handle a new connection. The connection is added to the addressed agent.
* @param {WebSocket} conn
* @private
*/
WebSocketTransport.prototype._onConnection = function (conn) {
var url = conn.upgradeReq.url;
var urlParts = urlModule.parse(url, true);
var toPath = urlParts.pathname;
var to = util.normalizeURL(this.address + toPath);
// read sender id from query parameters or generate a random uuid
var queryParams = urlParts.query;
var from = queryParams.id || uuid();
// TODO: make a config option to allow/disallow anonymous connections?
//console.log('onConnection, to=', to, ', from=', from, ', agents:', Object.keys(this.agents)); // TODO: cleanup
var agent = this.agents[to];
if (agent) {
agent._onConnection(from, conn);
}
else {
// reject the connection
// conn.send('Error: Agent with id "' + to + '" not found'); // TODO: can we send back a message before closing?
conn.close();
}
};
/**
* Connect an agent
* @param {string} id The id or url of the agent. In case of an
* url, this url should match the url of the
* WebSocket server.
* @param {Function} receive Invoked as receive(from, message)
* @return {WebSocketConnection} Returns a promise which resolves when
* connected.
*/
WebSocketTransport.prototype.connect = function(id, receive) {
var isURL = (id.indexOf('://') !== -1);
// FIXME: it's confusing right now what the final url will be based on the provided id...
var url = isURL ? id : (this.getUrl(id) || id);
if (url) url = util.normalizeURL(url);
// register the agents receive function
if (this.agents[url]) {
throw new Error('Agent with id ' + this.id + ' already exists');
}
var conn = new WebSocketConnection(this, url, receive);
this.agents[conn.url] = conn; // use conn.url, url can be changed when it was null
return conn;
};
/**
* Close the transport. Removes all agent connections.
*/
WebSocketTransport.prototype.close = function() {
// close all connections
for (var id in this.agents) {
if (this.agents.hasOwnProperty(id)) {
this.agents[id].close();
}
}
this.agents = {};
// close the server
if (this.server) {
this.server.close();
}
};
module.exports = WebSocketTransport;
},{"../../util":23,"../Transport":10,"./WebSocketConnection":21,"promise":114,"url":157,"uuid-v4":125,"ws":126}],23:[function(_dereq_,module,exports){
'use strict';
/**
* Test whether the provided value is a Promise.
* A value is marked as a Promise when it is an object containing functions
* `then` and `catch`.
* @param {*} value
* @return {boolean} Returns true when `value` is a Promise
*/
exports.isPromise = function (value) {
return value &&
typeof value['then'] === 'function' &&
typeof value['catch'] === 'function'
};
/**
* Splits an url like "protocol://domain/path"
* @param {string} url
* @return {{protocol: string, domain: string, path: string} | null}
* Returns an object with properties protocol, domain, and path
* when there is a match. Returns null if no valid url.
*
*/
exports.parseUrl = function (url) {
// match an url like "protocol://domain/path"
var match = /^([A-z]+):\/\/([^\/]+)(\/(.*)$|$)/.exec(url);
if (match) {
return {
protocol: match[1],
domain: match[2],
path: match[4]
}
}
return null;
};
/**
* Normalize a url. Removes trailing slash
* @param {string} url
* @return {string} Returns the normalized url
*/
exports.normalizeURL = function (url) {
if (url[url.length - 1] == '/') {
return url.substring(0, url.length - 1);
}
else {
return url;
}
};
},{}],24:[function(_dereq_,module,exports){
'use strict';
var Connection = _dereq_('./lib/connection');
module.exports = {
Connection: Connection,
createConnection: function (options, implOptions, readyCallback) {
var c = new Connection(options, implOptions, readyCallback);
c.connect();
return c;
}
};
},{"./lib/connection":28}],25:[function(_dereq_,module,exports){
// Copyright (c) 2008, Fair Oaks Labs, Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this list
// of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice, this
// list of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
// * Neither the name of Fair Oaks Labs, Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Modified from original JSPack <cbond@positrace.com>
exports.jspack = function (bigEndian) {
this.bigEndian = bigEndian;
}
exports.jspack.prototype._DeArray = function (a, p, l) {
return [a.slice(p, p + l)];
};
exports.jspack.prototype._EnArray = function (a, p, l, v) {
for (var i = 0; i < l; ++i) {
a[p + i] = v[i] ? v[i] : 0;
}
};
exports.jspack.prototype._DeChar = function (a, p) {
return String.fromCharCode(a[p]);
};
exports.jspack.prototype._EnChar = function (a, p, v) {
a[p] = v.charCodeAt(0);
};
exports.jspack.prototype._DeInt = function (a, p) {
var lsb = bigEndian ? format.len - 1 : 0;
var nsb = bigEndian ? -1 : 1;
var stp = lsb + nsb * format.len,
rv;
var ret = 0;
var i = lsb;
var f = 1;
while (i != stp) {
rv += a[p + i] * f;
i += nsb;
f *= 256;
}
if (format.signed) {
if ((rv & Math.pow(2, format.len * 8 - 1)) != 0) {
rv -= Math.pow(2, format.len * 8);
}
}
return rv;
};
exports.jspack.prototype._EnInt = function (a, p, v) {
var lsb = bigEndian ? format.len - 1 : 0;
var nsb = bigEndian ? -1 : 1;
var stp = lsb + nsb * format.len;
v = v < format.min ? format.min : ((v > format.max) ? format.max : v);
var i = lsb;
while (i != stp) {
a[p + i] = v & 0xff;
i += nsb;
v >>= 8;
}
};
exports.jspack.prototype._DeString = function (a, p, l) {
var rv = new Array(1);
for (i = 0; i < l; i++) {
rv[i] = String.fromCharCode(a[p + i]);
}
return rv.join('');
};
exports.jspack.prototype._EnString = function (a, p, l, v) {
for (var t, i = 0; i < l; ++i) {
t = v.charCodeAt(i);
if (!t) t = 0;
a[p + i] = t;
}
};
exports.jspack.prototype._De754 = function (a, p) {
var s, e, m, i, d, bits, bit, len, bias, max;
bit = format.bit;
len = format.len * 8 - format.bit - 1;
max = (1 << len) - 1;
bias = max >> 1;
i = bigEndian ? 0 : format.len - 1;
d = bigEndian ? 1 : -1;;
s = a[p + i];
i = i + d;
bits = -7;
e = s & ((1 << -bits) - 1);
s >>= -bits;
for (bits += len; bits > 0; bits -= 8) {
e = e * 256 + a[p + i];
i += d;
}
m = e & ((1 << -bits) - 1);
e >>= -bits;
for (bits += bit; bits > 0; bits -= 8) {
m = m * 256 + a[p + i];
i += d;
}
switch (e) {
case 0:
// Zero, or denormalized number
e = 1 - bias;
break;
case max:
// NaN, or +/-Infinity
return m ? NaN : ((s ? -1 : 1) * Infinity);
default:
// Normalized number
m = m + Math.pow(2, bit);
e = e - bias;
break;
}
return (s ? -1 : 1) * m * Math.pow(2, e - bit);
};
exports.jspack.prototype._En754 = function (a, p, v) {
var s, e, m, i, d, c, bit, len, bias, max;
bit = format.bit;
len = format.len * 8 - format.bit - 1;
max = (1 << len) - 1;
bias = max >> 1;
s = v < 0 ? 1 : 0;
v = Math.abs(v);
if (isNaN(v) || (v == Infinity)) {
m = isNaN(v) ? 1 : 0;
e = max;
} else {
e = Math.floor(Math.log(v) / Math.LN2); // Calculate log2 of the value
c = Math.pow(2, -e);
if (v * c < 1) {
e--;
c = c * 2;
}
// Round by adding 1/2 the significand's LSD
if (e + bias >= 1) {
v += format.rt / c; // Normalized: bit significand digits
} else {
v += format.rt * Math.pow(2, 1 - bias); // Denormalized: <= bit significand digits
}
if (v * c >= 2) {
e++;
c = c / 2; // Rounding can increment the exponent
}
if (e + bias >= max) { // overflow
m = 0;
e = max;
} else if (e + bias >= 1) { // normalized
m = (v * c - 1) * Math.pow(2, bit); // do not reorder this expression
e = e + bias;
} else {
// Denormalized - also catches the '0' case, somewhat by chance
m = v * Math.pow(2, bias - 1) * Math.pow(2, bit);
e = 0;
}
}
i = bigEndian ? format.len - 1 : 0;
d = bigEndian ? -1 : 1;;
while (bit >= 8) {
a[p + i] = m & 0xff;
i += d;
m /= 256;
bit -= 8;
}
e = (e << bit) | m;
for (len += bit; len > 0; len -= 8) {
a[p + i] = e & 0xff;
i += d;
e /= 256;
}
a[p + i - d] |= s * 128;
};
// Unpack a series of n formatements of size s from array a at offset p with fxn
exports.jspack.prototype._UnpackSeries = function (n, s, a, p) {
var fxn = format.de;
var ret = [];
for (var i = 0; i < n; i++) {
ret.push(fxn(a, p + i * s));
}
return ret;
};
// Pack a series of n formatements of size s from array v at offset i to array a at offset p with fxn
exports.jspack.prototype._PackSeries = function (n, s, a, p, v, i) {
var fxn = format.en;
for (o = 0; o < n; o++) {
fxn(a, p + o * s, v[i + o]);
}
};
// Unpack the octet array a, beginning at offset p, according to the fmt string
exports.jspack.prototype.Unpack = function (fmt, a, p) {
bigEndian = fmt.charAt(0) != '<';
if (p == undefined || p == null) p = 0;
var re = new RegExp(this._sPattern, 'g');
var ret = [];
for (var m; m = re.exec(fmt); /* */ ) {
var n;
if (m[1] == undefined || m[1] == '') n = 1;
else n = parseInt(m[1]);
var s = this._lenLut[m[2]];
if ((p + n * s) > a.length) return undefined;
switch (m[2]) {
case 'A':
case 's':
rv.push(this._formatLut[m[2]].de(a, p, n));
break;
case 'c':
case 'b':
case 'B':
case 'h':
case 'H':
case 'i':
case 'I':
case 'l':
case 'L':
case 'f':
case 'd':
format = this._formatLut[m[2]];
ret.push(this._UnpackSeries(n, s, a, p));
break;
}
p += n * s;
}
return Array.prototype.concat.apply([], ret);
};
// Pack the supplied values into the octet array a, beginning at offset p, according to the fmt string
exports.jspack.prototype.PackTo = function (fmt, a, p, values) {
bigEndian = (fmt.charAt(0) != '<');
var re = new RegExp(this._sPattern, 'g');
for (var m, i = 0; m = re.exec(fmt); /* */ ) {
var n;
if (m[1] == undefined || m[1] == '') n = 1;
else n = parseInt(m[1]);
var s = this._lenLut[m[2]];
if ((p + n * s) > a.length) return false;
switch (m[2]) {
case 'A':
case 's':
if ((i + 1) > values.length) return false;
this._formatLut[m[2]].en(a, p, n, values[i]);
i += 1;
break;
case 'c':
case 'b':
case 'B':
case 'h':
case 'H':
case 'i':
case 'I':
case 'l':
case 'L':
case 'f':
case 'd':
format = this._formatLut[m[2]];
if (i + n > values.length) return false;
this._PackSeries(n, s, a, p, values, i);
i += n;
break;
case 'x':
for (var j = 0; j < n; j++) {
a[p + j] = 0;
}
break;
}
p += n * s;
}
return a;
};
// Pack the supplied values into a new octet array, according to the fmt string
exports.jspack.prototype.Pack = function (fmt, values) {
return this.PackTo(fmt, new Array(this.CalcLength(fmt)), 0, values);
};
// Determine the number of bytes represented by the format string
exports.jspack.prototype.CalcLength = function (fmt) {
var re = new RegExp(this._sPattern, 'g');
var sz = 0;
while (match = re.exec(fmt)) {
var n;
if (match[1] == undefined || match[1] == '') n = 1;
else n = parseInt(match[1]);
sz += n * this._lenLut[match[2]];
}
return sz;
};
// Regular expression for counting digits
exports.jspack.prototype._sPattern = '(\\d+)?([AxcbBhHsfdiIlL])';
// Byte widths for associated formats
exports.jspack.prototype._lenLut = {
'A': 1,
'x': 1,
'c': 1,
'b': 1,
'B': 1,
'h': 2,
'H': 2,
's': 1,
'f': 4,
'd': 8,
'i': 4,
'I': 4,
'l': 4,
'L': 4
};
exports.jspack.prototype._formatLut = {
'A': {
en: exports.jspack.prototype._EnArray,
de: exports.jspack.prototype._DeArray
},
's': {
en: exports.jspack.prototype._EnString,
de: exports.jspack.prototype._DeString
},
'c': {
en: exports.jspack.prototype._EnChar,
de: exports.jspack.prototype._DeChar
},
'b': {
en: exports.jspack.prototype._EnInt,
de: exports.jspack.prototype._DeInt,
len: 1,
signed: true,
min: -Math.pow(2, 7),
max: Math.pow(2, 7) - 1
},
'B': {
en: exports.jspack.prototype._EnInt,
de: exports.jspack.prototype._DeInt,
len: 1,
signed: false,
min: 0,
max: Math.pow(2, 8) - 1
},
'h': {
en: exports.jspack.prototype._EnInt,
de: exports.jspack.prototype._DeInt,
len: 2,
signed: true,
min: -Math.pow(2, 15),
max: Math.pow(2, 15) - 1
},
'H': {
en: exports.jspack.prototype._EnInt,
de: exports.jspack.prototype._DeInt,
len: 2,
signed: false,
min: 0,
max: Math.pow(2, 16) - 1
},
'i': {
en: exports.jspack.prototype._EnInt,
de: exports.jspack.prototype._DeInt,
len: 4,
signed: true,
min: -Math.pow(2, 31),
max: Math.pow(2, 31) - 1
},
'I': {
en: exports.jspack.prototype._EnInt,
de: exports.jspack.prototype._DeInt,
len: 4,
signed: false,
min: 0,
max: Math.pow(2, 32) - 1
},
'l': {
en: exports.jspack.prototype._EnInt,
de: exports.jspack.prototype._DeInt,
len: 4,
signed: true,
min: -Math.pow(2, 31),
max: Math.pow(2, 31) - 1
},
'L': {
en: exports.jspack.prototype._EnInt,
de: exports.jspack.prototype._DeInt,
len: 4,
signed: false,
min: 0,
max: Math.pow(2, 32) - 1
},
'f': {
en: exports.jspack.prototype._En754,
de: exports.jspack.prototype._De754,
len: 4,
bit: 23,
rt: Math.pow(2, -24) - Math.pow(2, -77)
},
'd': {
en: exports.jspack.prototype._En754,
de: exports.jspack.prototype._De754,
len: 8,
bit: 52,
rt: 0
}
};
},{}],26:[function(_dereq_,module,exports){
exports.constants = [
[1, "frameMethod"],
[2, "frameHeader"],
[3, "frameBody"],
[8, "frameHeartbeat"],
[200, "replySuccess"],
[206, "frameEnd"],
[311, "contentTooLarge"],
[313, "noConsumers"],
[320, "connectionForced"],
[402, "invalidPath"],
[403, "accessRefused"],
[404, "notFound"],
[405, "resourceLocked"],
[406, "preconditionFailed"],
[501, "frameError"],
[502, "syntaxError"],
[503, "commandInvalid"],
[504, "channelError"],
[505, "unexpectedFrame"],
[506, "resourceError"],
[530, "notAllowed"],
[540, "notImplemented"],
[541, "internalError"],
[4096, "frameMinSize"]
];
exports.classes = [{
"name": "connection",
"index": 10,
"fields": [],
"methods": [{
"name": "start",
"index": 10,
"fields": [{
"name": "versionMajor",
"domain": "octet"
}, {
"name": "versionMinor",
"domain": "octet"
}, {
"name": "serverProperties",
"domain": "table"
}, {
"name": "mechanisms",
"domain": "longstr"
}, {
"name": "locales",
"domain": "longstr"
}]
}, {
"name": "startOk",
"index": 11,
"fields": [{
"name": "clientProperties",
"domain": "table"
}, {
"name": "mechanism",
"domain": "shortstr"
}, {
"name": "response",
"domain": "longstr"
}, {
"name": "locale",
"domain": "shortstr"
}]
}, {
"name": "secure",
"index": 20,
"fields": [{
"name": "challenge",
"domain": "longstr"
}]
}, {
"name": "secureOk",
"index": 21,
"fields": [{
"name": "response",
"domain": "longstr"
}]
}, {
"name": "tune",
"index": 30,
"fields": [{
"name": "channelMax",
"domain": "short"
}, {
"name": "frameMax",
"domain": "long"
}, {
"name": "heartbeat",
"domain": "short"
}]
}, {
"name": "tuneOk",
"index": 31,
"fields": [{
"name": "channelMax",
"domain": "short"
}, {
"name": "frameMax",
"domain": "long"
}, {
"name": "heartbeat",
"domain": "short"
}]
}, {
"name": "open",
"index": 40,
"fields": [{
"name": "virtualHost",
"domain": "shortstr"
}, {
"name": "reserved1",
"domain": "shortstr"
}, {
"name": "reserved2",
"domain": "bit"
}]
}, {
"name": "openOk",
"index": 41,
"fields": [{
"name": "reserved1",
"domain": "shortstr"
}]
}, {
"name": "close",
"index": 50,
"fields": [{
"name": "replyCode",
"domain": "short"
}, {
"name": "replyText",
"domain": "shortstr"
}, {
"name": "classId",
"domain": "short"
}, {
"name": "methodId",
"domain": "short"
}]
}, {
"name": "closeOk",
"index": 51,
"fields": []
}]
}, {
"name": "channel",
"index": 20,
"fields": [],
"methods": [{
"name": "open",
"index": 10,
"fields": [{
"name": "reserved1",
"domain": "shortstr"
}]
}, {
"name": "openOk",
"index": 11,
"fields": [{
"name": "reserved1",
"domain": "longstr"
}]
}, {
"name": "flow",
"index": 20,
"fields": [{
"name": "active",
"domain": "bit"
}]
}, {
"name": "flowOk",
"index": 21,
"fields": [{
"name": "active",
"domain": "bit"
}]
}, {
"name": "close",
"index": 40,
"fields": [{
"name": "replyCode",
"domain": "short"
}, {
"name": "replyText",
"domain": "shortstr"
}, {
"name": "classId",
"domain": "short"
}, {
"name": "methodId",
"domain": "short"
}]
}, {
"name": "closeOk",
"index": 41,
"fields": []
}]
}, {
"name": "exchange",
"index": 40,
"fields": [],
"methods": [{
"name": "declare",
"index": 10,
"fields": [{
"name": "reserved1",
"domain": "short"
}, {
"name": "exchange",
"domain": "shortstr"
}, {
"name": "type",
"domain": "shortstr"
}, {
"name": "passive",
"domain": "bit"
}, {
"name": "durable",
"domain": "bit"
}, {
"name": "autoDelete",
"domain": "bit"
}, {
"name": "reserved2",
"domain": "bit"
}, {
"name": "reserved3",
"domain": "bit"
}, {
"name": "noWait",
"domain": "bit"
}, {
"name": "arguments",
"domain": "table"
}]
}, {
"name": "declareOk",
"index": 11,
"fields": []
}, {
"name": "delete",
"index": 20,
"fields": [{
"name": "reserved1",
"domain": "short"
}, {
"name": "exchange",
"domain": "shortstr"
}, {
"name": "ifUnused",
"domain": "bit"
}, {
"name": "noWait",
"domain": "bit"
}]
}, {
"name": "deleteOk",
"index": 21,
"fields": []
}, {
"name": "bind",
"index": 30,
"fields": [{
"name": "reserved1",
"domain": "short"
}, {
"name": "destination",
"domain": "shortstr"
}, {
"name": "source",
"domain": "shortstr"
}, {
"name": "routingKey",
"domain": "shortstr"
}, {
"name": "noWait",
"domain": "bit"
}, {
"name": "arguments",
"domain": "table"
}]
}, {
"name": "bindOk",
"index": 31,
"fields": []
}, {
"name": "unbind",
"index": 40,
"fields": [{
"name": "reserved1",
"domain": "short"
}, {
"name": "destination",
"domain": "shortstr"
}, {
"name": "source",
"domain": "shortstr"
}, {
"name": "routingKey",
"domain": "shortstr"
}, {
"name": "noWait",
"domain": "bit"
}, {
"name": "arguments",
"domain": "table"
}]
}, {
"name": "unbindOk",
"index": 51,
"fields": []
}]
}, {
"name": "queue",
"index": 50,
"fields": [],
"methods": [{
"name": "declare",
"index": 10,
"fields": [{
"name": "reserved1",
"domain": "short"
}, {
"name": "queue",
"domain": "shortstr"
}, {
"name": "passive",
"domain": "bit"
}, {
"name": "durable",
"domain": "bit"
}, {
"name": "exclusive",
"domain": "bit"
}, {
"name": "autoDelete",
"domain": "bit"
}, {
"name": "noWait",
"domain": "bit"
}, {
"name": "arguments",
"domain": "table"
}]
}, {
"name": "declareOk",
"index": 11,
"fields": [{
"name": "queue",
"domain": "shortstr"
}, {
"name": "messageCount",
"domain": "long"
}, {
"name": "consumerCount",
"domain": "long"
}]
}, {
"name": "bind",
"index": 20,
"fields": [{
"name": "reserved1",
"domain": "short"
}, {
"name": "queue",
"domain": "shortstr"
}, {
"name": "exchange",
"domain": "shortstr"
}, {
"name": "routingKey",
"domain": "shortstr"
}, {
"name": "noWait",
"domain": "bit"
}, {
"name": "arguments",
"domain": "table"
}]
}, {
"name": "bindOk",
"index": 21,
"fields": []
}, {
"name": "unbind",
"index": 50,
"fields": [{
"name": "reserved1",
"domain": "short"
}, {
"name": "queue",
"domain": "shortstr"
}, {
"name": "exchange",
"domain": "shortstr"
}, {
"name": "routingKey",
"domain": "shortstr"
}, {
"name": "arguments",
"domain": "table"
}]
}, {
"name": "unbindOk",
"index": 51,
"fields": []
}, {
"name": "purge",
"index": 30,
"fields": [{
"name": "reserved1",
"domain": "short"
}, {
"name": "queue",
"domain": "shortstr"
}, {
"name": "noWait",
"domain": "bit"
}]
}, {
"name": "purgeOk",
"index": 31,
"fields": [{
"name": "messageCount",
"domain": "long"
}]
}, {
"name": "delete",
"index": 40,
"fields": [{
"name": "reserved1",
"domain": "short"
}, {
"name": "queue",
"domain": "shortstr"
}, {
"name": "ifUnused",
"domain": "bit"
}, {
"name": "ifEmpty",
"domain": "bit"
}, {
"name": "noWait",
"domain": "bit"
}]
}, {
"name": "deleteOk",
"index": 41,
"fields": [{
"name": "messageCount",
"domain": "long"
}]
}]
}, {
"name": "basic",
"index": 60,
"fields": [{
"name": "contentType",
"domain": "shortstr"
}, {
"name": "contentEncoding",
"domain": "shortstr"
}, {
"name": "headers",
"domain": "table"
}, {
"name": "deliveryMode",
"domain": "octet"
}, {
"name": "priority",
"domain": "octet"
}, {
"name": "correlationId",
"domain": "shortstr"
}, {
"name": "replyTo",
"domain": "shortstr"
}, {
"name": "expiration",
"domain": "shortstr"
}, {
"name": "messageId",
"domain": "shortstr"
}, {
"name": "timestamp",
"domain": "timestamp"
}, {
"name": "type",
"domain": "shortstr"
}, {
"name": "userId",
"domain": "shortstr"
}, {
"name": "appId",
"domain": "shortstr"
}, {
"name": "reserved",
"domain": "shortstr"
}],
"methods": [{
"name": "qos",
"index": 10,
"fields": [{
"name": "prefetchSize",
"domain": "long"
}, {
"name": "prefetchCount",
"domain": "short"
}, {
"name": "global",
"domain": "bit"
}]
}, {
"name": "qosOk",
"index": 11,
"fields": []
}, {
"name": "consume",
"index": 20,
"fields": [{
"name": "reserved1",
"domain": "short"
}, {
"name": "queue",
"domain": "shortstr"
}, {
"name": "consumerTag",
"domain": "shortstr"
}, {
"name": "noLocal",
"domain": "bit"
}, {
"name": "noAck",
"domain": "bit"
}, {
"name": "exclusive",
"domain": "bit"
}, {
"name": "noWait",
"domain": "bit"
}, {
"name": "arguments",
"domain": "table"
}]
}, {
"name": "consumeOk",
"index": 21,
"fields": [{
"name": "consumerTag",
"domain": "shortstr"
}]
}, {
"name": "cancel",
"index": 30,
"fields": [{
"name": "consumerTag",
"domain": "shortstr"
}, {
"name": "noWait",
"domain": "bit"
}]
}, {
"name": "cancelOk",
"index": 31,
"fields": [{
"name": "consumerTag",
"domain": "shortstr"
}]
}, {
"name": "publish",
"index": 40,
"fields": [{
"name": "reserved1",
"domain": "short"
}, {
"name": "exchange",
"domain": "shortstr"
}, {
"name": "routingKey",
"domain": "shortstr"
}, {
"name": "mandatory",
"domain": "bit"
}, {
"name": "immediate",
"domain": "bit"
}]
}, {
"name": "return",
"index": 50,
"fields": [{
"name": "replyCode",
"domain": "short"
}, {
"name": "replyText",
"domain": "shortstr"
}, {
"name": "exchange",
"domain": "shortstr"
}, {
"name": "routingKey",
"domain": "shortstr"
}]
}, {
"name": "deliver",
"index": 60,
"fields": [{
"name": "consumerTag",
"domain": "shortstr"
}, {
"name": "deliveryTag",
"domain": "longlong"
}, {
"name": "redelivered",
"domain": "bit"
}, {
"name": "exchange",
"domain": "shortstr"
}, {
"name": "routingKey",
"domain": "shortstr"
}]
}, {
"name": "get",
"index": 70,
"fields": [{
"name": "reserved1",
"domain": "short"
}, {
"name": "queue",
"domain": "shortstr"
}, {
"name": "noAck",
"domain": "bit"
}]
}, {
"name": "getOk",
"index": 71,
"fields": [{
"name": "deliveryTag",
"domain": "longlong"
}, {
"name": "redelivered",
"domain": "bit"
}, {
"name": "exchange",
"domain": "shortstr"
}, {
"name": "routingKey",
"domain": "shortstr"
}, {
"name": "messageCount",
"domain": "long"
}]
}, {
"name": "getEmpty",
"index": 72,
"fields": [{
"name": "reserved1",
"domain": "shortstr"
}]
}, {
"name": "ack",
"index": 80,
"fields": [{
"name": "deliveryTag",
"domain": "longlong"
}, {
"name": "multiple",
"domain": "bit"
}]
}, {
"name": "reject",
"index": 90,
"fields": [{
"name": "deliveryTag",
"domain": "longlong"
}, {
"name": "requeue",
"domain": "bit"
}]
}, {
"name": "recoverAsync",
"index": 100,
"fields": [{
"name": "requeue",
"domain": "bit"
}]
}, {
"name": "recover",
"index": 110,
"fields": [{
"name": "requeue",
"domain": "bit"
}]
}, {
"name": "recoverOk",
"index": 111,
"fields": []
}]
}, {
"name": "tx",
"index": 90,
"fields": [],
"methods": [{
"name": "select",
"index": 10,
"fields": []
}, {
"name": "selectOk",
"index": 11,
"fields": []
}, {
"name": "commit",
"index": 20,
"fields": []
}, {
"name": "commitOk",
"index": 21,
"fields": []
}, {
"name": "rollback",
"index": 30,
"fields": []
}, {
"name": "rollbackOk",
"index": 31,
"fields": []
}]
}, {
"name": "confirm",
"index": 85,
"fields": [],
"methods": [{
"name": "select",
"index": 10,
"fields": [{
"name": "noWait",
"domain": "bit"
}]
}, {
"name": "selectOk",
"index": 11,
"fields": []
}]
}];
},{}],27:[function(_dereq_,module,exports){
'use strict';
var events = _dereq_('events');
var util = _dereq_('util');
var fs = _dereq_('fs');
var Promise = _dereq_('./promise').Promise;
var definitions = _dereq_('./definitions');
var methods = definitions.methods;
// This class is not exposed to the user. Queue and Exchange are subclasses
// of Channel. This just provides a task queue.
var Channel = module.exports = function Channel (connection, channel) {
events.EventEmitter.call(this);
// Unlimited listeners. Helps when e.g. publishing high-volume messages,
// 10 is far too low.
this.setMaxListeners(0);
this.channel = channel;
this.connection = connection;
this._tasks = [];
this.reconnect();
};
util.inherits(Channel, events.EventEmitter);
Channel.prototype.closeOK = function() {
this.connection._sendMethod(this.channel, methods.channelCloseOk, {reserved1: ""});
};
Channel.prototype.reconnect = function () {
this.connection._sendMethod(this.channel, methods.channelOpen, {reserved1: ""});
};
Channel.prototype._taskPush = function (reply, cb) {
var promise = new Promise();
this._tasks.push({
promise: promise,
reply: reply,
sent: false,
cb: cb
});
this._tasksFlush();
return promise;
};
Channel.prototype._tasksFlush = function () {
if (this.state != 'open') return;
for (var i = 0; i < this._tasks.length; i++) {
var task = this._tasks[i];
if (task.sent) continue;
task.cb();
task.sent = true;
if (!task.reply) {
// if we don't expect a reply, just delete it now
this._tasks.splice(i, 1);
i = i-1;
}
}
};
Channel.prototype._handleTaskReply = function (channel, method, args) {
var task, i;
for (i = 0; i < this._tasks.length; i++) {
if (this._tasks[i].reply == method) {
task = this._tasks[i];
this._tasks.splice(i, 1);
task.promise.emitSuccess(args);
this._tasksFlush();
return true;
}
}
return false;
};
Channel.prototype._onChannelMethod = function(channel, method, args) {
switch (method) {
case methods.channelCloseOk:
delete this.connection.channels[this.channel];
this.state = 'closed';
// TODO should this be falling through?
default:
this._onMethod(channel, method, args);
}
};
Channel.prototype.close = function(reason) {
this.state = 'closing';
this.connection._sendMethod(this.channel, methods.channelClose,
{'replyText': reason ? reason : 'Goodbye from node',
'replyCode': 200,
'classId': 0,
'methodId': 0});
};
},{"./definitions":31,"./promise":35,"events":137,"fs":127,"util":159}],28:[function(_dereq_,module,exports){
(function (process,Buffer){
'use strict';
var net = _dereq_('net');
var tls = _dereq_('tls');
var fs = _dereq_('fs');
var URL = _dereq_('url');
var _ = _dereq_('lodash');
var debug = _dereq_('./debug');
var EventEmitter = _dereq_('events').EventEmitter;
var util = _dereq_('util');
var serializer = _dereq_('./serializer');
var definitions = _dereq_('./definitions');
var methods = definitions.methods;
var methodTable = definitions.methodTable;
var classes = definitions.classes;
var Exchange = _dereq_('./exchange');
var Queue = _dereq_('./queue');
var AMQPParser = _dereq_('./parser');
var nodeAMQPVersion = _dereq_('../package').version;
var maxFrameBuffer = 131072; // 128k, same as rabbitmq (which was
// copying qpid)
var defaultPorts = { 'amqp': 5672, 'amqps': 5671 };
var defaultOptions = {
host: 'localhost',
port: defaultPorts['amqp'],
login: 'guest',
password: 'guest',
authMechanism: 'AMQPLAIN',
vhost: '/',
connectionTimeout: 10000,
ssl: {
enabled: false
}
};
var defaultSslOptions = {
port: defaultPorts['amqps'],
ssl: {
rejectUnauthorized: true
}
};
var defaultImplOptions = {
defaultExchangeName: '',
reconnect: true,
reconnectBackoffStrategy: 'linear',
reconnectExponentialLimit: 120000,
reconnectBackoffTime: 1000
};
var defaultClientProperties = {
version: nodeAMQPVersion,
platform: 'node-' + process.version,
product: 'node-amqp'
};
var Connection = module.exports = function Connection (connectionArgs, options, readyCallback) {
EventEmitter.call(this);
this.setOptions(connectionArgs);
this.setImplOptions(options);
if (typeof readyCallback === 'function') {
this._readyCallback = readyCallback;
}
this.connectionAttemptScheduled = false;
this._defaultExchange = null;
this.channelCounter = 0;
this._sendBuffer = new Buffer(maxFrameBuffer);
};
util.inherits(Connection, EventEmitter);
Connection.prototype.setOptions = function (options) {
var urlo = (options && options.url) ? this._parseURLOptions(options.url) : {};
var sslo = (options && options.ssl && options.ssl.enabled) ? defaultSslOptions : {};
this.options = _.extend({}, defaultOptions, sslo, urlo, options || {});
this.options.clientProperties = _.extend({}, defaultClientProperties, (options && options.clientProperties) || {});
};
Connection.prototype.setImplOptions = function (options) {
this.implOptions = _.extend({}, defaultImplOptions, options || {});
};
Connection.prototype.connect = function () {
// If this is our first connection, add listeners.
if (!this.socket) this.addAllListeners();
this._createSocket();
this._startHandshake();
};
Connection.prototype.reconnect = function () {
// Suspend activity on channels
for (var channel in this.channels) {
this.channels[channel].state = 'closed';
}
debug && debug("Connection lost, reconnecting...");
// Terminate socket activity
if (this.socket) this.socket.end();
this.connect();
};
Connection.prototype.disconnect = function () {
debug && debug("Sending disconnect request to server");
this._sendMethod(0, methods.connectionClose, {
'replyText': 'client disconnect',
'replyCode': 200,
'classId': 0,
'methodId': 0
});
};
Connection.prototype.addAllListeners = function() {
var self = this;
var connectEvent = this.options.ssl.enabled ? 'secureConnect' : 'connect';
self.addListener(connectEvent, function() {
// In the case where this is a reconnection, do not trample on the existing
// channels.
// For your reference, channel 0 is the control channel.
self.channels = self.channels || {0:self};
self.queues = self.queues || {};
self.exchanges = self.exchanges || {};
self.parser = new AMQPParser('0-9-1', 'client');
self.parser.onMethod = function (channel, method, args) {
self._onMethod(channel, method, args);
};
self.parser.onContent = function (channel, data) {
debug && debug(channel + " > content " + data.length);
if (self.channels[channel] && self.channels[channel]._onContent) {
self.channels[channel]._onContent(channel, data);
} else {
debug && debug("unhandled content: " + data);
}
};
self.parser.onContentHeader = function (channel, classInfo, weight, properties, size) {
debug && debug(channel + " > content header " + JSON.stringify([classInfo.name, weight, properties, size]));
if (self.channels[channel] && self.channels[channel]._onContentHeader) {
self.channels[channel]._onContentHeader(channel, classInfo, weight, properties, size);
} else {
debug && debug("unhandled content header");
}
};
self.parser.onHeartBeat = function () {
self.emit("heartbeat");
debug && debug("heartbeat");
};
self.parser.onError = function (e) {
self.emit("error", e);
self.emit("close");
};
// Remove readyEmitted flag so we can detect an auth error.
self.readyEmitted = false;
});
self.addListener('data', function (data) {
if(self.parser != null){
try {
self.parser.execute(data);
} catch (exception) {
self.emit('error', exception);
return;
}
}
self._inboundHeartbeatTimerReset();
});
var backoffTime = null;
self.addListener('error', function backoff(e) {
if (self._inboundHeartbeatTimer !== null) {
clearTimeout(self._inboundHeartbeatTimer);
self._inboundHeartbeatTimer = null;
}
if (self._outboundHeartbeatTimer !== null) {
clearTimeout(self._outboundHeartbeatTimer);
self._outboundHeartbeatTimer = null;
}
if (!self.connectionAttemptScheduled) {
// Set to true, as we are presently in the process of scheduling one.
self.connectionAttemptScheduled = true;
// Kill the socket, if it hasn't been killed already.
self.socket.end();
// Reset parser state
self.parser = null;
// In order for our reconnection to be seamless, we have to notify the
// channels that they are no longer connected so that nobody attempts
// to send messages which would be doomed to fail.
for (var channel in self.channels) {
if (channel !== 0) {
self.channels[channel].state = 'closed';
}
}
// Queues are channels (so we have already marked them as closed), but
// queues have special needs, since the subscriptions will no longer
// be known to the server when we reconnect. Mark the subscriptions as
// closed so that we can resubscribe them once we are reconnected.
for (var queue in self.queues) {
for (var index in self.queues[queue].consumerTagOptions) {
self.queues[queue].consumerTagOptions[index]['state'] = 'closed';
}
}
// Begin reconnection attempts
if (self.implOptions.reconnect) {
// Don't thrash, use a backoff strategy.
if (backoffTime === null) {
// This is the first time we've failed since a successful connection,
// so use the configured backoff time without any modification.
backoffTime = self.implOptions.reconnectBackoffTime;
} else if (self.implOptions.reconnectBackoffStrategy === 'exponential') {
// If you've configured exponential backoff, we'll double the
// backoff time each subsequent attempt until success.
backoffTime *= 2;
// limit the maxium timeout, to avoid potentially unlimited stalls
if(backoffTime > self.implOptions.reconnectExponentialLimit){
backoffTime = self.implOptions.reconnectExponentialLimit;
}
} else if (self.implOptions.reconnectBackoffStrategy === 'linear') {
// Linear strategy is the default. In this case, we will retry at a
// constant interval, so there's no need to change the backoff time
// between attempts.
} else {
// TODO should we warn people if they picked a nonexistent strategy?
}
setTimeout(function () {
// Set to false, so that if we fail in the reconnect attempt, we can
// schedule another one.
self.connectionAttemptScheduled = false;
self.reconnect();
}, backoffTime);
} else {
self.removeListener('error', backoff);
}
}
});
self.addListener('ready', function () {
// Reset the backoff time since we have successfully connected.
backoffTime = null;
if (self.implOptions.reconnect) {
// Reconnect any channels which were open.
_.each(self.channels, function(channel, index) {
// FIXME why is the index "0" instead of 0?
if (index !== "0") channel.reconnect();
});
}
// Set 'ready' flag for auth failure detection.
this.readyEmitted = true;
// Restart the heartbeat to the server
self._outboundHeartbeatTimerReset();
});
// Apparently, it is not possible to determine if an authentication error
// has occurred, but when the connection closes then we can HINT that a
// possible authentication error has occured. Although this may be a bug
// in the spec, handling it as a possible error is considerably better than
// failing silently.
self.addListener('end', function (){
if (!this.readyEmitted){
this.emit('error', new Error(
'Connection ended: possibly due to an authentication failure.'
));
}
});
};
Connection.prototype.heartbeat = function () {
if(this.socket.writable) this.write(new Buffer([8,0,0,0,0,0,0,206]));
};
// connection.exchange('my-exchange', { type: 'topic' });
// Options
// - type 'fanout', 'direct', or 'topic' (default)
// - passive (boolean)
// - durable (boolean)
// - autoDelete (boolean, default true)
Connection.prototype.exchange = function (name, options, openCallback) {
if (name === undefined) name = this.implOptions.defaultExchangeName;
if (!options) options = {};
if (name !== '' && options.type === undefined) options.type = 'topic';
try{
var channel = this.generateChannelId();
}catch(exception){
this.emit("error", exception);
return;
}
var exchange = new Exchange(this, channel, name, options, openCallback);
this.channels[channel] = exchange;
this.exchanges[name] = exchange;
return exchange;
};
// remove an exchange when it's closed (called from Exchange)
Connection.prototype.exchangeClosed = function (name) {
if (this.exchanges[name]) delete this.exchanges[name];
};
// Options
// - passive (boolean)
// - durable (boolean)
// - exclusive (boolean)
// - autoDelete (boolean, default true)
Connection.prototype.queue = function (name /* options, openCallback */) {
var options, callback;
if (typeof arguments[1] == 'object') {
options = arguments[1];
callback = arguments[2];
} else {
callback = arguments[1];
}
try{
var channel = this.generateChannelId();
}catch(exception){
this.emit("error", exception);
return;
}
var q = new Queue(this, channel, name, options, callback);
this.channels[channel] = q;
return q;
};
// remove a queue when it's closed (called from Queue)
Connection.prototype.queueClosed = function (name) {
if (this.queues[name]) delete this.queues[name];
};
// Publishes a message to the default exchange.
Connection.prototype.publish = function (routingKey, body, options, callback) {
if (!this._defaultExchange) this._defaultExchange = this.exchange();
return this._defaultExchange.publish(routingKey, body, options, callback);
};
Connection.prototype._bodyToBuffer = function (body) {
// Handles 3 cases
// - body is utf8 string
// - body is instance of Buffer
// - body is an object and its JSON representation is sent
// Does not handle the case for streaming bodies.
// Returns buffer.
if (typeof(body) == 'string') {
return [null, new Buffer(body, 'utf8')];
} else if (body instanceof Buffer) {
return [null, body];
} else {
var jsonBody = JSON.stringify(body);
debug && debug('sending json: ' + jsonBody);
var props = {contentType: 'application/json'};
return [props, new Buffer(jsonBody, 'utf8')];
}
};
Connection.prototype._inboundHeartbeatTimerReset = function () {
if (this._inboundHeartbeatTimer !== null) {
clearTimeout(this._inboundHeartbeatTimer);
this._inboundHeartbeatTimer = null;
}
if (this.options.heartbeat) {
var self = this;
var gracePeriod = 2 * this.options.heartbeat;
this._inboundHeartbeatTimer = setTimeout(function () {
if(self.socket.readable)
self.emit('error', new Error('no heartbeat or data in last ' + gracePeriod + ' seconds'));
}, gracePeriod * 1000);
}
};
Connection.prototype._outboundHeartbeatTimerReset = function () {
if (this._outboundHeartbeatTimer !== null) {
clearTimeout(this._outboundHeartbeatTimer);
this._outboundHeartbeatTimer = null;
}
if (this.socket.writable && this.options.heartbeat) {
var self = this;
this._outboundHeartbeatTimer = setTimeout(function () {
self.heartbeat();
self._outboundHeartbeatTimerReset();
}, 1000 * this.options.heartbeat);
}
};
Connection.prototype._onMethod = function (channel, method, args) {
debug && debug(channel + " > " + method.name + " " + JSON.stringify(args));
// Channel 0 is the control channel. If not zero then delegate to
// one of the channel objects.
if (channel > 0) {
if (!this.channels[channel]) {
debug && debug("Received message on untracked channel.");
return;
}
if (!this.channels[channel]._onChannelMethod) {
throw new Error('Channel ' + channel + ' has no _onChannelMethod method.');
}
this.channels[channel]._onChannelMethod(channel, method, args);
return;
}
// channel 0
switch (method) {
// 2. The server responds, after the version string, with the
// 'connectionStart' method (contains various useless information)
case methods.connectionStart:
// We check that they're serving us AMQP 0-9
if (args.versionMajor !== 0 && args.versionMinor != 9) {
this.socket.end();
this.emit('error', new Error("Bad server version"));
return;
}
this.serverProperties = args.serverProperties;
// 3. Then we reply with StartOk, containing our useless information.
this._sendMethod(0, methods.connectionStartOk, {
clientProperties: this.options.clientProperties,
mechanism: this.options.authMechanism,
response: {
LOGIN: this.options.login,
PASSWORD: this.options.password
},
locale: 'en_US'
});
break;
// 4. The server responds with a connectionTune request
case methods.connectionTune:
if (args.frameMax) {
debug && debug("tweaking maxFrameBuffer to " + args.frameMax);
maxFrameBuffer = args.frameMax;
}
// 5. We respond with connectionTuneOk
this._sendMethod(0, methods.connectionTuneOk, {
channelMax: 0,
frameMax: maxFrameBuffer,
heartbeat: this.options.heartbeat || 0
});
// 6. Then we have to send a connectionOpen request
this._sendMethod(0, methods.connectionOpen, {
virtualHost: this.options.vhost
// , capabilities: ''
// , insist: true
,
reserved1: '',
reserved2: true
});
break;
case methods.connectionOpenOk:
// 7. Finally they respond with connectionOpenOk
// Whew! That's why they call it the Advanced MQP.
if (this._readyCallback) {
this._readyCallback(this);
this._readyCallback = null;
}
this.emit('ready');
break;
case methods.connectionClose:
var e = new Error(args.replyText);
e.code = args.replyCode;
if (!this.listeners('close').length) {
console.log('Unhandled connection error: ' + args.replyText);
}
this.socket.destroy(e);
break;
case methods.connectionCloseOk:
debug && debug("Received close-ok from server, closing socket");
this.socket.end();
break;
default:
throw new Error("Uncaught method '" + method.name + "' with args " +
JSON.stringify(args));
}
};
// Generate connection options from URI string formatted with amqp scheme.
Connection.prototype._parseURLOptions = function(connectionString) {
var opts = {};
opts.ssl = {};
var url = URL.parse(connectionString);
var scheme = url.protocol.substring(0, url.protocol.lastIndexOf(':'));
if (scheme != 'amqp' && scheme != 'amqps') {
throw new Error('Connection URI must use amqp or amqps scheme. ' +
'For example, "amqp://bus.megacorp.internal:5766".');
}
opts.ssl.enabled = ('amqps' === scheme);
opts.host = url.hostname;
opts.port = url.port || defaultPorts[scheme];
if (url.auth) {
var auth = url.auth.split(':');
auth[0] && (opts.login = auth[0]);
auth[1] && (opts.password = auth[1]);
}
if (url.pathname) {
opts.vhost = unescape(url.pathname.substr(1));
}
return opts;
};
/*
*
* Connect helpers
*
*/
// If you pass a array of hosts, lets choose a random host or the preferred host number, or then next one.
Connection.prototype._chooseHost = function() {
if(Array.isArray(this.options.host)){
if(this.hosti == null){
if(typeof this.options.hostPreference == 'number') {
this.hosti = (this.options.hostPreference < this.options.host.length) ?
this.options.hostPreference : this.options.host.length-1;
} else {
this.hosti = parseInt(Math.random() * this.options.host.length, 10);
}
} else {
// If this is already set, it looks like we want to choose another one.
// Add one to hosti but don't overflow it.
this.hosti = (this.hosti + 1) % this.options.host.length;
}
return this.options.host[this.hosti];
} else {
return this.options.host;
}
};
Connection.prototype._createSocket = function() {
var hostName = this._chooseHost(), self = this;
var options = {
port: this.options.port,
host: hostName
};
var resetConnectionTimeout = function () {
debug && debug('connected so resetting connection timeout');
this.setTimeout(0);
};
// Connect socket
if (this.options.ssl.enabled) {
debug && debug('making ssl connection');
options = _.extend(options, this._getSSLOptions());
this.socket = tls.connect(options, resetConnectionTimeout);
} else {
debug && debug('making non-ssl connection');
this.socket = net.connect(options, resetConnectionTimeout);
}
var connTimeout = this.options.connectionTimeout;
if (connTimeout) {
debug && debug('setting connection timeout to ' + connTimeout);
this.socket.setTimeout(connTimeout, function () {
debug && debug('connection timeout');
this.destroy();
var e = new Error('connection timeout');
e.name = 'TimeoutError';
self.emit('error', e);
});
}
// Proxy events.
// Note that if we don't attach a 'data' event, no data will flow.
var events = ['close', 'connect', 'data', 'drain', 'error', 'end', 'secureConnect', 'timeout'];
_.each(events, function(event){
self.socket.on(event, self.emit.bind(self, event));
});
// Proxy a few methods that we use / previously used.
var methods = ['end', 'destroy', 'write', 'pause', 'resume', 'setEncoding', 'ref', 'unref', 'address'];
_.each(methods, function(method){
self[method] = function(){
self.socket[method].apply(self.socket, arguments);
};
});
};
Connection.prototype._getSSLOptions = function() {
if (this.sslConnectionOptions) return this.sslConnectionOptions;
this.sslConnectionOptions = {};
if (this.options.ssl.keyFile) {
this.sslConnectionOptions.key = fs.readFileSync(this.options.ssl.keyFile);
}
if (this.options.ssl.certFile) {
this.sslConnectionOptions.cert = fs.readFileSync(this.options.ssl.certFile);
}
if (this.options.ssl.caFile) {
this.sslConnectionOptions.ca = fs.readFileSync(this.options.ssl.caFile);
}
this.sslConnectionOptions.rejectUnauthorized = this.options.ssl.rejectUnauthorized;
return this.sslConnectionOptions;
};
// Time to start the AMQP 7-way connection initialization handshake!
// 1. The client sends the server a version string
Connection.prototype._startHandshake = function() {
debug && debug("Initiating handshake...");
this.write("AMQP" + String.fromCharCode(0,0,9,1));
};
/*
*
* Parse helpers
*
*/
Connection.prototype._sendBody = function (channel, body, properties) {
var r = this._bodyToBuffer(body);
var props = r[0], buffer = r[1];
properties = _.extend(props || {}, properties);
this._sendHeader(channel, buffer.length, properties);
var pos = 0, len = buffer.length;
var metaSize = 8; // headerBytes = 7, frameEndBytes = 1
var maxBodySize = maxFrameBuffer - metaSize;
while (len > 0) {
var bodySize = len < maxBodySize ? len : maxBodySize;
var frameSize = bodySize + metaSize;
var b = new Buffer(frameSize);
b.used = 0;
b[b.used++] = 3; // constants.frameBody
serializer.serializeInt(b, 2, channel);
serializer.serializeInt(b, 4, bodySize);
buffer.copy(b, b.used, pos, pos+bodySize);
b.used += bodySize;
b[b.used++] = 206; // constants.frameEnd;
this.write(b);
len -= bodySize;
pos += bodySize;
}
return;
};
// connection: the connection
// channel: the channel to send this on
// size: size in bytes of the following message
// properties: an object containing any of the following:
// - contentType (default 'application/octet-stream')
// - contentEncoding
// - headers
// - deliveryMode
// - priority (0-9)
// - correlationId
// - replyTo
// - expiration
// - messageId
// - timestamp
// - userId
// - appId
// - clusterId
Connection.prototype._sendHeader = function(channel, size, properties) {
var b = new Buffer(maxFrameBuffer); // FIXME allocating too much.
// use freelist?
b.used = 0;
var classInfo = classes[60]; // always basic class.
// 7 OCTET FRAME HEADER
b[b.used++] = 2; // constants.frameHeader
serializer.serializeInt(b, 2, channel);
var lengthStart = b.used;
serializer.serializeInt(b, 4, 0 /*dummy*/); // length
var bodyStart = b.used;
// HEADER'S BODY
serializer.serializeInt(b, 2, classInfo.index); // class 60 for Basic
serializer.serializeInt(b, 2, 0); // weight, always 0 for rabbitmq
serializer.serializeInt(b, 8, size); // byte size of body
// properties - first propertyFlags
properties = _.defaults(properties || {}, {contentType: 'application/octet-stream'});
var propertyFlags = 0;
for (var i = 0; i < classInfo.fields.length; i++) {
if (properties[classInfo.fields[i].name]) propertyFlags |= 1 << (15-i);
}
serializer.serializeInt(b, 2, propertyFlags);
// now the actual properties.
serializer.serializeFields(b, classInfo.fields, properties, false);
//serializeTable(b, properties);
var bodyEnd = b.used;
// Go back to the header and write in the length now that we know it.
b.used = lengthStart;
serializer.serializeInt(b, 4, bodyEnd - bodyStart);
b.used = bodyEnd;
// 1 OCTET END
b[b.used++] = 206; // constants.frameEnd;
var s = new Buffer(b.used);
b.copy(s);
//debug && debug('header sent: ' + JSON.stringify(s));
this.write(s);
};
Connection.prototype._sendMethod = function (channel, method, args) {
debug && debug(channel + " < " + method.name + " " + JSON.stringify(args));
var b = this._sendBuffer;
b.used = 0;
b[b.used++] = 1; // constants.frameMethod
serializer.serializeInt(b, 2, channel);
var lengthIndex = b.used;
serializer.serializeInt(b, 4, 42); // replace with actual length.
var startIndex = b.used;
serializer.serializeInt(b, 2, method.classIndex); // short, classId
serializer.serializeInt(b, 2, method.methodIndex); // short, methodId
serializer.serializeFields(b, method.fields, args, true);
var endIndex = b.used;
// write in the frame length now that we know it.
b.used = lengthIndex;
serializer.serializeInt(b, 4, endIndex - startIndex);
b.used = endIndex;
b[b.used++] = 206; // constants.frameEnd;
var c = new Buffer(b.used);
b.copy(c);
debug && debug("sending frame: " + c.toJSON());
this.write(c);
this._outboundHeartbeatTimerReset();
};
// tries to find the next available id slot for a channel
Connection.prototype.generateChannelId = function () {
// start from the last used slot id
var channelId = this.channelCounter;
while(true){
// use values in range of 1..65535
channelId = channelId % 65535 + 1;
if(!this.channels[channelId]){
break;
}
// after a full loop throw an Error
if(channelId == this.channelCounter){
throw new Error("No valid Channel Id values available");
}
}
this.channelCounter = channelId;
return this.channelCounter;
};
}).call(this,_dereq_("C:\\Users\\Alex\\AppData\\Roaming\\npm\\node_modules\\browserify\\node_modules\\insert-module-globals\\node_modules\\process\\browser.js"),_dereq_("buffer").Buffer)
},{"../package":39,"./debug":30,"./definitions":31,"./exchange":32,"./parser":34,"./queue":36,"./serializer":37,"C:\\Users\\Alex\\AppData\\Roaming\\npm\\node_modules\\browserify\\node_modules\\insert-module-globals\\node_modules\\process\\browser.js":144,"buffer":128,"events":137,"fs":127,"lodash":38,"net":127,"tls":127,"url":157,"util":159}],29:[function(_dereq_,module,exports){
module.exports = {
AMQPTypes: Object.freeze({
STRING: 'S'.charCodeAt(0)
, INTEGER: 'I'.charCodeAt(0)
, HASH: 'F'.charCodeAt(0)
, TIME: 'T'.charCodeAt(0)
, DECIMAL: 'D'.charCodeAt(0)
, BOOLEAN: 't'.charCodeAt(0)
, SIGNED_8BIT: 'b'.charCodeAt(0)
, SIGNED_16BIT: 's'.charCodeAt(0)
, SIGNED_64BIT: 'l'.charCodeAt(0)
, _32BIT_FLOAT: 'f'.charCodeAt(0)
, _64BIT_FLOAT: 'd'.charCodeAt(0)
, VOID: 'v'.charCodeAt(0)
, BYTE_ARRAY: 'x'.charCodeAt(0)
, ARRAY: 'A'.charCodeAt(0)
, TEN: '10'.charCodeAt(0)
, BOOLEAN_TRUE: '\x01'
, BOOLEAN_FALSE:'\x00'
})
, Indicators: Object.freeze({
FRAME_END: 206
})
, FrameType: Object.freeze({
METHOD: 1
, HEADER: 2
, BODY: 3
, HEARTBEAT: 8
})
}
},{}],30:[function(_dereq_,module,exports){
(function (process){
'use strict';
var DEBUG = process.env['NODE_DEBUG_AMQP'];
// only define debug function in debugging mode
if (DEBUG) {
module.exports = function debug () {
console.error.apply(null, arguments);
};
} else {
module.exports = null;
}
}).call(this,_dereq_("C:\\Users\\Alex\\AppData\\Roaming\\npm\\node_modules\\browserify\\node_modules\\insert-module-globals\\node_modules\\process\\browser.js"))
},{"C:\\Users\\Alex\\AppData\\Roaming\\npm\\node_modules\\browserify\\node_modules\\insert-module-globals\\node_modules\\process\\browser.js":144}],31:[function(_dereq_,module,exports){
'use strict';
var protocol = _dereq_('./amqp-definitions-0-9-1');
// a look up table for methods recieved
// indexed on class id, method id
var methodTable = {};
// methods keyed on their name
var methods = {};
// classes keyed on their index
var classes = {};
(function () { // anon scope for init
//debug("initializing amqp methods...");
for (var i = 0; i < protocol.classes.length; i++) {
var classInfo = protocol.classes[i];
classes[classInfo.index] = classInfo;
for (var j = 0; j < classInfo.methods.length; j++) {
var methodInfo = classInfo.methods[j];
var name = classInfo.name +
methodInfo.name[0].toUpperCase() +
methodInfo.name.slice(1);
//debug(name);
var method = {
name: name,
fields: methodInfo.fields,
methodIndex: methodInfo.index,
classIndex: classInfo.index
};
if (!methodTable[classInfo.index]) methodTable[classInfo.index] = {};
methodTable[classInfo.index][methodInfo.index] = method;
methods[name] = method;
}
}
})();
module.exports = {methods: methods, classes: classes, methodTable: methodTable};
},{"./amqp-definitions-0-9-1":26}],32:[function(_dereq_,module,exports){
'use strict';
var events = _dereq_('events');
var util = _dereq_('util');
var net = _dereq_('net');
var tls = _dereq_('tls');
var fs = _dereq_('fs');
var _ = _dereq_('lodash');
var methods = _dereq_('./definitions').methods;
var Channel = _dereq_('./channel');
var Exchange = module.exports = function Exchange (connection, channel, name, options, openCallback) {
Channel.call(this, connection, channel);
this.name = name;
this.binds = 0; // keep track of queues bound
this.exchangeBinds = 0; // keep track of exchanges bound
this.sourceExchanges = {};
this.options = _.defaults(options || {}, {autoDelete: true});
this._openCallback = openCallback;
this._sequence = null;
this._unAcked = {};
this._addedExchangeErrorHandler = false;
};
util.inherits(Exchange, Channel);
// creates an error handler scoped to the given `exchange`
function createExchangeErrorHandlerFor (exchange) {
return function (err) {
if (!exchange.options.confirm) return;
for (var id in exchange._unAcked) {
var task = exchange._unAcked[id];
task.emit('ack error', err);
delete exchange._unAcked[id];
}
}
};
Exchange.prototype._onMethod = function (channel, method, args) {
this.emit(method.name, args);
if (this._handleTaskReply.apply(this, arguments))
return true;
var cb;
switch (method) {
case methods.channelOpenOk:
// Pre-baked exchanges don't need to be declared
if (/^$|(amq\.)/.test(this.name)) {
this.state = 'open';
// - issue #33 fix
if (this._openCallback) {
this._openCallback(this);
this._openCallback = null;
}
// --
this.emit('open');
// For if we want to delete a exchange,
// we dont care if all of the options match.
} else if (this.options.noDeclare) {
this.state = 'open';
if (this._openCallback) {
this._openCallback(this);
this._openCallback = null;
}
this.emit('open');
} else {
this.connection._sendMethod(channel, methods.exchangeDeclare,
{ reserved1: 0
, reserved2: false
, reserved3: false
, exchange: this.name
, type: this.options.type || 'topic'
, passive: !!this.options.passive
, durable: !!this.options.durable
, autoDelete: !!this.options.autoDelete
, internal: !!this.options.internal
, noWait: false
, "arguments":this.options.arguments || {}
});
this.state = 'declaring';
}
break;
case methods.exchangeDeclareOk:
if (this.options.confirm) {
this.connection._sendMethod(channel, methods.confirmSelect,
{ noWait: false });
} else {
this.state = 'open';
this.emit('open');
if (this._openCallback) {
this._openCallback(this);
this._openCallback = null;
}
}
break;
case methods.confirmSelectOk:
this._sequence = 1;
this.state = 'open';
this.emit('open');
if (this._openCallback) {
this._openCallback(this);
this._openCallback = null;
}
break;
case methods.channelClose:
this.state = "closed";
this.closeOK();
this.connection.exchangeClosed(this.name);
var e = new Error(args.replyText);
e.code = args.replyCode;
this.emit('error', e);
this.emit('close');
break;
case methods.channelCloseOk:
this.connection.exchangeClosed(this.name);
this.emit('close');
break;
case methods.basicAck:
this.emit('basic-ack', args);
var sequenceNumber = args.deliveryTag.readUInt32BE(4), tag;
if (sequenceNumber === 0 && args.multiple === true) {
// we must ack everything
for (tag in this._unAcked) {
this._unAcked[tag].emit('ack');
delete this._unAcked[tag];
}
} else if (sequenceNumber !== 0 && args.multiple === true) {
// we must ack everything before the delivery tag
for (tag in this._unAcked) {
if (tag <= sequenceNumber) {
this._unAcked[tag].emit('ack');
delete this._unAcked[tag];
}
}
} else if (this._unAcked[sequenceNumber] && args.multiple === false) {
// simple single ack
this._unAcked[sequenceNumber].emit('ack');
delete this._unAcked[sequenceNumber];
}
break;
case methods.basicReturn:
this.emit('basic-return', args);
break;
case methods.exchangeBindOk:
if (this._bindCallback) {
// setting this._bindCallback to null before calling the callback allows for a subsequent bind within the callback
cb = this._bindCallback;
this._bindCallback = null;
cb(this);
}
break;
case methods.exchangeUnbindOk:
if (this._unbindCallback) {
cb = this._unbindCallback;
this._unbindCallback = null;
cb(this);
}
break;
default:
throw new Error("Uncaught method '" + method.name + "' with args " +
JSON.stringify(args));
}
this._tasksFlush();
};
// exchange.publish('routing.key', 'body');
//
// the third argument can specify additional options
// - mandatory (boolean, default false)
// - immediate (boolean, default false)
// - contentType (default 'application/octet-stream')
// - contentEncoding
// - headers
// - deliveryMode
// - priority (0-9)
// - correlationId
// - replyTo
// - expiration
// - messageId
// - timestamp
// - userId
// - appId
// - clusterId
//
// the callback is optional and is only used when confirm is turned on for the exchange
Exchange.prototype.publish = function (routingKey, data, options, callback) {
var self = this;
options = _.extend({}, options || {});
options.routingKey = routingKey;
options.exchange = self.name;
options.mandatory = options.mandatory ? true : false;
options.immediate = options.immediate ? true : false;
options.reserved1 = 0;
var task = this._taskPush(null, function () {
self.connection._sendMethod(self.channel, methods.basicPublish, options);
// This interface is probably not appropriate for streaming large files.
// (Of course it's arguable about whether AMQP is the appropriate
// transport for large files.) The content header wants to know the size
// of the data before sending it - so there's no point in trying to have a
// general streaming interface - streaming messages of unknown size simply
// isn't possible with AMQP. This is all to say, don't send big messages.
// If you need to stream something large, chunk it yourself.
self.connection._sendBody(self.channel, data, options);
});
if (self.options.confirm) self._awaitConfirm(task, callback);
return task;
};
// registers tasks for confirms
Exchange.prototype._awaitConfirm = function _awaitConfirm (task, callback) {
if (!this._addedExchangeErrorHandler) {
this.on('error', createExchangeErrorHandlerFor(this));
this._addedExchangeErrorHandler = true;
}
task.sequence = this._sequence;
this._unAcked[this._sequence] = task;
this._sequence++;
if ('function' != typeof callback) return;
task.once('ack error', function (err) {
task.removeAllListeners();
callback(true, err);
});
task.once('ack', function () {
task.removeAllListeners();
callback(false);
});
};
// do any necessary cleanups eg. after queue destruction
Exchange.prototype.cleanup = function() {
if (this.binds === 0) { // don't keep reference open if unused
this.connection.exchangeClosed(this.name);
}
};
Exchange.prototype.destroy = function (ifUnused) {
var self = this;
return this._taskPush(methods.exchangeDeleteOk, function () {
self.connection.exchangeClosed(self.name);
self.connection._sendMethod(self.channel, methods.exchangeDelete,
{ reserved1: 0
, exchange: self.name
, ifUnused: ifUnused ? true : false
, noWait: false
});
});
};
// E2E Unbind
// support RabbitMQ's exchange-to-exchange binding extension
// http://www.rabbitmq.com/e2e.html
Exchange.prototype.unbind = function (/* exchange, routingKey [, bindCallback] */) {
var self = this;
// Both arguments are required. The binding to the destination
// exchange/routingKey will be unbound.
var exchange = arguments[0]
, routingKey = arguments[1]
, callback = arguments[2]
;
if (callback) this._unbindCallback = callback;
return this._taskPush(methods.exchangeUnbindOk, function () {
var source = exchange instanceof Exchange ? exchange.name : exchange;
var destination = self.name;
if (source in self.connection.exchanges) {
delete self.sourceExchanges[source];
self.connection.exchanges[source].exchangeBinds--;
}
self.connection._sendMethod(self.channel, methods.exchangeUnbind,
{ reserved1: 0
, destination: destination
, source: source
, routingKey: routingKey
, noWait: false
, "arguments": {}
});
});
};
// E2E Bind
// support RabbitMQ's exchange-to-exchange binding extension
// http://www.rabbitmq.com/e2e.html
Exchange.prototype.bind = function (/* exchange, routingKey [, bindCallback] */) {
var self = this;
// Two arguments are required. The binding to the destination
// exchange/routingKey will be established.
var exchange = arguments[0]
, routingKey = arguments[1]
, callback = arguments[2]
;
if (callback) this._bindCallback = callback;
var source = exchange instanceof Exchange ? exchange.name : exchange;
var destination = self.name;
if(source in self.connection.exchanges) {
self.sourceExchanges[source] = self.connection.exchanges[source];
self.connection.exchanges[source].exchangeBinds++;
}
self.connection._sendMethod(self.channel, methods.exchangeBind,
{ reserved1: 0
, destination: destination
, source: source
, routingKey: routingKey
, noWait: false
, "arguments": {}
});
};
// E2E Bind
// support RabbitMQ's exchange-to-exchange binding extension
// http://www.rabbitmq.com/e2e.html
Exchange.prototype.bind_headers = function (/* exchange, routing [, bindCallback] */) {
var self = this;
// Two arguments are required. The binding to the destination
// exchange/routingKey will be established.
var exchange = arguments[0]
, routing = arguments[1]
, callback = arguments[2]
;
if (callback) this._bindCallback = callback;
var source = exchange instanceof Exchange ? exchange.name : exchange;
var destination = self.name;
if (source in self.connection.exchanges) {
self.sourceExchanges[source] = self.connection.exchanges[source];
self.connection.exchanges[source].exchangeBinds++;
}
self.connection._sendMethod(self.channel, methods.exchangeBind,
{ reserved1: 0
, destination: destination
, source: source
, routingKey: ''
, noWait: false
, "arguments": routing
});
};
},{"./channel":27,"./definitions":31,"events":137,"fs":127,"lodash":38,"net":127,"tls":127,"util":159}],33:[function(_dereq_,module,exports){
'use strict';
var events = _dereq_('events'),
util = _dereq_('util'),
fs = _dereq_('fs'),
protocol,
definitions = _dereq_('./definitions');
// Properties:
// - routingKey
// - size
// - deliveryTag
//
// - contentType (default 'application/octet-stream')
// - contentEncoding
// - headers
// - deliveryMode
// - priority (0-9)
// - correlationId
// - replyTo
// - experation
// - messageId
// - timestamp
// - userId
// - appId
// - clusterId
var Message = module.exports = function Message (queue, args) {
var msgProperties = definitions.classes[60].fields;
events.EventEmitter.call(this);
this.queue = queue;
this.deliveryTag = args.deliveryTag;
this.redelivered = args.redelivered;
this.exchange = args.exchange;
this.routingKey = args.routingKey;
this.consumerTag = args.consumerTag;
for (var i=0, l=msgProperties.length; i<l; i++) {
if (args[msgProperties[i].name]) {
this[msgProperties[i].name] = args[msgProperties[i].name];
}
}
};
util.inherits(Message, events.EventEmitter);
// Acknowledge receipt of message.
// Set first arg to 'true' to acknowledge this and all previous messages
// received on this queue.
Message.prototype.acknowledge = function (all) {
this.queue.connection._sendMethod(this.queue.channel, definitions.methods.basicAck,
{ reserved1: 0
, deliveryTag: this.deliveryTag
, multiple: all ? true : false
});
};
// Reject an incoming message.
// Set first arg to 'true' to requeue the message.
Message.prototype.reject = function (requeue) {
this.queue.connection._sendMethod(this.queue.channel, definitions.methods.basicReject,
{ deliveryTag: this.deliveryTag
, requeue: requeue ? true : false
});
};
},{"./definitions":31,"events":137,"fs":127,"util":159}],34:[function(_dereq_,module,exports){
(function (Buffer){
'use strict';
var events = _dereq_('events');
var util = _dereq_('util');
var net = _dereq_('net');
var tls = _dereq_('tls');
var fs = _dereq_('fs');
var debug = _dereq_('./debug');
var jspack = _dereq_('../jspack').jspack;
var AMQPTypes = _dereq_('./constants').AMQPTypes;
var Indicators = _dereq_('./constants').Indicators;
var FrameType = _dereq_('./constants').FrameType;
var definitions = _dereq_('./definitions');
var methodTable = definitions.methodTable;
var classes = definitions.classes;
// parser
var maxFrameBuffer = 131072; // 128k, same as rabbitmq (which was
// copying qpid)
// An interruptible AMQP parser.
//
// type is either 'server' or 'client'
// version is '0-9-1'.
//
// Instances of this class have several callbacks
// - onMethod(channel, method, args);
// - onHeartBeat()
// - onContent(channel, buffer);
// - onContentHeader(channel, class, weight, properties, size);
//
// This class does not subclass EventEmitter, in order to reduce the speed
// of emitting the callbacks. Since this is an internal class, that should
// be fine.
var AMQPParser = module.exports = function AMQPParser (version, type) {
this.isClient = (type == 'client');
this.state = this.isClient ? 'frameHeader' : 'protocolHeader';
if (version != '0-9-1') this.throwError("Unsupported protocol version");
var frameHeader = new Buffer(7);
frameHeader.used = 0;
var frameBuffer, frameType, frameChannel;
var self = this;
function header(data) {
var fh = frameHeader;
var needed = fh.length - fh.used;
data.copy(fh, fh.used, 0, data.length);
fh.used += data.length; // sloppy
if (fh.used >= fh.length) {
fh.read = 0;
frameType = fh[fh.read++];
frameChannel = parseInt(fh, 2);
var frameSize = parseInt(fh, 4);
fh.used = 0; // for reuse
if (frameSize > maxFrameBuffer) {
self.throwError("Oversized frame " + frameSize);
}
frameBuffer = new Buffer(frameSize);
frameBuffer.used = 0;
return frame(data.slice(needed));
}
else { // need more!
return header;
}
}
function frame(data) {
var fb = frameBuffer;
var needed = fb.length - fb.used;
var sourceEnd = (fb.length > data.length) ? data.length : fb.length;
data.copy(fb, fb.used, 0, sourceEnd);
fb.used += data.length;
if (data.length > needed) {
return frameEnd(data.slice(needed));
}
else if (data.length == needed) {
return frameEnd;
}
else {
return frame;
}
}
function frameEnd(data) {
if (data.length > 0) {
if (data[0] === Indicators.FRAME_END) {
switch (frameType) {
case FrameType.METHOD:
self._parseMethodFrame(frameChannel, frameBuffer);
break;
case FrameType.HEADER:
self._parseHeaderFrame(frameChannel, frameBuffer);
break;
case FrameType.BODY:
if (self.onContent) {
self.onContent(frameChannel, frameBuffer);
}
break;
case FrameType.HEARTBEAT:
debug && debug("heartbeat");
if (self.onHeartBeat) self.onHeartBeat();
break;
default:
self.throwError("Unhandled frame type " + frameType);
break;
}
return header(data.slice(1));
}
else {
self.throwError("Missing frame end marker");
}
}
else {
return frameEnd;
}
}
self.parse = header;
}
// If there's an error in the parser, call the onError handler or throw
AMQPParser.prototype.throwError = function (error) {
if (this.onError) this.onError(error);
else throw new Error(error);
};
// Everytime data is recieved on the socket, pass it to this function for
// parsing.
AMQPParser.prototype.execute = function (data) {
// This function only deals with dismantling and buffering the frames.
// It delegates to other functions for parsing the frame-body.
debug && debug('execute: ' + data.toString('hex'));
this.parse = this.parse(data);
};
// parse Network Byte Order integers. size can be 1,2,4,8
function parseInt (buffer, size) {
switch (size) {
case 1:
return buffer[buffer.read++];
case 2:
return (buffer[buffer.read++] << 8) + buffer[buffer.read++];
case 4:
return (buffer[buffer.read++] << 24) + (buffer[buffer.read++] << 16) +
(buffer[buffer.read++] << 8) + buffer[buffer.read++];
case 8:
return (buffer[buffer.read++] << 56) + (buffer[buffer.read++] << 48) +
(buffer[buffer.read++] << 40) + (buffer[buffer.read++] << 32) +
(buffer[buffer.read++] << 24) + (buffer[buffer.read++] << 16) +
(buffer[buffer.read++] << 8) + buffer[buffer.read++];
default:
throw new Error("cannot parse ints of that size");
}
}
function parseShortString (buffer) {
var length = buffer[buffer.read++];
var s = buffer.toString('utf8', buffer.read, buffer.read+length);
buffer.read += length;
return s;
}
function parseLongString (buffer) {
var length = parseInt(buffer, 4);
var s = buffer.slice(buffer.read, buffer.read + length);
buffer.read += length;
return s.toString();
}
function parseSignedInteger (buffer) {
var int = parseInt(buffer, 4);
if (int & 0x80000000) {
int |= 0xEFFFFFFF;
int = -int;
}
return int;
}
function parseValue (buffer) {
switch (buffer[buffer.read++]) {
case AMQPTypes.STRING:
return parseLongString(buffer);
case AMQPTypes.INTEGER:
return parseInt(buffer, 4);
case AMQPTypes.DECIMAL:
var dec = parseInt(buffer, 1);
var num = parseInt(buffer, 4);
return num / (dec * 10);
case AMQPTypes._64BIT_FLOAT:
var b = [];
for (var i = 0; i < 8; ++i)
b[i] = buffer[buffer.read++];
return (new jspack(true)).Unpack('d', b);
case AMQPTypes._32BIT_FLOAT:
var b = [];
for (var i = 0; i < 4; ++i)
b[i] = buffer[buffer.read++];
return (new jspack(true)).Unpack('f', b);
case AMQPTypes.TIME:
var int = parseInt(buffer, 8);
return (new Date()).setTime(int * 1000);
case AMQPTypes.HASH:
return parseTable(buffer);
case AMQPTypes.SIGNED_64BIT:
return parseInt(buffer, 8);
case AMQPTypes.BOOLEAN:
return (parseInt(buffer, 1) > 0);
case AMQPTypes.BYTE_ARRAY:
var len = parseInt(buffer, 4);
var buf = new Buffer(len);
buffer.copy(buf, 0, buffer.read, buffer.read + len);
buffer.read += len;
return buf;
case AMQPTypes.ARRAY:
var len = parseInt(buffer, 4);
var end = buffer.read + len;
var arr = [];
while (buffer.read < end) {
arr.push(parseValue(buffer));
}
return arr;
default:
throw new Error("Unknown field value type " + buffer[buffer.read-1]);
}
}
function parseTable (buffer) {
var length = buffer.read + parseInt(buffer, 4);
var table = {};
while (buffer.read < length) {
table[parseShortString(buffer)] = parseValue(buffer);
}
return table;
}
function parseFields (buffer, fields) {
var args = {};
var bitIndex = 0;
var value;
for (var i = 0; i < fields.length; i++) {
var field = fields[i];
//debug && debug("parsing field " + field.name + " of type " + field.domain);
switch (field.domain) {
case 'bit':
// 8 bits can be packed into one octet.
// XXX check if bitIndex greater than 7?
value = (buffer[buffer.read] & (1 << bitIndex)) ? true : false;
if (fields[i+1] && fields[i+1].domain == 'bit') {
bitIndex++;
} else {
bitIndex = 0;
buffer.read++;
}
break;
case 'octet':
value = buffer[buffer.read++];
break;
case 'short':
value = parseInt(buffer, 2);
break;
case 'long':
value = parseInt(buffer, 4);
break;
// In a previous version this shared code with 'longlong', which caused problems when passed Date
// integers. Nobody expects to pass a Buffer here, 53 bits is still 28 million years after 1970, we'll be fine.
case 'timestamp':
value = parseInt(buffer, 8);
break;
// JS doesn't support 64-bit Numbers, so we expect if you're using 'longlong' that you've
// used a Buffer instead
case 'longlong':
value = new Buffer(8);
for (var j = 0; j < 8; j++) {
value[j] = buffer[buffer.read++];
}
break;
case 'shortstr':
value = parseShortString(buffer);
break;
case 'longstr':
value = parseLongString(buffer);
break;
case 'table':
value = parseTable(buffer);
break;
default:
throw new Error("Unhandled parameter type " + field.domain);
}
//debug && debug("got " + value);
args[field.name] = value;
}
return args;
}
AMQPParser.prototype._parseMethodFrame = function (channel, buffer) {
buffer.read = 0;
var classId = parseInt(buffer, 2),
methodId = parseInt(buffer, 2);
// Make sure that this is a method that we understand.
if (!methodTable[classId] || !methodTable[classId][methodId]) {
this.throwError("Received unknown [classId, methodId] pair [" +
classId + ", " + methodId + "]");
}
var method = methodTable[classId][methodId];
if (!method) this.throwError("bad method?");
var args = parseFields(buffer, method.fields);
if (this.onMethod) {
debug && debug("Executing method", channel, method, args);
this.onMethod(channel, method, args);
}
};
AMQPParser.prototype._parseHeaderFrame = function (channel, buffer) {
buffer.read = 0;
var classIndex = parseInt(buffer, 2);
var weight = parseInt(buffer, 2);
var size = parseInt(buffer, 8);
var classInfo = classes[classIndex];
if (classInfo.fields.length > 15) {
this.throwError("TODO: support more than 15 properties");
}
var propertyFlags = parseInt(buffer, 2);
var fields = [];
for (var i = 0; i < classInfo.fields.length; i++) {
var field = classInfo.fields[i];
// groan.
if (propertyFlags & (1 << (15-i))) fields.push(field);
}
var properties = parseFields(buffer, fields);
if (this.onContentHeader) {
this.onContentHeader(channel, classInfo, weight, properties, size);
}
};
}).call(this,_dereq_("buffer").Buffer)
},{"../jspack":25,"./constants":29,"./debug":30,"./definitions":31,"buffer":128,"events":137,"fs":127,"net":127,"tls":127,"util":159}],35:[function(_dereq_,module,exports){
(function (process){
var events = _dereq_('events');
var inherits = _dereq_('util').inherits;
exports.Promise = function () {
events.EventEmitter.call(this);
this._blocking = false;
this.hasFired = false;
this.hasAcked = false;
this._values = undefined;
};
inherits(exports.Promise, events.EventEmitter);
exports.Promise.prototype.timeout = function(timeout) {
if (!timeout) {
return this._timeoutDuration;
}
this._timeoutDuration = timeout;
if (this.hasFired) return;
this._clearTimeout();
var self = this;
this._timer = setTimeout(function() {
self._timer = null;
if (self.hasFired) {
return;
}
self.emitError(new Error('timeout'));
}, timeout);
return this;
};
exports.Promise.prototype._clearTimeout = function() {
if (!this._timer) return;
clearTimeout(this._timer);
this._timer = null;
}
exports.Promise.prototype.emitSuccess = function() {
if (this.hasFired) return;
this.hasFired = 'success';
this._clearTimeout();
this._values = Array.prototype.slice.call(arguments);
this.emit.apply(this, ['success'].concat(this._values));
};
exports.Promise.prototype.emitError = function() {
if (this.hasFired) return;
this.hasFired = 'error';
this._clearTimeout();
this._values = Array.prototype.slice.call(arguments);
this.emit.apply(this, ['error'].concat(this._values));
if (this.listeners('error').length == 0) {
var self = this;
process.nextTick(function() {
if (self.listeners('error').length == 0) {
throw (self._values[0] instanceof Error)
? self._values[0]
: new Error('Unhandled emitError: '+JSON.stringify(self._values));
}
});
}
};
exports.Promise.prototype.addCallback = function (listener) {
if (this.hasFired === 'success') {
listener.apply(this, this._values);
}
return this.addListener("success", listener);
};
exports.Promise.prototype.addErrback = function (listener) {
if (this.hasFired === 'error') {
listener.apply(this, this._values);
}
return this.addListener("error", listener);
};
}).call(this,_dereq_("C:\\Users\\Alex\\AppData\\Roaming\\npm\\node_modules\\browserify\\node_modules\\insert-module-globals\\node_modules\\process\\browser.js"))
},{"C:\\Users\\Alex\\AppData\\Roaming\\npm\\node_modules\\browserify\\node_modules\\insert-module-globals\\node_modules\\process\\browser.js":144,"events":137,"util":159}],36:[function(_dereq_,module,exports){
(function (process,Buffer){
'use strict';
var util = _dereq_('util');
var fs = _dereq_('fs');
var _ = _dereq_('lodash');
var Channel = _dereq_('./channel');
var Exchange = _dereq_('./exchange');
var Message = _dereq_('./message');
var debug = _dereq_('./debug');
var definitions = _dereq_('./definitions');
var methods = definitions.methods;
var classes = definitions.classes;
var Queue = module.exports = function Queue (connection, channel, name, options, callback) {
Channel.call(this, connection, channel);
var self = this;
this.name = name;
this._bindings = {};
this.consumerTagListeners = {};
this.consumerTagOptions = {};
// route messages to subscribers based on consumerTag
this.on('rawMessage', function(message) {
if (message.consumerTag && self.consumerTagListeners[message.consumerTag]) {
self.consumerTagListeners[message.consumerTag](message);
}
});
this.options = { autoDelete: true, closeChannelOnUnsubscribe: false };
_.extend(this.options, options || {});
this._openCallback = callback;
};
util.inherits(Queue, Channel);
Queue.prototype.subscribeRaw = function (options, messageListener) {
var self = this;
// multiple method signatures
if (typeof options === "function") {
messageListener = options;
options = {};
}
var consumerTag = 'node-amqp-' + process.pid + '-' + Math.random();
this.consumerTagListeners[consumerTag] = messageListener;
options = options || {};
options['state'] = 'opening';
this.consumerTagOptions[consumerTag] = options;
if (options.prefetchCount !== undefined) {
self.connection._sendMethod(self.channel, methods.basicQos,
{ reserved1: 0
, prefetchSize: 0
, prefetchCount: options.prefetchCount
, global: false
});
}
return this._taskPush(methods.basicConsumeOk, function () {
self.connection._sendMethod(self.channel, methods.basicConsume,
{ reserved1: 0
, queue: self.name
, consumerTag: consumerTag
, noLocal: !!options.noLocal
, noAck: !!options.noAck
, exclusive: !!options.exclusive
, noWait: false
, "arguments": {}
});
self.consumerTagOptions[consumerTag]['state'] = 'open';
});
};
Queue.prototype.unsubscribe = function(consumerTag) {
var self = this;
return this._taskPush(methods.basicCancelOk, function () {
self.connection._sendMethod(self.channel, methods.basicCancel,
{ reserved1: 0,
consumerTag: consumerTag,
noWait: false });
})
.addCallback(function () {
if (self.options.closeChannelOnUnsubscribe) {
self.close();
}
delete self.consumerTagListeners[consumerTag];
delete self.consumerTagOptions[consumerTag];
});
};
Queue.prototype.subscribe = function (options, messageListener) {
var self = this;
// Optional options
if (typeof options === "function") {
messageListener = options;
options = {};
}
options = _.defaults(options || {}, {
ack: false,
prefetchCount: 1,
routingKeyInPayload: self.connection.options.routingKeyInPayload,
deliveryTagInPayload: self.connection.options.deliveryTagInPayload
});
// basic consume
var rawOptions = {
noAck: !options.ack,
exclusive: options.exclusive
};
if (options.ack) {
rawOptions['prefetchCount'] = options.prefetchCount;
}
return this.subscribeRaw(rawOptions, function (m) {
var contentType = m.contentType;
if (contentType == null && m.headers && m.headers.properties) {
contentType = m.headers.properties.content_type;
}
var isJSON = contentType == 'text/json' ||
contentType == 'application/json';
var buffer;
if (isJSON) {
buffer = "";
} else {
buffer = new Buffer(m.size);
buffer.used = 0;
}
self._lastMessage = m;
m.addListener('data', function (d) {
if (isJSON) {
buffer += d.toString();
} else {
d.copy(buffer, buffer.used);
buffer.used += d.length;
}
});
m.addListener('end', function () {
var json, deliveryInfo = {}, msgProperties = classes[60].fields, i, l;
if (isJSON) {
try {
json = JSON.parse(buffer);
} catch (e) {
json = null;
deliveryInfo.parseError = e;
deliveryInfo.rawData = buffer;
}
} else {
json = { data: buffer, contentType: m.contentType };
}
for (i = 0, l = msgProperties.length; i<l; i++) {
if (m[msgProperties[i].name]) {
deliveryInfo[msgProperties[i].name] = m[msgProperties[i].name];
}
}
deliveryInfo.queue = m.queue ? m.queue.name : null;
deliveryInfo.deliveryTag = m.deliveryTag;
deliveryInfo.redelivered = m.redelivered;
deliveryInfo.exchange = m.exchange;
deliveryInfo.routingKey = m.routingKey;
deliveryInfo.consumerTag = m.consumerTag;
if (options.routingKeyInPayload) json._routingKey = m.routingKey;
if (options.deliveryTagInPayload) json._deliveryTag = m.deliveryTag;
var headers = {};
for (i in this.headers) {
if (this.headers.hasOwnProperty(i)) {
if (this.headers[i] instanceof Buffer) {
headers[i] = this.headers[i].toString();
} else {
headers[i] = this.headers[i];
}
}
}
if (messageListener) messageListener(json, headers, deliveryInfo, m);
self.emit('message', json, headers, deliveryInfo, m);
});
});
};
Queue.prototype.subscribeJSON = Queue.prototype.subscribe;
/* Acknowledges the last message */
Queue.prototype.shift = function (reject, requeue) {
if (this._lastMessage) {
if (reject) {
this._lastMessage.reject(requeue ? true : false);
} else {
this._lastMessage.acknowledge();
}
}
};
Queue.prototype.bind = function (exchange, routingKey, callback) {
var self = this;
// The first argument, exchange is optional.
// If not supplied the connection will use the 'amq.topic'
// exchange.
if (routingKey === undefined || _.isFunction(routingKey)) {
callback = routingKey;
routingKey = exchange;
exchange = 'amq.topic';
}
if (_.isFunction(callback)) this._bindCallback = callback;
var exchangeName = exchange instanceof Exchange ? exchange.name : exchange;
if (exchangeName in self.connection.exchanges) {
this.exchange = self.connection.exchanges[exchangeName];
this.exchange.binds++;
}
// Record this binding so we can restore it upon reconnect.
if (!this._bindings[exchangeName]) {
this._bindings[exchangeName] = {};
}
if (!this._bindings[exchangeName][routingKey]) {
this._bindings[exchangeName][routingKey] = 0;
}
this._bindings[exchangeName][routingKey]++;
self.connection._sendMethod(self.channel, methods.queueBind,
{ reserved1: 0
, queue: self.name
, exchange: exchangeName
, routingKey: routingKey
, noWait: false
, "arguments": {}
});
};
Queue.prototype.unbind = function (exchange, routingKey) {
var self = this;
// The first argument, exchange is optional.
// If not supplied the connection will use the default 'amq.topic'
// exchange.
if (routingKey === undefined) {
routingKey = exchange;
exchange = 'amq.topic';
}
var exchangeName = exchange instanceof Exchange ? exchange.name : exchange;
// Decrement binding count.
this._bindings[exchangeName][routingKey]--;
if (!this._bindings[exchangeName][routingKey]) {
delete this._bindings[exchangeName][routingKey];
}
// If there are no more bindings to this exchange, delete the key for the exchange.
if (!_.keys(this._bindings[exchangeName]).length){
delete this._bindings[exchangeName];
}
return this._taskPush(methods.queueUnbindOk, function () {
self.connection._sendMethod(self.channel, methods.queueUnbind,
{ reserved1: 0
, queue: self.name
, exchange: exchangeName
, routingKey: routingKey
, noWait: false
, "arguments": {}
});
});
};
Queue.prototype.bind_headers = function (/* [exchange,] matchingPairs */) {
var self = this;
// The first argument, exchange is optional.
// If not supplied the connection will use the default 'amq.headers'
// exchange.
var exchange, matchingPairs;
if (arguments.length == 2) {
exchange = arguments[0];
matchingPairs = arguments[1];
} else {
exchange = 'amq.headers';
matchingPairs = arguments[0];
}
return this._taskPush(methods.queueBindOk, function () {
var exchangeName = exchange instanceof Exchange ? exchange.name : exchange;
self.connection._sendMethod(self.channel, methods.queueBind,
{ reserved1: 0
, queue: self.name
, exchange: exchangeName
, routingKey: ''
, noWait: false
, "arguments": matchingPairs
});
});
};
Queue.prototype.unbind_headers = function (/* [exchange,] matchingPairs */) {
var self = this;
// The first argument, exchange is optional.
// If not supplied the connection will use the default 'amq.topic'
// exchange.
var exchange, matchingPairs;
if (arguments.length === 2) {
exchange = arguments[0];
matchingPairs = arguments[1];
} else {
exchange = 'amq.headers';
matchingPairs = arguments[0];
}
return this._taskPush(methods.queueUnbindOk, function () {
var exchangeName = exchange instanceof Exchange ? exchange.name : exchange;
self.connection._sendMethod(self.channel, methods.queueUnbind,
{ reserved1: 0
, queue: self.name
, exchange: exchangeName
, routingKey: ''
, noWait: false
, "arguments": matchingPairs
});
});
};
Queue.prototype.destroy = function (options) {
var self = this;
options = options || {};
return this._taskPush(methods.queueDeleteOk, function () {
self.connection.queueClosed(self.name);
if ('exchange' in self) {
self.exchange.binds--;
self.exchange.cleanup();
}
self.connection._sendMethod(self.channel, methods.queueDelete,
{ reserved1: 0
, queue: self.name
, ifUnused: options.ifUnused ? true : false
, ifEmpty: options.ifEmpty ? true : false
, noWait: false
, "arguments": {}
});
});
};
Queue.prototype.purge = function() {
var self = this;
return this._taskPush(methods.queuePurgeOk, function () {
self.connection._sendMethod(self.channel, methods.queuePurge,
{ reserved1 : 0,
queue: self.name,
noWait: false});
});
};
Queue.prototype._onMethod = function (channel, method, args) {
var self = this;
this.emit(method.name, args);
if (this._handleTaskReply.apply(this, arguments)) return;
switch (method) {
case methods.channelOpenOk:
if (this.options.noDeclare) {
this.state = 'open';
if (this._openCallback) {
this._openCallback(this);
this._openCallback = null;
}
this.emit('open');
} else {
if (this.name.indexOf('amq.') == 0) {
this.name = '';
}
this.connection._sendMethod(channel, methods.queueDeclare,
{ reserved1: 0
, queue: this.name
, passive: !!this.options.passive
, durable: !!this.options.durable
, exclusive: !!this.options.exclusive
, autoDelete: !!this.options.autoDelete
, noWait: false
, "arguments": this.options.arguments || {}
});
this.state = "declare queue";
}
break;
case methods.queueDeclareOk:
this.state = 'open';
this.name = args.queue;
this.connection.queues[this.name] = this;
// Rebind to previously bound exchanges, if present.
// Important this is called *before* openCallback, otherwise bindings will happen twice.
// Run test-purge to make sure you got this right
_.each(this._bindings, function(exchange, exchangeName){
_.each(exchange, function(count, routingKey){
self.bind(exchangeName, routingKey);
});
});
// Call opening callback (passed in function)
// FIXME use eventemitter - maybe we call a namespaced event here
if (this._openCallback) {
this._openCallback(this, args.messageCount, args.consumerCount);
this._openCallback = null;
}
// TODO this is legacy interface, remove me
this.emit('open', args.queue, args.messageCount, args.consumerCount);
// If this is a reconnect, we must re-subscribe our queue listeners.
var consumerTags = Object.keys(this.consumerTagListeners);
for (var index in consumerTags) {
if (consumerTags.hasOwnProperty(index)) {
if (this.consumerTagOptions[consumerTags[index]]['state'] === 'closed') {
this.subscribeRaw(this.consumerTagOptions[consumerTags[index]], this.consumerTagListeners[consumerTags[index]]);
// Having called subscribeRaw, we are now a new consumer with a new consumerTag.
delete this.consumerTagListeners[consumerTags[index]];
delete this.consumerTagOptions[consumerTags[index]];
}
}
}
break;
case methods.basicConsumeOk:
debug && debug('basicConsumeOk', util.inspect(args, null));
break;
case methods.queueBindOk:
if (this._bindCallback) {
// setting this._bindCallback to null before calling the callback allows for a subsequent bind within the callback
// FIXME use eventemitter
var cb = this._bindCallback;
this._bindCallback = null;
cb(this);
}
break;
case methods.queueUnbindOk:
break;
case methods.basicQosOk:
break;
case methods.confirmSelectOk:
this._sequence = 1;
this.confirm = true;
break;
case methods.channelClose:
this.state = "closed";
this.closeOK();
this.connection.queueClosed(this.name);
var e = new Error(args.replyText);
e.code = args.replyCode;
this.emit('error', e);
this.emit('close');
break;
case methods.channelCloseOk:
this.connection.queueClosed(this.name);
this.emit('close');
break;
case methods.basicDeliver:
this.currentMessage = new Message(this, args);
break;
case methods.queueDeleteOk:
break;
case methods.basicCancel:
this.close("Closed due to basicCancel received on consumer (" + args.consumerTag + ")");
break;
default:
throw new Error("Uncaught method '" + method.name + "' with args " +
JSON.stringify(args) + "; tasks = " + JSON.stringify(this._tasks));
}
this._tasksFlush();
};
Queue.prototype._onContentHeader = function (channel, classInfo, weight, properties, size) {
_.extend(this.currentMessage, properties);
this.currentMessage.read = 0;
this.currentMessage.size = size;
this.emit('rawMessage', this.currentMessage);
if (size === 0) {
// If the message has no body, directly emit 'end'
this.currentMessage.emit('end');
}
};
Queue.prototype._onContent = function (channel, data) {
this.currentMessage.read += data.length;
this.currentMessage.emit('data', data);
if (this.currentMessage.read == this.currentMessage.size) {
this.currentMessage.emit('end');
}
};
Queue.prototype.flow = function(active) {
var self = this;
return this._taskPush(methods.channelFlowOk, function () {
self.connection._sendMethod(self.channel, methods.channelFlow, {'active': active });
});
};
}).call(this,_dereq_("C:\\Users\\Alex\\AppData\\Roaming\\npm\\node_modules\\browserify\\node_modules\\insert-module-globals\\node_modules\\process\\browser.js"),_dereq_("buffer").Buffer)
},{"./channel":27,"./debug":30,"./definitions":31,"./exchange":32,"./message":33,"C:\\Users\\Alex\\AppData\\Roaming\\npm\\node_modules\\browserify\\node_modules\\insert-module-globals\\node_modules\\process\\browser.js":144,"buffer":128,"fs":127,"lodash":38,"util":159}],37:[function(_dereq_,module,exports){
(function (Buffer){
'use strict';
var jspack = _dereq_('../jspack').jspack;
var serializer = module.exports = {
serializeFloat: function(b, size, value, bigEndian) {
var jp = new jspack(bigEndian);
switch(size) {
case 4:
var x = jp.Pack('f', [value]);
for (var i = 0; i < x.length; ++i)
b[b.used++] = x[i];
break;
case 8:
var x = jp.Pack('d', [value]);
for (var i = 0; i < x.length; ++i)
b[b.used++] = x[i];
break;
default:
throw new Error("Unknown floating point size");
}
},
serializeInt: function (b, size, int) {
if (b.used + size > b.length) {
throw new Error("write out of bounds");
}
// Only 4 cases - just going to be explicit instead of looping.
switch (size) {
// octet
case 1:
b[b.used++] = int;
break;
// short
case 2:
b[b.used++] = (int & 0xFF00) >> 8;
b[b.used++] = (int & 0x00FF) >> 0;
break;
// long
case 4:
b[b.used++] = (int & 0xFF000000) >> 24;
b[b.used++] = (int & 0x00FF0000) >> 16;
b[b.used++] = (int & 0x0000FF00) >> 8;
b[b.used++] = (int & 0x000000FF) >> 0;
break;
// long long
case 8:
b[b.used++] = (int & 0xFF00000000000000) >> 56;
b[b.used++] = (int & 0x00FF000000000000) >> 48;
b[b.used++] = (int & 0x0000FF0000000000) >> 40;
b[b.used++] = (int & 0x000000FF00000000) >> 32;
b[b.used++] = (int & 0x00000000FF000000) >> 24;
b[b.used++] = (int & 0x0000000000FF0000) >> 16;
b[b.used++] = (int & 0x000000000000FF00) >> 8;
b[b.used++] = (int & 0x00000000000000FF) >> 0;
break;
default:
throw new Error("Bad size");
}
},
serializeShortString: function (b, string) {
if (typeof(string) != "string") {
throw new Error("param must be a string");
}
var byteLength = Buffer.byteLength(string, 'utf8');
if (byteLength > 0xFF) {
throw new Error("String too long for 'shortstr' parameter");
}
if (1 + byteLength + b.used >= b.length) {
throw new Error("Not enough space in buffer for 'shortstr'");
}
b[b.used++] = byteLength;
b.write(string, b.used, 'utf8');
b.used += byteLength;
},
serializeLongString: function(b, string) {
// we accept string, object, or buffer for this parameter.
// in the case of string we serialize it to utf8.
if (typeof(string) == 'string') {
var byteLength = Buffer.byteLength(string, 'utf8');
serializer.serializeInt(b, 4, byteLength);
b.write(string, b.used, 'utf8');
b.used += byteLength;
} else if (typeof(string) == 'object') {
serializer.serializeTable(b, string);
} else {
// data is Buffer
var byteLength = string.length;
serializer.serializeInt(b, 4, byteLength);
b.write(string, b.used); // memcpy
b.used += byteLength;
}
},
serializeDate: function(b, date) {
serializer.serializeInt(b, 8, date.valueOf() / 1000);
},
serializeBuffer: function(b, buffer) {
serializer.serializeInt(b, 4, buffer.length);
buffer.copy(b, b.used, 0);
b.used += buffer.length;
},
serializeBase64: function(b, buffer) {
serializer.serializeLongString(b, buffer.toString('base64'));
},
isBigInt: function(value) {
return value > 0xffffffff;
},
getCode: function(dec) {
var hexArray = "0123456789ABCDEF".split('');
var code1 = Math.floor(dec / 16);
var code2 = dec - code1 * 16;
return hexArray[code2];
},
isFloat: function(value){
return value === +value && value !== (value|0);
},
serializeValue: function(b, value) {
switch (typeof(value)) {
case 'string':
b[b.used++] = 'S'.charCodeAt(0);
serializer.serializeLongString(b, value);
break;
case 'number':
if (!serializer.isFloat(value)) {
if (serializer.isBigInt(value)) {
// 64-bit uint
b[b.used++] = 'l'.charCodeAt(0);
serializer.serializeInt(b, 8, value);
} else {
//32-bit uint
b[b.used++] = 'I'.charCodeAt(0);
serializer.serializeInt(b, 4, value);
}
} else {
//64-bit float
b[b.used++] = 'd'.charCodeAt(0);
serializer.serializeFloat(b, 8, value);
}
break;
case 'boolean':
b[b.used++] = 't'.charCodeAt(0);
b[b.used++] = value;
break;
default:
if (value instanceof Date) {
b[b.used++] = 'T'.charCodeAt(0);
serializer.serializeDate(b, value);
} else if (value instanceof Buffer) {
b[b.used++] = 'x'.charCodeAt(0);
serializer.serializeBuffer(b, value);
} else if (Array.isArray(value)) {
b[b.used++] = 'A'.charCodeAt(0);
serializer.serializeArray(b, value);
} else if (typeof(value) === 'object') {
b[b.used++] = 'F'.charCodeAt(0);
serializer.serializeTable(b, value);
} else {
throw new Error("unsupported type in amqp table: " + typeof(value));
}
}
},
serializeTable: function(b, object) {
if (typeof(object) != "object") {
throw new Error("param must be an object");
}
// Save our position so that we can go back and write the length of this table
// at the beginning of the packet (once we know how many entries there are).
var lengthIndex = b.used;
b.used += 4; // sizeof long
var startIndex = b.used;
for (var key in object) {
if (!object.hasOwnProperty(key)) continue;
serializer.serializeShortString(b, key);
serializer.serializeValue(b, object[key]);
}
var endIndex = b.used;
b.used = lengthIndex;
serializer.serializeInt(b, 4, endIndex - startIndex);
b.used = endIndex;
},
serializeArray: function(b, arr) {
// Save our position so that we can go back and write the byte length of this array
// at the beginning of the packet (once we have serialized all elements).
var lengthIndex = b.used;
b.used += 4; // sizeof long
var startIndex = b.used;
var len = arr.length;
for (var i = 0; i < len; i++) {
serializer.serializeValue(b, arr[i]);
}
var endIndex = b.used;
b.used = lengthIndex;
serializer.serializeInt(b, 4, endIndex - startIndex);
b.used = endIndex;
},
serializeFields: function(buffer, fields, args, strict) {
var bitField = 0;
var bitIndex = 0;
for (var i = 0; i < fields.length; i++) {
var field = fields[i];
var domain = field.domain;
if (!(field.name in args)) {
if (strict) {
throw new Error("Missing field '" + field.name + "' of type '" + domain + "' while executing AMQP method '" +
arguments.callee.caller.arguments[1].name + "'");
}
continue;
}
var param = args[field.name];
//debug("domain: " + domain + " param: " + param);
switch (domain) {
case 'bit':
if (typeof(param) != "boolean") {
throw new Error("Unmatched field " + JSON.stringify(field));
}
if (param) bitField |= (1 << bitIndex);
bitIndex++;
if (!fields[i+1] || fields[i+1].domain != 'bit') {
//debug('SET bit field ' + field.name + ' 0x' + bitField.toString(16));
buffer[buffer.used++] = bitField;
bitField = 0;
bitIndex = 0;
}
break;
case 'octet':
if (typeof(param) != "number" || param > 0xFF) {
throw new Error("Unmatched field " + JSON.stringify(field));
}
buffer[buffer.used++] = param;
break;
case 'short':
if (typeof(param) != "number" || param > 0xFFFF) {
throw new Error("Unmatched field " + JSON.stringify(field));
}
serializer.serializeInt(buffer, 2, param);
break;
case 'long':
if (typeof(param) != "number" || param > 0xFFFFFFFF) {
throw new Error("Unmatched field " + JSON.stringify(field));
}
serializer.serializeInt(buffer, 4, param);
break;
// In a previous version this shared code with 'longlong', which caused problems when passed Date
// integers. Nobody expects to pass a Buffer here, 53 bits is still 28 million years after 1970, we'll be fine.
case 'timestamp':
serializer.serializeInt(buffer, 8, param);
break;
case 'longlong':
for (var j = 0; j < 8; j++) {
buffer[buffer.used++] = param[j];
}
break;
case 'shortstr':
if (typeof(param) != "string" || param.length > 0xFF) {
throw new Error("Unmatched field " + JSON.stringify(field));
}
serializer.serializeShortString(buffer, param);
break;
case 'longstr':
serializer.serializeLongString(buffer, param);
break;
case 'table':
if (typeof(param) != "object") {
throw new Error("Unmatched field " + JSON.stringify(field));
}
serializer.serializeTable(buffer, param);
break;
default:
throw new Error("Unknown domain value type " + domain);
}
}
}
};
}).call(this,_dereq_("buffer").Buffer)
},{"../jspack":25,"buffer":128}],38:[function(_dereq_,module,exports){
(function (global){
/**
* @license
* Lo-Dash 1.3.1 (Custom Build) <http://lodash.com/>
* Build: `lodash modern -o ./dist/lodash.js`
* Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.4.4 <http://underscorejs.org/>
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
* Available under MIT license <http://lodash.com/license>
*/
;(function(window) {
/** Used as a safe reference for `undefined` in pre ES5 environments */
var undefined;
/** Used to pool arrays and objects used internally */
var arrayPool = [],
objectPool = [];
/** Used to generate unique IDs */
var idCounter = 0;
/** Used internally to indicate various things */
var indicatorObject = {};
/** Used to prefix keys to avoid issues with `__proto__` and properties on `Object.prototype` */
var keyPrefix = +new Date + '';
/** Used as the size when optimizations are enabled for large arrays */
var largeArraySize = 75;
/** Used as the max size of the `arrayPool` and `objectPool` */
var maxPoolSize = 40;
/** Used to match empty string literals in compiled template source */
var reEmptyStringLeading = /\b__p \+= '';/g,
reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
/** Used to match HTML entities */
var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g;
/**
* Used to match ES6 template delimiters
* http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.8.6
*/
var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
/** Used to match regexp flags from their coerced string values */
var reFlags = /\w*$/;
/** Used to match "interpolate" template delimiters */
var reInterpolate = /<%=([\s\S]+?)%>/g;
/** Used to detect functions containing a `this` reference */
var reThis = (reThis = /\bthis\b/) && reThis.test(runInContext) && reThis;
/** Used to detect and test whitespace */
var whitespace = (
// whitespace
' \t\x0B\f\xA0\ufeff' +
// line terminators
'\n\r\u2028\u2029' +
// unicode category "Zs" space separators
'\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000'
);
/** Used to match leading whitespace and zeros to be removed */
var reLeadingSpacesAndZeros = RegExp('^[' + whitespace + ']*0+(?=.$)');
/** Used to ensure capturing order of template delimiters */
var reNoMatch = /($^)/;
/** Used to match HTML characters */
var reUnescapedHtml = /[&<>"']/g;
/** Used to match unescaped characters in compiled string literals */
var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g;
/** Used to assign default `context` object properties */
var contextProps = [
'Array', 'Boolean', 'Date', 'Function', 'Math', 'Number', 'Object',
'RegExp', 'String', '_', 'attachEvent', 'clearTimeout', 'isFinite', 'isNaN',
'parseInt', 'setImmediate', 'setTimeout'
];
/** Used to make template sourceURLs easier to identify */
var templateCounter = 0;
/** `Object#toString` result shortcuts */
var argsClass = '[object Arguments]',
arrayClass = '[object Array]',
boolClass = '[object Boolean]',
dateClass = '[object Date]',
errorClass = '[object Error]',
funcClass = '[object Function]',
numberClass = '[object Number]',
objectClass = '[object Object]',
regexpClass = '[object RegExp]',
stringClass = '[object String]';
/** Used to identify object classifications that `_.clone` supports */
var cloneableClasses = {};
cloneableClasses[funcClass] = false;
cloneableClasses[argsClass] = cloneableClasses[arrayClass] =
cloneableClasses[boolClass] = cloneableClasses[dateClass] =
cloneableClasses[numberClass] = cloneableClasses[objectClass] =
cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true;
/** Used to determine if values are of the language type Object */
var objectTypes = {
'boolean': false,
'function': true,
'object': true,
'number': false,
'string': false,
'undefined': false
};
/** Used to escape characters for inclusion in compiled string literals */
var stringEscapes = {
'\\': '\\',
"'": "'",
'\n': 'n',
'\r': 'r',
'\t': 't',
'\u2028': 'u2028',
'\u2029': 'u2029'
};
/** Detect free variable `exports` */
var freeExports = objectTypes[typeof exports] && exports;
/** Detect free variable `module` */
var freeModule = objectTypes[typeof module] && module && module.exports == freeExports && module;
/** Detect free variable `global`, from Node.js or Browserified code, and use it as `window` */
var freeGlobal = objectTypes[typeof global] && global;
if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal)) {
window = freeGlobal;
}
/*--------------------------------------------------------------------------*/
/**
* A basic implementation of `_.indexOf` without support for binary searches
* or `fromIndex` constraints.
*
* @private
* @param {Array} array The array to search.
* @param {Mixed} value The value to search for.
* @param {Number} [fromIndex=0] The index to search from.
* @returns {Number} Returns the index of the matched value or `-1`.
*/
function basicIndexOf(array, value, fromIndex) {
var index = (fromIndex || 0) - 1,
length = array.length;
while (++index < length) {
if (array[index] === value) {
return index;
}
}
return -1;
}
/**
* An implementation of `_.contains` for cache objects that mimics the return
* signature of `_.indexOf` by returning `0` if the value is found, else `-1`.
*
* @private
* @param {Object} cache The cache object to inspect.
* @param {Mixed} value The value to search for.
* @returns {Number} Returns `0` if `value` is found, else `-1`.
*/
function cacheIndexOf(cache, value) {
var type = typeof value;
cache = cache.cache;
if (type == 'boolean' || value == null) {
return cache[value];
}
if (type != 'number' && type != 'string') {
type = 'object';
}
var key = type == 'number' ? value : keyPrefix + value;
cache = cache[type] || (cache[type] = {});
return type == 'object'
? (cache[key] && basicIndexOf(cache[key], value) > -1 ? 0 : -1)
: (cache[key] ? 0 : -1);
}
/**
* Adds a given `value` to the corresponding cache object.
*
* @private
* @param {Mixed} value The value to add to the cache.
*/
function cachePush(value) {
var cache = this.cache,
type = typeof value;
if (type == 'boolean' || value == null) {
cache[value] = true;
} else {
if (type != 'number' && type != 'string') {
type = 'object';
}
var key = type == 'number' ? value : keyPrefix + value,
typeCache = cache[type] || (cache[type] = {});
if (type == 'object') {
if ((typeCache[key] || (typeCache[key] = [])).push(value) == this.array.length) {
cache[type] = false;
}
} else {
typeCache[key] = true;
}
}
}
/**
* Used by `_.max` and `_.min` as the default `callback` when a given
* `collection` is a string value.
*
* @private
* @param {String} value The character to inspect.
* @returns {Number} Returns the code unit of given character.
*/
function charAtCallback(value) {
return value.charCodeAt(0);
}
/**
* Used by `sortBy` to compare transformed `collection` values, stable sorting
* them in ascending order.
*
* @private
* @param {Object} a The object to compare to `b`.
* @param {Object} b The object to compare to `a`.
* @returns {Number} Returns the sort order indicator of `1` or `-1`.
*/
function compareAscending(a, b) {
var ai = a.index,
bi = b.index;
a = a.criteria;
b = b.criteria;
// ensure a stable sort in V8 and other engines
// http://code.google.com/p/v8/issues/detail?id=90
if (a !== b) {
if (a > b || typeof a == 'undefined') {
return 1;
}
if (a < b || typeof b == 'undefined') {
return -1;
}
}
return ai < bi ? -1 : 1;
}
/**
* Creates a cache object to optimize linear searches of large arrays.
*
* @private
* @param {Array} [array=[]] The array to search.
* @returns {Null|Object} Returns the cache object or `null` if caching should not be used.
*/
function createCache(array) {
var index = -1,
length = array.length;
var cache = getObject();
cache['false'] = cache['null'] = cache['true'] = cache['undefined'] = false;
var result = getObject();
result.array = array;
result.cache = cache;
result.push = cachePush;
while (++index < length) {
result.push(array[index]);
}
return cache.object === false
? (releaseObject(result), null)
: result;
}
/**
* Used by `template` to escape characters for inclusion in compiled
* string literals.
*
* @private
* @param {String} match The matched character to escape.
* @returns {String} Returns the escaped character.
*/
function escapeStringChar(match) {
return '\\' + stringEscapes[match];
}
/**
* Gets an array from the array pool or creates a new one if the pool is empty.
*
* @private
* @returns {Array} The array from the pool.
*/
function getArray() {
return arrayPool.pop() || [];
}
/**
* Gets an object from the object pool or creates a new one if the pool is empty.
*
* @private
* @returns {Object} The object from the pool.
*/
function getObject() {
return objectPool.pop() || {
'array': null,
'cache': null,
'criteria': null,
'false': false,
'index': 0,
'leading': false,
'maxWait': 0,
'null': false,
'number': null,
'object': null,
'push': null,
'string': null,
'trailing': false,
'true': false,
'undefined': false,
'value': null
};
}
/**
* A no-operation function.
*
* @private
*/
function noop() {
// no operation performed
}
/**
* Releases the given `array` back to the array pool.
*
* @private
* @param {Array} [array] The array to release.
*/
function releaseArray(array) {
array.length = 0;
if (arrayPool.length < maxPoolSize) {
arrayPool.push(array);
}
}
/**
* Releases the given `object` back to the object pool.
*
* @private
* @param {Object} [object] The object to release.
*/
function releaseObject(object) {
var cache = object.cache;
if (cache) {
releaseObject(cache);
}
object.array = object.cache = object.criteria = object.object = object.number = object.string = object.value = null;
if (objectPool.length < maxPoolSize) {
objectPool.push(object);
}
}
/**
* Slices the `collection` from the `start` index up to, but not including,
* the `end` index.
*
* Note: This function is used, instead of `Array#slice`, to support node lists
* in IE < 9 and to ensure dense arrays are returned.
*
* @private
* @param {Array|Object|String} collection The collection to slice.
* @param {Number} start The start index.
* @param {Number} end The end index.
* @returns {Array} Returns the new array.
*/
function slice(array, start, end) {
start || (start = 0);
if (typeof end == 'undefined') {
end = array ? array.length : 0;
}
var index = -1,
length = end - start || 0,
result = Array(length < 0 ? 0 : length);
while (++index < length) {
result[index] = array[start + index];
}
return result;
}
/*--------------------------------------------------------------------------*/
/**
* Create a new `lodash` function using the given `context` object.
*
* @static
* @memberOf _
* @category Utilities
* @param {Object} [context=window] The context object.
* @returns {Function} Returns the `lodash` function.
*/
function runInContext(context) {
// Avoid issues with some ES3 environments that attempt to use values, named
// after built-in constructors like `Object`, for the creation of literals.
// ES5 clears this up by stating that literals must use built-in constructors.
// See http://es5.github.com/#x11.1.5.
context = context ? _.defaults(window.Object(), context, _.pick(window, contextProps)) : window;
/** Native constructor references */
var Array = context.Array,
Boolean = context.Boolean,
Date = context.Date,
Function = context.Function,
Math = context.Math,
Number = context.Number,
Object = context.Object,
RegExp = context.RegExp,
String = context.String,
TypeError = context.TypeError;
/**
* Used for `Array` method references.
*
* Normally `Array.prototype` would suffice, however, using an array literal
* avoids issues in Narwhal.
*/
var arrayRef = [];
/** Used for native method references */
var objectProto = Object.prototype,
stringProto = String.prototype;
/** Used to restore the original `_` reference in `noConflict` */
var oldDash = context._;
/** Used to detect if a method is native */
var reNative = RegExp('^' +
String(objectProto.valueOf)
.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
.replace(/valueOf|for [^\]]+/g, '.+?') + '$'
);
/** Native method shortcuts */
var ceil = Math.ceil,
clearTimeout = context.clearTimeout,
concat = arrayRef.concat,
floor = Math.floor,
fnToString = Function.prototype.toString,
getPrototypeOf = reNative.test(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf,
hasOwnProperty = objectProto.hasOwnProperty,
push = arrayRef.push,
propertyIsEnumerable = objectProto.propertyIsEnumerable,
setImmediate = context.setImmediate,
setTimeout = context.setTimeout,
toString = objectProto.toString;
/* Native method shortcuts for methods with the same name as other `lodash` methods */
var nativeBind = reNative.test(nativeBind = toString.bind) && nativeBind,
nativeCreate = reNative.test(nativeCreate = Object.create) && nativeCreate,
nativeIsArray = reNative.test(nativeIsArray = Array.isArray) && nativeIsArray,
nativeIsFinite = context.isFinite,
nativeIsNaN = context.isNaN,
nativeKeys = reNative.test(nativeKeys = Object.keys) && nativeKeys,
nativeMax = Math.max,
nativeMin = Math.min,
nativeParseInt = context.parseInt,
nativeRandom = Math.random,
nativeSlice = arrayRef.slice;
/** Detect various environments */
var isIeOpera = reNative.test(context.attachEvent),
isV8 = nativeBind && !/\n|true/.test(nativeBind + isIeOpera);
/** Used to lookup a built-in constructor by [[Class]] */
var ctorByClass = {};
ctorByClass[arrayClass] = Array;
ctorByClass[boolClass] = Boolean;
ctorByClass[dateClass] = Date;
ctorByClass[funcClass] = Function;
ctorByClass[objectClass] = Object;
ctorByClass[numberClass] = Number;
ctorByClass[regexpClass] = RegExp;
ctorByClass[stringClass] = String;
/*--------------------------------------------------------------------------*/
/**
* Creates a `lodash` object, which wraps the given `value`, to enable method
* chaining.
*
* In addition to Lo-Dash methods, wrappers also have the following `Array` methods:
* `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`,
* and `unshift`
*
* Chaining is supported in custom builds as long as the `value` method is
* implicitly or explicitly included in the build.
*
* The chainable wrapper functions are:
* `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`,
* `compose`, `concat`, `countBy`, `createCallback`, `debounce`, `defaults`,
* `defer`, `delay`, `difference`, `filter`, `flatten`, `forEach`, `forIn`,
* `forOwn`, `functions`, `groupBy`, `initial`, `intersection`, `invert`,
* `invoke`, `keys`, `map`, `max`, `memoize`, `merge`, `min`, `object`, `omit`,
* `once`, `pairs`, `partial`, `partialRight`, `pick`, `pluck`, `push`, `range`,
* `reject`, `rest`, `reverse`, `shuffle`, `slice`, `sort`, `sortBy`, `splice`,
* `tap`, `throttle`, `times`, `toArray`, `transform`, `union`, `uniq`, `unshift`,
* `unzip`, `values`, `where`, `without`, `wrap`, and `zip`
*
* The non-chainable wrapper functions are:
* `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `has`,
* `identity`, `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`,
* `isElement`, `isEmpty`, `isEqual`, `isFinite`, `isFunction`, `isNaN`,
* `isNull`, `isNumber`, `isObject`, `isPlainObject`, `isRegExp`, `isString`,
* `isUndefined`, `join`, `lastIndexOf`, `mixin`, `noConflict`, `parseInt`,
* `pop`, `random`, `reduce`, `reduceRight`, `result`, `shift`, `size`, `some`,
* `sortedIndex`, `runInContext`, `template`, `unescape`, `uniqueId`, and `value`
*
* The wrapper functions `first` and `last` return wrapped values when `n` is
* passed, otherwise they return unwrapped values.
*
* @name _
* @constructor
* @alias chain
* @category Chaining
* @param {Mixed} value The value to wrap in a `lodash` instance.
* @returns {Object} Returns a `lodash` instance.
* @example
*
* var wrapped = _([1, 2, 3]);
*
* // returns an unwrapped value
* wrapped.reduce(function(sum, num) {
* return sum + num;
* });
* // => 6
*
* // returns a wrapped value
* var squares = wrapped.map(function(num) {
* return num * num;
* });
*
* _.isArray(squares);
* // => false
*
* _.isArray(squares.value());
* // => true
*/
function lodash(value) {
// don't wrap if already wrapped, even if wrapped by a different `lodash` constructor
return (value && typeof value == 'object' && !isArray(value) && hasOwnProperty.call(value, '__wrapped__'))
? value
: new lodashWrapper(value);
}
/**
* A fast path for creating `lodash` wrapper objects.
*
* @private
* @param {Mixed} value The value to wrap in a `lodash` instance.
* @returns {Object} Returns a `lodash` instance.
*/
function lodashWrapper(value) {
this.__wrapped__ = value;
}
// ensure `new lodashWrapper` is an instance of `lodash`
lodashWrapper.prototype = lodash.prototype;
/**
* An object used to flag environments features.
*
* @static
* @memberOf _
* @type Object
*/
var support = lodash.support = {};
/**
* Detect if `Function#bind` exists and is inferred to be fast (all but V8).
*
* @memberOf _.support
* @type Boolean
*/
support.fastBind = nativeBind && !isV8;
/**
* By default, the template delimiters used by Lo-Dash are similar to those in
* embedded Ruby (ERB). Change the following template settings to use alternative
* delimiters.
*
* @static
* @memberOf _
* @type Object
*/
lodash.templateSettings = {
/**
* Used to detect `data` property values to be HTML-escaped.
*
* @memberOf _.templateSettings
* @type RegExp
*/
'escape': /<%-([\s\S]+?)%>/g,
/**
* Used to detect code to be evaluated.
*
* @memberOf _.templateSettings
* @type RegExp
*/
'evaluate': /<%([\s\S]+?)%>/g,
/**
* Used to detect `data` property values to inject.
*
* @memberOf _.templateSettings
* @type RegExp
*/
'interpolate': reInterpolate,
/**
* Used to reference the data object in the template text.
*
* @memberOf _.templateSettings
* @type String
*/
'variable': '',
/**
* Used to import variables into the compiled template.
*
* @memberOf _.templateSettings
* @type Object
*/
'imports': {
/**
* A reference to the `lodash` function.
*
* @memberOf _.templateSettings.imports
* @type Function
*/
'_': lodash
}
};
/*--------------------------------------------------------------------------*/
/**
* Creates a function that, when called, invokes `func` with the `this` binding
* of `thisArg` and prepends any `partialArgs` to the arguments passed to the
* bound function.
*
* @private
* @param {Function|String} func The function to bind or the method name.
* @param {Mixed} [thisArg] The `this` binding of `func`.
* @param {Array} partialArgs An array of arguments to be partially applied.
* @param {Object} [idicator] Used to indicate binding by key or partially
* applying arguments from the right.
* @returns {Function} Returns the new bound function.
*/
function createBound(func, thisArg, partialArgs, indicator) {
var isFunc = isFunction(func),
isPartial = !partialArgs,
key = thisArg;
// juggle arguments
if (isPartial) {
var rightIndicator = indicator;
partialArgs = thisArg;
}
else if (!isFunc) {
if (!indicator) {
throw new TypeError;
}
thisArg = func;
}
function bound() {
// `Function#bind` spec
// http://es5.github.com/#x15.3.4.5
var args = arguments,
thisBinding = isPartial ? this : thisArg;
if (!isFunc) {
func = thisArg[key];
}
if (partialArgs.length) {
args = args.length
? (args = nativeSlice.call(args), rightIndicator ? args.concat(partialArgs) : partialArgs.concat(args))
: partialArgs;
}
if (this instanceof bound) {
// ensure `new bound` is an instance of `func`
thisBinding = createObject(func.prototype);
// mimic the constructor's `return` behavior
// http://es5.github.com/#x13.2.2
var result = func.apply(thisBinding, args);
return isObject(result) ? result : thisBinding;
}
return func.apply(thisBinding, args);
}
return bound;
}
/**
* Creates a new object with the specified `prototype`.
*
* @private
* @param {Object} prototype The prototype object.
* @returns {Object} Returns the new object.
*/
function createObject(prototype) {
return isObject(prototype) ? nativeCreate(prototype) : {};
}
/**
* Used by `escape` to convert characters to HTML entities.
*
* @private
* @param {String} match The matched character to escape.
* @returns {String} Returns the escaped character.
*/
function escapeHtmlChar(match) {
return htmlEscapes[match];
}
/**
* Gets the appropriate "indexOf" function. If the `_.indexOf` method is
* customized, this method returns the custom method, otherwise it returns
* the `basicIndexOf` function.
*
* @private
* @returns {Function} Returns the "indexOf" function.
*/
function getIndexOf(array, value, fromIndex) {
var result = (result = lodash.indexOf) === indexOf ? basicIndexOf : result;
return result;
}
/**
* Creates a function that juggles arguments, allowing argument overloading
* for `_.flatten` and `_.uniq`, before passing them to the given `func`.
*
* @private
* @param {Function} func The function to wrap.
* @returns {Function} Returns the new function.
*/
function overloadWrapper(func) {
return function(array, flag, callback, thisArg) {
// juggle arguments
if (typeof flag != 'boolean' && flag != null) {
thisArg = callback;
callback = !(thisArg && thisArg[flag] === array) ? flag : undefined;
flag = false;
}
if (callback != null) {
callback = lodash.createCallback(callback, thisArg);
}
return func(array, flag, callback, thisArg);
};
}
/**
* A fallback implementation of `isPlainObject` which checks if a given `value`
* is an object created by the `Object` constructor, assuming objects created
* by the `Object` constructor have no inherited enumerable properties and that
* there are no `Object.prototype` extensions.
*
* @private
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true`, if `value` is a plain object, else `false`.
*/
function shimIsPlainObject(value) {
var ctor,
result;
// avoid non Object objects, `arguments` objects, and DOM elements
if (!(value && toString.call(value) == objectClass) ||
(ctor = value.constructor, isFunction(ctor) && !(ctor instanceof ctor))) {
return false;
}
// In most environments an object's own properties are iterated before
// its inherited properties. If the last iterated property is an object's
// own property then there are no inherited enumerable properties.
forIn(value, function(value, key) {
result = key;
});
return result === undefined || hasOwnProperty.call(value, result);
}
/**
* Used by `unescape` to convert HTML entities to characters.
*
* @private
* @param {String} match The matched character to unescape.
* @returns {String} Returns the unescaped character.
*/
function unescapeHtmlChar(match) {
return htmlUnescapes[match];
}
/*--------------------------------------------------------------------------*/
/**
* Checks if `value` is an `arguments` object.
*
* @static
* @memberOf _
* @category Objects
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true`, if the `value` is an `arguments` object, else `false`.
* @example
*
* (function() { return _.isArguments(arguments); })(1, 2, 3);
* // => true
*
* _.isArguments([1, 2, 3]);
* // => false
*/
function isArguments(value) {
return toString.call(value) == argsClass;
}
/**
* Checks if `value` is an array.
*
* @static
* @memberOf _
* @category Objects
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true`, if the `value` is an array, else `false`.
* @example
*
* (function() { return _.isArray(arguments); })();
* // => false
*
* _.isArray([1, 2, 3]);
* // => true
*/
var isArray = nativeIsArray;
/**
* A fallback implementation of `Object.keys` which produces an array of the
* given object's own enumerable property names.
*
* @private
* @type Function
* @param {Object} object The object to inspect.
* @returns {Array} Returns a new array of property names.
*/
var shimKeys = function (object) {
var index, iterable = object, result = [];
if (!iterable) return result;
if (!(objectTypes[typeof object])) return result;
for (index in iterable) {
if (hasOwnProperty.call(iterable, index)) {
result.push(index);
}
}
return result
};
/**
* Creates an array composed of the own enumerable property names of `object`.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to inspect.
* @returns {Array} Returns a new array of property names.
* @example
*
* _.keys({ 'one': 1, 'two': 2, 'three': 3 });
* // => ['one', 'two', 'three'] (order is not guaranteed)
*/
var keys = !nativeKeys ? shimKeys : function(object) {
if (!isObject(object)) {
return [];
}
return nativeKeys(object);
};
/**
* Used to convert characters to HTML entities:
*
* Though the `>` character is escaped for symmetry, characters like `>` and `/`
* don't require escaping in HTML and have no special meaning unless they're part
* of a tag or an unquoted attribute value.
* http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact")
*/
var htmlEscapes = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#39;'
};
/** Used to convert HTML entities to characters */
var htmlUnescapes = invert(htmlEscapes);
/*--------------------------------------------------------------------------*/
/**
* Assigns own enumerable properties of source object(s) to the destination
* object. Subsequent sources will overwrite property assignments of previous
* sources. If a `callback` function is passed, it will be executed to produce
* the assigned values. The `callback` is bound to `thisArg` and invoked with
* two arguments; (objectValue, sourceValue).
*
* @static
* @memberOf _
* @type Function
* @alias extend
* @category Objects
* @param {Object} object The destination object.
* @param {Object} [source1, source2, ...] The source objects.
* @param {Function} [callback] The function to customize assigning values.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns the destination object.
* @example
*
* _.assign({ 'name': 'moe' }, { 'age': 40 });
* // => { 'name': 'moe', 'age': 40 }
*
* var defaults = _.partialRight(_.assign, function(a, b) {
* return typeof a == 'undefined' ? b : a;
* });
*
* var food = { 'name': 'apple' };
* defaults(food, { 'name': 'banana', 'type': 'fruit' });
* // => { 'name': 'apple', 'type': 'fruit' }
*/
var assign = function (object, source, guard) {
var index, iterable = object, result = iterable;
if (!iterable) return result;
var args = arguments,
argsIndex = 0,
argsLength = typeof guard == 'number' ? 2 : args.length;
if (argsLength > 3 && typeof args[argsLength - 2] == 'function') {
var callback = lodash.createCallback(args[--argsLength - 1], args[argsLength--], 2);
} else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {
callback = args[--argsLength];
}
while (++argsIndex < argsLength) {
iterable = args[argsIndex];
if (iterable && objectTypes[typeof iterable]) {
var ownIndex = -1,
ownProps = objectTypes[typeof iterable] && keys(iterable),
length = ownProps ? ownProps.length : 0;
while (++ownIndex < length) {
index = ownProps[ownIndex];
result[index] = callback ? callback(result[index], iterable[index]) : iterable[index];
}
}
}
return result
};
/**
* Creates a clone of `value`. If `deep` is `true`, nested objects will also
* be cloned, otherwise they will be assigned by reference. If a `callback`
* function is passed, it will be executed to produce the cloned values. If
* `callback` returns `undefined`, cloning will be handled by the method instead.
* The `callback` is bound to `thisArg` and invoked with one argument; (value).
*
* @static
* @memberOf _
* @category Objects
* @param {Mixed} value The value to clone.
* @param {Boolean} [deep=false] A flag to indicate a deep clone.
* @param {Function} [callback] The function to customize cloning values.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @param- {Array} [stackA=[]] Tracks traversed source objects.
* @param- {Array} [stackB=[]] Associates clones with source counterparts.
* @returns {Mixed} Returns the cloned `value`.
* @example
*
* var stooges = [
* { 'name': 'moe', 'age': 40 },
* { 'name': 'larry', 'age': 50 }
* ];
*
* var shallow = _.clone(stooges);
* shallow[0] === stooges[0];
* // => true
*
* var deep = _.clone(stooges, true);
* deep[0] === stooges[0];
* // => false
*
* _.mixin({
* 'clone': _.partialRight(_.clone, function(value) {
* return _.isElement(value) ? value.cloneNode(false) : undefined;
* })
* });
*
* var clone = _.clone(document.body);
* clone.childNodes.length;
* // => 0
*/
function clone(value, deep, callback, thisArg, stackA, stackB) {
var result = value;
// allows working with "Collections" methods without using their `callback`
// argument, `index|key`, for this method's `callback`
if (typeof deep != 'boolean' && deep != null) {
thisArg = callback;
callback = deep;
deep = false;
}
if (typeof callback == 'function') {
callback = (typeof thisArg == 'undefined')
? callback
: lodash.createCallback(callback, thisArg, 1);
result = callback(result);
if (typeof result != 'undefined') {
return result;
}
result = value;
}
// inspect [[Class]]
var isObj = isObject(result);
if (isObj) {
var className = toString.call(result);
if (!cloneableClasses[className]) {
return result;
}
var isArr = isArray(result);
}
// shallow clone
if (!isObj || !deep) {
return isObj
? (isArr ? slice(result) : assign({}, result))
: result;
}
var ctor = ctorByClass[className];
switch (className) {
case boolClass:
case dateClass:
return new ctor(+result);
case numberClass:
case stringClass:
return new ctor(result);
case regexpClass:
return ctor(result.source, reFlags.exec(result));
}
// check for circular references and return corresponding clone
var initedStack = !stackA;
stackA || (stackA = getArray());
stackB || (stackB = getArray());
var length = stackA.length;
while (length--) {
if (stackA[length] == value) {
return stackB[length];
}
}
// init cloned object
result = isArr ? ctor(result.length) : {};
// add array properties assigned by `RegExp#exec`
if (isArr) {
if (hasOwnProperty.call(value, 'index')) {
result.index = value.index;
}
if (hasOwnProperty.call(value, 'input')) {
result.input = value.input;
}
}
// add the source value to the stack of traversed objects
// and associate it with its clone
stackA.push(value);
stackB.push(result);
// recursively populate clone (susceptible to call stack limits)
(isArr ? forEach : forOwn)(value, function(objValue, key) {
result[key] = clone(objValue, deep, callback, undefined, stackA, stackB);
});
if (initedStack) {
releaseArray(stackA);
releaseArray(stackB);
}
return result;
}
/**
* Creates a deep clone of `value`. If a `callback` function is passed,
* it will be executed to produce the cloned values. If `callback` returns
* `undefined`, cloning will be handled by the method instead. The `callback`
* is bound to `thisArg` and invoked with one argument; (value).
*
* Note: This method is loosely based on the structured clone algorithm. Functions
* and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and
* objects created by constructors other than `Object` are cloned to plain `Object` objects.
* See http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm.
*
* @static
* @memberOf _
* @category Objects
* @param {Mixed} value The value to deep clone.
* @param {Function} [callback] The function to customize cloning values.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Mixed} Returns the deep cloned `value`.
* @example
*
* var stooges = [
* { 'name': 'moe', 'age': 40 },
* { 'name': 'larry', 'age': 50 }
* ];
*
* var deep = _.cloneDeep(stooges);
* deep[0] === stooges[0];
* // => false
*
* var view = {
* 'label': 'docs',
* 'node': element
* };
*
* var clone = _.cloneDeep(view, function(value) {
* return _.isElement(value) ? value.cloneNode(true) : undefined;
* });
*
* clone.node == view.node;
* // => false
*/
function cloneDeep(value, callback, thisArg) {
return clone(value, true, callback, thisArg);
}
/**
* Assigns own enumerable properties of source object(s) to the destination
* object for all destination properties that resolve to `undefined`. Once a
* property is set, additional defaults of the same property will be ignored.
*
* @static
* @memberOf _
* @type Function
* @category Objects
* @param {Object} object The destination object.
* @param {Object} [source1, source2, ...] The source objects.
* @param- {Object} [guard] Allows working with `_.reduce` without using its
* callback's `key` and `object` arguments as sources.
* @returns {Object} Returns the destination object.
* @example
*
* var food = { 'name': 'apple' };
* _.defaults(food, { 'name': 'banana', 'type': 'fruit' });
* // => { 'name': 'apple', 'type': 'fruit' }
*/
var defaults = function (object, source, guard) {
var index, iterable = object, result = iterable;
if (!iterable) return result;
var args = arguments,
argsIndex = 0,
argsLength = typeof guard == 'number' ? 2 : args.length;
while (++argsIndex < argsLength) {
iterable = args[argsIndex];
if (iterable && objectTypes[typeof iterable]) {
var ownIndex = -1,
ownProps = objectTypes[typeof iterable] && keys(iterable),
length = ownProps ? ownProps.length : 0;
while (++ownIndex < length) {
index = ownProps[ownIndex];
if (typeof result[index] == 'undefined') result[index] = iterable[index];
}
}
}
return result
};
/**
* This method is similar to `_.find`, except that it returns the key of the
* element that passes the callback check, instead of the element itself.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to search.
* @param {Function|Object|String} [callback=identity] The function called per
* iteration. If a property name or object is passed, it will be used to create
* a "_.pluck" or "_.where" style callback, respectively.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Mixed} Returns the key of the found element, else `undefined`.
* @example
*
* _.findKey({ 'a': 1, 'b': 2, 'c': 3, 'd': 4 }, function(num) {
* return num % 2 == 0;
* });
* // => 'b'
*/
function findKey(object, callback, thisArg) {
var result;
callback = lodash.createCallback(callback, thisArg);
forOwn(object, function(value, key, object) {
if (callback(value, key, object)) {
result = key;
return false;
}
});
return result;
}
/**
* Iterates over `object`'s own and inherited enumerable properties, executing
* the `callback` for each property. The `callback` is bound to `thisArg` and
* invoked with three arguments; (value, key, object). Callbacks may exit iteration
* early by explicitly returning `false`.
*
* @static
* @memberOf _
* @type Function
* @category Objects
* @param {Object} object The object to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns `object`.
* @example
*
* function Dog(name) {
* this.name = name;
* }
*
* Dog.prototype.bark = function() {
* alert('Woof, woof!');
* };
*
* _.forIn(new Dog('Dagny'), function(value, key) {
* alert(key);
* });
* // => alerts 'name' and 'bark' (order is not guaranteed)
*/
var forIn = function (collection, callback, thisArg) {
var index, iterable = collection, result = iterable;
if (!iterable) return result;
if (!objectTypes[typeof iterable]) return result;
callback = callback && typeof thisArg == 'undefined' ? callback : lodash.createCallback(callback, thisArg);
for (index in iterable) {
if (callback(iterable[index], index, collection) === false) return result;
}
return result
};
/**
* Iterates over an object's own enumerable properties, executing the `callback`
* for each property. The `callback` is bound to `thisArg` and invoked with three
* arguments; (value, key, object). Callbacks may exit iteration early by explicitly
* returning `false`.
*
* @static
* @memberOf _
* @type Function
* @category Objects
* @param {Object} object The object to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns `object`.
* @example
*
* _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
* alert(key);
* });
* // => alerts '0', '1', and 'length' (order is not guaranteed)
*/
var forOwn = function (collection, callback, thisArg) {
var index, iterable = collection, result = iterable;
if (!iterable) return result;
if (!objectTypes[typeof iterable]) return result;
callback = callback && typeof thisArg == 'undefined' ? callback : lodash.createCallback(callback, thisArg);
var ownIndex = -1,
ownProps = objectTypes[typeof iterable] && keys(iterable),
length = ownProps ? ownProps.length : 0;
while (++ownIndex < length) {
index = ownProps[ownIndex];
if (callback(iterable[index], index, collection) === false) return result;
}
return result
};
/**
* Creates a sorted array of all enumerable properties, own and inherited,
* of `object` that have function values.
*
* @static
* @memberOf _
* @alias methods
* @category Objects
* @param {Object} object The object to inspect.
* @returns {Array} Returns a new array of property names that have function values.
* @example
*
* _.functions(_);
* // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
*/
function functions(object) {
var result = [];
forIn(object, function(value, key) {
if (isFunction(value)) {
result.push(key);
}
});
return result.sort();
}
/**
* Checks if the specified object `property` exists and is a direct property,
* instead of an inherited property.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to check.
* @param {String} property The property to check for.
* @returns {Boolean} Returns `true` if key is a direct property, else `false`.
* @example
*
* _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
* // => true
*/
function has(object, property) {
return object ? hasOwnProperty.call(object, property) : false;
}
/**
* Creates an object composed of the inverted keys and values of the given `object`.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to invert.
* @returns {Object} Returns the created inverted object.
* @example
*
* _.invert({ 'first': 'moe', 'second': 'larry' });
* // => { 'moe': 'first', 'larry': 'second' }
*/
function invert(object) {
var index = -1,
props = keys(object),
length = props.length,
result = {};
while (++index < length) {
var key = props[index];
result[object[key]] = key;
}
return result;
}
/**
* Checks if `value` is a boolean value.
*
* @static
* @memberOf _
* @category Objects
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true`, if the `value` is a boolean value, else `false`.
* @example
*
* _.isBoolean(null);
* // => false
*/
function isBoolean(value) {
return value === true || value === false || toString.call(value) == boolClass;
}
/**
* Checks if `value` is a date.
*
* @static
* @memberOf _
* @category Objects
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true`, if the `value` is a date, else `false`.
* @example
*
* _.isDate(new Date);
* // => true
*/
function isDate(value) {
return value ? (typeof value == 'object' && toString.call(value) == dateClass) : false;
}
/**
* Checks if `value` is a DOM element.
*
* @static
* @memberOf _
* @category Objects
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true`, if the `value` is a DOM element, else `false`.
* @example
*
* _.isElement(document.body);
* // => true
*/
function isElement(value) {
return value ? value.nodeType === 1 : false;
}
/**
* Checks if `value` is empty. Arrays, strings, or `arguments` objects with a
* length of `0` and objects with no own enumerable properties are considered
* "empty".
*
* @static
* @memberOf _
* @category Objects
* @param {Array|Object|String} value The value to inspect.
* @returns {Boolean} Returns `true`, if the `value` is empty, else `false`.
* @example
*
* _.isEmpty([1, 2, 3]);
* // => false
*
* _.isEmpty({});
* // => true
*
* _.isEmpty('');
* // => true
*/
function isEmpty(value) {
var result = true;
if (!value) {
return result;
}
var className = toString.call(value),
length = value.length;
if ((className == arrayClass || className == stringClass || className == argsClass ) ||
(className == objectClass && typeof length == 'number' && isFunction(value.splice))) {
return !length;
}
forOwn(value, function() {
return (result = false);
});
return result;
}
/**
* Performs a deep comparison between two values to determine if they are
* equivalent to each other. If `callback` is passed, it will be executed to
* compare values. If `callback` returns `undefined`, comparisons will be handled
* by the method instead. The `callback` is bound to `thisArg` and invoked with
* two arguments; (a, b).
*
* @static
* @memberOf _
* @category Objects
* @param {Mixed} a The value to compare.
* @param {Mixed} b The other value to compare.
* @param {Function} [callback] The function to customize comparing values.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @param- {Array} [stackA=[]] Tracks traversed `a` objects.
* @param- {Array} [stackB=[]] Tracks traversed `b` objects.
* @returns {Boolean} Returns `true`, if the values are equivalent, else `false`.
* @example
*
* var moe = { 'name': 'moe', 'age': 40 };
* var copy = { 'name': 'moe', 'age': 40 };
*
* moe == copy;
* // => false
*
* _.isEqual(moe, copy);
* // => true
*
* var words = ['hello', 'goodbye'];
* var otherWords = ['hi', 'goodbye'];
*
* _.isEqual(words, otherWords, function(a, b) {
* var reGreet = /^(?:hello|hi)$/i,
* aGreet = _.isString(a) && reGreet.test(a),
* bGreet = _.isString(b) && reGreet.test(b);
*
* return (aGreet || bGreet) ? (aGreet == bGreet) : undefined;
* });
* // => true
*/
function isEqual(a, b, callback, thisArg, stackA, stackB) {
// used to indicate that when comparing objects, `a` has at least the properties of `b`
var whereIndicator = callback === indicatorObject;
if (typeof callback == 'function' && !whereIndicator) {
callback = lodash.createCallback(callback, thisArg, 2);
var result = callback(a, b);
if (typeof result != 'undefined') {
return !!result;
}
}
// exit early for identical values
if (a === b) {
// treat `+0` vs. `-0` as not equal
return a !== 0 || (1 / a == 1 / b);
}
var type = typeof a,
otherType = typeof b;
// exit early for unlike primitive values
if (a === a &&
(!a || (type != 'function' && type != 'object')) &&
(!b || (otherType != 'function' && otherType != 'object'))) {
return false;
}
// exit early for `null` and `undefined`, avoiding ES3's Function#call behavior
// http://es5.github.com/#x15.3.4.4
if (a == null || b == null) {
return a === b;
}
// compare [[Class]] names
var className = toString.call(a),
otherClass = toString.call(b);
if (className == argsClass) {
className = objectClass;
}
if (otherClass == argsClass) {
otherClass = objectClass;
}
if (className != otherClass) {
return false;
}
switch (className) {
case boolClass:
case dateClass:
// coerce dates and booleans to numbers, dates to milliseconds and booleans
// to `1` or `0`, treating invalid dates coerced to `NaN` as not equal
return +a == +b;
case numberClass:
// treat `NaN` vs. `NaN` as equal
return (a != +a)
? b != +b
// but treat `+0` vs. `-0` as not equal
: (a == 0 ? (1 / a == 1 / b) : a == +b);
case regexpClass:
case stringClass:
// coerce regexes to strings (http://es5.github.com/#x15.10.6.4)
// treat string primitives and their corresponding object instances as equal
return a == String(b);
}
var isArr = className == arrayClass;
if (!isArr) {
// unwrap any `lodash` wrapped values
if (hasOwnProperty.call(a, '__wrapped__ ') || hasOwnProperty.call(b, '__wrapped__')) {
return isEqual(a.__wrapped__ || a, b.__wrapped__ || b, callback, thisArg, stackA, stackB);
}
// exit for functions and DOM nodes
if (className != objectClass) {
return false;
}
// in older versions of Opera, `arguments` objects have `Array` constructors
var ctorA = a.constructor,
ctorB = b.constructor;
// non `Object` object instances with different constructors are not equal
if (ctorA != ctorB && !(
isFunction(ctorA) && ctorA instanceof ctorA &&
isFunction(ctorB) && ctorB instanceof ctorB
)) {
return false;
}
}
// assume cyclic structures are equal
// the algorithm for detecting cyclic structures is adapted from ES 5.1
// section 15.12.3, abstract operation `JO` (http://es5.github.com/#x15.12.3)
var initedStack = !stackA;
stackA || (stackA = getArray());
stackB || (stackB = getArray());
var length = stackA.length;
while (length--) {
if (stackA[length] == a) {
return stackB[length] == b;
}
}
var size = 0;
result = true;
// add `a` and `b` to the stack of traversed objects
stackA.push(a);
stackB.push(b);
// recursively compare objects and arrays (susceptible to call stack limits)
if (isArr) {
length = a.length;
size = b.length;
// compare lengths to determine if a deep comparison is necessary
result = size == a.length;
if (!result && !whereIndicator) {
return result;
}
// deep compare the contents, ignoring non-numeric properties
while (size--) {
var index = length,
value = b[size];
if (whereIndicator) {
while (index--) {
if ((result = isEqual(a[index], value, callback, thisArg, stackA, stackB))) {
break;
}
}
} else if (!(result = isEqual(a[size], value, callback, thisArg, stackA, stackB))) {
break;
}
}
return result;
}
// deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys`
// which, in this case, is more costly
forIn(b, function(value, key, b) {
if (hasOwnProperty.call(b, key)) {
// count the number of properties.
size++;
// deep compare each property value.
return (result = hasOwnProperty.call(a, key) && isEqual(a[key], value, callback, thisArg, stackA, stackB));
}
});
if (result && !whereIndicator) {
// ensure both objects have the same number of properties
forIn(a, function(value, key, a) {
if (hasOwnProperty.call(a, key)) {
// `size` will be `-1` if `a` has more properties than `b`
return (result = --size > -1);
}
});
}
if (initedStack) {
releaseArray(stackA);
releaseArray(stackB);
}
return result;
}
/**
* Checks if `value` is, or can be coerced to, a finite number.
*
* Note: This is not the same as native `isFinite`, which will return true for
* booleans and empty strings. See http://es5.github.com/#x15.1.2.5.
*
* @static
* @memberOf _
* @category Objects
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true`, if the `value` is finite, else `false`.
* @example
*
* _.isFinite(-101);
* // => true
*
* _.isFinite('10');
* // => true
*
* _.isFinite(true);
* // => false
*
* _.isFinite('');
* // => false
*
* _.isFinite(Infinity);
* // => false
*/
function isFinite(value) {
return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value));
}
/**
* Checks if `value` is a function.
*
* @static
* @memberOf _
* @category Objects
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true`, if the `value` is a function, else `false`.
* @example
*
* _.isFunction(_);
* // => true
*/
function isFunction(value) {
return typeof value == 'function';
}
/**
* Checks if `value` is the language type of Object.
* (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
*
* @static
* @memberOf _
* @category Objects
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true`, if the `value` is an object, else `false`.
* @example
*
* _.isObject({});
* // => true
*
* _.isObject([1, 2, 3]);
* // => true
*
* _.isObject(1);
* // => false
*/
function isObject(value) {
// check if the value is the ECMAScript language type of Object
// http://es5.github.com/#x8
// and avoid a V8 bug
// http://code.google.com/p/v8/issues/detail?id=2291
return !!(value && objectTypes[typeof value]);
}
/**
* Checks if `value` is `NaN`.
*
* Note: This is not the same as native `isNaN`, which will return `true` for
* `undefined` and other values. See http://es5.github.com/#x15.1.2.4.
*
* @static
* @memberOf _
* @category Objects
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true`, if the `value` is `NaN`, else `false`.
* @example
*
* _.isNaN(NaN);
* // => true
*
* _.isNaN(new Number(NaN));
* // => true
*
* isNaN(undefined);
* // => true
*
* _.isNaN(undefined);
* // => false
*/
function isNaN(value) {
// `NaN` as a primitive is the only value that is not equal to itself
// (perform the [[Class]] check first to avoid errors with some host objects in IE)
return isNumber(value) && value != +value
}
/**
* Checks if `value` is `null`.
*
* @static
* @memberOf _
* @category Objects
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true`, if the `value` is `null`, else `false`.
* @example
*
* _.isNull(null);
* // => true
*
* _.isNull(undefined);
* // => false
*/
function isNull(value) {
return value === null;
}
/**
* Checks if `value` is a number.
*
* @static
* @memberOf _
* @category Objects
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true`, if the `value` is a number, else `false`.
* @example
*
* _.isNumber(8.4 * 5);
* // => true
*/
function isNumber(value) {
return typeof value == 'number' || toString.call(value) == numberClass;
}
/**
* Checks if a given `value` is an object created by the `Object` constructor.
*
* @static
* @memberOf _
* @category Objects
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true`, if `value` is a plain object, else `false`.
* @example
*
* function Stooge(name, age) {
* this.name = name;
* this.age = age;
* }
*
* _.isPlainObject(new Stooge('moe', 40));
* // => false
*
* _.isPlainObject([1, 2, 3]);
* // => false
*
* _.isPlainObject({ 'name': 'moe', 'age': 40 });
* // => true
*/
var isPlainObject = function(value) {
if (!(value && toString.call(value) == objectClass)) {
return false;
}
var valueOf = value.valueOf,
objProto = typeof valueOf == 'function' && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto);
return objProto
? (value == objProto || getPrototypeOf(value) == objProto)
: shimIsPlainObject(value);
};
/**
* Checks if `value` is a regular expression.
*
* @static
* @memberOf _
* @category Objects
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true`, if the `value` is a regular expression, else `false`.
* @example
*
* _.isRegExp(/moe/);
* // => true
*/
function isRegExp(value) {
return value ? (typeof value == 'object' && toString.call(value) == regexpClass) : false;
}
/**
* Checks if `value` is a string.
*
* @static
* @memberOf _
* @category Objects
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true`, if the `value` is a string, else `false`.
* @example
*
* _.isString('moe');
* // => true
*/
function isString(value) {
return typeof value == 'string' || toString.call(value) == stringClass;
}
/**
* Checks if `value` is `undefined`.
*
* @static
* @memberOf _
* @category Objects
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true`, if the `value` is `undefined`, else `false`.
* @example
*
* _.isUndefined(void 0);
* // => true
*/
function isUndefined(value) {
return typeof value == 'undefined';
}
/**
* Recursively merges own enumerable properties of the source object(s), that
* don't resolve to `undefined`, into the destination object. Subsequent sources
* will overwrite property assignments of previous sources. If a `callback` function
* is passed, it will be executed to produce the merged values of the destination
* and source properties. If `callback` returns `undefined`, merging will be
* handled by the method instead. The `callback` is bound to `thisArg` and
* invoked with two arguments; (objectValue, sourceValue).
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The destination object.
* @param {Object} [source1, source2, ...] The source objects.
* @param {Function} [callback] The function to customize merging properties.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @param- {Object} [deepIndicator] Indicates that `stackA` and `stackB` are
* arrays of traversed objects, instead of source objects.
* @param- {Array} [stackA=[]] Tracks traversed source objects.
* @param- {Array} [stackB=[]] Associates values with source counterparts.
* @returns {Object} Returns the destination object.
* @example
*
* var names = {
* 'stooges': [
* { 'name': 'moe' },
* { 'name': 'larry' }
* ]
* };
*
* var ages = {
* 'stooges': [
* { 'age': 40 },
* { 'age': 50 }
* ]
* };
*
* _.merge(names, ages);
* // => { 'stooges': [{ 'name': 'moe', 'age': 40 }, { 'name': 'larry', 'age': 50 }] }
*
* var food = {
* 'fruits': ['apple'],
* 'vegetables': ['beet']
* };
*
* var otherFood = {
* 'fruits': ['banana'],
* 'vegetables': ['carrot']
* };
*
* _.merge(food, otherFood, function(a, b) {
* return _.isArray(a) ? a.concat(b) : undefined;
* });
* // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] }
*/
function merge(object, source, deepIndicator) {
var args = arguments,
index = 0,
length = 2;
if (!isObject(object)) {
return object;
}
if (deepIndicator === indicatorObject) {
var callback = args[3],
stackA = args[4],
stackB = args[5];
} else {
var initedStack = true;
stackA = getArray();
stackB = getArray();
// allows working with `_.reduce` and `_.reduceRight` without
// using their `callback` arguments, `index|key` and `collection`
if (typeof deepIndicator != 'number') {
length = args.length;
}
if (length > 3 && typeof args[length - 2] == 'function') {
callback = lodash.createCallback(args[--length - 1], args[length--], 2);
} else if (length > 2 && typeof args[length - 1] == 'function') {
callback = args[--length];
}
}
while (++index < length) {
(isArray(args[index]) ? forEach : forOwn)(args[index], function(source, key) {
var found,
isArr,
result = source,
value = object[key];
if (source && ((isArr = isArray(source)) || isPlainObject(source))) {
// avoid merging previously merged cyclic sources
var stackLength = stackA.length;
while (stackLength--) {
if ((found = stackA[stackLength] == source)) {
value = stackB[stackLength];
break;
}
}
if (!found) {
var isShallow;
if (callback) {
result = callback(value, source);
if ((isShallow = typeof result != 'undefined')) {
value = result;
}
}
if (!isShallow) {
value = isArr
? (isArray(value) ? value : [])
: (isPlainObject(value) ? value : {});
}
// add `source` and associated `value` to the stack of traversed objects
stackA.push(source);
stackB.push(value);
// recursively merge objects and arrays (susceptible to call stack limits)
if (!isShallow) {
value = merge(value, source, indicatorObject, callback, stackA, stackB);
}
}
}
else {
if (callback) {
result = callback(value, source);
if (typeof result == 'undefined') {
result = source;
}
}
if (typeof result != 'undefined') {
value = result;
}
}
object[key] = value;
});
}
if (initedStack) {
releaseArray(stackA);
releaseArray(stackB);
}
return object;
}
/**
* Creates a shallow clone of `object` excluding the specified properties.
* Property names may be specified as individual arguments or as arrays of
* property names. If a `callback` function is passed, it will be executed
* for each property in the `object`, omitting the properties `callback`
* returns truthy for. The `callback` is bound to `thisArg` and invoked
* with three arguments; (value, key, object).
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The source object.
* @param {Function|String} callback|[prop1, prop2, ...] The properties to omit
* or the function called per iteration.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns an object without the omitted properties.
* @example
*
* _.omit({ 'name': 'moe', 'age': 40 }, 'age');
* // => { 'name': 'moe' }
*
* _.omit({ 'name': 'moe', 'age': 40 }, function(value) {
* return typeof value == 'number';
* });
* // => { 'name': 'moe' }
*/
function omit(object, callback, thisArg) {
var indexOf = getIndexOf(),
isFunc = typeof callback == 'function',
result = {};
if (isFunc) {
callback = lodash.createCallback(callback, thisArg);
} else {
var props = concat.apply(arrayRef, nativeSlice.call(arguments, 1));
}
forIn(object, function(value, key, object) {
if (isFunc
? !callback(value, key, object)
: indexOf(props, key) < 0
) {
result[key] = value;
}
});
return result;
}
/**
* Creates a two dimensional array of the given object's key-value pairs,
* i.e. `[[key1, value1], [key2, value2]]`.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to inspect.
* @returns {Array} Returns new array of key-value pairs.
* @example
*
* _.pairs({ 'moe': 30, 'larry': 40 });
* // => [['moe', 30], ['larry', 40]] (order is not guaranteed)
*/
function pairs(object) {
var index = -1,
props = keys(object),
length = props.length,
result = Array(length);
while (++index < length) {
var key = props[index];
result[index] = [key, object[key]];
}
return result;
}
/**
* Creates a shallow clone of `object` composed of the specified properties.
* Property names may be specified as individual arguments or as arrays of property
* names. If `callback` is passed, it will be executed for each property in the
* `object`, picking the properties `callback` returns truthy for. The `callback`
* is bound to `thisArg` and invoked with three arguments; (value, key, object).
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The source object.
* @param {Array|Function|String} callback|[prop1, prop2, ...] The function called
* per iteration or properties to pick, either as individual arguments or arrays.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns an object composed of the picked properties.
* @example
*
* _.pick({ 'name': 'moe', '_userid': 'moe1' }, 'name');
* // => { 'name': 'moe' }
*
* _.pick({ 'name': 'moe', '_userid': 'moe1' }, function(value, key) {
* return key.charAt(0) != '_';
* });
* // => { 'name': 'moe' }
*/
function pick(object, callback, thisArg) {
var result = {};
if (typeof callback != 'function') {
var index = -1,
props = concat.apply(arrayRef, nativeSlice.call(arguments, 1)),
length = isObject(object) ? props.length : 0;
while (++index < length) {
var key = props[index];
if (key in object) {
result[key] = object[key];
}
}
} else {
callback = lodash.createCallback(callback, thisArg);
forIn(object, function(value, key, object) {
if (callback(value, key, object)) {
result[key] = value;
}
});
}
return result;
}
/**
* An alternative to `_.reduce`, this method transforms an `object` to a new
* `accumulator` object which is the result of running each of its elements
* through the `callback`, with each `callback` execution potentially mutating
* the `accumulator` object. The `callback` is bound to `thisArg` and invoked
* with four arguments; (accumulator, value, key, object). Callbacks may exit
* iteration early by explicitly returning `false`.
*
* @static
* @memberOf _
* @category Objects
* @param {Array|Object} collection The collection to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {Mixed} [accumulator] The custom accumulator value.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Mixed} Returns the accumulated value.
* @example
*
* var squares = _.transform([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function(result, num) {
* num *= num;
* if (num % 2) {
* return result.push(num) < 3;
* }
* });
* // => [1, 9, 25]
*
* var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
* result[key] = num * 3;
* });
* // => { 'a': 3, 'b': 6, 'c': 9 }
*/
function transform(object, callback, accumulator, thisArg) {
var isArr = isArray(object);
callback = lodash.createCallback(callback, thisArg, 4);
if (accumulator == null) {
if (isArr) {
accumulator = [];
} else {
var ctor = object && object.constructor,
proto = ctor && ctor.prototype;
accumulator = createObject(proto);
}
}
(isArr ? forEach : forOwn)(object, function(value, index, object) {
return callback(accumulator, value, index, object);
});
return accumulator;
}
/**
* Creates an array composed of the own enumerable property values of `object`.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to inspect.
* @returns {Array} Returns a new array of property values.
* @example
*
* _.values({ 'one': 1, 'two': 2, 'three': 3 });
* // => [1, 2, 3] (order is not guaranteed)
*/
function values(object) {
var index = -1,
props = keys(object),
length = props.length,
result = Array(length);
while (++index < length) {
result[index] = object[props[index]];
}
return result;
}
/*--------------------------------------------------------------------------*/
/**
* Creates an array of elements from the specified indexes, or keys, of the
* `collection`. Indexes may be specified as individual arguments or as arrays
* of indexes.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|String} collection The collection to iterate over.
* @param {Array|Number|String} [index1, index2, ...] The indexes of
* `collection` to retrieve, either as individual arguments or arrays.
* @returns {Array} Returns a new array of elements corresponding to the
* provided indexes.
* @example
*
* _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]);
* // => ['a', 'c', 'e']
*
* _.at(['moe', 'larry', 'curly'], 0, 2);
* // => ['moe', 'curly']
*/
function at(collection) {
var index = -1,
props = concat.apply(arrayRef, nativeSlice.call(arguments, 1)),
length = props.length,
result = Array(length);
while(++index < length) {
result[index] = collection[props[index]];
}
return result;
}
/**
* Checks if a given `target` element is present in a `collection` using strict
* equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
* as the offset from the end of the collection.
*
* @static
* @memberOf _
* @alias include
* @category Collections
* @param {Array|Object|String} collection The collection to iterate over.
* @param {Mixed} target The value to check for.
* @param {Number} [fromIndex=0] The index to search from.
* @returns {Boolean} Returns `true` if the `target` element is found, else `false`.
* @example
*
* _.contains([1, 2, 3], 1);
* // => true
*
* _.contains([1, 2, 3], 1, 2);
* // => false
*
* _.contains({ 'name': 'moe', 'age': 40 }, 'moe');
* // => true
*
* _.contains('curly', 'ur');
* // => true
*/
function contains(collection, target, fromIndex) {
var index = -1,
indexOf = getIndexOf(),
length = collection ? collection.length : 0,
result = false;
fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0;
if (length && typeof length == 'number') {
result = (isString(collection)
? collection.indexOf(target, fromIndex)
: indexOf(collection, target, fromIndex)
) > -1;
} else {
forOwn(collection, function(value) {
if (++index >= fromIndex) {
return !(result = value === target);
}
});
}
return result;
}
/**
* Creates an object composed of keys returned from running each element of the
* `collection` through the given `callback`. The corresponding value of each key
* is the number of times the key was returned by the `callback`. The `callback`
* is bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
*
* If a property name is passed for `callback`, the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is passed for `callback`, the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|String} collection The collection to iterate over.
* @param {Function|Object|String} [callback=identity] The function called per
* iteration. If a property name or object is passed, it will be used to create
* a "_.pluck" or "_.where" style callback, respectively.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns the composed aggregate object.
* @example
*
* _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); });
* // => { '4': 1, '6': 2 }
*
* _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
* // => { '4': 1, '6': 2 }
*
* _.countBy(['one', 'two', 'three'], 'length');
* // => { '3': 2, '5': 1 }
*/
function countBy(collection, callback, thisArg) {
var result = {};
callback = lodash.createCallback(callback, thisArg);
forEach(collection, function(value, key, collection) {
key = String(callback(value, key, collection));
(hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1);
});
return result;
}
/**
* Checks if the `callback` returns a truthy value for **all** elements of a
* `collection`. The `callback` is bound to `thisArg` and invoked with three
* arguments; (value, index|key, collection).
*
* If a property name is passed for `callback`, the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is passed for `callback`, the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias all
* @category Collections
* @param {Array|Object|String} collection The collection to iterate over.
* @param {Function|Object|String} [callback=identity] The function called per
* iteration. If a property name or object is passed, it will be used to create
* a "_.pluck" or "_.where" style callback, respectively.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Boolean} Returns `true` if all elements pass the callback check,
* else `false`.
* @example
*
* _.every([true, 1, null, 'yes'], Boolean);
* // => false
*
* var stooges = [
* { 'name': 'moe', 'age': 40 },
* { 'name': 'larry', 'age': 50 }
* ];
*
* // using "_.pluck" callback shorthand
* _.every(stooges, 'age');
* // => true
*
* // using "_.where" callback shorthand
* _.every(stooges, { 'age': 50 });
* // => false
*/
function every(collection, callback, thisArg) {
var result = true;
callback = lodash.createCallback(callback, thisArg);
var index = -1,
length = collection ? collection.length : 0;
if (typeof length == 'number') {
while (++index < length) {
if (!(result = !!callback(collection[index], index, collection))) {
break;
}
}
} else {
forOwn(collection, function(value, index, collection) {
return (result = !!callback(value, index, collection));
});
}
return result;
}
/**
* Examines each element in a `collection`, returning an array of all elements
* the `callback` returns truthy for. The `callback` is bound to `thisArg` and
* invoked with three arguments; (value, index|key, collection).
*
* If a property name is passed for `callback`, the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is passed for `callback`, the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias select
* @category Collections
* @param {Array|Object|String} collection The collection to iterate over.
* @param {Function|Object|String} [callback=identity] The function called per
* iteration. If a property name or object is passed, it will be used to create
* a "_.pluck" or "_.where" style callback, respectively.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new array of elements that passed the callback check.
* @example
*
* var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
* // => [2, 4, 6]
*
* var food = [
* { 'name': 'apple', 'organic': false, 'type': 'fruit' },
* { 'name': 'carrot', 'organic': true, 'type': 'vegetable' }
* ];
*
* // using "_.pluck" callback shorthand
* _.filter(food, 'organic');
* // => [{ 'name': 'carrot', 'organic': true, 'type': 'vegetable' }]
*
* // using "_.where" callback shorthand
* _.filter(food, { 'type': 'fruit' });
* // => [{ 'name': 'apple', 'organic': false, 'type': 'fruit' }]
*/
function filter(collection, callback, thisArg) {
var result = [];
callback = lodash.createCallback(callback, thisArg);
var index = -1,
length = collection ? collection.length : 0;
if (typeof length == 'number') {
while (++index < length) {
var value = collection[index];
if (callback(value, index, collection)) {
result.push(value);
}
}
} else {
forOwn(collection, function(value, index, collection) {
if (callback(value, index, collection)) {
result.push(value);
}
});
}
return result;
}
/**
* Examines each element in a `collection`, returning the first that the `callback`
* returns truthy for. The `callback` is bound to `thisArg` and invoked with three
* arguments; (value, index|key, collection).
*
* If a property name is passed for `callback`, the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is passed for `callback`, the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias detect, findWhere
* @category Collections
* @param {Array|Object|String} collection The collection to iterate over.
* @param {Function|Object|String} [callback=identity] The function called per
* iteration. If a property name or object is passed, it will be used to create
* a "_.pluck" or "_.where" style callback, respectively.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Mixed} Returns the found element, else `undefined`.
* @example
*
* _.find([1, 2, 3, 4], function(num) {
* return num % 2 == 0;
* });
* // => 2
*
* var food = [
* { 'name': 'apple', 'organic': false, 'type': 'fruit' },
* { 'name': 'banana', 'organic': true, 'type': 'fruit' },
* { 'name': 'beet', 'organic': false, 'type': 'vegetable' }
* ];
*
* // using "_.where" callback shorthand
* _.find(food, { 'type': 'vegetable' });
* // => { 'name': 'beet', 'organic': false, 'type': 'vegetable' }
*
* // using "_.pluck" callback shorthand
* _.find(food, 'organic');
* // => { 'name': 'banana', 'organic': true, 'type': 'fruit' }
*/
function find(collection, callback, thisArg) {
callback = lodash.createCallback(callback, thisArg);
var index = -1,
length = collection ? collection.length : 0;
if (typeof length == 'number') {
while (++index < length) {
var value = collection[index];
if (callback(value, index, collection)) {
return value;
}
}
} else {
var result;
forOwn(collection, function(value, index, collection) {
if (callback(value, index, collection)) {
result = value;
return false;
}
});
return result;
}
}
/**
* Iterates over a `collection`, executing the `callback` for each element in
* the `collection`. The `callback` is bound to `thisArg` and invoked with three
* arguments; (value, index|key, collection). Callbacks may exit iteration early
* by explicitly returning `false`.
*
* @static
* @memberOf _
* @alias each
* @category Collections
* @param {Array|Object|String} collection The collection to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Array|Object|String} Returns `collection`.
* @example
*
* _([1, 2, 3]).forEach(alert).join(',');
* // => alerts each number and returns '1,2,3'
*
* _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, alert);
* // => alerts each number value (order is not guaranteed)
*/
function forEach(collection, callback, thisArg) {
var index = -1,
length = collection ? collection.length : 0;
callback = callback && typeof thisArg == 'undefined' ? callback : lodash.createCallback(callback, thisArg);
if (typeof length == 'number') {
while (++index < length) {
if (callback(collection[index], index, collection) === false) {
break;
}
}
} else {
forOwn(collection, callback);
}
return collection;
}
/**
* Creates an object composed of keys returned from running each element of the
* `collection` through the `callback`. The corresponding value of each key is
* an array of elements passed to `callback` that returned the key. The `callback`
* is bound to `thisArg` and invoked with three arguments; (value, index|key, collection).
*
* If a property name is passed for `callback`, the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is passed for `callback`, the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|String} collection The collection to iterate over.
* @param {Function|Object|String} [callback=identity] The function called per
* iteration. If a property name or object is passed, it will be used to create
* a "_.pluck" or "_.where" style callback, respectively.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns the composed aggregate object.
* @example
*
* _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); });
* // => { '4': [4.2], '6': [6.1, 6.4] }
*
* _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
* // => { '4': [4.2], '6': [6.1, 6.4] }
*
* // using "_.pluck" callback shorthand
* _.groupBy(['one', 'two', 'three'], 'length');
* // => { '3': ['one', 'two'], '5': ['three'] }
*/
function groupBy(collection, callback, thisArg) {
var result = {};
callback = lodash.createCallback(callback, thisArg);
forEach(collection, function(value, key, collection) {
key = String(callback(value, key, collection));
(hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value);
});
return result;
}
/**
* Invokes the method named by `methodName` on each element in the `collection`,
* returning an array of the results of each invoked method. Additional arguments
* will be passed to each invoked method. If `methodName` is a function, it will
* be invoked for, and `this` bound to, each element in the `collection`.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|String} collection The collection to iterate over.
* @param {Function|String} methodName The name of the method to invoke or
* the function invoked per iteration.
* @param {Mixed} [arg1, arg2, ...] Arguments to invoke the method with.
* @returns {Array} Returns a new array of the results of each invoked method.
* @example
*
* _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
* // => [[1, 5, 7], [1, 2, 3]]
*
* _.invoke([123, 456], String.prototype.split, '');
* // => [['1', '2', '3'], ['4', '5', '6']]
*/
function invoke(collection, methodName) {
var args = nativeSlice.call(arguments, 2),
index = -1,
isFunc = typeof methodName == 'function',
length = collection ? collection.length : 0,
result = Array(typeof length == 'number' ? length : 0);
forEach(collection, function(value) {
result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args);
});
return result;
}
/**
* Creates an array of values by running each element in the `collection`
* through the `callback`. The `callback` is bound to `thisArg` and invoked with
* three arguments; (value, index|key, collection).
*
* If a property name is passed for `callback`, the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is passed for `callback`, the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias collect
* @category Collections
* @param {Array|Object|String} collection The collection to iterate over.
* @param {Function|Object|String} [callback=identity] The function called per
* iteration. If a property name or object is passed, it will be used to create
* a "_.pluck" or "_.where" style callback, respectively.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new array of the results of each `callback` execution.
* @example
*
* _.map([1, 2, 3], function(num) { return num * 3; });
* // => [3, 6, 9]
*
* _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
* // => [3, 6, 9] (order is not guaranteed)
*
* var stooges = [
* { 'name': 'moe', 'age': 40 },
* { 'name': 'larry', 'age': 50 }
* ];
*
* // using "_.pluck" callback shorthand
* _.map(stooges, 'name');
* // => ['moe', 'larry']
*/
function map(collection, callback, thisArg) {
var index = -1,
length = collection ? collection.length : 0;
callback = lodash.createCallback(callback, thisArg);
if (typeof length == 'number') {
var result = Array(length);
while (++index < length) {
result[index] = callback(collection[index], index, collection);
}
} else {
result = [];
forOwn(collection, function(value, key, collection) {
result[++index] = callback(value, key, collection);
});
}
return result;
}
/**
* Retrieves the maximum value of an `array`. If `callback` is passed,
* it will be executed for each value in the `array` to generate the
* criterion by which the value is ranked. The `callback` is bound to
* `thisArg` and invoked with three arguments; (value, index, collection).
*
* If a property name is passed for `callback`, the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is passed for `callback`, the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|String} collection The collection to iterate over.
* @param {Function|Object|String} [callback=identity] The function called per
* iteration. If a property name or object is passed, it will be used to create
* a "_.pluck" or "_.where" style callback, respectively.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Mixed} Returns the maximum value.
* @example
*
* _.max([4, 2, 8, 6]);
* // => 8
*
* var stooges = [
* { 'name': 'moe', 'age': 40 },
* { 'name': 'larry', 'age': 50 }
* ];
*
* _.max(stooges, function(stooge) { return stooge.age; });
* // => { 'name': 'larry', 'age': 50 };
*
* // using "_.pluck" callback shorthand
* _.max(stooges, 'age');
* // => { 'name': 'larry', 'age': 50 };
*/
function max(collection, callback, thisArg) {
var computed = -Infinity,
result = computed;
if (!callback && isArray(collection)) {
var index = -1,
length = collection.length;
while (++index < length) {
var value = collection[index];
if (value > result) {
result = value;
}
}
} else {
callback = (!callback && isString(collection))
? charAtCallback
: lodash.createCallback(callback, thisArg);
forEach(collection, function(value, index, collection) {
var current = callback(value, index, collection);
if (current > computed) {
computed = current;
result = value;
}
});
}
return result;
}
/**
* Retrieves the minimum value of an `array`. If `callback` is passed,
* it will be executed for each value in the `array` to generate the
* criterion by which the value is ranked. The `callback` is bound to `thisArg`
* and invoked with three arguments; (value, index, collection).
*
* If a property name is passed for `callback`, the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is passed for `callback`, the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|String} collection The collection to iterate over.
* @param {Function|Object|String} [callback=identity] The function called per
* iteration. If a property name or object is passed, it will be used to create
* a "_.pluck" or "_.where" style callback, respectively.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Mixed} Returns the minimum value.
* @example
*
* _.min([4, 2, 8, 6]);
* // => 2
*
* var stooges = [
* { 'name': 'moe', 'age': 40 },
* { 'name': 'larry', 'age': 50 }
* ];
*
* _.min(stooges, function(stooge) { return stooge.age; });
* // => { 'name': 'moe', 'age': 40 };
*
* // using "_.pluck" callback shorthand
* _.min(stooges, 'age');
* // => { 'name': 'moe', 'age': 40 };
*/
function min(collection, callback, thisArg) {
var computed = Infinity,
result = computed;
if (!callback && isArray(collection)) {
var index = -1,
length = collection.length;
while (++index < length) {
var value = collection[index];
if (value < result) {
result = value;
}
}
} else {
callback = (!callback && isString(collection))
? charAtCallback
: lodash.createCallback(callback, thisArg);
forEach(collection, function(value, index, collection) {
var current = callback(value, index, collection);
if (current < computed) {
computed = current;
result = value;
}
});
}
return result;
}
/**
* Retrieves the value of a specified property from all elements in the `collection`.
*
* @static
* @memberOf _
* @type Function
* @category Collections
* @param {Array|Object|String} collection The collection to iterate over.
* @param {String} property The property to pluck.
* @returns {Array} Returns a new array of property values.
* @example
*
* var stooges = [
* { 'name': 'moe', 'age': 40 },
* { 'name': 'larry', 'age': 50 }
* ];
*
* _.pluck(stooges, 'name');
* // => ['moe', 'larry']
*/
function pluck(collection, property) {
var index = -1,
length = collection ? collection.length : 0;
if (typeof length == 'number') {
var result = Array(length);
while (++index < length) {
result[index] = collection[index][property];
}
}
return result || map(collection, property);
}
/**
* Reduces a `collection` to a value which is the accumulated result of running
* each element in the `collection` through the `callback`, where each successive
* `callback` execution consumes the return value of the previous execution.
* If `accumulator` is not passed, the first element of the `collection` will be
* used as the initial `accumulator` value. The `callback` is bound to `thisArg`
* and invoked with four arguments; (accumulator, value, index|key, collection).
*
* @static
* @memberOf _
* @alias foldl, inject
* @category Collections
* @param {Array|Object|String} collection The collection to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {Mixed} [accumulator] Initial value of the accumulator.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Mixed} Returns the accumulated value.
* @example
*
* var sum = _.reduce([1, 2, 3], function(sum, num) {
* return sum + num;
* });
* // => 6
*
* var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
* result[key] = num * 3;
* return result;
* }, {});
* // => { 'a': 3, 'b': 6, 'c': 9 }
*/
function reduce(collection, callback, accumulator, thisArg) {
if (!collection) return accumulator;
var noaccum = arguments.length < 3;
callback = lodash.createCallback(callback, thisArg, 4);
var index = -1,
length = collection.length;
if (typeof length == 'number') {
if (noaccum) {
accumulator = collection[++index];
}
while (++index < length) {
accumulator = callback(accumulator, collection[index], index, collection);
}
} else {
forOwn(collection, function(value, index, collection) {
accumulator = noaccum
? (noaccum = false, value)
: callback(accumulator, value, index, collection)
});
}
return accumulator;
}
/**
* This method is similar to `_.reduce`, except that it iterates over a
* `collection` from right to left.
*
* @static
* @memberOf _
* @alias foldr
* @category Collections
* @param {Array|Object|String} collection The collection to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {Mixed} [accumulator] Initial value of the accumulator.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Mixed} Returns the accumulated value.
* @example
*
* var list = [[0, 1], [2, 3], [4, 5]];
* var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
* // => [4, 5, 2, 3, 0, 1]
*/
function reduceRight(collection, callback, accumulator, thisArg) {
var iterable = collection,
length = collection ? collection.length : 0,
noaccum = arguments.length < 3;
if (typeof length != 'number') {
var props = keys(collection);
length = props.length;
}
callback = lodash.createCallback(callback, thisArg, 4);
forEach(collection, function(value, index, collection) {
index = props ? props[--length] : --length;
accumulator = noaccum
? (noaccum = false, iterable[index])
: callback(accumulator, iterable[index], index, collection);
});
return accumulator;
}
/**
* The opposite of `_.filter`, this method returns the elements of a
* `collection` that `callback` does **not** return truthy for.
*
* If a property name is passed for `callback`, the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is passed for `callback`, the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|String} collection The collection to iterate over.
* @param {Function|Object|String} [callback=identity] The function called per
* iteration. If a property name or object is passed, it will be used to create
* a "_.pluck" or "_.where" style callback, respectively.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new array of elements that did **not** pass the
* callback check.
* @example
*
* var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
* // => [1, 3, 5]
*
* var food = [
* { 'name': 'apple', 'organic': false, 'type': 'fruit' },
* { 'name': 'carrot', 'organic': true, 'type': 'vegetable' }
* ];
*
* // using "_.pluck" callback shorthand
* _.reject(food, 'organic');
* // => [{ 'name': 'apple', 'organic': false, 'type': 'fruit' }]
*
* // using "_.where" callback shorthand
* _.reject(food, { 'type': 'fruit' });
* // => [{ 'name': 'carrot', 'organic': true, 'type': 'vegetable' }]
*/
function reject(collection, callback, thisArg) {
callback = lodash.createCallback(callback, thisArg);
return filter(collection, function(value, index, collection) {
return !callback(value, index, collection);
});
}
/**
* Creates an array of shuffled `array` values, using a version of the
* Fisher-Yates shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|String} collection The collection to shuffle.
* @returns {Array} Returns a new shuffled collection.
* @example
*
* _.shuffle([1, 2, 3, 4, 5, 6]);
* // => [4, 1, 6, 3, 5, 2]
*/
function shuffle(collection) {
var index = -1,
length = collection ? collection.length : 0,
result = Array(typeof length == 'number' ? length : 0);
forEach(collection, function(value) {
var rand = floor(nativeRandom() * (++index + 1));
result[index] = result[rand];
result[rand] = value;
});
return result;
}
/**
* Gets the size of the `collection` by returning `collection.length` for arrays
* and array-like objects or the number of own enumerable properties for objects.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|String} collection The collection to inspect.
* @returns {Number} Returns `collection.length` or number of own enumerable properties.
* @example
*
* _.size([1, 2]);
* // => 2
*
* _.size({ 'one': 1, 'two': 2, 'three': 3 });
* // => 3
*
* _.size('curly');
* // => 5
*/
function size(collection) {
var length = collection ? collection.length : 0;
return typeof length == 'number' ? length : keys(collection).length;
}
/**
* Checks if the `callback` returns a truthy value for **any** element of a
* `collection`. The function returns as soon as it finds passing value, and
* does not iterate over the entire `collection`. The `callback` is bound to
* `thisArg` and invoked with three arguments; (value, index|key, collection).
*
* If a property name is passed for `callback`, the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is passed for `callback`, the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias any
* @category Collections
* @param {Array|Object|String} collection The collection to iterate over.
* @param {Function|Object|String} [callback=identity] The function called per
* iteration. If a property name or object is passed, it will be used to create
* a "_.pluck" or "_.where" style callback, respectively.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Boolean} Returns `true` if any element passes the callback check,
* else `false`.
* @example
*
* _.some([null, 0, 'yes', false], Boolean);
* // => true
*
* var food = [
* { 'name': 'apple', 'organic': false, 'type': 'fruit' },
* { 'name': 'carrot', 'organic': true, 'type': 'vegetable' }
* ];
*
* // using "_.pluck" callback shorthand
* _.some(food, 'organic');
* // => true
*
* // using "_.where" callback shorthand
* _.some(food, { 'type': 'meat' });
* // => false
*/
function some(collection, callback, thisArg) {
var result;
callback = lodash.createCallback(callback, thisArg);
var index = -1,
length = collection ? collection.length : 0;
if (typeof length == 'number') {
while (++index < length) {
if ((result = callback(collection[index], index, collection))) {
break;
}
}
} else {
forOwn(collection, function(value, index, collection) {
return !(result = callback(value, index, collection));
});
}
return !!result;
}
/**
* Creates an array of elements, sorted in ascending order by the results of
* running each element in the `collection` through the `callback`. This method
* performs a stable sort, that is, it will preserve the original sort order of
* equal elements. The `callback` is bound to `thisArg` and invoked with three
* arguments; (value, index|key, collection).
*
* If a property name is passed for `callback`, the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is passed for `callback`, the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|String} collection The collection to iterate over.
* @param {Function|Object|String} [callback=identity] The function called per
* iteration. If a property name or object is passed, it will be used to create
* a "_.pluck" or "_.where" style callback, respectively.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new array of sorted elements.
* @example
*
* _.sortBy([1, 2, 3], function(num) { return Math.sin(num); });
* // => [3, 1, 2]
*
* _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math);
* // => [3, 1, 2]
*
* // using "_.pluck" callback shorthand
* _.sortBy(['banana', 'strawberry', 'apple'], 'length');
* // => ['apple', 'banana', 'strawberry']
*/
function sortBy(collection, callback, thisArg) {
var index = -1,
length = collection ? collection.length : 0,
result = Array(typeof length == 'number' ? length : 0);
callback = lodash.createCallback(callback, thisArg);
forEach(collection, function(value, key, collection) {
var object = result[++index] = getObject();
object.criteria = callback(value, key, collection);
object.index = index;
object.value = value;
});
length = result.length;
result.sort(compareAscending);
while (length--) {
var object = result[length];
result[length] = object.value;
releaseObject(object);
}
return result;
}
/**
* Converts the `collection` to an array.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|String} collection The collection to convert.
* @returns {Array} Returns the new converted array.
* @example
*
* (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
* // => [2, 3, 4]
*/
function toArray(collection) {
if (collection && typeof collection.length == 'number') {
return slice(collection);
}
return values(collection);
}
/**
* Examines each element in a `collection`, returning an array of all elements
* that have the given `properties`. When checking `properties`, this method
* performs a deep comparison between values to determine if they are equivalent
* to each other.
*
* @static
* @memberOf _
* @type Function
* @category Collections
* @param {Array|Object|String} collection The collection to iterate over.
* @param {Object} properties The object of property values to filter by.
* @returns {Array} Returns a new array of elements that have the given `properties`.
* @example
*
* var stooges = [
* { 'name': 'moe', 'age': 40 },
* { 'name': 'larry', 'age': 50 }
* ];
*
* _.where(stooges, { 'age': 40 });
* // => [{ 'name': 'moe', 'age': 40 }]
*/
var where = filter;
/*--------------------------------------------------------------------------*/
/**
* Creates an array with all falsey values of `array` removed. The values
* `false`, `null`, `0`, `""`, `undefined` and `NaN` are all falsey.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to compact.
* @returns {Array} Returns a new filtered array.
* @example
*
* _.compact([0, 1, false, 2, '', 3]);
* // => [1, 2, 3]
*/
function compact(array) {
var index = -1,
length = array ? array.length : 0,
result = [];
while (++index < length) {
var value = array[index];
if (value) {
result.push(value);
}
}
return result;
}
/**
* Creates an array of `array` elements not present in the other arrays
* using strict equality for comparisons, i.e. `===`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to process.
* @param {Array} [array1, array2, ...] Arrays to check.
* @returns {Array} Returns a new array of `array` elements not present in the
* other arrays.
* @example
*
* _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
* // => [1, 3, 4]
*/
function difference(array) {
var index = -1,
indexOf = getIndexOf(),
length = array ? array.length : 0,
seen = concat.apply(arrayRef, nativeSlice.call(arguments, 1)),
result = [];
var isLarge = length >= largeArraySize && indexOf === basicIndexOf;
if (isLarge) {
var cache = createCache(seen);
if (cache) {
indexOf = cacheIndexOf;
seen = cache;
} else {
isLarge = false;
}
}
while (++index < length) {
var value = array[index];
if (indexOf(seen, value) < 0) {
result.push(value);
}
}
if (isLarge) {
releaseObject(seen);
}
return result;
}
/**
* This method is similar to `_.find`, except that it returns the index of
* the element that passes the callback check, instead of the element itself.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to search.
* @param {Function|Object|String} [callback=identity] The function called per
* iteration. If a property name or object is passed, it will be used to create
* a "_.pluck" or "_.where" style callback, respectively.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Mixed} Returns the index of the found element, else `-1`.
* @example
*
* _.findIndex(['apple', 'banana', 'beet'], function(food) {
* return /^b/.test(food);
* });
* // => 1
*/
function findIndex(array, callback, thisArg) {
var index = -1,
length = array ? array.length : 0;
callback = lodash.createCallback(callback, thisArg);
while (++index < length) {
if (callback(array[index], index, array)) {
return index;
}
}
return -1;
}
/**
* Gets the first element of the `array`. If a number `n` is passed, the first
* `n` elements of the `array` are returned. If a `callback` function is passed,
* elements at the beginning of the array are returned as long as the `callback`
* returns truthy. The `callback` is bound to `thisArg` and invoked with three
* arguments; (value, index, array).
*
* If a property name is passed for `callback`, the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is passed for `callback`, the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias head, take
* @category Arrays
* @param {Array} array The array to query.
* @param {Function|Object|Number|String} [callback|n] The function called
* per element or the number of elements to return. If a property name or
* object is passed, it will be used to create a "_.pluck" or "_.where"
* style callback, respectively.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Mixed} Returns the first element(s) of `array`.
* @example
*
* _.first([1, 2, 3]);
* // => 1
*
* _.first([1, 2, 3], 2);
* // => [1, 2]
*
* _.first([1, 2, 3], function(num) {
* return num < 3;
* });
* // => [1, 2]
*
* var food = [
* { 'name': 'banana', 'organic': true },
* { 'name': 'beet', 'organic': false },
* ];
*
* // using "_.pluck" callback shorthand
* _.first(food, 'organic');
* // => [{ 'name': 'banana', 'organic': true }]
*
* var food = [
* { 'name': 'apple', 'type': 'fruit' },
* { 'name': 'banana', 'type': 'fruit' },
* { 'name': 'beet', 'type': 'vegetable' }
* ];
*
* // using "_.where" callback shorthand
* _.first(food, { 'type': 'fruit' });
* // => [{ 'name': 'apple', 'type': 'fruit' }, { 'name': 'banana', 'type': 'fruit' }]
*/
function first(array, callback, thisArg) {
if (array) {
var n = 0,
length = array.length;
if (typeof callback != 'number' && callback != null) {
var index = -1;
callback = lodash.createCallback(callback, thisArg);
while (++index < length && callback(array[index], index, array)) {
n++;
}
} else {
n = callback;
if (n == null || thisArg) {
return array[0];
}
}
return slice(array, 0, nativeMin(nativeMax(0, n), length));
}
}
/**
* Flattens a nested array (the nesting can be to any depth). If `isShallow`
* is truthy, `array` will only be flattened a single level. If `callback`
* is passed, each element of `array` is passed through a `callback` before
* flattening. The `callback` is bound to `thisArg` and invoked with three
* arguments; (value, index, array).
*
* If a property name is passed for `callback`, the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is passed for `callback`, the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to flatten.
* @param {Boolean} [isShallow=false] A flag to indicate only flattening a single level.
* @param {Function|Object|String} [callback=identity] The function called per
* iteration. If a property name or object is passed, it will be used to create
* a "_.pluck" or "_.where" style callback, respectively.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new flattened array.
* @example
*
* _.flatten([1, [2], [3, [[4]]]]);
* // => [1, 2, 3, 4];
*
* _.flatten([1, [2], [3, [[4]]]], true);
* // => [1, 2, 3, [[4]]];
*
* var stooges = [
* { 'name': 'curly', 'quotes': ['Oh, a wise guy, eh?', 'Poifect!'] },
* { 'name': 'moe', 'quotes': ['Spread out!', 'You knucklehead!'] }
* ];
*
* // using "_.pluck" callback shorthand
* _.flatten(stooges, 'quotes');
* // => ['Oh, a wise guy, eh?', 'Poifect!', 'Spread out!', 'You knucklehead!']
*/
var flatten = overloadWrapper(function flatten(array, isShallow, callback) {
var index = -1,
length = array ? array.length : 0,
result = [];
while (++index < length) {
var value = array[index];
if (callback) {
value = callback(value, index, array);
}
// recursively flatten arrays (susceptible to call stack limits)
if (isArray(value)) {
push.apply(result, isShallow ? value : flatten(value));
} else {
result.push(value);
}
}
return result;
});
/**
* Gets the index at which the first occurrence of `value` is found using
* strict equality for comparisons, i.e. `===`. If the `array` is already
* sorted, passing `true` for `fromIndex` will run a faster binary search.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to search.
* @param {Mixed} value The value to search for.
* @param {Boolean|Number} [fromIndex=0] The index to search from or `true` to
* perform a binary search on a sorted `array`.
* @returns {Number} Returns the index of the matched value or `-1`.
* @example
*
* _.indexOf([1, 2, 3, 1, 2, 3], 2);
* // => 1
*
* _.indexOf([1, 2, 3, 1, 2, 3], 2, 3);
* // => 4
*
* _.indexOf([1, 1, 2, 2, 3, 3], 2, true);
* // => 2
*/
function indexOf(array, value, fromIndex) {
if (typeof fromIndex == 'number') {
var length = array ? array.length : 0;
fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0);
} else if (fromIndex) {
var index = sortedIndex(array, value);
return array[index] === value ? index : -1;
}
return array ? basicIndexOf(array, value, fromIndex) : -1;
}
/**
* Gets all but the last element of `array`. If a number `n` is passed, the
* last `n` elements are excluded from the result. If a `callback` function
* is passed, elements at the end of the array are excluded from the result
* as long as the `callback` returns truthy. The `callback` is bound to
* `thisArg` and invoked with three arguments; (value, index, array).
*
* If a property name is passed for `callback`, the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is passed for `callback`, the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to query.
* @param {Function|Object|Number|String} [callback|n=1] The function called
* per element or the number of elements to exclude. If a property name or
* object is passed, it will be used to create a "_.pluck" or "_.where"
* style callback, respectively.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a slice of `array`.
* @example
*
* _.initial([1, 2, 3]);
* // => [1, 2]
*
* _.initial([1, 2, 3], 2);
* // => [1]
*
* _.initial([1, 2, 3], function(num) {
* return num > 1;
* });
* // => [1]
*
* var food = [
* { 'name': 'beet', 'organic': false },
* { 'name': 'carrot', 'organic': true }
* ];
*
* // using "_.pluck" callback shorthand
* _.initial(food, 'organic');
* // => [{ 'name': 'beet', 'organic': false }]
*
* var food = [
* { 'name': 'banana', 'type': 'fruit' },
* { 'name': 'beet', 'type': 'vegetable' },
* { 'name': 'carrot', 'type': 'vegetable' }
* ];
*
* // using "_.where" callback shorthand
* _.initial(food, { 'type': 'vegetable' });
* // => [{ 'name': 'banana', 'type': 'fruit' }]
*/
function initial(array, callback, thisArg) {
if (!array) {
return [];
}
var n = 0,
length = array.length;
if (typeof callback != 'number' && callback != null) {
var index = length;
callback = lodash.createCallback(callback, thisArg);
while (index-- && callback(array[index], index, array)) {
n++;
}
} else {
n = (callback == null || thisArg) ? 1 : callback || n;
}
return slice(array, 0, nativeMin(nativeMax(0, length - n), length));
}
/**
* Computes the intersection of all the passed-in arrays using strict equality
* for comparisons, i.e. `===`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} [array1, array2, ...] Arrays to process.
* @returns {Array} Returns a new array of unique elements that are present
* in **all** of the arrays.
* @example
*
* _.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
* // => [1, 2]
*/
function intersection(array) {
var args = arguments,
argsLength = args.length,
argsIndex = -1,
caches = getArray(),
index = -1,
indexOf = getIndexOf(),
length = array ? array.length : 0,
result = [],
seen = getArray();
while (++argsIndex < argsLength) {
var value = args[argsIndex];
caches[argsIndex] = indexOf === basicIndexOf &&
(value ? value.length : 0) >= largeArraySize &&
createCache(argsIndex ? args[argsIndex] : seen);
}
outer:
while (++index < length) {
var cache = caches[0];
value = array[index];
if ((cache ? cacheIndexOf(cache, value) : indexOf(seen, value)) < 0) {
argsIndex = argsLength;
(cache || seen).push(value);
while (--argsIndex) {
cache = caches[argsIndex];
if ((cache ? cacheIndexOf(cache, value) : indexOf(args[argsIndex], value)) < 0) {
continue outer;
}
}
result.push(value);
}
}
while (argsLength--) {
cache = caches[argsLength];
if (cache) {
releaseObject(cache);
}
}
releaseArray(caches);
releaseArray(seen);
return result;
}
/**
* Gets the last element of the `array`. If a number `n` is passed, the
* last `n` elements of the `array` are returned. If a `callback` function
* is passed, elements at the end of the array are returned as long as the
* `callback` returns truthy. The `callback` is bound to `thisArg` and
* invoked with three arguments;(value, index, array).
*
*
* If a property name is passed for `callback`, the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is passed for `callback`, the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to query.
* @param {Function|Object|Number|String} [callback|n] The function called
* per element or the number of elements to return. If a property name or
* object is passed, it will be used to create a "_.pluck" or "_.where"
* style callback, respectively.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Mixed} Returns the last element(s) of `array`.
* @example
*
* _.last([1, 2, 3]);
* // => 3
*
* _.last([1, 2, 3], 2);
* // => [2, 3]
*
* _.last([1, 2, 3], function(num) {
* return num > 1;
* });
* // => [2, 3]
*
* var food = [
* { 'name': 'beet', 'organic': false },
* { 'name': 'carrot', 'organic': true }
* ];
*
* // using "_.pluck" callback shorthand
* _.last(food, 'organic');
* // => [{ 'name': 'carrot', 'organic': true }]
*
* var food = [
* { 'name': 'banana', 'type': 'fruit' },
* { 'name': 'beet', 'type': 'vegetable' },
* { 'name': 'carrot', 'type': 'vegetable' }
* ];
*
* // using "_.where" callback shorthand
* _.last(food, { 'type': 'vegetable' });
* // => [{ 'name': 'beet', 'type': 'vegetable' }, { 'name': 'carrot', 'type': 'vegetable' }]
*/
function last(array, callback, thisArg) {
if (array) {
var n = 0,
length = array.length;
if (typeof callback != 'number' && callback != null) {
var index = length;
callback = lodash.createCallback(callback, thisArg);
while (index-- && callback(array[index], index, array)) {
n++;
}
} else {
n = callback;
if (n == null || thisArg) {
return array[length - 1];
}
}
return slice(array, nativeMax(0, length - n));
}
}
/**
* Gets the index at which the last occurrence of `value` is found using strict
* equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
* as the offset from the end of the collection.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to search.
* @param {Mixed} value The value to search for.
* @param {Number} [fromIndex=array.length-1] The index to search from.
* @returns {Number} Returns the index of the matched value or `-1`.
* @example
*
* _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
* // => 4
*
* _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3);
* // => 1
*/
function lastIndexOf(array, value, fromIndex) {
var index = array ? array.length : 0;
if (typeof fromIndex == 'number') {
index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1;
}
while (index--) {
if (array[index] === value) {
return index;
}
}
return -1;
}
/**
* Creates an array of numbers (positive and/or negative) progressing from
* `start` up to but not including `end`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Number} [start=0] The start of the range.
* @param {Number} end The end of the range.
* @param {Number} [step=1] The value to increment or decrement by.
* @returns {Array} Returns a new range array.
* @example
*
* _.range(10);
* // => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
*
* _.range(1, 11);
* // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
*
* _.range(0, 30, 5);
* // => [0, 5, 10, 15, 20, 25]
*
* _.range(0, -10, -1);
* // => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
*
* _.range(0);
* // => []
*/
function range(start, end, step) {
start = +start || 0;
step = +step || 1;
if (end == null) {
end = start;
start = 0;
}
// use `Array(length)` so V8 will avoid the slower "dictionary" mode
// http://youtu.be/XAqIpGU8ZZk#t=17m25s
var index = -1,
length = nativeMax(0, ceil((end - start) / step)),
result = Array(length);
while (++index < length) {
result[index] = start;
start += step;
}
return result;
}
/**
* The opposite of `_.initial`, this method gets all but the first value of
* `array`. If a number `n` is passed, the first `n` values are excluded from
* the result. If a `callback` function is passed, elements at the beginning
* of the array are excluded from the result as long as the `callback` returns
* truthy. The `callback` is bound to `thisArg` and invoked with three
* arguments; (value, index, array).
*
* If a property name is passed for `callback`, the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is passed for `callback`, the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias drop, tail
* @category Arrays
* @param {Array} array The array to query.
* @param {Function|Object|Number|String} [callback|n=1] The function called
* per element or the number of elements to exclude. If a property name or
* object is passed, it will be used to create a "_.pluck" or "_.where"
* style callback, respectively.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a slice of `array`.
* @example
*
* _.rest([1, 2, 3]);
* // => [2, 3]
*
* _.rest([1, 2, 3], 2);
* // => [3]
*
* _.rest([1, 2, 3], function(num) {
* return num < 3;
* });
* // => [3]
*
* var food = [
* { 'name': 'banana', 'organic': true },
* { 'name': 'beet', 'organic': false },
* ];
*
* // using "_.pluck" callback shorthand
* _.rest(food, 'organic');
* // => [{ 'name': 'beet', 'organic': false }]
*
* var food = [
* { 'name': 'apple', 'type': 'fruit' },
* { 'name': 'banana', 'type': 'fruit' },
* { 'name': 'beet', 'type': 'vegetable' }
* ];
*
* // using "_.where" callback shorthand
* _.rest(food, { 'type': 'fruit' });
* // => [{ 'name': 'beet', 'type': 'vegetable' }]
*/
function rest(array, callback, thisArg) {
if (typeof callback != 'number' && callback != null) {
var n = 0,
index = -1,
length = array ? array.length : 0;
callback = lodash.createCallback(callback, thisArg);
while (++index < length && callback(array[index], index, array)) {
n++;
}
} else {
n = (callback == null || thisArg) ? 1 : nativeMax(0, callback);
}
return slice(array, n);
}
/**
* Uses a binary search to determine the smallest index at which the `value`
* should be inserted into `array` in order to maintain the sort order of the
* sorted `array`. If `callback` is passed, it will be executed for `value` and
* each element in `array` to compute their sort ranking. The `callback` is
* bound to `thisArg` and invoked with one argument; (value).
*
* If a property name is passed for `callback`, the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is passed for `callback`, the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to inspect.
* @param {Mixed} value The value to evaluate.
* @param {Function|Object|String} [callback=identity] The function called per
* iteration. If a property name or object is passed, it will be used to create
* a "_.pluck" or "_.where" style callback, respectively.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Number} Returns the index at which the value should be inserted
* into `array`.
* @example
*
* _.sortedIndex([20, 30, 50], 40);
* // => 2
*
* // using "_.pluck" callback shorthand
* _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
* // => 2
*
* var dict = {
* 'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 }
* };
*
* _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
* return dict.wordToNumber[word];
* });
* // => 2
*
* _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
* return this.wordToNumber[word];
* }, dict);
* // => 2
*/
function sortedIndex(array, value, callback, thisArg) {
var low = 0,
high = array ? array.length : low;
// explicitly reference `identity` for better inlining in Firefox
callback = callback ? lodash.createCallback(callback, thisArg, 1) : identity;
value = callback(value);
while (low < high) {
var mid = (low + high) >>> 1;
(callback(array[mid]) < value)
? low = mid + 1
: high = mid;
}
return low;
}
/**
* Computes the union of the passed-in arrays using strict equality for
* comparisons, i.e. `===`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} [array1, array2, ...] Arrays to process.
* @returns {Array} Returns a new array of unique values, in order, that are
* present in one or more of the arrays.
* @example
*
* _.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
* // => [1, 2, 3, 101, 10]
*/
function union(array) {
if (!isArray(array)) {
arguments[0] = array ? nativeSlice.call(array) : arrayRef;
}
return uniq(concat.apply(arrayRef, arguments));
}
/**
* Creates a duplicate-value-free version of the `array` using strict equality
* for comparisons, i.e. `===`. If the `array` is already sorted, passing `true`
* for `isSorted` will run a faster algorithm. If `callback` is passed, each
* element of `array` is passed through the `callback` before uniqueness is computed.
* The `callback` is bound to `thisArg` and invoked with three arguments; (value, index, array).
*
* If a property name is passed for `callback`, the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is passed for `callback`, the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias unique
* @category Arrays
* @param {Array} array The array to process.
* @param {Boolean} [isSorted=false] A flag to indicate that the `array` is already sorted.
* @param {Function|Object|String} [callback=identity] The function called per
* iteration. If a property name or object is passed, it will be used to create
* a "_.pluck" or "_.where" style callback, respectively.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a duplicate-value-free array.
* @example
*
* _.uniq([1, 2, 1, 3, 1]);
* // => [1, 2, 3]
*
* _.uniq([1, 1, 2, 2, 3], true);
* // => [1, 2, 3]
*
* _.uniq(['A', 'b', 'C', 'a', 'B', 'c'], function(letter) { return letter.toLowerCase(); });
* // => ['A', 'b', 'C']
*
* _.uniq([1, 2.5, 3, 1.5, 2, 3.5], function(num) { return this.floor(num); }, Math);
* // => [1, 2.5, 3]
*
* // using "_.pluck" callback shorthand
* _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
* // => [{ 'x': 1 }, { 'x': 2 }]
*/
var uniq = overloadWrapper(function(array, isSorted, callback) {
var index = -1,
indexOf = getIndexOf(),
length = array ? array.length : 0,
result = [];
var isLarge = !isSorted && length >= largeArraySize && indexOf === basicIndexOf,
seen = (callback || isLarge) ? getArray() : result;
if (isLarge) {
var cache = createCache(seen);
if (cache) {
indexOf = cacheIndexOf;
seen = cache;
} else {
isLarge = false;
seen = callback ? seen : (releaseArray(seen), result);
}
}
while (++index < length) {
var value = array[index],
computed = callback ? callback(value, index, array) : value;
if (isSorted
? !index || seen[seen.length - 1] !== computed
: indexOf(seen, computed) < 0
) {
if (callback || isLarge) {
seen.push(computed);
}
result.push(value);
}
}
if (isLarge) {
releaseArray(seen.array);
releaseObject(seen);
} else if (callback) {
releaseArray(seen);
}
return result;
});
/**
* The inverse of `_.zip`, this method splits groups of elements into arrays
* composed of elements from each group at their corresponding indexes.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to process.
* @returns {Array} Returns a new array of the composed arrays.
* @example
*
* _.unzip([['moe', 30, true], ['larry', 40, false]]);
* // => [['moe', 'larry'], [30, 40], [true, false]];
*/
function unzip(array) {
var index = -1,
length = array ? max(pluck(array, 'length')) : 0,
result = Array(length < 0 ? 0 : length);
while (++index < length) {
result[index] = pluck(array, index);
}
return result;
}
/**
* Creates an array with all occurrences of the passed values removed using
* strict equality for comparisons, i.e. `===`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to filter.
* @param {Mixed} [value1, value2, ...] Values to remove.
* @returns {Array} Returns a new filtered array.
* @example
*
* _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
* // => [2, 3, 4]
*/
function without(array) {
return difference(array, nativeSlice.call(arguments, 1));
}
/**
* Groups the elements of each array at their corresponding indexes. Useful for
* separate data sources that are coordinated through matching array indexes.
* For a matrix of nested arrays, `_.zip.apply(...)` can transpose the matrix
* in a similar fashion.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} [array1, array2, ...] Arrays to process.
* @returns {Array} Returns a new array of grouped elements.
* @example
*
* _.zip(['moe', 'larry'], [30, 40], [true, false]);
* // => [['moe', 30, true], ['larry', 40, false]]
*/
function zip(array) {
return array ? unzip(arguments) : [];
}
/**
* Creates an object composed from arrays of `keys` and `values`. Pass either
* a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`, or
* two arrays, one of `keys` and one of corresponding `values`.
*
* @static
* @memberOf _
* @alias object
* @category Arrays
* @param {Array} keys The array of keys.
* @param {Array} [values=[]] The array of values.
* @returns {Object} Returns an object composed of the given keys and
* corresponding values.
* @example
*
* _.zipObject(['moe', 'larry'], [30, 40]);
* // => { 'moe': 30, 'larry': 40 }
*/
function zipObject(keys, values) {
var index = -1,
length = keys ? keys.length : 0,
result = {};
while (++index < length) {
var key = keys[index];
if (values) {
result[key] = values[index];
} else {
result[key[0]] = key[1];
}
}
return result;
}
/*--------------------------------------------------------------------------*/
/**
* If `n` is greater than `0`, a function is created that is restricted to
* executing `func`, with the `this` binding and arguments of the created
* function, only after it is called `n` times. If `n` is less than `1`,
* `func` is executed immediately, without a `this` binding or additional
* arguments, and its result is returned.
*
* @static
* @memberOf _
* @category Functions
* @param {Number} n The number of times the function must be called before
* it is executed.
* @param {Function} func The function to restrict.
* @returns {Function} Returns the new restricted function.
* @example
*
* var renderNotes = _.after(notes.length, render);
* _.forEach(notes, function(note) {
* note.asyncSave({ 'success': renderNotes });
* });
* // `renderNotes` is run once, after all notes have saved
*/
function after(n, func) {
if (n < 1) {
return func();
}
return function() {
if (--n < 1) {
return func.apply(this, arguments);
}
};
}
/**
* Creates a function that, when called, invokes `func` with the `this`
* binding of `thisArg` and prepends any additional `bind` arguments to those
* passed to the bound function.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to bind.
* @param {Mixed} [thisArg] The `this` binding of `func`.
* @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
* @returns {Function} Returns the new bound function.
* @example
*
* var func = function(greeting) {
* return greeting + ' ' + this.name;
* };
*
* func = _.bind(func, { 'name': 'moe' }, 'hi');
* func();
* // => 'hi moe'
*/
function bind(func, thisArg) {
// use `Function#bind` if it exists and is fast
// (in V8 `Function#bind` is slower except when partially applied)
return support.fastBind || (nativeBind && arguments.length > 2)
? nativeBind.call.apply(nativeBind, arguments)
: createBound(func, thisArg, nativeSlice.call(arguments, 2));
}
/**
* Binds methods on `object` to `object`, overwriting the existing method.
* Method names may be specified as individual arguments or as arrays of method
* names. If no method names are provided, all the function properties of `object`
* will be bound.
*
* @static
* @memberOf _
* @category Functions
* @param {Object} object The object to bind and assign the bound methods to.
* @param {String} [methodName1, methodName2, ...] Method names on the object to bind.
* @returns {Object} Returns `object`.
* @example
*
* var view = {
* 'label': 'docs',
* 'onClick': function() { alert('clicked ' + this.label); }
* };
*
* _.bindAll(view);
* jQuery('#docs').on('click', view.onClick);
* // => alerts 'clicked docs', when the button is clicked
*/
function bindAll(object) {
var funcs = arguments.length > 1 ? concat.apply(arrayRef, nativeSlice.call(arguments, 1)) : functions(object),
index = -1,
length = funcs.length;
while (++index < length) {
var key = funcs[index];
object[key] = bind(object[key], object);
}
return object;
}
/**
* Creates a function that, when called, invokes the method at `object[key]`
* and prepends any additional `bindKey` arguments to those passed to the bound
* function. This method differs from `_.bind` by allowing bound functions to
* reference methods that will be redefined or don't yet exist.
* See http://michaux.ca/articles/lazy-function-definition-pattern.
*
* @static
* @memberOf _
* @category Functions
* @param {Object} object The object the method belongs to.
* @param {String} key The key of the method.
* @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
* @returns {Function} Returns the new bound function.
* @example
*
* var object = {
* 'name': 'moe',
* 'greet': function(greeting) {
* return greeting + ' ' + this.name;
* }
* };
*
* var func = _.bindKey(object, 'greet', 'hi');
* func();
* // => 'hi moe'
*
* object.greet = function(greeting) {
* return greeting + ', ' + this.name + '!';
* };
*
* func();
* // => 'hi, moe!'
*/
function bindKey(object, key) {
return createBound(object, key, nativeSlice.call(arguments, 2), indicatorObject);
}
/**
* Creates a function that is the composition of the passed functions,
* where each function consumes the return value of the function that follows.
* For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`.
* Each function is executed with the `this` binding of the composed function.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} [func1, func2, ...] Functions to compose.
* @returns {Function} Returns the new composed function.
* @example
*
* var greet = function(name) { return 'hi ' + name; };
* var exclaim = function(statement) { return statement + '!'; };
* var welcome = _.compose(exclaim, greet);
* welcome('moe');
* // => 'hi moe!'
*/
function compose() {
var funcs = arguments;
return function() {
var args = arguments,
length = funcs.length;
while (length--) {
args = [funcs[length].apply(this, args)];
}
return args[0];
};
}
/**
* Produces a callback bound to an optional `thisArg`. If `func` is a property
* name, the created callback will return the property value for a given element.
* If `func` is an object, the created callback will return `true` for elements
* that contain the equivalent object properties, otherwise it will return `false`.
*
* Note: All Lo-Dash methods, that accept a `callback` argument, use `_.createCallback`.
*
* @static
* @memberOf _
* @category Functions
* @param {Mixed} [func=identity] The value to convert to a callback.
* @param {Mixed} [thisArg] The `this` binding of the created callback.
* @param {Number} [argCount=3] The number of arguments the callback accepts.
* @returns {Function} Returns a callback function.
* @example
*
* var stooges = [
* { 'name': 'moe', 'age': 40 },
* { 'name': 'larry', 'age': 50 }
* ];
*
* // wrap to create custom callback shorthands
* _.createCallback = _.wrap(_.createCallback, function(func, callback, thisArg) {
* var match = /^(.+?)__([gl]t)(.+)$/.exec(callback);
* return !match ? func(callback, thisArg) : function(object) {
* return match[2] == 'gt' ? object[match[1]] > match[3] : object[match[1]] < match[3];
* };
* });
*
* _.filter(stooges, 'age__gt45');
* // => [{ 'name': 'larry', 'age': 50 }]
*
* // create mixins with support for "_.pluck" and "_.where" callback shorthands
* _.mixin({
* 'toLookup': function(collection, callback, thisArg) {
* callback = _.createCallback(callback, thisArg);
* return _.reduce(collection, function(result, value, index, collection) {
* return (result[callback(value, index, collection)] = value, result);
* }, {});
* }
* });
*
* _.toLookup(stooges, 'name');
* // => { 'moe': { 'name': 'moe', 'age': 40 }, 'larry': { 'name': 'larry', 'age': 50 } }
*/
function createCallback(func, thisArg, argCount) {
if (func == null) {
return identity;
}
var type = typeof func;
if (type != 'function') {
if (type != 'object') {
return function(object) {
return object[func];
};
}
var props = keys(func);
return function(object) {
var length = props.length,
result = false;
while (length--) {
if (!(result = isEqual(object[props[length]], func[props[length]], indicatorObject))) {
break;
}
}
return result;
};
}
if (typeof thisArg == 'undefined' || (reThis && !reThis.test(fnToString.call(func)))) {
return func;
}
if (argCount === 1) {
return function(value) {
return func.call(thisArg, value);
};
}
if (argCount === 2) {
return function(a, b) {
return func.call(thisArg, a, b);
};
}
if (argCount === 4) {
return function(accumulator, value, index, collection) {
return func.call(thisArg, accumulator, value, index, collection);
};
}
return function(value, index, collection) {
return func.call(thisArg, value, index, collection);
};
}
/**
* Creates a function that will delay the execution of `func` until after
* `wait` milliseconds have elapsed since the last time it was invoked. Pass
* an `options` object to indicate that `func` should be invoked on the leading
* and/or trailing edge of the `wait` timeout. Subsequent calls to the debounced
* function will return the result of the last `func` call.
*
* Note: If `leading` and `trailing` options are `true`, `func` will be called
* on the trailing edge of the timeout only if the the debounced function is
* invoked more than once during the `wait` timeout.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to debounce.
* @param {Number} wait The number of milliseconds to delay.
* @param {Object} options The options object.
* [leading=false] A boolean to specify execution on the leading edge of the timeout.
* [maxWait] The maximum time `func` is allowed to be delayed before it's called.
* [trailing=true] A boolean to specify execution on the trailing edge of the timeout.
* @returns {Function} Returns the new debounced function.
* @example
*
* var lazyLayout = _.debounce(calculateLayout, 300);
* jQuery(window).on('resize', lazyLayout);
*
* jQuery('#postbox').on('click', _.debounce(sendMail, 200, {
* 'leading': true,
* 'trailing': false
* });
*/
function debounce(func, wait, options) {
var args,
result,
thisArg,
callCount = 0,
lastCalled = 0,
maxWait = false,
maxTimeoutId = null,
timeoutId = null,
trailing = true;
function clear() {
clearTimeout(maxTimeoutId);
clearTimeout(timeoutId);
callCount = 0;
maxTimeoutId = timeoutId = null;
}
function delayed() {
var isCalled = trailing && (!leading || callCount > 1);
clear();
if (isCalled) {
if (maxWait !== false) {
lastCalled = new Date;
}
result = func.apply(thisArg, args);
}
}
function maxDelayed() {
clear();
if (trailing || (maxWait !== wait)) {
lastCalled = new Date;
result = func.apply(thisArg, args);
}
}
wait = nativeMax(0, wait || 0);
if (options === true) {
var leading = true;
trailing = false;
} else if (isObject(options)) {
leading = options.leading;
maxWait = 'maxWait' in options && nativeMax(wait, options.maxWait || 0);
trailing = 'trailing' in options ? options.trailing : trailing;
}
return function() {
args = arguments;
thisArg = this;
callCount++;
// avoid issues with Titanium and `undefined` timeout ids
// https://github.com/appcelerator/titanium_mobile/blob/3_1_0_GA/android/titanium/src/java/ti/modules/titanium/TitaniumModule.java#L185-L192
clearTimeout(timeoutId);
if (maxWait === false) {
if (leading && callCount < 2) {
result = func.apply(thisArg, args);
}
} else {
var now = new Date;
if (!maxTimeoutId && !leading) {
lastCalled = now;
}
var remaining = maxWait - (now - lastCalled);
if (remaining <= 0) {
clearTimeout(maxTimeoutId);
maxTimeoutId = null;
lastCalled = now;
result = func.apply(thisArg, args);
}
else if (!maxTimeoutId) {
maxTimeoutId = setTimeout(maxDelayed, remaining);
}
}
if (wait !== maxWait) {
timeoutId = setTimeout(delayed, wait);
}
return result;
};
}
/**
* Defers executing the `func` function until the current call stack has cleared.
* Additional arguments will be passed to `func` when it is invoked.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to defer.
* @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with.
* @returns {Number} Returns the timer id.
* @example
*
* _.defer(function() { alert('deferred'); });
* // returns from the function before `alert` is called
*/
function defer(func) {
var args = nativeSlice.call(arguments, 1);
return setTimeout(function() { func.apply(undefined, args); }, 1);
}
// use `setImmediate` if it's available in Node.js
if (isV8 && freeModule && typeof setImmediate == 'function') {
defer = bind(setImmediate, context);
}
/**
* Executes the `func` function after `wait` milliseconds. Additional arguments
* will be passed to `func` when it is invoked.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to delay.
* @param {Number} wait The number of milliseconds to delay execution.
* @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with.
* @returns {Number} Returns the timer id.
* @example
*
* var log = _.bind(console.log, console);
* _.delay(log, 1000, 'logged later');
* // => 'logged later' (Appears after one second.)
*/
function delay(func, wait) {
var args = nativeSlice.call(arguments, 2);
return setTimeout(function() { func.apply(undefined, args); }, wait);
}
/**
* Creates a function that memoizes the result of `func`. If `resolver` is
* passed, it will be used to determine the cache key for storing the result
* based on the arguments passed to the memoized function. By default, the first
* argument passed to the memoized function is used as the cache key. The `func`
* is executed with the `this` binding of the memoized function. The result
* cache is exposed as the `cache` property on the memoized function.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to have its output memoized.
* @param {Function} [resolver] A function used to resolve the cache key.
* @returns {Function} Returns the new memoizing function.
* @example
*
* var fibonacci = _.memoize(function(n) {
* return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
* });
*/
function memoize(func, resolver) {
function memoized() {
var cache = memoized.cache,
key = keyPrefix + (resolver ? resolver.apply(this, arguments) : arguments[0]);
return hasOwnProperty.call(cache, key)
? cache[key]
: (cache[key] = func.apply(this, arguments));
}
memoized.cache = {};
return memoized;
}
/**
* Creates a function that is restricted to execute `func` once. Repeat calls to
* the function will return the value of the first call. The `func` is executed
* with the `this` binding of the created function.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to restrict.
* @returns {Function} Returns the new restricted function.
* @example
*
* var initialize = _.once(createApplication);
* initialize();
* initialize();
* // `initialize` executes `createApplication` once
*/
function once(func) {
var ran,
result;
return function() {
if (ran) {
return result;
}
ran = true;
result = func.apply(this, arguments);
// clear the `func` variable so the function may be garbage collected
func = null;
return result;
};
}
/**
* Creates a function that, when called, invokes `func` with any additional
* `partial` arguments prepended to those passed to the new function. This
* method is similar to `_.bind`, except it does **not** alter the `this` binding.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to partially apply arguments to.
* @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
* @returns {Function} Returns the new partially applied function.
* @example
*
* var greet = function(greeting, name) { return greeting + ' ' + name; };
* var hi = _.partial(greet, 'hi');
* hi('moe');
* // => 'hi moe'
*/
function partial(func) {
return createBound(func, nativeSlice.call(arguments, 1));
}
/**
* This method is similar to `_.partial`, except that `partial` arguments are
* appended to those passed to the new function.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to partially apply arguments to.
* @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied.
* @returns {Function} Returns the new partially applied function.
* @example
*
* var defaultsDeep = _.partialRight(_.merge, _.defaults);
*
* var options = {
* 'variable': 'data',
* 'imports': { 'jq': $ }
* };
*
* defaultsDeep(options, _.templateSettings);
*
* options.variable
* // => 'data'
*
* options.imports
* // => { '_': _, 'jq': $ }
*/
function partialRight(func) {
return createBound(func, nativeSlice.call(arguments, 1), null, indicatorObject);
}
/**
* Creates a function that, when executed, will only call the `func` function
* at most once per every `wait` milliseconds. Pass an `options` object to
* indicate that `func` should be invoked on the leading and/or trailing edge
* of the `wait` timeout. Subsequent calls to the throttled function will
* return the result of the last `func` call.
*
* Note: If `leading` and `trailing` options are `true`, `func` will be called
* on the trailing edge of the timeout only if the the throttled function is
* invoked more than once during the `wait` timeout.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to throttle.
* @param {Number} wait The number of milliseconds to throttle executions to.
* @param {Object} options The options object.
* [leading=true] A boolean to specify execution on the leading edge of the timeout.
* [trailing=true] A boolean to specify execution on the trailing edge of the timeout.
* @returns {Function} Returns the new throttled function.
* @example
*
* var throttled = _.throttle(updatePosition, 100);
* jQuery(window).on('scroll', throttled);
*
* jQuery('.interactive').on('click', _.throttle(renewToken, 300000, {
* 'trailing': false
* }));
*/
function throttle(func, wait, options) {
var leading = true,
trailing = true;
if (options === false) {
leading = false;
} else if (isObject(options)) {
leading = 'leading' in options ? options.leading : leading;
trailing = 'trailing' in options ? options.trailing : trailing;
}
options = getObject();
options.leading = leading;
options.maxWait = wait;
options.trailing = trailing;
var result = debounce(func, wait, options);
releaseObject(options);
return result;
}
/**
* Creates a function that passes `value` to the `wrapper` function as its
* first argument. Additional arguments passed to the function are appended
* to those passed to the `wrapper` function. The `wrapper` is executed with
* the `this` binding of the created function.
*
* @static
* @memberOf _
* @category Functions
* @param {Mixed} value The value to wrap.
* @param {Function} wrapper The wrapper function.
* @returns {Function} Returns the new function.
* @example
*
* var hello = function(name) { return 'hello ' + name; };
* hello = _.wrap(hello, function(func) {
* return 'before, ' + func('moe') + ', after';
* });
* hello();
* // => 'before, hello moe, after'
*/
function wrap(value, wrapper) {
return function() {
var args = [value];
push.apply(args, arguments);
return wrapper.apply(this, args);
};
}
/*--------------------------------------------------------------------------*/
/**
* Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their
* corresponding HTML entities.
*
* @static
* @memberOf _
* @category Utilities
* @param {String} string The string to escape.
* @returns {String} Returns the escaped string.
* @example
*
* _.escape('Moe, Larry & Curly');
* // => 'Moe, Larry &amp; Curly'
*/
function escape(string) {
return string == null ? '' : String(string).replace(reUnescapedHtml, escapeHtmlChar);
}
/**
* This method returns the first argument passed to it.
*
* @static
* @memberOf _
* @category Utilities
* @param {Mixed} value Any value.
* @returns {Mixed} Returns `value`.
* @example
*
* var moe = { 'name': 'moe' };
* moe === _.identity(moe);
* // => true
*/
function identity(value) {
return value;
}
/**
* Adds functions properties of `object` to the `lodash` function and chainable
* wrapper.
*
* @static
* @memberOf _
* @category Utilities
* @param {Object} object The object of function properties to add to `lodash`.
* @example
*
* _.mixin({
* 'capitalize': function(string) {
* return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
* }
* });
*
* _.capitalize('moe');
* // => 'Moe'
*
* _('moe').capitalize();
* // => 'Moe'
*/
function mixin(object) {
forEach(functions(object), function(methodName) {
var func = lodash[methodName] = object[methodName];
lodash.prototype[methodName] = function() {
var value = this.__wrapped__,
args = [value];
push.apply(args, arguments);
var result = func.apply(lodash, args);
return (value && typeof value == 'object' && value === result)
? this
: new lodashWrapper(result);
};
});
}
/**
* Reverts the '_' variable to its previous value and returns a reference to
* the `lodash` function.
*
* @static
* @memberOf _
* @category Utilities
* @returns {Function} Returns the `lodash` function.
* @example
*
* var lodash = _.noConflict();
*/
function noConflict() {
context._ = oldDash;
return this;
}
/**
* Converts the given `value` into an integer of the specified `radix`.
* If `radix` is `undefined` or `0`, a `radix` of `10` is used unless the
* `value` is a hexadecimal, in which case a `radix` of `16` is used.
*
* Note: This method avoids differences in native ES3 and ES5 `parseInt`
* implementations. See http://es5.github.com/#E.
*
* @static
* @memberOf _
* @category Utilities
* @param {String} value The value to parse.
* @param {Number} [radix] The radix used to interpret the value to parse.
* @returns {Number} Returns the new integer value.
* @example
*
* _.parseInt('08');
* // => 8
*/
var parseInt = nativeParseInt(whitespace + '08') == 8 ? nativeParseInt : function(value, radix) {
// Firefox and Opera still follow the ES3 specified implementation of `parseInt`
return nativeParseInt(isString(value) ? value.replace(reLeadingSpacesAndZeros, '') : value, radix || 0);
};
/**
* Produces a random number between `min` and `max` (inclusive). If only one
* argument is passed, a number between `0` and the given number will be returned.
*
* @static
* @memberOf _
* @category Utilities
* @param {Number} [min=0] The minimum possible value.
* @param {Number} [max=1] The maximum possible value.
* @returns {Number} Returns a random number.
* @example
*
* _.random(0, 5);
* // => a number between 0 and 5
*
* _.random(5);
* // => also a number between 0 and 5
*/
function random(min, max) {
if (min == null && max == null) {
max = 1;
}
min = +min || 0;
if (max == null) {
max = min;
min = 0;
} else {
max = +max || 0;
}
var rand = nativeRandom();
return (min % 1 || max % 1)
? min + nativeMin(rand * (max - min + parseFloat('1e-' + ((rand +'').length - 1))), max)
: min + floor(rand * (max - min + 1));
}
/**
* Resolves the value of `property` on `object`. If `property` is a function,
* it will be invoked with the `this` binding of `object` and its result returned,
* else the property value is returned. If `object` is falsey, then `undefined`
* is returned.
*
* @static
* @memberOf _
* @category Utilities
* @param {Object} object The object to inspect.
* @param {String} property The property to get the value of.
* @returns {Mixed} Returns the resolved value.
* @example
*
* var object = {
* 'cheese': 'crumpets',
* 'stuff': function() {
* return 'nonsense';
* }
* };
*
* _.result(object, 'cheese');
* // => 'crumpets'
*
* _.result(object, 'stuff');
* // => 'nonsense'
*/
function result(object, property) {
var value = object ? object[property] : undefined;
return isFunction(value) ? object[property]() : value;
}
/**
* A micro-templating method that handles arbitrary delimiters, preserves
* whitespace, and correctly escapes quotes within interpolated code.
*
* Note: In the development build, `_.template` utilizes sourceURLs for easier
* debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
*
* For more information on precompiling templates see:
* http://lodash.com/#custom-builds
*
* For more information on Chrome extension sandboxes see:
* http://developer.chrome.com/stable/extensions/sandboxingEval.html
*
* @static
* @memberOf _
* @category Utilities
* @param {String} text The template text.
* @param {Object} data The data object used to populate the text.
* @param {Object} options The options object.
* escape - The "escape" delimiter regexp.
* evaluate - The "evaluate" delimiter regexp.
* interpolate - The "interpolate" delimiter regexp.
* sourceURL - The sourceURL of the template's compiled source.
* variable - The data object variable name.
* @returns {Function|String} Returns a compiled function when no `data` object
* is given, else it returns the interpolated text.
* @example
*
* // using a compiled template
* var compiled = _.template('hello <%= name %>');
* compiled({ 'name': 'moe' });
* // => 'hello moe'
*
* var list = '<% _.forEach(people, function(name) { %><li><%= name %></li><% }); %>';
* _.template(list, { 'people': ['moe', 'larry'] });
* // => '<li>moe</li><li>larry</li>'
*
* // using the "escape" delimiter to escape HTML in data property values
* _.template('<b><%- value %></b>', { 'value': '<script>' });
* // => '<b>&lt;script&gt;</b>'
*
* // using the ES6 delimiter as an alternative to the default "interpolate" delimiter
* _.template('hello ${ name }', { 'name': 'curly' });
* // => 'hello curly'
*
* // using the internal `print` function in "evaluate" delimiters
* _.template('<% print("hello " + epithet); %>!', { 'epithet': 'stooge' });
* // => 'hello stooge!'
*
* // using custom template delimiters
* _.templateSettings = {
* 'interpolate': /{{([\s\S]+?)}}/g
* };
*
* _.template('hello {{ name }}!', { 'name': 'mustache' });
* // => 'hello mustache!'
*
* // using the `sourceURL` option to specify a custom sourceURL for the template
* var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' });
* compiled(data);
* // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
*
* // using the `variable` option to ensure a with-statement isn't used in the compiled template
* var compiled = _.template('hi <%= data.name %>!', null, { 'variable': 'data' });
* compiled.source;
* // => function(data) {
* var __t, __p = '', __e = _.escape;
* __p += 'hi ' + ((__t = ( data.name )) == null ? '' : __t) + '!';
* return __p;
* }
*
* // using the `source` property to inline compiled templates for meaningful
* // line numbers in error messages and a stack trace
* fs.writeFileSync(path.join(cwd, 'jst.js'), '\
* var JST = {\
* "main": ' + _.template(mainText).source + '\
* };\
* ');
*/
function template(text, data, options) {
// based on John Resig's `tmpl` implementation
// http://ejohn.org/blog/javascript-micro-templating/
// and Laura Doktorova's doT.js
// https://github.com/olado/doT
var settings = lodash.templateSettings;
text || (text = '');
// avoid missing dependencies when `iteratorTemplate` is not defined
options = defaults({}, options, settings);
var imports = defaults({}, options.imports, settings.imports),
importsKeys = keys(imports),
importsValues = values(imports);
var isEvaluating,
index = 0,
interpolate = options.interpolate || reNoMatch,
source = "__p += '";
// compile the regexp to match each delimiter
var reDelimiters = RegExp(
(options.escape || reNoMatch).source + '|' +
interpolate.source + '|' +
(interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
(options.evaluate || reNoMatch).source + '|$'
, 'g');
text.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
interpolateValue || (interpolateValue = esTemplateValue);
// escape characters that cannot be included in string literals
source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar);
// replace delimiters with snippets
if (escapeValue) {
source += "' +\n__e(" + escapeValue + ") +\n'";
}
if (evaluateValue) {
isEvaluating = true;
source += "';\n" + evaluateValue + ";\n__p += '";
}
if (interpolateValue) {
source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
}
index = offset + match.length;
// the JS engine embedded in Adobe products requires returning the `match`
// string in order to produce the correct `offset` value
return match;
});
source += "';\n";
// if `variable` is not specified, wrap a with-statement around the generated
// code to add the data object to the top of the scope chain
var variable = options.variable,
hasVariable = variable;
if (!hasVariable) {
variable = 'obj';
source = 'with (' + variable + ') {\n' + source + '\n}\n';
}
// cleanup code by stripping empty strings
source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
.replace(reEmptyStringMiddle, '$1')
.replace(reEmptyStringTrailing, '$1;');
// frame code as the function body
source = 'function(' + variable + ') {\n' +
(hasVariable ? '' : variable + ' || (' + variable + ' = {});\n') +
"var __t, __p = '', __e = _.escape" +
(isEvaluating
? ', __j = Array.prototype.join;\n' +
"function print() { __p += __j.call(arguments, '') }\n"
: ';\n'
) +
source +
'return __p\n}';
// Use a sourceURL for easier debugging and wrap in a multi-line comment to
// avoid issues with Narwhal, IE conditional compilation, and the JS engine
// embedded in Adobe products.
// http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
var sourceURL = '\n/*\n//@ sourceURL=' + (options.sourceURL || '/lodash/template/source[' + (templateCounter++) + ']') + '\n*/';
try {
var result = Function(importsKeys, 'return ' + source + sourceURL).apply(undefined, importsValues);
} catch(e) {
e.source = source;
throw e;
}
if (data) {
return result(data);
}
// provide the compiled function's source via its `toString` method, in
// supported environments, or the `source` property as a convenience for
// inlining compiled templates during the build process
result.source = source;
return result;
}
/**
* Executes the `callback` function `n` times, returning an array of the results
* of each `callback` execution. The `callback` is bound to `thisArg` and invoked
* with one argument; (index).
*
* @static
* @memberOf _
* @category Utilities
* @param {Number} n The number of times to execute the callback.
* @param {Function} callback The function called per iteration.
* @param {Mixed} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new array of the results of each `callback` execution.
* @example
*
* var diceRolls = _.times(3, _.partial(_.random, 1, 6));
* // => [3, 6, 4]
*
* _.times(3, function(n) { mage.castSpell(n); });
* // => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively
*
* _.times(3, function(n) { this.cast(n); }, mage);
* // => also calls `mage.castSpell(n)` three times
*/
function times(n, callback, thisArg) {
n = (n = +n) > -1 ? n : 0;
var index = -1,
result = Array(n);
callback = lodash.createCallback(callback, thisArg, 1);
while (++index < n) {
result[index] = callback(index);
}
return result;
}
/**
* The inverse of `_.escape`, this method converts the HTML entities
* `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to their
* corresponding characters.
*
* @static
* @memberOf _
* @category Utilities
* @param {String} string The string to unescape.
* @returns {String} Returns the unescaped string.
* @example
*
* _.unescape('Moe, Larry &amp; Curly');
* // => 'Moe, Larry & Curly'
*/
function unescape(string) {
return string == null ? '' : String(string).replace(reEscapedHtml, unescapeHtmlChar);
}
/**
* Generates a unique ID. If `prefix` is passed, the ID will be appended to it.
*
* @static
* @memberOf _
* @category Utilities
* @param {String} [prefix] The value to prefix the ID with.
* @returns {String} Returns the unique ID.
* @example
*
* _.uniqueId('contact_');
* // => 'contact_104'
*
* _.uniqueId();
* // => '105'
*/
function uniqueId(prefix) {
var id = ++idCounter;
return String(prefix == null ? '' : prefix) + id;
}
/*--------------------------------------------------------------------------*/
/**
* Invokes `interceptor` with the `value` as the first argument, and then
* returns `value`. The purpose of this method is to "tap into" a method chain,
* in order to perform operations on intermediate results within the chain.
*
* @static
* @memberOf _
* @category Chaining
* @param {Mixed} value The value to pass to `interceptor`.
* @param {Function} interceptor The function to invoke.
* @returns {Mixed} Returns `value`.
* @example
*
* _([1, 2, 3, 4])
* .filter(function(num) { return num % 2 == 0; })
* .tap(alert)
* .map(function(num) { return num * num; })
* .value();
* // => // [2, 4] (alerted)
* // => [4, 16]
*/
function tap(value, interceptor) {
interceptor(value);
return value;
}
/**
* Produces the `toString` result of the wrapped value.
*
* @name toString
* @memberOf _
* @category Chaining
* @returns {String} Returns the string result.
* @example
*
* _([1, 2, 3]).toString();
* // => '1,2,3'
*/
function wrapperToString() {
return String(this.__wrapped__);
}
/**
* Extracts the wrapped value.
*
* @name valueOf
* @memberOf _
* @alias value
* @category Chaining
* @returns {Mixed} Returns the wrapped value.
* @example
*
* _([1, 2, 3]).valueOf();
* // => [1, 2, 3]
*/
function wrapperValueOf() {
return this.__wrapped__;
}
/*--------------------------------------------------------------------------*/
// add functions that return wrapped values when chaining
lodash.after = after;
lodash.assign = assign;
lodash.at = at;
lodash.bind = bind;
lodash.bindAll = bindAll;
lodash.bindKey = bindKey;
lodash.compact = compact;
lodash.compose = compose;
lodash.countBy = countBy;
lodash.createCallback = createCallback;
lodash.debounce = debounce;
lodash.defaults = defaults;
lodash.defer = defer;
lodash.delay = delay;
lodash.difference = difference;
lodash.filter = filter;
lodash.flatten = flatten;
lodash.forEach = forEach;
lodash.forIn = forIn;
lodash.forOwn = forOwn;
lodash.functions = functions;
lodash.groupBy = groupBy;
lodash.initial = initial;
lodash.intersection = intersection;
lodash.invert = invert;
lodash.invoke = invoke;
lodash.keys = keys;
lodash.map = map;
lodash.max = max;
lodash.memoize = memoize;
lodash.merge = merge;
lodash.min = min;
lodash.omit = omit;
lodash.once = once;
lodash.pairs = pairs;
lodash.partial = partial;
lodash.partialRight = partialRight;
lodash.pick = pick;
lodash.pluck = pluck;
lodash.range = range;
lodash.reject = reject;
lodash.rest = rest;
lodash.shuffle = shuffle;
lodash.sortBy = sortBy;
lodash.tap = tap;
lodash.throttle = throttle;
lodash.times = times;
lodash.toArray = toArray;
lodash.transform = transform;
lodash.union = union;
lodash.uniq = uniq;
lodash.unzip = unzip;
lodash.values = values;
lodash.where = where;
lodash.without = without;
lodash.wrap = wrap;
lodash.zip = zip;
lodash.zipObject = zipObject;
// add aliases
lodash.collect = map;
lodash.drop = rest;
lodash.each = forEach;
lodash.extend = assign;
lodash.methods = functions;
lodash.object = zipObject;
lodash.select = filter;
lodash.tail = rest;
lodash.unique = uniq;
// add functions to `lodash.prototype`
mixin(lodash);
// add Underscore compat
lodash.chain = lodash;
lodash.prototype.chain = function() { return this; };
/*--------------------------------------------------------------------------*/
// add functions that return unwrapped values when chaining
lodash.clone = clone;
lodash.cloneDeep = cloneDeep;
lodash.contains = contains;
lodash.escape = escape;
lodash.every = every;
lodash.find = find;
lodash.findIndex = findIndex;
lodash.findKey = findKey;
lodash.has = has;
lodash.identity = identity;
lodash.indexOf = indexOf;
lodash.isArguments = isArguments;
lodash.isArray = isArray;
lodash.isBoolean = isBoolean;
lodash.isDate = isDate;
lodash.isElement = isElement;
lodash.isEmpty = isEmpty;
lodash.isEqual = isEqual;
lodash.isFinite = isFinite;
lodash.isFunction = isFunction;
lodash.isNaN = isNaN;
lodash.isNull = isNull;
lodash.isNumber = isNumber;
lodash.isObject = isObject;
lodash.isPlainObject = isPlainObject;
lodash.isRegExp = isRegExp;
lodash.isString = isString;
lodash.isUndefined = isUndefined;
lodash.lastIndexOf = lastIndexOf;
lodash.mixin = mixin;
lodash.noConflict = noConflict;
lodash.parseInt = parseInt;
lodash.random = random;
lodash.reduce = reduce;
lodash.reduceRight = reduceRight;
lodash.result = result;
lodash.runInContext = runInContext;
lodash.size = size;
lodash.some = some;
lodash.sortedIndex = sortedIndex;
lodash.template = template;
lodash.unescape = unescape;
lodash.uniqueId = uniqueId;
// add aliases
lodash.all = every;
lodash.any = some;
lodash.detect = find;
lodash.findWhere = find;
lodash.foldl = reduce;
lodash.foldr = reduceRight;
lodash.include = contains;
lodash.inject = reduce;
forOwn(lodash, function(func, methodName) {
if (!lodash.prototype[methodName]) {
lodash.prototype[methodName] = function() {
var args = [this.__wrapped__];
push.apply(args, arguments);
return func.apply(lodash, args);
};
}
});
/*--------------------------------------------------------------------------*/
// add functions capable of returning wrapped and unwrapped values when chaining
lodash.first = first;
lodash.last = last;
// add aliases
lodash.take = first;
lodash.head = first;
forOwn(lodash, function(func, methodName) {
if (!lodash.prototype[methodName]) {
lodash.prototype[methodName]= function(callback, thisArg) {
var result = func(this.__wrapped__, callback, thisArg);
return callback == null || (thisArg && typeof callback != 'function')
? result
: new lodashWrapper(result);
};
}
});
/*--------------------------------------------------------------------------*/
/**
* The semantic version number.
*
* @static
* @memberOf _
* @type String
*/
lodash.VERSION = '1.3.1';
// add "Chaining" functions to the wrapper
lodash.prototype.toString = wrapperToString;
lodash.prototype.value = wrapperValueOf;
lodash.prototype.valueOf = wrapperValueOf;
// add `Array` functions that return unwrapped values
forEach(['join', 'pop', 'shift'], function(methodName) {
var func = arrayRef[methodName];
lodash.prototype[methodName] = function() {
return func.apply(this.__wrapped__, arguments);
};
});
// add `Array` functions that return the wrapped value
forEach(['push', 'reverse', 'sort', 'unshift'], function(methodName) {
var func = arrayRef[methodName];
lodash.prototype[methodName] = function() {
func.apply(this.__wrapped__, arguments);
return this;
};
});
// add `Array` functions that return new wrapped values
forEach(['concat', 'slice', 'splice'], function(methodName) {
var func = arrayRef[methodName];
lodash.prototype[methodName] = function() {
return new lodashWrapper(func.apply(this.__wrapped__, arguments));
};
});
return lodash;
}
/*--------------------------------------------------------------------------*/
// expose Lo-Dash
var _ = runInContext();
// some AMD build optimizers, like r.js, check for specific condition patterns like the following:
if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
// Expose Lo-Dash to the global object even when an AMD loader is present in
// case Lo-Dash was injected by a third-party script and not intended to be
// loaded as a module. The global assignment can be reverted in the Lo-Dash
// module via its `noConflict()` method.
window._ = _;
// define as an anonymous module so, through path mapping, it can be
// referenced as the "underscore" module
define(function() {
return _;
});
}
// check for `exports` after `define` in case a build optimizer adds an `exports` object
else if (freeExports && !freeExports.nodeType) {
// in Node.js or RingoJS v0.8.0+
if (freeModule) {
(freeModule.exports = _)._ = _;
}
// in Narwhal or RingoJS v0.7.0-
else {
freeExports._ = _;
}
}
else {
// in a browser or Rhino
window._ = _;
}
}(this));
}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],39:[function(_dereq_,module,exports){
module.exports={
"name": "amqp",
"description": "AMQP driver for node",
"keywords": [
"amqp"
],
"version": "0.2.0",
"author": {
"name": "Ryan Dahl"
},
"contributors": [
{
"name": "Vasili Sviridov"
},
{
"name": "Theo Schlossnagle"
},
{
"name": "Vincent Desjardins"
},
{
"name": "Liang-Chi Hsieh"
},
{
"name": "Tim Baga"
},
{
"name": "Stéphane Alnet"
},
{
"name": "Alen Mujezinovic"
},
{
"name": "Michael Bridgen"
},
{
"name": "Chris Bond"
},
{
"name": "Andrei Vereha"
},
{
"name": "Mike Bardzinski"
},
{
"name": "James Carr"
},
{
"name": "David Barshow"
},
{
"name": "Jason Pincin"
},
{
"name": "Carl Hörberg"
}
],
"repository": {
"type": "git",
"url": "git://github.com/postwait/node-amqp.git"
},
"bugs": {
"url": "http://github.com/postwait/node-amqp/issues"
},
"main": "./amqp",
"engines": {
"node": "0.4 || 0.6 || 0.8 || 0.9 || 0.10 || 0.11"
},
"licenses": [
{
"type": "MIT",
"url": "http://github.com/postwait/node-amqp/raw/master/LICENSE-MIT"
}
],
"dependencies": {
"lodash": "~1.3.1"
},
"devDependencies": {
"optimist": "~0.6.0",
"longjohn": "~0.2.1"
},
"scripts": {
"test": "make test"
},
"_id": "amqp@0.2.0",
"dist": {
"shasum": "caed3d5a1ef5f419663f80dcf6e95312e5fca2ca",
"tarball": "http://registry.npmjs.org/amqp/-/amqp-0.2.0.tgz"
},
"_from": "amqp@^0.2.0",
"_npmVersion": "1.2.18",
"_npmUser": {
"name": "postwait",
"email": "jesus@omniti.com"
},
"maintainers": [
{
"name": "ry",
"email": "ry@tinyclouds.org"
},
{
"name": "postwait",
"email": "jesus@omniti.com"
}
],
"directories": {},
"_shasum": "caed3d5a1ef5f419663f80dcf6e95312e5fca2ca",
"_resolved": "https://registry.npmjs.org/amqp/-/amqp-0.2.0.tgz",
"readme": "ERROR: No README data found!",
"homepage": "https://github.com/postwait/node-amqp"
}
},{}],40:[function(_dereq_,module,exports){
'use strict';
module.exports = _dereq_('./lib/babble');
},{"./lib/babble":43}],41:[function(_dereq_,module,exports){
'use strict';
var uuid = _dereq_('node-uuid');
var Promise = _dereq_('es6-promise').Promise;
var messagebus = _dereq_('./messagebus');
var Conversation = _dereq_('./Conversation');
var Block = _dereq_('./block/Block');
var Then = _dereq_('./block/Then');
var Tell = _dereq_('./block/Tell');
var Listen = _dereq_('./block/Listen');
_dereq_('./block/IIf'); // append iif function to Block
/**
* Babbler
* @param {String} id
* @constructor
*/
function Babbler (id) {
if (!(this instanceof Babbler)) {
throw new SyntaxError('Constructor must be called with the new operator');
}
if (!id) {
throw new Error('id required');
}
this.id = id;
this.listeners = []; // Array.<Listen>
this.conversations = {}; // Array.<Array.<Conversation>> all open conversations
this.connect(); // automatically connect to the local message bus
}
/**
* Connect to a message bus
* @param {{connect: function, disconnect: function, send: function}} [bus]
* A messaging interface. Must have the following functions:
* - connect(params: {id: string,
* message: function, callback: function}) : string
* must return a token to disconnects again.
* parameter callback is optional.
* - disconnect(token: string)
* disconnect from a message bus.
* - send(id: string, message: *)
* send a message
* A number of interfaces is provided under babble.messagebus.
* Default interface is babble.messagebus['default']
* @return {Promise.<Babbler>} Returns a Promise which resolves when the
* babbler is connected.
*/
Babbler.prototype.connect = function (bus) {
// disconnect (in case we are already connected)
this.disconnect();
if (!bus) {
bus = messagebus['default']();
}
// validate the message bus functions
if (typeof bus.connect !== 'function') {
throw new Error('message bus must contain a function ' +
'connect(params: {id: string, callback: function}) : string');
}
if (typeof bus.disconnect !== 'function') {
throw new Error('message bus must contain a function ' +
'disconnect(token: string)');
}
if (typeof bus.send !== 'function') {
throw new Error('message bus must contain a function ' +
'send(params: {id: string, message: *})');
}
// we return a promise, but we run the message.connect function immediately
// (outside of the Promise), so that synchronous connects are done without
// the need to await the promise to resolve on the next tick.
var _resolve = null;
var connected = new Promise(function (resolve, reject) {
_resolve = resolve;
});
var token = bus.connect({
id: this.id,
message: this._receive.bind(this),
callback: _resolve
});
// link functions to disconnect and send
this.disconnect = function () {
bus.disconnect(token);
};
this.send = bus.send;
// return a promise
return connected;
};
/**
* Handle an incoming message
* @param {{id: string, from: string, to: string, message: string}} envelope
* @private
*/
Babbler.prototype._receive = function (envelope) {
// ignore when envelope does not contain an id and message
if (!envelope || !('id' in envelope) || !('message' in envelope)) {
return;
}
// console.log('_receive', envelope) // TODO: cleanup
var me = this;
var id = envelope.id;
var conversations = this.conversations[id];
if (conversations && conversations.length) {
// directly deliver to all open conversations with this id
conversations.forEach(function (conversation) {
conversation.deliver(envelope);
})
}
else {
// start new conversations at each of the listeners
if (!conversations) {
conversations = [];
}
this.conversations[id] = conversations;
this.listeners.forEach(function (block) {
// create a new conversation
var conversation = new Conversation({
id: id,
self: me.id,
other: envelope.from,
context: {
from: envelope.from
},
send: me.send
});
// append this conversation to the list with conversations
conversations.push(conversation);
// deliver the first message to the new conversation
conversation.deliver(envelope);
// process the conversation
return me._process(block, conversation)
.then(function() {
// remove the conversation from the list again
var index = conversations.indexOf(conversation);
if (index !== -1) {
conversations.splice(index, 1);
}
if (conversations.length === 0) {
delete me.conversations[id];
}
});
});
}
};
/**
* Disconnect from the babblebox
*/
Babbler.prototype.disconnect = function () {
// by default, do nothing. The disconnect function will be overwritten
// when the Babbler is connected to a message bus.
};
/**
* Send a message
* @param {String} to Id of a babbler
* @param {*} message Any message. Message must be a stringifiable JSON object.
*/
Babbler.prototype.send = function (to, message) {
// send is overridden when running connect
throw new Error('Cannot send: not connected');
};
/**
* Listen for a specific event
*
* Providing a condition will only start the flow when condition is met,
* this is equivalent of doing `listen().iif(condition)`
*
* Providing a callback function is equivalent of doing either
* `listen(message).then(callback)` or `listen().iif(message).then(callback)`.
*
* @param {function | RegExp | String | *} [condition]
* @param {Function} [callback] Invoked as callback(message, context),
* where `message` is the just received message,
* and `context` is an object where state can be
* stored during a conversation. This is equivalent
* of doing `listen().then(callback)`
* @return {Block} block Start block of a control flow.
*/
Babbler.prototype.listen = function (condition, callback) {
var listen = new Listen();
this.listeners.push(listen);
var block = listen;
if (condition) {
block = block.iif(condition);
}
if (callback) {
block = block.then(callback);
}
return block;
};
/**
* Listen for a specific event, and execute the flow once.
*
* Providing a condition will only start the flow when condition is met,
* this is equivalent of doing `listen().iif(condition)`
*
* Providing a callback function is equivalent of doing either
* `listen(message).then(callback)` or `listen().iif(message).then(callback)`.
*
* @param {function | RegExp | String | *} [condition]
* @param {Function} [callback] Invoked as callback(message, context),
* where `message` is the just received message,
* and `context` is an object where state can be
* stored during a conversation. This is equivalent
* of doing `listen().then(callback)`
* @return {Block} block Start block of a control flow.
*/
Babbler.prototype.listenOnce = function (condition, callback) {
var listen = new Listen();
this.listeners.push(listen);
var me = this;
var block = listen;
if (condition) {
block = block.iif(condition);
}
block = block.then(function (message) {
// remove the flow from the listeners after fired once
var index = me.listeners.indexOf(listen);
if (index !== -1) {
me.listeners.splice(index, 1);
}
return message;
});
if (callback) {
block = block.then(callback);
}
return block;
};
/**
* Send a message to the other peer
* Creates a block Tell, and runs the block immediately.
* @param {String} to Babbler id
* @param {Function | *} message
* @return {Block} block Last block in the created control flow
*/
Babbler.prototype.tell = function (to, message) {
var me = this;
var cid = uuid.v4(); // create an id for this conversation
// create a new conversation
var conversation = new Conversation({
id: cid,
self: this.id,
other: to,
context: {
from: to
},
send: me.send
});
this.conversations[cid] = [conversation];
var block = new Tell(message);
// run the Tell block on the next tick, when the conversation flow is created
setTimeout(function () {
me._process(block, conversation)
.then(function () {
// cleanup the conversation
delete me.conversations[cid];
})
}, 0);
return block;
};
/**
* Send a question, listen for a response.
* Creates two blocks: Tell and Listen, and runs them immediately.
* This is equivalent of doing `Babbler.tell(to, message).listen(callback)`
* @param {String} to Babbler id
* @param {* | Function} message A message or a callback returning a message.
* @param {Function} [callback] Invoked as callback(message, context),
* where `message` is the just received message,
* and `context` is an object where state can be
* stored during a conversation. This is equivalent
* of doing `listen().then(callback)`
* @return {Block} block Last block in the created control flow
*/
Babbler.prototype.ask = function (to, message, callback) {
return this
.tell(to, message)
.listen(callback);
};
/**
* Process a flow starting with `block`, given a conversation
* @param {Block} block
* @param {Conversation} conversation
* @return {Promise.<Conversation>} Resolves when the conversation is finished
* @private
*/
Babbler.prototype._process = function (block, conversation) {
return new Promise(function (resolve, reject) {
/**
* Process a block, given the conversation and a message which is chained
* from block to block.
* @param {Block} block
* @param {*} [message]
*/
function process(block, message) {
//console.log('process', conversation.self, conversation.id, block.constructor.name, message) // TODO: cleanup
block.execute(conversation, message)
.then(function (next) {
if (next.block) {
// recursively evaluate the next block in the conversation flow
process(next.block, next.result);
}
else {
// we are done, this is the end of the conversation
resolve(conversation);
}
});
}
// process the first block
process(block);
});
};
module.exports = Babbler;
},{"./Conversation":42,"./block/Block":44,"./block/IIf":46,"./block/Listen":47,"./block/Tell":48,"./block/Then":49,"./messagebus":50,"es6-promise":52,"node-uuid":113}],42:[function(_dereq_,module,exports){
var uuid = _dereq_('node-uuid');
var Promise = _dereq_('es6-promise').Promise;
/**
* A conversation
* Holds meta data for a conversation between two peers
* @param {Object} [config] Configuration options:
* {string} [id] A unique id for the conversation. If not provided, a uuid is generated
* {string} self Id of the peer on this side of the conversation
* {string} other Id of the peer on the other side of the conversation
* {Object} [context] Context passed with all callbacks of the conversation
* {function(to: string, message: *): Promise} send Function to send a message
* @constructor
*/
function Conversation (config) {
if (!(this instanceof Conversation)) {
throw new SyntaxError('Constructor must be called with the new operator');
}
// public properties
this.id = config && config.id || uuid.v4();
this.self = config && config.self || null;
this.other = config && config.other || null;
this.context = config && config.context || {};
// private properties
this._send = config && config.send || null;
this._inbox = []; // queue with received but not yet picked messages
this._receivers = []; // queue with handlers waiting for a new message
}
/**
* Send a message
* @param {*} message
* @return {Promise.<null>} Resolves when the message has been sent
*/
Conversation.prototype.send = function (message) {
return this._send(this.other, {
id: this.id,
from: this.self,
to: this.other,
message: message
});
};
/**
* Deliver a message
* @param {{id: string, from: string, to: string, message: string}} envelope
*/
Conversation.prototype.deliver = function (envelope) {
if (this._receivers.length) {
var receiver = this._receivers.shift();
receiver(envelope.message);
}
else {
this._inbox.push(envelope.message);
}
};
/**
* Receive a message.
* @returns {Promise.<*>} Resolves with a message as soon as a message
* is delivered.
*/
Conversation.prototype.receive = function () {
var me = this;
if (this._inbox.length) {
return Promise.resolve(this._inbox.shift());
}
else {
return new Promise(function (resolve) {
me._receivers.push(resolve);
})
}
};
module.exports = Conversation;
},{"es6-promise":52,"node-uuid":113}],43:[function(_dereq_,module,exports){
'use strict';
var Babbler = _dereq_('./Babbler');
var Tell = _dereq_('./block/Tell');
var Listen = _dereq_('./block/Listen');
var Then = _dereq_('./block/Then');
var Decision = _dereq_('./block/Decision');
var IIf = _dereq_('./block/IIf');
/**
* Create a new babbler
* @param {String} id
* @return {Babbler} babbler
*/
exports.babbler = function (id) {
return new Babbler(id);
};
/**
* Create a control flow starting with a tell block
* @param {* | Function} [message] A static message or callback function
* returning a message dynamically.
* When `message` is a function, it will be
* invoked as callback(message, context),
* where `message` is the output from the
* previous block in the chain, and `context` is
* an object where state can be stored during a
* conversation.
* @return {Tell} tell
*/
exports.tell = function (message) {
return new Tell(message);
};
/**
* Send a question, listen for a response.
* Creates two blocks: Tell and Listen.
* This is equivalent of doing `babble.tell(message).listen(callback)`
* @param {* | Function} message
* @param {Function} [callback] Invoked as callback(message, context),
* where `message` is the just received message,
* and `context` is an object where state can be
* stored during a conversation. This is equivalent
* of doing `listen().then(callback)`
* @return {Block} block Last block in the created control flow
*/
exports.ask = function (message, callback) {
return exports
.tell(message)
.listen(callback);
};
/**
* Create a decision block and chain it to the current block.
*
* Syntax:
*
* decide(choices)
* decide(decision, choices)
*
* Where:
*
* {Function | Object} [decision]
* When a `decision` function is provided, the
* function is invoked as decision(message, context),
* where `message` is the output from the previous
* block in the chain, and `context` is an object
* where state can be stored during a conversation.
* The function must return the id for the next
* block in the control flow, which must be
* available in the provided `choices`.
* If `decision` is not provided, the next block
* will be mapped directly from the message.
* {Object.<String, Block>} choices
* A map with the possible next blocks in the flow
* The next block is selected by the id returned
* by the decision function.
*
* There is one special id for choices: 'default'. This id is called when either
* the decision function returns an id which does not match any of the available
* choices.
*
* @param {Function | Object} arg1 Can be {function} decision or {Object} choices
* @param {Object} [arg2] choices
* @return {Block} decision The created decision block
*/
exports.decide = function (arg1, arg2) {
// TODO: test arguments.length > 2
return new Decision(arg1, arg2);
};
/**
* Listen for a message.
*
* Optionally a callback function can be provided, which is equivalent of
* doing `listen().then(callback)`.
*
* @param {Function} [callback] Invoked as callback(message, context),
* where `message` is the just received message,
* and `context` is an object where state can be
* stored during a conversation. This is equivalent
* of doing `listen().then(callback)`
* @return {Block} Returns the created Listen block
*/
exports.listen = function(callback) {
var block = new Listen();
if (callback) {
return block.then(callback);
}
return block;
};
/**
* Create a control flow starting with a Then block
* @param {Function} callback Invoked as callback(message, context),
* where `message` is the output from the previous
* block in the chain, and `context` is an object
* where state can be stored during a conversation.
* @return {Then} then
*/
exports.then = function (callback) {
return new Then(callback);
};
/**
* IIf
* Create an iif block, which checks a condition and continues either with
* the trueBlock or the falseBlock. The input message is passed to the next
* block in the flow.
*
* Can be used as follows:
* - When `condition` evaluates true:
* - when `trueBlock` is provided, the flow continues with `trueBlock`
* - else, when there is a block connected to the IIf block, the flow continues
* with that block.
* - When `condition` evaluates false:
* - when `falseBlock` is provided, the flow continues with `falseBlock`
*
* Syntax:
*
* new IIf(condition, trueBlock)
* new IIf(condition, trueBlock [, falseBlock])
* new IIf(condition).then(...)
*
* @param {Function | RegExp | *} condition A condition returning true or false
* In case of a function,
* the function is invoked as
* `condition(message, context)` and
* must return a boolean. In case of
* a RegExp, condition will be tested
* to return true. In other cases,
* non-strict equality is tested on
* the input.
* @param {Block} [trueBlock]
* @param {Block} [falseBlock]
* @returns {Block}
*/
exports.iif = function (condition, trueBlock, falseBlock) {
return new IIf(condition, trueBlock, falseBlock);
};
// export the babbler prototype
exports.Babbler = Babbler;
// export all flow blocks
exports.block = {
Block: _dereq_('./block/Block'),
Then: _dereq_('./block/Then'),
Decision: _dereq_('./block/Decision'),
IIf: _dereq_('./block/IIf'),
Listen: _dereq_('./block/Listen'),
Tell: _dereq_('./block/Tell')
};
// export messagebus interfaces
exports.messagebus = _dereq_('./messagebus');
/**
* Babblify an actor. The babblified actor will be extended with functions
* `ask`, `tell`, and `listen`.
*
* Babble expects that messages sent via `actor.send(to, message)` will be
* delivered by the recipient on a function `actor.receive(from, message)`.
* Babble replaces the original `receive` with a new one, which is used to
* listen for all incoming messages. Messages ignored by babble are propagated
* to the original `receive` function.
*
* The actor can be restored in its original state using `unbabblify(actor)`.
*
* @param {Object} actor The actor to be babblified. Must be an object
* containing functions `send(to, message)` and
* `receive(from, message)`.
* @param {Object} [params] Optional parameters. Can contain properties:
* - id: string The id for the babbler
* - send: string The name of an alternative
* send function available on
* the actor.
* - receive: string The name of an alternative
* receive function available
* on the actor.
* @returns {Object} Returns the babblified actor.
*/
exports.babblify = function (actor, params) {
var babblerId;
if (params && params.id !== undefined) {
babblerId = params.id;
}
else if (actor.id !== undefined) {
babblerId = actor.id
}
else {
throw new Error('Id missing. Ensure that either actor has a property "id", ' +
'or provide an id as a property in second argument params')
}
// validate actor
['ask', 'tell', 'listen'].forEach(function (prop) {
if (actor[prop] !== undefined) {
throw new Error('Conflict: actor already has a property "' + prop + '"');
}
});
var sendName = params && params.send || 'send';
if (typeof actor[sendName] !== 'function') {
throw new Error('Missing function. ' +
'Function "' + sendName + '(to, message)" expected on actor or on params');
}
// create a new babbler
var babbler = exports.babbler(babblerId);
// attach receive function to the babbler
var receiveName = params && params.receive || 'receive';
var receiveOriginal = actor.hasOwnProperty(receiveName) ? actor[receiveName] : null;
if (receiveOriginal) {
actor[receiveName] = function (from, message) {
babbler._receive(message);
receiveOriginal.call(actor, from, message);
};
}
else {
actor[receiveName] = function (from, message) {
babbler._receive(message);
};
}
// attach send function to the babbler
babbler.send = function (to, message) {
// FIXME: there should be no need to send a message on next tick
setTimeout(function () {
actor[sendName](to, message)
}, 0)
};
// attach babbler functions and properties to the actor
actor.__babbler__ = {
babbler: babbler,
receive: receiveOriginal,
receiveName: receiveName
};
actor.ask = babbler.ask.bind(babbler);
actor.tell = babbler.tell.bind(babbler);
actor.listen = babbler.listen.bind(babbler);
actor.listenOnce = babbler.listenOnce.bind(babbler);
return actor;
};
/**
* Unbabblify an actor.
* @param {Object} actor
* @return {Object} Returns the unbabblified actor.
*/
exports.unbabblify = function (actor) {
var __babbler__ = actor.__babbler__;
if (__babbler__) {
delete actor.__babbler__;
delete actor.ask;
delete actor.tell;
delete actor.listen;
delete actor.listenOnce;
delete actor[__babbler__.receiveName];
// restore any original receive method
if (__babbler__.receive) {
actor[__babbler__.receiveName] = __babbler__.receive;
}
}
return actor;
};
},{"./Babbler":41,"./block/Block":44,"./block/Decision":45,"./block/IIf":46,"./block/Listen":47,"./block/Tell":48,"./block/Then":49,"./messagebus":50}],44:[function(_dereq_,module,exports){
'use strict';
/**
* Abstract control flow diagram block
* @constructor
*/
function Block() {
this.next = null;
this.previous = null;
}
/**
* Execute the block
* @param {Conversation} conversation
* @param {*} message
* @return {Promise.<{result: *, block: Block}, Error>} next
*/
Block.prototype.execute = function (conversation, message) {
throw new Error('Cannot run an abstract Block');
};
module.exports = Block;
},{}],45:[function(_dereq_,module,exports){
'use strict';
var Promise = _dereq_('es6-promise').Promise;
var Block = _dereq_('./Block');
var isPromise =_dereq_('../util').isPromise;
_dereq_('./Then'); // extend Block with function then
/**
* Decision
* A decision is made by executing the provided callback function, which returns
* a next control flow block.
*
* Syntax:
*
* new Decision(choices)
* new Decision(decision, choices)
*
* Where:
*
* {Function | Object} [decision]
* When a `decision` function is provided, the
* function is invoked as decision(message, context),
* where `message` is the output from the previous
* block in the chain, and `context` is an object
* where state can be stored during a conversation.
* The function must return the id for the next
* block in the control flow, which must be
* available in the provided `choices`.
* If `decision` is not provided, the next block
* will be mapped directly from the message.
* {Object.<String, Block>} choices
* A map with the possible next blocks in the flow
* The next block is selected by the id returned
* by the decision function.
*
* There is one special id for choices: 'default'. This id is called when either
* the decision function returns an id which does not match any of the available
* choices.
*
* @param arg1
* @param arg2
* @constructor
* @extends {Block}
*/
function Decision (arg1, arg2) {
var decision, choices;
if (!(this instanceof Decision)) {
throw new SyntaxError('Constructor must be called with the new operator');
}
if (typeof arg1 === 'function') {
decision = arg1;
choices = arg2;
}
else {
decision = null;
choices = arg1;
}
if (decision) {
if (typeof decision !== 'function') {
throw new TypeError('Parameter decision must be a function');
}
}
else {
decision = function (message, context) {
return message;
}
}
if (choices && (choices instanceof Function)) {
throw new TypeError('Parameter choices must be an object');
}
this.decision = decision;
this.choices = {};
// append all choices
if (choices) {
var me = this;
Object.keys(choices).forEach(function (id) {
me.addChoice(id, choices[id]);
});
}
}
Decision.prototype = Object.create(Block.prototype);
Decision.prototype.constructor = Decision;
/**
* Execute the block
* @param {Conversation} conversation
* @param {*} message
* @return {Promise.<{result: *, block: Block}, Error>} next
*/
Decision.prototype.execute = function (conversation, message) {
var me = this;
var id = this.decision(message, conversation.context);
var resolve = isPromise(id) ? id : Promise.resolve(id);
return resolve.then(function (id) {
var next = me.choices[id];
if (!next) {
// there is no match, fall back on the default choice
next = me.choices['default'];
}
if (!next) {
throw new Error('Block with id "' + id + '" not found');
}
return {
result: message,
block: next
};
});
};
/**
* Add a choice to the decision block.
* The choice can be a new chain of blocks. The first block of the chain
* will be triggered when the this id comes out of the decision function.
* @param {String | 'default'} id
* @param {Block} block
* @return {Decision} self
*/
Decision.prototype.addChoice = function (id, block) {
if (typeof id !== 'string') {
throw new TypeError('String expected as choice id');
}
if (!(block instanceof Block)) {
throw new TypeError('Block expected as choice');
}
if (id in this.choices) {
throw new Error('Choice with id "' + id + '" already exists');
}
// find the first block of the chain
var first = block;
while (first && first.previous) {
first = first.previous;
}
this.choices[id] = first;
return this;
};
/**
* Create a decision block and chain it to the current block.
* Returns the first block in the chain.
*
* Syntax:
*
* decide(choices)
* decide(decision, choices)
*
* Where:
*
* {Function | Object} [decision]
* When a `decision` function is provided, the
* function is invoked as decision(message, context),
* where `message` is the output from the previous
* block in the chain, and `context` is an object
* where state can be stored during a conversation.
* The function must return the id for the next
* block in the control flow, which must be
* available in the provided `choices`.
* If `decision` is not provided, the next block
* will be mapped directly from the message.
* {Object.<String, Block>} choices
* A map with the possible next blocks in the flow
* The next block is selected by the id returned
* by the decision function.
*
* There is one special id for choices: 'default'. This id is called when either
* the decision function returns an id which does not match any of the available
* choices.
*
* @param {Function | Object} arg1 Can be {function} decision or {Object} choices
* @param {Object} [arg2] choices
* @return {Block} first First block in the chain
*/
Block.prototype.decide = function (arg1, arg2) {
var decision = new Decision(arg1, arg2);
return this.then(decision);
};
module.exports = Decision;
},{"../util":51,"./Block":44,"./Then":49,"es6-promise":52}],46:[function(_dereq_,module,exports){
'use strict';
var Promise = _dereq_('es6-promise').Promise;
var Block = _dereq_('./Block');
var isPromise = _dereq_('../util').isPromise;
_dereq_('./Then'); // extend Block with function then
/**
* IIf
* Create an iif block, which checks a condition and continues either with
* the trueBlock or the falseBlock. The input message is passed to the next
* block in the flow.
*
* Can be used as follows:
* - When `condition` evaluates true:
* - when `trueBlock` is provided, the flow continues with `trueBlock`
* - else, when there is a block connected to the IIf block, the flow continues
* with that block.
* - When `condition` evaluates false:
* - when `falseBlock` is provided, the flow continues with `falseBlock`
*
* Syntax:
*
* new IIf(condition, trueBlock)
* new IIf(condition, trueBlock [, falseBlock])
* new IIf(condition).then(...)
*
* @param {Function | RegExp | *} condition A condition returning true or false
* In case of a function,
* the function is invoked as
* `condition(message, context)` and
* must return a boolean. In case of
* a RegExp, condition will be tested
* to return true. In other cases,
* non-strict equality is tested on
* the input.
* @param {Block} [trueBlock]
* @param {Block} [falseBlock]
* @constructor
* @extends {Block}
*/
function IIf (condition, trueBlock, falseBlock) {
if (!(this instanceof IIf)) {
throw new SyntaxError('Constructor must be called with the new operator');
}
if (condition instanceof Function) {
this.condition = condition;
}
else if (condition instanceof RegExp) {
this.condition = function (message, context) {
return condition.test(message);
}
}
else {
this.condition = function (message, context) {
return message == condition;
}
}
if (trueBlock && !(trueBlock instanceof Block)) {
throw new TypeError('Parameter trueBlock must be a Block');
}
if (falseBlock && !(falseBlock instanceof Block)) {
throw new TypeError('Parameter falseBlock must be a Block');
}
this.trueBlock = trueBlock || null;
this.falseBlock = falseBlock || null;
}
IIf.prototype = Object.create(Block.prototype);
IIf.prototype.constructor = IIf;
/**
* Execute the block
* @param {Conversation} conversation
* @param {*} message
* @return {Promise.<{result: *, block: Block}, Error>} next
*/
IIf.prototype.execute = function (conversation, message) {
var me = this;
var condition = this.condition(message, conversation.context);
var resolve = isPromise(condition) ? condition : Promise.resolve(condition);
return resolve.then(function (condition) {
var next = condition ? (me.trueBlock || me.next) : me.falseBlock;
return {
result: message,
block: next
};
});
};
/**
* IIf
* Create an iif block, which checks a condition and continues either with
* the trueBlock or the falseBlock. The input message is passed to the next
* block in the flow.
*
* Can be used as follows:
* - When `condition` evaluates true:
* - when `trueBlock` is provided, the flow continues with `trueBlock`
* - else, when there is a block connected to the IIf block, the flow continues
* with that block.
* - When `condition` evaluates false:
* - when `falseBlock` is provided, the flow continues with `falseBlock`
*
* Syntax:
*
* new IIf(condition, trueBlock)
* new IIf(condition, trueBlock [, falseBlock])
* new IIf(condition).then(...)
*
* @param {Function | RegExp | *} condition A condition returning true or false
* In case of a function,
* the function is invoked as
* `condition(message, context)` and
* must return a boolean. In case of
* a RegExp, condition will be tested
* to return true. In other cases,
* non-strict equality is tested on
* the input.
* @param {Block} [trueBlock]
* @param {Block} [falseBlock]
* @returns {Block} Returns the created IIf block
*/
Block.prototype.iif = function (condition, trueBlock, falseBlock) {
var iif = new IIf(condition, trueBlock, falseBlock);
return this.then(iif);
};
module.exports = IIf;
},{"../util":51,"./Block":44,"./Then":49,"es6-promise":52}],47:[function(_dereq_,module,exports){
'use strict';
var Promise = _dereq_('es6-promise').Promise;
var Block = _dereq_('./Block');
var Then = _dereq_('./Then');
/**
* Listen
* Wait until a message comes in from the connected peer, then continue
* with the next block in the control flow.
*
* @constructor
* @extends {Block}
*/
function Listen () {
if (!(this instanceof Listen)) {
throw new SyntaxError('Constructor must be called with the new operator');
}
}
Listen.prototype = Object.create(Block.prototype);
Listen.prototype.constructor = Listen;
/**
* Execute the block
* @param {Conversation} conversation
* @param {*} [message] Message is ignored by Listen blocks
* @return {Promise.<{result: *, block: Block}, Error>} next
*/
Listen.prototype.execute = function (conversation, message) {
var me = this;
// wait until a message is received
return conversation.receive()
.then(function (message) {
return {
result: message,
block: me.next
}
});
};
/**
* Create a Listen block and chain it to the current block
*
* Optionally a callback function can be provided, which is equivalent of
* doing `listen().then(callback)`.
*
* @param {Function} [callback] Executed as callback(message: *, context: Object)
* Must return a result
* @return {Block} Returns the appended block
*/
Block.prototype.listen = function (callback) {
var listen = new Listen();
var block = this.then(listen);
if (callback) {
block = block.then(callback);
}
return block;
};
module.exports = Listen;
},{"./Block":44,"./Then":49,"es6-promise":52}],48:[function(_dereq_,module,exports){
'use strict';
var Promise = _dereq_('es6-promise').Promise;
var Block = _dereq_('./Block');
var isPromise = _dereq_('../util').isPromise;
_dereq_('./Then'); // extend Block with function then
_dereq_('./Listen'); // extend Block with function listen
/**
* Tell
* Send a message to the other peer.
* @param {* | Function} message A static message or callback function
* returning a message dynamically.
* When `message` is a function, it will be
* invoked as callback(message, context),
* where `message` is the output from the
* previous block in the chain, and `context` is
* an object where state can be stored during a
* conversation.
* @constructor
* @extends {Block}
*/
function Tell (message) {
if (!(this instanceof Tell)) {
throw new SyntaxError('Constructor must be called with the new operator');
}
this.message = message;
}
Tell.prototype = Object.create(Block.prototype);
Tell.prototype.constructor = Tell;
/**
* Execute the block
* @param {Conversation} conversation
* @param {*} [message] A message is ignored by the Tell block
* @return {Promise.<{result: *, block: Block}, Error>} next
*/
Tell.prototype.execute = function (conversation, message) {
// resolve the message
var me = this;
var resolve;
if (typeof this.message === 'function') {
var result = this.message(message, conversation.context);
resolve = isPromise(result) ? result : Promise.resolve(result);
}
else {
resolve = Promise.resolve(this.message); // static string or value
}
return resolve
.then(function (result) {
var res = conversation.send(result);
var done = isPromise(res) ? res : Promise.resolve(res);
return done.then(function () {
return {
result: result,
block: me.next
};
});
});
};
/**
* Create a Tell block and chain it to the current block
* @param {* | Function} [message] A static message or callback function
* returning a message dynamically.
* When `message` is a function, it will be
* invoked as callback(message, context),
* where `message` is the output from the
* previous block in the chain, and `context` is
* an object where state can be stored during a
* conversation.
* @return {Block} Returns the appended block
*/
Block.prototype.tell = function (message) {
var block = new Tell(message);
return this.then(block);
};
/**
* Send a question, listen for a response.
* Creates two blocks: Tell and Listen.
* This is equivalent of doing `babble.tell(message).listen(callback)`
* @param {* | Function} message
* @param {Function} [callback] Invoked as callback(message, context),
* where `message` is the just received message,
* and `context` is an object where state can be
* stored during a conversation. This is equivalent
* of doing `listen().then(callback)`
* @return {Block} Returns the appended block
*/
Block.prototype.ask = function (message, callback) {
// FIXME: this doesn't work
return this
.tell(message)
.listen(callback);
};
module.exports = Tell;
},{"../util":51,"./Block":44,"./Listen":47,"./Then":49,"es6-promise":52}],49:[function(_dereq_,module,exports){
'use strict';
var Promise = _dereq_('es6-promise').Promise;
var Block = _dereq_('./Block');
var isPromise = _dereq_('../util').isPromise;
/**
* Then
* Execute a callback function or a next block in the chain.
* @param {Function} callback Invoked as callback(message, context),
* where `message` is the output from the previous
* block in the chain, and `context` is an object
* where state can be stored during a conversation.
* @constructor
* @extends {Block}
*/
function Then (callback) {
if (!(this instanceof Then)) {
throw new SyntaxError('Constructor must be called with the new operator');
}
if (!(typeof callback === 'function')) {
throw new TypeError('Parameter callback must be a Function');
}
this.callback = callback;
}
Then.prototype = Object.create(Block.prototype);
Then.prototype.constructor = Then;
/**
* Execute the block
* @param {Conversation} conversation
* @param {*} message
* @return {Promise.<{result: *, block: Block}, Error>} next
*/
Then.prototype.execute = function (conversation, message) {
var me = this;
var result = this.callback(message, conversation.context);
var resolve = isPromise(result) ? result : Promise.resolve(result);
return resolve.then(function (result) {
return {
result: result,
block: me.next
}
});
};
/**
* Chain a block to the current block.
*
* When a function is provided, a Then block will be generated which
* executes the function. The function is invoked as callback(message, context),
* where `message` is the output from the previous block in the chain,
* and `context` is an object where state can be stored during a conversation.
*
* @param {Block | function} next A callback function or Block.
* @return {Block} Returns the appended block
*/
Block.prototype.then = function (next) {
// turn a callback function into a Then block
if (typeof next === 'function') {
next = new Then(next);
}
if (!(next instanceof Block)) {
throw new TypeError('Parameter next must be a Block or function');
}
// append after the last block
next.previous = this;
this.next = next;
// return the appended block
return next;
};
module.exports = Then;
},{"../util":51,"./Block":44,"es6-promise":52}],50:[function(_dereq_,module,exports){
'use strict';
var Promise = _dereq_('es6-promise').Promise;
// built-in messaging interfaces
/**
* pubsub-js messaging interface
* @returns {{connect: function, disconnect: function, send: function}}
*/
exports['pubsub-js'] = function () {
var PubSub = _dereq_('pubsub-js');
return {
connect: function (params) {
var token = PubSub.subscribe(params.id, function (id, message) {
params.message(message);
});
if (typeof params.callback === 'function') {
params.callback();
}
return token;
},
disconnect: function(token) {
PubSub.unsubscribe(token);
},
send: function (to, message) {
PubSub.publish(to, message);
}
}
};
/**
* // pubnub messaging interface
* @param {{publish_key: string, subscribe_key: string}} params
* @returns {{connect: function, disconnect: function, send: function}}
*/
exports['pubnub'] = function (params) {
var PUBNUB;
if (typeof window !== 'undefined') {
// browser
if (typeof window['PUBNUB'] === 'undefined') {
throw new Error('Please load pubnub first in the browser');
}
PUBNUB = window['PUBNUB'];
}
else {
// node.js
PUBNUB = _dereq_('pubnub');
}
var pubnub = PUBNUB.init(params);
return {
connect: function (params) {
pubnub.subscribe({
channel: params.id,
message: params.message,
connect: params.callback
});
return params.id;
},
disconnect: function (id) {
pubnub.unsubscribe(id);
},
send: function (to, message) {
return new Promise(function (resolve, reject) {
pubnub.publish({
channel: to,
message: message,
callback: resolve
});
})
}
}
};
// default interface
exports['default'] = exports['pubsub-js'];
},{"es6-promise":52,"pubnub":65,"pubsub-js":66}],51:[function(_dereq_,module,exports){
/**
* Test whether the provided value is a Promise.
* A value is marked as a Promise when it is an object containing functions
* `then` and `catch`.
* @param {*} value
* @return {boolean} Returns true when `value` is a Promise
*/
exports.isPromise = function (value) {
return value &&
typeof value['then'] === 'function' &&
typeof value['catch'] === 'function'
};
},{}],52:[function(_dereq_,module,exports){
"use strict";
var Promise = _dereq_("./promise/promise").Promise;
var polyfill = _dereq_("./promise/polyfill").polyfill;
exports.Promise = Promise;
exports.polyfill = polyfill;
},{"./promise/polyfill":56,"./promise/promise":57}],53:[function(_dereq_,module,exports){
"use strict";
/* global toString */
var isArray = _dereq_("./utils").isArray;
var isFunction = _dereq_("./utils").isFunction;
/**
Returns a promise that is fulfilled when all the given promises have been
fulfilled, or rejected if any of them become rejected. The return promise
is fulfilled with an array that gives all the values in the order they were
passed in the `promises` array argument.
Example:
```javascript
var promise1 = RSVP.resolve(1);
var promise2 = RSVP.resolve(2);
var promise3 = RSVP.resolve(3);
var promises = [ promise1, promise2, promise3 ];
RSVP.all(promises).then(function(array){
// The array here would be [ 1, 2, 3 ];
});
```
If any of the `promises` given to `RSVP.all` are rejected, the first promise
that is rejected will be given as an argument to the returned promises's
rejection handler. For example:
Example:
```javascript
var promise1 = RSVP.resolve(1);
var promise2 = RSVP.reject(new Error("2"));
var promise3 = RSVP.reject(new Error("3"));
var promises = [ promise1, promise2, promise3 ];
RSVP.all(promises).then(function(array){
// Code here never runs because there are rejected promises!
}, function(error) {
// error.message === "2"
});
```
@method all
@for RSVP
@param {Array} promises
@param {String} label
@return {Promise} promise that is fulfilled when all `promises` have been
fulfilled, or rejected if any of them become rejected.
*/
function all(promises) {
/*jshint validthis:true */
var Promise = this;
if (!isArray(promises)) {
throw new TypeError('You must pass an array to all.');
}
return new Promise(function(resolve, reject) {
var results = [], remaining = promises.length,
promise;
if (remaining === 0) {
resolve([]);
}
function resolver(index) {
return function(value) {
resolveAll(index, value);
};
}
function resolveAll(index, value) {
results[index] = value;
if (--remaining === 0) {
resolve(results);
}
}
for (var i = 0; i < promises.length; i++) {
promise = promises[i];
if (promise && isFunction(promise.then)) {
promise.then(resolver(i), reject);
} else {
resolveAll(i, promise);
}
}
});
}
exports.all = all;
},{"./utils":61}],54:[function(_dereq_,module,exports){
(function (process,global){
"use strict";
var browserGlobal = (typeof window !== 'undefined') ? window : {};
var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
var local = (typeof global !== 'undefined') ? global : (this === undefined? window:this);
// node
function useNextTick() {
return function() {
process.nextTick(flush);
};
}
function useMutationObserver() {
var iterations = 0;
var observer = new BrowserMutationObserver(flush);
var node = document.createTextNode('');
observer.observe(node, { characterData: true });
return function() {
node.data = (iterations = ++iterations % 2);
};
}
function useSetTimeout() {
return function() {
local.setTimeout(flush, 1);
};
}
var queue = [];
function flush() {
for (var i = 0; i < queue.length; i++) {
var tuple = queue[i];
var callback = tuple[0], arg = tuple[1];
callback(arg);
}
queue = [];
}
var scheduleFlush;
// Decide what async method to use to triggering processing of queued callbacks:
if (typeof process !== 'undefined' && {}.toString.call(process) === '[object process]') {
scheduleFlush = useNextTick();
} else if (BrowserMutationObserver) {
scheduleFlush = useMutationObserver();
} else {
scheduleFlush = useSetTimeout();
}
function asap(callback, arg) {
var length = queue.push([callback, arg]);
if (length === 1) {
// If length is 1, that means that we need to schedule an async flush.
// If additional callbacks are queued before the queue is flushed, they
// will be processed by this flush that we are scheduling.
scheduleFlush();
}
}
exports.asap = asap;
}).call(this,_dereq_("C:\\Users\\Alex\\AppData\\Roaming\\npm\\node_modules\\browserify\\node_modules\\insert-module-globals\\node_modules\\process\\browser.js"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"C:\\Users\\Alex\\AppData\\Roaming\\npm\\node_modules\\browserify\\node_modules\\insert-module-globals\\node_modules\\process\\browser.js":144}],55:[function(_dereq_,module,exports){
"use strict";
var config = {
instrument: false
};
function configure(name, value) {
if (arguments.length === 2) {
config[name] = value;
} else {
return config[name];
}
}
exports.config = config;
exports.configure = configure;
},{}],56:[function(_dereq_,module,exports){
(function (global){
"use strict";
/*global self*/
var RSVPPromise = _dereq_("./promise").Promise;
var isFunction = _dereq_("./utils").isFunction;
function polyfill() {
var local;
if (typeof global !== 'undefined') {
local = global;
} else if (typeof window !== 'undefined' && window.document) {
local = window;
} else {
local = self;
}
var es6PromiseSupport =
"Promise" in local &&
// Some of these methods are missing from
// Firefox/Chrome experimental implementations
"resolve" in local.Promise &&
"reject" in local.Promise &&
"all" in local.Promise &&
"race" in local.Promise &&
// Older version of the spec had a resolver object
// as the arg rather than a function
(function() {
var resolve;
new local.Promise(function(r) { resolve = r; });
return isFunction(resolve);
}());
if (!es6PromiseSupport) {
local.Promise = RSVPPromise;
}
}
exports.polyfill = polyfill;
}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./promise":57,"./utils":61}],57:[function(_dereq_,module,exports){
"use strict";
var config = _dereq_("./config").config;
var configure = _dereq_("./config").configure;
var objectOrFunction = _dereq_("./utils").objectOrFunction;
var isFunction = _dereq_("./utils").isFunction;
var now = _dereq_("./utils").now;
var all = _dereq_("./all").all;
var race = _dereq_("./race").race;
var staticResolve = _dereq_("./resolve").resolve;
var staticReject = _dereq_("./reject").reject;
var asap = _dereq_("./asap").asap;
var counter = 0;
config.async = asap; // default async is asap;
function Promise(resolver) {
if (!isFunction(resolver)) {
throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');
}
if (!(this instanceof Promise)) {
throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");
}
this._subscribers = [];
invokeResolver(resolver, this);
}
function invokeResolver(resolver, promise) {
function resolvePromise(value) {
resolve(promise, value);
}
function rejectPromise(reason) {
reject(promise, reason);
}
try {
resolver(resolvePromise, rejectPromise);
} catch(e) {
rejectPromise(e);
}
}
function invokeCallback(settled, promise, callback, detail) {
var hasCallback = isFunction(callback),
value, error, succeeded, failed;
if (hasCallback) {
try {
value = callback(detail);
succeeded = true;
} catch(e) {
failed = true;
error = e;
}
} else {
value = detail;
succeeded = true;
}
if (handleThenable(promise, value)) {
return;
} else if (hasCallback && succeeded) {
resolve(promise, value);
} else if (failed) {
reject(promise, error);
} else if (settled === FULFILLED) {
resolve(promise, value);
} else if (settled === REJECTED) {
reject(promise, value);
}
}
var PENDING = void 0;
var SEALED = 0;
var FULFILLED = 1;
var REJECTED = 2;
function subscribe(parent, child, onFulfillment, onRejection) {
var subscribers = parent._subscribers;
var length = subscribers.length;
subscribers[length] = child;
subscribers[length + FULFILLED] = onFulfillment;
subscribers[length + REJECTED] = onRejection;
}
function publish(promise, settled) {
var child, callback, subscribers = promise._subscribers, detail = promise._detail;
for (var i = 0; i < subscribers.length; i += 3) {
child = subscribers[i];
callback = subscribers[i + settled];
invokeCallback(settled, child, callback, detail);
}
promise._subscribers = null;
}
Promise.prototype = {
constructor: Promise,
_state: undefined,
_detail: undefined,
_subscribers: undefined,
then: function(onFulfillment, onRejection) {
var promise = this;
var thenPromise = new this.constructor(function() {});
if (this._state) {
var callbacks = arguments;
config.async(function invokePromiseCallback() {
invokeCallback(promise._state, thenPromise, callbacks[promise._state - 1], promise._detail);
});
} else {
subscribe(this, thenPromise, onFulfillment, onRejection);
}
return thenPromise;
},
'catch': function(onRejection) {
return this.then(null, onRejection);
}
};
Promise.all = all;
Promise.race = race;
Promise.resolve = staticResolve;
Promise.reject = staticReject;
function handleThenable(promise, value) {
var then = null,
resolved;
try {
if (promise === value) {
throw new TypeError("A promises callback cannot return that same promise.");
}
if (objectOrFunction(value)) {
then = value.then;
if (isFunction(then)) {
then.call(value, function(val) {
if (resolved) { return true; }
resolved = true;
if (value !== val) {
resolve(promise, val);
} else {
fulfill(promise, val);
}
}, function(val) {
if (resolved) { return true; }
resolved = true;
reject(promise, val);
});
return true;
}
}
} catch (error) {
if (resolved) { return true; }
reject(promise, error);
return true;
}
return false;
}
function resolve(promise, value) {
if (promise === value) {
fulfill(promise, value);
} else if (!handleThenable(promise, value)) {
fulfill(promise, value);
}
}
function fulfill(promise, value) {
if (promise._state !== PENDING) { return; }
promise._state = SEALED;
promise._detail = value;
config.async(publishFulfillment, promise);
}
function reject(promise, reason) {
if (promise._state !== PENDING) { return; }
promise._state = SEALED;
promise._detail = reason;
config.async(publishRejection, promise);
}
function publishFulfillment(promise) {
publish(promise, promise._state = FULFILLED);
}
function publishRejection(promise) {
publish(promise, promise._state = REJECTED);
}
exports.Promise = Promise;
},{"./all":53,"./asap":54,"./config":55,"./race":58,"./reject":59,"./resolve":60,"./utils":61}],58:[function(_dereq_,module,exports){
"use strict";
/* global toString */
var isArray = _dereq_("./utils").isArray;
/**
`RSVP.race` allows you to watch a series of promises and act as soon as the
first promise given to the `promises` argument fulfills or rejects.
Example:
```javascript
var promise1 = new RSVP.Promise(function(resolve, reject){
setTimeout(function(){
resolve("promise 1");
}, 200);
});
var promise2 = new RSVP.Promise(function(resolve, reject){
setTimeout(function(){
resolve("promise 2");
}, 100);
});
RSVP.race([promise1, promise2]).then(function(result){
// result === "promise 2" because it was resolved before promise1
// was resolved.
});
```
`RSVP.race` is deterministic in that only the state of the first completed
promise matters. For example, even if other promises given to the `promises`
array argument are resolved, but the first completed promise has become
rejected before the other promises became fulfilled, the returned promise
will become rejected:
```javascript
var promise1 = new RSVP.Promise(function(resolve, reject){
setTimeout(function(){
resolve("promise 1");
}, 200);
});
var promise2 = new RSVP.Promise(function(resolve, reject){
setTimeout(function(){
reject(new Error("promise 2"));
}, 100);
});
RSVP.race([promise1, promise2]).then(function(result){
// Code here never runs because there are rejected promises!
}, function(reason){
// reason.message === "promise2" because promise 2 became rejected before
// promise 1 became fulfilled
});
```
@method race
@for RSVP
@param {Array} promises array of promises to observe
@param {String} label optional string for describing the promise returned.
Useful for tooling.
@return {Promise} a promise that becomes fulfilled with the value the first
completed promises is resolved with if the first completed promise was
fulfilled, or rejected with the reason that the first completed promise
was rejected with.
*/
function race(promises) {
/*jshint validthis:true */
var Promise = this;
if (!isArray(promises)) {
throw new TypeError('You must pass an array to race.');
}
return new Promise(function(resolve, reject) {
var results = [], promise;
for (var i = 0; i < promises.length; i++) {
promise = promises[i];
if (promise && typeof promise.then === 'function') {
promise.then(resolve, reject);
} else {
resolve(promise);
}
}
});
}
exports.race = race;
},{"./utils":61}],59:[function(_dereq_,module,exports){
"use strict";
/**
`RSVP.reject` returns a promise that will become rejected with the passed
`reason`. `RSVP.reject` is essentially shorthand for the following:
```javascript
var promise = new RSVP.Promise(function(resolve, reject){
reject(new Error('WHOOPS'));
});
promise.then(function(value){
// Code here doesn't run because the promise is rejected!
}, function(reason){
// reason.message === 'WHOOPS'
});
```
Instead of writing the above, your code now simply becomes the following:
```javascript
var promise = RSVP.reject(new Error('WHOOPS'));
promise.then(function(value){
// Code here doesn't run because the promise is rejected!
}, function(reason){
// reason.message === 'WHOOPS'
});
```
@method reject
@for RSVP
@param {Any} reason value that the returned promise will be rejected with.
@param {String} label optional string for identifying the returned promise.
Useful for tooling.
@return {Promise} a promise that will become rejected with the given
`reason`.
*/
function reject(reason) {
/*jshint validthis:true */
var Promise = this;
return new Promise(function (resolve, reject) {
reject(reason);
});
}
exports.reject = reject;
},{}],60:[function(_dereq_,module,exports){
"use strict";
function resolve(value) {
/*jshint validthis:true */
if (value && typeof value === 'object' && value.constructor === this) {
return value;
}
var Promise = this;
return new Promise(function(resolve) {
resolve(value);
});
}
exports.resolve = resolve;
},{}],61:[function(_dereq_,module,exports){
"use strict";
function objectOrFunction(x) {
return isFunction(x) || (typeof x === "object" && x !== null);
}
function isFunction(x) {
return typeof x === "function";
}
function isArray(x) {
return Object.prototype.toString.call(x) === "[object Array]";
}
// Date.now is not available in browsers < IE9
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now#Compatibility
var now = Date.now || function() { return new Date().getTime(); };
exports.objectOrFunction = objectOrFunction;
exports.isFunction = isFunction;
exports.isArray = isArray;
exports.now = now;
},{}],62:[function(_dereq_,module,exports){
module.exports = _dereq_('./lib/agent');
},{"./lib/agent":64}],63:[function(_dereq_,module,exports){
(function (process){
// 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.
// copy from https://github.com/joyent/node/blob/master/lib/_http_agent.js
var net = _dereq_('net');
var url = _dereq_('url');
var util = _dereq_('util');
var EventEmitter = _dereq_('events').EventEmitter;
// var ClientRequest = require('_http_client').ClientRequest;
// var debug = util.debuglog('http');
var ClientRequest = _dereq_('http').ClientRequest;
var debug;
if (process.env.NODE_DEBUG && /agentkeepalive/.test(process.env.NODE_DEBUG)) {
debug = function (x) {
console.error.apply(console, arguments);
};
} else {
debug = function () { };
}
// New Agent code.
// The largest departure from the previous implementation is that
// an Agent instance holds connections for a variable number of host:ports.
// Surprisingly, this is still API compatible as far as third parties are
// concerned. The only code that really notices the difference is the
// request object.
// Another departure is that all code related to HTTP parsing is in
// ClientRequest.onSocket(). The Agent is now *strictly*
// concerned with managing a connection pool.
function Agent(options) {
if (!(this instanceof Agent))
return new Agent(options);
EventEmitter.call(this);
var self = this;
self.defaultPort = 80;
self.protocol = 'http:';
self.options = util._extend({}, options);
// don't confuse net and make it think that we're connecting to a pipe
self.options.path = null;
self.requests = {};
self.sockets = {};
self.freeSockets = {};
self.keepAliveMsecs = self.options.keepAliveMsecs || 1000;
self.keepAlive = self.options.keepAlive || false;
self.maxSockets = self.options.maxSockets || Agent.defaultMaxSockets;
self.maxFreeSockets = self.options.maxFreeSockets || 256;
self.on('free', function(socket, options) {
var name = self.getName(options);
debug('agent.on(free)', name);
if (!socket.destroyed &&
self.requests[name] && self.requests[name].length) {
self.requests[name].shift().onSocket(socket);
if (self.requests[name].length === 0) {
// don't leak
delete self.requests[name];
}
} else {
// If there are no pending requests, then put it in
// the freeSockets pool, but only if we're allowed to do so.
var req = socket._httpMessage;
if (req &&
req.shouldKeepAlive &&
!socket.destroyed &&
self.options.keepAlive) {
var freeSockets = self.freeSockets[name];
var freeLen = freeSockets ? freeSockets.length : 0;
var count = freeLen;
if (self.sockets[name])
count += self.sockets[name].length;
if (count >= self.maxSockets || freeLen >= self.maxFreeSockets) {
self.removeSocket(socket, options);
socket.destroy();
} else {
freeSockets = freeSockets || [];
self.freeSockets[name] = freeSockets;
socket.setKeepAlive(true, self.keepAliveMsecs);
socket.unref && socket.unref();
socket._httpMessage = null;
self.removeSocket(socket, options);
freeSockets.push(socket);
}
} else {
self.removeSocket(socket, options);
socket.destroy();
}
}
});
}
util.inherits(Agent, EventEmitter);
exports.Agent = Agent;
Agent.defaultMaxSockets = Infinity;
Agent.prototype.createConnection = net.createConnection;
// Get the key for a given set of request options
Agent.prototype.getName = function(options) {
var name = '';
if (options.host)
name += options.host;
else
name += 'localhost';
name += ':';
if (options.port)
name += options.port;
name += ':';
if (options.localAddress)
name += options.localAddress;
name += ':';
return name;
};
Agent.prototype.addRequest = function(req, options) {
// Legacy API: addRequest(req, host, port, path)
if (typeof options === 'string') {
options = {
host: options,
port: arguments[2],
path: arguments[3]
};
}
var name = this.getName(options);
if (!this.sockets[name]) {
this.sockets[name] = [];
}
var freeLen = this.freeSockets[name] ? this.freeSockets[name].length : 0;
var sockLen = freeLen + this.sockets[name].length;
if (freeLen) {
// we have a free socket, so use that.
var socket = this.freeSockets[name].shift();
debug('have free socket');
// don't leak
if (!this.freeSockets[name].length)
delete this.freeSockets[name];
socket.ref && socket.ref();
req.onSocket(socket);
this.sockets[name].push(socket);
} else if (sockLen < this.maxSockets) {
debug('call onSocket', sockLen, freeLen);
// If we are under maxSockets create a new one.
req.onSocket(this.createSocket(req, options));
} else {
debug('wait for socket');
// We are over limit so we'll add it to the queue.
if (!this.requests[name]) {
this.requests[name] = [];
}
this.requests[name].push(req);
}
};
Agent.prototype.createSocket = function(req, options) {
var self = this;
options = util._extend({}, options);
options = util._extend(options, self.options);
options.servername = options.host;
if (req) {
var hostHeader = req.getHeader('host');
if (hostHeader) {
options.servername = hostHeader.replace(/:.*$/, '');
}
}
var name = self.getName(options);
debug('createConnection', name, options);
var s = self.createConnection(options);
if (!self.sockets[name]) {
self.sockets[name] = [];
}
this.sockets[name].push(s);
debug('sockets', name, this.sockets[name].length);
function onFree() {
self.emit('free', s, options);
}
s.on('free', onFree);
function onClose(err) {
debug('CLIENT socket onClose');
// This is the only place where sockets get removed from the Agent.
// If you want to remove a socket from the pool, just close it.
// All socket errors end in a close event anyway.
self.removeSocket(s, options);
}
s.on('close', onClose);
function onRemove() {
// We need this function for cases like HTTP 'upgrade'
// (defined by WebSockets) where we need to remove a socket from the
// pool because it'll be locked up indefinitely
debug('CLIENT socket onRemove');
self.removeSocket(s, options, 'agentRemove');
s.removeListener('close', onClose);
s.removeListener('free', onFree);
s.removeListener('agentRemove', onRemove);
}
s.on('agentRemove', onRemove);
return s;
};
Agent.prototype.removeSocket = function(s, options) {
var name = this.getName(options);
debug('removeSocket', name, 'destroyed:', s.destroyed);
var sets = [this.sockets];
if (s.destroyed) {
// If the socket was destroyed, we need to remove it from the free buffers.
sets.push(this.freeSockets);
}
sets.forEach(function(sockets) {
if (sockets[name]) {
var index = sockets[name].indexOf(s);
if (index !== -1) {
sockets[name].splice(index, 1);
if (sockets[name].length === 0) {
// don't leak
delete sockets[name];
}
}
}
});
if (this.requests[name] && this.requests[name].length) {
debug('removeSocket, have a request, make a socket');
var req = this.requests[name][0];
// If we have pending requests and a socket gets closed make a new one
this.createSocket(req, options).emit('free');
}
};
Agent.prototype.destroy = function() {
var sets = [this.freeSockets, this.sockets];
sets.forEach(function(set) {
Object.keys(set).forEach(function(name) {
set[name].forEach(function(socket) {
socket.destroy();
});
});
});
};
Agent.prototype.request = function(options, cb) {
// if (util.isString(options)) {
// options = url.parse(options);
// }
if (typeof options === 'string') {
options = url.parse(options);
}
// don't try to do dns lookups of foo.com:8080, just foo.com
if (options.hostname) {
options.host = options.hostname;
}
if (options && options.path && / /.test(options.path)) {
// The actual regex is more like /[^A-Za-z0-9\-._~!$&'()*+,;=/:@]/
// with an additional rule for ignoring percentage-escaped characters
// but that's a) hard to capture in a regular expression that performs
// well, and b) possibly too restrictive for real-world usage. That's
// why it only scans for spaces because those are guaranteed to create
// an invalid request.
throw new TypeError('Request path contains unescaped characters.');
} else if (options.protocol && options.protocol !== this.protocol) {
throw new Error('Protocol:' + options.protocol + ' not supported.');
}
options = util._extend({
agent: this,
keepAlive: this.keepAlive
}, options);
// if it's false, then make a new one, just like this one.
if (options.agent === false)
options.agent = new this.constructor();
debug('agent.request', options);
return new ClientRequest(options, cb);
};
Agent.prototype.get = function(options, cb) {
var req = this.request(options, cb);
req.end();
return req;
};
exports.globalAgent = new Agent();
}).call(this,_dereq_("C:\\Users\\Alex\\AppData\\Roaming\\npm\\node_modules\\browserify\\node_modules\\insert-module-globals\\node_modules\\process\\browser.js"))
},{"C:\\Users\\Alex\\AppData\\Roaming\\npm\\node_modules\\browserify\\node_modules\\insert-module-globals\\node_modules\\process\\browser.js":144,"events":137,"http":138,"net":127,"url":157,"util":159}],64:[function(_dereq_,module,exports){
(function (process){
/**!
* agentkeepalive - lib/agent.js
*
* refer:
* * @atimb "Real keep-alive HTTP agent": https://gist.github.com/2963672
* * https://github.com/joyent/node/blob/master/lib/http.js
* * https://github.com/joyent/node/blob/master/lib/_http_agent.js
*
* Copyright(c) 2012 - 2013 fengmk2 <fengmk2@gmail.com>
* MIT Licensed
*/
"use strict";
/**
* Module dependencies.
*/
var http = _dereq_('http');
var https = _dereq_('https');
var util = _dereq_('util');
var debug;
if (process.env.NODE_DEBUG && /agentkeepalive/.test(process.env.NODE_DEBUG)) {
debug = function (x) {
console.error.apply(console, arguments);
};
} else {
debug = function () { };
}
var OriginalAgent = http.Agent;
if (process.version.indexOf('v0.8.') === 0 || process.version.indexOf('v0.10.') === 0) {
OriginalAgent = _dereq_('./_http_agent').Agent;
debug('%s use _http_agent', process.version);
}
function Agent(options) {
options = options || {};
options.keepAlive = options.keepAlive !== false;
options.keepAliveMsecs = options.keepAliveMsecs || options.maxKeepAliveTime;
OriginalAgent.call(this, options);
var self = this;
// max requests per keepalive socket, default is 0, no limit.
self.maxKeepAliveRequests = parseInt(options.maxKeepAliveRequests, 10) || 0;
// max keep alive time, default 60 seconds.
// if set `keepAliveMsecs = 0`, will disable keepalive feature.
self.createSocketCount = 0;
self.timeoutSocketCount = 0;
self.requestFinishedCount = 0;
// override the `free` event listener
self.removeAllListeners('free');
self.on('free', function (socket, options) {
self.requestFinishedCount++;
socket._requestCount++;
var name = self.getName(options);
debug('agent.on(free)', name);
if (!socket.destroyed &&
self.requests[name] && self.requests[name].length) {
self.requests[name].shift().onSocket(socket);
if (self.requests[name].length === 0) {
// don't leak
delete self.requests[name];
}
} else {
// If there are no pending requests, then put it in
// the freeSockets pool, but only if we're allowed to do so.
var req = socket._httpMessage;
if (req &&
req.shouldKeepAlive &&
!socket.destroyed &&
self.options.keepAlive) {
var freeSockets = self.freeSockets[name];
var freeLen = freeSockets ? freeSockets.length : 0;
var count = freeLen;
if (self.sockets[name])
count += self.sockets[name].length;
if (count >= self.maxSockets || freeLen >= self.maxFreeSockets) {
self.removeSocket(socket, options);
socket.destroy();
} else {
freeSockets = freeSockets || [];
self.freeSockets[name] = freeSockets;
socket.setKeepAlive(true, self.keepAliveMsecs);
socket.unref && socket.unref();
socket._httpMessage = null;
self.removeSocket(socket, options);
freeSockets.push(socket);
// Avoid duplicitive timeout events by removing timeout listeners set on
// socket by previous requests. node does not do this normally because it
// assumes sockets are too short-lived for it to matter. It becomes a
// problem when sockets are being reused. Steps are being taken to fix
// this issue upstream in node v0.10.0.
//
// See https://github.com/joyent/node/commit/451ff1540ab536237e8d751d241d7fc3391a4087
if (self.keepAliveMsecs && socket._events && Array.isArray(socket._events.timeout)) {
socket.removeAllListeners('timeout');
// Restore the socket's setTimeout() that was remove as collateral
// damage.
socket.setTimeout(self.keepAliveMsecs, socket._maxKeepAliveTimeout);
}
}
} else {
self.removeSocket(socket, options);
socket.destroy();
}
}
});
}
util.inherits(Agent, OriginalAgent);
module.exports = Agent;
Agent.prototype.createSocket = function (req, options) {
var self = this;
var socket = OriginalAgent.prototype.createSocket.call(this, req, options);
socket._requestCount = 0;
if (self.keepAliveMsecs) {
socket._maxKeepAliveTimeout = function () {
debug('maxKeepAliveTimeout, socket destroy()');
socket.destroy();
self.timeoutSocketCount++;
};
socket.setTimeout(self.keepAliveMsecs, socket._maxKeepAliveTimeout);
// Disable Nagle's algorithm: http://blog.caustik.com/2012/04/08/scaling-node-js-to-100k-concurrent-connections/
socket.setNoDelay(true);
}
this.createSocketCount++;
return socket;
};
Agent.prototype.removeSocket = function (s, options) {
OriginalAgent.prototype.removeSocket.call(this, s, options);
var name = this.getName(options);
debug('removeSocket', name, 'destroyed:', s.destroyed);
if (s.destroyed && this.freeSockets[name]) {
var index = this.freeSockets[name].indexOf(s);
if (index !== -1) {
this.freeSockets[name].splice(index, 1);
if (this.freeSockets[name].length === 0) {
// don't leak
delete this.freeSockets[name];
}
}
}
};
function HttpsAgent(options) {
Agent.call(this, options);
this.defaultPort = 443;
this.protocol = 'https:';
}
util.inherits(HttpsAgent, Agent);
HttpsAgent.prototype.createConnection = https.globalAgent.createConnection;
HttpsAgent.prototype.getName = function(options) {
var name = Agent.prototype.getName.call(this, options);
name += ':';
if (options.ca)
name += options.ca;
name += ':';
if (options.cert)
name += options.cert;
name += ':';
if (options.ciphers)
name += options.ciphers;
name += ':';
if (options.key)
name += options.key;
name += ':';
if (options.pfx)
name += options.pfx;
name += ':';
if (options.rejectUnauthorized !== undefined)
name += options.rejectUnauthorized;
return name;
};
Agent.HttpsAgent = HttpsAgent;
}).call(this,_dereq_("C:\\Users\\Alex\\AppData\\Roaming\\npm\\node_modules\\browserify\\node_modules\\insert-module-globals\\node_modules\\process\\browser.js"))
},{"./_http_agent":63,"C:\\Users\\Alex\\AppData\\Roaming\\npm\\node_modules\\browserify\\node_modules\\insert-module-globals\\node_modules\\process\\browser.js":144,"http":138,"https":142,"util":159}],65:[function(_dereq_,module,exports){
(function (Buffer){
// Version: 3.6.8
var NOW = 1
, READY = false
, READY_BUFFER = []
, PRESENCE_SUFFIX = '-pnpres'
, DEF_WINDOWING = 10 // MILLISECONDS.
, DEF_TIMEOUT = 10000 // MILLISECONDS.
, DEF_SUB_TIMEOUT = 310 // SECONDS.
, DEF_KEEPALIVE = 60 // SECONDS (FOR TIMESYNC).
, SECOND = 1000 // A THOUSAND MILLISECONDS.
, URLBIT = '/'
, PARAMSBIT = '&'
, PRESENCE_HB_THRESHOLD = 5
, PRESENCE_HB_DEFAULT = 30
, SDK_VER = '3.6.8'
, REPL = /{([\w\-]+)}/g;
/**
* UTILITIES
*/
function unique() { return'x'+ ++NOW+''+(+new Date) }
function rnow() { return+new Date }
/**
* NEXTORIGIN
* ==========
* var next_origin = nextorigin();
*/
var nextorigin = (function() {
var max = 20
, ori = Math.floor(Math.random() * max);
return function( origin, failover ) {
return origin.indexOf('pubsub.') > 0
&& origin.replace(
'pubsub', 'ps' + (
failover ? uuid().split('-')[0] :
(++ori < max? ori : ori=1)
) ) || origin;
}
})();
/**
* Build Url
* =======
*
*/
function build_url( url_components, url_params ) {
var url = url_components.join(URLBIT)
, params = [];
if (!url_params) return url;
each( url_params, function( key, value ) {
var value_str = (typeof value == 'object')?JSON['stringify'](value):value;
(typeof value != 'undefined' &&
value != null && encode(value_str).length > 0
) && params.push(key + "=" + encode(value_str));
} );
url += "?" + params.join(PARAMSBIT);
return url;
}
/**
* UPDATER
* =======
* var timestamp = unique();
*/
function updater( fun, rate ) {
var timeout
, last = 0
, runnit = function() {
if (last + rate > rnow()) {
clearTimeout(timeout);
timeout = setTimeout( runnit, rate );
}
else {
last = rnow();
fun();
}
};
return runnit;
}
/**
* GREP
* ====
* var list = grep( [1,2,3], function(item) { return item % 2 } )
*/
function grep( list, fun ) {
var fin = [];
each( list || [], function(l) { fun(l) && fin.push(l) } );
return fin
}
/**
* SUPPLANT
* ========
* var text = supplant( 'Hello {name}!', { name : 'John' } )
*/
function supplant( str, values ) {
return str.replace( REPL, function( _, match ) {
return values[match] || _
} );
}
/**
* timeout
* =======
* timeout( function(){}, 100 );
*/
function timeout( fun, wait ) {
return setTimeout( fun, wait );
}
/**
* uuid
* ====
* var my_uuid = uuid();
*/
function uuid(callback) {
var u = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,
function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
});
if (callback) callback(u);
return u;
}
function isArray(arg) {
return !!arg && (Array.isArray && Array.isArray(arg) || typeof(arg.length) === "number")
}
/**
* EACH
* ====
* each( [1,2,3], function(item) { } )
*/
function each( o, f) {
if ( !o || !f ) return;
if ( isArray(o) )
for ( var i = 0, l = o.length; i < l; )
f.call( o[i], o[i], i++ );
else
for ( var i in o )
o.hasOwnProperty &&
o.hasOwnProperty(i) &&
f.call( o[i], i, o[i] );
}
/**
* MAP
* ===
* var list = map( [1,2,3], function(item) { return item + 1 } )
*/
function map( list, fun ) {
var fin = [];
each( list || [], function( k, v ) { fin.push(fun( k, v )) } );
return fin;
}
/**
* ENCODE
* ======
* var encoded_data = encode('path');
*/
function encode(path) { return encodeURIComponent(path) }
/**
* Generate Subscription Channel List
* ==================================
* generate_channel_list(channels_object);
*/
function generate_channel_list(channels, nopresence) {
var list = [];
each( channels, function( channel, status ) {
if (nopresence) {
if(channel.search('-pnpres') < 0) {
if (status.subscribed) list.push(channel);
}
} else {
if (status.subscribed) list.push(channel);
}
});
return list.sort();
}
// PUBNUB READY TO CONNECT
function ready() { timeout( function() {
if (READY) return;
READY = 1;
each( READY_BUFFER, function(connect) { connect() } );
}, SECOND ); }
function PNmessage(args) {
msg = args || {'apns' : {}},
msg['getPubnubMessage'] = function() {
var m = {};
if (Object.keys(msg['apns']).length) {
m['pn_apns'] = {
'aps' : {
'alert' : msg['apns']['alert'] ,
'badge' : msg['apns']['badge']
}
}
for (var k in msg['apns']) {
m['pn_apns'][k] = msg['apns'][k];
}
var exclude1 = ['badge','alert'];
for (var k in exclude1) {
//console.log(exclude[k]);
delete m['pn_apns'][exclude1[k]];
}
}
if (msg['gcm']) {
m['pn_gcm'] = {
'data' : msg['gcm']
}
}
for (var k in msg) {
m[k] = msg[k];
}
var exclude = ['apns','gcm','publish', 'channel','callback','error'];
for (var k in exclude) {
delete m[exclude[k]];
}
return m;
};
msg['publish'] = function() {
var m = msg.getPubnubMessage();
if (msg['pubnub'] && msg['channel']) {
msg['pubnub'].publish({
'message' : m,
'channel' : msg['channel'],
'callback' : msg['callback'],
'error' : msg['error']
})
}
};
return msg;
}
function PN_API(setup) {
var SUB_WINDOWING = +setup['windowing'] || DEF_WINDOWING
, SUB_TIMEOUT = (+setup['timeout'] || DEF_SUB_TIMEOUT) * SECOND
, KEEPALIVE = (+setup['keepalive'] || DEF_KEEPALIVE) * SECOND
, NOLEAVE = setup['noleave'] || 0
, PUBLISH_KEY = setup['publish_key'] || 'demo'
, SUBSCRIBE_KEY = setup['subscribe_key'] || 'demo'
, AUTH_KEY = setup['auth_key'] || ''
, SECRET_KEY = setup['secret_key'] || ''
, hmac_SHA256 = setup['hmac_SHA256']
, SSL = setup['ssl'] ? 's' : ''
, ORIGIN = 'http'+SSL+'://'+(setup['origin']||'pubsub.pubnub.com')
, STD_ORIGIN = nextorigin(ORIGIN)
, SUB_ORIGIN = nextorigin(ORIGIN)
, CONNECT = function(){}
, PUB_QUEUE = []
, TIME_DRIFT = 0
, SUB_CALLBACK = 0
, SUB_CHANNEL = 0
, SUB_RECEIVER = 0
, SUB_RESTORE = setup['restore'] || 0
, SUB_BUFF_WAIT = 0
, TIMETOKEN = 0
, RESUMED = false
, CHANNELS = {}
, STATE = {}
, PRESENCE_HB_TIMEOUT = null
, PRESENCE_HB = validate_presence_heartbeat(setup['heartbeat'] || setup['pnexpires'] || 0, setup['error'])
, PRESENCE_HB_INTERVAL = setup['heartbeat_interval'] || PRESENCE_HB - 3
, PRESENCE_HB_RUNNING = false
, NO_WAIT_FOR_PENDING = setup['no_wait_for_pending']
, COMPATIBLE_35 = setup['compatible_3.5'] || false
, xdr = setup['xdr']
, params = setup['params'] || {}
, error = setup['error'] || function() {}
, _is_online = setup['_is_online'] || function() { return 1 }
, jsonp_cb = setup['jsonp_cb'] || function() { return 0 }
, db = setup['db'] || {'get': function(){}, 'set': function(){}}
, CIPHER_KEY = setup['cipher_key']
, UUID = setup['uuid'] || ( db && db['get'](SUBSCRIBE_KEY+'uuid') || '');
var crypto_obj = setup['crypto_obj'] ||
{
'encrypt' : function(a,key){ return a},
'decrypt' : function(b,key){return b}
};
function _get_url_params(data) {
if (!data) data = {};
each( params , function( key, value ) {
if (!(key in data)) data[key] = value;
});
return data;
}
function _object_to_key_list(o) {
var l = []
each( o , function( key, value ) {
l.push(key);
});
return l;
}
function _object_to_key_list_sorted(o) {
return _object_to_key_list(o).sort();
}
function _get_pam_sign_input_from_params(params) {
var si = "";
var l = _object_to_key_list_sorted(params);
for (var i in l) {
var k = l[i]
si += k + "=" + encode(params[k]) ;
if (i != l.length - 1) si += "&"
}
return si;
}
function validate_presence_heartbeat(heartbeat, cur_heartbeat, error) {
var err = false;
if (typeof heartbeat === 'number') {
if (heartbeat > PRESENCE_HB_THRESHOLD || heartbeat == 0)
err = false;
else
err = true;
} else if(typeof heartbeat === 'boolean'){
if (!heartbeat) {
return 0;
} else {
return PRESENCE_HB_DEFAULT;
}
} else {
err = true;
}
if (err) {
error && error("Presence Heartbeat value invalid. Valid range ( x > " + PRESENCE_HB_THRESHOLD + " or x = 0). Current Value : " + (cur_heartbeat || PRESENCE_HB_THRESHOLD));
return cur_heartbeat || PRESENCE_HB_THRESHOLD;
} else return heartbeat;
}
function encrypt(input, key) {
return crypto_obj['encrypt'](input, key || CIPHER_KEY) || input;
}
function decrypt(input, key) {
return crypto_obj['decrypt'](input, key || CIPHER_KEY) ||
crypto_obj['decrypt'](input, CIPHER_KEY) ||
input;
}
function error_common(message, callback) {
callback && callback({ 'error' : message || "error occurred"});
error && error(message);
}
function _presence_heartbeat() {
clearTimeout(PRESENCE_HB_TIMEOUT);
if (!PRESENCE_HB_INTERVAL || PRESENCE_HB_INTERVAL >= 500 || PRESENCE_HB_INTERVAL < 1 || !generate_channel_list(CHANNELS,true).length){
PRESENCE_HB_RUNNING = false;
return;
}
PRESENCE_HB_RUNNING = true;
SELF['presence_heartbeat']({
'callback' : function(r) {
PRESENCE_HB_TIMEOUT = timeout( _presence_heartbeat, (PRESENCE_HB_INTERVAL) * SECOND );
},
'error' : function(e) {
error && error("Presence Heartbeat unable to reach Pubnub servers." + JSON.stringify(e));
PRESENCE_HB_TIMEOUT = timeout( _presence_heartbeat, (PRESENCE_HB_INTERVAL) * SECOND );
}
});
}
function start_presence_heartbeat() {
!PRESENCE_HB_RUNNING && _presence_heartbeat();
}
function publish(next) {
if (NO_WAIT_FOR_PENDING) {
if (!PUB_QUEUE.length) return;
} else {
if (next) PUB_QUEUE.sending = 0;
if ( PUB_QUEUE.sending || !PUB_QUEUE.length ) return;
PUB_QUEUE.sending = 1;
}
xdr(PUB_QUEUE.shift());
}
function each_channel(callback) {
var count = 0;
each( generate_channel_list(CHANNELS), function(channel) {
var chan = CHANNELS[channel];
if (!chan) return;
count++;
(callback||function(){})(chan);
} );
return count;
}
function _invoke_callback(response, callback, err) {
if (typeof response == 'object') {
if (response['error'] && response['message'] && response['payload']) {
err({'message' : response['message'], 'payload' : response['payload']});
return;
}
if (response['payload']) {
callback(response['payload']);
return;
}
}
callback(response);
}
function _invoke_error(response,err) {
if (typeof response == 'object' && response['error'] &&
response['message'] && response['payload']) {
err({'message' : response['message'], 'payload' : response['payload']});
} else err(response);
}
// Announce Leave Event
var SELF = {
'LEAVE' : function( channel, blocking, callback, error ) {
var data = { 'uuid' : UUID, 'auth' : AUTH_KEY }
, origin = nextorigin(ORIGIN)
, callback = callback || function(){}
, err = error || function(){}
, jsonp = jsonp_cb();
// Prevent Leaving a Presence Channel
if (channel.indexOf(PRESENCE_SUFFIX) > 0) return true;
if (COMPATIBLE_35) {
if (!SSL) return false;
if (jsonp == '0') return false;
}
if (NOLEAVE) return false;
if (jsonp != '0') data['callback'] = jsonp;
xdr({
blocking : blocking || SSL,
timeout : 2000,
callback : jsonp,
data : _get_url_params(data),
success : function(response) {
_invoke_callback(response, callback, err);
},
fail : function(response) {
_invoke_error(response, err);
},
url : [
origin, 'v2', 'presence', 'sub_key',
SUBSCRIBE_KEY, 'channel', encode(channel), 'leave'
]
});
return true;
},
'set_resumed' : function(resumed) {
RESUMED = resumed;
},
'get_cipher_key' : function() {
return CIPHER_KEY;
},
'set_cipher_key' : function(key) {
CIPHER_KEY = key;
},
'raw_encrypt' : function(input, key) {
return encrypt(input, key);
},
'raw_decrypt' : function(input, key) {
return decrypt(input, key);
},
'get_heartbeat' : function() {
return PRESENCE_HB;
},
'set_heartbeat' : function(heartbeat) {
PRESENCE_HB = validate_presence_heartbeat(heartbeat, PRESENCE_HB_INTERVAL, error);
PRESENCE_HB_INTERVAL = (PRESENCE_HB - 3 >= 1)?PRESENCE_HB - 3:1;
CONNECT();
_presence_heartbeat();
},
'get_heartbeat_interval' : function() {
return PRESENCE_HB_INTERVAL;
},
'set_heartbeat_interval' : function(heartbeat_interval) {
PRESENCE_HB_INTERVAL = heartbeat_interval;
_presence_heartbeat();
},
'get_version' : function() {
return SDK_VER;
},
'getGcmMessageObject' : function(obj) {
return {
'data' : obj
}
},
'getApnsMessageObject' : function(obj) {
var x = {
'aps' : { 'badge' : 1, 'alert' : ''}
}
for (k in obj) {
k[x] = obj[k];
}
return x;
},
'newPnMessage' : function() {
var x = {};
if (gcm) x['pn_gcm'] = gcm;
if (apns) x['pn_apns'] = apns;
for ( k in n ) {
x[k] = n[k];
}
return x;
},
'_add_param' : function(key,val) {
params[key] = val;
},
/*
PUBNUB.history({
channel : 'my_chat_channel',
limit : 100,
callback : function(history) { }
});
*/
'history' : function( args, callback ) {
var callback = args['callback'] || callback
, count = args['count'] || args['limit'] || 100
, reverse = args['reverse'] || "false"
, err = args['error'] || function(){}
, auth_key = args['auth_key'] || AUTH_KEY
, cipher_key = args['cipher_key']
, channel = args['channel']
, start = args['start']
, end = args['end']
, include_token = args['include_token']
, params = {}
, jsonp = jsonp_cb();
// Make sure we have a Channel
if (!channel) return error('Missing Channel');
if (!callback) return error('Missing Callback');
if (!SUBSCRIBE_KEY) return error('Missing Subscribe Key');
params['stringtoken'] = 'true';
params['count'] = count;
params['reverse'] = reverse;
params['auth'] = auth_key;
if (jsonp) params['callback'] = jsonp;
if (start) params['start'] = start;
if (end) params['end'] = end;
if (include_token) params['include_token'] = 'true';
// Send Message
xdr({
callback : jsonp,
data : _get_url_params(params),
success : function(response) {
if (typeof response == 'object' && response['error']) {
err({'message' : response['message'], 'payload' : response['payload']});
return;
}
var messages = response[0];
var decrypted_messages = [];
for (var a = 0; a < messages.length; a++) {
var new_message = decrypt(messages[a],cipher_key);
try {
decrypted_messages['push'](JSON['parse'](new_message));
} catch (e) {
decrypted_messages['push']((new_message));
}
}
callback([decrypted_messages, response[1], response[2]]);
},
fail : function(response) {
_invoke_error(response, err);
},
url : [
STD_ORIGIN, 'v2', 'history', 'sub-key',
SUBSCRIBE_KEY, 'channel', encode(channel)
]
});
},
/*
PUBNUB.replay({
source : 'my_channel',
destination : 'new_channel'
});
*/
'replay' : function(args, callback) {
var callback = callback || args['callback'] || function(){}
, auth_key = args['auth_key'] || AUTH_KEY
, source = args['source']
, destination = args['destination']
, stop = args['stop']
, start = args['start']
, end = args['end']
, reverse = args['reverse']
, limit = args['limit']
, jsonp = jsonp_cb()
, data = {}
, url;
// Check User Input
if (!source) return error('Missing Source Channel');
if (!destination) return error('Missing Destination Channel');
if (!PUBLISH_KEY) return error('Missing Publish Key');
if (!SUBSCRIBE_KEY) return error('Missing Subscribe Key');
// Setup URL Params
if (jsonp != '0') data['callback'] = jsonp;
if (stop) data['stop'] = 'all';
if (reverse) data['reverse'] = 'true';
if (start) data['start'] = start;
if (end) data['end'] = end;
if (limit) data['count'] = limit;
data['auth'] = auth_key;
// Compose URL Parts
url = [
STD_ORIGIN, 'v1', 'replay',
PUBLISH_KEY, SUBSCRIBE_KEY,
source, destination
];
// Start (or Stop) Replay!
xdr({
callback : jsonp,
success : function(response) {
_invoke_callback(response, callback, err);
},
fail : function() { callback([ 0, 'Disconnected' ]) },
url : url,
data : _get_url_params(data)
});
},
/*
PUBNUB.auth('AJFLKAJSDKLA');
*/
'auth' : function(auth) {
AUTH_KEY = auth;
CONNECT();
},
/*
PUBNUB.time(function(time){ });
*/
'time' : function(callback) {
var jsonp = jsonp_cb();
xdr({
callback : jsonp,
data : _get_url_params({ 'uuid' : UUID, 'auth' : AUTH_KEY }),
timeout : SECOND * 5,
url : [STD_ORIGIN, 'time', jsonp],
success : function(response) { callback(response[0]) },
fail : function() { callback(0) }
});
},
/*
PUBNUB.publish({
channel : 'my_chat_channel',
message : 'hello!'
});
*/
'publish' : function( args, callback ) {
var msg = args['message'];
if (!msg) return error('Missing Message');
var callback = callback || args['callback'] || msg['callback'] || function(){}
, channel = args['channel'] || msg['channel']
, auth_key = args['auth_key'] || AUTH_KEY
, cipher_key = args['cipher_key']
, err = args['error'] || msg['error'] || function() {}
, post = args['post'] || false
, store = ('store_in_history' in args) ? args['store_in_history']: true
, jsonp = jsonp_cb()
, add_msg = 'push'
, url;
if (args['prepend']) add_msg = 'unshift'
if (!channel) return error('Missing Channel');
if (!PUBLISH_KEY) return error('Missing Publish Key');
if (!SUBSCRIBE_KEY) return error('Missing Subscribe Key');
if (msg['getPubnubMessage']) {
msg = msg['getPubnubMessage']();
}
// If trying to send Object
msg = JSON['stringify'](encrypt(msg, cipher_key));
// Create URL
url = [
STD_ORIGIN, 'publish',
PUBLISH_KEY, SUBSCRIBE_KEY,
0, encode(channel),
jsonp, encode(msg)
];
params = { 'uuid' : UUID, 'auth' : auth_key }
if (!store) params['store'] ="0"
// Queue Message Send
PUB_QUEUE[add_msg]({
callback : jsonp,
timeout : SECOND * 5,
url : url,
data : _get_url_params(params),
fail : function(response){
_invoke_error(response, err);
publish(1);
},
success : function(response) {
_invoke_callback(response, callback, err);
publish(1);
},
mode : (post)?'POST':'GET'
});
// Send Message
publish();
},
/*
PUBNUB.unsubscribe({ channel : 'my_chat' });
*/
'unsubscribe' : function(args, callback) {
var channel = args['channel']
, callback = callback || args['callback'] || function(){}
, err = args['error'] || function(){};
TIMETOKEN = 0;
//SUB_RESTORE = 1; REVISIT !!!!
// Prepare Channel(s)
channel = map( (
channel.join ? channel.join(',') : ''+channel
).split(','), function(channel) {
if (!CHANNELS[channel]) return;
return channel + ',' + channel + PRESENCE_SUFFIX;
} ).join(',');
// Iterate over Channels
each( channel.split(','), function(channel) {
var CB_CALLED = true;
if (!channel) return;
if (READY) {
CB_CALLED = SELF['LEAVE']( channel, 0 , callback, err);
}
if (!CB_CALLED) callback({action : "leave"});
CHANNELS[channel] = 0;
if (channel in STATE) delete STATE[channel];
} );
// Reset Connection if Count Less
CONNECT();
},
/*
PUBNUB.subscribe({
channel : 'my_chat'
callback : function(message) { }
});
*/
'subscribe' : function( args, callback ) {
var channel = args['channel']
, callback = callback || args['callback']
, callback = callback || args['message']
, auth_key = args['auth_key'] || AUTH_KEY
, connect = args['connect'] || function(){}
, reconnect = args['reconnect'] || function(){}
, disconnect = args['disconnect'] || function(){}
, errcb = args['error'] || function(){}
, idlecb = args['idle'] || function(){}
, presence = args['presence'] || 0
, noheresync = args['noheresync'] || 0
, backfill = args['backfill'] || 0
, timetoken = args['timetoken'] || 0
, sub_timeout = args['timeout'] || SUB_TIMEOUT
, windowing = args['windowing'] || SUB_WINDOWING
, state = args['state']
, heartbeat = args['heartbeat'] || args['pnexpires']
, restore = args['restore'] || SUB_RESTORE;
// Restore Enabled?
SUB_RESTORE = restore;
// Always Reset the TT
TIMETOKEN = timetoken;
// Make sure we have a Channel
if (!channel) return error('Missing Channel');
if (!callback) return error('Missing Callback');
if (!SUBSCRIBE_KEY) return error('Missing Subscribe Key');
if (heartbeat || heartbeat === 0) {
SELF['set_heartbeat'](heartbeat);
}
// Setup Channel(s)
each( (channel.join ? channel.join(',') : ''+channel).split(','),
function(channel) {
var settings = CHANNELS[channel] || {};
// Store Channel State
CHANNELS[SUB_CHANNEL = channel] = {
name : channel,
connected : settings.connected,
disconnected : settings.disconnected,
subscribed : 1,
callback : SUB_CALLBACK = callback,
'cipher_key' : args['cipher_key'],
connect : connect,
disconnect : disconnect,
reconnect : reconnect
};
if (state) {
if (channel in state) {
STATE[channel] = state[channel];
} else {
STATE[channel] = state;
}
}
// Presence Enabled?
if (!presence) return;
// Subscribe Presence Channel
SELF['subscribe']({
'channel' : channel + PRESENCE_SUFFIX,
'callback' : presence,
'restore' : restore
});
// Presence Subscribed?
if (settings.subscribed) return;
// See Who's Here Now?
if (noheresync) return;
SELF['here_now']({
'channel' : channel,
'callback' : function(here) {
each( 'uuids' in here ? here['uuids'] : [],
function(uid) { presence( {
'action' : 'join',
'uuid' : uid,
'timestamp' : Math.floor(rnow() / 1000),
'occupancy' : here['occupancy'] || 1
}, here, channel ); } );
}
});
} );
// Test Network Connection
function _test_connection(success) {
if (success) {
// Begin Next Socket Connection
timeout( CONNECT, SECOND );
}
else {
// New Origin on Failed Connection
STD_ORIGIN = nextorigin( ORIGIN, 1 );
SUB_ORIGIN = nextorigin( ORIGIN, 1 );
// Re-test Connection
timeout( function() {
SELF['time'](_test_connection);
}, SECOND );
}
// Disconnect & Reconnect
each_channel(function(channel){
// Reconnect
if (success && channel.disconnected) {
channel.disconnected = 0;
return channel.reconnect(channel.name);
}
// Disconnect
if (!success && !channel.disconnected) {
channel.disconnected = 1;
channel.disconnect(channel.name);
}
});
}
// Evented Subscribe
function _connect() {
var jsonp = jsonp_cb()
, channels = generate_channel_list(CHANNELS).join(',');
// Stop Connection
if (!channels) return;
// Connect to PubNub Subscribe Servers
_reset_offline();
var data = _get_url_params({ 'uuid' : UUID, 'auth' : auth_key });
var st = JSON.stringify(STATE);
if (st.length > 2) data['state'] = JSON.stringify(STATE);
if (PRESENCE_HB) data['heartbeat'] = PRESENCE_HB;
start_presence_heartbeat();
SUB_RECEIVER = xdr({
timeout : sub_timeout,
callback : jsonp,
fail : function(response) {
_invoke_error(response, errcb);
//SUB_RECEIVER = null;
SELF['time'](_test_connection);
},
data : _get_url_params(data),
url : [
SUB_ORIGIN, 'subscribe',
SUBSCRIBE_KEY, encode(channels),
jsonp, TIMETOKEN
],
success : function(messages) {
//SUB_RECEIVER = null;
// Check for Errors
if (!messages || (
typeof messages == 'object' &&
'error' in messages &&
messages['error']
)) {
errcb(messages['error']);
return timeout( CONNECT, SECOND );
}
// User Idle Callback
idlecb(messages[1]);
// Restore Previous Connection Point if Needed
TIMETOKEN = !TIMETOKEN &&
SUB_RESTORE &&
db['get'](SUBSCRIBE_KEY) || messages[1];
// Connect
each_channel(function(channel){
if (channel.connected) return;
channel.connected = 1;
channel.connect(channel.name);
});
if (RESUMED && !SUB_RESTORE) {
TIMETOKEN = 0;
RESUMED = false;
// Update Saved Timetoken
db['set']( SUBSCRIBE_KEY, 0 );
timeout( _connect, windowing );
return;
}
// Invoke Memory Catchup and Receive Up to 100
// Previous Messages from the Queue.
if (backfill) {
TIMETOKEN = 10000;
backfill = 0;
}
// Update Saved Timetoken
db['set']( SUBSCRIBE_KEY, messages[1] );
// Route Channel <---> Callback for Message
var next_callback = (function() {
var channels = (messages.length>2?messages[2]:map(
generate_channel_list(CHANNELS), function(chan) { return map(
Array(messages[0].length)
.join(',').split(','),
function() { return chan; }
) }).join(','));
var list = channels.split(',');
return function() {
var channel = list.shift()||SUB_CHANNEL;
return [
(CHANNELS[channel]||{})
.callback||SUB_CALLBACK,
channel.split(PRESENCE_SUFFIX)[0]
];
};
})();
var latency = detect_latency(+messages[1]);
each( messages[0], function(msg) {
var next = next_callback();
var decrypted_msg = decrypt(msg,
(CHANNELS[next[1]])?CHANNELS[next[1]]['cipher_key']:null);
next[0]( decrypted_msg, messages, next[1], latency);
});
timeout( _connect, windowing );
}
});
}
CONNECT = function() {
_reset_offline();
timeout( _connect, windowing );
};
// Reduce Status Flicker
if (!READY) return READY_BUFFER.push(CONNECT);
// Connect Now
CONNECT();
},
/*
PUBNUB.here_now({ channel : 'my_chat', callback : fun });
*/
'here_now' : function( args, callback ) {
var callback = args['callback'] || callback
, err = args['error'] || function(){}
, auth_key = args['auth_key'] || AUTH_KEY
, channel = args['channel']
, jsonp = jsonp_cb()
, uuids = ('uuids' in args) ? args['uuids'] : true
, state = args['state']
, data = { 'uuid' : UUID, 'auth' : auth_key };
if (!uuids) data['disable_uuids'] = 1;
if (state) data['state'] = 1;
// Make sure we have a Channel
if (!callback) return error('Missing Callback');
if (!SUBSCRIBE_KEY) return error('Missing Subscribe Key');
var url = [
STD_ORIGIN, 'v2', 'presence',
'sub_key', SUBSCRIBE_KEY
];
channel && url.push('channel') && url.push(encode(channel));
if (jsonp != '0') { data['callback'] = jsonp; }
xdr({
callback : jsonp,
data : _get_url_params(data),
success : function(response) {
_invoke_callback(response, callback, err);
},
fail : function(response) {
_invoke_error(response, err);
},
url : url
});
},
/*
PUBNUB.current_channels_by_uuid({ channel : 'my_chat', callback : fun });
*/
'where_now' : function( args, callback ) {
var callback = args['callback'] || callback
, err = args['error'] || function(){}
, auth_key = args['auth_key'] || AUTH_KEY
, jsonp = jsonp_cb()
, uuid = args['uuid'] || UUID
, data = { 'auth' : auth_key };
// Make sure we have a Channel
if (!callback) return error('Missing Callback');
if (!SUBSCRIBE_KEY) return error('Missing Subscribe Key');
if (jsonp != '0') { data['callback'] = jsonp; }
xdr({
callback : jsonp,
data : _get_url_params(data),
success : function(response) {
_invoke_callback(response, callback, err);
},
fail : function(response) {
_invoke_error(response, err);
},
url : [
STD_ORIGIN, 'v2', 'presence',
'sub_key', SUBSCRIBE_KEY,
'uuid', encode(uuid)
]
});
},
'state' : function(args, callback) {
var callback = args['callback'] || callback || function(r) {}
, err = args['error'] || function(){}
, auth_key = args['auth_key'] || AUTH_KEY
, jsonp = jsonp_cb()
, state = args['state']
, uuid = args['uuid'] || UUID
, channel = args['channel']
, url
, data = _get_url_params({ 'auth' : auth_key });
// Make sure we have a Channel
if (!SUBSCRIBE_KEY) return error('Missing Subscribe Key');
if (!uuid) return error('Missing UUID');
if (!channel) return error('Missing Channel');
if (jsonp != '0') { data['callback'] = jsonp; }
if (CHANNELS[channel] && CHANNELS[channel].subscribed && state) STATE[channel] = state;
data['state'] = JSON.stringify(state);
if (state) {
url = [
STD_ORIGIN, 'v2', 'presence',
'sub-key', SUBSCRIBE_KEY,
'channel', encode(channel),
'uuid', uuid, 'data'
]
} else {
url = [
STD_ORIGIN, 'v2', 'presence',
'sub-key', SUBSCRIBE_KEY,
'channel', encode(channel),
'uuid', encode(uuid)
]
}
xdr({
callback : jsonp,
data : _get_url_params(data),
success : function(response) {
_invoke_callback(response, callback, err);
},
fail : function(response) {
_invoke_error(response, err);
},
url : url
});
},
/*
PUBNUB.grant({
channel : 'my_chat',
callback : fun,
error : fun,
ttl : 24 * 60, // Minutes
read : true,
write : true,
auth_key : '3y8uiajdklytowsj'
});
*/
'grant' : function( args, callback ) {
var callback = args['callback'] || callback
, err = args['error'] || function(){}
, channel = args['channel']
, jsonp = jsonp_cb()
, ttl = args['ttl']
, r = (args['read'] )?"1":"0"
, w = (args['write'])?"1":"0"
, auth_key = args['auth_key'];
if (!callback) return error('Missing Callback');
if (!SUBSCRIBE_KEY) return error('Missing Subscribe Key');
if (!PUBLISH_KEY) return error('Missing Publish Key');
if (!SECRET_KEY) return error('Missing Secret Key');
var timestamp = Math.floor(new Date().getTime() / 1000)
, sign_input = SUBSCRIBE_KEY + "\n" + PUBLISH_KEY + "\n"
+ "grant" + "\n";
var data = {
'w' : w,
'r' : r,
'timestamp' : timestamp
};
if (channel != 'undefined' && channel != null && channel.length > 0) data['channel'] = channel;
if (jsonp != '0') { data['callback'] = jsonp; }
if (ttl || ttl === 0) data['ttl'] = ttl;
if (auth_key) data['auth'] = auth_key;
data = _get_url_params(data)
if (!auth_key) delete data['auth'];
sign_input += _get_pam_sign_input_from_params(data);
var signature = hmac_SHA256( sign_input, SECRET_KEY );
signature = signature.replace( /\+/g, "-" );
signature = signature.replace( /\//g, "_" );
data['signature'] = signature;
xdr({
callback : jsonp,
data : data,
success : function(response) {
_invoke_callback(response, callback, err);
},
fail : function(response) {
_invoke_error(response, err);
},
url : [
STD_ORIGIN, 'v1', 'auth', 'grant' ,
'sub-key', SUBSCRIBE_KEY
]
});
},
/*
PUBNUB.audit({
channel : 'my_chat',
callback : fun,
error : fun,
read : true,
write : true,
auth_key : '3y8uiajdklytowsj'
});
*/
'audit' : function( args, callback ) {
var callback = args['callback'] || callback
, err = args['error'] || function(){}
, channel = args['channel']
, auth_key = args['auth_key']
, jsonp = jsonp_cb();
// Make sure we have a Channel
if (!callback) return error('Missing Callback');
if (!SUBSCRIBE_KEY) return error('Missing Subscribe Key');
if (!PUBLISH_KEY) return error('Missing Publish Key');
if (!SECRET_KEY) return error('Missing Secret Key');
var timestamp = Math.floor(new Date().getTime() / 1000)
, sign_input = SUBSCRIBE_KEY + "\n"
+ PUBLISH_KEY + "\n"
+ "audit" + "\n";
var data = {'timestamp' : timestamp };
if (jsonp != '0') { data['callback'] = jsonp; }
if (channel != 'undefined' && channel != null && channel.length > 0) data['channel'] = channel;
if (auth_key) data['auth'] = auth_key;
data = _get_url_params(data)
if (!auth_key) delete data['auth'];
sign_input += _get_pam_sign_input_from_params(data);
var signature = hmac_SHA256( sign_input, SECRET_KEY );
signature = signature.replace( /\+/g, "-" );
signature = signature.replace( /\//g, "_" );
data['signature'] = signature;
xdr({
callback : jsonp,
data : data,
success : function(response) {
_invoke_callback(response, callback, err);
},
fail : function(response) {
_invoke_error(response, err);
},
url : [
STD_ORIGIN, 'v1', 'auth', 'audit' ,
'sub-key', SUBSCRIBE_KEY
]
});
},
/*
PUBNUB.revoke({
channel : 'my_chat',
callback : fun,
error : fun,
auth_key : '3y8uiajdklytowsj'
});
*/
'revoke' : function( args, callback ) {
args['read'] = false;
args['write'] = false;
SELF['grant']( args, callback );
},
'set_uuid' : function(uuid) {
UUID = uuid;
CONNECT();
},
'get_uuid' : function() {
return UUID;
},
'presence_heartbeat' : function(args) {
var callback = args['callback'] || function() {}
var err = args['error'] || function() {}
var jsonp = jsonp_cb();
var data = { 'uuid' : UUID, 'auth' : AUTH_KEY };
var st = JSON['stringify'](STATE);
if (st.length > 2) data['state'] = JSON['stringify'](STATE);
if (PRESENCE_HB > 0 && PRESENCE_HB < 320) data['heartbeat'] = PRESENCE_HB;
if (jsonp != '0') { data['callback'] = jsonp; }
xdr({
callback : jsonp,
data : _get_url_params(data),
timeout : SECOND * 5,
url : [
STD_ORIGIN, 'v2', 'presence',
'sub-key', SUBSCRIBE_KEY,
'channel' , encode(generate_channel_list(CHANNELS, true)['join'](',')),
'heartbeat'
],
success : function(response) {
_invoke_callback(response, callback, err);
},
fail : function(response) { _invoke_error(response, err); }
});
},
// Expose PUBNUB Functions
'xdr' : xdr,
'ready' : ready,
'db' : db,
'uuid' : uuid,
'map' : map,
'each' : each,
'each-channel' : each_channel,
'grep' : grep,
'offline' : function(){_reset_offline(1, { "message":"Offline. Please check your network settings." })},
'supplant' : supplant,
'now' : rnow,
'unique' : unique,
'updater' : updater
};
function _poll_online() {
_is_online() || _reset_offline( 1, {
"error" : "Offline. Please check your network settings. "
});
timeout( _poll_online, SECOND );
}
function _poll_online2() {
SELF['time'](function(success){
detect_time_detla( function(){}, success );
success || _reset_offline( 1, {
"error" : "Heartbeat failed to connect to Pubnub Servers." +
"Please check your network settings."
});
timeout( _poll_online2, KEEPALIVE );
});
}
function _reset_offline(err, msg) {
SUB_RECEIVER && SUB_RECEIVER(err, msg);
SUB_RECEIVER = null;
}
if (!UUID) UUID = SELF['uuid']();
db['set']( SUBSCRIBE_KEY + 'uuid', UUID );
timeout( _poll_online, SECOND );
timeout( _poll_online2, KEEPALIVE );
PRESENCE_HB_TIMEOUT = timeout( start_presence_heartbeat, ( PRESENCE_HB_INTERVAL - 3 ) * SECOND ) ;
// Detect Age of Message
function detect_latency(tt) {
var adjusted_time = rnow() - TIME_DRIFT;
return adjusted_time - tt / 10000;
}
detect_time_detla();
function detect_time_detla( cb, time ) {
var stime = rnow();
time && calculate(time) || SELF['time'](calculate);
function calculate(time) {
if (!time) return;
var ptime = time / 10000
, latency = (rnow() - stime) / 2;
TIME_DRIFT = rnow() - (ptime + latency);
cb && cb(TIME_DRIFT);
}
}
return SELF;
}
/* ---------------------------------------------------------------------------
WAIT! - This file depends on instructions from the PUBNUB Cloud.
http://www.pubnub.com/account
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
PubNub Real-time Cloud-Hosted Push API and Push Notification Client Frameworks
Copyright (c) 2011 TopMambo Inc.
http://www.pubnub.com/
http://www.pubnub.com/terms
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
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.
--------------------------------------------------------------------------- */
/**
* UTIL LOCALS
*/
var NOW = 1
, http = _dereq_('http')
, https = _dereq_('https')
, keepAliveAgent = new (keepAliveIsEmbedded() ? http.Agent : _dereq_('agentkeepalive'))({
keepAlive: true,
keepAliveMsecs: 300000,
maxSockets: 5
})
, XHRTME = 310000
, DEF_TIMEOUT = 10000
, SECOND = 1000
, PNSDK = 'PubNub-JS-' + 'Nodejs' + '/' + '3.6.8'
, crypto = _dereq_('crypto')
, proxy = null
, XORIGN = 1;
function get_hmac_SHA256(data, key) {
return crypto.createHmac('sha256',
new Buffer(key, 'utf8')).update(data).digest('base64');
}
/**
* ERROR
* ===
* error('message');
*/
function error(message) { console['error'](message) }
/**
* Request
* =======
* xdr({
* url : ['http://www.blah.com/url'],
* success : function(response) {},
* fail : function() {}
* });
*/
function xdr( setup ) {
var request
, response
, success = setup.success || function(){}
, fail = setup.fail || function(){}
, origin = setup.origin || 'pubsub.pubnub.com'
, ssl = setup.ssl
, failed = 0
, complete = 0
, loaded = 0
, mode = setup['mode'] || 'GET'
, data = setup['data'] || {}
, xhrtme = setup.timeout || DEF_TIMEOUT
, body = ''
, finished = function() {
if (loaded) return;
loaded = 1;
clearTimeout(timer);
try { response = JSON['parse'](body); }
catch (r) { return done(1); }
success(response);
}
, done = function(failed, response) {
if (complete) return;
complete = 1;
clearTimeout(timer);
if (request) {
request.on('error', function(){});
request.on('data', function(){});
request.on('end', function(){});
request.abort && request.abort();
request = null;
}
failed && fail(response);
}
, timer = timeout( function(){done(1);} , xhrtme );
data['pnsdk'] = PNSDK;
var options = {};
var headers = {};
var payload = '';
if (mode == 'POST')
payload = decodeURIComponent(setup.url.pop());
var url = build_url( setup.url, data );
if (!ssl) ssl = (url.split('://')[0] == 'https')?true:false;
url = '/' + url.split('/').slice(3).join('/');
var origin = setup.url[0].split("//")[1]
options.hostname = proxy ? proxy.hostname : setup.url[0].split("//")[1];
options.port = proxy ? proxy.port : ssl ? 443 : 80;
options.path = proxy ? "http://" + origin + url:url;
options.headers = proxy ? { 'Host': origin }:null;
options.method = mode;
options.keepAlive= !!keepAliveAgent;
options.agent = keepAliveAgent;
options.body = payload;
_dereq_('http').globalAgent.maxSockets = Infinity;
try {
request = (ssl ? https : http)['request'](options, function(response) {
response.setEncoding('utf8');
response.on( 'error', function(){console.log('error');done(1, body || { "error" : "Network Connection Error"})});
response.on( 'abort', function(){console.log('abort');done(1, body || { "error" : "Network Connection Error"})});
response.on( 'data', function (chunk) {
if (chunk) body += chunk;
} );
response.on( 'end', function(){
var statusCode = response.statusCode;
switch(statusCode) {
case 401:
case 402:
case 403:
try {
response = JSON['parse'](body);
done(1,response);
}
catch (r) { return done(1, body); }
return;
default:
break;
}
finished();
});
});
request.timeout = xhrtme;
request.on( 'error', function() {
done( 1, {"error":"Network Connection Error"} );
} );
if (mode == 'POST') request.write(payload);
request.end();
} catch(e) {
done(0);
return xdr(setup);
}
return done;
}
/**
* LOCAL STORAGE
*/
var db = (function(){
var store = {};
return {
'get' : function(key) {
return store[key];
},
'set' : function( key, value ) {
store[key] = value;
}
};
})();
function crypto_obj() {
var iv = "0123456789012345";
function get_padded_key(key) {
return crypto.createHash('sha256').update(key).digest("hex").slice(0,32);
}
return {
'encrypt' : function(input, key) {
if (!key) return input;
var plain_text = JSON['stringify'](input);
var cipher = crypto.createCipheriv('aes-256-cbc', get_padded_key(key), iv);
var base_64_encrypted = cipher.update(plain_text, 'utf8', 'base64') + cipher.final('base64');
return base_64_encrypted || input;
},
'decrypt' : function(input, key) {
if (!key) return input;
var decipher = crypto.createDecipheriv('aes-256-cbc', get_padded_key(key), iv);
try {
var decrypted = decipher.update(input, 'base64', 'utf8') + decipher.final('utf8');
} catch (e) {
return null;
}
return JSON.parse(decrypted);
}
}
}
function keepAliveIsEmbedded() {
return 'EventEmitter' in http.Agent.super_;
}
var CREATE_PUBNUB = function(setup) {
proxy = setup['proxy'];
setup['xdr'] = xdr;
setup['db'] = db;
setup['error'] = setup['error'] || error;
setup['hmac_SHA256'] = get_hmac_SHA256;
setup['crypto_obj'] = crypto_obj();
setup['params'] = {'pnsdk' : PNSDK};
if (setup['keepAlive'] === false) {
keepAliveAgent = undefined;
}
SELF = function(setup) {
return CREATE_PUBNUB(setup);
}
var PN = PN_API(setup);
for (var prop in PN) {
if (PN.hasOwnProperty(prop)) {
SELF[prop] = PN[prop];
}
}
SELF.init = SELF;
SELF.secure = SELF;
SELF.ready();
return SELF;
}
CREATE_PUBNUB.init = CREATE_PUBNUB;
CREATE_PUBNUB.unique = unique
CREATE_PUBNUB.secure = CREATE_PUBNUB;
module.exports = CREATE_PUBNUB
module.exports.PNmessage = PNmessage;
}).call(this,_dereq_("buffer").Buffer)
},{"agentkeepalive":62,"buffer":128,"crypto":132,"http":138,"https":142}],66:[function(_dereq_,module,exports){
/*
Copyright (c) 2010,2011,2012,2013 Morgan Roderick http://roderick.dk
License: MIT - http://mrgnrdrck.mit-license.org
https://github.com/mroderick/PubSubJS
*/
/*jslint white:true, plusplus:true, stupid:true*/
/*global
setTimeout,
module,
exports,
define,
require,
window
*/
(function(root, factory){
'use strict';
// CommonJS
if (typeof exports === 'object' && module){
module.exports = factory();
// AMD
} else if (typeof define === 'function' && define.amd){
define(factory);
// Browser
} else {
root.PubSub = factory();
}
}( ( typeof window === 'object' && window ) || this, function(){
'use strict';
var PubSub = {},
messages = {},
lastUid = -1;
function hasKeys(obj){
var key;
for (key in obj){
if ( obj.hasOwnProperty(key) ){
return true;
}
}
return false;
}
/**
* Returns a function that throws the passed exception, for use as argument for setTimeout
* @param { Object } ex An Error object
*/
function throwException( ex ){
return function reThrowException(){
throw ex;
};
}
function callSubscriberWithDelayedExceptions( subscriber, message, data ){
try {
subscriber( message, data );
} catch( ex ){
setTimeout( throwException( ex ), 0);
}
}
function callSubscriberWithImmediateExceptions( subscriber, message, data ){
subscriber( message, data );
}
function deliverMessage( originalMessage, matchedMessage, data, immediateExceptions ){
var subscribers = messages[matchedMessage],
callSubscriber = immediateExceptions ? callSubscriberWithImmediateExceptions : callSubscriberWithDelayedExceptions,
s;
if ( !messages.hasOwnProperty( matchedMessage ) ) {
return;
}
for (s in subscribers){
if ( subscribers.hasOwnProperty(s)){
callSubscriber( subscribers[s], originalMessage, data );
}
}
}
function createDeliveryFunction( message, data, immediateExceptions ){
return function deliverNamespaced(){
var topic = String( message ),
position = topic.lastIndexOf( '.' );
// deliver the message as it is now
deliverMessage(message, message, data, immediateExceptions);
// trim the hierarchy and deliver message to each level
while( position !== -1 ){
topic = topic.substr( 0, position );
position = topic.lastIndexOf('.');
deliverMessage( message, topic, data );
}
};
}
function messageHasSubscribers( message ){
var topic = String( message ),
found = Boolean(messages.hasOwnProperty( topic ) && hasKeys(messages[topic])),
position = topic.lastIndexOf( '.' );
while ( !found && position !== -1 ){
topic = topic.substr( 0, position );
position = topic.lastIndexOf( '.' );
found = Boolean(messages.hasOwnProperty( topic ) && hasKeys(messages[topic]));
}
return found;
}
function publish( message, data, sync, immediateExceptions ){
var deliver = createDeliveryFunction( message, data, immediateExceptions ),
hasSubscribers = messageHasSubscribers( message );
if ( !hasSubscribers ){
return false;
}
if ( sync === true ){
deliver();
} else {
setTimeout( deliver, 0 );
}
return true;
}
/**
* PubSub.publish( message[, data] ) -> Boolean
* - message (String): The message to publish
* - data: The data to pass to subscribers
* Publishes the the message, passing the data to it's subscribers
**/
PubSub.publish = function( message, data ){
return publish( message, data, false, PubSub.immediateExceptions );
};
/**
* PubSub.publishSync( message[, data] ) -> Boolean
* - message (String): The message to publish
* - data: The data to pass to subscribers
* Publishes the the message synchronously, passing the data to it's subscribers
**/
PubSub.publishSync = function( message, data ){
return publish( message, data, true, PubSub.immediateExceptions );
};
/**
* PubSub.subscribe( message, func ) -> String
* - message (String): The message to subscribe to
* - func (Function): The function to call when a new message is published
* Subscribes the passed function to the passed message. Every returned token is unique and should be stored if
* you need to unsubscribe
**/
PubSub.subscribe = function( message, func ){
if ( typeof func !== 'function'){
return false;
}
// message is not registered yet
if ( !messages.hasOwnProperty( message ) ){
messages[message] = {};
}
// forcing token as String, to allow for future expansions without breaking usage
// and allow for easy use as key names for the 'messages' object
var token = 'uid_' + String(++lastUid);
messages[message][token] = func;
// return token for unsubscribing
return token;
};
/**
* PubSub.unsubscribe( tokenOrFunction ) -> String | Boolean
* - tokenOrFunction (String|Function): The token of the function to unsubscribe or func passed in on subscribe
* Unsubscribes a specific subscriber from a specific message using the unique token
* or if using Function as argument, it will remove all subscriptions with that function
**/
PubSub.unsubscribe = function( tokenOrFunction ){
var isToken = typeof tokenOrFunction === 'string',
result = false,
m, message, t, token;
for ( m in messages ){
if ( messages.hasOwnProperty( m ) ){
message = messages[m];
if ( isToken && message[tokenOrFunction] ){
delete message[tokenOrFunction];
result = tokenOrFunction;
// tokens are unique, so we can just stop here
break;
} else if (!isToken) {
for ( t in message ){
if (message.hasOwnProperty(t) && message[t] === tokenOrFunction){
delete message[t];
result = true;
}
}
}
}
}
return result;
};
return PubSub;
}));
},{}],67:[function(_dereq_,module,exports){
exports.Host = _dereq_('./lib/Host');
exports.Promise = _dereq_('./lib/Promise');
},{"./lib/Host":68,"./lib/Promise":70}],68:[function(_dereq_,module,exports){
var WebSocket = _dereq_('ws');
var WebSocketServer = _dereq_('ws').Server;
var uuid = _dereq_('node-uuid');
var Promise = _dereq_('./Promise');
var requestify = _dereq_('./requestify');
var Peer = _dereq_('./Peer');
/**
* Host
* @param {Object} [options] Available options: see Host.config
*/
function Host(options) {
var me = this;
// peers and cached peer addresses
this.peers = {}; // local peers
this.addresses = {}; // cached addresses of peers located on other hosts
// pubsub
this.channels = {}; // keys are the channels, values are arrays with callbacks of subscribers
// default options
this.options = {
reconnectTimeout: 5 * 60 * 1000, // give up reconnecting after 5 minutes
reconnectDelay: 1000, // try reconnecting after one second
reconnectDecay: 2
};
// server properties
this.server = null;
this.address = null;
this.port = null;
this.connections = {}; // List with open connections, key is the url and value is the connection
this.timers = {}; // reconnect timers
/**
* Send a message from one peer to another
* @param {string} from Id of the sending peer
* @param {string} to Id of the receiving peer
* @param {*} message JSON message
* @returns {Promise.<null, Error>} Resolves when sent
*/
this.send = function (from, to, message) {
// see if the peer lives on the same host
var peer = me.peers[to];
if (peer) {
peer.emit('message', from, message);
return Promise.resolve(null);
}
// find the remote host where the recipient is located
return me.find(to)
.then(function (url) {
var conn = me.connections[url];
if (conn) {
var request = {
method: 'send',
params: {
from: from,
to: to,
message: message
}
};
// TODO: there is a maximum callstack issue when queuing a lot of notifications
return conn.request(request) // the send request returns null
//return conn.notify(request) // the send request returns null
.catch(function (err) {
// FIXME: use a protocol for errors, use error code
if (err.toString().indexOf('Error: Peer not found') === 0) {
// this peer was deleted. Remove it from cache
delete me.addresses[to];
throw _peerNotFoundError(to);
}
})
}
else {
throw _peerUnreachable(to, url);
}
});
};
this.config(options);
}
/**
* Apply configuration options to the host, and/or retrieve the current
* configuration.
* @param {Object} [options] Available options:
* - networkId An id for the distribus
* network. A Host can only
* connect to other hosts with
* the same id. networkId cannot
* be changed once set.
* - reconnectTimeout Timeout in milliseconds for
* giving up reconnecting.
* 5 minutes by default
* - reconnectDelay Initial delay for trying to
* reconnect. for consecutive
* reconnect trials, the delay
* decays with a factor
* `reconnectDecay`.
* 1 second by default.
* - reconnectDecay Decay for the reconnect
* delay. 2 by default.
* @return {Object} Returns the current configuration
*/
Host.prototype.config = function (options) {
// apply new options
if (options) {
_merge(this.options, options);
// apply networkId
if (options.networkId) {
if (this.networkId !== null) {
this.networkId = options.networkId;
}
else {
throw new Error('Cannot replace networkId once set');
}
}
}
// return a copy of the options
return _merge({}, this.options);
};
/**
* Create a new peer.
* Throws an error when a peer with the same id already exists on this host.
* Does not check whether this id exists on any remote host (use Host.find(id)
* to validate this before creating a peer, or even better, use a uuid to
* prevent id collisions).
* @param {string} id The id for the new peer
* @return {Peer} Returns the created peer
*/
Host.prototype.create = function (id) {
if (id in this.peers) {
throw new Error('Id already exists (id: ' + id +')');
}
var peer = new Peer(id, this.send);
this.peers[id] = peer;
return peer;
};
/**
* Remove a peer from the host
* @param {Peer | string} peer A peer or the id of a peer
*/
Host.prototype.remove = function (peer) {
if (peer instanceof Peer) { // a peer instance
delete this.peers[peer.id];
}
else if (peer) { // a string with the peers id
delete this.peers[peer];
}
};
/**
* Get a local peer by its id
* @param {string} id The id of an existing peer
* @return {Peer | null} returns the peer, or returns null when not existing.
*/
Host.prototype.get = function (id) {
return this.peers[id] || null;
};
/**
* Find the host of a peer by it's id
* @param {string} id Id of a peer
* @return {Promise.<string | null, Error>} The url of the peers host.
* Returns null if the found host has no url.
* Throws an error if not found.
*/
Host.prototype.find = function (id) {
var me = this;
// check if this is a local peer
if (id in me.peers) {
return Promise.resolve(me.url || null);
}
// check if this id is already in cache
var url = me.addresses[id];
if (url) {
// yes, we already have the address
return Promise.resolve(url);
}
// search on other hosts
return new Promise(function (resolve, reject) {
// TODO: send requests in small batches, not all at once
// send a find request to a host
var found = false;
function _find(url) {
var conn = me.connections[url];
return conn.request({method: 'find', params: {id: id}})
.then(function (url) {
if (url && !found) {
// we found the peer
found = true;
// put this address in cache
// TODO: limit the number of cached addresses. When exceeding the limit, store on disk in a temporary db
me.addresses[id] = url;
// return the found url
resolve(url);
}
});
}
// ask all connected hosts if they host this peer
var results = Object.keys(me.connections).map(_find);
// if all requests are finished and the peer is not found, reject with an error
Promise.all(results)
.then(function () {
if (!found || results.length == 0) {
reject(_peerNotFoundError(id));
}
});
});
};
/**
* Start listening on a socket.
* @param {string} address
* @param {number} port
* @return {Promise.<Host, Error>} Returns itself when connected
*/
Host.prototype.listen = function (address, port) {
var me = this;
return new Promise(function (resolve, reject) {
if (me.server) {
reject(new Error('Server already listening'));
return;
}
me.server = new WebSocketServer({port: port}, function () {
me.address = address;
me.port = port;
me.url = 'ws://' + address + ':' + port;
resolve(me);
});
me.server.on('connection', function (conn) {
conn = requestify(conn);
conn.onerror = function (err) {
// TODO: what to do with errors?
};
conn.onclose = function () {
// remove this connection from the connections list
// (we do not yet forget the cached peers)
var url = me._findUrl(conn);
delete me.connections[url];
me.timers[url] = setTimeout(function () {
delete me.timers[url];
// clear cache
me._forgetPeers(url);
}, me.options.reconnectTimeout);
};
conn.onrequest = function (request) {
return me._onRequest(conn, request);
};
});
me.server.on('error', function (err) {
reject(err)
});
});
};
/**
* Handle a request
* @param {WebSocket} conn
* @param {Object} request
* @returns {Promise}
* @private
*/
Host.prototype._onRequest = function (conn, request) {
var me = this;
var url;
switch (request.method) {
case 'greeting':
url = request.params && request.params.url;
var networkId = request.params.networkId || null;
if (networkId === null || networkId === me.networkId) {
if (url && !(url in this.connections)) {
this.connections[url] = conn;
return this._broadcastJoin(url)
.then(function () {
return Promise.resolve({networkId: me.networkId})
});
}
else {
return Promise.resolve({networkId: me.networkId});
}
}
else {
return Promise.reject(new Error('Network id mismatch (' + networkId + ' !== ' + me.networkId + ')'));
}
case 'join':
url = request.params && request.params.url;
return this.join(url)
.then(function (host) {
return Promise.resolve();
});
case 'goodbye':
url = this._findUrl(conn);
this._forgetPeers(url);
this._disconnect(url);
return Promise.resolve('goodbye');
case 'hosts':
// connect to all newly retrieved urls
if (request.params && request.params.urls) {
this.join(request.params.urls);
}
// return a list with the urls of all known hosts
return Promise.resolve(Object.keys(this.connections));
case 'find': // find a peer
var id = request.params && request.params.id;
return Promise.resolve(this.peers[id] ? this.url : null);
case 'send':
var from = request.params && request.params.from;
var to = request.params && request.params.to;
var message = request.params && request.params.message;
// TODO: validate whether all parameters are there
var peer = this.peers[to];
if (peer) {
peer.emit('message', from, message);
return Promise.resolve(null);
}
else {
return Promise.reject(_peerNotFoundError(to).toString());
}
case 'publish':
var channel = request.params && request.params.channel;
var message = request.params && request.params.message;
this._publish(channel, message);
return Promise.resolve({
result: null,
error: null
});
case 'ping':
return Promise.resolve({
result: request.params,
error: null
});
default:
return Promise.reject('Unknown method "' + request.method + '"');
}
};
/**
* Find an url from a connection
* @param {WebSocket} conn
* @return {String | null} url
* @private
*/
Host.prototype._findUrl = function (conn) {
// search by instance
for (var url in this.connections) {
if (this.connections.hasOwnProperty(url) && this.connections[url] === conn) {
return url;
}
}
return null;
};
/**
* Remove all cached peers of given
* @param {string} url Url of a host for which to forget the cached peers
* @private
*/
Host.prototype._forgetPeers = function (url) {
// remove all cached peers
for (var id in this.addresses) {
if (this.addresses.hasOwnProperty(id) && this.addresses[id] === url) {
delete this.addresses[id];
}
}
};
/**
* Join an other Host.
* A host can only join another host when having the same id, or having no id
* defined. In the latter case, the host will orphan the id of the host it
* connects to.
* @param {string} url For example 'ws://localhost:3000'
* @return {Promise.<Host, Error>} Returns itself when joined
*/
Host.prototype.join = function (url) {
var me = this;
if (url && !(url in me.connections)) {
return me._connect(url)
.then(function () {
// broadcast the join request to all known hosts
return me._broadcastJoin(url);
})
.then(function (urls) {
// return the host itself as last result in the promise chain
return me;
});
// TODO: handle connection error
}
else {
// already known url. ignore this join
// FIXME: it is possible that this connection is still being established
return Promise.resolve(me);
}
};
/**
* Open a connection to an other host and add the host to the list of connected
* hosts.
* @param {String} url
* @returns {Promise.<WebSocket, Error>} Returns the established connection
* @private
*/
Host.prototype._connect = function(url) {
var me = this;
return new Promise(function (resolve, reject) {
// open a web socket
var conn = new WebSocket(url);
requestify(conn);
me.connections[url] = conn;
conn.onrequest = function (request) {
return me._onRequest(conn, request);
};
conn.onclose = function () {
if (me.connections[url]) {
// remove the connection from the list
delete me.connections[url];
// schedule reconnection
me._reconnect(url);
}
};
conn.onopen = function () {
// send a greeting with the hosts url
conn.request({method: 'greeting', params: { url: me.url, networkId: me.networkId } })
.then(function (params) {
me.networkId = params.networkId;
resolve(conn);
})
.catch(function (err) {
// greeting rejected
delete me.connections[url];
conn.close();
reject(err);
});
};
conn.onerror = function (err) {
delete me.connections[url];
reject(err);
conn.close();
};
});
};
/**
* Reconnect with a host
* @param {String} url Url of the host to which to reconnect
* @private
*/
Host.prototype._reconnect = function (url) {
var me = this;
var start = new Date().valueOf();
function scheduleReconnect(delay, trial) {
me.timers[url] = setTimeout(function () {
delete me.timers[url];
var now = new Date().valueOf();
if (now - start < me.options.reconnectTimeout) {
// reconnect
me._connect(url)
.catch(function (err) {
// schedule next reconnect trial
scheduleReconnect(delay / me.options.reconnectDecay, trial + 1);
});
}
else {
// give up trying to reconnect
me._forgetPeers(url);
}
}, delay);
}
// schedule reconnection after a delay
scheduleReconnect(me.options.reconnectDelay, 0);
};
/**
* Forward a join message to all known hosts
* @param {string} url For example 'ws://localhost:3000'
* @return {Promise.<String[], Error>} returns the joined urls
*/
Host.prototype._broadcastJoin = function (url) {
// TODO: implement a more efficient broadcast mechanism
var me = this;
var urls = Object.keys(me.connections)
.filter(function (u) {
return u !== url
});
function join (existingUrl) {
var conn = me.connections[existingUrl];
return conn.request({method: 'join', params: {'url': url}})
.catch(function (err) {
// TODO: what to do with failed requests? Right now we ignore them
})
.then(function () {
// return the url where the join is broadcasted to
return existingUrl;
})
}
// send a join request to all known hosts
return Promise.all(urls.map(join));
};
/**
* Stop listening on currently a socket
* @return {Promise.<Host, Error>} Returns itself
*/
Host.prototype.close = function () {
var me = this;
// TODO: create a flag while closing? and opening?
if (this.server) {
// close the host, and clean up cache
function closeHost() {
// close the host itself
me.addresses = {};
if (me.server) {
me.server.close();
me.server = null;
me.address = null;
me.port = null;
me.url = null;
}
return me;
}
// close all connections
var urls = Object.keys(this.connections);
return Promise.all(urls.map(function (url) {
return me._disconnect(url);
})).then(closeHost);
}
else {
// no socket open. resolve immediately
Promise.resolve(this);
}
};
/**
* Close the connection with a host. Note: peers are not removed from cache
* @param {string} url Url of a connected host
* @return {Promise.<undefined, Error>} Resolves a promise when closed
* @private
*/
Host.prototype._disconnect = function (url) {
var conn = this.connections[url];
if (conn) {
delete this.connections[url];
if (this.timers[url]) {
clearTimeout(this.timers[url]);
delete this.timers[url];
}
// send a goodbye message
return conn.request({method: 'goodbye'})
.catch(function (err) {
// ignore failing to send goodbye
})
// then close the connection
.then(function () {
conn.close();
});
}
else {
Promise.resolve();
}
};
/**
* Publish a message via a channel. All listeners subscribed to this channel
* will be triggered, both listeners on this host as well as connected hosts.
* @param {string} channel The name of the channel
* @param {*} message A message, can be any type. Must be serializable JSON.
*/
Host.prototype.publish = function (channel, message) {
// trigger local subscribers
this._publish(channel, message);
// send the message to all connected hosts
for (var url in this.connections) {
if (this.connections.hasOwnProperty(url)) {
var connection = this.connections[url];
connection.notify({
method: 'publish',
params: {
channel: channel,
message: message
}
});
}
}
// TODO: improve efficiency by having the hosts share the channels for which
// they have subscribers, so we only have to send a message to a
// particular host when it has subscribers to the channel.
};
/**
* Publish a channel to all subscribers on this host.
* @param {string} channel The name of the channel
* @param {*} message A message, can be any type. Must be serializable JSON.
* @private
*/
Host.prototype._publish = function (channel, message) {
// trigger local subscribers
var callbacks = this.channels[channel];
if (callbacks) {
callbacks.forEach(function (callback) {
callback(message);
});
}
};
/**
* Subscribe to a channel.
* @param {string} channel The name of the channel
* @param {function} callback Called as callback(message)
*/
Host.prototype.subscribe = function (channel, callback) {
// TODO: implement support for wildcards, like subscribing to "foo.*" or something like that
var callbacks = this.channels[channel];
if (!callbacks) {
callbacks = [];
this.channels[channel] = callbacks;
}
callbacks.push(callback);
};
/**
* Unsubscribe from a channel.
* @param {string} channel The name of the channel
* @param {function} callback A callback used before to subscribe
*/
Host.prototype.unsubscribe = function (channel, callback) {
var callbacks = this.channels[channel];
if (callbacks) {
var index = callbacks.indexOf(callback);
if (index !== -1) {
callbacks.splice(index, 1);
if (callbacks.length === 0) {
delete this.channels[channel];
}
}
}
};
/**
* Merge object b into object a: copy all properties of b to a
* @param {Object} a
* @param {Object} b
* @return {Object} returns the merged a
* @private
*/
function _merge (a, b) {
for (var prop in b) {
if (b.hasOwnProperty(prop)) {
a[prop] = b[prop];
}
}
return a;
}
/**
* Create an Error "Peer not found"
* @param {string} id The id of the peer
* @return {Error}
* @private
*/
function _peerNotFoundError(id) {
return new Error('Peer not found (id: ' + id + ')');
}
/**
* Create an Error "Peer unreachable"
* @param {string} id The id of the peer
* @param {string} url Url of the peers host
* @return {Error}
* @private
*/
function _peerUnreachable(id, url) {
return new Error('Peer unreachable (id: ' + id + ', url: ' + url + ')');
}
// TODO: implement a function list() which returns the id's of all peers in the system
module.exports = Host;
},{"./Peer":69,"./Promise":70,"./requestify":71,"node-uuid":113,"ws":109}],69:[function(_dereq_,module,exports){
//var Emitter = require('emitter-component');
/**
* Peer
* A peer can send and receive messages via a connected message bus
* @param {string} id
* @param {function(string, string, *)} send A function to send a message to an other peer
*/
function Peer(id, send) {
this.id = id;
this._send = send;
this.listeners = {};
}
/**
* Send a message to another peer
* @param {string} to Id of the recipient
* @param {*} message Message to be send, can be JSON
* @returns {Promise.<null, Error>} Resolves when sent
*/
Peer.prototype.send = function (to, message) {
return this._send(this.id, to, message);
};
// Extend the Peer with event emitter functionality
//Emitter(Peer.prototype);
// TODO: complete this custom event emitter, it's about 5 times as fast as Emitter because its not slicing arguments
/**
* Register an event listener
* @param {string} event Available events: 'message'
* @param {Function} callback Callback function, called as callback(from, message)
*/
Peer.prototype.on = function (event, callback) {
if (!(event in this.listeners)) this.listeners[event] = [];
this.listeners[event].push(callback);
};
// TODO: implement off
/**
* Emit an event
* @param {string} event For example 'message'
* @param {string} from Id of the sender, for example 'peer1'
* @param {*} message A message, can be any type. Must be serializable JSON.
*/
Peer.prototype.emit = function (event, from, message) {
var listeners = this.listeners[event];
if (listeners) {
for (var i = 0, ii = listeners.length; i < ii; i++) {
var listener = listeners[i];
listener(from, message);
}
}
};
module.exports = Peer;
},{}],70:[function(_dereq_,module,exports){
// Return a promise implementation.
module.exports = _dereq_('bluebird');
},{"bluebird":74}],71:[function(_dereq_,module,exports){
var uuid = _dereq_('node-uuid'),
Promise = _dereq_('./Promise');
var TIMEOUT = 60000; // ms
// TODO: make timeout a configuration setting
/**
* Wrap a socket in a request/response handling layer.
* Requests are wrapped in an envelope with id and data, and responses
* are packed in an envelope with this same id and response data.
*
* The socket is extended with functions:
* request(data: *) : Promise.<*, Error>
* onrequest(data: *) : Promise.<*, Error>
*
* @param {WebSocket} socket
* @return {WebSocket} requestified socket
*/
function requestify (socket) {
return (function () {
var queue = {}; // queue with requests in progress
if ('request' in socket) {
throw new Error('Socket already has a request property');
}
var requestified = socket;
/**
* Event handler, handles incoming messages
* @param {Object} event
*/
socket.onmessage = function (event) {
var data = event.data;
if (data.charAt(0) == '{') {
var envelope = JSON.parse(data);
// match the request from the id in the response
var request = queue[envelope.id];
if (request) {
// handle an incoming response
clearTimeout(request.timeout);
delete queue[envelope.id];
// resolve the promise with response data
if (envelope.error) {
// TODO: implement a smarter way to serialize and deserialize errors
request.reject(new Error(envelope.error));
}
else {
request.resolve(envelope.message);
}
}
else {
if ('id' in envelope) {
try {
// handle an incoming request
requestified.onrequest(envelope.message)
.then(function (message) {
var response = {
id: envelope.id,
message: message,
error: null
};
socket.send(JSON.stringify(response));
})
.catch(function (error) {
var response = {
id: envelope.id,
message: null,
error: error.message || error.toString()
};
socket.send(JSON.stringify(response));
});
}
catch (err) {
var response = {
id: envelope.id,
message: null,
error: err.message || err.toString()
};
socket.send(JSON.stringify(response));
}
}
else {
// handle incoming notification (we don't do anything with the response)
requestified.onrequest(envelope.message);
}
}
}
};
/**
* Send a request
* @param {*} message
* @returns {Promise.<*, Error>} Returns a promise resolving with the response message
*/
requestified.request = function (message) {
return new Promise(function (resolve, reject) {
// put the data in an envelope with id
var id = uuid.v1();
var envelope = {
id: id,
message: message
};
// add the request to the list with requests in progress
queue[id] = {
resolve: resolve,
reject: reject,
timeout: setTimeout(function () {
delete queue[id];
reject(new Error('Timeout'));
}, TIMEOUT)
};
socket.send(JSON.stringify(envelope));
});
};
/**
* Send a notification. A notification does not receive a response.
* @param {*} message
* @returns {Promise.<null, Error>} Returns a promise resolving with the null
* when the notification has been sent.
*/
requestified.notify = function (message) {
return new Promise(function (resolve, reject) {
// put the data in an envelope
var envelope = {
// we don't add an id, so we send this as notification instead of a request
message: message
};
socket.send(JSON.stringify(envelope), function () {
resolve(null);
});
});
};
/**
* Handle an incoming request.
* @param {*} message Request message
* @returns {Promise.<*, Error>} Resolves with a response message
*/
requestified.onrequest = function (message) {
// this function must be implemented by the socket
return Promise.reject('No onrequest handler implemented');
};
// TODO: disable send and onmessage on the requestified socket
return requestified;
})();
}
module.exports = requestify;
},{"./Promise":70,"node-uuid":113}],72:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports = function(Promise, Promise$_CreatePromiseArray, PromiseArray) {
var SomePromiseArray = _dereq_("./some_promise_array.js")(PromiseArray);
function Promise$_Any(promises, useBound) {
var ret = Promise$_CreatePromiseArray(
promises,
SomePromiseArray,
useBound === true && promises._isBound()
? promises._boundTo
: void 0
);
var promise = ret.promise();
if (promise.isRejected()) {
return promise;
}
ret.setHowMany(1);
ret.setUnwrap();
ret.init();
return promise;
}
Promise.any = function Promise$Any(promises) {
return Promise$_Any(promises, false);
};
Promise.prototype.any = function Promise$any() {
return Promise$_Any(this, true);
};
};
},{"./some_promise_array.js":104}],73:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
var schedule = _dereq_("./schedule.js");
var Queue = _dereq_("./queue.js");
var errorObj = _dereq_("./util.js").errorObj;
var tryCatch1 = _dereq_("./util.js").tryCatch1;
var process = _dereq_("./global.js").process;
function Async() {
this._isTickUsed = false;
this._length = 0;
this._lateBuffer = new Queue();
this._functionBuffer = new Queue(25000 * 3);
var self = this;
this.consumeFunctionBuffer = function Async$consumeFunctionBuffer() {
self._consumeFunctionBuffer();
};
}
Async.prototype.haveItemsQueued = function Async$haveItemsQueued() {
return this._length > 0;
};
Async.prototype.invokeLater = function Async$invokeLater(fn, receiver, arg) {
if (process !== void 0 &&
process.domain != null &&
!fn.domain) {
fn = process.domain.bind(fn);
}
this._lateBuffer.push(fn, receiver, arg);
this._queueTick();
};
Async.prototype.invoke = function Async$invoke(fn, receiver, arg) {
if (process !== void 0 &&
process.domain != null &&
!fn.domain) {
fn = process.domain.bind(fn);
}
var functionBuffer = this._functionBuffer;
functionBuffer.push(fn, receiver, arg);
this._length = functionBuffer.length();
this._queueTick();
};
Async.prototype._consumeFunctionBuffer =
function Async$_consumeFunctionBuffer() {
var functionBuffer = this._functionBuffer;
while(functionBuffer.length() > 0) {
var fn = functionBuffer.shift();
var receiver = functionBuffer.shift();
var arg = functionBuffer.shift();
fn.call(receiver, arg);
}
this._reset();
this._consumeLateBuffer();
};
Async.prototype._consumeLateBuffer = function Async$_consumeLateBuffer() {
var buffer = this._lateBuffer;
while(buffer.length() > 0) {
var fn = buffer.shift();
var receiver = buffer.shift();
var arg = buffer.shift();
var res = tryCatch1(fn, receiver, arg);
if (res === errorObj) {
this._queueTick();
if (fn.domain != null) {
fn.domain.emit("error", res.e);
}
else {
throw res.e;
}
}
}
};
Async.prototype._queueTick = function Async$_queue() {
if (!this._isTickUsed) {
schedule(this.consumeFunctionBuffer);
this._isTickUsed = true;
}
};
Async.prototype._reset = function Async$_reset() {
this._isTickUsed = false;
this._length = 0;
};
module.exports = new Async();
},{"./global.js":86,"./queue.js":97,"./schedule.js":100,"./util.js":108}],74:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
var Promise = _dereq_("./promise.js")();
module.exports = Promise;
},{"./promise.js":90}],75:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports = function(Promise) {
Promise.prototype.call = function Promise$call(propertyName) {
var $_len = arguments.length;var args = new Array($_len - 1); for(var $_i = 1; $_i < $_len; ++$_i) {args[$_i - 1] = arguments[$_i];}
return this._then(function(obj) {
return obj[propertyName].apply(obj, args);
},
void 0,
void 0,
void 0,
void 0
);
};
function Promise$getter(obj) {
var prop = typeof this === "string"
? this
: ("" + this);
return obj[prop];
}
Promise.prototype.get = function Promise$get(propertyName) {
return this._then(
Promise$getter,
void 0,
void 0,
propertyName,
void 0
);
};
};
},{}],76:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports = function(Promise, INTERNAL) {
var errors = _dereq_("./errors.js");
var async = _dereq_("./async.js");
var CancellationError = errors.CancellationError;
Promise.prototype._cancel = function Promise$_cancel() {
if (!this.isCancellable()) return this;
var parent;
var promiseToReject = this;
while ((parent = promiseToReject._cancellationParent) !== void 0 &&
parent.isCancellable()) {
promiseToReject = parent;
}
var err = new CancellationError();
promiseToReject._attachExtraTrace(err);
promiseToReject._rejectUnchecked(err);
};
Promise.prototype.cancel = function Promise$cancel() {
if (!this.isCancellable()) return this;
async.invokeLater(this._cancel, this, void 0);
return this;
};
Promise.prototype.cancellable = function Promise$cancellable() {
if (this._cancellable()) return this;
this._setCancellable();
this._cancellationParent = void 0;
return this;
};
Promise.prototype.uncancellable = function Promise$uncancellable() {
var ret = new Promise(INTERNAL);
ret._setTrace(this);
ret._follow(this);
ret._unsetCancellable();
if (this._isBound()) ret._setBoundTo(this._boundTo);
return ret;
};
Promise.prototype.fork =
function Promise$fork(didFulfill, didReject, didProgress) {
var ret = this._then(didFulfill, didReject, didProgress,
void 0, void 0);
ret._setCancellable();
ret._cancellationParent = void 0;
return ret;
};
};
},{"./async.js":73,"./errors.js":80}],77:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports = function() {
var inherits = _dereq_("./util.js").inherits;
var defineProperty = _dereq_("./es5.js").defineProperty;
var rignore = new RegExp(
"\\b(?:[a-zA-Z0-9.]+\\$_\\w+|" +
"tryCatch(?:1|2|Apply)|new \\w*PromiseArray|" +
"\\w*PromiseArray\\.\\w*PromiseArray|" +
"setTimeout|CatchFilter\\$_\\w+|makeNodePromisified|processImmediate|" +
"process._tickCallback|nextTick|Async\\$\\w+)\\b"
);
var rtraceline = null;
var formatStack = null;
function formatNonError(obj) {
var str;
if (typeof obj === "function") {
str = "[function " +
(obj.name || "anonymous") +
"]";
}
else {
str = obj.toString();
var ruselessToString = /\[object [a-zA-Z0-9$_]+\]/;
if (ruselessToString.test(str)) {
try {
var newStr = JSON.stringify(obj);
str = newStr;
}
catch(e) {
}
}
if (str.length === 0) {
str = "(empty array)";
}
}
return ("(<" + snip(str) + ">, no stack trace)");
}
function snip(str) {
var maxChars = 41;
if (str.length < maxChars) {
return str;
}
return str.substr(0, maxChars - 3) + "...";
}
function CapturedTrace(ignoreUntil, isTopLevel) {
this.captureStackTrace(CapturedTrace, isTopLevel);
}
inherits(CapturedTrace, Error);
CapturedTrace.prototype.captureStackTrace =
function CapturedTrace$captureStackTrace(ignoreUntil, isTopLevel) {
captureStackTrace(this, ignoreUntil, isTopLevel);
};
CapturedTrace.possiblyUnhandledRejection =
function CapturedTrace$PossiblyUnhandledRejection(reason) {
if (typeof console === "object") {
var message;
if (typeof reason === "object" || typeof reason === "function") {
var stack = reason.stack;
message = "Possibly unhandled " + formatStack(stack, reason);
}
else {
message = "Possibly unhandled " + String(reason);
}
if (typeof console.error === "function" ||
typeof console.error === "object") {
console.error(message);
}
else if (typeof console.log === "function" ||
typeof console.log === "object") {
console.log(message);
}
}
};
CapturedTrace.combine = function CapturedTrace$Combine(current, prev) {
var curLast = current.length - 1;
for (var i = prev.length - 1; i >= 0; --i) {
var line = prev[i];
if (current[curLast] === line) {
current.pop();
curLast--;
}
else {
break;
}
}
current.push("From previous event:");
var lines = current.concat(prev);
var ret = [];
for (var i = 0, len = lines.length; i < len; ++i) {
if ((rignore.test(lines[i]) ||
(i > 0 && !rtraceline.test(lines[i])) &&
lines[i] !== "From previous event:")
) {
continue;
}
ret.push(lines[i]);
}
return ret;
};
CapturedTrace.isSupported = function CapturedTrace$IsSupported() {
return typeof captureStackTrace === "function";
};
var captureStackTrace = (function stackDetection() {
if (typeof Error.stackTraceLimit === "number" &&
typeof Error.captureStackTrace === "function") {
rtraceline = /^\s*at\s*/;
formatStack = function(stack, error) {
if (typeof stack === "string") return stack;
if (error.name !== void 0 &&
error.message !== void 0) {
return error.name + ". " + error.message;
}
return formatNonError(error);
};
var captureStackTrace = Error.captureStackTrace;
return function CapturedTrace$_captureStackTrace(
receiver, ignoreUntil) {
captureStackTrace(receiver, ignoreUntil);
};
}
var err = new Error();
if (typeof err.stack === "string" &&
typeof "".startsWith === "function" &&
(err.stack.startsWith("stackDetection@")) &&
stackDetection.name === "stackDetection") {
defineProperty(Error, "stackTraceLimit", {
writable: true,
enumerable: false,
configurable: false,
value: 25
});
rtraceline = /@/;
var rline = /[@\n]/;
formatStack = function(stack, error) {
if (typeof stack === "string") {
return (error.name + ". " + error.message + "\n" + stack);
}
if (error.name !== void 0 &&
error.message !== void 0) {
return error.name + ". " + error.message;
}
return formatNonError(error);
};
return function captureStackTrace(o) {
var stack = new Error().stack;
var split = stack.split(rline);
var len = split.length;
var ret = "";
for (var i = 0; i < len; i += 2) {
ret += split[i];
ret += "@";
ret += split[i + 1];
ret += "\n";
}
o.stack = ret;
};
}
else {
formatStack = function(stack, error) {
if (typeof stack === "string") return stack;
if ((typeof error === "object" ||
typeof error === "function") &&
error.name !== void 0 &&
error.message !== void 0) {
return error.name + ". " + error.message;
}
return formatNonError(error);
};
return null;
}
})();
return CapturedTrace;
};
},{"./es5.js":82,"./util.js":108}],78:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports = function(NEXT_FILTER) {
var util = _dereq_("./util.js");
var errors = _dereq_("./errors.js");
var tryCatch1 = util.tryCatch1;
var errorObj = util.errorObj;
var keys = _dereq_("./es5.js").keys;
var TypeError = errors.TypeError;
function CatchFilter(instances, callback, promise) {
this._instances = instances;
this._callback = callback;
this._promise = promise;
}
function CatchFilter$_safePredicate(predicate, e) {
var safeObject = {};
var retfilter = tryCatch1(predicate, safeObject, e);
if (retfilter === errorObj) return retfilter;
var safeKeys = keys(safeObject);
if (safeKeys.length) {
errorObj.e = new TypeError(
"Catch filter must inherit from Error "
+ "or be a simple predicate function");
return errorObj;
}
return retfilter;
}
CatchFilter.prototype.doFilter = function CatchFilter$_doFilter(e) {
var cb = this._callback;
var promise = this._promise;
var boundTo = promise._isBound() ? promise._boundTo : void 0;
for (var i = 0, len = this._instances.length; i < len; ++i) {
var item = this._instances[i];
var itemIsErrorType = item === Error ||
(item != null && item.prototype instanceof Error);
if (itemIsErrorType && e instanceof item) {
var ret = tryCatch1(cb, boundTo, e);
if (ret === errorObj) {
NEXT_FILTER.e = ret.e;
return NEXT_FILTER;
}
return ret;
} else if (typeof item === "function" && !itemIsErrorType) {
var shouldHandle = CatchFilter$_safePredicate(item, e);
if (shouldHandle === errorObj) {
var trace = errors.canAttach(errorObj.e)
? errorObj.e
: new Error(errorObj.e + "");
this._promise._attachExtraTrace(trace);
e = errorObj.e;
break;
} else if (shouldHandle) {
var ret = tryCatch1(cb, boundTo, e);
if (ret === errorObj) {
NEXT_FILTER.e = ret.e;
return NEXT_FILTER;
}
return ret;
}
}
}
NEXT_FILTER.e = e;
return NEXT_FILTER;
};
return CatchFilter;
};
},{"./errors.js":80,"./es5.js":82,"./util.js":108}],79:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
var util = _dereq_("./util.js");
var isPrimitive = util.isPrimitive;
var wrapsPrimitiveReceiver = util.wrapsPrimitiveReceiver;
module.exports = function(Promise) {
var returner = function Promise$_returner() {
return this;
};
var thrower = function Promise$_thrower() {
throw this;
};
var wrapper = function Promise$_wrapper(value, action) {
if (action === 1) {
return function Promise$_thrower() {
throw value;
};
}
else if (action === 2) {
return function Promise$_returner() {
return value;
};
}
};
Promise.prototype["return"] =
Promise.prototype.thenReturn =
function Promise$thenReturn(value) {
if (wrapsPrimitiveReceiver && isPrimitive(value)) {
return this._then(
wrapper(value, 2),
void 0,
void 0,
void 0,
void 0
);
}
return this._then(returner, void 0, void 0, value, void 0);
};
Promise.prototype["throw"] =
Promise.prototype.thenThrow =
function Promise$thenThrow(reason) {
if (wrapsPrimitiveReceiver && isPrimitive(reason)) {
return this._then(
wrapper(reason, 1),
void 0,
void 0,
void 0,
void 0
);
}
return this._then(thrower, void 0, void 0, reason, void 0);
};
};
},{"./util.js":108}],80:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
var global = _dereq_("./global.js");
var Objectfreeze = _dereq_("./es5.js").freeze;
var util = _dereq_("./util.js");
var inherits = util.inherits;
var notEnumerableProp = util.notEnumerableProp;
var Error = global.Error;
function markAsOriginatingFromRejection(e) {
try {
notEnumerableProp(e, "isAsync", true);
}
catch(ignore) {}
}
function originatesFromRejection(e) {
if (e == null) return false;
return ((e instanceof RejectionError) ||
e["isAsync"] === true);
}
function isError(obj) {
return obj instanceof Error;
}
function canAttach(obj) {
return isError(obj);
}
function subError(nameProperty, defaultMessage) {
function SubError(message) {
if (!(this instanceof SubError)) return new SubError(message);
this.message = typeof message === "string" ? message : defaultMessage;
this.name = nameProperty;
if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor);
}
}
inherits(SubError, Error);
return SubError;
}
var TypeError = global.TypeError;
if (typeof TypeError !== "function") {
TypeError = subError("TypeError", "type error");
}
var RangeError = global.RangeError;
if (typeof RangeError !== "function") {
RangeError = subError("RangeError", "range error");
}
var CancellationError = subError("CancellationError", "cancellation error");
var TimeoutError = subError("TimeoutError", "timeout error");
function RejectionError(message) {
this.name = "RejectionError";
this.message = message;
this.cause = message;
this.isAsync = true;
if (message instanceof Error) {
this.message = message.message;
this.stack = message.stack;
}
else if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor);
}
}
inherits(RejectionError, Error);
var key = "__BluebirdErrorTypes__";
var errorTypes = global[key];
if (!errorTypes) {
errorTypes = Objectfreeze({
CancellationError: CancellationError,
TimeoutError: TimeoutError,
RejectionError: RejectionError
});
notEnumerableProp(global, key, errorTypes);
}
module.exports = {
Error: Error,
TypeError: TypeError,
RangeError: RangeError,
CancellationError: errorTypes.CancellationError,
RejectionError: errorTypes.RejectionError,
TimeoutError: errorTypes.TimeoutError,
originatesFromRejection: originatesFromRejection,
markAsOriginatingFromRejection: markAsOriginatingFromRejection,
canAttach: canAttach
};
},{"./es5.js":82,"./global.js":86,"./util.js":108}],81:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports = function(Promise) {
var TypeError = _dereq_('./errors.js').TypeError;
function apiRejection(msg) {
var error = new TypeError(msg);
var ret = Promise.rejected(error);
var parent = ret._peekContext();
if (parent != null) {
parent._attachExtraTrace(error);
}
return ret;
}
return apiRejection;
};
},{"./errors.js":80}],82:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* 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 isES5 = (function(){
"use strict";
return this === void 0;
})();
if (isES5) {
module.exports = {
freeze: Object.freeze,
defineProperty: Object.defineProperty,
keys: Object.keys,
getPrototypeOf: Object.getPrototypeOf,
isArray: Array.isArray,
isES5: isES5
};
}
else {
var has = {}.hasOwnProperty;
var str = {}.toString;
var proto = {}.constructor.prototype;
var ObjectKeys = function ObjectKeys(o) {
var ret = [];
for (var key in o) {
if (has.call(o, key)) {
ret.push(key);
}
}
return ret;
}
var ObjectDefineProperty = function ObjectDefineProperty(o, key, desc) {
o[key] = desc.value;
return o;
}
var ObjectFreeze = function ObjectFreeze(obj) {
return obj;
}
var ObjectGetPrototypeOf = function ObjectGetPrototypeOf(obj) {
try {
return Object(obj).constructor.prototype;
}
catch (e) {
return proto;
}
}
var ArrayIsArray = function ArrayIsArray(obj) {
try {
return str.call(obj) === "[object Array]";
}
catch(e) {
return false;
}
}
module.exports = {
isArray: ArrayIsArray,
keys: ObjectKeys,
defineProperty: ObjectDefineProperty,
freeze: ObjectFreeze,
getPrototypeOf: ObjectGetPrototypeOf,
isES5: isES5
};
}
},{}],83:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports = function(Promise) {
var isArray = _dereq_("./util.js").isArray;
function Promise$_filter(booleans) {
var values = this instanceof Promise ? this._settledValue : this;
var len = values.length;
var ret = new Array(len);
var j = 0;
for (var i = 0; i < len; ++i) {
if (booleans[i]) ret[j++] = values[i];
}
ret.length = j;
return ret;
}
var ref = {ref: null};
Promise.filter = function Promise$Filter(promises, fn) {
return Promise.map(promises, fn, ref)
._then(Promise$_filter, void 0, void 0, ref.ref, void 0);
};
Promise.prototype.filter = function Promise$filter(fn) {
return this.map(fn, ref)
._then(Promise$_filter, void 0, void 0, ref.ref, void 0);
};
};
},{"./util.js":108}],84:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports = function(Promise, NEXT_FILTER) {
var util = _dereq_("./util.js");
var wrapsPrimitiveReceiver = util.wrapsPrimitiveReceiver;
var isPrimitive = util.isPrimitive;
var thrower = util.thrower;
function returnThis() {
return this;
}
function throwThis() {
throw this;
}
function return$(r) {
return function Promise$_returner() {
return r;
};
}
function throw$(r) {
return function Promise$_thrower() {
throw r;
};
}
function promisedFinally(ret, reasonOrValue, isFulfilled) {
var then;
if (wrapsPrimitiveReceiver && isPrimitive(reasonOrValue)) {
then = isFulfilled ? return$(reasonOrValue) : throw$(reasonOrValue);
}
else {
then = isFulfilled ? returnThis : throwThis;
}
return ret._then(then, thrower, void 0, reasonOrValue, void 0);
}
function finallyHandler(reasonOrValue) {
var promise = this.promise;
var handler = this.handler;
var ret = promise._isBound()
? handler.call(promise._boundTo)
: handler();
if (ret !== void 0) {
var maybePromise = Promise._cast(ret, void 0);
if (maybePromise instanceof Promise) {
return promisedFinally(maybePromise, reasonOrValue,
promise.isFulfilled());
}
}
if (promise.isRejected()) {
NEXT_FILTER.e = reasonOrValue;
return NEXT_FILTER;
}
else {
return reasonOrValue;
}
}
function tapHandler(value) {
var promise = this.promise;
var handler = this.handler;
var ret = promise._isBound()
? handler.call(promise._boundTo, value)
: handler(value);
if (ret !== void 0) {
var maybePromise = Promise._cast(ret, void 0);
if (maybePromise instanceof Promise) {
return promisedFinally(maybePromise, value, true);
}
}
return value;
}
Promise.prototype._passThroughHandler =
function Promise$_passThroughHandler(handler, isFinally) {
if (typeof handler !== "function") return this.then();
var promiseAndHandler = {
promise: this,
handler: handler
};
return this._then(
isFinally ? finallyHandler : tapHandler,
isFinally ? finallyHandler : void 0, void 0,
promiseAndHandler, void 0);
};
Promise.prototype.lastly =
Promise.prototype["finally"] = function Promise$finally(handler) {
return this._passThroughHandler(handler, true);
};
Promise.prototype.tap = function Promise$tap(handler) {
return this._passThroughHandler(handler, false);
};
};
},{"./util.js":108}],85:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports = function(Promise, apiRejection, INTERNAL) {
var PromiseSpawn = _dereq_("./promise_spawn.js")(Promise, INTERNAL);
var errors = _dereq_("./errors.js");
var TypeError = errors.TypeError;
var deprecated = _dereq_("./util.js").deprecated;
Promise.coroutine = function Promise$Coroutine(generatorFunction) {
if (typeof generatorFunction !== "function") {
throw new TypeError("generatorFunction must be a function");
}
var PromiseSpawn$ = PromiseSpawn;
return function () {
var generator = generatorFunction.apply(this, arguments);
var spawn = new PromiseSpawn$(void 0, void 0);
spawn._generator = generator;
spawn._next(void 0);
return spawn.promise();
};
};
Promise.coroutine.addYieldHandler = PromiseSpawn.addYieldHandler;
Promise.spawn = function Promise$Spawn(generatorFunction) {
deprecated("Promise.spawn is deprecated. Use Promise.coroutine instead.");
if (typeof generatorFunction !== "function") {
return apiRejection("generatorFunction must be a function");
}
var spawn = new PromiseSpawn(generatorFunction, this);
var ret = spawn.promise();
spawn._run(Promise.spawn);
return ret;
};
};
},{"./errors.js":80,"./promise_spawn.js":93,"./util.js":108}],86:[function(_dereq_,module,exports){
(function (global){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
module.exports = (function() {
if (this !== void 0) return this;
try {return global;}
catch(e) {}
try {return window;}
catch(e) {}
try {return self;}
catch(e) {}
})();
}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],87:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports = function(Promise, PromiseArray, INTERNAL, apiRejection) {
var all = Promise.all;
var util = _dereq_("./util.js");
var canAttach = _dereq_("./errors.js").canAttach;
var isArray = util.isArray;
var _cast = Promise._cast;
function unpack(values) {
return Promise$_Map(values, this[0], this[1], this[2]);
}
function Promise$_Map(promises, fn, useBound, ref) {
if (typeof fn !== "function") {
return apiRejection("fn must be a function");
}
var receiver = void 0;
if (useBound === true) {
if (promises._isBound()) {
receiver = promises._boundTo;
}
}
else if (useBound !== false) {
receiver = useBound;
}
var shouldUnwrapItems = ref !== void 0;
if (shouldUnwrapItems) ref.ref = promises;
if (promises instanceof Promise) {
var pack = [fn, receiver, ref];
return promises._then(unpack, void 0, void 0, pack, void 0);
}
else if (!isArray(promises)) {
return apiRejection("expecting an array, a promise or a thenable");
}
var promise = new Promise(INTERNAL);
if (receiver !== void 0) promise._setBoundTo(receiver);
promise._setTrace(void 0);
var mapping = new Mapping(promise,
fn,
promises,
receiver,
shouldUnwrapItems);
mapping.init();
return promise;
}
var pending = {};
function Mapping(promise, callback, items, receiver, shouldUnwrapItems) {
this.shouldUnwrapItems = shouldUnwrapItems;
this.index = 0;
this.items = items;
this.callback = callback;
this.receiver = receiver;
this.promise = promise;
this.result = new Array(items.length);
}
util.inherits(Mapping, PromiseArray);
Mapping.prototype.init = function Mapping$init() {
var items = this.items;
var len = items.length;
var result = this.result;
var isRejected = false;
for (var i = 0; i < len; ++i) {
var maybePromise = _cast(items[i], void 0);
if (maybePromise instanceof Promise) {
if (maybePromise.isPending()) {
result[i] = pending;
maybePromise._proxyPromiseArray(this, i);
}
else if (maybePromise.isFulfilled()) {
result[i] = maybePromise.value();
}
else {
maybePromise._unsetRejectionIsUnhandled();
if (!isRejected) {
this.reject(maybePromise.reason());
isRejected = true;
}
}
}
else {
result[i] = maybePromise;
}
}
if (!isRejected) this.iterate();
};
Mapping.prototype.isResolved = function Mapping$isResolved() {
return this.promise === null;
};
Mapping.prototype._promiseProgressed =
function Mapping$_promiseProgressed(value) {
if (this.isResolved()) return;
this.promise._progress(value);
};
Mapping.prototype._promiseFulfilled =
function Mapping$_promiseFulfilled(value, index) {
if (this.isResolved()) return;
this.result[index] = value;
if (this.shouldUnwrapItems) this.items[index] = value;
if (this.index === index) this.iterate();
};
Mapping.prototype._promiseRejected =
function Mapping$_promiseRejected(reason) {
this.reject(reason);
};
Mapping.prototype.reject = function Mapping$reject(reason) {
if (this.isResolved()) return;
var trace = canAttach(reason) ? reason : new Error(reason + "");
this.promise._attachExtraTrace(trace);
this.promise._reject(reason, trace);
};
Mapping.prototype.iterate = function Mapping$iterate() {
var i = this.index;
var items = this.items;
var result = this.result;
var len = items.length;
var result = this.result;
var receiver = this.receiver;
var callback = this.callback;
for (; i < len; ++i) {
var value = result[i];
if (value === pending) {
this.index = i;
return;
}
try { result[i] = callback.call(receiver, value, i, len); }
catch (e) { return this.reject(e); }
}
this.promise._follow(all(result));
this.items = this.result = this.callback = this.promise = null;
};
Promise.prototype.map = function Promise$map(fn, ref) {
return Promise$_Map(this, fn, true, ref);
};
Promise.map = function Promise$Map(promises, fn, ref) {
return Promise$_Map(promises, fn, false, ref);
};
};
},{"./errors.js":80,"./util.js":108}],88:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports = function(Promise) {
var util = _dereq_("./util.js");
var async = _dereq_("./async.js");
var tryCatch2 = util.tryCatch2;
var tryCatch1 = util.tryCatch1;
var errorObj = util.errorObj;
function thrower(r) {
throw r;
}
function Promise$_successAdapter(val, receiver) {
var nodeback = this;
var ret = val === void 0
? tryCatch1(nodeback, receiver, null)
: tryCatch2(nodeback, receiver, null, val);
if (ret === errorObj) {
async.invokeLater(thrower, void 0, ret.e);
}
}
function Promise$_errorAdapter(reason, receiver) {
var nodeback = this;
var ret = tryCatch1(nodeback, receiver, reason);
if (ret === errorObj) {
async.invokeLater(thrower, void 0, ret.e);
}
}
Promise.prototype.nodeify = function Promise$nodeify(nodeback) {
if (typeof nodeback == "function") {
this._then(
Promise$_successAdapter,
Promise$_errorAdapter,
void 0,
nodeback,
this._isBound() ? this._boundTo : null
);
}
return this;
};
};
},{"./async.js":73,"./util.js":108}],89:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports = function(Promise, isPromiseArrayProxy) {
var util = _dereq_("./util.js");
var async = _dereq_("./async.js");
var errors = _dereq_("./errors.js");
var tryCatch1 = util.tryCatch1;
var errorObj = util.errorObj;
Promise.prototype.progressed = function Promise$progressed(handler) {
return this._then(void 0, void 0, handler, void 0, void 0);
};
Promise.prototype._progress = function Promise$_progress(progressValue) {
if (this._isFollowingOrFulfilledOrRejected()) return;
this._progressUnchecked(progressValue);
};
Promise.prototype._progressHandlerAt =
function Promise$_progressHandlerAt(index) {
if (index === 0) return this._progressHandler0;
return this[index + 2 - 5];
};
Promise.prototype._doProgressWith =
function Promise$_doProgressWith(progression) {
var progressValue = progression.value;
var handler = progression.handler;
var promise = progression.promise;
var receiver = progression.receiver;
this._pushContext();
var ret = tryCatch1(handler, receiver, progressValue);
this._popContext();
if (ret === errorObj) {
if (ret.e != null &&
ret.e.name !== "StopProgressPropagation") {
var trace = errors.canAttach(ret.e)
? ret.e : new Error(ret.e + "");
promise._attachExtraTrace(trace);
promise._progress(ret.e);
}
}
else if (ret instanceof Promise) {
ret._then(promise._progress, null, null, promise, void 0);
}
else {
promise._progress(ret);
}
};
Promise.prototype._progressUnchecked =
function Promise$_progressUnchecked(progressValue) {
if (!this.isPending()) return;
var len = this._length();
var progress = this._progress;
for (var i = 0; i < len; i += 5) {
var handler = this._progressHandlerAt(i);
var promise = this._promiseAt(i);
if (!(promise instanceof Promise)) {
var receiver = this._receiverAt(i);
if (typeof handler === "function") {
handler.call(receiver, progressValue, promise);
}
else if (receiver instanceof Promise && receiver._isProxied()) {
receiver._progressUnchecked(progressValue);
}
else if (isPromiseArrayProxy(receiver, promise)) {
receiver._promiseProgressed(progressValue, promise);
}
continue;
}
if (typeof handler === "function") {
async.invoke(this._doProgressWith, this, {
handler: handler,
promise: promise,
receiver: this._receiverAt(i),
value: progressValue
});
}
else {
async.invoke(progress, promise, progressValue);
}
}
};
};
},{"./async.js":73,"./errors.js":80,"./util.js":108}],90:[function(_dereq_,module,exports){
(function (process){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports = function() {
var global = _dereq_("./global.js");
var util = _dereq_("./util.js");
var async = _dereq_("./async.js");
var errors = _dereq_("./errors.js");
var INTERNAL = function(){};
var APPLY = {};
var NEXT_FILTER = {e: null};
var PromiseArray = _dereq_("./promise_array.js")(Promise, INTERNAL);
var CapturedTrace = _dereq_("./captured_trace.js")();
var CatchFilter = _dereq_("./catch_filter.js")(NEXT_FILTER);
var PromiseResolver = _dereq_("./promise_resolver.js");
var isArray = util.isArray;
var errorObj = util.errorObj;
var tryCatch1 = util.tryCatch1;
var tryCatch2 = util.tryCatch2;
var tryCatchApply = util.tryCatchApply;
var RangeError = errors.RangeError;
var TypeError = errors.TypeError;
var CancellationError = errors.CancellationError;
var TimeoutError = errors.TimeoutError;
var RejectionError = errors.RejectionError;
var originatesFromRejection = errors.originatesFromRejection;
var markAsOriginatingFromRejection = errors.markAsOriginatingFromRejection;
var canAttach = errors.canAttach;
var thrower = util.thrower;
var apiRejection = _dereq_("./errors_api_rejection")(Promise);
var makeSelfResolutionError = function Promise$_makeSelfResolutionError() {
return new TypeError("circular promise resolution chain");
};
function isPromise(obj) {
if (obj === void 0) return false;
return obj instanceof Promise;
}
function isPromiseArrayProxy(receiver, promiseSlotValue) {
if (receiver instanceof PromiseArray) {
return promiseSlotValue >= 0;
}
return false;
}
function Promise(resolver) {
if (typeof resolver !== "function") {
throw new TypeError("the promise constructor requires a resolver function");
}
if (this.constructor !== Promise) {
throw new TypeError("the promise constructor cannot be invoked directly");
}
this._bitField = 0;
this._fulfillmentHandler0 = void 0;
this._rejectionHandler0 = void 0;
this._promise0 = void 0;
this._receiver0 = void 0;
this._settledValue = void 0;
this._boundTo = void 0;
if (resolver !== INTERNAL) this._resolveFromResolver(resolver);
}
Promise.prototype.bind = function Promise$bind(thisArg) {
var ret = new Promise(INTERNAL);
ret._setTrace(this);
ret._follow(this);
ret._setBoundTo(thisArg);
if (this._cancellable()) {
ret._setCancellable();
ret._cancellationParent = this;
}
return ret;
};
Promise.prototype.toString = function Promise$toString() {
return "[object Promise]";
};
Promise.prototype.caught = Promise.prototype["catch"] =
function Promise$catch(fn) {
var len = arguments.length;
if (len > 1) {
var catchInstances = new Array(len - 1),
j = 0, i;
for (i = 0; i < len - 1; ++i) {
var item = arguments[i];
if (typeof item === "function") {
catchInstances[j++] = item;
}
else {
var catchFilterTypeError =
new TypeError(
"A catch filter must be an error constructor "
+ "or a filter function");
this._attachExtraTrace(catchFilterTypeError);
async.invoke(this._reject, this, catchFilterTypeError);
return;
}
}
catchInstances.length = j;
fn = arguments[i];
this._resetTrace();
var catchFilter = new CatchFilter(catchInstances, fn, this);
return this._then(void 0, catchFilter.doFilter, void 0,
catchFilter, void 0);
}
return this._then(void 0, fn, void 0, void 0, void 0);
};
Promise.prototype.then =
function Promise$then(didFulfill, didReject, didProgress) {
return this._then(didFulfill, didReject, didProgress,
void 0, void 0);
};
Promise.prototype.done =
function Promise$done(didFulfill, didReject, didProgress) {
var promise = this._then(didFulfill, didReject, didProgress,
void 0, void 0);
promise._setIsFinal();
};
Promise.prototype.spread = function Promise$spread(didFulfill, didReject) {
return this._then(didFulfill, didReject, void 0,
APPLY, void 0);
};
Promise.prototype.isCancellable = function Promise$isCancellable() {
return !this.isResolved() &&
this._cancellable();
};
Promise.prototype.toJSON = function Promise$toJSON() {
var ret = {
isFulfilled: false,
isRejected: false,
fulfillmentValue: void 0,
rejectionReason: void 0
};
if (this.isFulfilled()) {
ret.fulfillmentValue = this._settledValue;
ret.isFulfilled = true;
}
else if (this.isRejected()) {
ret.rejectionReason = this._settledValue;
ret.isRejected = true;
}
return ret;
};
Promise.prototype.all = function Promise$all() {
return Promise$_all(this, true);
};
Promise.is = isPromise;
function Promise$_all(promises, useBound) {
return Promise$_CreatePromiseArray(
promises,
PromiseArray,
useBound === true && promises._isBound()
? promises._boundTo
: void 0
).promise();
}
Promise.all = function Promise$All(promises) {
return Promise$_all(promises, false);
};
Promise.join = function Promise$Join() {
var $_len = arguments.length;var args = new Array($_len); for(var $_i = 0; $_i < $_len; ++$_i) {args[$_i] = arguments[$_i];}
return Promise$_CreatePromiseArray(args, PromiseArray, void 0).promise();
};
Promise.resolve = Promise.fulfilled =
function Promise$Resolve(value) {
var ret = new Promise(INTERNAL);
ret._setTrace(void 0);
if (ret._tryFollow(value)) {
return ret;
}
ret._cleanValues();
ret._setFulfilled();
ret._settledValue = value;
return ret;
};
Promise.reject = Promise.rejected = function Promise$Reject(reason) {
var ret = new Promise(INTERNAL);
ret._setTrace(void 0);
markAsOriginatingFromRejection(reason);
ret._cleanValues();
ret._setRejected();
ret._settledValue = reason;
if (!canAttach(reason)) {
var trace = new Error(reason + "");
ret._setCarriedStackTrace(trace);
}
ret._ensurePossibleRejectionHandled();
return ret;
};
Promise.prototype.error = function Promise$_error(fn) {
return this.caught(originatesFromRejection, fn);
};
Promise.prototype._resolveFromSyncValue =
function Promise$_resolveFromSyncValue(value) {
if (value === errorObj) {
this._cleanValues();
this._setRejected();
this._settledValue = value.e;
this._ensurePossibleRejectionHandled();
}
else {
var maybePromise = Promise._cast(value, void 0);
if (maybePromise instanceof Promise) {
this._follow(maybePromise);
}
else {
this._cleanValues();
this._setFulfilled();
this._settledValue = value;
}
}
};
Promise.method = function Promise$_Method(fn) {
if (typeof fn !== "function") {
throw new TypeError("fn must be a function");
}
return function Promise$_method() {
var value;
switch(arguments.length) {
case 0: value = tryCatch1(fn, this, void 0); break;
case 1: value = tryCatch1(fn, this, arguments[0]); break;
case 2: value = tryCatch2(fn, this, arguments[0], arguments[1]); break;
default:
var $_len = arguments.length;var args = new Array($_len); for(var $_i = 0; $_i < $_len; ++$_i) {args[$_i] = arguments[$_i];}
value = tryCatchApply(fn, args, this); break;
}
var ret = new Promise(INTERNAL);
ret._setTrace(void 0);
ret._resolveFromSyncValue(value);
return ret;
};
};
Promise.attempt = Promise["try"] = function Promise$_Try(fn, args, ctx) {
if (typeof fn !== "function") {
return apiRejection("fn must be a function");
}
var value = isArray(args)
? tryCatchApply(fn, args, ctx)
: tryCatch1(fn, ctx, args);
var ret = new Promise(INTERNAL);
ret._setTrace(void 0);
ret._resolveFromSyncValue(value);
return ret;
};
Promise.defer = Promise.pending = function Promise$Defer() {
var promise = new Promise(INTERNAL);
promise._setTrace(void 0);
return new PromiseResolver(promise);
};
Promise.bind = function Promise$Bind(thisArg) {
var ret = new Promise(INTERNAL);
ret._setTrace(void 0);
ret._setFulfilled();
ret._setBoundTo(thisArg);
return ret;
};
Promise.cast = function Promise$_Cast(obj) {
var ret = Promise._cast(obj, void 0);
if (!(ret instanceof Promise)) {
return Promise.resolve(ret);
}
return ret;
};
Promise.onPossiblyUnhandledRejection =
function Promise$OnPossiblyUnhandledRejection(fn) {
CapturedTrace.possiblyUnhandledRejection = typeof fn === "function"
? fn : void 0;
};
var unhandledRejectionHandled;
Promise.onUnhandledRejectionHandled =
function Promise$onUnhandledRejectionHandled(fn) {
unhandledRejectionHandled = typeof fn === "function" ? fn : void 0;
};
var debugging = false || !!(
typeof process !== "undefined" &&
typeof process.execPath === "string" &&
typeof process.env === "object" &&
(process.env["BLUEBIRD_DEBUG"] ||
process.env["NODE_ENV"] === "development")
);
Promise.longStackTraces = function Promise$LongStackTraces() {
if (async.haveItemsQueued() &&
debugging === false
) {
throw new Error("cannot enable long stack traces after promises have been created");
}
debugging = CapturedTrace.isSupported();
};
Promise.hasLongStackTraces = function Promise$HasLongStackTraces() {
return debugging && CapturedTrace.isSupported();
};
Promise.prototype._setProxyHandlers =
function Promise$_setProxyHandlers(receiver, promiseSlotValue) {
var index = this._length();
if (index >= 524287 - 5) {
index = 0;
this._setLength(0);
}
if (index === 0) {
this._promise0 = promiseSlotValue;
this._receiver0 = receiver;
}
else {
var i = index - 5;
this[i + 3] = promiseSlotValue;
this[i + 4] = receiver;
this[i + 0] =
this[i + 1] =
this[i + 2] = void 0;
}
this._setLength(index + 5);
};
Promise.prototype._proxyPromiseArray =
function Promise$_proxyPromiseArray(promiseArray, index) {
this._setProxyHandlers(promiseArray, index);
};
Promise.prototype._proxyPromise = function Promise$_proxyPromise(promise) {
promise._setProxied();
this._setProxyHandlers(promise, -1);
};
Promise.prototype._then =
function Promise$_then(
didFulfill,
didReject,
didProgress,
receiver,
internalData
) {
var haveInternalData = internalData !== void 0;
var ret = haveInternalData ? internalData : new Promise(INTERNAL);
if (debugging && !haveInternalData) {
var haveSameContext = this._peekContext() === this._traceParent;
ret._traceParent = haveSameContext ? this._traceParent : this;
ret._setTrace(this);
}
if (!haveInternalData && this._isBound()) {
ret._setBoundTo(this._boundTo);
}
var callbackIndex =
this._addCallbacks(didFulfill, didReject, didProgress, ret, receiver);
if (!haveInternalData && this._cancellable()) {
ret._setCancellable();
ret._cancellationParent = this;
}
if (this.isResolved()) {
async.invoke(this._queueSettleAt, this, callbackIndex);
}
return ret;
};
Promise.prototype._length = function Promise$_length() {
return this._bitField & 524287;
};
Promise.prototype._isFollowingOrFulfilledOrRejected =
function Promise$_isFollowingOrFulfilledOrRejected() {
return (this._bitField & 939524096) > 0;
};
Promise.prototype._isFollowing = function Promise$_isFollowing() {
return (this._bitField & 536870912) === 536870912;
};
Promise.prototype._setLength = function Promise$_setLength(len) {
this._bitField = (this._bitField & -524288) |
(len & 524287);
};
Promise.prototype._setFulfilled = function Promise$_setFulfilled() {
this._bitField = this._bitField | 268435456;
};
Promise.prototype._setRejected = function Promise$_setRejected() {
this._bitField = this._bitField | 134217728;
};
Promise.prototype._setFollowing = function Promise$_setFollowing() {
this._bitField = this._bitField | 536870912;
};
Promise.prototype._setIsFinal = function Promise$_setIsFinal() {
this._bitField = this._bitField | 33554432;
};
Promise.prototype._isFinal = function Promise$_isFinal() {
return (this._bitField & 33554432) > 0;
};
Promise.prototype._cancellable = function Promise$_cancellable() {
return (this._bitField & 67108864) > 0;
};
Promise.prototype._setCancellable = function Promise$_setCancellable() {
this._bitField = this._bitField | 67108864;
};
Promise.prototype._unsetCancellable = function Promise$_unsetCancellable() {
this._bitField = this._bitField & (~67108864);
};
Promise.prototype._setRejectionIsUnhandled =
function Promise$_setRejectionIsUnhandled() {
this._bitField = this._bitField | 2097152;
};
Promise.prototype._unsetRejectionIsUnhandled =
function Promise$_unsetRejectionIsUnhandled() {
this._bitField = this._bitField & (~2097152);
if (this._isUnhandledRejectionNotified()) {
this._unsetUnhandledRejectionIsNotified();
this._notifyUnhandledRejectionIsHandled();
}
};
Promise.prototype._isRejectionUnhandled =
function Promise$_isRejectionUnhandled() {
return (this._bitField & 2097152) > 0;
};
Promise.prototype._setUnhandledRejectionIsNotified =
function Promise$_setUnhandledRejectionIsNotified() {
this._bitField = this._bitField | 524288;
};
Promise.prototype._unsetUnhandledRejectionIsNotified =
function Promise$_unsetUnhandledRejectionIsNotified() {
this._bitField = this._bitField & (~524288);
};
Promise.prototype._isUnhandledRejectionNotified =
function Promise$_isUnhandledRejectionNotified() {
return (this._bitField & 524288) > 0;
};
Promise.prototype._setCarriedStackTrace =
function Promise$_setCarriedStackTrace(capturedTrace) {
this._bitField = this._bitField | 1048576;
this._fulfillmentHandler0 = capturedTrace;
};
Promise.prototype._unsetCarriedStackTrace =
function Promise$_unsetCarriedStackTrace() {
this._bitField = this._bitField & (~1048576);
this._fulfillmentHandler0 = void 0;
};
Promise.prototype._isCarryingStackTrace =
function Promise$_isCarryingStackTrace() {
return (this._bitField & 1048576) > 0;
};
Promise.prototype._getCarriedStackTrace =
function Promise$_getCarriedStackTrace() {
return this._isCarryingStackTrace()
? this._fulfillmentHandler0
: void 0;
};
Promise.prototype._receiverAt = function Promise$_receiverAt(index) {
var ret;
if (index === 0) {
ret = this._receiver0;
}
else {
ret = this[index + 4 - 5];
}
if (this._isBound() && ret === void 0) {
return this._boundTo;
}
return ret;
};
Promise.prototype._promiseAt = function Promise$_promiseAt(index) {
if (index === 0) return this._promise0;
return this[index + 3 - 5];
};
Promise.prototype._fulfillmentHandlerAt =
function Promise$_fulfillmentHandlerAt(index) {
if (index === 0) return this._fulfillmentHandler0;
return this[index + 0 - 5];
};
Promise.prototype._rejectionHandlerAt =
function Promise$_rejectionHandlerAt(index) {
if (index === 0) return this._rejectionHandler0;
return this[index + 1 - 5];
};
Promise.prototype._unsetAt = function Promise$_unsetAt(index) {
if (index === 0) {
this._rejectionHandler0 =
this._progressHandler0 =
this._promise0 =
this._receiver0 = void 0;
if (!this._isCarryingStackTrace()) {
this._fulfillmentHandler0 = void 0;
}
}
else {
this[index - 5 + 0] =
this[index - 5 + 1] =
this[index - 5 + 2] =
this[index - 5 + 3] =
this[index - 5 + 4] = void 0;
}
};
Promise.prototype._resolveFromResolver =
function Promise$_resolveFromResolver(resolver) {
var promise = this;
this._setTrace(void 0);
this._pushContext();
function Promise$_resolver(val) {
if (promise._tryFollow(val)) {
return;
}
promise._fulfill(val);
}
function Promise$_rejecter(val) {
var trace = canAttach(val) ? val : new Error(val + "");
promise._attachExtraTrace(trace);
markAsOriginatingFromRejection(val);
promise._reject(val, trace === val ? void 0 : trace);
}
var r = tryCatch2(resolver, void 0, Promise$_resolver, Promise$_rejecter);
this._popContext();
if (r !== void 0 && r === errorObj) {
var e = r.e;
var trace = canAttach(e) ? e : new Error(e + "");
promise._reject(e, trace);
}
};
Promise.prototype._addCallbacks = function Promise$_addCallbacks(
fulfill,
reject,
progress,
promise,
receiver
) {
var index = this._length();
if (index >= 524287 - 5) {
index = 0;
this._setLength(0);
}
if (index === 0) {
this._promise0 = promise;
if (receiver !== void 0) this._receiver0 = receiver;
if (typeof fulfill === "function" && !this._isCarryingStackTrace())
this._fulfillmentHandler0 = fulfill;
if (typeof reject === "function") this._rejectionHandler0 = reject;
if (typeof progress === "function") this._progressHandler0 = progress;
}
else {
var i = index - 5;
this[i + 3] = promise;
this[i + 4] = receiver;
this[i + 0] = typeof fulfill === "function"
? fulfill : void 0;
this[i + 1] = typeof reject === "function"
? reject : void 0;
this[i + 2] = typeof progress === "function"
? progress : void 0;
}
this._setLength(index + 5);
return index;
};
Promise.prototype._setBoundTo = function Promise$_setBoundTo(obj) {
if (obj !== void 0) {
this._bitField = this._bitField | 8388608;
this._boundTo = obj;
}
else {
this._bitField = this._bitField & (~8388608);
}
};
Promise.prototype._isBound = function Promise$_isBound() {
return (this._bitField & 8388608) === 8388608;
};
Promise.prototype._spreadSlowCase =
function Promise$_spreadSlowCase(targetFn, promise, values, boundTo) {
var promiseForAll =
Promise$_CreatePromiseArray
(values, PromiseArray, boundTo)
.promise()
._then(function() {
return targetFn.apply(boundTo, arguments);
}, void 0, void 0, APPLY, void 0);
promise._follow(promiseForAll);
};
Promise.prototype._callSpread =
function Promise$_callSpread(handler, promise, value, localDebugging) {
var boundTo = this._isBound() ? this._boundTo : void 0;
if (isArray(value)) {
for (var i = 0, len = value.length; i < len; ++i) {
if (isPromise(Promise._cast(value[i], void 0))) {
this._spreadSlowCase(handler, promise, value, boundTo);
return;
}
}
}
if (localDebugging) promise._pushContext();
return tryCatchApply(handler, value, boundTo);
};
Promise.prototype._callHandler =
function Promise$_callHandler(
handler, receiver, promise, value, localDebugging) {
var x;
if (receiver === APPLY && !this.isRejected()) {
x = this._callSpread(handler, promise, value, localDebugging);
}
else {
if (localDebugging) promise._pushContext();
x = tryCatch1(handler, receiver, value);
}
if (localDebugging) promise._popContext();
return x;
};
Promise.prototype._settlePromiseFromHandler =
function Promise$_settlePromiseFromHandler(
handler, receiver, value, promise
) {
if (!isPromise(promise)) {
handler.call(receiver, value, promise);
return;
}
var localDebugging = debugging;
var x = this._callHandler(handler, receiver,
promise, value, localDebugging);
if (promise._isFollowing()) return;
if (x === errorObj || x === promise || x === NEXT_FILTER) {
var err = x === promise
? makeSelfResolutionError()
: x.e;
var trace = canAttach(err) ? err : new Error(err + "");
if (x !== NEXT_FILTER) promise._attachExtraTrace(trace);
promise._rejectUnchecked(err, trace);
}
else {
var castValue = Promise._cast(x, promise);
if (isPromise(castValue)) {
if (castValue.isRejected() &&
!castValue._isCarryingStackTrace() &&
!canAttach(castValue._settledValue)) {
var trace = new Error(castValue._settledValue + "");
promise._attachExtraTrace(trace);
castValue._setCarriedStackTrace(trace);
}
promise._follow(castValue);
if (castValue._cancellable()) {
promise._cancellationParent = castValue;
promise._setCancellable();
}
}
else {
promise._fulfillUnchecked(x);
}
}
};
Promise.prototype._follow =
function Promise$_follow(promise) {
this._setFollowing();
if (promise.isPending()) {
if (promise._cancellable() ) {
this._cancellationParent = promise;
this._setCancellable();
}
promise._proxyPromise(this);
}
else if (promise.isFulfilled()) {
this._fulfillUnchecked(promise._settledValue);
}
else {
this._rejectUnchecked(promise._settledValue,
promise._getCarriedStackTrace());
}
if (promise._isRejectionUnhandled()) promise._unsetRejectionIsUnhandled();
if (debugging &&
promise._traceParent == null) {
promise._traceParent = this;
}
};
Promise.prototype._tryFollow =
function Promise$_tryFollow(value) {
if (this._isFollowingOrFulfilledOrRejected() ||
value === this) {
return false;
}
var maybePromise = Promise._cast(value, void 0);
if (!isPromise(maybePromise)) {
return false;
}
this._follow(maybePromise);
return true;
};
Promise.prototype._resetTrace = function Promise$_resetTrace() {
if (debugging) {
this._trace = new CapturedTrace(this._peekContext() === void 0);
}
};
Promise.prototype._setTrace = function Promise$_setTrace(parent) {
if (debugging) {
var context = this._peekContext();
this._traceParent = context;
var isTopLevel = context === void 0;
if (parent !== void 0 &&
parent._traceParent === context) {
this._trace = parent._trace;
}
else {
this._trace = new CapturedTrace(isTopLevel);
}
}
return this;
};
Promise.prototype._attachExtraTrace =
function Promise$_attachExtraTrace(error) {
if (debugging) {
var promise = this;
var stack = error.stack;
stack = typeof stack === "string"
? stack.split("\n") : [];
var headerLineCount = 1;
while(promise != null &&
promise._trace != null) {
stack = CapturedTrace.combine(
stack,
promise._trace.stack.split("\n")
);
promise = promise._traceParent;
}
var max = Error.stackTraceLimit + headerLineCount;
var len = stack.length;
if (len > max) {
stack.length = max;
}
if (stack.length <= headerLineCount) {
error.stack = "(No stack trace)";
}
else {
error.stack = stack.join("\n");
}
}
};
Promise.prototype._cleanValues = function Promise$_cleanValues() {
if (this._cancellable()) {
this._cancellationParent = void 0;
}
};
Promise.prototype._fulfill = function Promise$_fulfill(value) {
if (this._isFollowingOrFulfilledOrRejected()) return;
this._fulfillUnchecked(value);
};
Promise.prototype._reject =
function Promise$_reject(reason, carriedStackTrace) {
if (this._isFollowingOrFulfilledOrRejected()) return;
this._rejectUnchecked(reason, carriedStackTrace);
};
Promise.prototype._settlePromiseAt = function Promise$_settlePromiseAt(index) {
var handler = this.isFulfilled()
? this._fulfillmentHandlerAt(index)
: this._rejectionHandlerAt(index);
var value = this._settledValue;
var receiver = this._receiverAt(index);
var promise = this._promiseAt(index);
if (typeof handler === "function") {
this._settlePromiseFromHandler(handler, receiver, value, promise);
}
else {
var done = false;
var isFulfilled = this.isFulfilled();
if (receiver !== void 0) {
if (receiver instanceof Promise &&
receiver._isProxied()) {
receiver._unsetProxied();
if (isFulfilled) receiver._fulfillUnchecked(value);
else receiver._rejectUnchecked(value,
this._getCarriedStackTrace());
done = true;
}
else if (isPromiseArrayProxy(receiver, promise)) {
if (isFulfilled) receiver._promiseFulfilled(value, promise);
else receiver._promiseRejected(value, promise);
done = true;
}
}
if (!done) {
if (isFulfilled) promise._fulfill(value);
else promise._reject(value, this._getCarriedStackTrace());
}
}
if (index >= 256) {
this._queueGC();
}
};
Promise.prototype._isProxied = function Promise$_isProxied() {
return (this._bitField & 4194304) === 4194304;
};
Promise.prototype._setProxied = function Promise$_setProxied() {
this._bitField = this._bitField | 4194304;
};
Promise.prototype._unsetProxied = function Promise$_unsetProxied() {
this._bitField = this._bitField & (~4194304);
};
Promise.prototype._isGcQueued = function Promise$_isGcQueued() {
return (this._bitField & -1073741824) === -1073741824;
};
Promise.prototype._setGcQueued = function Promise$_setGcQueued() {
this._bitField = this._bitField | -1073741824;
};
Promise.prototype._unsetGcQueued = function Promise$_unsetGcQueued() {
this._bitField = this._bitField & (~-1073741824);
};
Promise.prototype._queueGC = function Promise$_queueGC() {
if (this._isGcQueued()) return;
this._setGcQueued();
async.invokeLater(this._gc, this, void 0);
};
Promise.prototype._gc = function Promise$gc() {
var len = this._length();
this._unsetAt(0);
for (var i = 0; i < len; i++) {
delete this[i];
}
this._setLength(0);
this._unsetGcQueued();
};
Promise.prototype._queueSettleAt = function Promise$_queueSettleAt(index) {
if (this._isRejectionUnhandled()) this._unsetRejectionIsUnhandled();
async.invoke(this._settlePromiseAt, this, index);
};
Promise.prototype._fulfillUnchecked =
function Promise$_fulfillUnchecked(value) {
if (!this.isPending()) return;
if (value === this) {
var err = makeSelfResolutionError();
this._attachExtraTrace(err);
return this._rejectUnchecked(err, void 0);
}
this._cleanValues();
this._setFulfilled();
this._settledValue = value;
var len = this._length();
if (len > 0) {
async.invoke(this._settlePromises, this, len);
}
};
Promise.prototype._rejectUncheckedCheckError =
function Promise$_rejectUncheckedCheckError(reason) {
var trace = canAttach(reason) ? reason : new Error(reason + "");
this._rejectUnchecked(reason, trace === reason ? void 0 : trace);
};
Promise.prototype._rejectUnchecked =
function Promise$_rejectUnchecked(reason, trace) {
if (!this.isPending()) return;
if (reason === this) {
var err = makeSelfResolutionError();
this._attachExtraTrace(err);
return this._rejectUnchecked(err);
}
this._cleanValues();
this._setRejected();
this._settledValue = reason;
if (this._isFinal()) {
async.invokeLater(thrower, void 0, trace === void 0 ? reason : trace);
return;
}
var len = this._length();
if (trace !== void 0) this._setCarriedStackTrace(trace);
if (len > 0) {
async.invoke(this._rejectPromises, this, null);
}
else {
this._ensurePossibleRejectionHandled();
}
};
Promise.prototype._rejectPromises = function Promise$_rejectPromises() {
this._settlePromises();
this._unsetCarriedStackTrace();
};
Promise.prototype._settlePromises = function Promise$_settlePromises() {
var len = this._length();
for (var i = 0; i < len; i+= 5) {
this._settlePromiseAt(i);
}
};
Promise.prototype._ensurePossibleRejectionHandled =
function Promise$_ensurePossibleRejectionHandled() {
this._setRejectionIsUnhandled();
if (CapturedTrace.possiblyUnhandledRejection !== void 0) {
async.invokeLater(this._notifyUnhandledRejection, this, void 0);
}
};
Promise.prototype._notifyUnhandledRejectionIsHandled =
function Promise$_notifyUnhandledRejectionIsHandled() {
if (typeof unhandledRejectionHandled === "function") {
async.invokeLater(unhandledRejectionHandled, void 0, this);
}
};
Promise.prototype._notifyUnhandledRejection =
function Promise$_notifyUnhandledRejection() {
if (this._isRejectionUnhandled()) {
var reason = this._settledValue;
var trace = this._getCarriedStackTrace();
this._setUnhandledRejectionIsNotified();
if (trace !== void 0) {
this._unsetCarriedStackTrace();
reason = trace;
}
if (typeof CapturedTrace.possiblyUnhandledRejection === "function") {
CapturedTrace.possiblyUnhandledRejection(reason, this);
}
}
};
var contextStack = [];
Promise.prototype._peekContext = function Promise$_peekContext() {
var lastIndex = contextStack.length - 1;
if (lastIndex >= 0) {
return contextStack[lastIndex];
}
return void 0;
};
Promise.prototype._pushContext = function Promise$_pushContext() {
if (!debugging) return;
contextStack.push(this);
};
Promise.prototype._popContext = function Promise$_popContext() {
if (!debugging) return;
contextStack.pop();
};
function Promise$_CreatePromiseArray(
promises, PromiseArrayConstructor, boundTo) {
var list = null;
if (isArray(promises)) {
list = promises;
}
else {
list = Promise._cast(promises, void 0);
if (list !== promises) {
list._setBoundTo(boundTo);
}
else if (!isPromise(list)) {
list = null;
}
}
if (list !== null) {
return new PromiseArrayConstructor(list, boundTo);
}
return {
promise: function() {return apiRejection("expecting an array, a promise or a thenable");}
};
}
var old = global.Promise;
Promise.noConflict = function() {
if (global.Promise === Promise) {
global.Promise = old;
}
return Promise;
};
if (!CapturedTrace.isSupported()) {
Promise.longStackTraces = function(){};
debugging = false;
}
Promise._makeSelfResolutionError = makeSelfResolutionError;
_dereq_("./finally.js")(Promise, NEXT_FILTER);
_dereq_("./direct_resolve.js")(Promise);
_dereq_("./thenables.js")(Promise, INTERNAL);
_dereq_("./synchronous_inspection.js")(Promise);
Promise.RangeError = RangeError;
Promise.CancellationError = CancellationError;
Promise.TimeoutError = TimeoutError;
Promise.TypeError = TypeError;
Promise.RejectionError = RejectionError;
util.toFastProperties(Promise);
util.toFastProperties(Promise.prototype);
_dereq_('./timers.js')(Promise,INTERNAL);
_dereq_('./any.js')(Promise,Promise$_CreatePromiseArray,PromiseArray);
_dereq_('./race.js')(Promise,INTERNAL);
_dereq_('./call_get.js')(Promise);
_dereq_('./filter.js')(Promise,Promise$_CreatePromiseArray,PromiseArray,apiRejection);
_dereq_('./generators.js')(Promise,apiRejection,INTERNAL);
_dereq_('./map.js')(Promise,PromiseArray,INTERNAL,apiRejection);
_dereq_('./nodeify.js')(Promise);
_dereq_('./promisify.js')(Promise,INTERNAL);
_dereq_('./props.js')(Promise,PromiseArray);
_dereq_('./reduce.js')(Promise,Promise$_CreatePromiseArray,PromiseArray,apiRejection,INTERNAL);
_dereq_('./settle.js')(Promise,Promise$_CreatePromiseArray,PromiseArray);
_dereq_('./some.js')(Promise,Promise$_CreatePromiseArray,PromiseArray,apiRejection);
_dereq_('./progress.js')(Promise,isPromiseArrayProxy);
_dereq_('./cancel.js')(Promise,INTERNAL);
Promise.prototype = Promise.prototype;
return Promise;
};
}).call(this,_dereq_("C:\\Users\\Alex\\AppData\\Roaming\\npm\\node_modules\\browserify\\node_modules\\insert-module-globals\\node_modules\\process\\browser.js"))
},{"./any.js":72,"./async.js":73,"./call_get.js":75,"./cancel.js":76,"./captured_trace.js":77,"./catch_filter.js":78,"./direct_resolve.js":79,"./errors.js":80,"./errors_api_rejection":81,"./filter.js":83,"./finally.js":84,"./generators.js":85,"./global.js":86,"./map.js":87,"./nodeify.js":88,"./progress.js":89,"./promise_array.js":91,"./promise_resolver.js":92,"./promisify.js":94,"./props.js":96,"./race.js":98,"./reduce.js":99,"./settle.js":101,"./some.js":103,"./synchronous_inspection.js":105,"./thenables.js":106,"./timers.js":107,"./util.js":108,"C:\\Users\\Alex\\AppData\\Roaming\\npm\\node_modules\\browserify\\node_modules\\insert-module-globals\\node_modules\\process\\browser.js":144}],91:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports = function(Promise, INTERNAL) {
var canAttach = _dereq_("./errors.js").canAttach;
var util = _dereq_("./util.js");
var async = _dereq_("./async.js");
var hasOwn = {}.hasOwnProperty;
var isArray = util.isArray;
function toResolutionValue(val) {
switch(val) {
case -1: return void 0;
case -2: return [];
case -3: return {};
}
}
function PromiseArray(values, boundTo) {
var promise = this._promise = new Promise(INTERNAL);
var parent = void 0;
if (values instanceof Promise) {
parent = values;
if (values._cancellable()) {
promise._setCancellable();
promise._cancellationParent = values;
}
if (values._isBound()) {
promise._setBoundTo(boundTo);
}
}
promise._setTrace(parent);
this._values = values;
this._length = 0;
this._totalResolved = 0;
this._init(void 0, -2);
}
PromiseArray.PropertiesPromiseArray = function() {};
PromiseArray.prototype.length = function PromiseArray$length() {
return this._length;
};
PromiseArray.prototype.promise = function PromiseArray$promise() {
return this._promise;
};
PromiseArray.prototype._init =
function PromiseArray$_init(_, resolveValueIfEmpty) {
var values = this._values;
if (values instanceof Promise) {
if (values.isFulfilled()) {
values = values._settledValue;
if (!isArray(values)) {
var err = new Promise.TypeError("expecting an array, a promise or a thenable");
this.__hardReject__(err);
return;
}
this._values = values;
}
else if (values.isPending()) {
values._then(
this._init,
this._reject,
void 0,
this,
resolveValueIfEmpty
);
return;
}
else {
values._unsetRejectionIsUnhandled();
this._reject(values._settledValue);
return;
}
}
if (values.length === 0) {
this._resolve(toResolutionValue(resolveValueIfEmpty));
return;
}
var len = values.length;
var newLen = len;
var newValues;
if (this instanceof PromiseArray.PropertiesPromiseArray) {
newValues = this._values;
}
else {
newValues = new Array(len);
}
var isDirectScanNeeded = false;
for (var i = 0; i < len; ++i) {
var promise = values[i];
if (promise === void 0 && !hasOwn.call(values, i)) {
newLen--;
continue;
}
var maybePromise = Promise._cast(promise, void 0);
if (maybePromise instanceof Promise) {
if (maybePromise.isPending()) {
maybePromise._proxyPromiseArray(this, i);
}
else {
maybePromise._unsetRejectionIsUnhandled();
isDirectScanNeeded = true;
}
}
else {
isDirectScanNeeded = true;
}
newValues[i] = maybePromise;
}
if (newLen === 0) {
if (resolveValueIfEmpty === -2) {
this._resolve(newValues);
}
else {
this._resolve(toResolutionValue(resolveValueIfEmpty));
}
return;
}
this._values = newValues;
this._length = newLen;
if (isDirectScanNeeded) {
var scanMethod = newLen === len
? this._scanDirectValues
: this._scanDirectValuesHoled;
async.invoke(scanMethod, this, len);
}
};
PromiseArray.prototype._settlePromiseAt =
function PromiseArray$_settlePromiseAt(index) {
var value = this._values[index];
if (!(value instanceof Promise)) {
this._promiseFulfilled(value, index);
}
else if (value.isFulfilled()) {
this._promiseFulfilled(value._settledValue, index);
}
else if (value.isRejected()) {
this._promiseRejected(value._settledValue, index);
}
};
PromiseArray.prototype._scanDirectValuesHoled =
function PromiseArray$_scanDirectValuesHoled(len) {
for (var i = 0; i < len; ++i) {
if (this._isResolved()) {
break;
}
if (hasOwn.call(this._values, i)) {
this._settlePromiseAt(i);
}
}
};
PromiseArray.prototype._scanDirectValues =
function PromiseArray$_scanDirectValues(len) {
for (var i = 0; i < len; ++i) {
if (this._isResolved()) {
break;
}
this._settlePromiseAt(i);
}
};
PromiseArray.prototype._isResolved = function PromiseArray$_isResolved() {
return this._values === null;
};
PromiseArray.prototype._resolve = function PromiseArray$_resolve(value) {
this._values = null;
this._promise._fulfill(value);
};
PromiseArray.prototype.__hardReject__ =
PromiseArray.prototype._reject = function PromiseArray$_reject(reason) {
this._values = null;
var trace = canAttach(reason) ? reason : new Error(reason + "");
this._promise._attachExtraTrace(trace);
this._promise._reject(reason, trace);
};
PromiseArray.prototype._promiseProgressed =
function PromiseArray$_promiseProgressed(progressValue, index) {
if (this._isResolved()) return;
this._promise._progress({
index: index,
value: progressValue
});
};
PromiseArray.prototype._promiseFulfilled =
function PromiseArray$_promiseFulfilled(value, index) {
if (this._isResolved()) return;
this._values[index] = value;
var totalResolved = ++this._totalResolved;
if (totalResolved >= this._length) {
this._resolve(this._values);
}
};
PromiseArray.prototype._promiseRejected =
function PromiseArray$_promiseRejected(reason, index) {
if (this._isResolved()) return;
this._totalResolved++;
this._reject(reason);
};
return PromiseArray;
};
},{"./async.js":73,"./errors.js":80,"./util.js":108}],92:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
var util = _dereq_("./util.js");
var maybeWrapAsError = util.maybeWrapAsError;
var errors = _dereq_("./errors.js");
var TimeoutError = errors.TimeoutError;
var RejectionError = errors.RejectionError;
var async = _dereq_("./async.js");
var haveGetters = util.haveGetters;
var es5 = _dereq_("./es5.js");
function isUntypedError(obj) {
return obj instanceof Error &&
es5.getPrototypeOf(obj) === Error.prototype;
}
function wrapAsRejectionError(obj) {
var ret;
if (isUntypedError(obj)) {
ret = new RejectionError(obj);
}
else {
ret = obj;
}
errors.markAsOriginatingFromRejection(ret);
return ret;
}
function nodebackForPromise(promise) {
function PromiseResolver$_callback(err, value) {
if (promise === null) return;
if (err) {
var wrapped = wrapAsRejectionError(maybeWrapAsError(err));
promise._attachExtraTrace(wrapped);
promise._reject(wrapped);
}
else {
if (arguments.length > 2) {
var $_len = arguments.length;var args = new Array($_len - 1); for(var $_i = 1; $_i < $_len; ++$_i) {args[$_i - 1] = arguments[$_i];}
promise._fulfill(args);
}
else {
promise._fulfill(value);
}
}
promise = null;
}
return PromiseResolver$_callback;
}
var PromiseResolver;
if (!haveGetters) {
PromiseResolver = function PromiseResolver(promise) {
this.promise = promise;
this.asCallback = nodebackForPromise(promise);
this.callback = this.asCallback;
};
}
else {
PromiseResolver = function PromiseResolver(promise) {
this.promise = promise;
};
}
if (haveGetters) {
var prop = {
get: function() {
return nodebackForPromise(this.promise);
}
};
es5.defineProperty(PromiseResolver.prototype, "asCallback", prop);
es5.defineProperty(PromiseResolver.prototype, "callback", prop);
}
PromiseResolver._nodebackForPromise = nodebackForPromise;
PromiseResolver.prototype.toString = function PromiseResolver$toString() {
return "[object PromiseResolver]";
};
PromiseResolver.prototype.resolve =
PromiseResolver.prototype.fulfill = function PromiseResolver$resolve(value) {
var promise = this.promise;
if ((promise === void 0) || (promise._tryFollow === void 0)) {
throw new TypeError("Illegal invocation, resolver resolve/reject must be called within a resolver context. Consider using the promise constructor instead.");
}
if (promise._tryFollow(value)) {
return;
}
async.invoke(promise._fulfill, promise, value);
};
PromiseResolver.prototype.reject = function PromiseResolver$reject(reason) {
var promise = this.promise;
if ((promise === void 0) || (promise._attachExtraTrace === void 0)) {
throw new TypeError("Illegal invocation, resolver resolve/reject must be called within a resolver context. Consider using the promise constructor instead.");
}
errors.markAsOriginatingFromRejection(reason);
var trace = errors.canAttach(reason) ? reason : new Error(reason + "");
promise._attachExtraTrace(trace);
async.invoke(promise._reject, promise, reason);
if (trace !== reason) {
async.invoke(this._setCarriedStackTrace, this, trace);
}
};
PromiseResolver.prototype.progress =
function PromiseResolver$progress(value) {
async.invoke(this.promise._progress, this.promise, value);
};
PromiseResolver.prototype.cancel = function PromiseResolver$cancel() {
async.invoke(this.promise.cancel, this.promise, void 0);
};
PromiseResolver.prototype.timeout = function PromiseResolver$timeout() {
this.reject(new TimeoutError("timeout"));
};
PromiseResolver.prototype.isResolved = function PromiseResolver$isResolved() {
return this.promise.isResolved();
};
PromiseResolver.prototype.toJSON = function PromiseResolver$toJSON() {
return this.promise.toJSON();
};
PromiseResolver.prototype._setCarriedStackTrace =
function PromiseResolver$_setCarriedStackTrace(trace) {
if (this.promise.isRejected()) {
this.promise._setCarriedStackTrace(trace);
}
};
module.exports = PromiseResolver;
},{"./async.js":73,"./errors.js":80,"./es5.js":82,"./util.js":108}],93:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports = function(Promise, INTERNAL) {
var errors = _dereq_("./errors.js");
var TypeError = errors.TypeError;
var util = _dereq_("./util.js");
var isArray = util.isArray;
var errorObj = util.errorObj;
var tryCatch1 = util.tryCatch1;
var yieldHandlers = [];
function promiseFromYieldHandler(value) {
var _yieldHandlers = yieldHandlers;
var _errorObj = errorObj;
var _Promise = Promise;
var len = _yieldHandlers.length;
for (var i = 0; i < len; ++i) {
var result = tryCatch1(_yieldHandlers[i], void 0, value);
if (result === _errorObj) {
return _Promise.reject(_errorObj.e);
}
var maybePromise = _Promise._cast(result,
promiseFromYieldHandler, void 0);
if (maybePromise instanceof _Promise) return maybePromise;
}
return null;
}
function PromiseSpawn(generatorFunction, receiver) {
var promise = this._promise = new Promise(INTERNAL);
promise._setTrace(void 0);
this._generatorFunction = generatorFunction;
this._receiver = receiver;
this._generator = void 0;
}
PromiseSpawn.prototype.promise = function PromiseSpawn$promise() {
return this._promise;
};
PromiseSpawn.prototype._run = function PromiseSpawn$_run() {
this._generator = this._generatorFunction.call(this._receiver);
this._receiver =
this._generatorFunction = void 0;
this._next(void 0);
};
PromiseSpawn.prototype._continue = function PromiseSpawn$_continue(result) {
if (result === errorObj) {
this._generator = void 0;
var trace = errors.canAttach(result.e)
? result.e : new Error(result.e + "");
this._promise._attachExtraTrace(trace);
this._promise._reject(result.e, trace);
return;
}
var value = result.value;
if (result.done === true) {
this._generator = void 0;
if (!this._promise._tryFollow(value)) {
this._promise._fulfill(value);
}
}
else {
var maybePromise = Promise._cast(value, PromiseSpawn$_continue, void 0);
if (!(maybePromise instanceof Promise)) {
if (isArray(maybePromise)) {
maybePromise = Promise.all(maybePromise);
}
else {
maybePromise = promiseFromYieldHandler(maybePromise);
}
if (maybePromise === null) {
this._throw(new TypeError("A value was yielded that could not be treated as a promise"));
return;
}
}
maybePromise._then(
this._next,
this._throw,
void 0,
this,
null
);
}
};
PromiseSpawn.prototype._throw = function PromiseSpawn$_throw(reason) {
if (errors.canAttach(reason))
this._promise._attachExtraTrace(reason);
this._continue(
tryCatch1(this._generator["throw"], this._generator, reason)
);
};
PromiseSpawn.prototype._next = function PromiseSpawn$_next(value) {
this._continue(
tryCatch1(this._generator.next, this._generator, value)
);
};
PromiseSpawn.addYieldHandler = function PromiseSpawn$AddYieldHandler(fn) {
if (typeof fn !== "function") throw new TypeError("fn must be a function");
yieldHandlers.push(fn);
};
return PromiseSpawn;
};
},{"./errors.js":80,"./util.js":108}],94:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports = function(Promise, INTERNAL) {
var THIS = {};
var util = _dereq_("./util.js");
var es5 = _dereq_("./es5.js");
var nodebackForPromise = _dereq_("./promise_resolver.js")
._nodebackForPromise;
var withAppended = util.withAppended;
var maybeWrapAsError = util.maybeWrapAsError;
var canEvaluate = util.canEvaluate;
var deprecated = util.deprecated;
var TypeError = _dereq_("./errors").TypeError;
var rasyncSuffix = new RegExp("Async" + "$");
function isPromisified(fn) {
return fn.__isPromisified__ === true;
}
function hasPromisified(obj, key) {
var containsKey = ((key + "Async") in obj);
return containsKey ? isPromisified(obj[key + "Async"])
: false;
}
function checkValid(ret) {
for (var i = 0; i < ret.length; i += 2) {
var key = ret[i];
if (rasyncSuffix.test(key)) {
var keyWithoutAsyncSuffix = key.replace(rasyncSuffix, "");
for (var j = 0; j < ret.length; j += 2) {
if (ret[j] === keyWithoutAsyncSuffix) {
throw new TypeError("Cannot promisify an API " +
"that has normal methods with Async-suffix");
}
}
}
}
}
var inheritedMethods = (function() {
if (es5.isES5) {
var create = Object.create;
var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
return function(cur) {
var ret = [];
var visitedKeys = create(null);
var original = cur;
while (cur !== null) {
var keys = es5.keys(cur);
for (var i = 0, len = keys.length; i < len; ++i) {
var key = keys[i];
if (visitedKeys[key]) continue;
visitedKeys[key] = true;
var desc = getOwnPropertyDescriptor(cur, key);
if (desc != null &&
typeof desc.value === "function" &&
!isPromisified(desc.value) &&
!hasPromisified(original, key)) {
ret.push(key, desc.value);
}
}
cur = es5.getPrototypeOf(cur);
}
checkValid(ret);
return ret;
};
}
else {
return function(obj) {
var ret = [];
/*jshint forin:false */
for (var key in obj) {
var fn = obj[key];
if (typeof fn === "function" &&
!isPromisified(fn) &&
!hasPromisified(obj, key)) {
ret.push(key, fn);
}
}
checkValid(ret);
return ret;
};
}
})();
function switchCaseArgumentOrder(likelyArgumentCount) {
var ret = [likelyArgumentCount];
var min = Math.max(0, likelyArgumentCount - 1 - 5);
for(var i = likelyArgumentCount - 1; i >= min; --i) {
if (i === likelyArgumentCount) continue;
ret.push(i);
}
for(var i = likelyArgumentCount + 1; i <= 5; ++i) {
ret.push(i);
}
return ret;
}
function parameterDeclaration(parameterCount) {
var ret = new Array(parameterCount);
for(var i = 0; i < ret.length; ++i) {
ret[i] = "_arg" + i;
}
return ret.join(", ");
}
function parameterCount(fn) {
if (typeof fn.length === "number") {
return Math.max(Math.min(fn.length, 1023 + 1), 0);
}
return 0;
}
var rident = /^[a-z$_][a-z$_0-9]*$/i;
function propertyAccess(id) {
if (rident.test(id)) {
return "." + id;
}
else return "['" + id.replace(/(['\\])/g, "\\$1") + "']";
}
function makeNodePromisifiedEval(callback, receiver, originalName, fn) {
var newParameterCount = Math.max(0, parameterCount(fn) - 1);
var argumentOrder = switchCaseArgumentOrder(newParameterCount);
var callbackName = (typeof originalName === "string" ?
originalName + "Async" :
"promisified");
function generateCallForArgumentCount(count) {
var args = new Array(count);
for (var i = 0, len = args.length; i < len; ++i) {
args[i] = "arguments[" + i + "]";
}
var comma = count > 0 ? "," : "";
if (typeof callback === "string" &&
receiver === THIS) {
return "this" + propertyAccess(callback) + "("+args.join(",") +
comma +" fn);"+
"break;";
}
return (receiver === void 0
? "callback("+args.join(",")+ comma +" fn);"
: "callback.call("+(receiver === THIS
? "this"
: "receiver")+", "+args.join(",") + comma + " fn);") +
"break;";
}
if (!rident.test(callbackName)) {
callbackName = "promisified";
}
function generateArgumentSwitchCase() {
var ret = "";
for(var i = 0; i < argumentOrder.length; ++i) {
ret += "case " + argumentOrder[i] +":" +
generateCallForArgumentCount(argumentOrder[i]);
}
ret += "default: var args = new Array(len + 1);" +
"var i = 0;" +
"for (var i = 0; i < len; ++i) { " +
" args[i] = arguments[i];" +
"}" +
"args[i] = fn;" +
(typeof callback === "string"
? "this" + propertyAccess(callback) + ".apply("
: "callback.apply(") +
(receiver === THIS ? "this" : "receiver") +
", args); break;";
return ret;
}
return new Function("Promise", "callback", "receiver",
"withAppended", "maybeWrapAsError", "nodebackForPromise",
"INTERNAL",
"var ret = function " + callbackName +
"(" + parameterDeclaration(newParameterCount) + ") {\"use strict\";" +
"var len = arguments.length;" +
"var promise = new Promise(INTERNAL);"+
"promise._setTrace(void 0);" +
"var fn = nodebackForPromise(promise);"+
"try {" +
"switch(len) {" +
generateArgumentSwitchCase() +
"}" +
"}" +
"catch(e){ " +
"var wrapped = maybeWrapAsError(e);" +
"promise._attachExtraTrace(wrapped);" +
"promise._reject(wrapped);" +
"}" +
"return promise;" +
"" +
"}; ret.__isPromisified__ = true; return ret;"
)(Promise, callback, receiver, withAppended,
maybeWrapAsError, nodebackForPromise, INTERNAL);
}
function makeNodePromisifiedClosure(callback, receiver) {
function promisified() {
var _receiver = receiver;
if (receiver === THIS) _receiver = this;
if (typeof callback === "string") {
callback = _receiver[callback];
}
var promise = new Promise(INTERNAL);
promise._setTrace(void 0);
var fn = nodebackForPromise(promise);
try {
callback.apply(_receiver, withAppended(arguments, fn));
}
catch(e) {
var wrapped = maybeWrapAsError(e);
promise._attachExtraTrace(wrapped);
promise._reject(wrapped);
}
return promise;
}
promisified.__isPromisified__ = true;
return promisified;
}
var makeNodePromisified = canEvaluate
? makeNodePromisifiedEval
: makeNodePromisifiedClosure;
function _promisify(callback, receiver, isAll) {
if (isAll) {
var methods = inheritedMethods(callback);
for (var i = 0, len = methods.length; i < len; i+= 2) {
var key = methods[i];
var fn = methods[i+1];
var promisifiedKey = key + "Async";
callback[promisifiedKey] = makeNodePromisified(key, THIS, key, fn);
}
util.toFastProperties(callback);
return callback;
}
else {
return makeNodePromisified(callback, receiver, void 0, callback);
}
}
Promise.promisify = function Promise$Promisify(fn, receiver) {
if (typeof fn === "object" && fn !== null) {
deprecated("Promise.promisify for promisifying entire objects is deprecated. Use Promise.promisifyAll instead.");
return _promisify(fn, receiver, true);
}
if (typeof fn !== "function") {
throw new TypeError("fn must be a function");
}
if (isPromisified(fn)) {
return fn;
}
return _promisify(
fn,
arguments.length < 2 ? THIS : receiver,
false);
};
Promise.promisifyAll = function Promise$PromisifyAll(target) {
if (typeof target !== "function" && typeof target !== "object") {
throw new TypeError("the target of promisifyAll must be an object or a function");
}
return _promisify(target, void 0, true);
};
};
},{"./errors":80,"./es5.js":82,"./promise_resolver.js":92,"./util.js":108}],95:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports = function(Promise, PromiseArray) {
var util = _dereq_("./util.js");
var inherits = util.inherits;
var es5 = _dereq_("./es5.js");
function PropertiesPromiseArray(obj, boundTo) {
var keys = es5.keys(obj);
var values = new Array(keys.length);
for (var i = 0, len = values.length; i < len; ++i) {
values[i] = obj[keys[i]];
}
this.constructor$(values, boundTo);
if (!this._isResolved()) {
for (var i = 0, len = keys.length; i < len; ++i) {
values.push(keys[i]);
}
}
}
inherits(PropertiesPromiseArray, PromiseArray);
PropertiesPromiseArray.prototype._init =
function PropertiesPromiseArray$_init() {
this._init$(void 0, -3) ;
};
PropertiesPromiseArray.prototype._promiseFulfilled =
function PropertiesPromiseArray$_promiseFulfilled(value, index) {
if (this._isResolved()) return;
this._values[index] = value;
var totalResolved = ++this._totalResolved;
if (totalResolved >= this._length) {
var val = {};
var keyOffset = this.length();
for (var i = 0, len = this.length(); i < len; ++i) {
val[this._values[i + keyOffset]] = this._values[i];
}
this._resolve(val);
}
};
PropertiesPromiseArray.prototype._promiseProgressed =
function PropertiesPromiseArray$_promiseProgressed(value, index) {
if (this._isResolved()) return;
this._promise._progress({
key: this._values[index + this.length()],
value: value
});
};
PromiseArray.PropertiesPromiseArray = PropertiesPromiseArray;
return PropertiesPromiseArray;
};
},{"./es5.js":82,"./util.js":108}],96:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports = function(Promise, PromiseArray) {
var PropertiesPromiseArray = _dereq_("./properties_promise_array.js")(
Promise, PromiseArray);
var util = _dereq_("./util.js");
var apiRejection = _dereq_("./errors_api_rejection")(Promise);
var isObject = util.isObject;
function Promise$_Props(promises, useBound) {
var ret;
var castValue = Promise._cast(promises, void 0);
if (!isObject(castValue)) {
return apiRejection("cannot await properties of a non-object");
}
else if (castValue instanceof Promise) {
ret = castValue._then(Promise.props, void 0, void 0,
void 0, void 0);
}
else {
ret = new PropertiesPromiseArray(
castValue,
useBound === true && castValue._isBound()
? castValue._boundTo
: void 0
).promise();
useBound = false;
}
if (useBound === true && castValue._isBound()) {
ret._setBoundTo(castValue._boundTo);
}
return ret;
}
Promise.prototype.props = function Promise$props() {
return Promise$_Props(this, true);
};
Promise.props = function Promise$Props(promises) {
return Promise$_Props(promises, false);
};
};
},{"./errors_api_rejection":81,"./properties_promise_array.js":95,"./util.js":108}],97:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
function arrayCopy(src, srcIndex, dst, dstIndex, len) {
for (var j = 0; j < len; ++j) {
dst[j + dstIndex] = src[j + srcIndex];
}
}
function pow2AtLeast(n) {
n = n >>> 0;
n = n - 1;
n = n | (n >> 1);
n = n | (n >> 2);
n = n | (n >> 4);
n = n | (n >> 8);
n = n | (n >> 16);
return n + 1;
}
function getCapacity(capacity) {
if (typeof capacity !== "number") return 16;
return pow2AtLeast(
Math.min(
Math.max(16, capacity), 1073741824)
);
}
function Queue(capacity) {
this._capacity = getCapacity(capacity);
this._length = 0;
this._front = 0;
this._makeCapacity();
}
Queue.prototype._willBeOverCapacity =
function Queue$_willBeOverCapacity(size) {
return this._capacity < size;
};
Queue.prototype._pushOne = function Queue$_pushOne(arg) {
var length = this.length();
this._checkCapacity(length + 1);
var i = (this._front + length) & (this._capacity - 1);
this[i] = arg;
this._length = length + 1;
};
Queue.prototype.push = function Queue$push(fn, receiver, arg) {
var length = this.length() + 3;
if (this._willBeOverCapacity(length)) {
this._pushOne(fn);
this._pushOne(receiver);
this._pushOne(arg);
return;
}
var j = this._front + length - 3;
this._checkCapacity(length);
var wrapMask = this._capacity - 1;
this[(j + 0) & wrapMask] = fn;
this[(j + 1) & wrapMask] = receiver;
this[(j + 2) & wrapMask] = arg;
this._length = length;
};
Queue.prototype.shift = function Queue$shift() {
var front = this._front,
ret = this[front];
this[front] = void 0;
this._front = (front + 1) & (this._capacity - 1);
this._length--;
return ret;
};
Queue.prototype.length = function Queue$length() {
return this._length;
};
Queue.prototype._makeCapacity = function Queue$_makeCapacity() {
var len = this._capacity;
for (var i = 0; i < len; ++i) {
this[i] = void 0;
}
};
Queue.prototype._checkCapacity = function Queue$_checkCapacity(size) {
if (this._capacity < size) {
this._resizeTo(this._capacity << 3);
}
};
Queue.prototype._resizeTo = function Queue$_resizeTo(capacity) {
var oldFront = this._front;
var oldCapacity = this._capacity;
var oldQueue = new Array(oldCapacity);
var length = this.length();
arrayCopy(this, 0, oldQueue, 0, oldCapacity);
this._capacity = capacity;
this._makeCapacity();
this._front = 0;
if (oldFront + length <= oldCapacity) {
arrayCopy(oldQueue, oldFront, this, 0, length);
}
else { var lengthBeforeWrapping =
length - ((oldFront + length) & (oldCapacity - 1));
arrayCopy(oldQueue, oldFront, this, 0, lengthBeforeWrapping);
arrayCopy(oldQueue, 0, this, lengthBeforeWrapping,
length - lengthBeforeWrapping);
}
};
module.exports = Queue;
},{}],98:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports = function(Promise, INTERNAL) {
var apiRejection = _dereq_("./errors_api_rejection.js")(Promise);
var isArray = _dereq_("./util.js").isArray;
var raceLater = function Promise$_raceLater(promise) {
return promise.then(function(array) {
return Promise$_Race(array, promise);
});
};
var hasOwn = {}.hasOwnProperty;
function Promise$_Race(promises, parent) {
var maybePromise = Promise._cast(promises, void 0);
if (maybePromise instanceof Promise) {
return raceLater(maybePromise);
}
else if (!isArray(promises)) {
return apiRejection("expecting an array, a promise or a thenable");
}
var ret = new Promise(INTERNAL);
ret._setTrace(parent);
if (parent !== void 0) {
if (parent._isBound()) {
ret._setBoundTo(parent._boundTo);
}
if (parent._cancellable()) {
ret._setCancellable();
ret._cancellationParent = parent;
}
}
var fulfill = ret._fulfill;
var reject = ret._reject;
for (var i = 0, len = promises.length; i < len; ++i) {
var val = promises[i];
if (val === void 0 && !(hasOwn.call(promises, i))) {
continue;
}
Promise.cast(val)._then(
fulfill,
reject,
void 0,
ret,
null
);
}
return ret;
}
Promise.race = function Promise$Race(promises) {
return Promise$_Race(promises, void 0);
};
Promise.prototype.race = function Promise$race() {
return Promise$_Race(this, void 0);
};
};
},{"./errors_api_rejection.js":81,"./util.js":108}],99:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports = function(
Promise, Promise$_CreatePromiseArray,
PromiseArray, apiRejection, INTERNAL) {
function Reduction(callback, index, accum, items, receiver) {
this.promise = new Promise(INTERNAL);
this.index = index;
this.length = items.length;
this.items = items;
this.callback = callback;
this.receiver = receiver;
this.accum = accum;
}
Reduction.prototype.reject = function Reduction$reject(e) {
this.promise._reject(e);
};
Reduction.prototype.fulfill = function Reduction$fulfill(value, index) {
this.accum = value;
this.index = index + 1;
this.iterate();
};
Reduction.prototype.iterate = function Reduction$iterate() {
var i = this.index;
var len = this.length;
var items = this.items;
var result = this.accum;
var receiver = this.receiver;
var callback = this.callback;
for (; i < len; ++i) {
result = callback.call(receiver, result, items[i], i, len);
result = Promise._cast(result, void 0);
if (result instanceof Promise) {
result._then(
this.fulfill, this.reject, void 0, this, i);
return;
}
}
this.promise._fulfill(result);
};
function Promise$_reducer(fulfilleds, initialValue) {
var fn = this;
var receiver = void 0;
if (typeof fn !== "function") {
receiver = fn.receiver;
fn = fn.fn;
}
var len = fulfilleds.length;
var accum = void 0;
var startIndex = 0;
if (initialValue !== void 0) {
accum = initialValue;
startIndex = 0;
}
else {
startIndex = 1;
if (len > 0) accum = fulfilleds[0];
}
var i = startIndex;
if (i >= len) {
return accum;
}
var reduction = new Reduction(fn, i, accum, fulfilleds, receiver);
reduction.iterate();
return reduction.promise;
}
function Promise$_unpackReducer(fulfilleds) {
var fn = this.fn;
var initialValue = this.initialValue;
return Promise$_reducer.call(fn, fulfilleds, initialValue);
}
function Promise$_slowReduce(
promises, fn, initialValue, useBound) {
return initialValue._then(function(initialValue) {
return Promise$_Reduce(
promises, fn, initialValue, useBound);
}, void 0, void 0, void 0, void 0);
}
function Promise$_Reduce(promises, fn, initialValue, useBound) {
if (typeof fn !== "function") {
return apiRejection("fn must be a function");
}
if (useBound === true && promises._isBound()) {
fn = {
fn: fn,
receiver: promises._boundTo
};
}
if (initialValue !== void 0) {
if (initialValue instanceof Promise) {
if (initialValue.isFulfilled()) {
initialValue = initialValue._settledValue;
}
else {
return Promise$_slowReduce(promises,
fn, initialValue, useBound);
}
}
return Promise$_CreatePromiseArray(promises, PromiseArray,
useBound === true && promises._isBound()
? promises._boundTo
: void 0)
.promise()
._then(Promise$_unpackReducer, void 0, void 0, {
fn: fn,
initialValue: initialValue
}, void 0);
}
return Promise$_CreatePromiseArray(promises, PromiseArray,
useBound === true && promises._isBound()
? promises._boundTo
: void 0).promise()
._then(Promise$_reducer, void 0, void 0, fn, void 0);
}
Promise.reduce = function Promise$Reduce(promises, fn, initialValue) {
return Promise$_Reduce(promises, fn, initialValue, false);
};
Promise.prototype.reduce = function Promise$reduce(fn, initialValue) {
return Promise$_Reduce(this, fn, initialValue, true);
};
};
},{}],100:[function(_dereq_,module,exports){
(function (process){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
var global = _dereq_("./global.js");
var schedule;
if (typeof process !== "undefined" && process !== null &&
typeof process.cwd === "function" &&
typeof process.nextTick === "function" &&
typeof process.version === "string") {
schedule = function Promise$_Scheduler(fn) {
process.nextTick(fn);
};
}
else if ((typeof global.MutationObserver === "function" ||
typeof global.WebkitMutationObserver === "function" ||
typeof global.WebKitMutationObserver === "function") &&
typeof document !== "undefined" &&
typeof document.createElement === "function") {
schedule = (function(){
var MutationObserver = global.MutationObserver ||
global.WebkitMutationObserver ||
global.WebKitMutationObserver;
var div = document.createElement("div");
var queuedFn = void 0;
var observer = new MutationObserver(
function Promise$_Scheduler() {
var fn = queuedFn;
queuedFn = void 0;
fn();
}
);
observer.observe(div, {
attributes: true
});
return function Promise$_Scheduler(fn) {
queuedFn = fn;
div.setAttribute("class", "foo");
};
})();
}
else if (typeof global.postMessage === "function" &&
typeof global.importScripts !== "function" &&
typeof global.addEventListener === "function" &&
typeof global.removeEventListener === "function") {
var MESSAGE_KEY = "bluebird_message_key_" + Math.random();
schedule = (function(){
var queuedFn = void 0;
function Promise$_Scheduler(e) {
if (e.source === global &&
e.data === MESSAGE_KEY) {
var fn = queuedFn;
queuedFn = void 0;
fn();
}
}
global.addEventListener("message", Promise$_Scheduler, false);
return function Promise$_Scheduler(fn) {
queuedFn = fn;
global.postMessage(
MESSAGE_KEY, "*"
);
};
})();
}
else if (typeof global.MessageChannel === "function") {
schedule = (function(){
var queuedFn = void 0;
var channel = new global.MessageChannel();
channel.port1.onmessage = function Promise$_Scheduler() {
var fn = queuedFn;
queuedFn = void 0;
fn();
};
return function Promise$_Scheduler(fn) {
queuedFn = fn;
channel.port2.postMessage(null);
};
})();
}
else if (global.setTimeout) {
schedule = function Promise$_Scheduler(fn) {
setTimeout(fn, 4);
};
}
else {
schedule = function Promise$_Scheduler(fn) {
fn();
};
}
module.exports = schedule;
}).call(this,_dereq_("C:\\Users\\Alex\\AppData\\Roaming\\npm\\node_modules\\browserify\\node_modules\\insert-module-globals\\node_modules\\process\\browser.js"))
},{"./global.js":86,"C:\\Users\\Alex\\AppData\\Roaming\\npm\\node_modules\\browserify\\node_modules\\insert-module-globals\\node_modules\\process\\browser.js":144}],101:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports =
function(Promise, Promise$_CreatePromiseArray, PromiseArray) {
var SettledPromiseArray = _dereq_("./settled_promise_array.js")(
Promise, PromiseArray);
function Promise$_Settle(promises, useBound) {
return Promise$_CreatePromiseArray(
promises,
SettledPromiseArray,
useBound === true && promises._isBound()
? promises._boundTo
: void 0
).promise();
}
Promise.settle = function Promise$Settle(promises) {
return Promise$_Settle(promises, false);
};
Promise.prototype.settle = function Promise$settle() {
return Promise$_Settle(this, true);
};
};
},{"./settled_promise_array.js":102}],102:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports = function(Promise, PromiseArray) {
var PromiseInspection = Promise.PromiseInspection;
var util = _dereq_("./util.js");
var inherits = util.inherits;
function SettledPromiseArray(values, boundTo) {
this.constructor$(values, boundTo);
}
inherits(SettledPromiseArray, PromiseArray);
SettledPromiseArray.prototype._promiseResolved =
function SettledPromiseArray$_promiseResolved(index, inspection) {
this._values[index] = inspection;
var totalResolved = ++this._totalResolved;
if (totalResolved >= this._length) {
this._resolve(this._values);
}
};
SettledPromiseArray.prototype._promiseFulfilled =
function SettledPromiseArray$_promiseFulfilled(value, index) {
if (this._isResolved()) return;
var ret = new PromiseInspection();
ret._bitField = 268435456;
ret._settledValue = value;
this._promiseResolved(index, ret);
};
SettledPromiseArray.prototype._promiseRejected =
function SettledPromiseArray$_promiseRejected(reason, index) {
if (this._isResolved()) return;
var ret = new PromiseInspection();
ret._bitField = 134217728;
ret._settledValue = reason;
this._promiseResolved(index, ret);
};
return SettledPromiseArray;
};
},{"./util.js":108}],103:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports =
function(Promise, Promise$_CreatePromiseArray, PromiseArray, apiRejection) {
var SomePromiseArray = _dereq_("./some_promise_array.js")(PromiseArray);
function Promise$_Some(promises, howMany, useBound) {
if ((howMany | 0) !== howMany || howMany < 0) {
return apiRejection("expecting a positive integer");
}
var ret = Promise$_CreatePromiseArray(
promises,
SomePromiseArray,
useBound === true && promises._isBound()
? promises._boundTo
: void 0
);
var promise = ret.promise();
if (promise.isRejected()) {
return promise;
}
ret.setHowMany(howMany);
ret.init();
return promise;
}
Promise.some = function Promise$Some(promises, howMany) {
return Promise$_Some(promises, howMany, false);
};
Promise.prototype.some = function Promise$some(count) {
return Promise$_Some(this, count, true);
};
};
},{"./some_promise_array.js":104}],104:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports = function (PromiseArray) {
var util = _dereq_("./util.js");
var RangeError = _dereq_("./errors.js").RangeError;
var inherits = util.inherits;
var isArray = util.isArray;
function SomePromiseArray(values, boundTo) {
this.constructor$(values, boundTo);
this._howMany = 0;
this._unwrap = false;
this._initialized = false;
}
inherits(SomePromiseArray, PromiseArray);
SomePromiseArray.prototype._init = function SomePromiseArray$_init() {
if (!this._initialized) {
return;
}
if (this._howMany === 0) {
this._resolve([]);
return;
}
this._init$(void 0, -2);
var isArrayResolved = isArray(this._values);
this._holes = isArrayResolved ? this._values.length - this.length() : 0;
if (!this._isResolved() &&
isArrayResolved &&
this._howMany > this._canPossiblyFulfill()) {
var message = "(Promise.some) input array contains less than " +
this._howMany + " promises";
this._reject(new RangeError(message));
}
};
SomePromiseArray.prototype.init = function SomePromiseArray$init() {
this._initialized = true;
this._init();
};
SomePromiseArray.prototype.setUnwrap = function SomePromiseArray$setUnwrap() {
this._unwrap = true;
};
SomePromiseArray.prototype.howMany = function SomePromiseArray$howMany() {
return this._howMany;
};
SomePromiseArray.prototype.setHowMany =
function SomePromiseArray$setHowMany(count) {
if (this._isResolved()) return;
this._howMany = count;
};
SomePromiseArray.prototype._promiseFulfilled =
function SomePromiseArray$_promiseFulfilled(value) {
if (this._isResolved()) return;
this._addFulfilled(value);
if (this._fulfilled() === this.howMany()) {
this._values.length = this.howMany();
if (this.howMany() === 1 && this._unwrap) {
this._resolve(this._values[0]);
}
else {
this._resolve(this._values);
}
}
};
SomePromiseArray.prototype._promiseRejected =
function SomePromiseArray$_promiseRejected(reason) {
if (this._isResolved()) return;
this._addRejected(reason);
if (this.howMany() > this._canPossiblyFulfill()) {
if (this._values.length === this.length()) {
this._reject([]);
}
else {
this._reject(this._values.slice(this.length() + this._holes));
}
}
};
SomePromiseArray.prototype._fulfilled = function SomePromiseArray$_fulfilled() {
return this._totalResolved;
};
SomePromiseArray.prototype._rejected = function SomePromiseArray$_rejected() {
return this._values.length - this.length() - this._holes;
};
SomePromiseArray.prototype._addRejected =
function SomePromiseArray$_addRejected(reason) {
this._values.push(reason);
};
SomePromiseArray.prototype._addFulfilled =
function SomePromiseArray$_addFulfilled(value) {
this._values[this._totalResolved++] = value;
};
SomePromiseArray.prototype._canPossiblyFulfill =
function SomePromiseArray$_canPossiblyFulfill() {
return this.length() - this._rejected();
};
return SomePromiseArray;
};
},{"./errors.js":80,"./util.js":108}],105:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports = function(Promise) {
function PromiseInspection(promise) {
if (promise !== void 0) {
this._bitField = promise._bitField;
this._settledValue = promise.isResolved()
? promise._settledValue
: void 0;
}
else {
this._bitField = 0;
this._settledValue = void 0;
}
}
PromiseInspection.prototype.isFulfilled =
Promise.prototype.isFulfilled = function Promise$isFulfilled() {
return (this._bitField & 268435456) > 0;
};
PromiseInspection.prototype.isRejected =
Promise.prototype.isRejected = function Promise$isRejected() {
return (this._bitField & 134217728) > 0;
};
PromiseInspection.prototype.isPending =
Promise.prototype.isPending = function Promise$isPending() {
return (this._bitField & 402653184) === 0;
};
PromiseInspection.prototype.value =
Promise.prototype.value = function Promise$value() {
if (!this.isFulfilled()) {
throw new TypeError("cannot get fulfillment value of a non-fulfilled promise");
}
return this._settledValue;
};
PromiseInspection.prototype.error =
Promise.prototype.reason = function Promise$reason() {
if (!this.isRejected()) {
throw new TypeError("cannot get rejection reason of a non-rejected promise");
}
return this._settledValue;
};
PromiseInspection.prototype.isResolved =
Promise.prototype.isResolved = function Promise$isResolved() {
return (this._bitField & 402653184) > 0;
};
Promise.prototype.inspect = function Promise$inspect() {
return new PromiseInspection(this);
};
Promise.PromiseInspection = PromiseInspection;
};
},{}],106:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
module.exports = function(Promise, INTERNAL) {
var util = _dereq_("./util.js");
var canAttach = _dereq_("./errors.js").canAttach;
var errorObj = util.errorObj;
var isObject = util.isObject;
function getThen(obj) {
try {
return obj.then;
}
catch(e) {
errorObj.e = e;
return errorObj;
}
}
function Promise$_Cast(obj, originalPromise) {
if (isObject(obj)) {
if (obj instanceof Promise) {
return obj;
}
else if (isAnyBluebirdPromise(obj)) {
var ret = new Promise(INTERNAL);
ret._setTrace(void 0);
obj._then(
ret._fulfillUnchecked,
ret._rejectUncheckedCheckError,
ret._progressUnchecked,
ret,
null
);
ret._setFollowing();
return ret;
}
var then = getThen(obj);
if (then === errorObj) {
if (originalPromise !== void 0 && canAttach(then.e)) {
originalPromise._attachExtraTrace(then.e);
}
return Promise.reject(then.e);
}
else if (typeof then === "function") {
return Promise$_doThenable(obj, then, originalPromise);
}
}
return obj;
}
var hasProp = {}.hasOwnProperty;
function isAnyBluebirdPromise(obj) {
return hasProp.call(obj, "_promise0");
}
function Promise$_doThenable(x, then, originalPromise) {
var resolver = Promise.defer();
var called = false;
try {
then.call(
x,
Promise$_resolveFromThenable,
Promise$_rejectFromThenable,
Promise$_progressFromThenable
);
}
catch(e) {
if (!called) {
called = true;
var trace = canAttach(e) ? e : new Error(e + "");
if (originalPromise !== void 0) {
originalPromise._attachExtraTrace(trace);
}
resolver.promise._reject(e, trace);
}
}
return resolver.promise;
function Promise$_resolveFromThenable(y) {
if (called) return;
called = true;
if (x === y) {
var e = Promise._makeSelfResolutionError();
if (originalPromise !== void 0) {
originalPromise._attachExtraTrace(e);
}
resolver.promise._reject(e, void 0);
return;
}
resolver.resolve(y);
}
function Promise$_rejectFromThenable(r) {
if (called) return;
called = true;
var trace = canAttach(r) ? r : new Error(r + "");
if (originalPromise !== void 0) {
originalPromise._attachExtraTrace(trace);
}
resolver.promise._reject(r, trace);
}
function Promise$_progressFromThenable(v) {
if (called) return;
var promise = resolver.promise;
if (typeof promise._progress === "function") {
promise._progress(v);
}
}
}
Promise._cast = Promise$_Cast;
};
},{"./errors.js":80,"./util.js":108}],107:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
var global = _dereq_("./global.js");
var setTimeout = function(fn, ms) {
var $_len = arguments.length;var args = new Array($_len - 2); for(var $_i = 2; $_i < $_len; ++$_i) {args[$_i - 2] = arguments[$_i];}
global.setTimeout(function(){
fn.apply(void 0, args);
}, ms);
};
module.exports = function(Promise, INTERNAL) {
var util = _dereq_("./util.js");
var errors = _dereq_("./errors.js");
var apiRejection = _dereq_("./errors_api_rejection")(Promise);
var TimeoutError = Promise.TimeoutError;
var afterTimeout = function Promise$_afterTimeout(promise, message, ms) {
if (!promise.isPending()) return;
if (typeof message !== "string") {
message = "operation timed out after" + " " + ms + " ms"
}
var err = new TimeoutError(message);
errors.markAsOriginatingFromRejection(err);
promise._attachExtraTrace(err);
promise._rejectUnchecked(err);
};
var afterDelay = function Promise$_afterDelay(value, promise) {
promise._fulfill(value);
};
var delay = Promise.delay = function Promise$Delay(value, ms) {
if (ms === void 0) {
ms = value;
value = void 0;
}
ms = +ms;
var maybePromise = Promise._cast(value, void 0);
var promise = new Promise(INTERNAL);
if (maybePromise instanceof Promise) {
if (maybePromise._isBound()) {
promise._setBoundTo(maybePromise._boundTo);
}
if (maybePromise._cancellable()) {
promise._setCancellable();
promise._cancellationParent = maybePromise;
}
promise._setTrace(maybePromise);
promise._follow(maybePromise);
return promise.then(function(value) {
return Promise.delay(value, ms);
});
}
else {
promise._setTrace(void 0);
setTimeout(afterDelay, ms, value, promise);
}
return promise;
};
Promise.prototype.delay = function Promise$delay(ms) {
return delay(this, ms);
};
Promise.prototype.timeout = function Promise$timeout(ms, message) {
ms = +ms;
var ret = new Promise(INTERNAL);
ret._setTrace(this);
if (this._isBound()) ret._setBoundTo(this._boundTo);
if (this._cancellable()) {
ret._setCancellable();
ret._cancellationParent = this;
}
ret._follow(this);
setTimeout(afterTimeout, ms, ret, message, ms);
return ret;
};
};
},{"./errors.js":80,"./errors_api_rejection":81,"./global.js":86,"./util.js":108}],108:[function(_dereq_,module,exports){
/**
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
"use strict";
var global = _dereq_("./global.js");
var es5 = _dereq_("./es5.js");
var haveGetters = (function(){
try {
var o = {};
es5.defineProperty(o, "f", {
get: function () {
return 3;
}
});
return o.f === 3;
}
catch (e) {
return false;
}
})();
var canEvaluate = (function() {
if (typeof window !== "undefined" && window !== null &&
typeof window.document !== "undefined" &&
typeof navigator !== "undefined" && navigator !== null &&
typeof navigator.appName === "string" &&
window === global) {
return false;
}
return true;
})();
function deprecated(msg) {
if (typeof console !== "undefined" && console !== null &&
typeof console.warn === "function") {
console.warn("Bluebird: " + msg);
}
}
var errorObj = {e: {}};
function tryCatch1(fn, receiver, arg) {
try {
return fn.call(receiver, arg);
}
catch (e) {
errorObj.e = e;
return errorObj;
}
}
function tryCatch2(fn, receiver, arg, arg2) {
try {
return fn.call(receiver, arg, arg2);
}
catch (e) {
errorObj.e = e;
return errorObj;
}
}
function tryCatchApply(fn, args, receiver) {
try {
return fn.apply(receiver, args);
}
catch (e) {
errorObj.e = e;
return errorObj;
}
}
var inherits = function(Child, Parent) {
var hasProp = {}.hasOwnProperty;
function T() {
this.constructor = Child;
this.constructor$ = Parent;
for (var propertyName in Parent.prototype) {
if (hasProp.call(Parent.prototype, propertyName) &&
propertyName.charAt(propertyName.length-1) !== "$"
) {
this[propertyName + "$"] = Parent.prototype[propertyName];
}
}
}
T.prototype = Parent.prototype;
Child.prototype = new T();
return Child.prototype;
};
function asString(val) {
return typeof val === "string" ? val : ("" + val);
}
function isPrimitive(val) {
return val == null || val === true || val === false ||
typeof val === "string" || typeof val === "number";
}
function isObject(value) {
return !isPrimitive(value);
}
function maybeWrapAsError(maybeError) {
if (!isPrimitive(maybeError)) return maybeError;
return new Error(asString(maybeError));
}
function withAppended(target, appendee) {
var len = target.length;
var ret = new Array(len + 1);
var i;
for (i = 0; i < len; ++i) {
ret[i] = target[i];
}
ret[i] = appendee;
return ret;
}
function notEnumerableProp(obj, name, value) {
if (isPrimitive(obj)) return obj;
var descriptor = {
value: value,
configurable: true,
enumerable: false,
writable: true
};
es5.defineProperty(obj, name, descriptor);
return obj;
}
var wrapsPrimitiveReceiver = (function() {
return this !== "string";
}).call("string");
function thrower(r) {
throw r;
}
function toFastProperties(obj) {
/*jshint -W027*/
function f() {}
f.prototype = obj;
return f;
eval(obj);
}
var ret = {
thrower: thrower,
isArray: es5.isArray,
haveGetters: haveGetters,
notEnumerableProp: notEnumerableProp,
isPrimitive: isPrimitive,
isObject: isObject,
canEvaluate: canEvaluate,
deprecated: deprecated,
errorObj: errorObj,
tryCatch1: tryCatch1,
tryCatch2: tryCatch2,
tryCatchApply: tryCatchApply,
inherits: inherits,
withAppended: withAppended,
asString: asString,
maybeWrapAsError: maybeWrapAsError,
wrapsPrimitiveReceiver: wrapsPrimitiveReceiver,
toFastProperties: toFastProperties
};
module.exports = ret;
},{"./es5.js":82,"./global.js":86}],109:[function(_dereq_,module,exports){
/**
* Module dependencies.
*/
var global = (function() { return this; })();
/**
* WebSocket constructor.
*/
var WebSocket = global.WebSocket || global.MozWebSocket;
/**
* Module exports.
*/
module.exports = WebSocket ? ws : null;
/**
* WebSocket constructor.
*
* The third `opts` options object gets ignored in web browsers, since it's
* non-standard, and throws a TypeError if passed to the constructor.
* See: https://github.com/einaros/ws/issues/227
*
* @param {String} uri
* @param {Array} protocols (optional)
* @param {Object) opts (optional)
* @api public
*/
function ws(uri, protocols, opts) {
var instance;
if (protocols) {
instance = new WebSocket(uri, protocols);
} else {
instance = new WebSocket(uri);
}
return instance;
}
if (WebSocket) ws.prototype = WebSocket.prototype;
},{}],110:[function(_dereq_,module,exports){
module.exports = _dereq_('./lib/hypertimer');
},{"./lib/hypertimer":111}],111:[function(_dereq_,module,exports){
var util = _dereq_('./util');
// enum for type of timeout
var TYPE = {
TIMEOUT: 0,
INTERVAL: 1,
TRIGGER: 2
};
var DISCRETE = 'discrete';
/**
* Create a new hypertimer
* @param {Object} [options] The following options are available:
* rate: number | 'discrete'
* The rate of speed of hyper time with
* respect to real-time in milliseconds
* per millisecond. Rate must be a
* positive number, or 'discrete' to
* run in discrete time (jumping from
* event to event). By default, rate is 1.
* deterministic: boolean
* If true (default), simultaneous events
* are executed in a deterministic order.
*/
function hypertimer(options) {
// options
var rate = 1; // number of milliseconds per milliseconds
var deterministic = true; // run simultaneous events in a deterministic order
// properties
var running = false; // true when running
var realTime = null; // timestamp. the moment in real-time when hyperTime was set
var hyperTime = null; // timestamp. the start time in hyper-time
var timeouts = []; // array with all running timeouts
var current = {}; // the timeouts currently in progress (callback is being executed)
var timeoutId = null; // currently running timer
var idSeq = 0; // counter for unique timeout id's
// exported timer object with public functions and variables
var timer = {};
/**
* Change configuration options of the hypertimer, or retrieve current
* configuration.
* @param {Object} [options] The following options are available:
* rate: number | 'discrete'
* The rate of speed of hyper time with
* respect to real-time in milliseconds
* per millisecond. Rate must be a
* positive number, or 'discrete' to
* run in discrete time (jumping from
* event to event). By default, rate is 1.
* deterministic: boolean
* If true (default), simultaneous events
* are executed in a deterministic order.
* @return {Object} Returns the applied configuration
*/
timer.config = function(options) {
if (options) {
if ('rate' in options) {
var newRate = (options.rate === DISCRETE) ? DISCRETE : Number(options.rate);
if (newRate !== DISCRETE && (isNaN(newRate) || newRate <= 0)) {
throw new TypeError('rate must be a positive number or the string "discrete"');
}
hyperTime = timer.now();
realTime = util.nowReal();
rate = newRate;
}
if ('deterministic' in options) {
deterministic = options.deterministic ? true : false;
}
}
// reschedule running timeouts
_schedule();
// return a copy of the configuration options
return {
rate: rate,
deterministic: deterministic
};
};
/**
* Set the time of the timer. To get the current time, use getTime() or now().
* @param {number | Date} time The time in hyper-time.
*/
timer.setTime = function (time) {
if (time instanceof Date) {
hyperTime = time.valueOf();
}
else {
var newTime = Number(time);
if (isNaN(newTime)) {
throw new TypeError('time must be a Date or number');
}
hyperTime = newTime;
}
// reschedule running timeouts
_schedule();
};
/**
* Returns the current time of the timer as a number.
* See also getTime().
* @return {number} The time
*/
timer.now = function () {
if (rate === DISCRETE) {
return hyperTime;
}
else {
if (running) {
// TODO: implement performance.now() / process.hrtime(time) for high precision calculation of time interval
var realInterval = util.nowReal() - realTime;
var hyperInterval = realInterval * rate;
return hyperTime + hyperInterval;
}
else {
return hyperTime;
}
}
};
/**
* Continue the timer.
*/
timer['continue'] = function() {
realTime = util.nowReal();
running = true;
// reschedule running timeouts
_schedule();
};
/**
* Pause the timer. The timer can be continued again with `continue()`
*/
timer.pause = function() {
hyperTime = timer.now();
realTime = null;
running = false;
// reschedule running timeouts (pauses them)
_schedule();
};
/**
* Returns the current time of the timer as Date.
* See also now().
* @return {Date} The time
*/
// rename to getTime
timer.getTime = function() {
return new Date(timer.now());
};
/**
* Get the value of the hypertimer. This function returns the result of getTime().
* @return {Date} current time
*/
timer.valueOf = timer.getTime;
/**
* Return a string representation of the current hyper-time.
* @returns {string} String representation
*/
timer.toString = function () {
return timer.getTime().toString();
};
/**
* Set a timeout, which is triggered when the timeout occurs in hyper-time.
* See also setTrigger.
* @param {Function} callback Function executed when delay is exceeded.
* @param {number} delay The delay in milliseconds. When the delay is
* smaller or equal to zero, the callback is
* triggered immediately.
* @return {number} Returns a timeoutId which can be used to cancel the
* timeout using clearTimeout().
*/
timer.setTimeout = function(callback, delay) {
var id = idSeq++;
var timestamp = timer.now() + delay;
if (isNaN(timestamp)) {
throw new TypeError('delay must be a number');
}
// add a new timeout to the queue
_queueTimeout({
id: id,
type: TYPE.TIMEOUT,
time: timestamp,
callback: callback
});
// reschedule the timeouts
_schedule();
return id;
};
/**
* Set a trigger, which is triggered when the timeout occurs in hyper-time.
* See also getTimeout.
* @param {Function} callback Function executed when timeout occurs.
* @param {Date | number} time An absolute moment in time (Date) when the
* callback will be triggered. When the date is
* a Date in the past, the callback is triggered
* immediately.
* @return {number} Returns a triggerId which can be used to cancel the
* trigger using clearTrigger().
*/
timer.setTrigger = function (callback, time) {
var id = idSeq++;
var timestamp = Number(time);
if (isNaN(timestamp)) {
throw new TypeError('time must be a Date or number');
}
// add a new timeout to the queue
_queueTimeout({
id: id,
type: TYPE.TRIGGER,
time: timestamp,
callback: callback
});
// reschedule the timeouts
_schedule();
return id;
};
/**
* Trigger a callback every interval. Optionally, a start date can be provided
* to specify the first time the callback must be triggered.
* See also setTimeout and setTrigger.
* @param {Function} callback Function executed when delay is exceeded.
* @param {number} interval Interval in milliseconds. When interval
* is smaller than zero or is infinity, the
* interval will be set to zero and triggered
* with a maximum rate.
* @param {Date | number} [firstTime] An absolute moment in time (Date) when the
* callback will be triggered the first time.
* By default, firstTime = now() + interval.
* @return {number} Returns a intervalId which can be used to cancel the
* trigger using clearInterval().
*/
timer.setInterval = function(callback, interval, firstTime) {
var id = idSeq++;
var _interval = Number(interval);
if (isNaN(_interval)) {
throw new TypeError('interval must be a number');
}
if (_interval < 0 || !isFinite(_interval)) {
_interval = 0;
}
var timestamp;
if (firstTime != undefined) {
timestamp = Number(firstTime);
if (isNaN(timestamp)) {
throw new TypeError('firstTime must be a Date or number');
}
}
else {
// firstTime is undefined or null
timestamp = (timer.now() + _interval);
}
// add a new timeout to the queue
_queueTimeout({
id: id,
type: TYPE.INTERVAL,
interval: _interval,
time: timestamp,
firstTime: timestamp,
occurrence: 0,
callback: callback
});
// reschedule the timeouts
_schedule();
return id;
};
/**
* Cancel a timeout
* @param {number} timeoutId The id of a timeout
*/
timer.clearTimeout = function(timeoutId) {
// test whether timeout is currently being executed
if (current[timeoutId]) {
delete current[timeoutId];
return;
}
// find the timeout in the queue
for (var i = 0; i < timeouts.length; i++) {
if (timeouts[i].id === timeoutId) {
// remove this timeout from the queue
timeouts.splice(i, 1);
// reschedule timeouts
_schedule();
break;
}
}
};
/**
* Cancel a trigger
* @param {number} triggerId The id of a trigger
*/
timer.clearTrigger = timer.clearTimeout;
timer.clearInterval = timer.clearTimeout;
/**
* Returns a list with the id's of all timeouts
* @returns {number[]} Timeout id's
*/
timer.list = function () {
return timeouts.map(function (timeout) {
return timeout.id;
});
};
/**
* Clear all timeouts
*/
timer.clear = function () {
// empty the queue
current = {};
timeouts = [];
// reschedule
_schedule();
};
/**
* Add a timeout to the queue. After the queue has been changed, the queue
* must be rescheduled by executing _reschedule()
* @param {{id: number, type: number, time: number, callback: Function}} timeout
* @private
*/
function _queueTimeout(timeout) {
// insert the new timeout at the right place in the array, sorted by time
if (timeouts.length > 0) {
var i = timeouts.length - 1;
while (i >= 0 && timeouts[i].time > timeout.time) {
i--;
}
// insert the new timeout in the queue. Note that the timeout is
// inserted *after* existing timeouts with the exact *same* time,
// so the order in which they are executed is deterministic
timeouts.splice(i + 1, 0, timeout);
}
else {
// queue is empty, append the new timeout
timeouts.push(timeout);
}
}
/**
* Execute a timeout
* @param {{id: number, type: number, time: number, callback: function}} timeout
* @param {function} [callback]
* The callback is executed when the timeout's callback is
* finished. Called without parameters
* @private
*/
function _execTimeout(timeout, callback) {
// store the timeout in the queue with timeouts in progress
// it can be cleared when a clearTimeout is executed inside the callback
current[timeout.id] = timeout;
function finish() {
// in case of an interval we have to reschedule on next cycle
// interval must not be cleared while executing the callback
if (timeout.type === TYPE.INTERVAL && current[timeout.id]) {
timeout.occurrence++;
timeout.time = timeout.firstTime + timeout.occurrence * timeout.interval;
_queueTimeout(timeout);
}
// remove the timeout from the queue with timeouts in progress
delete current[timeout.id];
if (typeof callback === 'function') callback();
}
// execute the callback
try {
if (timeout.callback.length == 0) {
// synchronous timeout, like `timer.setTimeout(function () {...}, delay)`
timeout.callback();
finish();
} else {
// asynchronous timeout, like `timer.setTimeout(function (done) {...; done(); }, delay)`
timeout.callback(finish);
}
} catch (err) {
// silently ignore errors thrown by the callback
finish();
}
}
/**
* Remove all timeouts occurring before or on the provided time from the
* queue and return them.
* @param {number} time A timestamp
* @returns {Array} returns an array containing all expired timeouts
* @private
*/
function _getExpiredTimeouts(time) {
var i = 0;
while (i < timeouts.length && ((timeouts[i].time <= time) || !isFinite(timeouts[i].time))) {
i++;
}
var expired = timeouts.splice(0, i);
if (deterministic == false) {
// the array with expired timeouts is in deterministic order
// shuffle them
util.shuffle(expired);
}
return expired;
}
/**
* Reschedule all queued timeouts
* @private
*/
function _schedule() {
// do not _schedule when there are timeouts in progress
// this can be the case with async timeouts in discrete time.
// _schedule will be executed again when all async timeouts are finished.
if (rate === DISCRETE && Object.keys(current).length > 0) {
return;
}
var next = timeouts[0];
// cancel timer when running
if (timeoutId) {
clearTimeout(timeoutId);
timeoutId = null;
}
if (running && next) {
// schedule next timeout
var time = next.time;
var delay = time - timer.now();
var realDelay = (rate === DISCRETE) ? 0 : delay / rate;
function onTimeout() {
// when running in discrete time, update the hyperTime to the time
// of the current event
if (rate === DISCRETE) {
hyperTime = time;
}
// grab all expired timeouts from the queue
var expired = _getExpiredTimeouts(time);
// note: expired.length can never be zero (on every change of the queue, we reschedule)
// execute all expired timeouts
if (rate === DISCRETE) {
// in discrete time, we execute all expired timeouts serially,
// and wait for their completion in order to guarantee deterministic
// order of execution
function next() {
var timeout = expired.shift();
if (timeout) {
_execTimeout(timeout, next);
}
else {
// schedule the next round
_schedule();
}
}
next();
}
else {
// in continuous time, we fire all timeouts in parallel,
// and don't await their completion (they can do async operations)
expired.forEach(_execTimeout);
// schedule the next round
_schedule();
}
}
timeoutId = setTimeout(onTimeout, realDelay);
}
}
Object.defineProperty(timer, 'running', {
get: function () {
return running;
}
});
timer.config(options); // apply options
timer.setTime(util.nowReal()); // set time as current real time
timer.continue(); // start the timer
return timer;
}
module.exports = hypertimer;
},{"./util":112}],112:[function(_dereq_,module,exports){
/* istanbul ignore else */
if (typeof Date.now === 'function') {
/**
* Helper function to get the current time
* @return {number} Current time
*/
exports.nowReal = function () {
return Date.now();
}
}
else {
/**
* Helper function to get the current time
* @return {number} Current time
*/
exports.nowReal = function () {
return new Date().valueOf();
}
}
/**
* Shuffle an array
*
* + Jonas Raoni Soares Silva
* @ http://jsfromhell.com/array/shuffle [v1.0]
*
* @param {Array} o Array to be shuffled
* @returns {Array} Returns the shuffled array
*/
exports.shuffle = function (o){
for(var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
return o;
};
},{}],113:[function(_dereq_,module,exports){
(function (Buffer){
// uuid.js
//
// Copyright (c) 2010-2012 Robert Kieffer
// MIT License - http://opensource.org/licenses/mit-license.php
(function() {
var _global = this;
// Unique ID creation requires a high quality random # generator. We feature
// detect to determine the best RNG source, normalizing to a function that
// returns 128-bits of randomness, since that's what's usually required
var _rng;
// Node.js crypto-based RNG - http://nodejs.org/docs/v0.6.2/api/crypto.html
//
// Moderately fast, high quality
if (typeof(_dereq_) == 'function') {
try {
var _rb = _dereq_('crypto').randomBytes;
_rng = _rb && function() {return _rb(16);};
} catch(e) {}
}
if (!_rng && _global.crypto && crypto.getRandomValues) {
// WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto
//
// Moderately fast, high quality
var _rnds8 = new Uint8Array(16);
_rng = function whatwgRNG() {
crypto.getRandomValues(_rnds8);
return _rnds8;
};
}
if (!_rng) {
// Math.random()-based (RNG)
//
// If all else fails, use Math.random(). It's fast, but is of unspecified
// quality.
var _rnds = new Array(16);
_rng = function() {
for (var i = 0, r; i < 16; i++) {
if ((i & 0x03) === 0) r = Math.random() * 0x100000000;
_rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
}
return _rnds;
};
}
// Buffer class to use
var BufferClass = typeof(Buffer) == 'function' ? Buffer : Array;
// Maps for number <-> hex string conversion
var _byteToHex = [];
var _hexToByte = {};
for (var i = 0; i < 256; i++) {
_byteToHex[i] = (i + 0x100).toString(16).substr(1);
_hexToByte[_byteToHex[i]] = i;
}
// **`parse()` - Parse a UUID into it's component bytes**
function parse(s, buf, offset) {
var i = (buf && offset) || 0, ii = 0;
buf = buf || [];
s.toLowerCase().replace(/[0-9a-f]{2}/g, function(oct) {
if (ii < 16) { // Don't overflow!
buf[i + ii++] = _hexToByte[oct];
}
});
// Zero out remaining bytes if string was short
while (ii < 16) {
buf[i + ii++] = 0;
}
return buf;
}
// **`unparse()` - Convert UUID byte array (ala parse()) into a string**
function unparse(buf, offset) {
var i = offset || 0, bth = _byteToHex;
return bth[buf[i++]] + bth[buf[i++]] +
bth[buf[i++]] + bth[buf[i++]] + '-' +
bth[buf[i++]] + bth[buf[i++]] + '-' +
bth[buf[i++]] + bth[buf[i++]] + '-' +
bth[buf[i++]] + bth[buf[i++]] + '-' +
bth[buf[i++]] + bth[buf[i++]] +
bth[buf[i++]] + bth[buf[i++]] +
bth[buf[i++]] + bth[buf[i++]];
}
// **`v1()` - Generate time-based UUID**
//
// Inspired by https://github.com/LiosK/UUID.js
// and http://docs.python.org/library/uuid.html
// random #'s we need to init node and clockseq
var _seedBytes = _rng();
// Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
var _nodeId = [
_seedBytes[0] | 0x01,
_seedBytes[1], _seedBytes[2], _seedBytes[3], _seedBytes[4], _seedBytes[5]
];
// Per 4.2.2, randomize (14 bit) clockseq
var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff;
// Previous uuid creation time
var _lastMSecs = 0, _lastNSecs = 0;
// See https://github.com/broofa/node-uuid for API details
function v1(options, buf, offset) {
var i = buf && offset || 0;
var b = buf || [];
options = options || {};
var clockseq = options.clockseq != null ? options.clockseq : _clockseq;
// UUID timestamps are 100 nano-second units since the Gregorian epoch,
// (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
// time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
// (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
var msecs = options.msecs != null ? options.msecs : new Date().getTime();
// Per 4.2.1.2, use count of uuid's generated during the current clock
// cycle to simulate higher resolution clock
var nsecs = options.nsecs != null ? options.nsecs : _lastNSecs + 1;
// Time since last uuid creation (in msecs)
var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;
// Per 4.2.1.2, Bump clockseq on clock regression
if (dt < 0 && options.clockseq == null) {
clockseq = clockseq + 1 & 0x3fff;
}
// Reset nsecs if clock regresses (new clockseq) or we've moved onto a new
// time interval
if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) {
nsecs = 0;
}
// Per 4.2.1.2 Throw error if too many uuids are requested
if (nsecs >= 10000) {
throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec');
}
_lastMSecs = msecs;
_lastNSecs = nsecs;
_clockseq = clockseq;
// Per 4.1.4 - Convert from unix epoch to Gregorian epoch
msecs += 12219292800000;
// `time_low`
var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
b[i++] = tl >>> 24 & 0xff;
b[i++] = tl >>> 16 & 0xff;
b[i++] = tl >>> 8 & 0xff;
b[i++] = tl & 0xff;
// `time_mid`
var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
b[i++] = tmh >>> 8 & 0xff;
b[i++] = tmh & 0xff;
// `time_high_and_version`
b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
b[i++] = tmh >>> 16 & 0xff;
// `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
b[i++] = clockseq >>> 8 | 0x80;
// `clock_seq_low`
b[i++] = clockseq & 0xff;
// `node`
var node = options.node || _nodeId;
for (var n = 0; n < 6; n++) {
b[i + n] = node[n];
}
return buf ? buf : unparse(b);
}
// **`v4()` - Generate random UUID**
// See https://github.com/broofa/node-uuid for API details
function v4(options, buf, offset) {
// Deprecated - 'format' argument, as supported in v1.2
var i = buf && offset || 0;
if (typeof(options) == 'string') {
buf = options == 'binary' ? new BufferClass(16) : null;
options = null;
}
options = options || {};
var rnds = options.random || (options.rng || _rng)();
// Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
rnds[6] = (rnds[6] & 0x0f) | 0x40;
rnds[8] = (rnds[8] & 0x3f) | 0x80;
// Copy bytes to buffer, if provided
if (buf) {
for (var ii = 0; ii < 16; ii++) {
buf[i + ii] = rnds[ii];
}
}
return buf || unparse(rnds);
}
// Export public API
var uuid = v4;
uuid.v1 = v1;
uuid.v4 = v4;
uuid.parse = parse;
uuid.unparse = unparse;
uuid.BufferClass = BufferClass;
if (typeof define === 'function' && define.amd) {
// Publish as AMD module
define(function() {return uuid;});
} else if (typeof(module) != 'undefined' && module.exports) {
// Publish as node.js module
module.exports = uuid;
} else {
// Publish as global (in browsers)
var _previousRoot = _global.uuid;
// **`noConflict()` - (browser only) to reset global 'uuid' var**
uuid.noConflict = function() {
_global.uuid = _previousRoot;
return uuid;
};
_global.uuid = uuid;
}
}).call(this);
}).call(this,_dereq_("buffer").Buffer)
},{"buffer":128,"crypto":132}],114:[function(_dereq_,module,exports){
'use strict';
module.exports = _dereq_('./lib/core.js')
_dereq_('./lib/done.js')
_dereq_('./lib/es6-extensions.js')
_dereq_('./lib/node-extensions.js')
},{"./lib/core.js":115,"./lib/done.js":116,"./lib/es6-extensions.js":117,"./lib/node-extensions.js":118}],115:[function(_dereq_,module,exports){
'use strict';
var asap = _dereq_('asap')
module.exports = Promise;
function Promise(fn) {
if (typeof this !== 'object') throw new TypeError('Promises must be constructed via new')
if (typeof fn !== 'function') throw new TypeError('not a function')
var state = null
var value = null
var deferreds = []
var self = this
this.then = function(onFulfilled, onRejected) {
return new self.constructor(function(resolve, reject) {
handle(new Handler(onFulfilled, onRejected, resolve, reject))
})
}
function handle(deferred) {
if (state === null) {
deferreds.push(deferred)
return
}
asap(function() {
var cb = state ? deferred.onFulfilled : deferred.onRejected
if (cb === null) {
(state ? deferred.resolve : deferred.reject)(value)
return
}
var ret
try {
ret = cb(value)
}
catch (e) {
deferred.reject(e)
return
}
deferred.resolve(ret)
})
}
function resolve(newValue) {
try { //Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.')
if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
var then = newValue.then
if (typeof then === 'function') {
doResolve(then.bind(newValue), resolve, reject)
return
}
}
state = true
value = newValue
finale()
} catch (e) { reject(e) }
}
function reject(newValue) {
state = false
value = newValue
finale()
}
function finale() {
for (var i = 0, len = deferreds.length; i < len; i++)
handle(deferreds[i])
deferreds = null
}
doResolve(fn, resolve, reject)
}
function Handler(onFulfilled, onRejected, resolve, reject){
this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null
this.onRejected = typeof onRejected === 'function' ? onRejected : null
this.resolve = resolve
this.reject = reject
}
/**
* Take a potentially misbehaving resolver function and make sure
* onFulfilled and onRejected are only called once.
*
* Makes no guarantees about asynchrony.
*/
function doResolve(fn, onFulfilled, onRejected) {
var done = false;
try {
fn(function (value) {
if (done) return
done = true
onFulfilled(value)
}, function (reason) {
if (done) return
done = true
onRejected(reason)
})
} catch (ex) {
if (done) return
done = true
onRejected(ex)
}
}
},{"asap":119}],116:[function(_dereq_,module,exports){
'use strict';
var Promise = _dereq_('./core.js')
var asap = _dereq_('asap')
module.exports = Promise
Promise.prototype.done = function (onFulfilled, onRejected) {
var self = arguments.length ? this.then.apply(this, arguments) : this
self.then(null, function (err) {
asap(function () {
throw err
})
})
}
},{"./core.js":115,"asap":119}],117:[function(_dereq_,module,exports){
'use strict';
//This file contains the ES6 extensions to the core Promises/A+ API
var Promise = _dereq_('./core.js')
var asap = _dereq_('asap')
module.exports = Promise
/* Static Functions */
function ValuePromise(value) {
this.then = function (onFulfilled) {
if (typeof onFulfilled !== 'function') return this
return new Promise(function (resolve, reject) {
asap(function () {
try {
resolve(onFulfilled(value))
} catch (ex) {
reject(ex);
}
})
})
}
}
ValuePromise.prototype = Promise.prototype
var TRUE = new ValuePromise(true)
var FALSE = new ValuePromise(false)
var NULL = new ValuePromise(null)
var UNDEFINED = new ValuePromise(undefined)
var ZERO = new ValuePromise(0)
var EMPTYSTRING = new ValuePromise('')
Promise.resolve = function (value) {
if (value instanceof Promise) return value
if (value === null) return NULL
if (value === undefined) return UNDEFINED
if (value === true) return TRUE
if (value === false) return FALSE
if (value === 0) return ZERO
if (value === '') return EMPTYSTRING
if (typeof value === 'object' || typeof value === 'function') {
try {
var then = value.then
if (typeof then === 'function') {
return new Promise(then.bind(value))
}
} catch (ex) {
return new Promise(function (resolve, reject) {
reject(ex)
})
}
}
return new ValuePromise(value)
}
Promise.all = function (arr) {
var args = Array.prototype.slice.call(arr)
return new Promise(function (resolve, reject) {
if (args.length === 0) return resolve([])
var remaining = args.length
function res(i, val) {
try {
if (val && (typeof val === 'object' || typeof val === 'function')) {
var then = val.then
if (typeof then === 'function') {
then.call(val, function (val) { res(i, val) }, reject)
return
}
}
args[i] = val
if (--remaining === 0) {
resolve(args);
}
} catch (ex) {
reject(ex)
}
}
for (var i = 0; i < args.length; i++) {
res(i, args[i])
}
})
}
Promise.reject = function (value) {
return new Promise(function (resolve, reject) {
reject(value);
});
}
Promise.race = function (values) {
return new Promise(function (resolve, reject) {
values.forEach(function(value){
Promise.resolve(value).then(resolve, reject);
})
});
}
/* Prototype Methods */
Promise.prototype['catch'] = function (onRejected) {
return this.then(null, onRejected);
}
},{"./core.js":115,"asap":119}],118:[function(_dereq_,module,exports){
'use strict';
//This file contains then/promise specific extensions that are only useful for node.js interop
var Promise = _dereq_('./core.js')
var asap = _dereq_('asap')
module.exports = Promise
/* Static Functions */
Promise.denodeify = function (fn, argumentCount) {
argumentCount = argumentCount || Infinity
return function () {
var self = this
var args = Array.prototype.slice.call(arguments)
return new Promise(function (resolve, reject) {
while (args.length && args.length > argumentCount) {
args.pop()
}
args.push(function (err, res) {
if (err) reject(err)
else resolve(res)
})
fn.apply(self, args)
})
}
}
Promise.nodeify = function (fn) {
return function () {
var args = Array.prototype.slice.call(arguments)
var callback = typeof args[args.length - 1] === 'function' ? args.pop() : null
var ctx = this
try {
return fn.apply(this, arguments).nodeify(callback, ctx)
} catch (ex) {
if (callback === null || typeof callback == 'undefined') {
return new Promise(function (resolve, reject) { reject(ex) })
} else {
asap(function () {
callback.call(ctx, ex)
})
}
}
}
}
Promise.prototype.nodeify = function (callback, ctx) {
if (typeof callback != 'function') return this
this.then(function (value) {
asap(function () {
callback.call(ctx, null, value)
})
}, function (err) {
asap(function () {
callback.call(ctx, err)
})
})
}
},{"./core.js":115,"asap":119}],119:[function(_dereq_,module,exports){
(function (process){
// Use the fastest possible means to execute a task in a future turn
// of the event loop.
// linked list of tasks (single, with head node)
var head = {task: void 0, next: null};
var tail = head;
var flushing = false;
var requestFlush = void 0;
var isNodeJS = false;
function flush() {
/* jshint loopfunc: true */
while (head.next) {
head = head.next;
var task = head.task;
head.task = void 0;
var domain = head.domain;
if (domain) {
head.domain = void 0;
domain.enter();
}
try {
task();
} catch (e) {
if (isNodeJS) {
// In node, uncaught exceptions are considered fatal errors.
// Re-throw them synchronously to interrupt flushing!
// Ensure continuation if the uncaught exception is suppressed
// listening "uncaughtException" events (as domains does).
// Continue in next event to avoid tick recursion.
if (domain) {
domain.exit();
}
setTimeout(flush, 0);
if (domain) {
domain.enter();
}
throw e;
} else {
// In browsers, uncaught exceptions are not fatal.
// Re-throw them asynchronously to avoid slow-downs.
setTimeout(function() {
throw e;
}, 0);
}
}
if (domain) {
domain.exit();
}
}
flushing = false;
}
if (typeof process !== "undefined" && process.nextTick) {
// Node.js before 0.9. Note that some fake-Node environments, like the
// Mocha test runner, introduce a `process` global without a `nextTick`.
isNodeJS = true;
requestFlush = function () {
process.nextTick(flush);
};
} else if (typeof setImmediate === "function") {
// In IE10, Node.js 0.9+, or https://github.com/NobleJS/setImmediate
if (typeof window !== "undefined") {
requestFlush = setImmediate.bind(window, flush);
} else {
requestFlush = function () {
setImmediate(flush);
};
}
} else if (typeof MessageChannel !== "undefined") {
// modern browsers
// http://www.nonblocking.io/2011/06/windownexttick.html
var channel = new MessageChannel();
channel.port1.onmessage = flush;
requestFlush = function () {
channel.port2.postMessage(0);
};
} else {
// old browsers
requestFlush = function () {
setTimeout(flush, 0);
};
}
function asap(task) {
tail = tail.next = {
task: task,
domain: isNodeJS && process.domain,
next: null
};
if (!flushing) {
flushing = true;
requestFlush();
}
};
module.exports = asap;
}).call(this,_dereq_("C:\\Users\\Alex\\AppData\\Roaming\\npm\\node_modules\\browserify\\node_modules\\insert-module-globals\\node_modules\\process\\browser.js"))
},{"C:\\Users\\Alex\\AppData\\Roaming\\npm\\node_modules\\browserify\\node_modules\\insert-module-globals\\node_modules\\process\\browser.js":144}],120:[function(_dereq_,module,exports){
module.exports=_dereq_(62)
},{"./lib/agent":122}],121:[function(_dereq_,module,exports){
module.exports=_dereq_(63)
},{"C:\\Users\\Alex\\AppData\\Roaming\\npm\\node_modules\\browserify\\node_modules\\insert-module-globals\\node_modules\\process\\browser.js":144,"events":137,"http":138,"net":127,"url":157,"util":159}],122:[function(_dereq_,module,exports){
module.exports=_dereq_(64)
},{"./_http_agent":121,"C:\\Users\\Alex\\AppData\\Roaming\\npm\\node_modules\\browserify\\node_modules\\insert-module-globals\\node_modules\\process\\browser.js":144,"http":138,"https":142,"util":159}],123:[function(_dereq_,module,exports){
module.exports=_dereq_(65)
},{"agentkeepalive":120,"buffer":128,"crypto":132,"http":138,"https":142}],124:[function(_dereq_,module,exports){
(function (global){
'use strict';
var width = 256;// each RC4 output is 0 <= x < 256
var chunks = 6;// at least six RC4 outputs for each double
var digits = 52;// there are 52 significant digits in a double
var pool = [];// pool: entropy pool starts empty
var GLOBAL = typeof global === 'undefined' ? window : global;
//
// The following constants are related to IEEE 754 limits.
//
var startdenom = Math.pow(width, chunks),
significance = Math.pow(2, digits),
overflow = significance * 2,
mask = width - 1;
var oldRandom = Math.random;
//
// seedrandom()
// This is the seedrandom function described above.
//
module.exports = function(seed, options) {
if (options && options.global === true) {
options.global = false;
Math.random = module.exports(seed, options);
options.global = true;
return Math.random;
}
var use_entropy = (options && options.entropy) || false;
var key = [];
// Flatten the seed string or build one from local entropy if needed.
var shortseed = mixkey(flatten(
use_entropy ? [seed, tostring(pool)] :
0 in arguments ? seed : autoseed(), 3), key);
// Use the seed to initialize an ARC4 generator.
var arc4 = new ARC4(key);
// Mix the randomness into accumulated entropy.
mixkey(tostring(arc4.S), pool);
// Override Math.random
// This function returns a random double in [0, 1) that contains
// randomness in every bit of the mantissa of the IEEE 754 value.
return function() { // Closure to return a random double:
var n = arc4.g(chunks), // Start with a numerator n < 2 ^ 48
d = startdenom, // and denominator d = 2 ^ 48.
x = 0; // and no 'extra last byte'.
while (n < significance) { // Fill up all significant digits by
n = (n + x) * width; // shifting numerator and
d *= width; // denominator and generating a
x = arc4.g(1); // new least-significant-byte.
}
while (n >= overflow) { // To avoid rounding up, before adding
n /= 2; // last byte, shift everything
d /= 2; // right using integer Math until
x >>>= 1; // we have exactly the desired bits.
}
return (n + x) / d; // Form the number within [0, 1).
};
};
module.exports.resetGlobal = function () {
Math.random = oldRandom;
};
//
// ARC4
//
// An ARC4 implementation. The constructor takes a key in the form of
// an array of at most (width) integers that should be 0 <= x < (width).
//
// The g(count) method returns a pseudorandom integer that concatenates
// the next (count) outputs from ARC4. Its return value is a number x
// that is in the range 0 <= x < (width ^ count).
//
/** @constructor */
function ARC4(key) {
var t, keylen = key.length,
me = this, i = 0, j = me.i = me.j = 0, s = me.S = [];
// The empty key [] is treated as [0].
if (!keylen) { key = [keylen++]; }
// Set up S using the standard key scheduling algorithm.
while (i < width) {
s[i] = i++;
}
for (i = 0; i < width; i++) {
s[i] = s[j = mask & (j + key[i % keylen] + (t = s[i]))];
s[j] = t;
}
// The "g" method returns the next (count) outputs as one number.
(me.g = function(count) {
// Using instance members instead of closure state nearly doubles speed.
var t, r = 0,
i = me.i, j = me.j, s = me.S;
while (count--) {
t = s[i = mask & (i + 1)];
r = r * width + s[mask & ((s[i] = s[j = mask & (j + t)]) + (s[j] = t))];
}
me.i = i; me.j = j;
return r;
// For robust unpredictability discard an initial batch of values.
// See http://www.rsa.com/rsalabs/node.asp?id=2009
})(width);
}
//
// flatten()
// Converts an object tree to nested arrays of strings.
//
function flatten(obj, depth) {
var result = [], typ = (typeof obj)[0], prop;
if (depth && typ == 'o') {
for (prop in obj) {
try { result.push(flatten(obj[prop], depth - 1)); } catch (e) {}
}
}
return (result.length ? result : typ == 's' ? obj : obj + '\0');
}
//
// mixkey()
// Mixes a string seed into a key that is an array of integers, and
// returns a shortened string seed that is equivalent to the result key.
//
function mixkey(seed, key) {
var stringseed = seed + '', smear, j = 0;
while (j < stringseed.length) {
key[mask & j] =
mask & ((smear ^= key[mask & j] * 19) + stringseed.charCodeAt(j++));
}
return tostring(key);
}
//
// autoseed()
// Returns an object for autoseeding, using window.crypto if available.
//
/** @param {Uint8Array=} seed */
function autoseed(seed) {
try {
GLOBAL.crypto.getRandomValues(seed = new Uint8Array(width));
return tostring(seed);
} catch (e) {
return [+new Date, GLOBAL, GLOBAL.navigator && GLOBAL.navigator.plugins,
GLOBAL.screen, tostring(pool)];
}
}
//
// tostring()
// Converts an array of charcodes to a string
//
function tostring(a) {
return String.fromCharCode.apply(0, a);
}
//
// When seedrandom.js is loaded, we immediately mix a few bits
// from the built-in RNG into the entropy pool. Because we do
// not want to intefere with determinstic PRNG state later,
// seedrandom will not call Math.random on its own again after
// initialization.
//
mixkey(Math.random(), pool);
}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],125:[function(_dereq_,module,exports){
exports = module.exports = function() {
var ret = '', value;
for (var i = 0; i < 32; i++) {
value = exports.random() * 16 | 0;
// Insert the hypens
if (i > 4 && i < 21 && ! (i % 4)) {
ret += '-';
}
// Add the next random character
ret += (
(i === 12) ? 4 : (
(i === 16) ? (value & 3 | 8) : value
)
).toString(16);
}
return ret;
};
var uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
exports.isUUID = function(uuid) {
return uuidRegex.test(uuid);
};
exports.random = function() {
return Math.random();
};
},{}],126:[function(_dereq_,module,exports){
module.exports=_dereq_(109)
},{}],127:[function(_dereq_,module,exports){
},{}],128:[function(_dereq_,module,exports){
/*!
* The buffer module from node.js, for the browser.
*
* @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
* @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 '<Buffer ' + out.join(' ') + '>'
}
/**
* 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":129,"ieee754":130}],129:[function(_dereq_,module,exports){
var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
;(function (exports) {
'use strict';
var Arr = (typeof Uint8Array !== 'undefined')
? Uint8Array
: Array
var ZERO = '0'.charCodeAt(0)
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
}
module.exports.toByteArray = b64ToByteArray
module.exports.fromByteArray = uint8ToBase64
}())
},{}],130:[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;
};
},{}],131:[function(_dereq_,module,exports){
var Buffer = _dereq_('buffer').Buffer;
var intSize = 4;
var zeroBuffer = new Buffer(intSize); zeroBuffer.fill(0);
var chrsz = 8;
function toArray(buf, bigEndian) {
if ((buf.length % intSize) !== 0) {
var len = buf.length + (intSize - (buf.length % intSize));
buf = Buffer.concat([buf, zeroBuffer], len);
}
var arr = [];
var fn = bigEndian ? buf.readInt32BE : buf.readInt32LE;
for (var i = 0; i < buf.length; i += intSize) {
arr.push(fn.call(buf, i));
}
return arr;
}
function toBuffer(arr, size, bigEndian) {
var buf = new Buffer(size);
var fn = bigEndian ? buf.writeInt32BE : buf.writeInt32LE;
for (var i = 0; i < arr.length; i++) {
fn.call(buf, arr[i], i * 4, true);
}
return buf;
}
function hash(buf, fn, hashSize, bigEndian) {
if (!Buffer.isBuffer(buf)) buf = new Buffer(buf);
var arr = fn(toArray(buf, bigEndian), buf.length * chrsz);
return toBuffer(arr, hashSize, bigEndian);
}
module.exports = { hash: hash };
},{"buffer":128}],132:[function(_dereq_,module,exports){
var Buffer = _dereq_('buffer').Buffer
var sha = _dereq_('./sha')
var sha256 = _dereq_('./sha256')
var rng = _dereq_('./rng')
var md5 = _dereq_('./md5')
var algorithms = {
sha1: sha,
sha256: sha256,
md5: md5
}
var blocksize = 64
var zeroBuffer = new Buffer(blocksize); zeroBuffer.fill(0)
function hmac(fn, key, data) {
if(!Buffer.isBuffer(key)) key = new Buffer(key)
if(!Buffer.isBuffer(data)) data = new Buffer(data)
if(key.length > blocksize) {
key = fn(key)
} else if(key.length < blocksize) {
key = Buffer.concat([key, zeroBuffer], blocksize)
}
var ipad = new Buffer(blocksize), opad = new Buffer(blocksize)
for(var i = 0; i < blocksize; i++) {
ipad[i] = key[i] ^ 0x36
opad[i] = key[i] ^ 0x5C
}
var hash = fn(Buffer.concat([ipad, data]))
return fn(Buffer.concat([opad, hash]))
}
function hash(alg, key) {
alg = alg || 'sha1'
var fn = algorithms[alg]
var bufs = []
var length = 0
if(!fn) error('algorithm:', alg, 'is not yet supported')
return {
update: function (data) {
if(!Buffer.isBuffer(data)) data = new Buffer(data)
bufs.push(data)
length += data.length
return this
},
digest: function (enc) {
var buf = Buffer.concat(bufs)
var r = key ? hmac(fn, key, buf) : fn(buf)
bufs = null
return enc ? r.toString(enc) : r
}
}
}
function error () {
var m = [].slice.call(arguments).join(' ')
throw new Error([
m,
'we accept pull requests',
'http://github.com/dominictarr/crypto-browserify'
].join('\n'))
}
exports.createHash = function (alg) { return hash(alg) }
exports.createHmac = function (alg, key) { return hash(alg, key) }
exports.randomBytes = function(size, callback) {
if (callback && callback.call) {
try {
callback.call(this, undefined, new Buffer(rng(size)))
} catch (err) { callback(err) }
} else {
return new Buffer(rng(size))
}
}
function each(a, f) {
for(var i in a)
f(a[i], i)
}
// the least I can do is make error messages for the rest of the node.js/crypto api.
each(['createCredentials'
, 'createCipher'
, 'createCipheriv'
, 'createDecipher'
, 'createDecipheriv'
, 'createSign'
, 'createVerify'
, 'createDiffieHellman'
, 'pbkdf2'], function (name) {
exports[name] = function () {
error('sorry,', name, 'is not implemented yet')
}
})
},{"./md5":133,"./rng":134,"./sha":135,"./sha256":136,"buffer":128}],133:[function(_dereq_,module,exports){
/*
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
* Digest Algorithm, as defined in RFC 1321.
* Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
* Distributed under the BSD License
* See http://pajhome.org.uk/crypt/md5 for more info.
*/
var helpers = _dereq_('./helpers');
/*
* Perform a simple self-test to see if the VM is working
*/
function md5_vm_test()
{
return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
}
/*
* Calculate the MD5 of an array of little-endian words, and a bit length
*/
function core_md5(x, len)
{
/* append padding */
x[len >> 5] |= 0x80 << ((len) % 32);
x[(((len + 64) >>> 9) << 4) + 14] = len;
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
for(var i = 0; i < x.length; i += 16)
{
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
}
return Array(a, b, c, d);
}
/*
* These functions implement the four basic operations the algorithm uses.
*/
function md5_cmn(q, a, b, x, s, t)
{
return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
}
function md5_ff(a, b, c, d, x, s, t)
{
return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
function md5_gg(a, b, c, d, x, s, t)
{
return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
function md5_hh(a, b, c, d, x, s, t)
{
return md5_cmn(b ^ c ^ d, a, b, x, s, t);
}
function md5_ii(a, b, c, d, x, s, t)
{
return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
}
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function safe_add(x, y)
{
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function bit_rol(num, cnt)
{
return (num << cnt) | (num >>> (32 - cnt));
}
module.exports = function md5(buf) {
return helpers.hash(buf, core_md5, 16);
};
},{"./helpers":131}],134:[function(_dereq_,module,exports){
// Original code adapted from Robert Kieffer.
// details at https://github.com/broofa/node-uuid
(function() {
var _global = this;
var mathRNG, whatwgRNG;
// NOTE: Math.random() does not guarantee "cryptographic quality"
mathRNG = function(size) {
var bytes = new Array(size);
var r;
for (var i = 0, r; i < size; i++) {
if ((i & 0x03) == 0) r = Math.random() * 0x100000000;
bytes[i] = r >>> ((i & 0x03) << 3) & 0xff;
}
return bytes;
}
if (_global.crypto && crypto.getRandomValues) {
whatwgRNG = function(size) {
var bytes = new Uint8Array(size);
crypto.getRandomValues(bytes);
return bytes;
}
}
module.exports = whatwgRNG || mathRNG;
}())
},{}],135:[function(_dereq_,module,exports){
/*
* A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
* in FIPS PUB 180-1
* Version 2.1a Copyright Paul Johnston 2000 - 2002.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
* Distributed under the BSD License
* See http://pajhome.org.uk/crypt/md5 for details.
*/
var helpers = _dereq_('./helpers');
/*
* Calculate the SHA-1 of an array of big-endian words, and a bit length
*/
function core_sha1(x, len)
{
/* append padding */
x[len >> 5] |= 0x80 << (24 - len % 32);
x[((len + 64 >> 9) << 4) + 15] = len;
var w = Array(80);
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
var e = -1009589776;
for(var i = 0; i < x.length; i += 16)
{
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
var olde = e;
for(var j = 0; j < 80; j++)
{
if(j < 16) w[j] = x[i + j];
else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
safe_add(safe_add(e, w[j]), sha1_kt(j)));
e = d;
d = c;
c = rol(b, 30);
b = a;
a = t;
}
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
e = safe_add(e, olde);
}
return Array(a, b, c, d, e);
}
/*
* Perform the appropriate triplet combination function for the current
* iteration
*/
function sha1_ft(t, b, c, d)
{
if(t < 20) return (b & c) | ((~b) & d);
if(t < 40) return b ^ c ^ d;
if(t < 60) return (b & c) | (b & d) | (c & d);
return b ^ c ^ d;
}
/*
* Determine the appropriate additive constant for the current iteration
*/
function sha1_kt(t)
{
return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
(t < 60) ? -1894007588 : -899497514;
}
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function safe_add(x, y)
{
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function rol(num, cnt)
{
return (num << cnt) | (num >>> (32 - cnt));
}
module.exports = function sha1(buf) {
return helpers.hash(buf, core_sha1, 20, true);
};
},{"./helpers":131}],136:[function(_dereq_,module,exports){
/**
* A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined
* in FIPS 180-2
* Version 2.2-beta Copyright Angel Marin, Paul Johnston 2000 - 2009.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
*
*/
var helpers = _dereq_('./helpers');
var safe_add = function(x, y) {
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
};
var S = function(X, n) {
return (X >>> n) | (X << (32 - n));
};
var R = function(X, n) {
return (X >>> n);
};
var Ch = function(x, y, z) {
return ((x & y) ^ ((~x) & z));
};
var Maj = function(x, y, z) {
return ((x & y) ^ (x & z) ^ (y & z));
};
var Sigma0256 = function(x) {
return (S(x, 2) ^ S(x, 13) ^ S(x, 22));
};
var Sigma1256 = function(x) {
return (S(x, 6) ^ S(x, 11) ^ S(x, 25));
};
var Gamma0256 = function(x) {
return (S(x, 7) ^ S(x, 18) ^ R(x, 3));
};
var Gamma1256 = function(x) {
return (S(x, 17) ^ S(x, 19) ^ R(x, 10));
};
var core_sha256 = function(m, l) {
var K = new Array(0x428A2F98,0x71374491,0xB5C0FBCF,0xE9B5DBA5,0x3956C25B,0x59F111F1,0x923F82A4,0xAB1C5ED5,0xD807AA98,0x12835B01,0x243185BE,0x550C7DC3,0x72BE5D74,0x80DEB1FE,0x9BDC06A7,0xC19BF174,0xE49B69C1,0xEFBE4786,0xFC19DC6,0x240CA1CC,0x2DE92C6F,0x4A7484AA,0x5CB0A9DC,0x76F988DA,0x983E5152,0xA831C66D,0xB00327C8,0xBF597FC7,0xC6E00BF3,0xD5A79147,0x6CA6351,0x14292967,0x27B70A85,0x2E1B2138,0x4D2C6DFC,0x53380D13,0x650A7354,0x766A0ABB,0x81C2C92E,0x92722C85,0xA2BFE8A1,0xA81A664B,0xC24B8B70,0xC76C51A3,0xD192E819,0xD6990624,0xF40E3585,0x106AA070,0x19A4C116,0x1E376C08,0x2748774C,0x34B0BCB5,0x391C0CB3,0x4ED8AA4A,0x5B9CCA4F,0x682E6FF3,0x748F82EE,0x78A5636F,0x84C87814,0x8CC70208,0x90BEFFFA,0xA4506CEB,0xBEF9A3F7,0xC67178F2);
var HASH = new Array(0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19);
var W = new Array(64);
var a, b, c, d, e, f, g, h, i, j;
var T1, T2;
/* append padding */
m[l >> 5] |= 0x80 << (24 - l % 32);
m[((l + 64 >> 9) << 4) + 15] = l;
for (var i = 0; i < m.length; i += 16) {
a = HASH[0]; b = HASH[1]; c = HASH[2]; d = HASH[3]; e = HASH[4]; f = HASH[5]; g = HASH[6]; h = HASH[7];
for (var j = 0; j < 64; j++) {
if (j < 16) {
W[j] = m[j + i];
} else {
W[j] = safe_add(safe_add(safe_add(Gamma1256(W[j - 2]), W[j - 7]), Gamma0256(W[j - 15])), W[j - 16]);
}
T1 = safe_add(safe_add(safe_add(safe_add(h, Sigma1256(e)), Ch(e, f, g)), K[j]), W[j]);
T2 = safe_add(Sigma0256(a), Maj(a, b, c));
h = g; g = f; f = e; e = safe_add(d, T1); d = c; c = b; b = a; a = safe_add(T1, T2);
}
HASH[0] = safe_add(a, HASH[0]); HASH[1] = safe_add(b, HASH[1]); HASH[2] = safe_add(c, HASH[2]); HASH[3] = safe_add(d, HASH[3]);
HASH[4] = safe_add(e, HASH[4]); HASH[5] = safe_add(f, HASH[5]); HASH[6] = safe_add(g, HASH[6]); HASH[7] = safe_add(h, HASH[7]);
}
return HASH;
};
module.exports = function sha256(buf) {
return helpers.hash(buf, core_sha256, 32, true);
};
},{"./helpers":131}],137:[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
} else {
throw TypeError('Uncaught, unspecified "error" event.');
}
return false;
}
}
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);
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;
}
},{}],138:[function(_dereq_,module,exports){
var http = module.exports;
var EventEmitter = _dereq_('events').EventEmitter;
var Request = _dereq_('./lib/request');
var url = _dereq_('url')
http.request = function (params, cb) {
if (typeof params === 'string') {
params = url.parse(params)
}
if (!params) params = {};
if (!params.host && !params.port) {
params.port = parseInt(window.location.port, 10);
}
if (!params.host && params.hostname) {
params.host = params.hostname;
}
if (!params.scheme) params.scheme = window.location.protocol.split(':')[0];
if (!params.host) {
params.host = window.location.hostname || window.location.host;
}
if (/:/.test(params.host)) {
if (!params.port) {
params.port = params.host.split(':')[1];
}
params.host = params.host.split(':')[0];
}
if (!params.port) params.port = params.scheme == 'https' ? 443 : 80;
var req = new Request(new xhrHttp, params);
if (cb) req.on('response', cb);
return req;
};
http.get = function (params, cb) {
params.method = 'GET';
var req = http.request(params, cb);
req.end();
return req;
};
http.Agent = function () {};
http.Agent.defaultMaxSockets = 4;
var xhrHttp = (function () {
if (typeof window === 'undefined') {
throw new Error('no window object present');
}
else if (window.XMLHttpRequest) {
return window.XMLHttpRequest;
}
else if (window.ActiveXObject) {
var axs = [
'Msxml2.XMLHTTP.6.0',
'Msxml2.XMLHTTP.3.0',
'Microsoft.XMLHTTP'
];
for (var i = 0; i < axs.length; i++) {
try {
var ax = new(window.ActiveXObject)(axs[i]);
return function () {
if (ax) {
var ax_ = ax;
ax = null;
return ax_;
}
else {
return new(window.ActiveXObject)(axs[i]);
}
};
}
catch (e) {}
}
throw new Error('ajax not supported in this browser')
}
else {
throw new Error('ajax not supported in this browser');
}
})();
http.STATUS_CODES = {
100 : 'Continue',
101 : 'Switching Protocols',
102 : 'Processing', // RFC 2518, obsoleted by RFC 4918
200 : 'OK',
201 : 'Created',
202 : 'Accepted',
203 : 'Non-Authoritative Information',
204 : 'No Content',
205 : 'Reset Content',
206 : 'Partial Content',
207 : 'Multi-Status', // RFC 4918
300 : 'Multiple Choices',
301 : 'Moved Permanently',
302 : 'Moved Temporarily',
303 : 'See Other',
304 : 'Not Modified',
305 : 'Use Proxy',
307 : 'Temporary Redirect',
400 : 'Bad Request',
401 : 'Unauthorized',
402 : 'Payment Required',
403 : 'Forbidden',
404 : 'Not Found',
405 : 'Method Not Allowed',
406 : 'Not Acceptable',
407 : 'Proxy Authentication Required',
408 : 'Request Time-out',
409 : 'Conflict',
410 : 'Gone',
411 : 'Length Required',
412 : 'Precondition Failed',
413 : 'Request Entity Too Large',
414 : 'Request-URI Too Large',
415 : 'Unsupported Media Type',
416 : 'Requested Range Not Satisfiable',
417 : 'Expectation Failed',
418 : 'I\'m a teapot', // RFC 2324
422 : 'Unprocessable Entity', // RFC 4918
423 : 'Locked', // RFC 4918
424 : 'Failed Dependency', // RFC 4918
425 : 'Unordered Collection', // RFC 4918
426 : 'Upgrade Required', // RFC 2817
428 : 'Precondition Required', // RFC 6585
429 : 'Too Many Requests', // RFC 6585
431 : 'Request Header Fields Too Large',// RFC 6585
500 : 'Internal Server Error',
501 : 'Not Implemented',
502 : 'Bad Gateway',
503 : 'Service Unavailable',
504 : 'Gateway Time-out',
505 : 'HTTP Version Not Supported',
506 : 'Variant Also Negotiates', // RFC 2295
507 : 'Insufficient Storage', // RFC 4918
509 : 'Bandwidth Limit Exceeded',
510 : 'Not Extended', // RFC 2774
511 : 'Network Authentication Required' // RFC 6585
};
},{"./lib/request":139,"events":137,"url":157}],139:[function(_dereq_,module,exports){
var Stream = _dereq_('stream');
var Response = _dereq_('./response');
var Base64 = _dereq_('Base64');
var inherits = _dereq_('inherits');
var Request = module.exports = function (xhr, params) {
var self = this;
self.writable = true;
self.xhr = xhr;
self.body = [];
self.uri = (params.scheme || 'http') + '://'
+ params.host
+ (params.port ? ':' + params.port : '')
+ (params.path || '/')
;
if (typeof params.withCredentials === 'undefined') {
params.withCredentials = true;
}
try { xhr.withCredentials = params.withCredentials }
catch (e) {}
xhr.open(
params.method || 'GET',
self.uri,
true
);
self._headers = {};
if (params.headers) {
var keys = objectKeys(params.headers);
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
if (!self.isSafeRequestHeader(key)) continue;
var value = params.headers[key];
self.setHeader(key, value);
}
}
if (params.auth) {
//basic auth
this.setHeader('Authorization', 'Basic ' + Base64.btoa(params.auth));
}
var res = new Response;
res.on('close', function () {
self.emit('close');
});
res.on('ready', function () {
self.emit('response', res);
});
xhr.onreadystatechange = function () {
// Fix for IE9 bug
// SCRIPT575: Could not complete the operation due to error c00c023f
// It happens when a request is aborted, calling the success callback anyway with readyState === 4
if (xhr.__aborted) return;
res.handle(xhr);
};
};
inherits(Request, Stream);
Request.prototype.setHeader = function (key, value) {
this._headers[key.toLowerCase()] = value
};
Request.prototype.getHeader = function (key) {
return this._headers[key.toLowerCase()]
};
Request.prototype.removeHeader = function (key) {
delete this._headers[key.toLowerCase()]
};
Request.prototype.write = function (s) {
this.body.push(s);
};
Request.prototype.destroy = function (s) {
this.xhr.__aborted = true;
this.xhr.abort();
this.emit('close');
};
Request.prototype.end = function (s) {
if (s !== undefined) this.body.push(s);
var keys = objectKeys(this._headers);
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var value = this._headers[key];
if (isArray(value)) {
for (var j = 0; j < value.length; j++) {
this.xhr.setRequestHeader(key, value[j]);
}
}
else this.xhr.setRequestHeader(key, value)
}
if (this.body.length === 0) {
this.xhr.send('');
}
else if (typeof this.body[0] === 'string') {
this.xhr.send(this.body.join(''));
}
else if (isArray(this.body[0])) {
var body = [];
for (var i = 0; i < this.body.length; i++) {
body.push.apply(body, this.body[i]);
}
this.xhr.send(body);
}
else if (/Array/.test(Object.prototype.toString.call(this.body[0]))) {
var len = 0;
for (var i = 0; i < this.body.length; i++) {
len += this.body[i].length;
}
var body = new(this.body[0].constructor)(len);
var k = 0;
for (var i = 0; i < this.body.length; i++) {
var b = this.body[i];
for (var j = 0; j < b.length; j++) {
body[k++] = b[j];
}
}
this.xhr.send(body);
}
else {
var body = '';
for (var i = 0; i < this.body.length; i++) {
body += this.body[i].toString();
}
this.xhr.send(body);
}
};
// Taken from http://dxr.mozilla.org/mozilla/mozilla-central/content/base/src/nsXMLHttpRequest.cpp.html
Request.unsafeHeaders = [
"accept-charset",
"accept-encoding",
"access-control-request-headers",
"access-control-request-method",
"connection",
"content-length",
"cookie",
"cookie2",
"content-transfer-encoding",
"date",
"expect",
"host",
"keep-alive",
"origin",
"referer",
"te",
"trailer",
"transfer-encoding",
"upgrade",
"user-agent",
"via"
];
Request.prototype.isSafeRequestHeader = function (headerName) {
if (!headerName) return false;
return indexOf(Request.unsafeHeaders, headerName.toLowerCase()) === -1;
};
var objectKeys = Object.keys || function (obj) {
var keys = [];
for (var key in obj) keys.push(key);
return keys;
};
var isArray = Array.isArray || function (xs) {
return Object.prototype.toString.call(xs) === '[object Array]';
};
var indexOf = function (xs, x) {
if (xs.indexOf) return xs.indexOf(x);
for (var i = 0; i < xs.length; i++) {
if (xs[i] === x) return i;
}
return -1;
};
},{"./response":140,"Base64":141,"inherits":143,"stream":150}],140:[function(_dereq_,module,exports){
var Stream = _dereq_('stream');
var util = _dereq_('util');
var Response = module.exports = function (res) {
this.offset = 0;
this.readable = true;
};
util.inherits(Response, Stream);
var capable = {
streaming : true,
status2 : true
};
function parseHeaders (res) {
var lines = res.getAllResponseHeaders().split(/\r?\n/);
var headers = {};
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
if (line === '') continue;
var m = line.match(/^([^:]+):\s*(.*)/);
if (m) {
var key = m[1].toLowerCase(), value = m[2];
if (headers[key] !== undefined) {
if (isArray(headers[key])) {
headers[key].push(value);
}
else {
headers[key] = [ headers[key], value ];
}
}
else {
headers[key] = value;
}
}
else {
headers[line] = true;
}
}
return headers;
}
Response.prototype.getResponse = function (xhr) {
var respType = String(xhr.responseType).toLowerCase();
if (respType === 'blob') return xhr.responseBlob || xhr.response;
if (respType === 'arraybuffer') return xhr.response;
return xhr.responseText;
}
Response.prototype.getHeader = function (key) {
return this.headers[key.toLowerCase()];
};
Response.prototype.handle = function (res) {
if (res.readyState === 2 && capable.status2) {
try {
this.statusCode = res.status;
this.headers = parseHeaders(res);
}
catch (err) {
capable.status2 = false;
}
if (capable.status2) {
this.emit('ready');
}
}
else if (capable.streaming && res.readyState === 3) {
try {
if (!this.statusCode) {
this.statusCode = res.status;
this.headers = parseHeaders(res);
this.emit('ready');
}
}
catch (err) {}
try {
this._emitData(res);
}
catch (err) {
capable.streaming = false;
}
}
else if (res.readyState === 4) {
if (!this.statusCode) {
this.statusCode = res.status;
this.emit('ready');
}
this._emitData(res);
if (res.error) {
this.emit('error', this.getResponse(res));
}
else this.emit('end');
this.emit('close');
}
};
Response.prototype._emitData = function (res) {
var respBody = this.getResponse(res);
if (respBody.toString().match(/ArrayBuffer/)) {
this.emit('data', new Uint8Array(respBody, this.offset));
this.offset = respBody.byteLength;
return;
}
if (respBody.length > this.offset) {
this.emit('data', respBody.slice(this.offset));
this.offset = respBody.length;
}
};
var isArray = Array.isArray || function (xs) {
return Object.prototype.toString.call(xs) === '[object Array]';
};
},{"stream":150,"util":159}],141:[function(_dereq_,module,exports){
;(function () {
var object = typeof exports != 'undefined' ? exports : this; // #8: web workers
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
function InvalidCharacterError(message) {
this.message = message;
}
InvalidCharacterError.prototype = new Error;
InvalidCharacterError.prototype.name = 'InvalidCharacterError';
// encoder
// [https://gist.github.com/999166] by [https://github.com/nignag]
object.btoa || (
object.btoa = function (input) {
for (
// initialize result and counter
var block, charCode, idx = 0, map = chars, output = '';
// if the next input index does not exist:
// change the mapping table to "="
// check if d has no fractional digits
input.charAt(idx | 0) || (map = '=', idx % 1);
// "8 - idx % 1 * 8" generates the sequence 2, 4, 6, 8
output += map.charAt(63 & block >> 8 - idx % 1 * 8)
) {
charCode = input.charCodeAt(idx += 3/4);
if (charCode > 0xFF) {
throw new InvalidCharacterError("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.");
}
block = block << 8 | charCode;
}
return output;
});
// decoder
// [https://gist.github.com/1020396] by [https://github.com/atk]
object.atob || (
object.atob = function (input) {
input = input.replace(/=+$/, '');
if (input.length % 4 == 1) {
throw new InvalidCharacterError("'atob' failed: The string to be decoded is not correctly encoded.");
}
for (
// initialize result and counters
var bc = 0, bs, buffer, idx = 0, output = '';
// get next character
buffer = input.charAt(idx++);
// character found in table? initialize bit storage and add its ascii value;
~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,
// and if not first of each 4 characters,
// convert the first 8 bits to one ascii character
bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0
) {
// try to find character in table (0-63, not found => -1)
buffer = chars.indexOf(buffer);
}
return output;
});
}());
},{}],142:[function(_dereq_,module,exports){
var http = _dereq_('http');
var https = module.exports;
for (var key in http) {
if (http.hasOwnProperty(key)) https[key] = http[key];
};
https.request = function (params, cb) {
if (!params) params = {};
params.scheme = 'https';
return http.request.call(this, params, cb);
}
},{"http":138}],143:[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
}
}
},{}],144:[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 = [];
function noop() {}
process.on = noop;
process.once = noop;
process.off = noop;
process.emit = noop;
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');
};
},{}],145:[function(_dereq_,module,exports){
(function (global){
/*! http://mths.be/punycode v1.2.4 by @mathias */
;(function(root) {
/** Detect free variables */
var freeExports = typeof exports == 'object' && exports;
var freeModule = typeof module == 'object' && module &&
module.exports == freeExports && module;
var freeGlobal = typeof global == 'object' && global;
if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
root = freeGlobal;
}
/**
* The `punycode` object.
* @name punycode
* @type Object
*/
var punycode,
/** Highest positive signed 32-bit float value */
maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
/** Bootstring parameters */
base = 36,
tMin = 1,
tMax = 26,
skew = 38,
damp = 700,
initialBias = 72,
initialN = 128, // 0x80
delimiter = '-', // '\x2D'
/** Regular expressions */
regexPunycode = /^xn--/,
regexNonASCII = /[^ -~]/, // unprintable ASCII chars + non-ASCII chars
regexSeparators = /\x2E|\u3002|\uFF0E|\uFF61/g, // RFC 3490 separators
/** Error messages */
errors = {
'overflow': 'Overflow: input needs wider integers to process',
'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
'invalid-input': 'Invalid input'
},
/** Convenience shortcuts */
baseMinusTMin = base - tMin,
floor = Math.floor,
stringFromCharCode = String.fromCharCode,
/** Temporary variable */
key;
/*--------------------------------------------------------------------------*/
/**
* A generic error utility function.
* @private
* @param {String} type The error type.
* @returns {Error} Throws a `RangeError` with the applicable error message.
*/
function error(type) {
throw RangeError(errors[type]);
}
/**
* A generic `Array#map` utility function.
* @private
* @param {Array} array The array to iterate over.
* @param {Function} callback The function that gets called for every array
* item.
* @returns {Array} A new array of values returned by the callback function.
*/
function map(array, fn) {
var length = array.length;
while (length--) {
array[length] = fn(array[length]);
}
return array;
}
/**
* A simple `Array#map`-like wrapper to work with domain name strings.
* @private
* @param {String} domain The domain name.
* @param {Function} callback The function that gets called for every
* character.
* @returns {Array} A new string of characters returned by the callback
* function.
*/
function mapDomain(string, fn) {
return map(string.split(regexSeparators), fn).join('.');
}
/**
* Creates an array containing the numeric code points of each Unicode
* character in the string. While JavaScript uses UCS-2 internally,
* this function will convert a pair of surrogate halves (each of which
* UCS-2 exposes as separate characters) into a single code point,
* matching UTF-16.
* @see `punycode.ucs2.encode`
* @see <http://mathiasbynens.be/notes/javascript-encoding>
* @memberOf punycode.ucs2
* @name decode
* @param {String} string The Unicode input string (UCS-2).
* @returns {Array} The new array of code points.
*/
function ucs2decode(string) {
var output = [],
counter = 0,
length = string.length,
value,
extra;
while (counter < length) {
value = string.charCodeAt(counter++);
if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
// high surrogate, and there is a next character
extra = string.charCodeAt(counter++);
if ((extra & 0xFC00) == 0xDC00) { // low surrogate
output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
} else {
// unmatched surrogate; only append this code unit, in case the next
// code unit is the high surrogate of a surrogate pair
output.push(value);
counter--;
}
} else {
output.push(value);
}
}
return output;
}
/**
* Creates a string based on an array of numeric code points.
* @see `punycode.ucs2.decode`
* @memberOf punycode.ucs2
* @name encode
* @param {Array} codePoints The array of numeric code points.
* @returns {String} The new Unicode string (UCS-2).
*/
function ucs2encode(array) {
return map(array, function(value) {
var output = '';
if (value > 0xFFFF) {
value -= 0x10000;
output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
value = 0xDC00 | value & 0x3FF;
}
output += stringFromCharCode(value);
return output;
}).join('');
}
/**
* Converts a basic code point into a digit/integer.
* @see `digitToBasic()`
* @private
* @param {Number} codePoint The basic numeric code point value.
* @returns {Number} The numeric value of a basic code point (for use in
* representing integers) in the range `0` to `base - 1`, or `base` if
* the code point does not represent a value.
*/
function basicToDigit(codePoint) {
if (codePoint - 48 < 10) {
return codePoint - 22;
}
if (codePoint - 65 < 26) {
return codePoint - 65;
}
if (codePoint - 97 < 26) {
return codePoint - 97;
}
return base;
}
/**
* Converts a digit/integer into a basic code point.
* @see `basicToDigit()`
* @private
* @param {Number} digit The numeric value of a basic code point.
* @returns {Number} The basic code point whose value (when used for
* representing integers) is `digit`, which needs to be in the range
* `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
* used; else, the lowercase form is used. The behavior is undefined
* if `flag` is non-zero and `digit` has no uppercase form.
*/
function digitToBasic(digit, flag) {
// 0..25 map to ASCII a..z or A..Z
// 26..35 map to ASCII 0..9
return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
}
/**
* Bias adaptation function as per section 3.4 of RFC 3492.
* http://tools.ietf.org/html/rfc3492#section-3.4
* @private
*/
function adapt(delta, numPoints, firstTime) {
var k = 0;
delta = firstTime ? floor(delta / damp) : delta >> 1;
delta += floor(delta / numPoints);
for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
delta = floor(delta / baseMinusTMin);
}
return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
}
/**
* Converts a Punycode string of ASCII-only symbols to a string of Unicode
* symbols.
* @memberOf punycode
* @param {String} input The Punycode string of ASCII-only symbols.
* @returns {String} The resulting string of Unicode symbols.
*/
function decode(input) {
// Don't use UCS-2
var output = [],
inputLength = input.length,
out,
i = 0,
n = initialN,
bias = initialBias,
basic,
j,
index,
oldi,
w,
k,
digit,
t,
/** Cached calculation results */
baseMinusT;
// Handle the basic code points: let `basic` be the number of input code
// points before the last delimiter, or `0` if there is none, then copy
// the first basic code points to the output.
basic = input.lastIndexOf(delimiter);
if (basic < 0) {
basic = 0;
}
for (j = 0; j < basic; ++j) {
// if it's not a basic code point
if (input.charCodeAt(j) >= 0x80) {
error('not-basic');
}
output.push(input.charCodeAt(j));
}
// Main decoding loop: start just after the last delimiter if any basic code
// points were copied; start at the beginning otherwise.
for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
// `index` is the index of the next character to be consumed.
// Decode a generalized variable-length integer into `delta`,
// which gets added to `i`. The overflow checking is easier
// if we increase `i` as we go, then subtract off its starting
// value at the end to obtain `delta`.
for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
if (index >= inputLength) {
error('invalid-input');
}
digit = basicToDigit(input.charCodeAt(index++));
if (digit >= base || digit > floor((maxInt - i) / w)) {
error('overflow');
}
i += digit * w;
t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
if (digit < t) {
break;
}
baseMinusT = base - t;
if (w > floor(maxInt / baseMinusT)) {
error('overflow');
}
w *= baseMinusT;
}
out = output.length + 1;
bias = adapt(i - oldi, out, oldi == 0);
// `i` was supposed to wrap around from `out` to `0`,
// incrementing `n` each time, so we'll fix that now:
if (floor(i / out) > maxInt - n) {
error('overflow');
}
n += floor(i / out);
i %= out;
// Insert `n` at position `i` of the output
output.splice(i++, 0, n);
}
return ucs2encode(output);
}
/**
* Converts a string of Unicode symbols to a Punycode string of ASCII-only
* symbols.
* @memberOf punycode
* @param {String} input The string of Unicode symbols.
* @returns {String} The resulting Punycode string of ASCII-only symbols.
*/
function encode(input) {
var n,
delta,
handledCPCount,
basicLength,
bias,
j,
m,
q,
k,
t,
currentValue,
output = [],
/** `inputLength` will hold the number of code points in `input`. */
inputLength,
/** Cached calculation results */
handledCPCountPlusOne,
baseMinusT,
qMinusT;
// Convert the input in UCS-2 to Unicode
input = ucs2decode(input);
// Cache the length
inputLength = input.length;
// Initialize the state
n = initialN;
delta = 0;
bias = initialBias;
// Handle the basic code points
for (j = 0; j < inputLength; ++j) {
currentValue = input[j];
if (currentValue < 0x80) {
output.push(stringFromCharCode(currentValue));
}
}
handledCPCount = basicLength = output.length;
// `handledCPCount` is the number of code points that have been handled;
// `basicLength` is the number of basic code points.
// Finish the basic string - if it is not empty - with a delimiter
if (basicLength) {
output.push(delimiter);
}
// Main encoding loop:
while (handledCPCount < inputLength) {
// All non-basic code points < n have been handled already. Find the next
// larger one:
for (m = maxInt, j = 0; j < inputLength; ++j) {
currentValue = input[j];
if (currentValue >= n && currentValue < m) {
m = currentValue;
}
}
// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
// but guard against overflow
handledCPCountPlusOne = handledCPCount + 1;
if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
error('overflow');
}
delta += (m - n) * handledCPCountPlusOne;
n = m;
for (j = 0; j < inputLength; ++j) {
currentValue = input[j];
if (currentValue < n && ++delta > maxInt) {
error('overflow');
}
if (currentValue == n) {
// Represent delta as a generalized variable-length integer
for (q = delta, k = base; /* no condition */; k += base) {
t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
if (q < t) {
break;
}
qMinusT = q - t;
baseMinusT = base - t;
output.push(
stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
);
q = floor(qMinusT / baseMinusT);
}
output.push(stringFromCharCode(digitToBasic(q, 0)));
bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
delta = 0;
++handledCPCount;
}
}
++delta;
++n;
}
return output.join('');
}
/**
* Converts a Punycode string representing a domain name to Unicode. Only the
* Punycoded parts of the domain name will be converted, i.e. it doesn't
* matter if you call it on a string that has already been converted to
* Unicode.
* @memberOf punycode
* @param {String} domain The Punycode domain name to convert to Unicode.
* @returns {String} The Unicode representation of the given Punycode
* string.
*/
function toUnicode(domain) {
return mapDomain(domain, function(string) {
return regexPunycode.test(string)
? decode(string.slice(4).toLowerCase())
: string;
});
}
/**
* Converts a Unicode string representing a domain name to Punycode. Only the
* non-ASCII parts of the domain name will be converted, i.e. it doesn't
* matter if you call it with a domain that's already in ASCII.
* @memberOf punycode
* @param {String} domain The domain name to convert, as a Unicode string.
* @returns {String} The Punycode representation of the given domain name.
*/
function toASCII(domain) {
return mapDomain(domain, function(string) {
return regexNonASCII.test(string)
? 'xn--' + encode(string)
: string;
});
}
/*--------------------------------------------------------------------------*/
/** Define the public API */
punycode = {
/**
* A string representing the current Punycode.js version number.
* @memberOf punycode
* @type String
*/
'version': '1.2.4',
/**
* An object of methods to convert from JavaScript's internal character
* representation (UCS-2) to Unicode code points, and back.
* @see <http://mathiasbynens.be/notes/javascript-encoding>
* @memberOf punycode
* @type Object
*/
'ucs2': {
'decode': ucs2decode,
'encode': ucs2encode
},
'decode': decode,
'encode': encode,
'toASCII': toASCII,
'toUnicode': toUnicode
};
/** Expose `punycode` */
// Some AMD build optimizers, like r.js, check for specific condition patterns
// like the following:
if (
typeof define == 'function' &&
typeof define.amd == 'object' &&
define.amd
) {
define('punycode', function() {
return punycode;
});
} else if (freeExports && !freeExports.nodeType) {
if (freeModule) { // in Node.js or RingoJS v0.8.0+
freeModule.exports = punycode;
} else { // in Narwhal or RingoJS v0.7.0-
for (key in punycode) {
punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
}
}
} else { // in Rhino or a web browser
root.punycode = punycode;
}
}(this));
}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],146:[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.
'use strict';
// If obj.hasOwnProperty has been overridden, then calling
// obj.hasOwnProperty(prop) will break.
// See: https://github.com/joyent/node/issues/1707
function hasOwnProperty(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
module.exports = function(qs, sep, eq, options) {
sep = sep || '&';
eq = eq || '=';
var obj = {};
if (typeof qs !== 'string' || qs.length === 0) {
return obj;
}
var regexp = /\+/g;
qs = qs.split(sep);
var maxKeys = 1000;
if (options && typeof options.maxKeys === 'number') {
maxKeys = options.maxKeys;
}
var len = qs.length;
// maxKeys <= 0 means that we should not limit keys count
if (maxKeys > 0 && len > maxKeys) {
len = maxKeys;
}
for (var i = 0; i < len; ++i) {
var x = qs[i].replace(regexp, '%20'),
idx = x.indexOf(eq),
kstr, vstr, k, v;
if (idx >= 0) {
kstr = x.substr(0, idx);
vstr = x.substr(idx + 1);
} else {
kstr = x;
vstr = '';
}
k = decodeURIComponent(kstr);
v = decodeURIComponent(vstr);
if (!hasOwnProperty(obj, k)) {
obj[k] = v;
} else if (isArray(obj[k])) {
obj[k].push(v);
} else {
obj[k] = [obj[k], v];
}
}
return obj;
};
var isArray = Array.isArray || function (xs) {
return Object.prototype.toString.call(xs) === '[object Array]';
};
},{}],147:[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.
'use strict';
var stringifyPrimitive = function(v) {
switch (typeof v) {
case 'string':
return v;
case 'boolean':
return v ? 'true' : 'false';
case 'number':
return isFinite(v) ? v : '';
default:
return '';
}
};
module.exports = function(obj, sep, eq, name) {
sep = sep || '&';
eq = eq || '=';
if (obj === null) {
obj = undefined;
}
if (typeof obj === 'object') {
return map(objectKeys(obj), function(k) {
var ks = encodeURIComponent(stringifyPrimitive(k)) + eq;
if (isArray(obj[k])) {
return obj[k].map(function(v) {
return ks + encodeURIComponent(stringifyPrimitive(v));
}).join(sep);
} else {
return ks + encodeURIComponent(stringifyPrimitive(obj[k]));
}
}).join(sep);
}
if (!name) return '';
return encodeURIComponent(stringifyPrimitive(name)) + eq +
encodeURIComponent(stringifyPrimitive(obj));
};
var isArray = Array.isArray || function (xs) {
return Object.prototype.toString.call(xs) === '[object Array]';
};
function map (xs, f) {
if (xs.map) return xs.map(f);
var res = [];
for (var i = 0; i < xs.length; i++) {
res.push(f(xs[i], i));
}
return res;
}
var objectKeys = Object.keys || function (obj) {
var res = [];
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key);
}
return res;
};
},{}],148:[function(_dereq_,module,exports){
'use strict';
exports.decode = exports.parse = _dereq_('./decode');
exports.encode = exports.stringify = _dereq_('./encode');
},{"./decode":146,"./encode":147}],149:[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.
// a duplex stream is just a stream that is both readable and writable.
// Since JS doesn't have multiple prototypal inheritance, this class
// prototypally inherits from Readable, and then parasitically from
// Writable.
module.exports = Duplex;
var inherits = _dereq_('inherits');
var setImmediate = _dereq_('process/browser.js').nextTick;
var Readable = _dereq_('./readable.js');
var Writable = _dereq_('./writable.js');
inherits(Duplex, Readable);
Duplex.prototype.write = Writable.prototype.write;
Duplex.prototype.end = Writable.prototype.end;
Duplex.prototype._write = Writable.prototype._write;
function Duplex(options) {
if (!(this instanceof Duplex))
return new Duplex(options);
Readable.call(this, options);
Writable.call(this, options);
if (options && options.readable === false)
this.readable = false;
if (options && options.writable === false)
this.writable = false;
this.allowHalfOpen = true;
if (options && options.allowHalfOpen === false)
this.allowHalfOpen = false;
this.once('end', onend);
}
// the no-half-open enforcer
function onend() {
// if we allow half-open state, or if the writable side ended,
// then we're ok.
if (this.allowHalfOpen || this._writableState.ended)
return;
// no more data can be written.
// But allow more writes to happen in this tick.
var self = this;
setImmediate(function () {
self.end();
});
}
},{"./readable.js":153,"./writable.js":155,"inherits":143,"process/browser.js":151}],150:[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.
module.exports = Stream;
var EE = _dereq_('events').EventEmitter;
var inherits = _dereq_('inherits');
inherits(Stream, EE);
Stream.Readable = _dereq_('./readable.js');
Stream.Writable = _dereq_('./writable.js');
Stream.Duplex = _dereq_('./duplex.js');
Stream.Transform = _dereq_('./transform.js');
Stream.PassThrough = _dereq_('./passthrough.js');
// Backwards-compat with node 0.4.x
Stream.Stream = Stream;
// old-style streams. Note that the pipe method (the only relevant
// part of this class) is overridden in the Readable class.
function Stream() {
EE.call(this);
}
Stream.prototype.pipe = function(dest, options) {
var source = this;
function ondata(chunk) {
if (dest.writable) {
if (false === dest.write(chunk) && source.pause) {
source.pause();
}
}
}
source.on('data', ondata);
function ondrain() {
if (source.readable && source.resume) {
source.resume();
}
}
dest.on('drain', ondrain);
// If the 'end' option is not supplied, dest.end() will be called when
// source gets the 'end' or 'close' events. Only dest.end() once.
if (!dest._isStdio && (!options || options.end !== false)) {
source.on('end', onend);
source.on('close', onclose);
}
var didOnEnd = false;
function onend() {
if (didOnEnd) return;
didOnEnd = true;
dest.end();
}
function onclose() {
if (didOnEnd) return;
didOnEnd = true;
if (typeof dest.destroy === 'function') dest.destroy();
}
// don't leave dangling pipes when there are errors.
function onerror(er) {
cleanup();
if (EE.listenerCount(this, 'error') === 0) {
throw er; // Unhandled stream error in pipe.
}
}
source.on('error', onerror);
dest.on('error', onerror);
// remove all the event listeners that were added.
function cleanup() {
source.removeListener('data', ondata);
dest.removeListener('drain', ondrain);
source.removeListener('end', onend);
source.removeListener('close', onclose);
source.removeListener('error', onerror);
dest.removeListener('error', onerror);
source.removeListener('end', cleanup);
source.removeListener('close', cleanup);
dest.removeListener('close', cleanup);
}
source.on('end', cleanup);
source.on('close', cleanup);
dest.on('close', cleanup);
dest.emit('pipe', source);
// Allow for unix-like usage: A.pipe(B).pipe(C)
return dest;
};
},{"./duplex.js":149,"./passthrough.js":152,"./readable.js":153,"./transform.js":154,"./writable.js":155,"events":137,"inherits":143}],151:[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');
};
},{}],152:[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.
// a passthrough stream.
// basically just the most minimal sort of Transform stream.
// Every written chunk gets output as-is.
module.exports = PassThrough;
var Transform = _dereq_('./transform.js');
var inherits = _dereq_('inherits');
inherits(PassThrough, Transform);
function PassThrough(options) {
if (!(this instanceof PassThrough))
return new PassThrough(options);
Transform.call(this, options);
}
PassThrough.prototype._transform = function(chunk, encoding, cb) {
cb(null, chunk);
};
},{"./transform.js":154,"inherits":143}],153:[function(_dereq_,module,exports){
(function (process){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
module.exports = Readable;
Readable.ReadableState = ReadableState;
var EE = _dereq_('events').EventEmitter;
var Stream = _dereq_('./index.js');
var Buffer = _dereq_('buffer').Buffer;
var setImmediate = _dereq_('process/browser.js').nextTick;
var StringDecoder;
var inherits = _dereq_('inherits');
inherits(Readable, Stream);
function ReadableState(options, stream) {
options = options || {};
// the point at which it stops calling _read() to fill the buffer
// Note: 0 is a valid value, means "don't call _read preemptively ever"
var hwm = options.highWaterMark;
this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024;
// cast to ints.
this.highWaterMark = ~~this.highWaterMark;
this.buffer = [];
this.length = 0;
this.pipes = null;
this.pipesCount = 0;
this.flowing = false;
this.ended = false;
this.endEmitted = false;
this.reading = false;
// In streams that never have any data, and do push(null) right away,
// the consumer can miss the 'end' event if they do some I/O before
// consuming the stream. So, we don't emit('end') until some reading
// happens.
this.calledRead = false;
// a flag to be able to tell if the onwrite cb is called immediately,
// or on a later tick. We set this to true at first, becuase any
// actions that shouldn't happen until "later" should generally also
// not happen before the first write call.
this.sync = true;
// whenever we return null, then we set a flag to say
// that we're awaiting a 'readable' event emission.
this.needReadable = false;
this.emittedReadable = false;
this.readableListening = false;
// object stream flag. Used to make read(n) ignore n and to
// make all the buffer merging and length checks go away
this.objectMode = !!options.objectMode;
// Crypto is kind of old and crusty. Historically, its default string
// encoding is 'binary' so we have to make this configurable.
// Everything else in the universe uses 'utf8', though.
this.defaultEncoding = options.defaultEncoding || 'utf8';
// when piping, we only care about 'readable' events that happen
// after read()ing all the bytes and not getting any pushback.
this.ranOut = false;
// the number of writers that are awaiting a drain event in .pipe()s
this.awaitDrain = 0;
// if true, a maybeReadMore has been scheduled
this.readingMore = false;
this.decoder = null;
this.encoding = null;
if (options.encoding) {
if (!StringDecoder)
StringDecoder = _dereq_('string_decoder').StringDecoder;
this.decoder = new StringDecoder(options.encoding);
this.encoding = options.encoding;
}
}
function Readable(options) {
if (!(this instanceof Readable))
return new Readable(options);
this._readableState = new ReadableState(options, this);
// legacy
this.readable = true;
Stream.call(this);
}
// Manually shove something into the read() buffer.
// This returns true if the highWaterMark has not been hit yet,
// similar to how Writable.write() returns true if you should
// write() some more.
Readable.prototype.push = function(chunk, encoding) {
var state = this._readableState;
if (typeof chunk === 'string' && !state.objectMode) {
encoding = encoding || state.defaultEncoding;
if (encoding !== state.encoding) {
chunk = new Buffer(chunk, encoding);
encoding = '';
}
}
return readableAddChunk(this, state, chunk, encoding, false);
};
// Unshift should *always* be something directly out of read()
Readable.prototype.unshift = function(chunk) {
var state = this._readableState;
return readableAddChunk(this, state, chunk, '', true);
};
function readableAddChunk(stream, state, chunk, encoding, addToFront) {
var er = chunkInvalid(state, chunk);
if (er) {
stream.emit('error', er);
} else if (chunk === null || chunk === undefined) {
state.reading = false;
if (!state.ended)
onEofChunk(stream, state);
} else if (state.objectMode || chunk && chunk.length > 0) {
if (state.ended && !addToFront) {
var e = new Error('stream.push() after EOF');
stream.emit('error', e);
} else if (state.endEmitted && addToFront) {
var e = new Error('stream.unshift() after end event');
stream.emit('error', e);
} else {
if (state.decoder && !addToFront && !encoding)
chunk = state.decoder.write(chunk);
// update the buffer info.
state.length += state.objectMode ? 1 : chunk.length;
if (addToFront) {
state.buffer.unshift(chunk);
} else {
state.reading = false;
state.buffer.push(chunk);
}
if (state.needReadable)
emitReadable(stream);
maybeReadMore(stream, state);
}
} else if (!addToFront) {
state.reading = false;
}
return needMoreData(state);
}
// if it's past the high water mark, we can push in some more.
// Also, if we have no data yet, we can stand some
// more bytes. This is to work around cases where hwm=0,
// such as the repl. Also, if the push() triggered a
// readable event, and the user called read(largeNumber) such that
// needReadable was set, then we ought to push more, so that another
// 'readable' event will be triggered.
function needMoreData(state) {
return !state.ended &&
(state.needReadable ||
state.length < state.highWaterMark ||
state.length === 0);
}
// backwards compatibility.
Readable.prototype.setEncoding = function(enc) {
if (!StringDecoder)
StringDecoder = _dereq_('string_decoder').StringDecoder;
this._readableState.decoder = new StringDecoder(enc);
this._readableState.encoding = enc;
};
// Don't raise the hwm > 128MB
var MAX_HWM = 0x800000;
function roundUpToNextPowerOf2(n) {
if (n >= MAX_HWM) {
n = MAX_HWM;
} else {
// Get the next highest power of 2
n--;
for (var p = 1; p < 32; p <<= 1) n |= n >> p;
n++;
}
return n;
}
function howMuchToRead(n, state) {
if (state.length === 0 && state.ended)
return 0;
if (state.objectMode)
return n === 0 ? 0 : 1;
if (isNaN(n) || n === null) {
// only flow one buffer at a time
if (state.flowing && state.buffer.length)
return state.buffer[0].length;
else
return state.length;
}
if (n <= 0)
return 0;
// If we're asking for more than the target buffer level,
// then raise the water mark. Bump up to the next highest
// power of 2, to prevent increasing it excessively in tiny
// amounts.
if (n > state.highWaterMark)
state.highWaterMark = roundUpToNextPowerOf2(n);
// don't have that much. return null, unless we've ended.
if (n > state.length) {
if (!state.ended) {
state.needReadable = true;
return 0;
} else
return state.length;
}
return n;
}
// you can override either this method, or the async _read(n) below.
Readable.prototype.read = function(n) {
var state = this._readableState;
state.calledRead = true;
var nOrig = n;
if (typeof n !== 'number' || n > 0)
state.emittedReadable = false;
// if we're doing read(0) to trigger a readable event, but we
// already have a bunch of data in the buffer, then just trigger
// the 'readable' event and move on.
if (n === 0 &&
state.needReadable &&
(state.length >= state.highWaterMark || state.ended)) {
emitReadable(this);
return null;
}
n = howMuchToRead(n, state);
// if we've ended, and we're now clear, then finish it up.
if (n === 0 && state.ended) {
if (state.length === 0)
endReadable(this);
return null;
}
// All the actual chunk generation logic needs to be
// *below* the call to _read. The reason is that in certain
// synthetic stream cases, such as passthrough streams, _read
// may be a completely synchronous operation which may change
// the state of the read buffer, providing enough data when
// before there was *not* enough.
//
// So, the steps are:
// 1. Figure out what the state of things will be after we do
// a read from the buffer.
//
// 2. If that resulting state will trigger a _read, then call _read.
// Note that this may be asynchronous, or synchronous. Yes, it is
// deeply ugly to write APIs this way, but that still doesn't mean
// that the Readable class should behave improperly, as streams are
// designed to be sync/async agnostic.
// Take note if the _read call is sync or async (ie, if the read call
// has returned yet), so that we know whether or not it's safe to emit
// 'readable' etc.
//
// 3. Actually pull the requested chunks out of the buffer and return.
// if we need a readable event, then we need to do some reading.
var doRead = state.needReadable;
// if we currently have less than the highWaterMark, then also read some
if (state.length - n <= state.highWaterMark)
doRead = true;
// however, if we've ended, then there's no point, and if we're already
// reading, then it's unnecessary.
if (state.ended || state.reading)
doRead = false;
if (doRead) {
state.reading = true;
state.sync = true;
// if the length is currently zero, then we *need* a readable event.
if (state.length === 0)
state.needReadable = true;
// call internal read method
this._read(state.highWaterMark);
state.sync = false;
}
// If _read called its callback synchronously, then `reading`
// will be false, and we need to re-evaluate how much data we
// can return to the user.
if (doRead && !state.reading)
n = howMuchToRead(nOrig, state);
var ret;
if (n > 0)
ret = fromList(n, state);
else
ret = null;
if (ret === null) {
state.needReadable = true;
n = 0;
}
state.length -= n;
// If we have nothing in the buffer, then we want to know
// as soon as we *do* get something into the buffer.
if (state.length === 0 && !state.ended)
state.needReadable = true;
// If we happened to read() exactly the remaining amount in the
// buffer, and the EOF has been seen at this point, then make sure
// that we emit 'end' on the very next tick.
if (state.ended && !state.endEmitted && state.length === 0)
endReadable(this);
return ret;
};
function chunkInvalid(state, chunk) {
var er = null;
if (!Buffer.isBuffer(chunk) &&
'string' !== typeof chunk &&
chunk !== null &&
chunk !== undefined &&
!state.objectMode &&
!er) {
er = new TypeError('Invalid non-string/buffer chunk');
}
return er;
}
function onEofChunk(stream, state) {
if (state.decoder && !state.ended) {
var chunk = state.decoder.end();
if (chunk && chunk.length) {
state.buffer.push(chunk);
state.length += state.objectMode ? 1 : chunk.length;
}
}
state.ended = true;
// if we've ended and we have some data left, then emit
// 'readable' now to make sure it gets picked up.
if (state.length > 0)
emitReadable(stream);
else
endReadable(stream);
}
// Don't emit readable right away in sync mode, because this can trigger
// another read() call => stack overflow. This way, it might trigger
// a nextTick recursion warning, but that's not so bad.
function emitReadable(stream) {
var state = stream._readableState;
state.needReadable = false;
if (state.emittedReadable)
return;
state.emittedReadable = true;
if (state.sync)
setImmediate(function() {
emitReadable_(stream);
});
else
emitReadable_(stream);
}
function emitReadable_(stream) {
stream.emit('readable');
}
// at this point, the user has presumably seen the 'readable' event,
// and called read() to consume some data. that may have triggered
// in turn another _read(n) call, in which case reading = true if
// it's in progress.
// However, if we're not ended, or reading, and the length < hwm,
// then go ahead and try to read some more preemptively.
function maybeReadMore(stream, state) {
if (!state.readingMore) {
state.readingMore = true;
setImmediate(function() {
maybeReadMore_(stream, state);
});
}
}
function maybeReadMore_(stream, state) {
var len = state.length;
while (!state.reading && !state.flowing && !state.ended &&
state.length < state.highWaterMark) {
stream.read(0);
if (len === state.length)
// didn't get any data, stop spinning.
break;
else
len = state.length;
}
state.readingMore = false;
}
// abstract method. to be overridden in specific implementation classes.
// call cb(er, data) where data is <= n in length.
// for virtual (non-string, non-buffer) streams, "length" is somewhat
// arbitrary, and perhaps not very meaningful.
Readable.prototype._read = function(n) {
this.emit('error', new Error('not implemented'));
};
Readable.prototype.pipe = function(dest, pipeOpts) {
var src = this;
var state = this._readableState;
switch (state.pipesCount) {
case 0:
state.pipes = dest;
break;
case 1:
state.pipes = [state.pipes, dest];
break;
default:
state.pipes.push(dest);
break;
}
state.pipesCount += 1;
var doEnd = (!pipeOpts || pipeOpts.end !== false) &&
dest !== process.stdout &&
dest !== process.stderr;
var endFn = doEnd ? onend : cleanup;
if (state.endEmitted)
setImmediate(endFn);
else
src.once('end', endFn);
dest.on('unpipe', onunpipe);
function onunpipe(readable) {
if (readable !== src) return;
cleanup();
}
function onend() {
dest.end();
}
// when the dest drains, it reduces the awaitDrain counter
// on the source. This would be more elegant with a .once()
// handler in flow(), but adding and removing repeatedly is
// too slow.
var ondrain = pipeOnDrain(src);
dest.on('drain', ondrain);
function cleanup() {
// cleanup event handlers once the pipe is broken
dest.removeListener('close', onclose);
dest.removeListener('finish', onfinish);
dest.removeListener('drain', ondrain);
dest.removeListener('error', onerror);
dest.removeListener('unpipe', onunpipe);
src.removeListener('end', onend);
src.removeListener('end', cleanup);
// if the reader is waiting for a drain event from this
// specific writer, then it would cause it to never start
// flowing again.
// So, if this is awaiting a drain, then we just call it now.
// If we don't know, then assume that we are waiting for one.
if (!dest._writableState || dest._writableState.needDrain)
ondrain();
}
// if the dest has an error, then stop piping into it.
// however, don't suppress the throwing behavior for this.
// check for listeners before emit removes one-time listeners.
var errListeners = EE.listenerCount(dest, 'error');
function onerror(er) {
unpipe();
if (errListeners === 0 && EE.listenerCount(dest, 'error') === 0)
dest.emit('error', er);
}
dest.once('error', onerror);
// Both close and finish should trigger unpipe, but only once.
function onclose() {
dest.removeListener('finish', onfinish);
unpipe();
}
dest.once('close', onclose);
function onfinish() {
dest.removeListener('close', onclose);
unpipe();
}
dest.once('finish', onfinish);
function unpipe() {
src.unpipe(dest);
}
// tell the dest that it's being piped to
dest.emit('pipe', src);
// start the flow if it hasn't been started already.
if (!state.flowing) {
// the handler that waits for readable events after all
// the data gets sucked out in flow.
// This would be easier to follow with a .once() handler
// in flow(), but that is too slow.
this.on('readable', pipeOnReadable);
state.flowing = true;
setImmediate(function() {
flow(src);
});
}
return dest;
};
function pipeOnDrain(src) {
return function() {
var dest = this;
var state = src._readableState;
state.awaitDrain--;
if (state.awaitDrain === 0)
flow(src);
};
}
function flow(src) {
var state = src._readableState;
var chunk;
state.awaitDrain = 0;
function write(dest, i, list) {
var written = dest.write(chunk);
if (false === written) {
state.awaitDrain++;
}
}
while (state.pipesCount && null !== (chunk = src.read())) {
if (state.pipesCount === 1)
write(state.pipes, 0, null);
else
forEach(state.pipes, write);
src.emit('data', chunk);
// if anyone needs a drain, then we have to wait for that.
if (state.awaitDrain > 0)
return;
}
// if every destination was unpiped, either before entering this
// function, or in the while loop, then stop flowing.
//
// NB: This is a pretty rare edge case.
if (state.pipesCount === 0) {
state.flowing = false;
// if there were data event listeners added, then switch to old mode.
if (EE.listenerCount(src, 'data') > 0)
emitDataEvents(src);
return;
}
// at this point, no one needed a drain, so we just ran out of data
// on the next readable event, start it over again.
state.ranOut = true;
}
function pipeOnReadable() {
if (this._readableState.ranOut) {
this._readableState.ranOut = false;
flow(this);
}
}
Readable.prototype.unpipe = function(dest) {
var state = this._readableState;
// if we're not piping anywhere, then do nothing.
if (state.pipesCount === 0)
return this;
// just one destination. most common case.
if (state.pipesCount === 1) {
// passed in one, but it's not the right one.
if (dest && dest !== state.pipes)
return this;
if (!dest)
dest = state.pipes;
// got a match.
state.pipes = null;
state.pipesCount = 0;
this.removeListener('readable', pipeOnReadable);
state.flowing = false;
if (dest)
dest.emit('unpipe', this);
return this;
}
// slow case. multiple pipe destinations.
if (!dest) {
// remove all.
var dests = state.pipes;
var len = state.pipesCount;
state.pipes = null;
state.pipesCount = 0;
this.removeListener('readable', pipeOnReadable);
state.flowing = false;
for (var i = 0; i < len; i++)
dests[i].emit('unpipe', this);
return this;
}
// try to find the right one.
var i = indexOf(state.pipes, dest);
if (i === -1)
return this;
state.pipes.splice(i, 1);
state.pipesCount -= 1;
if (state.pipesCount === 1)
state.pipes = state.pipes[0];
dest.emit('unpipe', this);
return this;
};
// set up data events if they are asked for
// Ensure readable listeners eventually get something
Readable.prototype.on = function(ev, fn) {
var res = Stream.prototype.on.call(this, ev, fn);
if (ev === 'data' && !this._readableState.flowing)
emitDataEvents(this);
if (ev === 'readable' && this.readable) {
var state = this._readableState;
if (!state.readableListening) {
state.readableListening = true;
state.emittedReadable = false;
state.needReadable = true;
if (!state.reading) {
this.read(0);
} else if (state.length) {
emitReadable(this, state);
}
}
}
return res;
};
Readable.prototype.addListener = Readable.prototype.on;
// pause() and resume() are remnants of the legacy readable stream API
// If the user uses them, then switch into old mode.
Readable.prototype.resume = function() {
emitDataEvents(this);
this.read(0);
this.emit('resume');
};
Readable.prototype.pause = function() {
emitDataEvents(this, true);
this.emit('pause');
};
function emitDataEvents(stream, startPaused) {
var state = stream._readableState;
if (state.flowing) {
// https://github.com/isaacs/readable-stream/issues/16
throw new Error('Cannot switch to old mode now.');
}
var paused = startPaused || false;
var readable = false;
// convert to an old-style stream.
stream.readable = true;
stream.pipe = Stream.prototype.pipe;
stream.on = stream.addListener = Stream.prototype.on;
stream.on('readable', function() {
readable = true;
var c;
while (!paused && (null !== (c = stream.read())))
stream.emit('data', c);
if (c === null) {
readable = false;
stream._readableState.needReadable = true;
}
});
stream.pause = function() {
paused = true;
this.emit('pause');
};
stream.resume = function() {
paused = false;
if (readable)
setImmediate(function() {
stream.emit('readable');
});
else
this.read(0);
this.emit('resume');
};
// now make it start, just in case it hadn't already.
stream.emit('readable');
}
// wrap an old-style stream as the async data source.
// This is *not* part of the readable stream interface.
// It is an ugly unfortunate mess of history.
Readable.prototype.wrap = function(stream) {
var state = this._readableState;
var paused = false;
var self = this;
stream.on('end', function() {
if (state.decoder && !state.ended) {
var chunk = state.decoder.end();
if (chunk && chunk.length)
self.push(chunk);
}
self.push(null);
});
stream.on('data', function(chunk) {
if (state.decoder)
chunk = state.decoder.write(chunk);
if (!chunk || !state.objectMode && !chunk.length)
return;
var ret = self.push(chunk);
if (!ret) {
paused = true;
stream.pause();
}
});
// proxy all the other methods.
// important when wrapping filters and duplexes.
for (var i in stream) {
if (typeof stream[i] === 'function' &&
typeof this[i] === 'undefined') {
this[i] = function(method) { return function() {
return stream[method].apply(stream, arguments);
}}(i);
}
}
// proxy certain important events.
var events = ['error', 'close', 'destroy', 'pause', 'resume'];
forEach(events, function(ev) {
stream.on(ev, function (x) {
return self.emit.apply(self, ev, x);
});
});
// when we try to consume some more bytes, simply unpause the
// underlying stream.
self._read = function(n) {
if (paused) {
paused = false;
stream.resume();
}
};
return self;
};
// exposed for testing purposes only.
Readable._fromList = fromList;
// Pluck off n bytes from an array of buffers.
// Length is the combined lengths of all the buffers in the list.
function fromList(n, state) {
var list = state.buffer;
var length = state.length;
var stringMode = !!state.decoder;
var objectMode = !!state.objectMode;
var ret;
// nothing in the list, definitely empty.
if (list.length === 0)
return null;
if (length === 0)
ret = null;
else if (objectMode)
ret = list.shift();
else if (!n || n >= length) {
// read it all, truncate the array.
if (stringMode)
ret = list.join('');
else
ret = Buffer.concat(list, length);
list.length = 0;
} else {
// read just some of it.
if (n < list[0].length) {
// just take a part of the first list item.
// slice is the same for buffers and strings.
var buf = list[0];
ret = buf.slice(0, n);
list[0] = buf.slice(n);
} else if (n === list[0].length) {
// first list is a perfect match
ret = list.shift();
} else {
// complex case.
// we have enough to cover it, but it spans past the first buffer.
if (stringMode)
ret = '';
else
ret = new Buffer(n);
var c = 0;
for (var i = 0, l = list.length; i < l && c < n; i++) {
var buf = list[0];
var cpy = Math.min(n - c, buf.length);
if (stringMode)
ret += buf.slice(0, cpy);
else
buf.copy(ret, c, 0, cpy);
if (cpy < buf.length)
list[0] = buf.slice(cpy);
else
list.shift();
c += cpy;
}
}
}
return ret;
}
function endReadable(stream) {
var state = stream._readableState;
// If we get here before consuming all the bytes, then that is a
// bug in node. Should never happen.
if (state.length > 0)
throw new Error('endReadable called on non-empty stream');
if (!state.endEmitted && state.calledRead) {
state.ended = true;
setImmediate(function() {
// Check that we didn't get one last unshift.
if (!state.endEmitted && state.length === 0) {
state.endEmitted = true;
stream.readable = false;
stream.emit('end');
}
});
}
}
function forEach (xs, f) {
for (var i = 0, l = xs.length; i < l; i++) {
f(xs[i], i);
}
}
function indexOf (xs, x) {
for (var i = 0, l = xs.length; i < l; i++) {
if (xs[i] === x) return i;
}
return -1;
}
}).call(this,_dereq_("C:\\Users\\Alex\\AppData\\Roaming\\npm\\node_modules\\browserify\\node_modules\\insert-module-globals\\node_modules\\process\\browser.js"))
},{"./index.js":150,"C:\\Users\\Alex\\AppData\\Roaming\\npm\\node_modules\\browserify\\node_modules\\insert-module-globals\\node_modules\\process\\browser.js":144,"buffer":128,"events":137,"inherits":143,"process/browser.js":151,"string_decoder":156}],154:[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.
// a transform stream is a readable/writable stream where you do
// something with the data. Sometimes it's called a "filter",
// but that's not a great name for it, since that implies a thing where
// some bits pass through, and others are simply ignored. (That would
// be a valid example of a transform, of course.)
//
// While the output is causally related to the input, it's not a
// necessarily symmetric or synchronous transformation. For example,
// a zlib stream might take multiple plain-text writes(), and then
// emit a single compressed chunk some time in the future.
//
// Here's how this works:
//
// The Transform stream has all the aspects of the readable and writable
// stream classes. When you write(chunk), that calls _write(chunk,cb)
// internally, and returns false if there's a lot of pending writes
// buffered up. When you call read(), that calls _read(n) until
// there's enough pending readable data buffered up.
//
// In a transform stream, the written data is placed in a buffer. When
// _read(n) is called, it transforms the queued up data, calling the
// buffered _write cb's as it consumes chunks. If consuming a single
// written chunk would result in multiple output chunks, then the first
// outputted bit calls the readcb, and subsequent chunks just go into
// the read buffer, and will cause it to emit 'readable' if necessary.
//
// This way, back-pressure is actually determined by the reading side,
// since _read has to be called to start processing a new chunk. However,
// a pathological inflate type of transform can cause excessive buffering
// here. For example, imagine a stream where every byte of input is
// interpreted as an integer from 0-255, and then results in that many
// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in
// 1kb of data being output. In this case, you could write a very small
// amount of input, and end up with a very large amount of output. In
// such a pathological inflating mechanism, there'd be no way to tell
// the system to stop doing the transform. A single 4MB write could
// cause the system to run out of memory.
//
// However, even in such a pathological case, only a single written chunk
// would be consumed, and then the rest would wait (un-transformed) until
// the results of the previous transformed chunk were consumed.
module.exports = Transform;
var Duplex = _dereq_('./duplex.js');
var inherits = _dereq_('inherits');
inherits(Transform, Duplex);
function TransformState(options, stream) {
this.afterTransform = function(er, data) {
return afterTransform(stream, er, data);
};
this.needTransform = false;
this.transforming = false;
this.writecb = null;
this.writechunk = null;
}
function afterTransform(stream, er, data) {
var ts = stream._transformState;
ts.transforming = false;
var cb = ts.writecb;
if (!cb)
return stream.emit('error', new Error('no writecb in Transform class'));
ts.writechunk = null;
ts.writecb = null;
if (data !== null && data !== undefined)
stream.push(data);
if (cb)
cb(er);
var rs = stream._readableState;
rs.reading = false;
if (rs.needReadable || rs.length < rs.highWaterMark) {
stream._read(rs.highWaterMark);
}
}
function Transform(options) {
if (!(this instanceof Transform))
return new Transform(options);
Duplex.call(this, options);
var ts = this._transformState = new TransformState(options, this);
// when the writable side finishes, then flush out anything remaining.
var stream = this;
// start out asking for a readable event once data is transformed.
this._readableState.needReadable = true;
// we have implemented the _read method, and done the other things
// that Readable wants before the first _read call, so unset the
// sync guard flag.
this._readableState.sync = false;
this.once('finish', function() {
if ('function' === typeof this._flush)
this._flush(function(er) {
done(stream, er);
});
else
done(stream);
});
}
Transform.prototype.push = function(chunk, encoding) {
this._transformState.needTransform = false;
return Duplex.prototype.push.call(this, chunk, encoding);
};
// This is the part where you do stuff!
// override this function in implementation classes.
// 'chunk' is an input chunk.
//
// Call `push(newChunk)` to pass along transformed output
// to the readable side. You may call 'push' zero or more times.
//
// Call `cb(err)` when you are done with this chunk. If you pass
// an error, then that'll put the hurt on the whole operation. If you
// never call cb(), then you'll never get another chunk.
Transform.prototype._transform = function(chunk, encoding, cb) {
throw new Error('not implemented');
};
Transform.prototype._write = function(chunk, encoding, cb) {
var ts = this._transformState;
ts.writecb = cb;
ts.writechunk = chunk;
ts.writeencoding = encoding;
if (!ts.transforming) {
var rs = this._readableState;
if (ts.needTransform ||
rs.needReadable ||
rs.length < rs.highWaterMark)
this._read(rs.highWaterMark);
}
};
// Doesn't matter what the args are here.
// _transform does all the work.
// That we got here means that the readable side wants more data.
Transform.prototype._read = function(n) {
var ts = this._transformState;
if (ts.writechunk && ts.writecb && !ts.transforming) {
ts.transforming = true;
this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform);
} else {
// mark that we need a transform, so that any data that comes in
// will get processed, now that we've asked for it.
ts.needTransform = true;
}
};
function done(stream, er) {
if (er)
return stream.emit('error', er);
// if there's nothing in the write buffer, then that means
// that nothing more will ever be provided
var ws = stream._writableState;
var rs = stream._readableState;
var ts = stream._transformState;
if (ws.length)
throw new Error('calling transform done when ws.length != 0');
if (ts.transforming)
throw new Error('calling transform done when still transforming');
return stream.push(null);
}
},{"./duplex.js":149,"inherits":143}],155:[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.
// A bit simpler than readable streams.
// Implement an async ._write(chunk, cb), and it'll handle all
// the drain event emission and buffering.
module.exports = Writable;
Writable.WritableState = WritableState;
var isUint8Array = typeof Uint8Array !== 'undefined'
? function (x) { return x instanceof Uint8Array }
: function (x) {
return x && x.constructor && x.constructor.name === 'Uint8Array'
}
;
var isArrayBuffer = typeof ArrayBuffer !== 'undefined'
? function (x) { return x instanceof ArrayBuffer }
: function (x) {
return x && x.constructor && x.constructor.name === 'ArrayBuffer'
}
;
var inherits = _dereq_('inherits');
var Stream = _dereq_('./index.js');
var setImmediate = _dereq_('process/browser.js').nextTick;
var Buffer = _dereq_('buffer').Buffer;
inherits(Writable, Stream);
function WriteReq(chunk, encoding, cb) {
this.chunk = chunk;
this.encoding = encoding;
this.callback = cb;
}
function WritableState(options, stream) {
options = options || {};
// the point at which write() starts returning false
// Note: 0 is a valid value, means that we always return false if
// the entire buffer is not flushed immediately on write()
var hwm = options.highWaterMark;
this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024;
// object stream flag to indicate whether or not this stream
// contains buffers or objects.
this.objectMode = !!options.objectMode;
// cast to ints.
this.highWaterMark = ~~this.highWaterMark;
this.needDrain = false;
// at the start of calling end()
this.ending = false;
// when end() has been called, and returned
this.ended = false;
// when 'finish' is emitted
this.finished = false;
// should we decode strings into buffers before passing to _write?
// this is here so that some node-core streams can optimize string
// handling at a lower level.
var noDecode = options.decodeStrings === false;
this.decodeStrings = !noDecode;
// Crypto is kind of old and crusty. Historically, its default string
// encoding is 'binary' so we have to make this configurable.
// Everything else in the universe uses 'utf8', though.
this.defaultEncoding = options.defaultEncoding || 'utf8';
// not an actual buffer we keep track of, but a measurement
// of how much we're waiting to get pushed to some underlying
// socket or file.
this.length = 0;
// a flag to see when we're in the middle of a write.
this.writing = false;
// a flag to be able to tell if the onwrite cb is called immediately,
// or on a later tick. We set this to true at first, becuase any
// actions that shouldn't happen until "later" should generally also
// not happen before the first write call.
this.sync = true;
// a flag to know if we're processing previously buffered items, which
// may call the _write() callback in the same tick, so that we don't
// end up in an overlapped onwrite situation.
this.bufferProcessing = false;
// the callback that's passed to _write(chunk,cb)
this.onwrite = function(er) {
onwrite(stream, er);
};
// the callback that the user supplies to write(chunk,encoding,cb)
this.writecb = null;
// the amount that is being written when _write is called.
this.writelen = 0;
this.buffer = [];
}
function Writable(options) {
// Writable ctor is applied to Duplexes, though they're not
// instanceof Writable, they're instanceof Readable.
if (!(this instanceof Writable) && !(this instanceof Stream.Duplex))
return new Writable(options);
this._writableState = new WritableState(options, this);
// legacy.
this.writable = true;
Stream.call(this);
}
// Otherwise people can pipe Writable streams, which is just wrong.
Writable.prototype.pipe = function() {
this.emit('error', new Error('Cannot pipe. Not readable.'));
};
function writeAfterEnd(stream, state, cb) {
var er = new Error('write after end');
// TODO: defer error events consistently everywhere, not just the cb
stream.emit('error', er);
setImmediate(function() {
cb(er);
});
}
// If we get something that is not a buffer, string, null, or undefined,
// and we're not in objectMode, then that's an error.
// Otherwise stream chunks are all considered to be of length=1, and the
// watermarks determine how many objects to keep in the buffer, rather than
// how many bytes or characters.
function validChunk(stream, state, chunk, cb) {
var valid = true;
if (!Buffer.isBuffer(chunk) &&
'string' !== typeof chunk &&
chunk !== null &&
chunk !== undefined &&
!state.objectMode) {
var er = new TypeError('Invalid non-string/buffer chunk');
stream.emit('error', er);
setImmediate(function() {
cb(er);
});
valid = false;
}
return valid;
}
Writable.prototype.write = function(chunk, encoding, cb) {
var state = this._writableState;
var ret = false;
if (typeof encoding === 'function') {
cb = encoding;
encoding = null;
}
if (!Buffer.isBuffer(chunk) && isUint8Array(chunk))
chunk = new Buffer(chunk);
if (isArrayBuffer(chunk) && typeof Uint8Array !== 'undefined')
chunk = new Buffer(new Uint8Array(chunk));
if (Buffer.isBuffer(chunk))
encoding = 'buffer';
else if (!encoding)
encoding = state.defaultEncoding;
if (typeof cb !== 'function')
cb = function() {};
if (state.ended)
writeAfterEnd(this, state, cb);
else if (validChunk(this, state, chunk, cb))
ret = writeOrBuffer(this, state, chunk, encoding, cb);
return ret;
};
function decodeChunk(state, chunk, encoding) {
if (!state.objectMode &&
state.decodeStrings !== false &&
typeof chunk === 'string') {
chunk = new Buffer(chunk, encoding);
}
return chunk;
}
// if we're already writing something, then just put this
// in the queue, and wait our turn. Otherwise, call _write
// If we return false, then we need a drain event, so set that flag.
function writeOrBuffer(stream, state, chunk, encoding, cb) {
chunk = decodeChunk(state, chunk, encoding);
var len = state.objectMode ? 1 : chunk.length;
state.length += len;
var ret = state.length < state.highWaterMark;
state.needDrain = !ret;
if (state.writing)
state.buffer.push(new WriteReq(chunk, encoding, cb));
else
doWrite(stream, state, len, chunk, encoding, cb);
return ret;
}
function doWrite(stream, state, len, chunk, encoding, cb) {
state.writelen = len;
state.writecb = cb;
state.writing = true;
state.sync = true;
stream._write(chunk, encoding, state.onwrite);
state.sync = false;
}
function onwriteError(stream, state, sync, er, cb) {
if (sync)
setImmediate(function() {
cb(er);
});
else
cb(er);
stream.emit('error', er);
}
function onwriteStateUpdate(state) {
state.writing = false;
state.writecb = null;
state.length -= state.writelen;
state.writelen = 0;
}
function onwrite(stream, er) {
var state = stream._writableState;
var sync = state.sync;
var cb = state.writecb;
onwriteStateUpdate(state);
if (er)
onwriteError(stream, state, sync, er, cb);
else {
// Check if we're actually ready to finish, but don't emit yet
var finished = needFinish(stream, state);
if (!finished && !state.bufferProcessing && state.buffer.length)
clearBuffer(stream, state);
if (sync) {
setImmediate(function() {
afterWrite(stream, state, finished, cb);
});
} else {
afterWrite(stream, state, finished, cb);
}
}
}
function afterWrite(stream, state, finished, cb) {
if (!finished)
onwriteDrain(stream, state);
cb();
if (finished)
finishMaybe(stream, state);
}
// Must force callback to be called on nextTick, so that we don't
// emit 'drain' before the write() consumer gets the 'false' return
// value, and has a chance to attach a 'drain' listener.
function onwriteDrain(stream, state) {
if (state.length === 0 && state.needDrain) {
state.needDrain = false;
stream.emit('drain');
}
}
// if there's something in the buffer waiting, then process it
function clearBuffer(stream, state) {
state.bufferProcessing = true;
for (var c = 0; c < state.buffer.length; c++) {
var entry = state.buffer[c];
var chunk = entry.chunk;
var encoding = entry.encoding;
var cb = entry.callback;
var len = state.objectMode ? 1 : chunk.length;
doWrite(stream, state, len, chunk, encoding, cb);
// if we didn't call the onwrite immediately, then
// it means that we need to wait until it does.
// also, that means that the chunk and cb are currently
// being processed, so move the buffer counter past them.
if (state.writing) {
c++;
break;
}
}
state.bufferProcessing = false;
if (c < state.buffer.length)
state.buffer = state.buffer.slice(c);
else
state.buffer.length = 0;
}
Writable.prototype._write = function(chunk, encoding, cb) {
cb(new Error('not implemented'));
};
Writable.prototype.end = function(chunk, encoding, cb) {
var state = this._writableState;
if (typeof chunk === 'function') {
cb = chunk;
chunk = null;
encoding = null;
} else if (typeof encoding === 'function') {
cb = encoding;
encoding = null;
}
if (typeof chunk !== 'undefined' && chunk !== null)
this.write(chunk, encoding);
// ignore unnecessary end() calls.
if (!state.ending && !state.finished)
endWritable(this, state, cb);
};
function needFinish(stream, state) {
return (state.ending &&
state.length === 0 &&
!state.finished &&
!state.writing);
}
function finishMaybe(stream, state) {
var need = needFinish(stream, state);
if (need) {
state.finished = true;
stream.emit('finish');
}
return need;
}
function endWritable(stream, state, cb) {
state.ending = true;
finishMaybe(stream, state);
if (cb) {
if (state.finished)
setImmediate(cb);
else
stream.once('finish', cb);
}
state.ended = true;
}
},{"./index.js":150,"buffer":128,"inherits":143,"process/browser.js":151}],156:[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":128}],157:[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 punycode = _dereq_('punycode');
exports.parse = urlParse;
exports.resolve = urlResolve;
exports.resolveObject = urlResolveObject;
exports.format = urlFormat;
exports.Url = Url;
function Url() {
this.protocol = null;
this.slashes = null;
this.auth = null;
this.host = null;
this.port = null;
this.hostname = null;
this.hash = null;
this.search = null;
this.query = null;
this.pathname = null;
this.path = null;
this.href = null;
}
// Reference: RFC 3986, RFC 1808, RFC 2396
// define these here so at least they only have to be
// compiled once on the first module load.
var protocolPattern = /^([a-z0-9.+-]+:)/i,
portPattern = /:[0-9]*$/,
// RFC 2396: characters reserved for delimiting URLs.
// We actually just auto-escape these.
delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'],
// RFC 2396: characters not allowed for various reasons.
unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims),
// Allowed by RFCs, but cause of XSS attacks. Always escape these.
autoEscape = ['\''].concat(unwise),
// Characters that are never ever allowed in a hostname.
// Note that any invalid chars are also handled, but these
// are the ones that are *expected* to be seen, so we fast-path
// them.
nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape),
hostEndingChars = ['/', '?', '#'],
hostnameMaxLen = 255,
hostnamePartPattern = /^[a-z0-9A-Z_-]{0,63}$/,
hostnamePartStart = /^([a-z0-9A-Z_-]{0,63})(.*)$/,
// protocols that can allow "unsafe" and "unwise" chars.
unsafeProtocol = {
'javascript': true,
'javascript:': true
},
// protocols that never have a hostname.
hostlessProtocol = {
'javascript': true,
'javascript:': true
},
// protocols that always contain a // bit.
slashedProtocol = {
'http': true,
'https': true,
'ftp': true,
'gopher': true,
'file': true,
'http:': true,
'https:': true,
'ftp:': true,
'gopher:': true,
'file:': true
},
querystring = _dereq_('querystring');
function urlParse(url, parseQueryString, slashesDenoteHost) {
if (url && isObject(url) && url instanceof Url) return url;
var u = new Url;
u.parse(url, parseQueryString, slashesDenoteHost);
return u;
}
Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {
if (!isString(url)) {
throw new TypeError("Parameter 'url' must be a string, not " + typeof url);
}
var rest = url;
// trim before proceeding.
// This is to support parse stuff like " http://foo.com \n"
rest = rest.trim();
var proto = protocolPattern.exec(rest);
if (proto) {
proto = proto[0];
var lowerProto = proto.toLowerCase();
this.protocol = lowerProto;
rest = rest.substr(proto.length);
}
// figure out if it's got a host
// user@server is *always* interpreted as a hostname, and url
// resolution will treat //foo/bar as host=foo,path=bar because that's
// how the browser resolves relative URLs.
if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) {
var slashes = rest.substr(0, 2) === '//';
if (slashes && !(proto && hostlessProtocol[proto])) {
rest = rest.substr(2);
this.slashes = true;
}
}
if (!hostlessProtocol[proto] &&
(slashes || (proto && !slashedProtocol[proto]))) {
// there's a hostname.
// the first instance of /, ?, ;, or # ends the host.
//
// If there is an @ in the hostname, then non-host chars *are* allowed
// to the left of the last @ sign, unless some host-ending character
// comes *before* the @-sign.
// URLs are obnoxious.
//
// ex:
// http://a@b@c/ => user:a@b host:c
// http://a@b?@c => user:a host:c path:/?@c
// v0.12 TODO(isaacs): This is not quite how Chrome does things.
// Review our test case against browsers more comprehensively.
// find the first instance of any hostEndingChars
var hostEnd = -1;
for (var i = 0; i < hostEndingChars.length; i++) {
var hec = rest.indexOf(hostEndingChars[i]);
if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
hostEnd = hec;
}
// at this point, either we have an explicit point where the
// auth portion cannot go past, or the last @ char is the decider.
var auth, atSign;
if (hostEnd === -1) {
// atSign can be anywhere.
atSign = rest.lastIndexOf('@');
} else {
// atSign must be in auth portion.
// http://a@b/c@d => host:b auth:a path:/c@d
atSign = rest.lastIndexOf('@', hostEnd);
}
// Now we have a portion which is definitely the auth.
// Pull that off.
if (atSign !== -1) {
auth = rest.slice(0, atSign);
rest = rest.slice(atSign + 1);
this.auth = decodeURIComponent(auth);
}
// the host is the remaining to the left of the first non-host char
hostEnd = -1;
for (var i = 0; i < nonHostChars.length; i++) {
var hec = rest.indexOf(nonHostChars[i]);
if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
hostEnd = hec;
}
// if we still have not hit it, then the entire thing is a host.
if (hostEnd === -1)
hostEnd = rest.length;
this.host = rest.slice(0, hostEnd);
rest = rest.slice(hostEnd);
// pull out port.
this.parseHost();
// we've indicated that there is a hostname,
// so even if it's empty, it has to be present.
this.hostname = this.hostname || '';
// if hostname begins with [ and ends with ]
// assume that it's an IPv6 address.
var ipv6Hostname = this.hostname[0] === '[' &&
this.hostname[this.hostname.length - 1] === ']';
// validate a little.
if (!ipv6Hostname) {
var hostparts = this.hostname.split(/\./);
for (var i = 0, l = hostparts.length; i < l; i++) {
var part = hostparts[i];
if (!part) continue;
if (!part.match(hostnamePartPattern)) {
var newpart = '';
for (var j = 0, k = part.length; j < k; j++) {
if (part.charCodeAt(j) > 127) {
// we replace non-ASCII char with a temporary placeholder
// we need this to make sure size of hostname is not
// broken by replacing non-ASCII by nothing
newpart += 'x';
} else {
newpart += part[j];
}
}
// we test again with ASCII char only
if (!newpart.match(hostnamePartPattern)) {
var validParts = hostparts.slice(0, i);
var notHost = hostparts.slice(i + 1);
var bit = part.match(hostnamePartStart);
if (bit) {
validParts.push(bit[1]);
notHost.unshift(bit[2]);
}
if (notHost.length) {
rest = '/' + notHost.join('.') + rest;
}
this.hostname = validParts.join('.');
break;
}
}
}
}
if (this.hostname.length > hostnameMaxLen) {
this.hostname = '';
} else {
// hostnames are always lower case.
this.hostname = this.hostname.toLowerCase();
}
if (!ipv6Hostname) {
// IDNA Support: Returns a puny coded representation of "domain".
// It only converts the part of the domain name that
// has non ASCII characters. I.e. it dosent matter if
// you call it with a domain that already is in ASCII.
var domainArray = this.hostname.split('.');
var newOut = [];
for (var i = 0; i < domainArray.length; ++i) {
var s = domainArray[i];
newOut.push(s.match(/[^A-Za-z0-9_-]/) ?
'xn--' + punycode.encode(s) : s);
}
this.hostname = newOut.join('.');
}
var p = this.port ? ':' + this.port : '';
var h = this.hostname || '';
this.host = h + p;
this.href += this.host;
// strip [ and ] from the hostname
// the host field still retains them, though
if (ipv6Hostname) {
this.hostname = this.hostname.substr(1, this.hostname.length - 2);
if (rest[0] !== '/') {
rest = '/' + rest;
}
}
}
// now rest is set to the post-host stuff.
// chop off any delim chars.
if (!unsafeProtocol[lowerProto]) {
// First, make 100% sure that any "autoEscape" chars get
// escaped, even if encodeURIComponent doesn't think they
// need to be.
for (var i = 0, l = autoEscape.length; i < l; i++) {
var ae = autoEscape[i];
var esc = encodeURIComponent(ae);
if (esc === ae) {
esc = escape(ae);
}
rest = rest.split(ae).join(esc);
}
}
// chop off from the tail first.
var hash = rest.indexOf('#');
if (hash !== -1) {
// got a fragment string.
this.hash = rest.substr(hash);
rest = rest.slice(0, hash);
}
var qm = rest.indexOf('?');
if (qm !== -1) {
this.search = rest.substr(qm);
this.query = rest.substr(qm + 1);
if (parseQueryString) {
this.query = querystring.parse(this.query);
}
rest = rest.slice(0, qm);
} else if (parseQueryString) {
// no query string, but parseQueryString still requested
this.search = '';
this.query = {};
}
if (rest) this.pathname = rest;
if (slashedProtocol[lowerProto] &&
this.hostname && !this.pathname) {
this.pathname = '/';
}
//to support http.request
if (this.pathname || this.search) {
var p = this.pathname || '';
var s = this.search || '';
this.path = p + s;
}
// finally, reconstruct the href based on what has been validated.
this.href = this.format();
return this;
};
// format a parsed object into a url string
function urlFormat(obj) {
// ensure it's an object, and not a string url.
// If it's an obj, this is a no-op.
// this way, you can call url_format() on strings
// to clean up potentially wonky urls.
if (isString(obj)) obj = urlParse(obj);
if (!(obj instanceof Url)) return Url.prototype.format.call(obj);
return obj.format();
}
Url.prototype.format = function() {
var auth = this.auth || '';
if (auth) {
auth = encodeURIComponent(auth);
auth = auth.replace(/%3A/i, ':');
auth += '@';
}
var protocol = this.protocol || '',
pathname = this.pathname || '',
hash = this.hash || '',
host = false,
query = '';
if (this.host) {
host = auth + this.host;
} else if (this.hostname) {
host = auth + (this.hostname.indexOf(':') === -1 ?
this.hostname :
'[' + this.hostname + ']');
if (this.port) {
host += ':' + this.port;
}
}
if (this.query &&
isObject(this.query) &&
Object.keys(this.query).length) {
query = querystring.stringify(this.query);
}
var search = this.search || (query && ('?' + query)) || '';
if (protocol && protocol.substr(-1) !== ':') protocol += ':';
// only the slashedProtocols get the //. Not mailto:, xmpp:, etc.
// unless they had them to begin with.
if (this.slashes ||
(!protocol || slashedProtocol[protocol]) && host !== false) {
host = '//' + (host || '');
if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname;
} else if (!host) {
host = '';
}
if (hash && hash.charAt(0) !== '#') hash = '#' + hash;
if (search && search.charAt(0) !== '?') search = '?' + search;
pathname = pathname.replace(/[?#]/g, function(match) {
return encodeURIComponent(match);
});
search = search.replace('#', '%23');
return protocol + host + pathname + search + hash;
};
function urlResolve(source, relative) {
return urlParse(source, false, true).resolve(relative);
}
Url.prototype.resolve = function(relative) {
return this.resolveObject(urlParse(relative, false, true)).format();
};
function urlResolveObject(source, relative) {
if (!source) return relative;
return urlParse(source, false, true).resolveObject(relative);
}
Url.prototype.resolveObject = function(relative) {
if (isString(relative)) {
var rel = new Url();
rel.parse(relative, false, true);
relative = rel;
}
var result = new Url();
Object.keys(this).forEach(function(k) {
result[k] = this[k];
}, this);
// hash is always overridden, no matter what.
// even href="" will remove it.
result.hash = relative.hash;
// if the relative url is empty, then there's nothing left to do here.
if (relative.href === '') {
result.href = result.format();
return result;
}
// hrefs like //foo/bar always cut to the protocol.
if (relative.slashes && !relative.protocol) {
// take everything except the protocol from relative
Object.keys(relative).forEach(function(k) {
if (k !== 'protocol')
result[k] = relative[k];
});
//urlParse appends trailing / to urls like http://www.example.com
if (slashedProtocol[result.protocol] &&
result.hostname && !result.pathname) {
result.path = result.pathname = '/';
}
result.href = result.format();
return result;
}
if (relative.protocol && relative.protocol !== result.protocol) {
// if it's a known url protocol, then changing
// the protocol does weird things
// first, if it's not file:, then we MUST have a host,
// and if there was a path
// to begin with, then we MUST have a path.
// if it is file:, then the host is dropped,
// because that's known to be hostless.
// anything else is assumed to be absolute.
if (!slashedProtocol[relative.protocol]) {
Object.keys(relative).forEach(function(k) {
result[k] = relative[k];
});
result.href = result.format();
return result;
}
result.protocol = relative.protocol;
if (!relative.host && !hostlessProtocol[relative.protocol]) {
var relPath = (relative.pathname || '').split('/');
while (relPath.length && !(relative.host = relPath.shift()));
if (!relative.host) relative.host = '';
if (!relative.hostname) relative.hostname = '';
if (relPath[0] !== '') relPath.unshift('');
if (relPath.length < 2) relPath.unshift('');
result.pathname = relPath.join('/');
} else {
result.pathname = relative.pathname;
}
result.search = relative.search;
result.query = relative.query;
result.host = relative.host || '';
result.auth = relative.auth;
result.hostname = relative.hostname || relative.host;
result.port = relative.port;
// to support http.request
if (result.pathname || result.search) {
var p = result.pathname || '';
var s = result.search || '';
result.path = p + s;
}
result.slashes = result.slashes || relative.slashes;
result.href = result.format();
return result;
}
var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'),
isRelAbs = (
relative.host ||
relative.pathname && relative.pathname.charAt(0) === '/'
),
mustEndAbs = (isRelAbs || isSourceAbs ||
(result.host && relative.pathname)),
removeAllDots = mustEndAbs,
srcPath = result.pathname && result.pathname.split('/') || [],
relPath = relative.pathname && relative.pathname.split('/') || [],
psychotic = result.protocol && !slashedProtocol[result.protocol];
// if the url is a non-slashed url, then relative
// links like ../.. should be able
// to crawl up to the hostname, as well. This is strange.
// result.protocol has already been set by now.
// Later on, put the first path part into the host field.
if (psychotic) {
result.hostname = '';
result.port = null;
if (result.host) {
if (srcPath[0] === '') srcPath[0] = result.host;
else srcPath.unshift(result.host);
}
result.host = '';
if (relative.protocol) {
relative.hostname = null;
relative.port = null;
if (relative.host) {
if (relPath[0] === '') relPath[0] = relative.host;
else relPath.unshift(relative.host);
}
relative.host = null;
}
mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === '');
}
if (isRelAbs) {
// it's absolute.
result.host = (relative.host || relative.host === '') ?
relative.host : result.host;
result.hostname = (relative.hostname || relative.hostname === '') ?
relative.hostname : result.hostname;
result.search = relative.search;
result.query = relative.query;
srcPath = relPath;
// fall through to the dot-handling below.
} else if (relPath.length) {
// it's relative
// throw away the existing file, and take the new path instead.
if (!srcPath) srcPath = [];
srcPath.pop();
srcPath = srcPath.concat(relPath);
result.search = relative.search;
result.query = relative.query;
} else if (!isNullOrUndefined(relative.search)) {
// just pull out the search.
// like href='?foo'.
// Put this after the other two cases because it simplifies the booleans
if (psychotic) {
result.hostname = result.host = srcPath.shift();
//occationaly the auth can get stuck only in host
//this especialy happens in cases like
//url.resolveObject('mailto:local1@domain1', 'local2@domain2')
var authInHost = result.host && result.host.indexOf('@') > 0 ?
result.host.split('@') : false;
if (authInHost) {
result.auth = authInHost.shift();
result.host = result.hostname = authInHost.shift();
}
}
result.search = relative.search;
result.query = relative.query;
//to support http.request
if (!isNull(result.pathname) || !isNull(result.search)) {
result.path = (result.pathname ? result.pathname : '') +
(result.search ? result.search : '');
}
result.href = result.format();
return result;
}
if (!srcPath.length) {
// no path at all. easy.
// we've already handled the other stuff above.
result.pathname = null;
//to support http.request
if (result.search) {
result.path = '/' + result.search;
} else {
result.path = null;
}
result.href = result.format();
return result;
}
// if a url ENDs in . or .., then it must get a trailing slash.
// however, if it ends in anything else non-slashy,
// then it must NOT get a trailing slash.
var last = srcPath.slice(-1)[0];
var hasTrailingSlash = (
(result.host || relative.host) && (last === '.' || last === '..') ||
last === '');
// strip single dots, resolve double dots to parent dir
// if the path tries to go above the root, `up` ends up > 0
var up = 0;
for (var i = srcPath.length; i >= 0; i--) {
last = srcPath[i];
if (last == '.') {
srcPath.splice(i, 1);
} else if (last === '..') {
srcPath.splice(i, 1);
up++;
} else if (up) {
srcPath.splice(i, 1);
up--;
}
}
// if the path is allowed to go above the root, restore leading ..s
if (!mustEndAbs && !removeAllDots) {
for (; up--; up) {
srcPath.unshift('..');
}
}
if (mustEndAbs && srcPath[0] !== '' &&
(!srcPath[0] || srcPath[0].charAt(0) !== '/')) {
srcPath.unshift('');
}
if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) {
srcPath.push('');
}
var isAbsolute = srcPath[0] === '' ||
(srcPath[0] && srcPath[0].charAt(0) === '/');
// put the host back
if (psychotic) {
result.hostname = result.host = isAbsolute ? '' :
srcPath.length ? srcPath.shift() : '';
//occationaly the auth can get stuck only in host
//this especialy happens in cases like
//url.resolveObject('mailto:local1@domain1', 'local2@domain2')
var authInHost = result.host && result.host.indexOf('@') > 0 ?
result.host.split('@') : false;
if (authInHost) {
result.auth = authInHost.shift();
result.host = result.hostname = authInHost.shift();
}
}
mustEndAbs = mustEndAbs || (result.host && srcPath.length);
if (mustEndAbs && !isAbsolute) {
srcPath.unshift('');
}
if (!srcPath.length) {
result.pathname = null;
result.path = null;
} else {
result.pathname = srcPath.join('/');
}
//to support request.http
if (!isNull(result.pathname) || !isNull(result.search)) {
result.path = (result.pathname ? result.pathname : '') +
(result.search ? result.search : '');
}
result.auth = relative.auth || result.auth;
result.slashes = result.slashes || relative.slashes;
result.href = result.format();
return result;
};
Url.prototype.parseHost = function() {
var host = this.host;
var port = portPattern.exec(host);
if (port) {
port = port[0];
if (port !== ':') {
this.port = port.substr(1);
}
host = host.substr(0, host.length - port.length);
}
if (host) this.hostname = host;
};
function isString(arg) {
return typeof arg === "string";
}
function isObject(arg) {
return typeof arg === 'object' && arg !== null;
}
function isNull(arg) {
return arg === null;
}
function isNullOrUndefined(arg) {
return arg == null;
}
},{"punycode":145,"querystring":148}],158:[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';
}
},{}],159:[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_("C:\\Users\\Alex\\AppData\\Roaming\\npm\\node_modules\\browserify\\node_modules\\insert-module-globals\\node_modules\\process\\browser.js"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./support/isBuffer":158,"C:\\Users\\Alex\\AppData\\Roaming\\npm\\node_modules\\browserify\\node_modules\\insert-module-globals\\node_modules\\process\\browser.js":144,"inherits":143}]},{},[1])
(1)
});