|
|
- !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 = {
- '&': '&',
- '<': '<',
- '>': '>',
- '"': '"',
- "'": '''
- };
-
- /** 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 & 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><script></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
- * `&`, `<`, `>`, `"`, and `'` 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 & 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)
- });
|