var OrbitDB = /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) /******/ return installedModules[moduleId].exports; /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ // Flag the module as loaded /******/ module.l = true; /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = 125); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ function(module, exports) { var g; // This works in non-strict mode g = (function() { return this; })(); try { // This works if eval is allowed (see CSP) g = g || Function("return this")() || (1,eval)("this"); } catch(e) { // This works if the window reference is available if(typeof window === "object") g = window; } // g can still be undefined, but nothing to do about it... // We return undefined, instead of nothing here, so it's // easier to handle this case. if(!global) { ...} module.exports = g; /***/ }, /* 1 */ /***/ function(module, exports, __webpack_require__) { var store = __webpack_require__(65)('wks') , uid = __webpack_require__(69) , Symbol = __webpack_require__(2).Symbol , USE_SYMBOL = typeof Symbol == 'function'; var $exports = module.exports = function(name){ return store[name] || (store[name] = USE_SYMBOL && Symbol[name] || (USE_SYMBOL ? Symbol : uid)('Symbol.' + name)); }; $exports.store = store; /***/ }, /* 2 */ /***/ function(module, exports) { // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 var global = module.exports = typeof window != 'undefined' && window.Math == Math ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')(); if(typeof __g == 'number')__g = global; // eslint-disable-line no-undef /***/ }, /* 3 */ /***/ function(module, exports, __webpack_require__) { /** * This is the web browser implementation of `debug()`. * * Expose `debug()` as the module. */ exports = module.exports = __webpack_require__(170); exports.log = log; exports.formatArgs = formatArgs; exports.save = save; exports.load = load; exports.useColors = useColors; exports.storage = 'undefined' != typeof chrome && 'undefined' != typeof chrome.storage ? chrome.storage.local : localstorage(); /** * Colors. */ exports.colors = [ 'lightseagreen', 'forestgreen', 'goldenrod', 'dodgerblue', 'darkorchid', 'crimson' ]; /** * Currently only WebKit-based Web Inspectors, Firefox >= v31, * and the Firebug extension (any Firefox version) are known * to support "%c" CSS customizations. * * TODO: add a `localStorage` variable to explicitly enable/disable colors */ function useColors() { // is webkit? http://stackoverflow.com/a/16459606/376773 return ('WebkitAppearance' in document.documentElement.style) || // is firebug? http://stackoverflow.com/a/398120/376773 (window.console && (console.firebug || (console.exception && console.table))) || // is firefox >= v31? // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages (navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31); } /** * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. */ exports.formatters.j = function(v) { return JSON.stringify(v); }; /** * Colorize log arguments if enabled. * * @api public */ function formatArgs() { var args = arguments; var useColors = this.useColors; args[0] = (useColors ? '%c' : '') + this.namespace + (useColors ? ' %c' : ' ') + args[0] + (useColors ? '%c ' : ' ') + '+' + exports.humanize(this.diff); if (!useColors) return args; var c = 'color: ' + this.color; args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1)); // the final "%c" is somewhat tricky, because there could be other // arguments passed either before or after the %c, so we need to // figure out the correct index to insert the CSS into var index = 0; var lastC = 0; args[0].replace(/%[a-z%]/g, function(match) { if ('%%' === match) return; index++; if ('%c' === match) { // we only are interested in the *last* %c // (the user may have provided their own) lastC = index; } }); args.splice(lastC, 0, c); return args; } /** * Invokes `console.log()` when available. * No-op when `console.log` is not a "function". * * @api public */ function log() { // this hackery is required for IE8/9, where // the `console.log` function doesn't have 'apply' return 'object' === typeof console && console.log && Function.prototype.apply.call(console.log, console, arguments); } /** * Save `namespaces`. * * @param {String} namespaces * @api private */ function save(namespaces) { try { if (null == namespaces) { exports.storage.removeItem('debug'); } else { exports.storage.debug = namespaces; } } catch(e) {} } /** * Load `namespaces`. * * @return {String} returns the previously persisted debug modes * @api private */ function load() { var r; try { r = exports.storage.debug; } catch(e) {} return r; } /** * Enable namespaces listed in `localStorage.debug` initially. */ exports.enable(load()); /** * Localstorage attempts to return the localstorage. * * This is necessary because safari throws * when a user disables cookies/localstorage * and you attempt to access it. * * @return {LocalStorage} * @api private */ function localstorage(){ try { return window.localStorage; } catch (e) {} } /***/ }, /* 4 */ /***/ function(module, exports, __webpack_require__) { var isObject = __webpack_require__(12); module.exports = function(it){ if(!isObject(it))throw TypeError(it + ' is not an object!'); return it; }; /***/ }, /* 5 */ /***/ function(module, exports) { var core = module.exports = {version: '2.4.0'}; if(typeof __e == 'number')__e = core; // eslint-disable-line no-undef /***/ }, /* 6 */ /***/ function(module, exports, __webpack_require__) { // Thank's IE8 for his funny defineProperty module.exports = !__webpack_require__(60)(function(){ return Object.defineProperty({}, 'a', {get: function(){ return 7; }}).a != 7; }); /***/ }, /* 7 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(setImmediate, clearImmediate) {var nextTick = __webpack_require__(194).nextTick; var apply = Function.prototype.apply; var slice = Array.prototype.slice; var immediateIds = {}; var nextImmediateId = 0; // DOM APIs, for completeness exports.setTimeout = function() { return new Timeout(apply.call(setTimeout, window, arguments), clearTimeout); }; exports.setInterval = function() { return new Timeout(apply.call(setInterval, window, arguments), clearInterval); }; exports.clearTimeout = exports.clearInterval = function(timeout) { timeout.close(); }; function Timeout(id, clearFn) { this._id = id; this._clearFn = clearFn; } Timeout.prototype.unref = Timeout.prototype.ref = function() {}; Timeout.prototype.close = function() { this._clearFn.call(window, this._id); }; // Does not start the time, just sets up the members needed. exports.enroll = function(item, msecs) { clearTimeout(item._idleTimeoutId); item._idleTimeout = msecs; }; exports.unenroll = function(item) { clearTimeout(item._idleTimeoutId); item._idleTimeout = -1; }; exports._unrefActive = exports.active = function(item) { clearTimeout(item._idleTimeoutId); var msecs = item._idleTimeout; if (msecs >= 0) { item._idleTimeoutId = setTimeout(function onTimeout() { if (item._onTimeout) item._onTimeout(); }, msecs); } }; // That's not how node.js implements it but the exposed api is the same. exports.setImmediate = typeof setImmediate === "function" ? setImmediate : function(fn) { var id = nextImmediateId++; var args = arguments.length < 2 ? false : slice.call(arguments, 1); immediateIds[id] = true; nextTick(function onNextTick() { if (immediateIds[id]) { // fn.call() is faster so we optimize for the common use-case // @see http://jsperf.com/call-apply-segu if (args) { fn.apply(null, args); } else { fn.call(null); } // Prevent ids from leaking exports.clearImmediate(id); } }); return id; }; exports.clearImmediate = typeof clearImmediate === "function" ? clearImmediate : function(id) { delete immediateIds[id]; }; /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(7).setImmediate, __webpack_require__(7).clearImmediate)) /***/ }, /* 8 */ /***/ function(module, exports, __webpack_require__) { var dP = __webpack_require__(14) , createDesc = __webpack_require__(30); module.exports = __webpack_require__(6) ? function(object, key, value){ return dP.f(object, key, createDesc(1, value)); } : function(object, key, value){ object[key] = value; return object; }; /***/ }, /* 9 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(global) {/** * Module dependencies. */ var keys = __webpack_require__(177); var hasBinary = __webpack_require__(178); var sliceBuffer = __webpack_require__(122); var base64encoder = __webpack_require__(128); var after = __webpack_require__(121); var utf8 = __webpack_require__(200); /** * Check if we are running an android browser. That requires us to use * ArrayBuffer with polling transports... * * http://ghinda.net/jpeg-blob-ajax-android/ */ var isAndroid = navigator.userAgent.match(/Android/i); /** * Check if we are running in PhantomJS. * Uploading a Blob with PhantomJS does not work correctly, as reported here: * https://github.com/ariya/phantomjs/issues/11395 * @type boolean */ var isPhantomJS = /PhantomJS/i.test(navigator.userAgent); /** * When true, avoids using Blobs to encode payloads. * @type boolean */ var dontSendBlobs = isAndroid || isPhantomJS; /** * Current protocol version. */ exports.protocol = 3; /** * Packet types. */ var packets = exports.packets = { open: 0 // non-ws , close: 1 // non-ws , ping: 2 , pong: 3 , message: 4 , upgrade: 5 , noop: 6 }; var packetslist = keys(packets); /** * Premade error packet. */ var err = { type: 'error', data: 'parser error' }; /** * Create a blob api even for blob builder when vendor prefixes exist */ var Blob = __webpack_require__(130); /** * Encodes a packet. * * [ ] * * Example: * * 5hello world * 3 * 4 * * Binary is encoded in an identical principle * * @api private */ exports.encodePacket = function (packet, supportsBinary, utf8encode, callback) { if ('function' == typeof supportsBinary) { callback = supportsBinary; supportsBinary = false; } if ('function' == typeof utf8encode) { callback = utf8encode; utf8encode = null; } var data = (packet.data === undefined) ? undefined : packet.data.buffer || packet.data; if (global.ArrayBuffer && data instanceof ArrayBuffer) { return encodeArrayBuffer(packet, supportsBinary, callback); } else if (Blob && data instanceof global.Blob) { return encodeBlob(packet, supportsBinary, callback); } // might be an object with { base64: true, data: dataAsBase64String } if (data && data.base64) { return encodeBase64Object(packet, callback); } // Sending data as a utf-8 string var encoded = packets[packet.type]; // data fragment is optional if (undefined !== packet.data) { encoded += utf8encode ? utf8.encode(String(packet.data)) : String(packet.data); } return callback('' + encoded); }; function encodeBase64Object(packet, callback) { // packet data is an object { base64: true, data: dataAsBase64String } var message = 'b' + exports.packets[packet.type] + packet.data.data; return callback(message); } /** * Encode packet helpers for binary types */ function encodeArrayBuffer(packet, supportsBinary, callback) { if (!supportsBinary) { return exports.encodeBase64Packet(packet, callback); } var data = packet.data; var contentArray = new Uint8Array(data); var resultBuffer = new Uint8Array(1 + data.byteLength); resultBuffer[0] = packets[packet.type]; for (var i = 0; i < contentArray.length; i++) { resultBuffer[i+1] = contentArray[i]; } return callback(resultBuffer.buffer); } function encodeBlobAsArrayBuffer(packet, supportsBinary, callback) { if (!supportsBinary) { return exports.encodeBase64Packet(packet, callback); } var fr = new FileReader(); fr.onload = function() { packet.data = fr.result; exports.encodePacket(packet, supportsBinary, true, callback); }; return fr.readAsArrayBuffer(packet.data); } function encodeBlob(packet, supportsBinary, callback) { if (!supportsBinary) { return exports.encodeBase64Packet(packet, callback); } if (dontSendBlobs) { return encodeBlobAsArrayBuffer(packet, supportsBinary, callback); } var length = new Uint8Array(1); length[0] = packets[packet.type]; var blob = new Blob([length.buffer, packet.data]); return callback(blob); } /** * Encodes a packet with binary data in a base64 string * * @param {Object} packet, has `type` and `data` * @return {String} base64 encoded message */ exports.encodeBase64Packet = function(packet, callback) { var message = 'b' + exports.packets[packet.type]; if (Blob && packet.data instanceof global.Blob) { var fr = new FileReader(); fr.onload = function() { var b64 = fr.result.split(',')[1]; callback(message + b64); }; return fr.readAsDataURL(packet.data); } var b64data; try { b64data = String.fromCharCode.apply(null, new Uint8Array(packet.data)); } catch (e) { // iPhone Safari doesn't let you apply with typed arrays var typed = new Uint8Array(packet.data); var basic = new Array(typed.length); for (var i = 0; i < typed.length; i++) { basic[i] = typed[i]; } b64data = String.fromCharCode.apply(null, basic); } message += global.btoa(b64data); return callback(message); }; /** * Decodes a packet. Changes format to Blob if requested. * * @return {Object} with `type` and `data` (if any) * @api private */ exports.decodePacket = function (data, binaryType, utf8decode) { // String data if (typeof data == 'string' || data === undefined) { if (data.charAt(0) == 'b') { return exports.decodeBase64Packet(data.substr(1), binaryType); } if (utf8decode) { try { data = utf8.decode(data); } catch (e) { return err; } } var type = data.charAt(0); if (Number(type) != type || !packetslist[type]) { return err; } if (data.length > 1) { return { type: packetslist[type], data: data.substring(1) }; } else { return { type: packetslist[type] }; } } var asArray = new Uint8Array(data); var type = asArray[0]; var rest = sliceBuffer(data, 1); if (Blob && binaryType === 'blob') { rest = new Blob([rest]); } return { type: packetslist[type], data: rest }; }; /** * Decodes a packet encoded in a base64 string * * @param {String} base64 encoded message * @return {Object} with `type` and `data` (if any) */ exports.decodeBase64Packet = function(msg, binaryType) { var type = packetslist[msg.charAt(0)]; if (!global.ArrayBuffer) { return { type: type, data: { base64: true, data: msg.substr(1) } }; } var data = base64encoder.decode(msg.substr(1)); if (binaryType === 'blob' && Blob) { data = new Blob([data]); } return { type: type, data: data }; }; /** * Encodes multiple messages (payload). * * :data * * Example: * * 11:hello world2:hi * * If any contents are binary, they will be encoded as base64 strings. Base64 * encoded strings are marked with a b before the length specifier * * @param {Array} packets * @api private */ exports.encodePayload = function (packets, supportsBinary, callback) { if (typeof supportsBinary == 'function') { callback = supportsBinary; supportsBinary = null; } var isBinary = hasBinary(packets); if (supportsBinary && isBinary) { if (Blob && !dontSendBlobs) { return exports.encodePayloadAsBlob(packets, callback); } return exports.encodePayloadAsArrayBuffer(packets, callback); } if (!packets.length) { return callback('0:'); } function setLengthHeader(message) { return message.length + ':' + message; } function encodeOne(packet, doneCallback) { exports.encodePacket(packet, !isBinary ? false : supportsBinary, true, function(message) { doneCallback(null, setLengthHeader(message)); }); } map(packets, encodeOne, function(err, results) { return callback(results.join('')); }); }; /** * Async array map using after */ function map(ary, each, done) { var result = new Array(ary.length); var next = after(ary.length, done); var eachWithIndex = function(i, el, cb) { each(el, function(error, msg) { result[i] = msg; cb(error, result); }); }; for (var i = 0; i < ary.length; i++) { eachWithIndex(i, ary[i], next); } } /* * Decodes data when a payload is maybe expected. Possible binary contents are * decoded from their base64 representation * * @param {String} data, callback method * @api public */ exports.decodePayload = function (data, binaryType, callback) { if (typeof data != 'string') { return exports.decodePayloadAsBinary(data, binaryType, callback); } if (typeof binaryType === 'function') { callback = binaryType; binaryType = null; } var packet; if (data == '') { // parser error - ignoring payload return callback(err, 0, 1); } var length = '' , n, msg; for (var i = 0, l = data.length; i < l; i++) { var chr = data.charAt(i); if (':' != chr) { length += chr; } else { if ('' == length || (length != (n = Number(length)))) { // parser error - ignoring payload return callback(err, 0, 1); } msg = data.substr(i + 1, n); if (length != msg.length) { // parser error - ignoring payload return callback(err, 0, 1); } if (msg.length) { packet = exports.decodePacket(msg, binaryType, true); if (err.type == packet.type && err.data == packet.data) { // parser error in individual packet - ignoring payload return callback(err, 0, 1); } var ret = callback(packet, i + n, l); if (false === ret) return; } // advance cursor i += n; length = ''; } } if (length != '') { // parser error - ignoring payload return callback(err, 0, 1); } }; /** * Encodes multiple messages (payload) as binary. * * <1 = binary, 0 = string>[...] * * Example: * 1 3 255 1 2 3, if the binary contents are interpreted as 8 bit integers * * @param {Array} packets * @return {ArrayBuffer} encoded payload * @api private */ exports.encodePayloadAsArrayBuffer = function(packets, callback) { if (!packets.length) { return callback(new ArrayBuffer(0)); } function encodeOne(packet, doneCallback) { exports.encodePacket(packet, true, true, function(data) { return doneCallback(null, data); }); } map(packets, encodeOne, function(err, encodedPackets) { var totalLength = encodedPackets.reduce(function(acc, p) { var len; if (typeof p === 'string'){ len = p.length; } else { len = p.byteLength; } return acc + len.toString().length + len + 2; // string/binary identifier + separator = 2 }, 0); var resultArray = new Uint8Array(totalLength); var bufferIndex = 0; encodedPackets.forEach(function(p) { var isString = typeof p === 'string'; var ab = p; if (isString) { var view = new Uint8Array(p.length); for (var i = 0; i < p.length; i++) { view[i] = p.charCodeAt(i); } ab = view.buffer; } if (isString) { // not true binary resultArray[bufferIndex++] = 0; } else { // true binary resultArray[bufferIndex++] = 1; } var lenStr = ab.byteLength.toString(); for (var i = 0; i < lenStr.length; i++) { resultArray[bufferIndex++] = parseInt(lenStr[i]); } resultArray[bufferIndex++] = 255; var view = new Uint8Array(ab); for (var i = 0; i < view.length; i++) { resultArray[bufferIndex++] = view[i]; } }); return callback(resultArray.buffer); }); }; /** * Encode as Blob */ exports.encodePayloadAsBlob = function(packets, callback) { function encodeOne(packet, doneCallback) { exports.encodePacket(packet, true, true, function(encoded) { var binaryIdentifier = new Uint8Array(1); binaryIdentifier[0] = 1; if (typeof encoded === 'string') { var view = new Uint8Array(encoded.length); for (var i = 0; i < encoded.length; i++) { view[i] = encoded.charCodeAt(i); } encoded = view.buffer; binaryIdentifier[0] = 0; } var len = (encoded instanceof ArrayBuffer) ? encoded.byteLength : encoded.size; var lenStr = len.toString(); var lengthAry = new Uint8Array(lenStr.length + 1); for (var i = 0; i < lenStr.length; i++) { lengthAry[i] = parseInt(lenStr[i]); } lengthAry[lenStr.length] = 255; if (Blob) { var blob = new Blob([binaryIdentifier.buffer, lengthAry.buffer, encoded]); doneCallback(null, blob); } }); } map(packets, encodeOne, function(err, results) { return callback(new Blob(results)); }); }; /* * Decodes data when a payload is maybe expected. Strings are decoded by * interpreting each byte as a key code for entries marked to start with 0. See * description of encodePayloadAsBinary * * @param {ArrayBuffer} data, callback method * @api public */ exports.decodePayloadAsBinary = function (data, binaryType, callback) { if (typeof binaryType === 'function') { callback = binaryType; binaryType = null; } var bufferTail = data; var buffers = []; var numberTooLong = false; while (bufferTail.byteLength > 0) { var tailArray = new Uint8Array(bufferTail); var isString = tailArray[0] === 0; var msgLength = ''; for (var i = 1; ; i++) { if (tailArray[i] == 255) break; if (msgLength.length > 310) { numberTooLong = true; break; } msgLength += tailArray[i]; } if(numberTooLong) return callback(err, 0, 1); bufferTail = sliceBuffer(bufferTail, 2 + msgLength.length); msgLength = parseInt(msgLength); var msg = sliceBuffer(bufferTail, 0, msgLength); if (isString) { try { msg = String.fromCharCode.apply(null, new Uint8Array(msg)); } catch (e) { // iPhone Safari doesn't let you apply to typed arrays var typed = new Uint8Array(msg); msg = ''; for (var i = 0; i < typed.length; i++) { msg += String.fromCharCode(typed[i]); } } } buffers.push(msg); bufferTail = sliceBuffer(bufferTail, msgLength); } var total = buffers.length; buffers.forEach(function(buffer, i) { callback(exports.decodePacket(buffer, binaryType, true), i, total); }); }; /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0))) /***/ }, /* 10 */ /***/ function(module, exports, __webpack_require__) { // optional / simple context binding var aFunction = __webpack_require__(26); module.exports = function(fn, that, length){ aFunction(fn); if(that === undefined)return fn; switch(length){ case 1: return function(a){ return fn.call(that, a); }; case 2: return function(a, b){ return fn.call(that, a, b); }; case 3: return function(a, b, c){ return fn.call(that, a, b, c); }; } return function(/* ...args */){ return fn.apply(that, arguments); }; }; /***/ }, /* 11 */ /***/ function(module, exports) { var hasOwnProperty = {}.hasOwnProperty; module.exports = function(it, key){ return hasOwnProperty.call(it, key); }; /***/ }, /* 12 */ /***/ function(module, exports) { module.exports = function(it){ return typeof it === 'object' ? it !== null : typeof it === 'function'; }; /***/ }, /* 13 */ /***/ function(module, exports) { module.exports = {}; /***/ }, /* 14 */ /***/ function(module, exports, __webpack_require__) { var anObject = __webpack_require__(4) , IE8_DOM_DEFINE = __webpack_require__(62) , toPrimitive = __webpack_require__(68) , dP = Object.defineProperty; exports.f = __webpack_require__(6) ? Object.defineProperty : function defineProperty(O, P, Attributes){ anObject(O); P = toPrimitive(P, true); anObject(Attributes); if(IE8_DOM_DEFINE)try { return dP(O, P, Attributes); } catch(e){ /* empty */ } if('get' in Attributes || 'set' in Attributes)throw TypeError('Accessors not supported!'); if('value' in Attributes)O[P] = Attributes.value; return O; }; /***/ }, /* 15 */ /***/ function(module, exports) { var core = module.exports = {version: '2.4.0'}; if(typeof __e == 'number')__e = core; // eslint-disable-line no-undef /***/ }, /* 16 */ /***/ function(module, exports, __webpack_require__) { // Thank's IE8 for his funny defineProperty module.exports = !__webpack_require__(22)(function(){ return Object.defineProperty({}, 'a', {get: function(){ return 7; }}).a != 7; }); /***/ }, /* 17 */ /***/ function(module, exports) { module.exports = function(a, b){ var fn = function(){}; fn.prototype = b.prototype; a.prototype = new fn; a.prototype.constructor = a; }; /***/ }, /* 18 */ /***/ function(module, exports) { var toString = {}.toString; module.exports = function(it){ return toString.call(it).slice(8, -1); }; /***/ }, /* 19 */ /***/ function(module, exports, __webpack_require__) { // to indexed object, toObject with fallback for non-array-like ES3 strings var IObject = __webpack_require__(139) , defined = __webpack_require__(27); module.exports = function(it){ return IObject(defined(it)); }; /***/ }, /* 20 */ /***/ function(module, exports, __webpack_require__) { exports.nextTick = function nextTick(fn) { setTimeout(fn, 0); }; exports.platform = exports.arch = exports.execPath = exports.title = 'browser'; exports.pid = 1; exports.browser = true; exports.env = {}; exports.argv = []; exports.binding = function (name) { throw new Error('No such module. (Possibly not yet loaded)') }; (function () { var cwd = '/'; var path; exports.cwd = function () { return cwd }; exports.chdir = function (dir) { if (!path) path = __webpack_require__(77); cwd = path.resolve(dir, cwd); }; })(); exports.exit = exports.kill = exports.umask = exports.dlopen = exports.uptime = exports.memoryUsage = exports.uvCounters = function() {}; exports.features = {}; /***/ }, /* 21 */ /***/ function(module, exports) { // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. function EventEmitter() { this._events = this._events || {}; this._maxListeners = this._maxListeners || undefined; } module.exports = EventEmitter; // Backwards-compat with node 0.10.x EventEmitter.EventEmitter = EventEmitter; EventEmitter.prototype._events = undefined; EventEmitter.prototype._maxListeners = undefined; // By default EventEmitters will print a warning if more than 10 listeners are // added to it. This is a useful default which helps finding memory leaks. EventEmitter.defaultMaxListeners = 10; // Obviously not all Emitters should be limited to 10. This function allows // that to be increased. Set to zero for unlimited. EventEmitter.prototype.setMaxListeners = function(n) { if (!isNumber(n) || n < 0 || isNaN(n)) throw TypeError('n must be a positive number'); this._maxListeners = n; return this; }; EventEmitter.prototype.emit = function(type) { var er, handler, len, args, i, listeners; if (!this._events) this._events = {}; // If there is no 'error' event listener then throw. if (type === 'error') { if (!this._events.error || (isObject(this._events.error) && !this._events.error.length)) { er = arguments[1]; if (er instanceof Error) { throw er; // Unhandled 'error' event } throw TypeError('Uncaught, unspecified "error" event.'); } } handler = this._events[type]; if (isUndefined(handler)) return false; if (isFunction(handler)) { switch (arguments.length) { // fast cases case 1: handler.call(this); break; case 2: handler.call(this, arguments[1]); break; case 3: handler.call(this, arguments[1], arguments[2]); break; // slower default: args = Array.prototype.slice.call(arguments, 1); handler.apply(this, args); } } else if (isObject(handler)) { args = Array.prototype.slice.call(arguments, 1); 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) { if (!isUndefined(this._maxListeners)) { m = this._maxListeners; } else { m = EventEmitter.defaultMaxListeners; } if (m && m > 0 && this._events[type].length > m) { this._events[type].warned = true; console.error('(node) warning: possible EventEmitter memory ' + 'leak detected. %d listeners added. ' + 'Use emitter.setMaxListeners() to increase limit.', this._events[type].length); if (typeof console.trace === 'function') { // not supported in IE 10 console.trace(); } } } return this; }; EventEmitter.prototype.on = EventEmitter.prototype.addListener; EventEmitter.prototype.once = function(type, listener) { if (!isFunction(listener)) throw TypeError('listener must be a function'); var fired = false; function g() { this.removeListener(type, g); if (!fired) { fired = true; listener.apply(this, arguments); } } g.listener = listener; this.on(type, g); return this; }; // emits a 'removeListener' event iff the listener was removed EventEmitter.prototype.removeListener = function(type, listener) { var list, position, length, i; if (!isFunction(listener)) throw TypeError('listener must be a function'); if (!this._events || !this._events[type]) return this; list = this._events[type]; length = list.length; position = -1; if (list === listener || (isFunction(list.listener) && list.listener === listener)) { delete this._events[type]; if (this._events.removeListener) this.emit('removeListener', type, listener); } else if (isObject(list)) { for (i = length; i-- > 0;) { if (list[i] === listener || (list[i].listener && list[i].listener === listener)) { position = i; break; } } if (position < 0) return this; if (list.length === 1) { list.length = 0; delete this._events[type]; } else { list.splice(position, 1); } if (this._events.removeListener) this.emit('removeListener', type, listener); } return this; }; EventEmitter.prototype.removeAllListeners = function(type) { var key, listeners; if (!this._events) return this; // not listening for removeListener, no need to emit if (!this._events.removeListener) { if (arguments.length === 0) this._events = {}; else if (this._events[type]) delete this._events[type]; return this; } // emit removeListener for all listeners on all events if (arguments.length === 0) { for (key in this._events) { if (key === 'removeListener') continue; this.removeAllListeners(key); } this.removeAllListeners('removeListener'); this._events = {}; return this; } listeners = this._events[type]; if (isFunction(listeners)) { this.removeListener(type, listeners); } else if (listeners) { // 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.prototype.listenerCount = function(type) { if (this._events) { var evlistener = this._events[type]; if (isFunction(evlistener)) return 1; else if (evlistener) return evlistener.length; } return 0; }; EventEmitter.listenerCount = function(emitter, type) { return emitter.listenerCount(type); }; 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; } /***/ }, /* 22 */ /***/ function(module, exports) { module.exports = function(exec){ try { return !!exec(); } catch(e){ return true; } }; /***/ }, /* 23 */ /***/ function(module, exports) { // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 var global = module.exports = typeof window != 'undefined' && window.Math == Math ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')(); if(typeof __g == 'number')__g = global; // eslint-disable-line no-undef /***/ }, /* 24 */ /***/ function(module, exports) { module.exports = function(it){ return typeof it === 'object' ? it !== null : typeof it === 'function'; }; /***/ }, /* 25 */ /***/ function(module, exports, __webpack_require__) { "use strict"; /* WEBPACK VAR INJECTION */(function(Buffer, global) {/*! * The buffer module from node.js, for the browser. * * @author Feross Aboukhadijeh * @license MIT */ /* eslint-disable no-proto */ 'use strict' var base64 = __webpack_require__(129) var ieee754 = __webpack_require__(183) var isArray = __webpack_require__(185) exports.Buffer = Buffer exports.SlowBuffer = SlowBuffer exports.INSPECT_MAX_BYTES = 50 /** * If `Buffer.TYPED_ARRAY_SUPPORT`: * === true Use Uint8Array implementation (fastest) * === false Use Object implementation (most compatible, even IE6) * * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, * Opera 11.6+, iOS 4.2+. * * Due to various browser bugs, sometimes the Object implementation will be used even * when the browser supports typed arrays. * * Note: * * - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances, * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. * * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. * * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of * incorrect length in some situations. * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they * get the Object implementation, which is slower but behaves correctly. */ Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined ? global.TYPED_ARRAY_SUPPORT : typedArraySupport() /* * Export kMaxLength after typed array support is determined. */ exports.kMaxLength = kMaxLength() function typedArraySupport () { try { var arr = new Uint8Array(1) arr.foo = function () { return 42 } return arr.foo() === 42 && // typed array instances can be augmented typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` } catch (e) { return false } } function kMaxLength () { return Buffer.TYPED_ARRAY_SUPPORT ? 0x7fffffff : 0x3fffffff } function createBuffer (that, length) { if (kMaxLength() < length) { throw new RangeError('Invalid typed array length') } if (Buffer.TYPED_ARRAY_SUPPORT) { // Return an augmented `Uint8Array` instance, for best performance that = new Uint8Array(length) that.__proto__ = Buffer.prototype } else { // Fallback: Return an object instance of the Buffer class if (that === null) { that = new Buffer(length) } that.length = length } return that } /** * The Buffer constructor returns instances of `Uint8Array` that have their * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of * `Uint8Array`, so the returned instances will have all the node `Buffer` methods * and the `Uint8Array` methods. Square bracket notation works as expected -- it * returns a single octet. * * The `Uint8Array` prototype remains unmodified. */ function Buffer (arg, encodingOrOffset, length) { if (!Buffer.TYPED_ARRAY_SUPPORT && !(this instanceof Buffer)) { return new Buffer(arg, encodingOrOffset, length) } // Common case. if (typeof arg === 'number') { if (typeof encodingOrOffset === 'string') { throw new Error( 'If encoding is specified then the first argument must be a string' ) } return allocUnsafe(this, arg) } return from(this, arg, encodingOrOffset, length) } Buffer.poolSize = 8192 // not used by this implementation // TODO: Legacy, not needed anymore. Remove in next major version. Buffer._augment = function (arr) { arr.__proto__ = Buffer.prototype return arr } function from (that, value, encodingOrOffset, length) { if (typeof value === 'number') { throw new TypeError('"value" argument must not be a number') } if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) { return fromArrayBuffer(that, value, encodingOrOffset, length) } if (typeof value === 'string') { return fromString(that, value, encodingOrOffset) } return fromObject(that, value) } /** * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError * if value is a number. * Buffer.from(str[, encoding]) * Buffer.from(array) * Buffer.from(buffer) * Buffer.from(arrayBuffer[, byteOffset[, length]]) **/ Buffer.from = function (value, encodingOrOffset, length) { return from(null, value, encodingOrOffset, length) } if (Buffer.TYPED_ARRAY_SUPPORT) { Buffer.prototype.__proto__ = Uint8Array.prototype Buffer.__proto__ = Uint8Array if (typeof Symbol !== 'undefined' && Symbol.species && Buffer[Symbol.species] === Buffer) { // Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97 Object.defineProperty(Buffer, Symbol.species, { value: null, configurable: true }) } } function assertSize (size) { if (typeof size !== 'number') { throw new TypeError('"size" argument must be a number') } } function alloc (that, size, fill, encoding) { assertSize(size) if (size <= 0) { return createBuffer(that, size) } if (fill !== undefined) { // Only pay attention to encoding if it's a string. This // prevents accidentally sending in a number that would // be interpretted as a start offset. return typeof encoding === 'string' ? createBuffer(that, size).fill(fill, encoding) : createBuffer(that, size).fill(fill) } return createBuffer(that, size) } /** * Creates a new filled Buffer instance. * alloc(size[, fill[, encoding]]) **/ Buffer.alloc = function (size, fill, encoding) { return alloc(null, size, fill, encoding) } function allocUnsafe (that, size) { assertSize(size) that = createBuffer(that, size < 0 ? 0 : checked(size) | 0) if (!Buffer.TYPED_ARRAY_SUPPORT) { for (var i = 0; i < size; i++) { that[i] = 0 } } return that } /** * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. * */ Buffer.allocUnsafe = function (size) { return allocUnsafe(null, size) } /** * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. */ Buffer.allocUnsafeSlow = function (size) { return allocUnsafe(null, size) } function fromString (that, string, encoding) { if (typeof encoding !== 'string' || encoding === '') { encoding = 'utf8' } if (!Buffer.isEncoding(encoding)) { throw new TypeError('"encoding" must be a valid string encoding') } var length = byteLength(string, encoding) | 0 that = createBuffer(that, length) that.write(string, encoding) return that } function fromArrayLike (that, array) { var length = checked(array.length) | 0 that = createBuffer(that, length) for (var i = 0; i < length; i += 1) { that[i] = array[i] & 255 } return that } function fromArrayBuffer (that, array, byteOffset, length) { array.byteLength // this throws if `array` is not a valid ArrayBuffer if (byteOffset < 0 || array.byteLength < byteOffset) { throw new RangeError('\'offset\' is out of bounds') } if (array.byteLength < byteOffset + (length || 0)) { throw new RangeError('\'length\' is out of bounds') } if (length === undefined) { array = new Uint8Array(array, byteOffset) } else { array = new Uint8Array(array, byteOffset, length) } if (Buffer.TYPED_ARRAY_SUPPORT) { // Return an augmented `Uint8Array` instance, for best performance that = array that.__proto__ = Buffer.prototype } else { // Fallback: Return an object instance of the Buffer class that = fromArrayLike(that, array) } return that } function fromObject (that, obj) { if (Buffer.isBuffer(obj)) { var len = checked(obj.length) | 0 that = createBuffer(that, len) if (that.length === 0) { return that } obj.copy(that, 0, 0, len) return that } if (obj) { if ((typeof ArrayBuffer !== 'undefined' && obj.buffer instanceof ArrayBuffer) || 'length' in obj) { if (typeof obj.length !== 'number' || isnan(obj.length)) { return createBuffer(that, 0) } return fromArrayLike(that, obj) } if (obj.type === 'Buffer' && isArray(obj.data)) { return fromArrayLike(that, obj.data) } } throw new TypeError('First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.') } function checked (length) { // Note: cannot use `length < kMaxLength` here because that fails when // length is NaN (which is otherwise coerced to zero.) if (length >= kMaxLength()) { throw new RangeError('Attempt to allocate Buffer larger than maximum ' + 'size: 0x' + kMaxLength().toString(16) + ' bytes') } return length | 0 } function SlowBuffer (length) { if (+length != length) { // eslint-disable-line eqeqeq length = 0 } return Buffer.alloc(+length) } Buffer.isBuffer = function isBuffer (b) { return !!(b != null && b._isBuffer) } Buffer.compare = function compare (a, b) { if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { throw new TypeError('Arguments must be Buffers') } if (a === b) return 0 var x = a.length var y = b.length for (var i = 0, len = Math.min(x, y); i < len; ++i) { if (a[i] !== b[i]) { x = a[i] y = b[i] break } } if (x < y) return -1 if (y < x) return 1 return 0 } Buffer.isEncoding = function isEncoding (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.concat = function concat (list, length) { if (!isArray(list)) { throw new TypeError('"list" argument must be an Array of Buffers') } if (list.length === 0) { return Buffer.alloc(0) } var i if (length === undefined) { length = 0 for (i = 0; i < list.length; i++) { length += list[i].length } } var buffer = Buffer.allocUnsafe(length) var pos = 0 for (i = 0; i < list.length; i++) { var buf = list[i] if (!Buffer.isBuffer(buf)) { throw new TypeError('"list" argument must be an Array of Buffers') } buf.copy(buffer, pos) pos += buf.length } return buffer } function byteLength (string, encoding) { if (Buffer.isBuffer(string)) { return string.length } if (typeof ArrayBuffer !== 'undefined' && typeof ArrayBuffer.isView === 'function' && (ArrayBuffer.isView(string) || string instanceof ArrayBuffer)) { return string.byteLength } if (typeof string !== 'string') { string = '' + string } var len = string.length if (len === 0) return 0 // Use a for loop to avoid recursion var loweredCase = false for (;;) { switch (encoding) { case 'ascii': case 'binary': // Deprecated case 'raw': case 'raws': return len case 'utf8': case 'utf-8': case undefined: return utf8ToBytes(string).length case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return len * 2 case 'hex': return len >>> 1 case 'base64': return base64ToBytes(string).length default: if (loweredCase) return utf8ToBytes(string).length // assume utf8 encoding = ('' + encoding).toLowerCase() loweredCase = true } } } Buffer.byteLength = byteLength function slowToString (encoding, start, end) { var loweredCase = false // No need to verify that "this.length <= MAX_UINT32" since it's a read-only // property of a typed array. // This behaves neither like String nor Uint8Array in that we set start/end // to their upper/lower bounds if the value passed is out of range. // undefined is handled specially as per ECMA-262 6th Edition, // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization. if (start === undefined || start < 0) { start = 0 } // Return early if start > this.length. Done here to prevent potential uint32 // coercion fail below. if (start > this.length) { return '' } if (end === undefined || end > this.length) { end = this.length } if (end <= 0) { return '' } // Force coersion to uint32. This will also coerce falsey/NaN values to 0. end >>>= 0 start >>>= 0 if (end <= start) { return '' } if (!encoding) encoding = 'utf8' while (true) { switch (encoding) { case 'hex': return hexSlice(this, start, end) case 'utf8': case 'utf-8': return utf8Slice(this, start, end) case 'ascii': return asciiSlice(this, start, end) case 'binary': return binarySlice(this, start, end) case 'base64': return base64Slice(this, start, end) case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return utf16leSlice(this, start, end) default: if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) encoding = (encoding + '').toLowerCase() loweredCase = true } } } // The property is used by `Buffer.isBuffer` and `is-buffer` (in Safari 5-7) to detect // Buffer instances. Buffer.prototype._isBuffer = true function swap (b, n, m) { var i = b[n] b[n] = b[m] b[m] = i } Buffer.prototype.swap16 = function swap16 () { var len = this.length if (len % 2 !== 0) { throw new RangeError('Buffer size must be a multiple of 16-bits') } for (var i = 0; i < len; i += 2) { swap(this, i, i + 1) } return this } Buffer.prototype.swap32 = function swap32 () { var len = this.length if (len % 4 !== 0) { throw new RangeError('Buffer size must be a multiple of 32-bits') } for (var i = 0; i < len; i += 4) { swap(this, i, i + 3) swap(this, i + 1, i + 2) } return this } Buffer.prototype.toString = function toString () { var length = this.length | 0 if (length === 0) return '' if (arguments.length === 0) return utf8Slice(this, 0, length) return slowToString.apply(this, arguments) } Buffer.prototype.equals = function equals (b) { if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') if (this === b) return true return Buffer.compare(this, b) === 0 } Buffer.prototype.inspect = function inspect () { var str = '' var max = exports.INSPECT_MAX_BYTES if (this.length > 0) { str = this.toString('hex', 0, max).match(/.{2}/g).join(' ') if (this.length > max) str += ' ... ' } return '' } Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) { if (!Buffer.isBuffer(target)) { throw new TypeError('Argument must be a Buffer') } if (start === undefined) { start = 0 } if (end === undefined) { end = target ? target.length : 0 } if (thisStart === undefined) { thisStart = 0 } if (thisEnd === undefined) { thisEnd = this.length } if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) { throw new RangeError('out of range index') } if (thisStart >= thisEnd && start >= end) { return 0 } if (thisStart >= thisEnd) { return -1 } if (start >= end) { return 1 } start >>>= 0 end >>>= 0 thisStart >>>= 0 thisEnd >>>= 0 if (this === target) return 0 var x = thisEnd - thisStart var y = end - start var len = Math.min(x, y) var thisCopy = this.slice(thisStart, thisEnd) var targetCopy = target.slice(start, end) for (var i = 0; i < len; ++i) { if (thisCopy[i] !== targetCopy[i]) { x = thisCopy[i] y = targetCopy[i] break } } if (x < y) return -1 if (y < x) return 1 return 0 } function arrayIndexOf (arr, val, byteOffset, encoding) { var indexSize = 1 var arrLength = arr.length var valLength = val.length if (encoding !== undefined) { encoding = String(encoding).toLowerCase() if (encoding === 'ucs2' || encoding === 'ucs-2' || encoding === 'utf16le' || encoding === 'utf-16le') { if (arr.length < 2 || val.length < 2) { return -1 } indexSize = 2 arrLength /= 2 valLength /= 2 byteOffset /= 2 } } function read (buf, i) { if (indexSize === 1) { return buf[i] } else { return buf.readUInt16BE(i * indexSize) } } var foundIndex = -1 for (var i = 0; byteOffset + i < arrLength; i++) { if (read(arr, byteOffset + i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { if (foundIndex === -1) foundIndex = i if (i - foundIndex + 1 === valLength) return (byteOffset + foundIndex) * indexSize } else { if (foundIndex !== -1) i -= i - foundIndex foundIndex = -1 } } return -1 } Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) { if (typeof byteOffset === 'string') { encoding = byteOffset byteOffset = 0 } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff } else if (byteOffset < -0x80000000) { byteOffset = -0x80000000 } byteOffset >>= 0 if (this.length === 0) return -1 if (byteOffset >= this.length) return -1 // Negative offsets start from the end of the buffer if (byteOffset < 0) byteOffset = Math.max(this.length + byteOffset, 0) if (typeof val === 'string') { val = Buffer.from(val, encoding) } if (Buffer.isBuffer(val)) { // special case: looking for empty string/buffer always fails if (val.length === 0) { return -1 } return arrayIndexOf(this, val, byteOffset, encoding) } if (typeof val === 'number') { if (Buffer.TYPED_ARRAY_SUPPORT && Uint8Array.prototype.indexOf === 'function') { return Uint8Array.prototype.indexOf.call(this, val, byteOffset) } return arrayIndexOf(this, [ val ], byteOffset, encoding) } throw new TypeError('val must be string, number or Buffer') } Buffer.prototype.includes = function includes (val, byteOffset, encoding) { return this.indexOf(val, byteOffset, encoding) !== -1 } 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 if (strLen % 2 !== 0) throw new Error('Invalid hex string') if (length > strLen / 2) { length = strLen / 2 } for (var i = 0; i < length; i++) { var parsed = parseInt(string.substr(i * 2, 2), 16) if (isNaN(parsed)) return i buf[offset + i] = parsed } return i } function utf8Write (buf, string, offset, length) { return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) } function asciiWrite (buf, string, offset, length) { return blitBuffer(asciiToBytes(string), buf, offset, length) } function binaryWrite (buf, string, offset, length) { return asciiWrite(buf, string, offset, length) } function base64Write (buf, string, offset, length) { return blitBuffer(base64ToBytes(string), buf, offset, length) } function ucs2Write (buf, string, offset, length) { return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) } Buffer.prototype.write = function write (string, offset, length, encoding) { // Buffer#write(string) if (offset === undefined) { encoding = 'utf8' length = this.length offset = 0 // Buffer#write(string, encoding) } else if (length === undefined && typeof offset === 'string') { encoding = offset length = this.length offset = 0 // Buffer#write(string, offset[, length][, encoding]) } else if (isFinite(offset)) { offset = offset | 0 if (isFinite(length)) { length = length | 0 if (encoding === undefined) encoding = 'utf8' } else { encoding = length length = undefined } // legacy write(string, encoding, offset, length) - remove in v0.13 } else { throw new Error( 'Buffer.write(string, encoding, offset[, length]) is no longer supported' ) } var remaining = this.length - offset if (length === undefined || length > remaining) length = remaining if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { throw new RangeError('Attempt to write outside buffer bounds') } if (!encoding) encoding = 'utf8' var loweredCase = false for (;;) { switch (encoding) { case 'hex': return hexWrite(this, string, offset, length) case 'utf8': case 'utf-8': return utf8Write(this, string, offset, length) case 'ascii': return asciiWrite(this, string, offset, length) case 'binary': return binaryWrite(this, string, offset, length) case 'base64': // Warning: maxLength not taken into account in base64Write return base64Write(this, string, offset, length) case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return ucs2Write(this, string, offset, length) default: if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) encoding = ('' + encoding).toLowerCase() loweredCase = true } } } Buffer.prototype.toJSON = function toJSON () { return { type: 'Buffer', data: Array.prototype.slice.call(this._arr || this, 0) } } 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) { end = Math.min(buf.length, end) var res = [] var i = start while (i < end) { var firstByte = buf[i] var codePoint = null var bytesPerSequence = (firstByte > 0xEF) ? 4 : (firstByte > 0xDF) ? 3 : (firstByte > 0xBF) ? 2 : 1 if (i + bytesPerSequence <= end) { var secondByte, thirdByte, fourthByte, tempCodePoint switch (bytesPerSequence) { case 1: if (firstByte < 0x80) { codePoint = firstByte } break case 2: secondByte = buf[i + 1] if ((secondByte & 0xC0) === 0x80) { tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F) if (tempCodePoint > 0x7F) { codePoint = tempCodePoint } } break case 3: secondByte = buf[i + 1] thirdByte = buf[i + 2] if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F) if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { codePoint = tempCodePoint } } break case 4: secondByte = buf[i + 1] thirdByte = buf[i + 2] fourthByte = buf[i + 3] if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F) if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { codePoint = tempCodePoint } } } } if (codePoint === null) { // we did not generate a valid codePoint so insert a // replacement char (U+FFFD) and advance only 1 byte codePoint = 0xFFFD bytesPerSequence = 1 } else if (codePoint > 0xFFFF) { // encode to utf16 (surrogate pair dance) codePoint -= 0x10000 res.push(codePoint >>> 10 & 0x3FF | 0xD800) codePoint = 0xDC00 | codePoint & 0x3FF } res.push(codePoint) i += bytesPerSequence } return decodeCodePointsArray(res) } // Based on http://stackoverflow.com/a/22747272/680742, the browser with // the lowest limit is Chrome, with 0x10000 args. // We go 1 magnitude less, for safety var MAX_ARGUMENTS_LENGTH = 0x1000 function decodeCodePointsArray (codePoints) { var len = codePoints.length if (len <= MAX_ARGUMENTS_LENGTH) { return String.fromCharCode.apply(String, codePoints) // avoid extra slice() } // Decode in chunks to avoid "call stack size exceeded". var res = '' var i = 0 while (i < len) { res += String.fromCharCode.apply( String, codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) ) } return res } 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] & 0x7F) } return ret } function binarySlice (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 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 slice (start, end) { var len = this.length start = ~~start end = end === undefined ? len : ~~end if (start < 0) { start += len if (start < 0) start = 0 } else if (start > len) { start = len } if (end < 0) { end += len if (end < 0) end = 0 } else if (end > len) { end = len } if (end < start) end = start var newBuf if (Buffer.TYPED_ARRAY_SUPPORT) { newBuf = this.subarray(start, end) newBuf.__proto__ = Buffer.prototype } else { var sliceLen = end - start newBuf = new Buffer(sliceLen, undefined) for (var i = 0; i < sliceLen; i++) { newBuf[i] = this[i + start] } } return newBuf } /* * Need to make sure that buffer isn't trying to write out of bounds. */ function checkOffset (offset, ext, length) { if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') } Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { offset = offset | 0 byteLength = byteLength | 0 if (!noAssert) checkOffset(offset, byteLength, this.length) var val = this[offset] var mul = 1 var i = 0 while (++i < byteLength && (mul *= 0x100)) { val += this[offset + i] * mul } return val } Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { offset = offset | 0 byteLength = byteLength | 0 if (!noAssert) { checkOffset(offset, byteLength, this.length) } var val = this[offset + --byteLength] var mul = 1 while (byteLength > 0 && (mul *= 0x100)) { val += this[offset + --byteLength] * mul } return val } Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { if (!noAssert) checkOffset(offset, 1, this.length) return this[offset] } Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { if (!noAssert) checkOffset(offset, 2, this.length) return this[offset] | (this[offset + 1] << 8) } Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { if (!noAssert) checkOffset(offset, 2, this.length) return (this[offset] << 8) | this[offset + 1] } Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length) return ((this[offset]) | (this[offset + 1] << 8) | (this[offset + 2] << 16)) + (this[offset + 3] * 0x1000000) } Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length) return (this[offset] * 0x1000000) + ((this[offset + 1] << 16) | (this[offset + 2] << 8) | this[offset + 3]) } Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { offset = offset | 0 byteLength = byteLength | 0 if (!noAssert) checkOffset(offset, byteLength, this.length) var val = this[offset] var mul = 1 var i = 0 while (++i < byteLength && (mul *= 0x100)) { val += this[offset + i] * mul } mul *= 0x80 if (val >= mul) val -= Math.pow(2, 8 * byteLength) return val } Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { offset = offset | 0 byteLength = byteLength | 0 if (!noAssert) checkOffset(offset, byteLength, this.length) var i = byteLength var mul = 1 var val = this[offset + --i] while (i > 0 && (mul *= 0x100)) { val += this[offset + --i] * mul } mul *= 0x80 if (val >= mul) val -= Math.pow(2, 8 * byteLength) return val } Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { if (!noAssert) checkOffset(offset, 1, this.length) if (!(this[offset] & 0x80)) return (this[offset]) return ((0xff - this[offset] + 1) * -1) } Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { if (!noAssert) checkOffset(offset, 2, this.length) var val = this[offset] | (this[offset + 1] << 8) return (val & 0x8000) ? val | 0xFFFF0000 : val } Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { if (!noAssert) checkOffset(offset, 2, this.length) var val = this[offset + 1] | (this[offset] << 8) return (val & 0x8000) ? val | 0xFFFF0000 : val } Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length) return (this[offset]) | (this[offset + 1] << 8) | (this[offset + 2] << 16) | (this[offset + 3] << 24) } Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length) return (this[offset] << 24) | (this[offset + 1] << 16) | (this[offset + 2] << 8) | (this[offset + 3]) } Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length) return ieee754.read(this, offset, true, 23, 4) } Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length) return ieee754.read(this, offset, false, 23, 4) } Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { if (!noAssert) checkOffset(offset, 8, this.length) return ieee754.read(this, offset, true, 52, 8) } Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { if (!noAssert) checkOffset(offset, 8, this.length) return ieee754.read(this, offset, false, 52, 8) } function checkInt (buf, value, offset, ext, max, min) { if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance') if (value > max || value < min) throw new RangeError('"value" argument is out of bounds') if (offset + ext > buf.length) throw new RangeError('Index out of range') } Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { value = +value offset = offset | 0 byteLength = byteLength | 0 if (!noAssert) { var maxBytes = Math.pow(2, 8 * byteLength) - 1 checkInt(this, value, offset, byteLength, maxBytes, 0) } var mul = 1 var i = 0 this[offset] = value & 0xFF while (++i < byteLength && (mul *= 0x100)) { this[offset + i] = (value / mul) & 0xFF } return offset + byteLength } Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { value = +value offset = offset | 0 byteLength = byteLength | 0 if (!noAssert) { var maxBytes = Math.pow(2, 8 * byteLength) - 1 checkInt(this, value, offset, byteLength, maxBytes, 0) } var i = byteLength - 1 var mul = 1 this[offset + i] = value & 0xFF while (--i >= 0 && (mul *= 0x100)) { this[offset + i] = (value / mul) & 0xFF } return offset + byteLength } Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) this[offset] = (value & 0xff) return offset + 1 } function objectWriteUInt16 (buf, value, offset, littleEndian) { if (value < 0) value = 0xffff + value + 1 for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) { buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> (littleEndian ? i : 1 - i) * 8 } } Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff) this[offset + 1] = (value >>> 8) } else { objectWriteUInt16(this, value, offset, true) } return offset + 2 } Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8) this[offset + 1] = (value & 0xff) } else { objectWriteUInt16(this, value, offset, false) } return offset + 2 } function objectWriteUInt32 (buf, value, offset, littleEndian) { if (value < 0) value = 0xffffffff + value + 1 for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) { buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff } } Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset + 3] = (value >>> 24) this[offset + 2] = (value >>> 16) this[offset + 1] = (value >>> 8) this[offset] = (value & 0xff) } else { objectWriteUInt32(this, value, offset, true) } return offset + 4 } Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24) this[offset + 1] = (value >>> 16) this[offset + 2] = (value >>> 8) this[offset + 3] = (value & 0xff) } else { objectWriteUInt32(this, value, offset, false) } return offset + 4 } Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { value = +value offset = offset | 0 if (!noAssert) { var limit = Math.pow(2, 8 * byteLength - 1) checkInt(this, value, offset, byteLength, limit - 1, -limit) } var i = 0 var mul = 1 var sub = 0 this[offset] = value & 0xFF while (++i < byteLength && (mul *= 0x100)) { if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) { sub = 1 } this[offset + i] = ((value / mul) >> 0) - sub & 0xFF } return offset + byteLength } Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { value = +value offset = offset | 0 if (!noAssert) { var limit = Math.pow(2, 8 * byteLength - 1) checkInt(this, value, offset, byteLength, limit - 1, -limit) } var i = byteLength - 1 var mul = 1 var sub = 0 this[offset + i] = value & 0xFF while (--i >= 0 && (mul *= 0x100)) { if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) { sub = 1 } this[offset + i] = ((value / mul) >> 0) - sub & 0xFF } return offset + byteLength } Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) if (value < 0) value = 0xff + value + 1 this[offset] = (value & 0xff) return offset + 1 } Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff) this[offset + 1] = (value >>> 8) } else { objectWriteUInt16(this, value, offset, true) } return offset + 2 } Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8) this[offset + 1] = (value & 0xff) } else { objectWriteUInt16(this, value, offset, false) } return offset + 2 } Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff) this[offset + 1] = (value >>> 8) this[offset + 2] = (value >>> 16) this[offset + 3] = (value >>> 24) } else { objectWriteUInt32(this, value, offset, true) } return offset + 4 } Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) if (value < 0) value = 0xffffffff + value + 1 if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24) this[offset + 1] = (value >>> 16) this[offset + 2] = (value >>> 8) this[offset + 3] = (value & 0xff) } else { objectWriteUInt32(this, value, offset, false) } return offset + 4 } function checkIEEE754 (buf, value, offset, ext, max, min) { if (offset + ext > buf.length) throw new RangeError('Index out of range') if (offset < 0) throw new RangeError('Index out of range') } function writeFloat (buf, value, offset, littleEndian, noAssert) { if (!noAssert) { checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) } ieee754.write(buf, value, offset, littleEndian, 23, 4) return offset + 4 } Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { return writeFloat(this, value, offset, true, noAssert) } Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { return writeFloat(this, value, offset, false, noAssert) } function writeDouble (buf, value, offset, littleEndian, noAssert) { if (!noAssert) { checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) } ieee754.write(buf, value, offset, littleEndian, 52, 8) return offset + 8 } Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { return writeDouble(this, value, offset, true, noAssert) } Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { return writeDouble(this, value, offset, false, noAssert) } // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) Buffer.prototype.copy = function copy (target, targetStart, start, end) { if (!start) start = 0 if (!end && end !== 0) end = this.length if (targetStart >= target.length) targetStart = target.length if (!targetStart) targetStart = 0 if (end > 0 && end < start) end = start // Copy 0 bytes; we're done if (end === start) return 0 if (target.length === 0 || this.length === 0) return 0 // Fatal error conditions if (targetStart < 0) { throw new RangeError('targetStart out of bounds') } if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds') if (end < 0) throw new RangeError('sourceEnd out of bounds') // Are we oob? if (end > this.length) end = this.length if (target.length - targetStart < end - start) { end = target.length - targetStart + start } var len = end - start var i if (this === target && start < targetStart && targetStart < end) { // descending copy from end for (i = len - 1; i >= 0; i--) { target[i + targetStart] = this[i + start] } } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) { // ascending copy from start for (i = 0; i < len; i++) { target[i + targetStart] = this[i + start] } } else { Uint8Array.prototype.set.call( target, this.subarray(start, start + len), targetStart ) } return len } // Usage: // buffer.fill(number[, offset[, end]]) // buffer.fill(buffer[, offset[, end]]) // buffer.fill(string[, offset[, end]][, encoding]) Buffer.prototype.fill = function fill (val, start, end, encoding) { // Handle string cases: if (typeof val === 'string') { if (typeof start === 'string') { encoding = start start = 0 end = this.length } else if (typeof end === 'string') { encoding = end end = this.length } if (val.length === 1) { var code = val.charCodeAt(0) if (code < 256) { val = code } } if (encoding !== undefined && typeof encoding !== 'string') { throw new TypeError('encoding must be a string') } if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) { throw new TypeError('Unknown encoding: ' + encoding) } } else if (typeof val === 'number') { val = val & 255 } // Invalid ranges are not set to a default, so can range check early. if (start < 0 || this.length < start || this.length < end) { throw new RangeError('Out of range index') } if (end <= start) { return this } start = start >>> 0 end = end === undefined ? this.length : end >>> 0 if (!val) val = 0 var i if (typeof val === 'number') { for (i = start; i < end; i++) { this[i] = val } } else { var bytes = Buffer.isBuffer(val) ? val : utf8ToBytes(new Buffer(val, encoding).toString()) var len = bytes.length for (i = 0; i < end - start; i++) { this[i + start] = bytes[i % len] } } return this } // HELPER FUNCTIONS // ================ var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g function base64clean (str) { // Node strips out invalid characters like \n and \t from the string, base64-js does not str = stringtrim(str).replace(INVALID_BASE64_RE, '') // Node converts strings with length < 2 to '' if (str.length < 2) return '' // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not while (str.length % 4 !== 0) { str = str + '=' } return str } function stringtrim (str) { if (str.trim) return str.trim() return str.replace(/^\s+|\s+$/g, '') } function toHex (n) { if (n < 16) return '0' + n.toString(16) return n.toString(16) } function utf8ToBytes (string, units) { units = units || Infinity var codePoint var length = string.length var leadSurrogate = null var bytes = [] for (var i = 0; i < length; i++) { codePoint = string.charCodeAt(i) // is surrogate component if (codePoint > 0xD7FF && codePoint < 0xE000) { // last char was a lead if (!leadSurrogate) { // no lead yet if (codePoint > 0xDBFF) { // unexpected trail if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) continue } else if (i + 1 === length) { // unpaired lead if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) continue } // valid lead leadSurrogate = codePoint continue } // 2 leads in a row if (codePoint < 0xDC00) { if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) leadSurrogate = codePoint continue } // valid surrogate pair codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000 } else if (leadSurrogate) { // valid bmp char, but last char was a lead if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) } leadSurrogate = null // encode utf8 if (codePoint < 0x80) { if ((units -= 1) < 0) break bytes.push(codePoint) } else if (codePoint < 0x800) { if ((units -= 2) < 0) break bytes.push( codePoint >> 0x6 | 0xC0, codePoint & 0x3F | 0x80 ) } else if (codePoint < 0x10000) { if ((units -= 3) < 0) break bytes.push( codePoint >> 0xC | 0xE0, codePoint >> 0x6 & 0x3F | 0x80, codePoint & 0x3F | 0x80 ) } else if (codePoint < 0x110000) { if ((units -= 4) < 0) break bytes.push( codePoint >> 0x12 | 0xF0, codePoint >> 0xC & 0x3F | 0x80, codePoint >> 0x6 & 0x3F | 0x80, codePoint & 0x3F | 0x80 ) } else { throw new Error('Invalid code point') } } return bytes } 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, units) { var c, hi, lo var byteArray = [] for (var i = 0; i < str.length; i++) { if ((units -= 2) < 0) break c = str.charCodeAt(i) hi = c >> 8 lo = c % 256 byteArray.push(lo) byteArray.push(hi) } return byteArray } function base64ToBytes (str) { return base64.toByteArray(base64clean(str)) } function blitBuffer (src, dst, offset, length) { for (var i = 0; i < length; i++) { if ((i + offset >= dst.length) || (i >= src.length)) break dst[i + offset] = src[i] } return i } function isnan (val) { return val !== val // eslint-disable-line no-self-compare } /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(25).Buffer, __webpack_require__(0))) /***/ }, /* 26 */ /***/ function(module, exports) { module.exports = function(it){ if(typeof it != 'function')throw TypeError(it + ' is not a function!'); return it; }; /***/ }, /* 27 */ /***/ function(module, exports) { // 7.2.1 RequireObjectCoercible(argument) module.exports = function(it){ if(it == undefined)throw TypeError("Can't call method on " + it); return it; }; /***/ }, /* 28 */ /***/ function(module, exports, __webpack_require__) { var isObject = __webpack_require__(12) , document = __webpack_require__(2).document // in old IE typeof document.createElement is 'object' , is = isObject(document) && isObject(document.createElement); module.exports = function(it){ return is ? document.createElement(it) : {}; }; /***/ }, /* 29 */ /***/ function(module, exports, __webpack_require__) { var global = __webpack_require__(2) , core = __webpack_require__(5) , ctx = __webpack_require__(10) , hide = __webpack_require__(8) , PROTOTYPE = 'prototype'; var $export = function(type, name, source){ var IS_FORCED = type & $export.F , IS_GLOBAL = type & $export.G , IS_STATIC = type & $export.S , IS_PROTO = type & $export.P , IS_BIND = type & $export.B , IS_WRAP = type & $export.W , exports = IS_GLOBAL ? core : core[name] || (core[name] = {}) , expProto = exports[PROTOTYPE] , target = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {})[PROTOTYPE] , key, own, out; if(IS_GLOBAL)source = name; for(key in source){ // contains in native own = !IS_FORCED && target && target[key] !== undefined; if(own && key in exports)continue; // export native or passed out = own ? target[key] : source[key]; // prevent global pollution for namespaces exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key] // bind timers to global for call from export context : IS_BIND && own ? ctx(out, global) // wrap global constructors for prevent change them in library : IS_WRAP && target[key] == out ? (function(C){ var F = function(a, b, c){ if(this instanceof C){ switch(arguments.length){ case 0: return new C; case 1: return new C(a); case 2: return new C(a, b); } return new C(a, b, c); } return C.apply(this, arguments); }; F[PROTOTYPE] = C[PROTOTYPE]; return F; // make static versions for prototype methods })(out) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out; // export proto methods to core.%CONSTRUCTOR%.methods.%NAME% if(IS_PROTO){ (exports.virtual || (exports.virtual = {}))[key] = out; // export proto methods to core.%CONSTRUCTOR%.prototype.%NAME% if(type & $export.R && expProto && !expProto[key])hide(expProto, key, out); } } }; // type bitmap $export.F = 1; // forced $export.G = 2; // global $export.S = 4; // static $export.P = 8; // proto $export.B = 16; // bind $export.W = 32; // wrap $export.U = 64; // safe $export.R = 128; // real proto method for `library` module.exports = $export; /***/ }, /* 30 */ /***/ function(module, exports) { module.exports = function(bitmap, value){ return { enumerable : !(bitmap & 1), configurable: !(bitmap & 2), writable : !(bitmap & 4), value : value }; }; /***/ }, /* 31 */ /***/ function(module, exports, __webpack_require__) { var def = __webpack_require__(14).f , has = __webpack_require__(11) , TAG = __webpack_require__(1)('toStringTag'); module.exports = function(it, tag, stat){ if(it && !has(it = stat ? it : it.prototype, TAG))def(it, TAG, {configurable: true, value: tag}); }; /***/ }, /* 32 */ /***/ function(module, exports, __webpack_require__) { var shared = __webpack_require__(65)('keys') , uid = __webpack_require__(69); module.exports = function(key){ return shared[key] || (shared[key] = uid(key)); }; /***/ }, /* 33 */ /***/ function(module, exports) { // 7.1.4 ToInteger var ceil = Math.ceil , floor = Math.floor; module.exports = function(it){ return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it); }; /***/ }, /* 34 */ /***/ function(module, exports, __webpack_require__) { /** * Module dependencies. */ var parser = __webpack_require__(9); var Emitter = __webpack_require__(36); /** * Module exports. */ module.exports = Transport; /** * Transport abstract constructor. * * @param {Object} options. * @api private */ function Transport (opts) { this.path = opts.path; this.hostname = opts.hostname; this.port = opts.port; this.secure = opts.secure; this.query = opts.query; this.timestampParam = opts.timestampParam; this.timestampRequests = opts.timestampRequests; this.readyState = ''; this.agent = opts.agent || false; this.socket = opts.socket; this.enablesXDR = opts.enablesXDR; // SSL options for Node.js client this.pfx = opts.pfx; this.key = opts.key; this.passphrase = opts.passphrase; this.cert = opts.cert; this.ca = opts.ca; this.ciphers = opts.ciphers; this.rejectUnauthorized = opts.rejectUnauthorized; // other options for Node.js client this.extraHeaders = opts.extraHeaders; } /** * Mix in `Emitter`. */ Emitter(Transport.prototype); /** * Emits an error. * * @param {String} str * @return {Transport} for chaining * @api public */ Transport.prototype.onError = function (msg, desc) { var err = new Error(msg); err.type = 'TransportError'; err.description = desc; this.emit('error', err); return this; }; /** * Opens the transport. * * @api public */ Transport.prototype.open = function () { if ('closed' == this.readyState || '' == this.readyState) { this.readyState = 'opening'; this.doOpen(); } return this; }; /** * Closes the transport. * * @api private */ Transport.prototype.close = function () { if ('opening' == this.readyState || 'open' == this.readyState) { this.doClose(); this.onClose(); } return this; }; /** * Sends multiple packets. * * @param {Array} packets * @api private */ Transport.prototype.send = function(packets){ if ('open' == this.readyState) { this.write(packets); } else { throw new Error('Transport not open'); } }; /** * Called upon open * * @api private */ Transport.prototype.onOpen = function () { this.readyState = 'open'; this.writable = true; this.emit('open'); }; /** * Called with data. * * @param {String} data * @api private */ Transport.prototype.onData = function(data){ var packet = parser.decodePacket(data, this.socket.binaryType); this.onPacket(packet); }; /** * Called with a decoded packet. */ Transport.prototype.onPacket = function (packet) { this.emit('packet', packet); }; /** * Called upon close. * * @api private */ Transport.prototype.onClose = function () { this.readyState = 'closed'; this.emit('close'); }; /***/ }, /* 35 */ /***/ function(module, exports, __webpack_require__) { // browser shim for xmlhttprequest module var hasCORS = __webpack_require__(182); module.exports = function(opts) { var xdomain = opts.xdomain; // scheme must be same when usign XDomainRequest // http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx var xscheme = opts.xscheme; // XDomainRequest has a flow of not sending cookie, therefore it should be disabled as a default. // https://github.com/Automattic/engine.io-client/pull/217 var enablesXDR = opts.enablesXDR; // XMLHttpRequest can be disabled on IE try { if ('undefined' != typeof XMLHttpRequest && (!xdomain || hasCORS)) { return new XMLHttpRequest(); } } catch (e) { } // Use XDomainRequest for IE8 if enablesXDR is true // because loading bar keeps flashing when using jsonp-polling // https://github.com/yujiosaka/socke.io-ie8-loading-example try { if ('undefined' != typeof XDomainRequest && !xscheme && enablesXDR) { return new XDomainRequest(); } } catch (e) { } if (!xdomain) { try { return new ActiveXObject('Microsoft.XMLHTTP'); } catch(e) { } } } /***/ }, /* 36 */ /***/ function(module, exports) { /** * Expose `Emitter`. */ module.exports = Emitter; /** * Initialize a new `Emitter`. * * @api public */ function Emitter(obj) { if (obj) return mixin(obj); }; /** * Mixin the emitter properties. * * @param {Object} obj * @return {Object} * @api private */ function mixin(obj) { for (var key in Emitter.prototype) { obj[key] = Emitter.prototype[key]; } return obj; } /** * Listen on the given `event` with `fn`. * * @param {String} event * @param {Function} fn * @return {Emitter} * @api public */ Emitter.prototype.on = Emitter.prototype.addEventListener = function(event, fn){ this._callbacks = this._callbacks || {}; (this._callbacks[event] = this._callbacks[event] || []) .push(fn); return this; }; /** * Adds an `event` listener that will be invoked a single * time then automatically removed. * * @param {String} event * @param {Function} fn * @return {Emitter} * @api public */ Emitter.prototype.once = function(event, fn){ var self = this; this._callbacks = this._callbacks || {}; function on() { self.off(event, on); fn.apply(this, arguments); } on.fn = fn; this.on(event, on); return this; }; /** * Remove the given callback for `event` or all * registered callbacks. * * @param {String} event * @param {Function} fn * @return {Emitter} * @api public */ Emitter.prototype.off = Emitter.prototype.removeListener = Emitter.prototype.removeAllListeners = Emitter.prototype.removeEventListener = function(event, fn){ this._callbacks = this._callbacks || {}; // all if (0 == arguments.length) { this._callbacks = {}; return this; } // specific event var callbacks = this._callbacks[event]; if (!callbacks) return this; // remove all handlers if (1 == arguments.length) { delete this._callbacks[event]; return this; } // remove specific handler var cb; for (var i = 0; i < callbacks.length; i++) { cb = callbacks[i]; if (cb === fn || cb.fn === fn) { callbacks.splice(i, 1); break; } } return this; }; /** * Emit `event` with the given args. * * @param {String} event * @param {Mixed} ... * @return {Emitter} */ Emitter.prototype.emit = function(event){ this._callbacks = this._callbacks || {}; var args = [].slice.call(arguments, 1) , callbacks = this._callbacks[event]; if (callbacks) { callbacks = callbacks.slice(0); for (var i = 0, len = callbacks.length; i < len; ++i) { callbacks[i].apply(this, args); } } return this; }; /** * Return array of callbacks for `event`. * * @param {String} event * @return {Array} * @api public */ Emitter.prototype.listeners = function(event){ this._callbacks = this._callbacks || {}; return this._callbacks[event] || []; }; /** * Check if this emitter has `event` handlers. * * @param {String} event * @return {Boolean} * @api public */ Emitter.prototype.hasListeners = function(event){ return !! this.listeners(event).length; }; /***/ }, /* 37 */ /***/ function(module, exports, __webpack_require__) { "use strict"; 'use strict'; const EventEmitter = __webpack_require__(21).EventEmitter; const Log = __webpack_require__(123); const Index = __webpack_require__(192); const Cache = __webpack_require__(191); class Store { constructor(ipfs, id, dbname, options) { this.id = id; this.dbname = dbname; this.events = new EventEmitter(); if(!options) options = {}; if(!options.Index) Object.assign(options, { Index: Index }); if(!options.cacheFile) Object.assign(options, { cacheFile: null }); this.options = options; this._index = new this.options.Index(this.id); this._oplog = null; this._ipfs = ipfs; this._lastWrite = null; } use() { this.events.emit('load', this.dbname); this._oplog = new Log(this._ipfs, this.id, this.dbname, this.options); return Cache.loadCache(this.options.cacheFile).then(() => { const cached = Cache.get(this.dbname); if(cached) { this._lastWrite = cached; return Log.fromIpfsHash(this._ipfs, cached) .then((log) => this._oplog.join(log)) .then((merged) => this._index.updateIndex(this._oplog, merged)) .then(() => this.events.emit('ready', this.dbname)) .then(() => this) } this.events.emit('ready', this.dbname) return Promise.resolve(this); }); } close() { this.events.emit('close', this.dbname); } sync(hash) { if(!hash || hash === this._lastWrite) { this.events.emit('updated', this.dbname, []); return Promise.resolve([]); } const oldCount = this._oplog.items.length; let newItems = []; this.events.emit('sync', this.dbname); this._lastWrite = hash; return Log.fromIpfsHash(this._ipfs, hash) .then((log) => this._oplog.join(log)) .then((merged) => newItems = merged) .then(() => Cache.set(this.dbname, hash)) .then(() => this._index.updateIndex(this._oplog, newItems)) .then(() => { // if(newItems.length > 0) this.events.emit('updated', this.dbname, newItems); }) .then(() => newItems) } delete() { this._index = new this.options.Index(this.id); if(this._oplog) this._oplog.clear(); } _addOperation(data) { let result, logHash; if(this._oplog) { return this._oplog.add(data) .then((res) => result = res) .then(() => Log.getIpfsHash(this._ipfs, this._oplog)) .then((hash) => logHash = hash) .then(() => this._lastWrite = logHash) .then(() => Cache.set(this.dbname, logHash)) .then(() => this._index.updateIndex(this._oplog, [result])) .then(() => this.events.emit('data', this.dbname, logHash)) .then(() => result.hash); } } } module.exports = Store; /***/ }, /* 38 */ /***/ function(module, exports) { /** * Compiles a querystring * Returns string representation of the object * * @param {Object} * @api private */ exports.encode = function (obj) { var str = ''; for (var i in obj) { if (obj.hasOwnProperty(i)) { if (str.length) str += '&'; str += encodeURIComponent(i) + '=' + encodeURIComponent(obj[i]); } } return str; }; /** * Parses a simple querystring into an object * * @param {String} qs * @api private */ exports.decode = function(qs){ var qry = {}; var pairs = qs.split('&'); for (var i = 0, l = pairs.length; i < l; i++) { var pair = pairs[i].split('='); qry[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]); } return qry; }; /***/ }, /* 39 */ /***/ function(module, exports, __webpack_require__) { /** * Module dependencies. */ var debug = __webpack_require__(3)('socket.io-parser'); var json = __webpack_require__(186); var isArray = __webpack_require__(82); var Emitter = __webpack_require__(198); var binary = __webpack_require__(197); var isBuf = __webpack_require__(81); /** * Protocol version. * * @api public */ exports.protocol = 4; /** * Packet types. * * @api public */ exports.types = [ 'CONNECT', 'DISCONNECT', 'EVENT', 'ACK', 'ERROR', 'BINARY_EVENT', 'BINARY_ACK' ]; /** * Packet type `connect`. * * @api public */ exports.CONNECT = 0; /** * Packet type `disconnect`. * * @api public */ exports.DISCONNECT = 1; /** * Packet type `event`. * * @api public */ exports.EVENT = 2; /** * Packet type `ack`. * * @api public */ exports.ACK = 3; /** * Packet type `error`. * * @api public */ exports.ERROR = 4; /** * Packet type 'binary event' * * @api public */ exports.BINARY_EVENT = 5; /** * Packet type `binary ack`. For acks with binary arguments. * * @api public */ exports.BINARY_ACK = 6; /** * Encoder constructor. * * @api public */ exports.Encoder = Encoder; /** * Decoder constructor. * * @api public */ exports.Decoder = Decoder; /** * A socket.io Encoder instance * * @api public */ function Encoder() {} /** * Encode a packet as a single string if non-binary, or as a * buffer sequence, depending on packet type. * * @param {Object} obj - packet object * @param {Function} callback - function to handle encodings (likely engine.write) * @return Calls callback with Array of encodings * @api public */ Encoder.prototype.encode = function(obj, callback){ debug('encoding packet %j', obj); if (exports.BINARY_EVENT == obj.type || exports.BINARY_ACK == obj.type) { encodeAsBinary(obj, callback); } else { var encoding = encodeAsString(obj); callback([encoding]); } }; /** * Encode packet as string. * * @param {Object} packet * @return {String} encoded * @api private */ function encodeAsString(obj) { var str = ''; var nsp = false; // first is type str += obj.type; // attachments if we have them if (exports.BINARY_EVENT == obj.type || exports.BINARY_ACK == obj.type) { str += obj.attachments; str += '-'; } // if we have a namespace other than `/` // we append it followed by a comma `,` if (obj.nsp && '/' != obj.nsp) { nsp = true; str += obj.nsp; } // immediately followed by the id if (null != obj.id) { if (nsp) { str += ','; nsp = false; } str += obj.id; } // json data if (null != obj.data) { if (nsp) str += ','; str += json.stringify(obj.data); } debug('encoded %j as %s', obj, str); return str; } /** * Encode packet as 'buffer sequence' by removing blobs, and * deconstructing packet into object with placeholders and * a list of buffers. * * @param {Object} packet * @return {Buffer} encoded * @api private */ function encodeAsBinary(obj, callback) { function writeEncoding(bloblessData) { var deconstruction = binary.deconstructPacket(bloblessData); var pack = encodeAsString(deconstruction.packet); var buffers = deconstruction.buffers; buffers.unshift(pack); // add packet info to beginning of data list callback(buffers); // write all the buffers } binary.removeBlobs(obj, writeEncoding); } /** * A socket.io Decoder instance * * @return {Object} decoder * @api public */ function Decoder() { this.reconstructor = null; } /** * Mix in `Emitter` with Decoder. */ Emitter(Decoder.prototype); /** * Decodes an ecoded packet string into packet JSON. * * @param {String} obj - encoded packet * @return {Object} packet * @api public */ Decoder.prototype.add = function(obj) { var packet; if ('string' == typeof obj) { packet = decodeString(obj); if (exports.BINARY_EVENT == packet.type || exports.BINARY_ACK == packet.type) { // binary packet's json this.reconstructor = new BinaryReconstructor(packet); // no attachments, labeled binary but no binary data to follow if (this.reconstructor.reconPack.attachments === 0) { this.emit('decoded', packet); } } else { // non-binary full packet this.emit('decoded', packet); } } else if (isBuf(obj) || obj.base64) { // raw binary data if (!this.reconstructor) { throw new Error('got binary data when not reconstructing a packet'); } else { packet = this.reconstructor.takeBinaryData(obj); if (packet) { // received final buffer this.reconstructor = null; this.emit('decoded', packet); } } } else { throw new Error('Unknown type: ' + obj); } }; /** * Decode a packet String (JSON data) * * @param {String} str * @return {Object} packet * @api private */ function decodeString(str) { var p = {}; var i = 0; // look up type p.type = Number(str.charAt(0)); if (null == exports.types[p.type]) return error(); // look up attachments if type binary if (exports.BINARY_EVENT == p.type || exports.BINARY_ACK == p.type) { var buf = ''; while (str.charAt(++i) != '-') { buf += str.charAt(i); if (i == str.length) break; } if (buf != Number(buf) || str.charAt(i) != '-') { throw new Error('Illegal attachments'); } p.attachments = Number(buf); } // look up namespace (if any) if ('/' == str.charAt(i + 1)) { p.nsp = ''; while (++i) { var c = str.charAt(i); if (',' == c) break; p.nsp += c; if (i == str.length) break; } } else { p.nsp = '/'; } // look up id var next = str.charAt(i + 1); if ('' !== next && Number(next) == next) { p.id = ''; while (++i) { var c = str.charAt(i); if (null == c || Number(c) != c) { --i; break; } p.id += str.charAt(i); if (i == str.length) break; } p.id = Number(p.id); } // look up json data if (str.charAt(++i)) { try { p.data = json.parse(str.substr(i)); } catch(e){ return error(); } } debug('decoded %s as %j', str, p); return p; } /** * Deallocates a parser's resources * * @api public */ Decoder.prototype.destroy = function() { if (this.reconstructor) { this.reconstructor.finishedReconstruction(); } }; /** * A manager of a binary event's 'buffer sequence'. Should * be constructed whenever a packet of type BINARY_EVENT is * decoded. * * @param {Object} packet * @return {BinaryReconstructor} initialized reconstructor * @api private */ function BinaryReconstructor(packet) { this.reconPack = packet; this.buffers = []; } /** * Method to be called when binary data received from connection * after a BINARY_EVENT packet. * * @param {Buffer | ArrayBuffer} binData - the raw binary data received * @return {null | Object} returns null if more binary data is expected or * a reconstructed packet object if all buffers have been received. * @api private */ BinaryReconstructor.prototype.takeBinaryData = function(binData) { this.buffers.push(binData); if (this.buffers.length == this.reconPack.attachments) { // done with buffer list var packet = binary.reconstructPacket(this.reconPack, this.buffers); this.finishedReconstruction(); return packet; } return null; }; /** * Cleans up binary packet reconstruction variables. * * @api private */ BinaryReconstructor.prototype.finishedReconstruction = function() { this.reconPack = null; this.buffers = []; }; function error(data){ return { type: exports.ERROR, data: 'parser error' }; } /***/ }, /* 40 */ /***/ function(module, exports) { module.exports = function(module) { if(!module.webpackPolyfill) { module.deprecate = function() {}; module.paths = []; // module.parent = undefined by default module.children = []; Object.defineProperty(module, "loaded", { enumerable: true, configurable: false, get: function() { return module.l; } }); Object.defineProperty(module, "id", { enumerable: true, configurable: false, get: function() { return module.i; } }); module.webpackPolyfill = 1; } return module; } /***/ }, /* 41 */ /***/ function(module, exports, __webpack_require__) { module.exports = { "default": __webpack_require__(131), __esModule: true }; /***/ }, /* 42 */ /***/ function(module, exports, __webpack_require__) { module.exports = { "default": __webpack_require__(133), __esModule: true }; /***/ }, /* 43 */ /***/ function(module, exports) { "use strict"; "use strict"; exports.__esModule = true; exports.default = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; /***/ }, /* 44 */ /***/ function(module, exports, __webpack_require__) { "use strict"; "use strict"; exports.__esModule = true; var _defineProperty = __webpack_require__(126); var _defineProperty2 = _interopRequireDefault(_defineProperty); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } exports.default = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; (0, _defineProperty2.default)(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /***/ }, /* 45 */ /***/ function(module, exports, __webpack_require__) { "use strict"; /* WEBPACK VAR INJECTION */(function(process) {'use strict'; const fs = __webpack_require__(74); const format = __webpack_require__(202).format; let isNodejs = process.version ? true : false; const LogLevels = { 'DEBUG': 'DEBUG', 'INFO': 'INFO', 'WARN': 'WARN', 'ERROR': 'ERROR', 'NONE': 'NONE', }; // Global log level let GlobalLogLevel = LogLevels.DEBUG; // Global log file name let GlobalLogfile = null; // ANSI colors let Colors = { 'Black': 0, 'Red': 1, 'Green': 2, 'Yellow': 3, 'Blue': 4, 'Magenta': 5, 'Cyan': 6, 'Grey': 7, 'White': 9, 'Default': 9, }; // CSS colors if(!isNodejs) { Colors = { 'Black': 'Black', 'Red': 'IndianRed', 'Green': 'LimeGreen', 'Yellow': 'Orange', 'Blue': 'RoyalBlue', 'Magenta': 'Orchid', 'Cyan': 'SkyBlue', 'Grey': 'DimGrey', 'White': 'White', 'Default': 'Black', }; } const loglevelColors = [Colors.Cyan, Colors.Green, Colors.Yellow, Colors.Red, Colors.Default]; const defaultOptions = { useColors: true, color: Colors.Default, showTimestamp: true, showLevel: true, filename: GlobalLogfile, appendFile: true, }; class Logger { constructor(category, options) { this.category = category; let opts = {}; Object.assign(opts, defaultOptions); Object.assign(opts, options); this.options = opts; } debug() { this._write(LogLevels.DEBUG, format.apply(null, arguments)); } log() { this.debug.apply(this, arguments); } info() { this._write(LogLevels.INFO, format.apply(null, arguments)); } warn() { this._write(LogLevels.WARN, format.apply(null, arguments)); } error() { this._write(LogLevels.ERROR, format.apply(null, arguments)); } _write(level, text) { if(!this._shouldLog(level)) return; if((this.options.filename || GlobalLogfile) && !this.fileWriter) this.fileWriter = fs.openSync(this.options.filename || GlobalLogfile, this.options.appendFile ? 'a+' : 'w+'); let format = this._format(level, text); let unformattedText = this._createLogMessage(level, text); let formattedText = this._createLogMessage(level, text, format.timestamp, format.level, format.category, format.text); if(this.fileWriter) fs.writeSync(this.fileWriter, unformattedText + '\n', null, 'utf-8'); if(isNodejs) { console.log(formattedText) } else { // TODO: clean this up if(level === LogLevels.ERROR) { if(this.options.showTimestamp && this.options.showLevel) { console.error(formattedText, format.timestamp, format.level, format.category, format.text) } else if(this.options.showTimestamp && !this.options.showLevel) { console.error(formattedText, format.timestamp, format.category, format.text) } else if(!this.options.showTimestamp && this.options.showLevel) { console.error(formattedText, format.level, format.category, format.text) } else { console.error(formattedText, format.category, format.text) } } else { if(this.options.showTimestamp && this.options.showLevel) { console.log(formattedText, format.timestamp, format.level, format.category, format.text) } else if(this.options.showTimestamp && !this.options.showLevel) { console.log(formattedText, format.timestamp, format.category, format.text) } else if(!this.options.showTimestamp && this.options.showLevel) { console.log(formattedText, format.level, format.category, format.text) } else { console.log(formattedText, format.category, format.text) } } } } _format(level, text) { let timestampFormat = ''; let levelFormat = ''; let categoryFormat = ''; let textFormat = ': '; if(this.options.useColors) { const levelColor = Object.keys(LogLevels).map((f) => LogLevels[f]).indexOf(level); const categoryColor = this.options.color; if(isNodejs) { if(this.options.showTimestamp) timestampFormat = '\u001b[3' + Colors.Grey + 'm'; if(this.options.showLevel) levelFormat = '\u001b[3' + loglevelColors[levelColor] + ';22m'; categoryFormat = '\u001b[3' + categoryColor + ';1m'; textFormat = '\u001b[0m: '; } else { if(this.options.showTimestamp) timestampFormat = 'color:' + Colors.Grey; if(this.options.showLevel) levelFormat = 'color:' + loglevelColors[levelColor]; categoryFormat = 'color:' + categoryColor + '; font-weight: bold'; } } return { timestamp: timestampFormat, level: levelFormat, category: categoryFormat, text: textFormat }; } _createLogMessage(level, text, timestampFormat, levelFormat, categoryFormat, textFormat) { timestampFormat = timestampFormat || ''; levelFormat = levelFormat || ''; categoryFormat = categoryFormat || ''; textFormat = textFormat || ': '; if(!isNodejs) { if(this.options.showTimestamp) timestampFormat = '%c'; if(this.options.showLevel) levelFormat = '%c'; categoryFormat = '%c'; textFormat = ': %c'; } let result = ''; if(this.options.showTimestamp) result += '' + new Date().toISOString() + ' '; result = timestampFormat + result; if(this.options.showLevel) result += levelFormat + '[' + level +']' + (level === LogLevels.INFO || level === LogLevels.WARN ? ' ' : '') + ' '; result += categoryFormat + this.category; result += textFormat + text; return result; } _shouldLog(level) { const levels = Object.keys(LogLevels).map((f) => LogLevels[f]); const index = levels.indexOf(level); const levelIdx = levels.indexOf(GlobalLogLevel); return index >= levelIdx; } }; /* Public API */ module.exports = { Colors: Colors, LogLevels: LogLevels, setLogLevel: (level) => { GlobalLogLevel = level; }, setLogfile: (filename) => { GlobalLogfile = filename; }, create: (category, options) => { const logger = new Logger(category, options); return logger; }, forceBrowserMode: (force) => isNodejs = !force, // for testing }; /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(20))) /***/ }, /* 46 */ /***/ function(module, exports, __webpack_require__) { "use strict"; 'use strict'; const Lazy = __webpack_require__(73); const Store = __webpack_require__(37); const EventIndex = __webpack_require__(75); class EventStore extends Store { constructor(ipfs, id, dbname, options) { if(!options) options = {}; if(!options.Index) Object.assign(options, { Index: EventIndex }); super(ipfs, id, dbname, options) } add(data) { return this._addOperation({ op: 'ADD', key: null, value: data, meta: { ts: new Date().getTime() } }); } iterator(options) { const messages = this._query(this.dbname, options); let currentIndex = 0; let iterator = { [Symbol.iterator]() { return this; }, next() { let item = { value: null, done: true }; if(currentIndex < messages.length) { item = { value: messages[currentIndex], done: false }; currentIndex ++; } return item; }, collect: () => messages } return iterator; } _query(dbname, opts) { if(!opts) opts = {}; const amount = opts.limit ? (opts.limit > -1 ? opts.limit : this._index.get().length) : 1; // Return 1 if no limit is provided const events = this._index.get(); let result = []; if(opts.gt || opts.gte) { // Greater than case result = this._read(events, opts.gt ? opts.gt : opts.gte, amount, opts.gte ? true : false) } else { // Lower than and lastN case, search latest first by reversing the sequence result = this._read(events.reverse(), opts.lt ? opts.lt : opts.lte, amount, opts.lte || !opts.lt).reverse() } if(opts.reverse) result.reverse(); return result.toArray(); } _read(ops, hash, amount, inclusive) { return Lazy(ops) .skipWhile((f) => hash && f.hash !== hash) .drop(inclusive ? 0 : 1) .take(amount); } } module.exports = EventStore; /***/ }, /* 47 */ /***/ function(module, exports, __webpack_require__) { module.exports = { "default": __webpack_require__(91), __esModule: true }; /***/ }, /* 48 */ /***/ function(module, exports) { "use strict"; "use strict"; exports.__esModule = true; exports.default = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; /***/ }, /* 49 */ /***/ function(module, exports, __webpack_require__) { "use strict"; "use strict"; exports.__esModule = true; var _defineProperty = __webpack_require__(89); var _defineProperty2 = _interopRequireDefault(_defineProperty); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } exports.default = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; (0, _defineProperty2.default)(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /***/ }, /* 50 */ /***/ function(module, exports) { // 7.2.1 RequireObjectCoercible(argument) module.exports = function(it){ if(it == undefined)throw TypeError("Can't call method on " + it); return it; }; /***/ }, /* 51 */ /***/ function(module, exports, __webpack_require__) { var global = __webpack_require__(23) , core = __webpack_require__(15) , ctx = __webpack_require__(98) , hide = __webpack_require__(102) , PROTOTYPE = 'prototype'; var $export = function(type, name, source){ var IS_FORCED = type & $export.F , IS_GLOBAL = type & $export.G , IS_STATIC = type & $export.S , IS_PROTO = type & $export.P , IS_BIND = type & $export.B , IS_WRAP = type & $export.W , exports = IS_GLOBAL ? core : core[name] || (core[name] = {}) , expProto = exports[PROTOTYPE] , target = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {})[PROTOTYPE] , key, own, out; if(IS_GLOBAL)source = name; for(key in source){ // contains in native own = !IS_FORCED && target && target[key] !== undefined; if(own && key in exports)continue; // export native or passed out = own ? target[key] : source[key]; // prevent global pollution for namespaces exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key] // bind timers to global for call from export context : IS_BIND && own ? ctx(out, global) // wrap global constructors for prevent change them in library : IS_WRAP && target[key] == out ? (function(C){ var F = function(a, b, c){ if(this instanceof C){ switch(arguments.length){ case 0: return new C; case 1: return new C(a); case 2: return new C(a, b); } return new C(a, b, c); } return C.apply(this, arguments); }; F[PROTOTYPE] = C[PROTOTYPE]; return F; // make static versions for prototype methods })(out) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out; // export proto methods to core.%CONSTRUCTOR%.methods.%NAME% if(IS_PROTO){ (exports.virtual || (exports.virtual = {}))[key] = out; // export proto methods to core.%CONSTRUCTOR%.prototype.%NAME% if(type & $export.R && expProto && !expProto[key])hide(expProto, key, out); } } }; // type bitmap $export.F = 1; // forced $export.G = 2; // global $export.S = 4; // static $export.P = 8; // proto $export.B = 16; // bind $export.W = 32; // wrap $export.U = 64; // safe $export.R = 128; // real proto method for `library` module.exports = $export; /***/ }, /* 52 */ /***/ function(module, exports, __webpack_require__) { // fallback for non-array-like ES3 and non-enumerable old V8 strings var cof = __webpack_require__(97); module.exports = Object('z').propertyIsEnumerable(0) ? Object : function(it){ return cof(it) == 'String' ? it.split('') : Object(it); }; /***/ }, /* 53 */ /***/ function(module, exports, __webpack_require__) { var anObject = __webpack_require__(95) , IE8_DOM_DEFINE = __webpack_require__(103) , toPrimitive = __webpack_require__(115) , dP = Object.defineProperty; exports.f = __webpack_require__(16) ? Object.defineProperty : function defineProperty(O, P, Attributes){ anObject(O); P = toPrimitive(P, true); anObject(Attributes); if(IE8_DOM_DEFINE)try { return dP(O, P, Attributes); } catch(e){ /* empty */ } if('get' in Attributes || 'set' in Attributes)throw TypeError('Accessors not supported!'); if('value' in Attributes)O[P] = Attributes.value; return O; }; /***/ }, /* 54 */ /***/ function(module, exports) { // 7.1.4 ToInteger var ceil = Math.ceil , floor = Math.floor; module.exports = function(it){ return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it); }; /***/ }, /* 55 */ /***/ function(module, exports, __webpack_require__) { // to indexed object, toObject with fallback for non-array-like ES3 strings var IObject = __webpack_require__(52) , defined = __webpack_require__(50); module.exports = function(it){ return IObject(defined(it)); }; /***/ }, /* 56 */ /***/ function(module, exports) { /** * Slice reference. */ var slice = [].slice; /** * Bind `obj` to `fn`. * * @param {Object} obj * @param {Function|String} fn or string * @return {Function} * @api public */ module.exports = function(obj, fn){ if ('string' == typeof fn) fn = obj[fn]; if ('function' != typeof fn) throw new Error('bind() requires a function'); var args = slice.call(arguments, 2); return function(){ return fn.apply(obj, args.concat(slice.call(arguments))); } }; /***/ }, /* 57 */ /***/ function(module, exports) { /** * Expose `Emitter`. */ module.exports = Emitter; /** * Initialize a new `Emitter`. * * @api public */ function Emitter(obj) { if (obj) return mixin(obj); }; /** * Mixin the emitter properties. * * @param {Object} obj * @return {Object} * @api private */ function mixin(obj) { for (var key in Emitter.prototype) { obj[key] = Emitter.prototype[key]; } return obj; } /** * Listen on the given `event` with `fn`. * * @param {String} event * @param {Function} fn * @return {Emitter} * @api public */ Emitter.prototype.on = Emitter.prototype.addEventListener = function(event, fn){ this._callbacks = this._callbacks || {}; (this._callbacks['$' + event] = this._callbacks['$' + event] || []) .push(fn); return this; }; /** * Adds an `event` listener that will be invoked a single * time then automatically removed. * * @param {String} event * @param {Function} fn * @return {Emitter} * @api public */ Emitter.prototype.once = function(event, fn){ function on() { this.off(event, on); fn.apply(this, arguments); } on.fn = fn; this.on(event, on); return this; }; /** * Remove the given callback for `event` or all * registered callbacks. * * @param {String} event * @param {Function} fn * @return {Emitter} * @api public */ Emitter.prototype.off = Emitter.prototype.removeListener = Emitter.prototype.removeAllListeners = Emitter.prototype.removeEventListener = function(event, fn){ this._callbacks = this._callbacks || {}; // all if (0 == arguments.length) { this._callbacks = {}; return this; } // specific event var callbacks = this._callbacks['$' + event]; if (!callbacks) return this; // remove all handlers if (1 == arguments.length) { delete this._callbacks['$' + event]; return this; } // remove specific handler var cb; for (var i = 0; i < callbacks.length; i++) { cb = callbacks[i]; if (cb === fn || cb.fn === fn) { callbacks.splice(i, 1); break; } } return this; }; /** * Emit `event` with the given args. * * @param {String} event * @param {Mixed} ... * @return {Emitter} */ Emitter.prototype.emit = function(event){ this._callbacks = this._callbacks || {}; var args = [].slice.call(arguments, 1) , callbacks = this._callbacks['$' + event]; if (callbacks) { callbacks = callbacks.slice(0); for (var i = 0, len = callbacks.length; i < len; ++i) { callbacks[i].apply(this, args); } } return this; }; /** * Return array of callbacks for `event`. * * @param {String} event * @return {Array} * @api public */ Emitter.prototype.listeners = function(event){ this._callbacks = this._callbacks || {}; return this._callbacks['$' + event] || []; }; /** * Check if this emitter has `event` handlers. * * @param {String} event * @return {Boolean} * @api public */ Emitter.prototype.hasListeners = function(event){ return !! this.listeners(event).length; }; /***/ }, /* 58 */ /***/ function(module, exports, __webpack_require__) { // getting tag from 19.1.3.6 Object.prototype.toString() var cof = __webpack_require__(18) , TAG = __webpack_require__(1)('toStringTag') // ES3 wrong here , ARG = cof(function(){ return arguments; }()) == 'Arguments'; // fallback for IE11 Script Access Denied error var tryGet = function(it, key){ try { return it[key]; } catch(e){ /* empty */ } }; module.exports = function(it){ var O, T, B; return it === undefined ? 'Undefined' : it === null ? 'Null' // @@toStringTag case : typeof (T = tryGet(O = Object(it), TAG)) == 'string' ? T // builtinTag case : ARG ? cof(O) // ES3 arguments fallback : (B = cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B; }; /***/ }, /* 59 */ /***/ function(module, exports) { // IE 8- don't enum bug keys module.exports = ( 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf' ).split(','); /***/ }, /* 60 */ /***/ function(module, exports) { module.exports = function(exec){ try { return !!exec(); } catch(e){ return true; } }; /***/ }, /* 61 */ /***/ function(module, exports, __webpack_require__) { module.exports = __webpack_require__(2).document && document.documentElement; /***/ }, /* 62 */ /***/ function(module, exports, __webpack_require__) { module.exports = !__webpack_require__(6) && !__webpack_require__(60)(function(){ return Object.defineProperty(__webpack_require__(28)('div'), 'a', {get: function(){ return 7; }}).a != 7; }); /***/ }, /* 63 */ /***/ function(module, exports, __webpack_require__) { "use strict"; 'use strict'; var LIBRARY = __webpack_require__(64) , $export = __webpack_require__(29) , redefine = __webpack_require__(154) , hide = __webpack_require__(8) , has = __webpack_require__(11) , Iterators = __webpack_require__(13) , $iterCreate = __webpack_require__(142) , setToStringTag = __webpack_require__(31) , getPrototypeOf = __webpack_require__(149) , ITERATOR = __webpack_require__(1)('iterator') , BUGGY = !([].keys && 'next' in [].keys()) // Safari has buggy iterators w/o `next` , FF_ITERATOR = '@@iterator' , KEYS = 'keys' , VALUES = 'values'; var returnThis = function(){ return this; }; module.exports = function(Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED){ $iterCreate(Constructor, NAME, next); var getMethod = function(kind){ if(!BUGGY && kind in proto)return proto[kind]; switch(kind){ case KEYS: return function keys(){ return new Constructor(this, kind); }; case VALUES: return function values(){ return new Constructor(this, kind); }; } return function entries(){ return new Constructor(this, kind); }; }; var TAG = NAME + ' Iterator' , DEF_VALUES = DEFAULT == VALUES , VALUES_BUG = false , proto = Base.prototype , $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT] , $default = $native || getMethod(DEFAULT) , $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined , $anyNative = NAME == 'Array' ? proto.entries || $native : $native , methods, key, IteratorPrototype; // Fix native if($anyNative){ IteratorPrototype = getPrototypeOf($anyNative.call(new Base)); if(IteratorPrototype !== Object.prototype){ // Set @@toStringTag to native iterators setToStringTag(IteratorPrototype, TAG, true); // fix for some old engines if(!LIBRARY && !has(IteratorPrototype, ITERATOR))hide(IteratorPrototype, ITERATOR, returnThis); } } // fix Array#{values, @@iterator}.name in V8 / FF if(DEF_VALUES && $native && $native.name !== VALUES){ VALUES_BUG = true; $default = function values(){ return $native.call(this); }; } // Define iterator if((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])){ hide(proto, ITERATOR, $default); } // Plug for library Iterators[NAME] = $default; Iterators[TAG] = returnThis; if(DEFAULT){ methods = { values: DEF_VALUES ? $default : getMethod(VALUES), keys: IS_SET ? $default : getMethod(KEYS), entries: $entries }; if(FORCED)for(key in methods){ if(!(key in proto))redefine(proto, key, methods[key]); } else $export($export.P + $export.F * (BUGGY || VALUES_BUG), NAME, methods); } return methods; }; /***/ }, /* 64 */ /***/ function(module, exports) { module.exports = true; /***/ }, /* 65 */ /***/ function(module, exports, __webpack_require__) { var global = __webpack_require__(2) , SHARED = '__core-js_shared__' , store = global[SHARED] || (global[SHARED] = {}); module.exports = function(key){ return store[key] || (store[key] = {}); }; /***/ }, /* 66 */ /***/ function(module, exports, __webpack_require__) { var ctx = __webpack_require__(10) , invoke = __webpack_require__(138) , html = __webpack_require__(61) , cel = __webpack_require__(28) , global = __webpack_require__(2) , process = global.process , setTask = global.setImmediate , clearTask = global.clearImmediate , MessageChannel = global.MessageChannel , counter = 0 , queue = {} , ONREADYSTATECHANGE = 'onreadystatechange' , defer, channel, port; var run = function(){ var id = +this; if(queue.hasOwnProperty(id)){ var fn = queue[id]; delete queue[id]; fn(); } }; var listener = function(event){ run.call(event.data); }; // Node.js 0.9+ & IE10+ has setImmediate, otherwise: if(!setTask || !clearTask){ setTask = function setImmediate(fn){ var args = [], i = 1; while(arguments.length > i)args.push(arguments[i++]); queue[++counter] = function(){ invoke(typeof fn == 'function' ? fn : Function(fn), args); }; defer(counter); return counter; }; clearTask = function clearImmediate(id){ delete queue[id]; }; // Node.js 0.8- if(__webpack_require__(18)(process) == 'process'){ defer = function(id){ process.nextTick(ctx(run, id, 1)); }; // Browsers with MessageChannel, includes WebWorkers } else if(MessageChannel){ channel = new MessageChannel; port = channel.port2; channel.port1.onmessage = listener; defer = ctx(port.postMessage, port, 1); // Browsers with postMessage, skip WebWorkers // IE8 has postMessage, but it's sync & typeof its postMessage is 'object' } else if(global.addEventListener && typeof postMessage == 'function' && !global.importScripts){ defer = function(id){ global.postMessage(id + '', '*'); }; global.addEventListener('message', listener, false); // IE8- } else if(ONREADYSTATECHANGE in cel('script')){ defer = function(id){ html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function(){ html.removeChild(this); run.call(id); }; }; // Rest old browsers } else { defer = function(id){ setTimeout(ctx(run, id, 1), 0); }; } } module.exports = { set: setTask, clear: clearTask }; /***/ }, /* 67 */ /***/ function(module, exports, __webpack_require__) { // 7.1.15 ToLength var toInteger = __webpack_require__(33) , min = Math.min; module.exports = function(it){ return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991 }; /***/ }, /* 68 */ /***/ function(module, exports, __webpack_require__) { // 7.1.1 ToPrimitive(input [, PreferredType]) var isObject = __webpack_require__(12); // instead of the ES6 spec version, we didn't implement @@toPrimitive case // and the second argument - flag - preferred type is a string module.exports = function(it, S){ if(!isObject(it))return it; var fn, val; if(S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val; if(typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it)))return val; if(!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val; throw TypeError("Can't convert object to primitive value"); }; /***/ }, /* 69 */ /***/ function(module, exports) { var id = 0 , px = Math.random(); module.exports = function(key){ return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36)); }; /***/ }, /* 70 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(global) {/** * Module dependencies */ var XMLHttpRequest = __webpack_require__(35); var XHR = __webpack_require__(175); var JSONP = __webpack_require__(174); var websocket = __webpack_require__(176); /** * Export transports. */ exports.polling = polling; exports.websocket = websocket; /** * Polling transport polymorphic constructor. * Decides on xhr vs jsonp based on feature detection. * * @api private */ function polling(opts){ var xhr; var xd = false; var xs = false; var jsonp = false !== opts.jsonp; if (global.location) { var isSSL = 'https:' == location.protocol; var port = location.port; // some user agents have empty `location.port` if (!port) { port = isSSL ? 443 : 80; } xd = opts.hostname != location.hostname || port != opts.port; xs = opts.secure != isSSL; } opts.xdomain = xd; opts.xscheme = xs; xhr = new XMLHttpRequest(opts); if ('open' in xhr && !opts.forceJSONP) { return new XHR(opts); } else { if (!jsonp) throw new Error('JSONP disabled'); return new JSONP(opts); } } /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0))) /***/ }, /* 71 */ /***/ function(module, exports, __webpack_require__) { /** * Module dependencies. */ var Transport = __webpack_require__(34); var parseqs = __webpack_require__(38); var parser = __webpack_require__(9); var inherit = __webpack_require__(17); var yeast = __webpack_require__(83); var debug = __webpack_require__(3)('engine.io-client:polling'); /** * Module exports. */ module.exports = Polling; /** * Is XHR2 supported? */ var hasXHR2 = (function() { var XMLHttpRequest = __webpack_require__(35); var xhr = new XMLHttpRequest({ xdomain: false }); return null != xhr.responseType; })(); /** * Polling interface. * * @param {Object} opts * @api private */ function Polling(opts){ var forceBase64 = (opts && opts.forceBase64); if (!hasXHR2 || forceBase64) { this.supportsBinary = false; } Transport.call(this, opts); } /** * Inherits from Transport. */ inherit(Polling, Transport); /** * Transport name. */ Polling.prototype.name = 'polling'; /** * Opens the socket (triggers polling). We write a PING message to determine * when the transport is open. * * @api private */ Polling.prototype.doOpen = function(){ this.poll(); }; /** * Pauses polling. * * @param {Function} callback upon buffers are flushed and transport is paused * @api private */ Polling.prototype.pause = function(onPause){ var pending = 0; var self = this; this.readyState = 'pausing'; function pause(){ debug('paused'); self.readyState = 'paused'; onPause(); } if (this.polling || !this.writable) { var total = 0; if (this.polling) { debug('we are currently polling - waiting to pause'); total++; this.once('pollComplete', function(){ debug('pre-pause polling complete'); --total || pause(); }); } if (!this.writable) { debug('we are currently writing - waiting to pause'); total++; this.once('drain', function(){ debug('pre-pause writing complete'); --total || pause(); }); } } else { pause(); } }; /** * Starts polling cycle. * * @api public */ Polling.prototype.poll = function(){ debug('polling'); this.polling = true; this.doPoll(); this.emit('poll'); }; /** * Overloads onData to detect payloads. * * @api private */ Polling.prototype.onData = function(data){ var self = this; debug('polling got data %s', data); var callback = function(packet, index, total) { // if its the first message we consider the transport open if ('opening' == self.readyState) { self.onOpen(); } // if its a close packet, we close the ongoing requests if ('close' == packet.type) { self.onClose(); return false; } // otherwise bypass onData and handle the message self.onPacket(packet); }; // decode payload parser.decodePayload(data, this.socket.binaryType, callback); // if an event did not trigger closing if ('closed' != this.readyState) { // if we got data we're not polling this.polling = false; this.emit('pollComplete'); if ('open' == this.readyState) { this.poll(); } else { debug('ignoring poll - transport state "%s"', this.readyState); } } }; /** * For polling, send a close packet. * * @api private */ Polling.prototype.doClose = function(){ var self = this; function close(){ debug('writing close packet'); self.write([{ type: 'close' }]); } if ('open' == this.readyState) { debug('transport open - closing'); close(); } else { // in case we're trying to close while // handshaking is in progress (GH-164) debug('transport not open - deferring close'); this.once('open', close); } }; /** * Writes a packets payload. * * @param {Array} data packets * @param {Function} drain callback * @api private */ Polling.prototype.write = function(packets){ var self = this; this.writable = false; var callbackfn = function() { self.writable = true; self.emit('drain'); }; var self = this; parser.encodePayload(packets, this.supportsBinary, function(data) { self.doWrite(data, callbackfn); }); }; /** * Generates uri for connection. * * @api private */ Polling.prototype.uri = function(){ var query = this.query || {}; var schema = this.secure ? 'https' : 'http'; var port = ''; // cache busting is forced if (false !== this.timestampRequests) { query[this.timestampParam] = yeast(); } if (!this.supportsBinary && !query.sid) { query.b64 = 1; } query = parseqs.encode(query); // avoid port if default for schema if (this.port && (('https' == schema && this.port != 443) || ('http' == schema && this.port != 80))) { port = ':' + this.port; } // prepend ? to query if (query.length) { query = '?' + query; } var ipv6 = this.hostname.indexOf(':') !== -1; return schema + '://' + (ipv6 ? '[' + this.hostname + ']' : this.hostname) + port + this.path + query; }; /***/ }, /* 72 */ /***/ function(module, exports) { var indexOf = [].indexOf; module.exports = function(arr, obj){ if (indexOf) return arr.indexOf(obj); for (var i = 0; i < arr.length; ++i) { if (arr[i] === obj) return i; } return -1; }; /***/ }, /* 73 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(setImmediate, clearImmediate) {var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;/* * @name Lazy.js * * @fileOverview * Lazy.js is a lazy evaluation library for JavaScript. * * This has been done before. For examples see: * * - [wu.js](http://fitzgen.github.io/wu.js/) * - [Linq.js](http://linqjs.codeplex.com/) * - [from.js](https://github.com/suckgamoni/fromjs/) * - [IxJS](http://rx.codeplex.com/) * - [sloth.js](http://rfw.name/sloth.js/) * * However, at least at present, Lazy.js is faster (on average) than any of * those libraries. It is also more complete, with nearly all of the * functionality of [Underscore](http://underscorejs.org/) and * [Lo-Dash](http://lodash.com/). * * Finding your way around the code * -------------------------------- * * At the heart of Lazy.js is the {@link Sequence} object. You create an initial * sequence using {@link Lazy}, which can accept an array, object, or string. * You can then "chain" together methods from this sequence, creating a new * sequence with each call. * * Here's an example: * * var data = getReallyBigArray(); * * var statistics = Lazy(data) * .map(transform) * .filter(validate) * .reduce(aggregate); * * {@link Sequence} is the foundation of other, more specific sequence types. * * An {@link ArrayLikeSequence} provides indexed access to its elements. * * An {@link ObjectLikeSequence} consists of key/value pairs. * * A {@link StringLikeSequence} is like a string (duh): actually, it is an * {@link ArrayLikeSequence} whose elements happen to be characters. * * An {@link AsyncSequence} is special: it iterates over its elements * asynchronously (so calling `each` generally begins an asynchronous loop and * returns immediately). * * For more information * -------------------- * * I wrote a blog post that explains a little bit more about Lazy.js, which you * can read [here](http://philosopherdeveloper.com/posts/introducing-lazy-js.html). * * You can also [create an issue on GitHub](https://github.com/dtao/lazy.js/issues) * if you have any issues with the library. I work through them eventually. * * [@dtao](https://github.com/dtao) */ (function(root, factory) { if (true) { !(__WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); } else if (typeof exports === 'object') { module.exports = factory(); } else { root.Lazy = factory(); } })(this, function(context) { /** * Wraps an object and returns a {@link Sequence}. For `null` or `undefined`, * simply returns an empty sequence (see {@link Lazy.strict} for a stricter * implementation). * * - For **arrays**, Lazy will create a sequence comprising the elements in * the array (an {@link ArrayLikeSequence}). * - For **objects**, Lazy will create a sequence of key/value pairs * (an {@link ObjectLikeSequence}). * - For **strings**, Lazy will create a sequence of characters (a * {@link StringLikeSequence}). * * @public * @param {Array|Object|string} source An array, object, or string to wrap. * @returns {Sequence} The wrapped lazy object. * * @exampleHelpers * // Utility functions to provide to all examples * function increment(x) { return x + 1; } * function isEven(x) { return x % 2 === 0; } * function isPositive(x) { return x > 0; } * function isNegative(x) { return x < 0; } * * @examples * Lazy([1, 2, 4]) // instanceof Lazy.ArrayLikeSequence * Lazy({ foo: "bar" }) // instanceof Lazy.ObjectLikeSequence * Lazy("hello, world!") // instanceof Lazy.StringLikeSequence * Lazy() // sequence: [] * Lazy(null) // sequence: [] */ function Lazy(source) { if (source instanceof Array) { return new ArrayWrapper(source); } else if (typeof source === "string") { return new StringWrapper(source); } else if (source instanceof Sequence) { return source; } if (Lazy.extensions) { var extensions = Lazy.extensions, length = extensions.length, result; while (!result && length--) { result = extensions[length](source); } if (result) { return result; } } return new ObjectWrapper(source); } Lazy.VERSION = '0.4.2'; /*** Utility methods of questionable value ***/ Lazy.noop = function noop() {}; Lazy.identity = function identity(x) { return x; }; /** * Provides a stricter version of {@link Lazy} which throws an error when * attempting to wrap `null`, `undefined`, or numeric or boolean values as a * sequence. * * @public * @returns {Function} A stricter version of the {@link Lazy} helper function. * * @examples * var Strict = Lazy.strict(); * * Strict() // throws * Strict(null) // throws * Strict(true) // throws * Strict(5) // throws * Strict([1, 2, 3]) // instanceof Lazy.ArrayLikeSequence * Strict({ foo: "bar" }) // instanceof Lazy.ObjectLikeSequence * Strict("hello, world!") // instanceof Lazy.StringLikeSequence * * // Let's also ensure the static functions are still there. * Strict.range(3) // sequence: [0, 1, 2] * Strict.generate(Date.now) // instanceof Lazy.GeneratedSequence */ Lazy.strict = function strict() { function StrictLazy(source) { if (source == null) { throw new Error("You cannot wrap null or undefined using Lazy."); } if (typeof source === "number" || typeof source === "boolean") { throw new Error("You cannot wrap primitive values using Lazy."); } return Lazy(source); }; Lazy(Lazy).each(function(property, name) { StrictLazy[name] = property; }); return StrictLazy; }; /** * The `Sequence` object provides a unified API encapsulating the notion of * zero or more consecutive elements in a collection, stream, etc. * * Lazy evaluation * --------------- * * Generally speaking, creating a sequence should not be an expensive operation, * and should not iterate over an underlying source or trigger any side effects. * This means that chaining together methods that return sequences incurs only * the cost of creating the `Sequence` objects themselves and not the cost of * iterating an underlying data source multiple times. * * The following code, for example, creates 4 sequences and does nothing with * `source`: * * var seq = Lazy(source) // 1st sequence * .map(func) // 2nd * .filter(pred) // 3rd * .reverse(); // 4th * * Lazy's convention is to hold off on iterating or otherwise *doing* anything * (aside from creating `Sequence` objects) until you call `each`: * * seq.each(function(x) { console.log(x); }); * * Defining custom sequences * ------------------------- * * Defining your own type of sequence is relatively simple: * * 1. Pass a *method name* and an object containing *function overrides* to * {@link Sequence.define}. If the object includes a function called `init`, * this function will be called upon initialization. * 2. The object should include at least either a `getIterator` method or an * `each` method. The former supports both asynchronous and synchronous * iteration, but is slightly more cumbersome to implement. The latter * supports synchronous iteration and can be automatically implemented in * terms of the former. You can also implement both if you want, e.g. to * optimize performance. For more info, see {@link Iterator} and * {@link AsyncSequence}. * * As a trivial example, the following code defines a new method, `sample`, * which randomly may or may not include each element from its parent. * * Lazy.Sequence.define("sample", { * each: function(fn) { * return this.parent.each(function(e) { * // 50/50 chance of including this element. * if (Math.random() > 0.5) { * return fn(e); * } * }); * } * }); * * (Of course, the above could also easily have been implemented using * {@link #filter} instead of creating a custom sequence. But I *did* say this * was a trivial example, to be fair.) * * Now it will be possible to create this type of sequence from any parent * sequence by calling the method name you specified. In other words, you can * now do this: * * Lazy(arr).sample(); * Lazy(arr).map(func).sample(); * Lazy(arr).map(func).filter(pred).sample(); * * Etc., etc. * * @public * @constructor */ function Sequence() {} /** * Create a new constructor function for a type inheriting from `Sequence`. * * @public * @param {string|Array.} methodName The name(s) of the method(s) to be * used for constructing the new sequence. The method will be attached to * the `Sequence` prototype so that it can be chained with any other * sequence methods, like {@link #map}, {@link #filter}, etc. * @param {Object} overrides An object containing function overrides for this * new sequence type. **Must** include either `getIterator` or `each` (or * both). *May* include an `init` method as well. For these overrides, * `this` will be the new sequence, and `this.parent` will be the base * sequence from which the new sequence was constructed. * @returns {Function} A constructor for a new type inheriting from `Sequence`. * * @examples * // This sequence type logs every element to the specified logger as it * // iterates over it. * Lazy.Sequence.define("verbose", { * init: function(logger) { * this.logger = logger; * }, * * each: function(fn) { * var logger = this.logger; * return this.parent.each(function(e, i) { * logger(e); * return fn(e, i); * }); * } * }); * * Lazy([1, 2, 3]).verbose(logger).each(Lazy.noop) // calls logger 3 times */ Sequence.define = function define(methodName, overrides) { if (!overrides || (!overrides.getIterator && !overrides.each)) { throw new Error("A custom sequence must implement *at least* getIterator or each!"); } return defineSequenceType(Sequence, methodName, overrides); }; /** * Gets the number of elements in the sequence. In some cases, this may * require eagerly evaluating the sequence. * * @public * @returns {number} The number of elements in the sequence. * * @examples * Lazy([1, 2, 3]).size(); // => 3 * Lazy([1, 2]).map(Lazy.identity).size(); // => 2 * Lazy([1, 2, 3]).reject(isEven).size(); // => 2 * Lazy([1, 2, 3]).take(1).size(); // => 1 * Lazy({ foo: 1, bar: 2 }).size(); // => 2 * Lazy('hello').size(); // => 5 */ Sequence.prototype.size = function size() { return this.getIndex().length(); }; /** * Creates an {@link Iterator} object with two methods, `moveNext` -- returning * true or false -- and `current` -- returning the current value. * * This method is used when asynchronously iterating over sequences. Any type * inheriting from `Sequence` must implement this method or it can't support * asynchronous iteration. * * Note that **this method is not intended to be used directly by application * code.** Rather, it is intended as a means for implementors to potentially * define custom sequence types that support either synchronous or * asynchronous iteration. * * @public * @returns {Iterator} An iterator object. * * @examples * var iterator = Lazy([1, 2]).getIterator(); * * iterator.moveNext(); // => true * iterator.current(); // => 1 * iterator.moveNext(); // => true * iterator.current(); // => 2 * iterator.moveNext(); // => false */ Sequence.prototype.getIterator = function getIterator() { return new Iterator(this); }; /** * Gets the root sequence underlying the current chain of sequences. */ Sequence.prototype.root = function root() { return this.parent.root(); }; /** * Whether or not the current sequence is an asynchronous one. This is more * accurate than checking `instanceof {@link AsyncSequence}` because, for * example, `Lazy([1, 2, 3]).async().map(Lazy.identity)` returns a sequence * that iterates asynchronously even though it's not an instance of * `AsyncSequence`. * * @returns {boolean} Whether or not the current sequence is an asynchronous one. */ Sequence.prototype.isAsync = function isAsync() { return this.parent ? this.parent.isAsync() : false; }; /** * Evaluates the sequence and produces the appropriate value (an array in most * cases, an object for {@link ObjectLikeSequence}s or a string for * {@link StringLikeSequence}s). * * @returns {Array|string|Object} The value resulting from fully evaluating * the sequence. */ Sequence.prototype.value = function value() { return this.toArray(); }; /** * Applies the current transformation chain to a given source, returning the * resulting value. * * @examples * var sequence = Lazy([]) * .map(function(x) { return x * -1; }) * .filter(function(x) { return x % 2 === 0; }); * * sequence.apply([1, 2, 3, 4]); // => [-2, -4] */ Sequence.prototype.apply = function apply(source) { var root = this.root(), previousSource = root.source, result; try { root.source = source; result = this.value(); } finally { root.source = previousSource; } return result; }; /** * The Iterator object provides an API for iterating over a sequence. * * The purpose of the `Iterator` type is mainly to offer an agnostic way of * iterating over a sequence -- either synchronous (i.e. with a `while` loop) * or asynchronously (with recursive calls to either `setTimeout` or --- if * available --- `setImmediate`). It is not intended to be used directly by * application code. * * @public * @constructor * @param {Sequence} sequence The sequence to iterate over. */ function Iterator(sequence) { this.sequence = sequence; this.index = -1; } /** * Gets the current item this iterator is pointing to. * * @public * @returns {*} The current item. */ Iterator.prototype.current = function current() { return this.cachedIndex && this.cachedIndex.get(this.index); }; /** * Moves the iterator to the next item in a sequence, if possible. * * @public * @returns {boolean} True if the iterator is able to move to a new item, or else * false. */ Iterator.prototype.moveNext = function moveNext() { var cachedIndex = this.cachedIndex; if (!cachedIndex) { cachedIndex = this.cachedIndex = this.sequence.getIndex(); } if (this.index >= cachedIndex.length() - 1) { return false; } ++this.index; return true; }; /** * Creates an array snapshot of a sequence. * * Note that for indefinite sequences, this method may raise an exception or * (worse) cause the environment to hang. * * @public * @returns {Array} An array containing the current contents of the sequence. * * @examples * Lazy([1, 2, 3]).toArray() // => [1, 2, 3] */ Sequence.prototype.toArray = function toArray() { return this.reduce(function(arr, element) { arr.push(element); return arr; }, []); }; /** * Provides an indexed view into the sequence. * * For sequences that are already indexed, this will simply return the * sequence. For non-indexed sequences, this will eagerly evaluate the * sequence. * * @returns {ArrayLikeSequence} A sequence containing the current contents of * the sequence. * * @examples * Lazy([1, 2, 3]).filter(isEven) // instanceof Lazy.Sequence * Lazy([1, 2, 3]).filter(isEven).getIndex() // instanceof Lazy.ArrayLikeSequence */ Sequence.prototype.getIndex = function getIndex() { return new ArrayWrapper(this.toArray()); }; /** * Returns the element at the specified index. Note that, for sequences that * are not {@link ArrayLikeSequence}s, this may require partially evaluating * the sequence, iterating to reach the result. (In other words for such * sequences this method is not O(1).) * * @public * @param {number} i The index to access. * @returns {*} The element. * */ Sequence.prototype.get = function get(i) { var element; this.each(function(e, index) { if (index === i) { element = e; return false; } }); return element; }; /** * Provides an indexed, memoized view into the sequence. This will cache the * result whenever the sequence is first iterated, so that subsequent * iterations will access the same element objects. * * @public * @returns {ArrayLikeSequence} An indexed, memoized sequence containing this * sequence's elements, cached after the first iteration. * * @example * function createObject() { return new Object(); } * * var plain = Lazy.generate(createObject, 10), * memoized = Lazy.generate(createObject, 10).memoize(); * * plain.toArray()[0] === plain.toArray()[0]; // => false * memoized.toArray()[0] === memoized.toArray()[0]; // => true */ Sequence.prototype.memoize = function memoize() { return new MemoizedSequence(this); }; /** * @constructor */ function MemoizedSequence(parent) { this.parent = parent; } // MemoizedSequence needs to have its prototype set up after ArrayLikeSequence /** * Creates an object from a sequence of key/value pairs. * * @public * @returns {Object} An object with keys and values corresponding to the pairs * of elements in the sequence. * * @examples * var details = [ * ["first", "Dan"], * ["last", "Tao"], * ["age", 29] * ]; * * Lazy(details).toObject() // => { first: "Dan", last: "Tao", age: 29 } */ Sequence.prototype.toObject = function toObject() { return this.reduce(function(object, pair) { object[pair[0]] = pair[1]; return object; }, {}); }; /** * Iterates over this sequence and executes a function for every element. * * @public * @aka forEach * @param {Function} fn The function to call on each element in the sequence. * Return false from the function to end the iteration. * @returns {boolean} `true` if the iteration evaluated the entire sequence, * or `false` if iteration was ended early. * * @examples * Lazy([1, 2, 3, 4]).each(fn) // calls fn 4 times */ Sequence.prototype.each = function each(fn) { var iterator = this.getIterator(), i = -1; while (iterator.moveNext()) { if (fn(iterator.current(), ++i) === false) { return false; } } return true; }; Sequence.prototype.forEach = function forEach(fn) { return this.each(fn); }; /** * Creates a new sequence whose values are calculated by passing this sequence's * elements through some mapping function. * * @public * @aka collect * @param {Function} mapFn The mapping function used to project this sequence's * elements onto a new sequence. This function takes up to two arguments: * the element, and the current index. * @returns {Sequence} The new sequence. * * @examples * function addIndexToValue(e, i) { return e + i; } * * Lazy([]).map(increment) // sequence: [] * Lazy([1, 2, 3]).map(increment) // sequence: [2, 3, 4] * Lazy([1, 2, 3]).map(addIndexToValue) // sequence: [1, 3, 5] * * @benchmarks * function increment(x) { return x + 1; } * * var smArr = Lazy.range(10).toArray(), * lgArr = Lazy.range(100).toArray(); * * Lazy(smArr).map(increment).each(Lazy.noop) // lazy - 10 elements * Lazy(lgArr).map(increment).each(Lazy.noop) // lazy - 100 elements * _.each(_.map(smArr, increment), _.noop) // lodash - 10 elements * _.each(_.map(lgArr, increment), _.noop) // lodash - 100 elements */ Sequence.prototype.map = function map(mapFn) { return new MappedSequence(this, createCallback(mapFn)); }; Sequence.prototype.collect = function collect(mapFn) { return this.map(mapFn); }; /** * @constructor */ function MappedSequence(parent, mapFn) { this.parent = parent; this.mapFn = mapFn; } MappedSequence.prototype = new Sequence(); MappedSequence.prototype.getIterator = function getIterator() { return new MappingIterator(this.parent, this.mapFn); }; MappedSequence.prototype.each = function each(fn) { var mapFn = this.mapFn; return this.parent.each(function(e, i) { return fn(mapFn(e, i), i); }); }; /** * @constructor */ function MappingIterator(sequence, mapFn) { this.iterator = sequence.getIterator(); this.mapFn = mapFn; this.index = -1; } MappingIterator.prototype.current = function current() { return this.mapFn(this.iterator.current(), this.index); }; MappingIterator.prototype.moveNext = function moveNext() { if (this.iterator.moveNext()) { ++this.index; return true; } return false; }; /** * Creates a new sequence whose values are calculated by accessing the specified * property from each element in this sequence. * * @public * @param {string} propertyName The name of the property to access for every * element in this sequence. * @returns {Sequence} The new sequence. * * @examples * var people = [ * { first: "Dan", last: "Tao" }, * { first: "Bob", last: "Smith" } * ]; * * Lazy(people).pluck("last") // sequence: ["Tao", "Smith"] */ Sequence.prototype.pluck = function pluck(property) { return this.map(property); }; /** * Creates a new sequence whose values are calculated by invoking the specified * function on each element in this sequence. * * @public * @param {string} methodName The name of the method to invoke for every element * in this sequence. * @returns {Sequence} The new sequence. * * @examples * function Person(first, last) { * this.fullName = function fullName() { * return first + " " + last; * }; * } * * var people = [ * new Person("Dan", "Tao"), * new Person("Bob", "Smith") * ]; * * Lazy(people).invoke("fullName") // sequence: ["Dan Tao", "Bob Smith"] */ Sequence.prototype.invoke = function invoke(methodName) { return this.map(function(e) { return e[methodName](); }); }; /** * Creates a new sequence whose values are the elements of this sequence which * satisfy the specified predicate. * * @public * @aka select * @param {Function} filterFn The predicate to call on each element in this * sequence, which returns true if the element should be included. * @returns {Sequence} The new sequence. * * @examples * var numbers = [1, 2, 3, 4, 5, 6]; * * Lazy(numbers).filter(isEven) // sequence: [2, 4, 6] * * @benchmarks * function isEven(x) { return x % 2 === 0; } * * var smArr = Lazy.range(10).toArray(), * lgArr = Lazy.range(100).toArray(); * * Lazy(smArr).filter(isEven).each(Lazy.noop) // lazy - 10 elements * Lazy(lgArr).filter(isEven).each(Lazy.noop) // lazy - 100 elements * _.each(_.filter(smArr, isEven), _.noop) // lodash - 10 elements * _.each(_.filter(lgArr, isEven), _.noop) // lodash - 100 elements */ Sequence.prototype.filter = function filter(filterFn) { return new FilteredSequence(this, createCallback(filterFn)); }; Sequence.prototype.select = function select(filterFn) { return this.filter(filterFn); }; /** * @constructor */ function FilteredSequence(parent, filterFn) { this.parent = parent; this.filterFn = filterFn; } FilteredSequence.prototype = new Sequence(); FilteredSequence.prototype.getIterator = function getIterator() { return new FilteringIterator(this.parent, this.filterFn); }; FilteredSequence.prototype.each = function each(fn) { var filterFn = this.filterFn, j = 0; return this.parent.each(function(e, i) { if (filterFn(e, i)) { return fn(e, j++); } }); }; FilteredSequence.prototype.reverse = function reverse() { return this.parent.reverse().filter(this.filterFn); }; /** * @constructor */ function FilteringIterator(sequence, filterFn) { this.iterator = sequence.getIterator(); this.filterFn = filterFn; this.index = 0; } FilteringIterator.prototype.current = function current() { return this.value; }; FilteringIterator.prototype.moveNext = function moveNext() { var iterator = this.iterator, filterFn = this.filterFn, value; while (iterator.moveNext()) { value = iterator.current(); if (filterFn(value, this.index++)) { this.value = value; return true; } } this.value = undefined; return false; }; /** * Creates a new sequence whose values exclude the elements of this sequence * identified by the specified predicate. * * @public * @param {Function} rejectFn The predicate to call on each element in this * sequence, which returns true if the element should be omitted. * @returns {Sequence} The new sequence. * * @examples * Lazy([1, 2, 3, 4, 5]).reject(isEven) // sequence: [1, 3, 5] * Lazy([{ foo: 1 }, { bar: 2 }]).reject('foo') // sequence: [{ bar: 2 }] * Lazy([{ foo: 1 }, { foo: 2 }]).reject({ foo: 2 }) // sequence: [{ foo: 1 }] */ Sequence.prototype.reject = function reject(rejectFn) { rejectFn = createCallback(rejectFn); return this.filter(function(e) { return !rejectFn(e); }); }; /** * Creates a new sequence whose values have the specified type, as determined * by the `typeof` operator. * * @public * @param {string} type The type of elements to include from the underlying * sequence, i.e. where `typeof [element] === [type]`. * @returns {Sequence} The new sequence, comprising elements of the specified * type. * * @examples * Lazy([1, 2, 'foo', 'bar']).ofType('number') // sequence: [1, 2] * Lazy([1, 2, 'foo', 'bar']).ofType('string') // sequence: ['foo', 'bar'] * Lazy([1, 2, 'foo', 'bar']).ofType('boolean') // sequence: [] */ Sequence.prototype.ofType = function ofType(type) { return this.filter(function(e) { return typeof e === type; }); }; /** * Creates a new sequence whose values are the elements of this sequence with * property names and values matching those of the specified object. * * @public * @param {Object} properties The properties that should be found on every * element that is to be included in this sequence. * @returns {Sequence} The new sequence. * * @examples * var people = [ * { first: "Dan", last: "Tao" }, * { first: "Bob", last: "Smith" } * ]; * * Lazy(people).where({ first: "Dan" }) // sequence: [{ first: "Dan", last: "Tao" }] * * @benchmarks * var animals = ["dog", "cat", "mouse", "horse", "pig", "snake"]; * * Lazy(animals).where({ length: 3 }).each(Lazy.noop) // lazy * _.each(_.where(animals, { length: 3 }), _.noop) // lodash */ Sequence.prototype.where = function where(properties) { return this.filter(properties); }; /** * Creates a new sequence with the same elements as this one, but to be iterated * in the opposite order. * * Note that in some (but not all) cases, the only way to create such a sequence * may require iterating the entire underlying source when `each` is called. * * @public * @returns {Sequence} The new sequence. * * @examples * Lazy([1, 2, 3]).reverse() // sequence: [3, 2, 1] * Lazy([]).reverse() // sequence: [] */ Sequence.prototype.reverse = function reverse() { return new ReversedSequence(this); }; /** * @constructor */ function ReversedSequence(parent) { this.parent = parent; } ReversedSequence.prototype = new Sequence(); ReversedSequence.prototype.getIterator = function getIterator() { return new ReversedIterator(this.parent); }; /** * @constuctor */ function ReversedIterator(sequence) { this.sequence = sequence; } ReversedIterator.prototype.current = function current() { return this.getIndex().get(this.index); }; ReversedIterator.prototype.moveNext = function moveNext() { var index = this.getIndex(), length = index.length(); if (typeof this.index === "undefined") { this.index = length; } return (--this.index >= 0); }; ReversedIterator.prototype.getIndex = function getIndex() { if (!this.cachedIndex) { this.cachedIndex = this.sequence.getIndex(); } return this.cachedIndex; }; /** * Creates a new sequence with all of the elements of this one, plus those of * the given array(s). * * @public * @param {...*} var_args One or more values (or arrays of values) to use for * additional items after this sequence. * @returns {Sequence} The new sequence. * * @examples * var left = [1, 2, 3]; * var right = [4, 5, 6]; * * Lazy(left).concat(right) // sequence: [1, 2, 3, 4, 5, 6] * Lazy(left).concat(Lazy(right)) // sequence: [1, 2, 3, 4, 5, 6] * Lazy(left).concat(right, [7, 8]) // sequence: [1, 2, 3, 4, 5, 6, 7, 8] */ Sequence.prototype.concat = function concat(var_args) { return new ConcatenatedSequence(this, arraySlice.call(arguments, 0)); }; /** * @constructor */ function ConcatenatedSequence(parent, arrays) { this.parent = parent; this.arrays = arrays; } ConcatenatedSequence.prototype = new Sequence(); ConcatenatedSequence.prototype.each = function each(fn) { var done = false, i = 0; this.parent.each(function(e) { if (fn(e, i++) === false) { done = true; return false; } }); if (!done) { Lazy(this.arrays).flatten().each(function(e) { if (fn(e, i++) === false) { return false; } }); } }; /** * Creates a new sequence comprising the first N elements from this sequence, OR * (if N is `undefined`) simply returns the first element of this sequence. * * @public * @aka head, take * @param {number=} count The number of elements to take from this sequence. If * this value exceeds the length of the sequence, the resulting sequence * will be essentially the same as this one. * @returns {*} The new sequence (or the first element from this sequence if * no count was given). * * @examples * function powerOfTwo(exp) { * return Math.pow(2, exp); * } * * Lazy.generate(powerOfTwo).first() // => 1 * Lazy.generate(powerOfTwo).first(5) // sequence: [1, 2, 4, 8, 16] * Lazy.generate(powerOfTwo).skip(2).first() // => 4 * Lazy.generate(powerOfTwo).skip(2).first(2) // sequence: [4, 8] */ Sequence.prototype.first = function first(count) { if (typeof count === "undefined") { return getFirst(this); } return new TakeSequence(this, count); }; Sequence.prototype.head = Sequence.prototype.take = function (count) { return this.first(count); }; /** * @constructor */ function TakeSequence(parent, count) { this.parent = parent; this.count = count; } TakeSequence.prototype = new Sequence(); TakeSequence.prototype.getIterator = function getIterator() { return new TakeIterator(this.parent, this.count); }; TakeSequence.prototype.each = function each(fn) { var count = this.count, i = 0; var result; var handle = this.parent.each(function(e) { if (i < count) { result = fn(e, i++); } if (i >= count) { return false; } return result; }); if (handle instanceof AsyncHandle) { return handle; } return i === count && result !== false; }; /** * @constructor */ function TakeIterator(sequence, count) { this.iterator = sequence.getIterator(); this.count = count; } TakeIterator.prototype.current = function current() { return this.iterator.current(); }; TakeIterator.prototype.moveNext = function moveNext() { return ((--this.count >= 0) && this.iterator.moveNext()); }; /** * Creates a new sequence comprising the elements from the head of this sequence * that satisfy some predicate. Once an element is encountered that doesn't * satisfy the predicate, iteration will stop. * * @public * @param {Function} predicate * @returns {Sequence} The new sequence * * @examples * function lessThan(x) { * return function(y) { * return y < x; * }; * } * * Lazy([1, 2, 3, 4]).takeWhile(lessThan(3)) // sequence: [1, 2] * Lazy([1, 2, 3, 4]).takeWhile(lessThan(0)) // sequence: [] */ Sequence.prototype.takeWhile = function takeWhile(predicate) { return new TakeWhileSequence(this, predicate); }; /** * @constructor */ function TakeWhileSequence(parent, predicate) { this.parent = parent; this.predicate = predicate; } TakeWhileSequence.prototype = new Sequence(); TakeWhileSequence.prototype.each = function each(fn) { var predicate = this.predicate, finished = false, j = 0; var result = this.parent.each(function(e, i) { if (!predicate(e, i)) { finished = true; return false; } return fn(e, j++); }); if (result instanceof AsyncHandle) { return result; } return finished; }; /** * Creates a new sequence comprising all but the last N elements of this * sequence. * * @public * @param {number=} count The number of items to omit from the end of the * sequence (defaults to 1). * @returns {Sequence} The new sequence. * * @examples * Lazy([1, 2, 3, 4]).initial() // sequence: [1, 2, 3] * Lazy([1, 2, 3, 4]).initial(2) // sequence: [1, 2] * Lazy([1, 2, 3]).filter(Lazy.identity).initial() // sequence: [1, 2] */ Sequence.prototype.initial = function initial(count) { return new InitialSequence(this, count); }; function InitialSequence(parent, count) { this.parent = parent; this.count = typeof count === "number" ? count : 1; } InitialSequence.prototype = new Sequence(); InitialSequence.prototype.each = function each(fn) { var index = this.parent.getIndex(); return index.take(index.length() - this.count).each(fn); }; /** * Creates a new sequence comprising the last N elements of this sequence, OR * (if N is `undefined`) simply returns the last element of this sequence. * * @public * @param {number=} count The number of items to take from the end of the * sequence. * @returns {*} The new sequence (or the last element from this sequence * if no count was given). * * @examples * Lazy([1, 2, 3]).last() // => 3 * Lazy([1, 2, 3]).last(2) // sequence: [2, 3] * Lazy([1, 2, 3]).filter(isEven).last(2) // sequence: [2] */ Sequence.prototype.last = function last(count) { if (typeof count === "undefined") { return this.reverse().first(); } return this.reverse().take(count).reverse(); }; /** * Returns the first element in this sequence with property names and values * matching those of the specified object. * * @public * @param {Object} properties The properties that should be found on some * element in this sequence. * @returns {*} The found element, or `undefined` if none exists in this * sequence. * * @examples * var words = ["foo", "bar"]; * * Lazy(words).findWhere({ 0: "f" }); // => "foo" * Lazy(words).findWhere({ 0: "z" }); // => undefined */ Sequence.prototype.findWhere = function findWhere(properties) { return this.where(properties).first(); }; /** * Creates a new sequence comprising all but the first N elements of this * sequence. * * @public * @aka skip, tail, rest * @param {number=} count The number of items to omit from the beginning of the * sequence (defaults to 1). * @returns {Sequence} The new sequence. * * @examples * Lazy([1, 2, 3, 4]).rest() // sequence: [2, 3, 4] * Lazy([1, 2, 3, 4]).rest(0) // sequence: [1, 2, 3, 4] * Lazy([1, 2, 3, 4]).rest(2) // sequence: [3, 4] * Lazy([1, 2, 3, 4]).rest(5) // sequence: [] */ Sequence.prototype.rest = function rest(count) { return new DropSequence(this, count); }; Sequence.prototype.skip = Sequence.prototype.tail = Sequence.prototype.drop = function drop(count) { return this.rest(count); }; /** * @constructor */ function DropSequence(parent, count) { this.parent = parent; this.count = typeof count === "number" ? count : 1; } DropSequence.prototype = new Sequence(); DropSequence.prototype.each = function each(fn) { var count = this.count, dropped = 0, i = 0; return this.parent.each(function(e) { if (dropped++ < count) { return; } return fn(e, i++); }); }; /** * Creates a new sequence comprising the elements from this sequence *after* * those that satisfy some predicate. The sequence starts with the first * element that does not match the predicate. * * @public * @aka skipWhile * @param {Function} predicate * @returns {Sequence} The new sequence */ Sequence.prototype.dropWhile = function dropWhile(predicate) { return new DropWhileSequence(this, predicate); }; Sequence.prototype.skipWhile = function skipWhile(predicate) { return this.dropWhile(predicate); }; /** * @constructor */ function DropWhileSequence(parent, predicate) { this.parent = parent; this.predicate = predicate; } DropWhileSequence.prototype = new Sequence(); DropWhileSequence.prototype.each = function each(fn) { var predicate = this.predicate, done = false; return this.parent.each(function(e) { if (!done) { if (predicate(e)) { return; } done = true; } return fn(e); }); }; /** * Creates a new sequence with the same elements as this one, but ordered * using the specified comparison function. * * This has essentially the same behavior as calling * [`Array#sort`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort), * but obviously instead of modifying the collection it returns a new * {@link Sequence} object. * * @public * @param {Function=} sortFn The function used to compare elements in the * sequence. The function will be passed two elements and should return: * - 1 if the first is greater * - -1 if the second is greater * - 0 if the two values are the same * @param {boolean} descending Whether or not the resulting sequence should be * in descending order (defaults to `false`). * @returns {Sequence} The new sequence. * * @examples * Lazy([5, 10, 1]).sort() // sequence: [1, 5, 10] * Lazy(['foo', 'bar']).sort() // sequence: ['bar', 'foo'] * Lazy(['b', 'c', 'a']).sort(null, true) // sequence: ['c', 'b', 'a'] * Lazy([5, 10, 1]).sort(null, true) // sequence: [10, 5, 1] * * // Sorting w/ custom comparison function * Lazy(['a', 'ab', 'aa', 'ba', 'b', 'abc']).sort(function compare(x, y) { * if (x.length && (x.length !== y.length)) { return compare(x.length, y.length); } * if (x === y) { return 0; } * return x > y ? 1 : -1; * }); * // => sequence: ['a', 'b', 'aa', 'ab', 'ba', 'abc'] */ Sequence.prototype.sort = function sort(sortFn, descending) { sortFn || (sortFn = compare); if (descending) { sortFn = reverseArguments(sortFn); } return new SortedSequence(this, sortFn); }; /** * Creates a new sequence with the same elements as this one, but ordered by * the results of the given function. * * You can pass: * * - a *string*, to sort by the named property * - a function, to sort by the result of calling the function on each element * * @public * @param {Function} sortFn The function to call on the elements in this * sequence, in order to sort them. * @param {boolean} descending Whether or not the resulting sequence should be * in descending order (defaults to `false`). * @returns {Sequence} The new sequence. * * @examples * function population(country) { * return country.pop; * } * * function area(country) { * return country.sqkm; * } * * var countries = [ * { name: "USA", pop: 320000000, sqkm: 9600000 }, * { name: "Brazil", pop: 194000000, sqkm: 8500000 }, * { name: "Nigeria", pop: 174000000, sqkm: 924000 }, * { name: "China", pop: 1350000000, sqkm: 9700000 }, * { name: "Russia", pop: 143000000, sqkm: 17000000 }, * { name: "Australia", pop: 23000000, sqkm: 7700000 } * ]; * * Lazy(countries).sortBy(population).last(3).pluck('name') // sequence: ["Brazil", "USA", "China"] * Lazy(countries).sortBy(area).last(3).pluck('name') // sequence: ["USA", "China", "Russia"] * Lazy(countries).sortBy(area, true).first(3).pluck('name') // sequence: ["Russia", "China", "USA"] * * @benchmarks * var randoms = Lazy.generate(Math.random).take(100).toArray(); * * Lazy(randoms).sortBy(Lazy.identity).each(Lazy.noop) // lazy * _.each(_.sortBy(randoms, Lazy.identity), _.noop) // lodash */ Sequence.prototype.sortBy = function sortBy(sortFn, descending) { sortFn = createComparator(sortFn); if (descending) { sortFn = reverseArguments(sortFn); } return new SortedSequence(this, sortFn); }; /** * @constructor */ function SortedSequence(parent, sortFn) { this.parent = parent; this.sortFn = sortFn; } SortedSequence.prototype = new Sequence(); SortedSequence.prototype.each = function each(fn) { var sortFn = this.sortFn, result = this.parent.toArray(); result.sort(sortFn); return forEach(result, fn); }; /** * @examples * var items = [{ a: 4 }, { a: 3 }, { a: 5 }]; * * Lazy(items).sortBy('a').reverse(); * // => sequence: [{ a: 5 }, { a: 4 }, { a: 3 }] * * Lazy(items).sortBy('a').reverse().reverse(); * // => sequence: [{ a: 3 }, { a: 4 }, { a: 5 }] */ SortedSequence.prototype.reverse = function reverse() { return new SortedSequence(this.parent, reverseArguments(this.sortFn)); }; /** * Creates a new {@link ObjectLikeSequence} comprising the elements in this * one, grouped together according to some key. The value associated with each * key in the resulting object-like sequence is an array containing all of * the elements in this sequence with that key. * * @public * @param {Function|string} keyFn The function to call on the elements in this * sequence to obtain a key by which to group them, or a string representing * a parameter to read from all the elements in this sequence. * @param {Function|string} valFn (Optional) The function to call on the elements * in this sequence to assign to the value for each instance to appear in the * group, or a string representing a parameter to read from all the elements * in this sequence. * @returns {ObjectLikeSequence} The new sequence. * * @examples * function oddOrEven(x) { * return x % 2 === 0 ? 'even' : 'odd'; * } * function square(x) { * return x*x; * } * * var numbers = [1, 2, 3, 4, 5]; * * Lazy(numbers).groupBy(oddOrEven) // sequence: { odd: [1, 3, 5], even: [2, 4] } * Lazy(numbers).groupBy(oddOrEven).get("odd") // => [1, 3, 5] * Lazy(numbers).groupBy(oddOrEven).get("foo") // => undefined * Lazy(numbers).groupBy(oddOrEven, square).get("even") // => [4, 16] * * Lazy([ * { name: 'toString' }, * { name: 'toString' } * ]).groupBy('name'); * // => sequence: { * 'toString': [ * { name: 'toString' }, * { name: 'toString' } * ] * } */ Sequence.prototype.groupBy = function groupBy(keyFn, valFn) { return new GroupedSequence(this, keyFn, valFn); }; /** * @constructor */ function GroupedSequence(parent, keyFn, valFn) { this.parent = parent; this.keyFn = keyFn; this.valFn = valFn; } // GroupedSequence must have its prototype set after ObjectLikeSequence has // been fully initialized. /** * Creates a new {@link ObjectLikeSequence} comprising the elements in this * one, indexed according to some key. * * @public * @param {Function|string} keyFn The function to call on the elements in this * sequence to obtain a key by which to index them, or a string * representing a property to read from all the elements in this sequence. * @param {Function|string} valFn (Optional) The function to call on the elements * in this sequence to assign to the value of the indexed object, or a string * representing a parameter to read from all the elements in this sequence. * @returns {Sequence} The new sequence. * * @examples * var people = [ * { name: 'Bob', age: 25 }, * { name: 'Fred', age: 34 } * ]; * * var bob = people[0], * fred = people[1]; * * Lazy(people).indexBy('name') // sequence: { 'Bob': bob, 'Fred': fred } * Lazy(people).indexBy('name', 'age') // sequence: { 'Bob': 25, 'Fred': 34 } */ Sequence.prototype.indexBy = function(keyFn, valFn) { return new IndexedSequence(this, keyFn, valFn); }; /** * @constructor */ function IndexedSequence(parent, keyFn, valFn) { this.parent = parent; this.keyFn = keyFn; this.valFn = valFn; } // IndexedSequence must have its prototype set after ObjectLikeSequence has // been fully initialized. /** * Creates a new {@link ObjectLikeSequence} containing the unique keys of all * the elements in this sequence, each paired with the number of elements * in this sequence having that key. * * @public * @param {Function|string} keyFn The function to call on the elements in this * sequence to obtain a key by which to count them, or a string representing * a parameter to read from all the elements in this sequence. * @returns {Sequence} The new sequence. * * @examples * function oddOrEven(x) { * return x % 2 === 0 ? 'even' : 'odd'; * } * * var numbers = [1, 2, 3, 4, 5]; * * Lazy(numbers).countBy(oddOrEven) // sequence: { odd: 3, even: 2 } * Lazy(numbers).countBy(oddOrEven).get("odd") // => 3 * Lazy(numbers).countBy(oddOrEven).get("foo") // => undefined */ Sequence.prototype.countBy = function countBy(keyFn) { return new CountedSequence(this, keyFn); }; /** * @constructor */ function CountedSequence(parent, keyFn) { this.parent = parent; this.keyFn = keyFn; } // CountedSequence, like GroupedSequence, must have its prototype set after // ObjectLikeSequence has been fully initialized. /** * Creates a new sequence with every unique element from this one appearing * exactly once (i.e., with duplicates removed). * * @public * @aka unique * @param {Function} keyFn An optional function to produce the key for each * object. This key is then tested for uniqueness as opposed to the * object reference. * @returns {Sequence} The new sequence. * * @examples * Lazy([1, 2, 2, 3, 3, 3]).uniq() // sequence: [1, 2, 3] * Lazy([{ name: 'mike' }, * { name: 'sarah' }, * { name: 'mike' } * ]).uniq('name') * // sequence: [{ name: 'mike' }, { name: 'sarah' }] * * @benchmarks * function randomOf(array) { * return function() { * return array[Math.floor(Math.random() * array.length)]; * }; * } * * var mostUnique = Lazy.generate(randomOf(_.range(100)), 100).toArray(), * someUnique = Lazy.generate(randomOf(_.range(50)), 100).toArray(), * mostDupes = Lazy.generate(randomOf(_.range(5)), 100).toArray(); * * Lazy(mostUnique).uniq().each(Lazy.noop) // lazy - mostly unique elements * Lazy(someUnique).uniq().each(Lazy.noop) // lazy - some unique elements * Lazy(mostDupes).uniq().each(Lazy.noop) // lazy - mostly duplicate elements * _.each(_.uniq(mostUnique), _.noop) // lodash - mostly unique elements * _.each(_.uniq(someUnique), _.noop) // lodash - some unique elements * _.each(_.uniq(mostDupes), _.noop) // lodash - mostly duplicate elements */ Sequence.prototype.uniq = function uniq(keyFn) { return new UniqueSequence(this, keyFn); }; Sequence.prototype.unique = function unique(keyFn) { return this.uniq(keyFn); }; /** * @constructor */ function UniqueSequence(parent, keyFn) { this.parent = parent; this.keyFn = keyFn; } UniqueSequence.prototype = new Sequence(); UniqueSequence.prototype.each = function each(fn) { var cache = new Set(), keyFn = this.keyFn, i = 0; if (keyFn) { keyFn = createCallback(keyFn); return this.parent.each(function(e) { if (cache.add(keyFn(e))) { return fn(e, i++); } }); } else { return this.parent.each(function(e) { if (cache.add(e)) { return fn(e, i++); } }); } }; /** * Creates a new sequence by combining the elements from this sequence with * corresponding elements from the specified array(s). * * @public * @param {...Array} var_args One or more arrays of elements to combine with * those of this sequence. * @returns {Sequence} The new sequence. * * @examples * Lazy([1, 2]).zip([3, 4]) // sequence: [[1, 3], [2, 4]] * * @benchmarks * var smArrL = Lazy.range(10).toArray(), * smArrR = Lazy.range(10, 20).toArray(), * lgArrL = Lazy.range(100).toArray(), * lgArrR = Lazy.range(100, 200).toArray(); * * Lazy(smArrL).zip(smArrR).each(Lazy.noop) // lazy - zipping 10-element arrays * Lazy(lgArrL).zip(lgArrR).each(Lazy.noop) // lazy - zipping 100-element arrays * _.each(_.zip(smArrL, smArrR), _.noop) // lodash - zipping 10-element arrays * _.each(_.zip(lgArrL, lgArrR), _.noop) // lodash - zipping 100-element arrays */ Sequence.prototype.zip = function zip(var_args) { if (arguments.length === 1) { return new SimpleZippedSequence(this, (/** @type {Array} */ var_args)); } else { return new ZippedSequence(this, arraySlice.call(arguments, 0)); } }; /** * @constructor */ function ZippedSequence(parent, arrays) { this.parent = parent; this.arrays = arrays; } ZippedSequence.prototype = new Sequence(); ZippedSequence.prototype.each = function each(fn) { var arrays = this.arrays, i = 0; this.parent.each(function(e) { var group = [e]; for (var j = 0; j < arrays.length; ++j) { if (arrays[j].length > i) { group.push(arrays[j][i]); } } return fn(group, i++); }); }; /** * Creates a new sequence with the same elements as this one, in a randomized * order. * * @public * @returns {Sequence} The new sequence. * * @examples * Lazy([1, 2, 3, 4, 5]).shuffle().value() // =~ [1, 2, 3, 4, 5] */ Sequence.prototype.shuffle = function shuffle() { return new ShuffledSequence(this); }; /** * @constructor */ function ShuffledSequence(parent) { this.parent = parent; } ShuffledSequence.prototype = new Sequence(); ShuffledSequence.prototype.each = function each(fn) { var shuffled = this.parent.toArray(), floor = Math.floor, random = Math.random, j = 0; for (var i = shuffled.length - 1; i > 0; --i) { swap(shuffled, i, floor(random() * (i + 1))); if (fn(shuffled[i], j++) === false) { return; } } fn(shuffled[0], j); }; /** * Creates a new sequence with every element from this sequence, and with arrays * exploded so that a sequence of arrays (of arrays) becomes a flat sequence of * values. * * @public * @returns {Sequence} The new sequence. * * @examples * Lazy([1, [2, 3], [4, [5]]]).flatten() // sequence: [1, 2, 3, 4, 5] * Lazy([1, Lazy([2, 3])]).flatten() // sequence: [1, 2, 3] */ Sequence.prototype.flatten = function flatten() { return new FlattenedSequence(this); }; /** * @constructor */ function FlattenedSequence(parent) { this.parent = parent; } FlattenedSequence.prototype = new Sequence(); FlattenedSequence.prototype.each = function each(fn) { var index = 0; return this.parent.each(function recurseVisitor(e) { if (e instanceof Array) { return forEach(e, recurseVisitor); } if (e instanceof Sequence) { return e.each(recurseVisitor); } return fn(e, index++); }); }; /** * Creates a new sequence with the same elements as this one, except for all * falsy values (`false`, `0`, `""`, `null`, and `undefined`). * * @public * @returns {Sequence} The new sequence. * * @examples * Lazy(["foo", null, "bar", undefined]).compact() // sequence: ["foo", "bar"] */ Sequence.prototype.compact = function compact() { return this.filter(function(e) { return !!e; }); }; /** * Creates a new sequence with all the elements of this sequence that are not * also among the specified arguments. * * @public * @aka difference * @param {...*} var_args The values, or array(s) of values, to be excluded from the * resulting sequence. * @returns {Sequence} The new sequence. * * @examples * Lazy([1, 2, 3, 4, 5]).without(2, 3) // sequence: [1, 4, 5] * Lazy([1, 2, 3, 4, 5]).without([4, 5]) // sequence: [1, 2, 3] */ Sequence.prototype.without = function without(var_args) { return new WithoutSequence(this, arraySlice.call(arguments, 0)); }; Sequence.prototype.difference = function difference(var_args) { return this.without.apply(this, arguments); }; /** * @constructor */ function WithoutSequence(parent, values) { this.parent = parent; this.values = values; } WithoutSequence.prototype = new Sequence(); WithoutSequence.prototype.each = function each(fn) { var set = createSet(this.values), i = 0; return this.parent.each(function(e) { if (!set.contains(e)) { return fn(e, i++); } }); }; /** * Creates a new sequence with all the unique elements either in this sequence * or among the specified arguments. * * @public * @param {...*} var_args The values, or array(s) of values, to be additionally * included in the resulting sequence. * @returns {Sequence} The new sequence. * * @examples * Lazy(["foo", "bar"]).union([]) // sequence: ["foo", "bar"] * Lazy(["foo", "bar"]).union(["bar", "baz"]) // sequence: ["foo", "bar", "baz"] */ Sequence.prototype.union = function union(var_args) { return this.concat(var_args).uniq(); }; /** * Creates a new sequence with all the elements of this sequence that also * appear among the specified arguments. * * @public * @param {...*} var_args The values, or array(s) of values, in which elements * from this sequence must also be included to end up in the resulting sequence. * @returns {Sequence} The new sequence. * * @examples * Lazy(["foo", "bar"]).intersection([]) // sequence: [] * Lazy(["foo", "bar"]).intersection(["bar", "baz"]) // sequence: ["bar"] */ Sequence.prototype.intersection = function intersection(var_args) { if (arguments.length === 1 && arguments[0] instanceof Array) { return new SimpleIntersectionSequence(this, (/** @type {Array} */ var_args)); } else { return new IntersectionSequence(this, arraySlice.call(arguments, 0)); } }; /** * @constructor */ function IntersectionSequence(parent, arrays) { this.parent = parent; this.arrays = arrays; } IntersectionSequence.prototype = new Sequence(); IntersectionSequence.prototype.each = function each(fn) { var sets = Lazy(this.arrays).map(function(values) { return new UniqueMemoizer(Lazy(values).getIterator()); }); var setIterator = new UniqueMemoizer(sets.getIterator()), i = 0; return this.parent.each(function(e) { var includedInAll = true; setIterator.each(function(set) { if (!set.contains(e)) { includedInAll = false; return false; } }); if (includedInAll) { return fn(e, i++); } }); }; /** * @constructor */ function UniqueMemoizer(iterator) { this.iterator = iterator; this.set = new Set(); this.memo = []; this.currentValue = undefined; } UniqueMemoizer.prototype.current = function current() { return this.currentValue; }; UniqueMemoizer.prototype.moveNext = function moveNext() { var iterator = this.iterator, set = this.set, memo = this.memo, current; while (iterator.moveNext()) { current = iterator.current(); if (set.add(current)) { memo.push(current); this.currentValue = current; return true; } } return false; }; UniqueMemoizer.prototype.each = function each(fn) { var memo = this.memo, length = memo.length, i = -1; while (++i < length) { if (fn(memo[i], i) === false) { return false; } } while (this.moveNext()) { if (fn(this.currentValue, i++) === false) { break; } } }; UniqueMemoizer.prototype.contains = function contains(e) { if (this.set.contains(e)) { return true; } while (this.moveNext()) { if (this.currentValue === e) { return true; } } return false; }; /** * Checks whether every element in this sequence satisfies a given predicate. * * @public * @aka all * @param {Function} predicate A function to call on (potentially) every element * in this sequence. * @returns {boolean} True if `predicate` returns true for every element in the * sequence (or the sequence is empty). False if `predicate` returns false * for at least one element. * * @examples * var numbers = [1, 2, 3, 4, 5]; * * var objects = [{ foo: true }, { foo: false, bar: true }]; * * Lazy(numbers).every(isEven) // => false * Lazy(numbers).every(isPositive) // => true * Lazy(objects).all('foo') // => false * Lazy(objects).all('bar') // => false */ Sequence.prototype.every = function every(predicate) { predicate = createCallback(predicate); return this.each(function(e, i) { return !!predicate(e, i); }); }; Sequence.prototype.all = function all(predicate) { return this.every(predicate); }; /** * Checks whether at least one element in this sequence satisfies a given * predicate (or, if no predicate is specified, whether the sequence contains at * least one element). * * @public * @aka any * @param {Function=} predicate A function to call on (potentially) every element * in this sequence. * @returns {boolean} True if `predicate` returns true for at least one element * in the sequence. False if `predicate` returns false for every element (or * the sequence is empty). * * @examples * var numbers = [1, 2, 3, 4, 5]; * * Lazy(numbers).some() // => true * Lazy(numbers).some(isEven) // => true * Lazy(numbers).some(isNegative) // => false * Lazy([]).some() // => false */ Sequence.prototype.some = function some(predicate) { predicate = createCallback(predicate, true); var success = false; this.each(function(e) { if (predicate(e)) { success = true; return false; } }); return success; }; Sequence.prototype.any = function any(predicate) { return this.some(predicate); }; /** * Checks whether NO elements in this sequence satisfy the given predicate * (the opposite of {@link Sequence#all}, basically). * * @public * @param {Function=} predicate A function to call on (potentially) every element * in this sequence. * @returns {boolean} True if `predicate` does not return true for any element * in the sequence. False if `predicate` returns true for at least one * element. * * @examples * var numbers = [1, 2, 3, 4, 5]; * * Lazy(numbers).none() // => false * Lazy(numbers).none(isEven) // => false * Lazy(numbers).none(isNegative) // => true * Lazy([]).none(isEven) // => true * Lazy([]).none(isNegative) // => true * Lazy([]).none() // => true */ Sequence.prototype.none = function none(predicate) { return !this.any(predicate); }; /** * Checks whether the sequence has no elements. * * @public * @returns {boolean} True if the sequence is empty, false if it contains at * least one element. * * @examples * Lazy([]).isEmpty() // => true * Lazy([1, 2, 3]).isEmpty() // => false */ Sequence.prototype.isEmpty = function isEmpty() { return !this.any(); }; /** * Performs (at worst) a linear search from the head of this sequence, * returning the first index at which the specified value is found. * * @public * @param {*} value The element to search for in the sequence. * @returns {number} The index within this sequence where the given value is * located, or -1 if the sequence doesn't contain the value. * * @examples * function reciprocal(x) { return 1 / x; } * * Lazy(["foo", "bar", "baz"]).indexOf("bar") // => 1 * Lazy([1, 2, 3]).indexOf(4) // => -1 * Lazy([1, 2, 3]).map(reciprocal).indexOf(0.5) // => 1 */ Sequence.prototype.indexOf = function indexOf(value) { var foundIndex = -1; this.each(function(e, i) { if (e === value) { foundIndex = i; return false; } }); return foundIndex; }; /** * Performs (at worst) a linear search from the tail of this sequence, * returning the last index at which the specified value is found. * * @public * @param {*} value The element to search for in the sequence. * @returns {number} The last index within this sequence where the given value * is located, or -1 if the sequence doesn't contain the value. * * @examples * Lazy(["a", "b", "c", "b", "a"]).lastIndexOf("b") // => 3 * Lazy([1, 2, 3]).lastIndexOf(0) // => -1 * Lazy([2, 2, 1, 2, 4]).filter(isEven).lastIndexOf(2) // 2 */ Sequence.prototype.lastIndexOf = function lastIndexOf(value) { var reversed = this.getIndex().reverse(), index = reversed.indexOf(value); if (index !== -1) { index = reversed.length() - index - 1; } return index; }; /** * Performs a binary search of this sequence, returning the lowest index where * the given value is either found, or where it belongs (if it is not already * in the sequence). * * This method assumes the sequence is in sorted order and will fail otherwise. * * @public * @param {*} value The element to search for in the sequence. * @returns {number} An index within this sequence where the given value is * located, or where it belongs in sorted order. * * @examples * Lazy([1, 3, 6, 9]).sortedIndex(3) // => 1 * Lazy([1, 3, 6, 9]).sortedIndex(7) // => 3 * Lazy([5, 10, 15, 20]).filter(isEven).sortedIndex(10) // => 0 * Lazy([5, 10, 15, 20]).filter(isEven).sortedIndex(12) // => 1 */ Sequence.prototype.sortedIndex = function sortedIndex(value) { var indexed = this.getIndex(), lower = 0, upper = indexed.length(), i; while (lower < upper) { i = (lower + upper) >>> 1; if (compare(indexed.get(i), value) === -1) { lower = i + 1; } else { upper = i; } } return lower; }; /** * Checks whether the given value is in this sequence. * * @public * @param {*} value The element to search for in the sequence. * @returns {boolean} True if the sequence contains the value, false if not. * * @examples * var numbers = [5, 10, 15, 20]; * * Lazy(numbers).contains(15) // => true * Lazy(numbers).contains(13) // => false */ Sequence.prototype.contains = function contains(value) { return this.indexOf(value) !== -1; }; /** * Aggregates a sequence into a single value according to some accumulator * function. * * For an asynchronous sequence, instead of immediately returning a result * (which it can't, obviously), this method returns an {@link AsyncHandle} * whose `onComplete` method can be called to supply a callback to handle the * final result once iteration has completed. * * @public * @aka inject, foldl * @param {Function} aggregator The function through which to pass every element * in the sequence. For every element, the function will be passed the total * aggregated result thus far and the element itself, and should return a * new aggregated result. * @param {*=} memo The starting value to use for the aggregated result * (defaults to the first element in the sequence). * @returns {*} The result of the aggregation, or, for asynchronous sequences, * an {@link AsyncHandle} whose `onComplete` method accepts a callback to * handle the final result. * * @examples * function multiply(x, y) { return x * y; } * * var numbers = [1, 2, 3, 4]; * * Lazy(numbers).reduce(multiply) // => 24 * Lazy(numbers).reduce(multiply, 5) // => 120 */ Sequence.prototype.reduce = function reduce(aggregator, memo) { if (arguments.length < 2) { return this.tail().reduce(aggregator, this.head()); } var eachResult = this.each(function(e, i) { memo = aggregator(memo, e, i); }); // TODO: Think of a way more efficient solution to this problem. if (eachResult instanceof AsyncHandle) { return eachResult.then(function() { return memo; }); } return memo; }; Sequence.prototype.inject = Sequence.prototype.foldl = function foldl(aggregator, memo) { return this.reduce(aggregator, memo); }; /** * Aggregates a sequence, from the tail, into a single value according to some * accumulator function. * * @public * @aka foldr * @param {Function} aggregator The function through which to pass every element * in the sequence. For every element, the function will be passed the total * aggregated result thus far and the element itself, and should return a * new aggregated result. * @param {*} memo The starting value to use for the aggregated result. * @returns {*} The result of the aggregation. * * @examples * function append(s1, s2) { * return s1 + s2; * } * * function isVowel(str) { * return "aeiou".indexOf(str) !== -1; * } * * Lazy("abcde").reduceRight(append) // => "edcba" * Lazy("abcde").filter(isVowel).reduceRight(append) // => "ea" */ Sequence.prototype.reduceRight = function reduceRight(aggregator, memo) { if (arguments.length < 2) { return this.initial(1).reduceRight(aggregator, this.last()); } // This bothers me... but frankly, calling reverse().reduce() is potentially // going to eagerly evaluate the sequence anyway; so it's really not an issue. var indexed = this.getIndex(), i = indexed.length() - 1; return indexed.reverse().reduce(function(m, e) { return aggregator(m, e, i--); }, memo); }; Sequence.prototype.foldr = function foldr(aggregator, memo) { return this.reduceRight(aggregator, memo); }; /** * Groups this sequence into consecutive (overlapping) segments of a specified * length. If the underlying sequence has fewer elements than the specfied * length, then this sequence will be empty. * * @public * @param {number} length The length of each consecutive segment. * @returns {Sequence} The resulting sequence of consecutive segments. * * @examples * Lazy([]).consecutive(2) // => sequence: [] * Lazy([1]).consecutive(2) // => sequence: [] * Lazy([1, 2]).consecutive(2) // => sequence: [[1, 2]] * Lazy([1, 2, 3]).consecutive(2) // => sequence: [[1, 2], [2, 3]] * Lazy([1, 2, 3]).consecutive(0) // => sequence: [[]] * Lazy([1, 2, 3]).consecutive(1) // => sequence: [[1], [2], [3]] */ Sequence.prototype.consecutive = function consecutive(count) { var queue = new Queue(count); var segments = this.map(function(element) { if (queue.add(element).count === count) { return queue.toArray(); } }); return segments.compact(); }; /** * Breaks this sequence into chunks (arrays) of a specified length. * * @public * @param {number} size The size of each chunk. * @returns {Sequence} The resulting sequence of chunks. * * @examples * Lazy([]).chunk(2) // sequence: [] * Lazy([1, 2, 3]).chunk(2) // sequence: [[1, 2], [3]] * Lazy([1, 2, 3]).chunk(1) // sequence: [[1], [2], [3]] * Lazy([1, 2, 3]).chunk(4) // sequence: [[1, 2, 3]] * Lazy([1, 2, 3]).chunk(0) // throws */ Sequence.prototype.chunk = function chunk(size) { if (size < 1) { throw new Error("You must specify a positive chunk size."); } return new ChunkedSequence(this, size); }; /** * @constructor */ function ChunkedSequence(parent, size) { this.parent = parent; this.chunkSize = size; } ChunkedSequence.prototype = new Sequence(); ChunkedSequence.prototype.getIterator = function getIterator() { return new ChunkedIterator(this.parent, this.chunkSize); }; /** * @constructor */ function ChunkedIterator(sequence, size) { this.iterator = sequence.getIterator(); this.size = size; } ChunkedIterator.prototype.current = function current() { return this.currentChunk; }; ChunkedIterator.prototype.moveNext = function moveNext() { var iterator = this.iterator, chunkSize = this.size, chunk = []; while (chunk.length < chunkSize && iterator.moveNext()) { chunk.push(iterator.current()); } if (chunk.length === 0) { return false; } this.currentChunk = chunk; return true; }; /** * Passes each element in the sequence to the specified callback during * iteration. This is like {@link Sequence#each}, except that it can be * inserted anywhere in the middle of a chain of methods to "intercept" the * values in the sequence at that point. * * @public * @param {Function} callback A function to call on every element in the * sequence during iteration. The return value of this function does not * matter. * @returns {Sequence} A sequence comprising the same elements as this one. * * @examples * Lazy([1, 2, 3]).tap(fn).each(Lazy.noop); // calls fn 3 times */ Sequence.prototype.tap = function tap(callback) { return new TappedSequence(this, callback); }; /** * @constructor */ function TappedSequence(parent, callback) { this.parent = parent; this.callback = callback; } TappedSequence.prototype = new Sequence(); TappedSequence.prototype.each = function each(fn) { var callback = this.callback; return this.parent.each(function(e, i) { callback(e, i); return fn(e, i); }); }; /** * Seaches for the first element in the sequence satisfying a given predicate. * * @public * @aka detect * @param {Function} predicate A function to call on (potentially) every element * in the sequence. * @returns {*} The first element in the sequence for which `predicate` returns * `true`, or `undefined` if no such element is found. * * @examples * function divisibleBy3(x) { * return x % 3 === 0; * } * * var numbers = [5, 6, 7, 8, 9, 10]; * * Lazy(numbers).find(divisibleBy3) // => 6 * Lazy(numbers).find(isNegative) // => undefined */ Sequence.prototype.find = function find(predicate) { return this.filter(predicate).first(); }; Sequence.prototype.detect = function detect(predicate) { return this.find(predicate); }; /** * Gets the minimum value in the sequence. * * @public * @param {Function=} valueFn The function by which the value for comparison is * calculated for each element in the sequence. * @returns {*} The element with the lowest value in the sequence, or * `Infinity` if the sequence is empty. * * @examples * function negate(x) { return x * -1; } * * Lazy([]).min() // => Infinity * Lazy([6, 18, 2, 49, 34]).min() // => 2 * Lazy([6, 18, 2, 49, 34]).min(negate) // => 49 */ Sequence.prototype.min = function min(valueFn) { if (typeof valueFn !== "undefined") { return this.minBy(valueFn); } return this.reduce(function(x, y) { return y < x ? y : x; }, Infinity); }; Sequence.prototype.minBy = function minBy(valueFn) { valueFn = createCallback(valueFn); return this.reduce(function(x, y) { return valueFn(y) < valueFn(x) ? y : x; }); }; /** * Gets the maximum value in the sequence. * * @public * @param {Function=} valueFn The function by which the value for comparison is * calculated for each element in the sequence. * @returns {*} The element with the highest value in the sequence, or * `-Infinity` if the sequence is empty. * * @examples * function reverseDigits(x) { * return Number(String(x).split('').reverse().join('')); * } * * Lazy([]).max() // => -Infinity * Lazy([6, 18, 2, 48, 29]).max() // => 48 * Lazy([6, 18, 2, 48, 29]).max(reverseDigits) // => 29 */ Sequence.prototype.max = function max(valueFn) { if (typeof valueFn !== "undefined") { return this.maxBy(valueFn); } return this.reduce(function(x, y) { return y > x ? y : x; }, -Infinity); }; Sequence.prototype.maxBy = function maxBy(valueFn) { valueFn = createCallback(valueFn); return this.reduce(function(x, y) { return valueFn(y) > valueFn(x) ? y : x; }); }; /** * Gets the sum of the values in the sequence. * * @public * @param {Function=} valueFn The function used to select the values that will * be summed up. * @returns {*} The sum. * * @examples * Lazy([]).sum() // => 0 * Lazy([1, 2, 3, 4]).sum() // => 10 * Lazy([1.2, 3.4]).sum(Math.floor) // => 4 * Lazy(['foo', 'bar']).sum('length') // => 6 */ Sequence.prototype.sum = function sum(valueFn) { if (typeof valueFn !== "undefined") { return this.sumBy(valueFn); } return this.reduce(function(x, y) { return x + y; }, 0); }; Sequence.prototype.sumBy = function sumBy(valueFn) { valueFn = createCallback(valueFn); return this.reduce(function(x, y) { return x + valueFn(y); }, 0); }; /** * Creates a string from joining together all of the elements in this sequence, * separated by the given delimiter. * * @public * @aka toString * @param {string=} delimiter The separator to insert between every element from * this sequence in the resulting string (defaults to `","`). * @returns {string} The delimited string. * * @examples * Lazy([6, 29, 1984]).join("/") // => "6/29/1984" * Lazy(["a", "b", "c"]).join() // => "a,b,c" * Lazy(["a", "b", "c"]).join("") // => "abc" * Lazy([1, 2, 3]).join() // => "1,2,3" * Lazy([1, 2, 3]).join("") // => "123" * Lazy(["", "", ""]).join(",") // => ",," */ Sequence.prototype.join = function join(delimiter) { delimiter = typeof delimiter === "string" ? delimiter : ","; return this.reduce(function(str, e, i) { if (i > 0) { str += delimiter; } return str + e; }, ""); }; Sequence.prototype.toString = function toString(delimiter) { return this.join(delimiter); }; /** * Creates a sequence, with the same elements as this one, that will be iterated * over asynchronously when calling `each`. * * @public * @param {number=} interval The approximate period, in milliseconds, that * should elapse between each element in the resulting sequence. Omitting * this argument will result in the fastest possible asynchronous iteration. * @returns {AsyncSequence} The new asynchronous sequence. * * @examples * Lazy([1, 2, 3]).async(100).each(fn) // calls fn 3 times asynchronously */ Sequence.prototype.async = function async(interval) { return new AsyncSequence(this, interval); }; /** * @constructor */ function SimpleIntersectionSequence(parent, array) { this.parent = parent; this.array = array; this.each = getEachForIntersection(array); } SimpleIntersectionSequence.prototype = new Sequence(); SimpleIntersectionSequence.prototype.eachMemoizerCache = function eachMemoizerCache(fn) { var iterator = new UniqueMemoizer(Lazy(this.array).getIterator()), i = 0; return this.parent.each(function(e) { if (iterator.contains(e)) { return fn(e, i++); } }); }; SimpleIntersectionSequence.prototype.eachArrayCache = function eachArrayCache(fn) { var array = this.array, find = arrayContains, i = 0; return this.parent.each(function(e) { if (find(array, e)) { return fn(e, i++); } }); }; function getEachForIntersection(source) { if (source.length < 40) { return SimpleIntersectionSequence.prototype.eachArrayCache; } else { return SimpleIntersectionSequence.prototype.eachMemoizerCache; } } /** * An optimized version of {@link ZippedSequence}, when zipping a sequence with * only one array. * * @param {Sequence} parent The underlying sequence. * @param {Array} array The array with which to zip the sequence. * @constructor */ function SimpleZippedSequence(parent, array) { this.parent = parent; this.array = array; } SimpleZippedSequence.prototype = new Sequence(); SimpleZippedSequence.prototype.each = function each(fn) { var array = this.array; return this.parent.each(function(e, i) { return fn([e, array[i]], i); }); }; /** * An `ArrayLikeSequence` is a {@link Sequence} that provides random access to * its elements. This extends the API for iterating with the additional methods * {@link #get} and {@link #length}, allowing a sequence to act as a "view" into * a collection or other indexed data source. * * The initial sequence created by wrapping an array with `Lazy(array)` is an * `ArrayLikeSequence`. * * All methods of `ArrayLikeSequence` that conceptually should return * something like a array (with indexed access) return another * `ArrayLikeSequence`, for example: * * - {@link Sequence#map} * - {@link ArrayLikeSequence#slice} * - {@link Sequence#take} and {@link Sequence#drop} * - {@link Sequence#reverse} * * The above is not an exhaustive list. There are also certain other cases * where it might be possible to return an `ArrayLikeSequence` (e.g., calling * {@link Sequence#concat} with a single array argument), but this is not * guaranteed by the API. * * Note that in many cases, it is not possible to provide indexed access * without first performing at least a partial iteration of the underlying * sequence. In these cases an `ArrayLikeSequence` will not be returned: * * - {@link Sequence#filter} * - {@link Sequence#uniq} * - {@link Sequence#union} * - {@link Sequence#intersect} * * etc. The above methods only return ordinary {@link Sequence} objects. * * Defining custom array-like sequences * ------------------------------------ * * Creating a custom `ArrayLikeSequence` is essentially the same as creating a * custom {@link Sequence}. You just have a couple more methods you need to * implement: `get` and (optionally) `length`. * * Here's an example. Let's define a sequence type called `OffsetSequence` that * offsets each of its parent's elements by a set distance, and circles back to * the beginning after reaching the end. **Remember**: the initialization * function you pass to {@link #define} should always accept a `parent` as its * first parameter. * * ArrayLikeSequence.define("offset", { * init: function(parent, offset) { * this.offset = offset; * }, * * get: function(i) { * return this.parent.get((i + this.offset) % this.parent.length()); * } * }); * * It's worth noting a couple of things here. * * First, Lazy's default implementation of `length` simply returns the parent's * length. In this case, since an `OffsetSequence` will always have the same * number of elements as its parent, that implementation is fine; so we don't * need to override it. * * Second, the default implementation of `each` uses `get` and `length` to * essentially create a `for` loop, which is fine here. If you want to implement * `each` your own way, you can do that; but in most cases (as here), you can * probably just stick with the default. * * So we're already done, after only implementing `get`! Pretty easy, huh? * * Now the `offset` method will be chainable from any `ArrayLikeSequence`. So * for example: * * Lazy([1, 2, 3]).map(mapFn).offset(3); * * ...will work, but: * * Lazy([1, 2, 3]).filter(mapFn).offset(3); * * ...will not (because `filter` does not return an `ArrayLikeSequence`). * * (Also, as with the example provided for defining custom {@link Sequence} * types, this example really could have been implemented using a function * already available as part of Lazy.js: in this case, {@link Sequence#map}.) * * @public * @constructor * * @examples * Lazy([1, 2, 3]) // instanceof Lazy.ArrayLikeSequence * Lazy([1, 2, 3]).map(Lazy.identity) // instanceof Lazy.ArrayLikeSequence * Lazy([1, 2, 3]).take(2) // instanceof Lazy.ArrayLikeSequence * Lazy([1, 2, 3]).drop(2) // instanceof Lazy.ArrayLikeSequence * Lazy([1, 2, 3]).reverse() // instanceof Lazy.ArrayLikeSequence * Lazy([1, 2, 3]).slice(1, 2) // instanceof Lazy.ArrayLikeSequence */ function ArrayLikeSequence() {} ArrayLikeSequence.prototype = new Sequence(); /** * Create a new constructor function for a type inheriting from * `ArrayLikeSequence`. * * @public * @param {string|Array.} methodName The name(s) of the method(s) to be * used for constructing the new sequence. The method will be attached to * the `ArrayLikeSequence` prototype so that it can be chained with any other * methods that return array-like sequences. * @param {Object} overrides An object containing function overrides for this * new sequence type. **Must** include `get`. *May* include `init`, * `length`, `getIterator`, and `each`. For each function, `this` will be * the new sequence and `this.parent` will be the source sequence. * @returns {Function} A constructor for a new type inheriting from * `ArrayLikeSequence`. * * @examples * Lazy.ArrayLikeSequence.define("offset", { * init: function(offset) { * this.offset = offset; * }, * * get: function(i) { * return this.parent.get((i + this.offset) % this.parent.length()); * } * }); * * Lazy([1, 2, 3]).offset(1) // sequence: [2, 3, 1] */ ArrayLikeSequence.define = function define(methodName, overrides) { if (!overrides || typeof overrides.get !== 'function') { throw new Error("A custom array-like sequence must implement *at least* get!"); } return defineSequenceType(ArrayLikeSequence, methodName, overrides); }; /** * Returns the element at the specified index. * * @public * @param {number} i The index to access. * @returns {*} The element. * * @examples * function increment(x) { return x + 1; } * * Lazy([1, 2, 3]).get(1) // => 2 * Lazy([1, 2, 3]).get(-1) // => undefined * Lazy([1, 2, 3]).map(increment).get(1) // => 3 */ ArrayLikeSequence.prototype.get = function get(i) { return this.parent.get(i); }; /** * Returns the length of the sequence. * * @public * @returns {number} The length. * * @examples * function increment(x) { return x + 1; } * * Lazy([]).length() // => 0 * Lazy([1, 2, 3]).length() // => 3 * Lazy([1, 2, 3]).map(increment).length() // => 3 */ ArrayLikeSequence.prototype.length = function length() { return this.parent.length(); }; /** * Returns the current sequence (since it is already indexed). */ ArrayLikeSequence.prototype.getIndex = function getIndex() { return this; }; /** * An optimized version of {@link Sequence#getIterator}. */ ArrayLikeSequence.prototype.getIterator = function getIterator() { return new IndexedIterator(this); }; /** * An optimized version of {@link Iterator} meant to work with already-indexed * sequences. * * @param {ArrayLikeSequence} sequence The sequence to iterate over. * @constructor */ function IndexedIterator(sequence) { this.sequence = sequence; this.index = -1; } IndexedIterator.prototype.current = function current() { return this.sequence.get(this.index); }; IndexedIterator.prototype.moveNext = function moveNext() { if (this.index >= this.sequence.length() - 1) { return false; } ++this.index; return true; }; /** * An optimized version of {@link Sequence#each}. */ ArrayLikeSequence.prototype.each = function each(fn) { var length = this.length(), i = -1; while (++i < length) { if (fn(this.get(i), i) === false) { return false; } } return true; }; /** * Returns a new sequence with the same elements as this one, minus the last * element. * * @public * @returns {ArrayLikeSequence} The new array-like sequence. * * @examples * Lazy([1, 2, 3]).pop() // sequence: [1, 2] * Lazy([]).pop() // sequence: [] */ ArrayLikeSequence.prototype.pop = function pop() { return this.initial(); }; /** * Returns a new sequence with the same elements as this one, minus the first * element. * * @public * @returns {ArrayLikeSequence} The new array-like sequence. * * @examples * Lazy([1, 2, 3]).shift() // sequence: [2, 3] * Lazy([]).shift() // sequence: [] */ ArrayLikeSequence.prototype.shift = function shift() { return this.drop(); }; /** * Returns a new sequence comprising the portion of this sequence starting * from the specified starting index and continuing until the specified ending * index or to the end of the sequence. * * @public * @param {number} begin The index at which the new sequence should start. * @param {number=} end The index at which the new sequence should end. * @returns {ArrayLikeSequence} The new array-like sequence. * * @examples * Lazy([1, 2, 3, 4, 5]).slice(0) // sequence: [1, 2, 3, 4, 5] * Lazy([1, 2, 3, 4, 5]).slice(2) // sequence: [3, 4, 5] * Lazy([1, 2, 3, 4, 5]).slice(2, 4) // sequence: [3, 4] * Lazy([1, 2, 3, 4, 5]).slice(-1) // sequence: [5] * Lazy([1, 2, 3, 4, 5]).slice(1, -1) // sequence: [2, 3, 4] * Lazy([1, 2, 3, 4, 5]).slice(0, 10) // sequence: [1, 2, 3, 4, 5] */ ArrayLikeSequence.prototype.slice = function slice(begin, end) { var length = this.length(); if (begin < 0) { begin = length + begin; } var result = this.drop(begin); if (typeof end === "number") { if (end < 0) { end = length + end; } result = result.take(end - begin); } return result; }; /** * An optimized version of {@link Sequence#map}, which creates an * {@link ArrayLikeSequence} so that the result still provides random access. * * @public * * @examples * Lazy([1, 2, 3]).map(Lazy.identity) // instanceof Lazy.ArrayLikeSequence */ ArrayLikeSequence.prototype.map = function map(mapFn) { return new IndexedMappedSequence(this, createCallback(mapFn)); }; /** * @constructor */ function IndexedMappedSequence(parent, mapFn) { this.parent = parent; this.mapFn = mapFn; } IndexedMappedSequence.prototype = new ArrayLikeSequence(); IndexedMappedSequence.prototype.get = function get(i) { if (i < 0 || i >= this.parent.length()) { return undefined; } return this.mapFn(this.parent.get(i), i); }; /** * An optimized version of {@link Sequence#filter}. */ ArrayLikeSequence.prototype.filter = function filter(filterFn) { return new IndexedFilteredSequence(this, createCallback(filterFn)); }; /** * @constructor */ function IndexedFilteredSequence(parent, filterFn) { this.parent = parent; this.filterFn = filterFn; } IndexedFilteredSequence.prototype = new FilteredSequence(); IndexedFilteredSequence.prototype.each = function each(fn) { var parent = this.parent, filterFn = this.filterFn, length = this.parent.length(), i = -1, j = 0, e; while (++i < length) { e = parent.get(i); if (filterFn(e, i) && fn(e, j++) === false) { return false; } } return true; }; /** * An optimized version of {@link Sequence#reverse}, which creates an * {@link ArrayLikeSequence} so that the result still provides random access. * * @public * * @examples * Lazy([1, 2, 3]).reverse() // instanceof Lazy.ArrayLikeSequence */ ArrayLikeSequence.prototype.reverse = function reverse() { return new IndexedReversedSequence(this); }; /** * @constructor */ function IndexedReversedSequence(parent) { this.parent = parent; } IndexedReversedSequence.prototype = new ArrayLikeSequence(); IndexedReversedSequence.prototype.get = function get(i) { return this.parent.get(this.length() - i - 1); }; /** * An optimized version of {@link Sequence#first}, which creates an * {@link ArrayLikeSequence} so that the result still provides random access. * * @public * * @examples * Lazy([1, 2, 3]).first(2) // instanceof Lazy.ArrayLikeSequence */ ArrayLikeSequence.prototype.first = function first(count) { if (typeof count === "undefined") { return this.get(0); } return new IndexedTakeSequence(this, count); }; /** * @constructor */ function IndexedTakeSequence(parent, count) { this.parent = parent; this.count = count; } IndexedTakeSequence.prototype = new ArrayLikeSequence(); IndexedTakeSequence.prototype.length = function length() { var parentLength = this.parent.length(); return this.count <= parentLength ? this.count : parentLength; }; /** * An optimized version of {@link Sequence#rest}, which creates an * {@link ArrayLikeSequence} so that the result still provides random access. * * @public * * @examples * Lazy([1, 2, 3]).rest() // instanceof Lazy.ArrayLikeSequence */ ArrayLikeSequence.prototype.rest = function rest(count) { return new IndexedDropSequence(this, count); }; /** * @constructor */ function IndexedDropSequence(parent, count) { this.parent = parent; this.count = typeof count === "number" ? count : 1; } IndexedDropSequence.prototype = new ArrayLikeSequence(); IndexedDropSequence.prototype.get = function get(i) { return this.parent.get(this.count + i); }; IndexedDropSequence.prototype.length = function length() { var parentLength = this.parent.length(); return this.count <= parentLength ? parentLength - this.count : 0; }; /** * An optimized version of {@link Sequence#concat} that returns another * {@link ArrayLikeSequence} *if* the argument is an array. * * @public * @param {...*} var_args * * @examples * Lazy([1, 2]).concat([3, 4]) // instanceof Lazy.ArrayLikeSequence * Lazy([1, 2]).concat([3, 4]) // sequence: [1, 2, 3, 4] */ ArrayLikeSequence.prototype.concat = function concat(var_args) { if (arguments.length === 1 && arguments[0] instanceof Array) { return new IndexedConcatenatedSequence(this, (/** @type {Array} */ var_args)); } else { return Sequence.prototype.concat.apply(this, arguments); } }; /** * @constructor */ function IndexedConcatenatedSequence(parent, other) { this.parent = parent; this.other = other; } IndexedConcatenatedSequence.prototype = new ArrayLikeSequence(); IndexedConcatenatedSequence.prototype.get = function get(i) { var parentLength = this.parent.length(); if (i < parentLength) { return this.parent.get(i); } else { return this.other[i - parentLength]; } }; IndexedConcatenatedSequence.prototype.length = function length() { return this.parent.length() + this.other.length; }; /** * An optimized version of {@link Sequence#uniq}. */ ArrayLikeSequence.prototype.uniq = function uniq(keyFn) { return new IndexedUniqueSequence(this, createCallback(keyFn)); }; /** * @param {ArrayLikeSequence} parent * @constructor */ function IndexedUniqueSequence(parent, keyFn) { this.parent = parent; this.each = getEachForParent(parent); this.keyFn = keyFn; } IndexedUniqueSequence.prototype = new Sequence(); IndexedUniqueSequence.prototype.eachArrayCache = function eachArrayCache(fn) { // Basically the same implementation as w/ the set, but using an array because // it's cheaper for smaller sequences. var parent = this.parent, keyFn = this.keyFn, length = parent.length(), cache = [], find = arrayContains, key, value, i = -1, j = 0; while (++i < length) { value = parent.get(i); key = keyFn(value); if (!find(cache, key)) { cache.push(key); if (fn(value, j++) === false) { return false; } } } }; IndexedUniqueSequence.prototype.eachSetCache = UniqueSequence.prototype.each; function getEachForParent(parent) { if (parent.length() < 100) { return IndexedUniqueSequence.prototype.eachArrayCache; } else { return UniqueSequence.prototype.each; } } // Now that we've fully initialized the ArrayLikeSequence prototype, we can // set the prototype for MemoizedSequence. MemoizedSequence.prototype = new ArrayLikeSequence(); MemoizedSequence.prototype.cache = function cache() { return this.cachedResult || (this.cachedResult = this.parent.toArray()); }; MemoizedSequence.prototype.get = function get(i) { return this.cache()[i]; }; MemoizedSequence.prototype.length = function length() { return this.cache().length; }; MemoizedSequence.prototype.slice = function slice(begin, end) { return this.cache().slice(begin, end); }; MemoizedSequence.prototype.toArray = function toArray() { return this.cache().slice(0); }; /** * ArrayWrapper is the most basic {@link Sequence}. It directly wraps an array * and implements the same methods as {@link ArrayLikeSequence}, but more * efficiently. * * @constructor */ function ArrayWrapper(source) { this.source = source; } ArrayWrapper.prototype = new ArrayLikeSequence(); ArrayWrapper.prototype.root = function root() { return this; }; ArrayWrapper.prototype.isAsync = function isAsync() { return false; }; /** * Returns the element at the specified index in the source array. * * @param {number} i The index to access. * @returns {*} The element. */ ArrayWrapper.prototype.get = function get(i) { return this.source[i]; }; /** * Returns the length of the source array. * * @returns {number} The length. */ ArrayWrapper.prototype.length = function length() { return this.source.length; }; /** * An optimized version of {@link Sequence#each}. */ ArrayWrapper.prototype.each = function each(fn) { return forEach(this.source, fn); }; /** * An optimized version of {@link Sequence#map}. */ ArrayWrapper.prototype.map = function map(mapFn) { return new MappedArrayWrapper(this, createCallback(mapFn)); }; /** * An optimized version of {@link Sequence#filter}. */ ArrayWrapper.prototype.filter = function filter(filterFn) { return new FilteredArrayWrapper(this, createCallback(filterFn)); }; /** * An optimized version of {@link Sequence#uniq}. */ ArrayWrapper.prototype.uniq = function uniq(keyFn) { return new UniqueArrayWrapper(this, keyFn); }; /** * An optimized version of {@link ArrayLikeSequence#concat}. * * @param {...*} var_args */ ArrayWrapper.prototype.concat = function concat(var_args) { if (arguments.length === 1 && arguments[0] instanceof Array) { return new ConcatArrayWrapper(this, (/** @type {Array} */ var_args)); } else { return ArrayLikeSequence.prototype.concat.apply(this, arguments); } }; /** * An optimized version of {@link Sequence#toArray}. */ ArrayWrapper.prototype.toArray = function toArray() { return this.source.slice(0); }; /** * @constructor */ function MappedArrayWrapper(parent, mapFn) { this.parent = parent; this.mapFn = mapFn; } MappedArrayWrapper.prototype = new ArrayLikeSequence(); MappedArrayWrapper.prototype.get = function get(i) { var source = this.parent.source; if (i < 0 || i >= source.length) { return undefined; } return this.mapFn(source[i]); }; MappedArrayWrapper.prototype.length = function length() { return this.parent.source.length; }; MappedArrayWrapper.prototype.each = function each(fn) { var source = this.parent.source, length = source.length, mapFn = this.mapFn, i = -1; while (++i < length) { if (fn(mapFn(source[i], i), i) === false) { return false; } } return true; }; /** * @constructor */ function FilteredArrayWrapper(parent, filterFn) { this.parent = parent; this.filterFn = filterFn; } FilteredArrayWrapper.prototype = new FilteredSequence(); FilteredArrayWrapper.prototype.each = function each(fn) { var source = this.parent.source, filterFn = this.filterFn, length = source.length, i = -1, j = 0, e; while (++i < length) { e = source[i]; if (filterFn(e, i) && fn(e, j++) === false) { return false; } } return true; }; /** * @constructor */ function UniqueArrayWrapper(parent, keyFn) { this.parent = parent; this.each = getEachForSource(parent.source); this.keyFn = keyFn; } UniqueArrayWrapper.prototype = new Sequence(); UniqueArrayWrapper.prototype.eachNoCache = function eachNoCache(fn) { var source = this.parent.source, keyFn = this.keyFn, length = source.length, find = arrayContainsBefore, value, // Yes, this is hideous. // Trying to get performance first, will refactor next! i = -1, k = 0; while (++i < length) { value = source[i]; if (!find(source, value, i, keyFn) && fn(value, k++) === false) { return false; } } return true; }; UniqueArrayWrapper.prototype.eachArrayCache = function eachArrayCache(fn) { // Basically the same implementation as w/ the set, but using an array because // it's cheaper for smaller sequences. var source = this.parent.source, keyFn = this.keyFn, length = source.length, cache = [], find = arrayContains, key, value, i = -1, j = 0; if (keyFn) { keyFn = createCallback(keyFn); while (++i < length) { value = source[i]; key = keyFn(value); if (!find(cache, key)) { cache.push(key); if (fn(value, j++) === false) { return false; } } } } else { while (++i < length) { value = source[i]; if (!find(cache, value)) { cache.push(value); if (fn(value, j++) === false) { return false; } } } } return true; }; UniqueArrayWrapper.prototype.eachSetCache = UniqueSequence.prototype.each; /** * My latest findings here... * * So I hadn't really given the set-based approach enough credit. The main issue * was that my Set implementation was totally not optimized at all. After pretty * heavily optimizing it (just take a look; it's a monstrosity now!), it now * becomes the fastest option for much smaller values of N. */ function getEachForSource(source) { if (source.length < 40) { return UniqueArrayWrapper.prototype.eachNoCache; } else if (source.length < 100) { return UniqueArrayWrapper.prototype.eachArrayCache; } else { return UniqueArrayWrapper.prototype.eachSetCache; } } /** * @constructor */ function ConcatArrayWrapper(parent, other) { this.parent = parent; this.other = other; } ConcatArrayWrapper.prototype = new ArrayLikeSequence(); ConcatArrayWrapper.prototype.get = function get(i) { var source = this.parent.source, sourceLength = source.length; if (i < sourceLength) { return source[i]; } else { return this.other[i - sourceLength]; } }; ConcatArrayWrapper.prototype.length = function length() { return this.parent.source.length + this.other.length; }; ConcatArrayWrapper.prototype.each = function each(fn) { var source = this.parent.source, sourceLength = source.length, other = this.other, otherLength = other.length, i = 0, j = -1; while (++j < sourceLength) { if (fn(source[j], i++) === false) { return false; } } j = -1; while (++j < otherLength) { if (fn(other[j], i++) === false) { return false; } } return true; }; /** * An `ObjectLikeSequence` object represents a sequence of key/value pairs. * * The initial sequence you get by wrapping an object with `Lazy(object)` is * an `ObjectLikeSequence`. * * All methods of `ObjectLikeSequence` that conceptually should return * something like an object return another `ObjectLikeSequence`. * * @public * @constructor * * @examples * var obj = { foo: 'bar' }; * * Lazy(obj).assign({ bar: 'baz' }) // instanceof Lazy.ObjectLikeSequence * Lazy(obj).defaults({ bar: 'baz' }) // instanceof Lazy.ObjectLikeSequence * Lazy(obj).invert() // instanceof Lazy.ObjectLikeSequence */ function ObjectLikeSequence() {} ObjectLikeSequence.prototype = new Sequence(); /** * Create a new constructor function for a type inheriting from * `ObjectLikeSequence`. * * @public * @param {string|Array.} methodName The name(s) of the method(s) to be * used for constructing the new sequence. The method will be attached to * the `ObjectLikeSequence` prototype so that it can be chained with any other * methods that return object-like sequences. * @param {Object} overrides An object containing function overrides for this * new sequence type. **Must** include `each`. *May* include `init` and * `get` (for looking up an element by key). * @returns {Function} A constructor for a new type inheriting from * `ObjectLikeSequence`. * * @examples * function downcaseKey(value, key) { * return [key.toLowerCase(), value]; * } * * Lazy.ObjectLikeSequence.define("caseInsensitive", { * init: function() { * var downcased = this.parent * .map(downcaseKey) * .toObject(); * this.downcased = Lazy(downcased); * }, * * get: function(key) { * return this.downcased.get(key.toLowerCase()); * }, * * each: function(fn) { * return this.downcased.each(fn); * } * }); * * Lazy({ Foo: 'bar' }).caseInsensitive() // sequence: { foo: 'bar' } * Lazy({ FOO: 'bar' }).caseInsensitive().get('foo') // => 'bar' * Lazy({ FOO: 'bar' }).caseInsensitive().get('FOO') // => 'bar' */ ObjectLikeSequence.define = function define(methodName, overrides) { if (!overrides || typeof overrides.each !== 'function') { throw new Error("A custom object-like sequence must implement *at least* each!"); } return defineSequenceType(ObjectLikeSequence, methodName, overrides); }; ObjectLikeSequence.prototype.value = function value() { return this.toObject(); }; /** * Gets the element at the specified key in this sequence. * * @public * @param {string} key The key. * @returns {*} The element. * * @examples * Lazy({ foo: "bar" }).get("foo") // => "bar" * Lazy({ foo: "bar" }).extend({ foo: "baz" }).get("foo") // => "baz" * Lazy({ foo: "bar" }).defaults({ bar: "baz" }).get("bar") // => "baz" * Lazy({ foo: "bar" }).invert().get("bar") // => "foo" * Lazy({ foo: 1, bar: 2 }).pick(["foo"]).get("foo") // => 1 * Lazy({ foo: 1, bar: 2 }).pick(["foo"]).get("bar") // => undefined * Lazy({ foo: 1, bar: 2 }).omit(["foo"]).get("bar") // => 2 * Lazy({ foo: 1, bar: 2 }).omit(["foo"]).get("foo") // => undefined */ ObjectLikeSequence.prototype.get = function get(key) { var pair = this.pairs().find(function(pair) { return pair[0] === key; }); return pair ? pair[1] : undefined; }; /** * Returns a {@link Sequence} whose elements are the keys of this object-like * sequence. * * @public * @returns {Sequence} The sequence based on this sequence's keys. * * @examples * Lazy({ hello: "hola", goodbye: "hasta luego" }).keys() // sequence: ["hello", "goodbye"] */ ObjectLikeSequence.prototype.keys = function keys() { return this.map(function(v, k) { return k; }); }; /** * Returns a {@link Sequence} whose elements are the values of this object-like * sequence. * * @public * @returns {Sequence} The sequence based on this sequence's values. * * @examples * Lazy({ hello: "hola", goodbye: "hasta luego" }).values() // sequence: ["hola", "hasta luego"] */ ObjectLikeSequence.prototype.values = function values() { return this.map(function(v, k) { return v; }); }; /** * Throws an exception. Asynchronous iteration over object-like sequences is * not supported. * * @public * @examples * Lazy({ foo: 'bar' }).async() // throws */ ObjectLikeSequence.prototype.async = function async() { throw new Error('An ObjectLikeSequence does not support asynchronous iteration.'); }; ObjectLikeSequence.prototype.filter = function filter(filterFn) { return new FilteredObjectLikeSequence(this, createCallback(filterFn)); }; function FilteredObjectLikeSequence(parent, filterFn) { this.parent = parent; this.filterFn = filterFn; } FilteredObjectLikeSequence.prototype = new ObjectLikeSequence(); FilteredObjectLikeSequence.prototype.each = function each(fn) { var filterFn = this.filterFn; return this.parent.each(function(v, k) { if (filterFn(v, k)) { return fn(v, k); } }); }; /** * Returns this same sequence. (Reversing an object-like sequence doesn't make * any sense.) */ ObjectLikeSequence.prototype.reverse = function reverse() { return this; }; /** * Returns an {@link ObjectLikeSequence} whose elements are the combination of * this sequence and another object. In the case of a key appearing in both this * sequence and the given object, the other object's value will override the * one in this sequence. * * @public * @aka extend * @param {Object} other The other object to assign to this sequence. * @returns {ObjectLikeSequence} A new sequence comprising elements from this * sequence plus the contents of `other`. * * @examples * Lazy({ "uno": 1, "dos": 2 }).assign({ "tres": 3 }) // sequence: { uno: 1, dos: 2, tres: 3 } * Lazy({ foo: "bar" }).assign({ foo: "baz" }); // sequence: { foo: "baz" } */ ObjectLikeSequence.prototype.assign = function assign(other) { return new AssignSequence(this, other); }; ObjectLikeSequence.prototype.extend = function extend(other) { return this.assign(other); }; /** * @constructor */ function AssignSequence(parent, other) { this.parent = parent; this.other = other; } AssignSequence.prototype = new ObjectLikeSequence(); AssignSequence.prototype.get = function get(key) { return this.other[key] || this.parent.get(key); }; AssignSequence.prototype.each = function each(fn) { var merged = new Set(), done = false; Lazy(this.other).each(function(value, key) { if (fn(value, key) === false) { done = true; return false; } merged.add(key); }); if (!done) { return this.parent.each(function(value, key) { if (!merged.contains(key) && fn(value, key) === false) { return false; } }); } }; /** * Returns an {@link ObjectLikeSequence} whose elements are the combination of * this sequence and a 'default' object. In the case of a key appearing in both * this sequence and the given object, this sequence's value will override the * default object's. * * @public * @param {Object} defaults The 'default' object to use for missing keys in this * sequence. * @returns {ObjectLikeSequence} A new sequence comprising elements from this * sequence supplemented by the contents of `defaults`. * * @examples * Lazy({ name: "Dan" }).defaults({ name: "User", password: "passw0rd" }) // sequence: { name: "Dan", password: "passw0rd" } */ ObjectLikeSequence.prototype.defaults = function defaults(defaults) { return new DefaultsSequence(this, defaults); }; /** * @constructor */ function DefaultsSequence(parent, defaults) { this.parent = parent; this.defaults = defaults; } DefaultsSequence.prototype = new ObjectLikeSequence(); DefaultsSequence.prototype.get = function get(key) { return this.parent.get(key) || this.defaults[key]; }; DefaultsSequence.prototype.each = function each(fn) { var merged = new Set(), done = false; this.parent.each(function(value, key) { if (fn(value, key) === false) { done = true; return false; } if (typeof value !== "undefined") { merged.add(key); } }); if (!done) { Lazy(this.defaults).each(function(value, key) { if (!merged.contains(key) && fn(value, key) === false) { return false; } }); } }; /** * Returns an {@link ObjectLikeSequence} whose values are this sequence's keys, * and whose keys are this sequence's values. * * @public * @returns {ObjectLikeSequence} A new sequence comprising the inverted keys and * values from this sequence. * * @examples * Lazy({ first: "Dan", last: "Tao" }).invert() // sequence: { Dan: "first", Tao: "last" } */ ObjectLikeSequence.prototype.invert = function invert() { return new InvertedSequence(this); }; /** * @constructor */ function InvertedSequence(parent) { this.parent = parent; } InvertedSequence.prototype = new ObjectLikeSequence(); InvertedSequence.prototype.each = function each(fn) { this.parent.each(function(value, key) { return fn(key, value); }); }; /** * Produces an {@link ObjectLikeSequence} consisting of all the recursively * merged values from this and the given object(s) or sequence(s). * * Note that by default this method only merges "vanilla" objects (bags of * key/value pairs), not arrays or any other custom object types. To customize * how merging works, you can provide the mergeFn argument, e.g. to handling * merging arrays, strings, or other types of objects. * * @public * @param {...Object|ObjectLikeSequence} others The other object(s) or * sequence(s) whose values will be merged into this one. * @param {Function=} mergeFn An optional function used to customize merging * behavior. The function should take two values as parameters and return * whatever the "merged" form of those values is. If the function returns * undefined then the new value will simply replace the old one in the * final result. * @returns {ObjectLikeSequence} The new sequence consisting of merged values. * * @examples * // These examples are completely stolen from Lo-Dash's documentation: * // lodash.com/docs#merge * * var names = { * 'characters': [ * { 'name': 'barney' }, * { 'name': 'fred' } * ] * }; * * var ages = { * 'characters': [ * { 'age': 36 }, * { 'age': 40 } * ] * }; * * var food = { * 'fruits': ['apple'], * 'vegetables': ['beet'] * }; * * var otherFood = { * 'fruits': ['banana'], * 'vegetables': ['carrot'] * }; * * function mergeArrays(a, b) { * return Array.isArray(a) ? a.concat(b) : undefined; * } * * Lazy(names).merge(ages); // => sequence: { 'characters': [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 }] } * Lazy(food).merge(otherFood, mergeArrays); // => sequence: { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] } * * // ----- Now for my own tests: ----- * * // merges objects * Lazy({ foo: 1 }).merge({ foo: 2 }); // => sequence: { foo: 2 } * Lazy({ foo: 1 }).merge({ bar: 2 }); // => sequence: { foo: 1, bar: 2 } * * // goes deep * Lazy({ foo: { bar: 1 } }).merge({ foo: { bar: 2 } }); // => sequence: { foo: { bar: 2 } } * Lazy({ foo: { bar: 1 } }).merge({ foo: { baz: 2 } }); // => sequence: { foo: { bar: 1, baz: 2 } } * Lazy({ foo: { bar: 1 } }).merge({ foo: { baz: 2 } }); // => sequence: { foo: { bar: 1, baz: 2 } } * * // gives precedence to later sources * Lazy({ foo: 1 }).merge({ bar: 2 }, { bar: 3 }); // => sequence: { foo: 1, bar: 3 } * * // undefined gets passed over * Lazy({ foo: 1 }).merge({ foo: undefined }); // => sequence: { foo: 1 } * * // null doesn't get passed over * Lazy({ foo: 1 }).merge({ foo: null }); // => sequence: { foo: null } * * // array contents get merged as well * Lazy({ foo: [{ bar: 1 }] }).merge({ foo: [{ baz: 2 }] }); // => sequence: { foo: [{ bar: 1, baz: 2}] } */ ObjectLikeSequence.prototype.merge = function merge(var_args) { var mergeFn = arguments.length > 1 && typeof arguments[arguments.length - 1] === "function" ? arrayPop.call(arguments) : null; return new MergedSequence(this, arraySlice.call(arguments, 0), mergeFn); }; /** * @constructor */ function MergedSequence(parent, others, mergeFn) { this.parent = parent; this.others = others; this.mergeFn = mergeFn; } MergedSequence.prototype = new ObjectLikeSequence(); MergedSequence.prototype.each = function each(fn) { var others = this.others, mergeFn = this.mergeFn || mergeObjects, keys = {}; var iteratedFullSource = this.parent.each(function(value, key) { var merged = value; forEach(others, function(other) { if (key in other) { merged = mergeFn(merged, other[key]); } }); keys[key] = true; return fn(merged, key); }); if (iteratedFullSource === false) { return false; } var remaining = {}; forEach(others, function(other) { for (var k in other) { if (!keys[k]) { remaining[k] = mergeFn(remaining[k], other[k]); } } }); return Lazy(remaining).each(fn); }; /** * @private * @examples * mergeObjects({ foo: 1 }, { bar: 2 }); // => { foo: 1, bar: 2 } * mergeObjects({ foo: { bar: 1 } }, { foo: { baz: 2 } }); // => { foo: { bar: 1, baz: 2 } } * mergeObjects({ foo: { bar: 1 } }, { foo: undefined }); // => { foo: { bar: 1 } } * mergeObjects({ foo: { bar: 1 } }, { foo: null }); // => { foo: null } * mergeObjects({ array: [0, 1, 2] }, { array: [3, 4, 5] }).array; // instanceof Array * mergeObjects({ date: new Date() }, { date: new Date() }).date; // instanceof Date * mergeObjects([{ foo: 1 }], [{ bar: 2 }]); // => [{ foo: 1, bar: 2 }] */ function mergeObjects(a, b) { var merged, prop; if (typeof b === 'undefined') { return a; } // Check that we're dealing with two objects or two arrays. if (isVanillaObject(a) && isVanillaObject(b)) { merged = {}; } else if (a instanceof Array && b instanceof Array) { merged = []; } else { // Otherwise there's no merging to do -- just replace a w/ b. return b; } for (prop in a) { merged[prop] = mergeObjects(a[prop], b[prop]); } for (prop in b) { if (!merged[prop]) { merged[prop] = b[prop]; } } return merged; } /** * Checks whether an object is a "vanilla" object, i.e. {'foo': 'bar'} as * opposed to an array, date, etc. * * @private * @examples * isVanillaObject({foo: 'bar'}); // => true * isVanillaObject(new Date()); // => false * isVanillaObject([1, 2, 3]); // => false */ function isVanillaObject(object) { return object && object.constructor === Object; } /** * Creates a {@link Sequence} consisting of the keys from this sequence whose * values are functions. * * @public * @aka methods * @returns {Sequence} The new sequence. * * @examples * var dog = { * name: "Fido", * breed: "Golden Retriever", * bark: function() { console.log("Woof!"); }, * wagTail: function() { console.log("TODO: implement robotic dog interface"); } * }; * * Lazy(dog).functions() // sequence: ["bark", "wagTail"] */ ObjectLikeSequence.prototype.functions = function functions() { return this .filter(function(v, k) { return typeof(v) === "function"; }) .map(function(v, k) { return k; }); }; ObjectLikeSequence.prototype.methods = function methods() { return this.functions(); }; /** * Creates an {@link ObjectLikeSequence} consisting of the key/value pairs from * this sequence whose keys are included in the given array of property names. * * @public * @param {Array} properties An array of the properties to "pick" from this * sequence. * @returns {ObjectLikeSequence} The new sequence. * * @examples * var players = { * "who": "first", * "what": "second", * "i don't know": "third" * }; * * Lazy(players).pick(["who", "what"]) // sequence: { who: "first", what: "second" } */ ObjectLikeSequence.prototype.pick = function pick(properties) { return new PickSequence(this, properties); }; /** * @constructor */ function PickSequence(parent, properties) { this.parent = parent; this.properties = properties; } PickSequence.prototype = new ObjectLikeSequence(); PickSequence.prototype.get = function get(key) { return arrayContains(this.properties, key) ? this.parent.get(key) : undefined; }; PickSequence.prototype.each = function each(fn) { var inArray = arrayContains, properties = this.properties; return this.parent.each(function(value, key) { if (inArray(properties, key)) { return fn(value, key); } }); }; /** * Creates an {@link ObjectLikeSequence} consisting of the key/value pairs from * this sequence excluding those with the specified keys. * * @public * @param {Array} properties An array of the properties to *omit* from this * sequence. * @returns {ObjectLikeSequence} The new sequence. * * @examples * var players = { * "who": "first", * "what": "second", * "i don't know": "third" * }; * * Lazy(players).omit(["who", "what"]) // sequence: { "i don't know": "third" } */ ObjectLikeSequence.prototype.omit = function omit(properties) { return new OmitSequence(this, properties); }; /** * @constructor */ function OmitSequence(parent, properties) { this.parent = parent; this.properties = properties; } OmitSequence.prototype = new ObjectLikeSequence(); OmitSequence.prototype.get = function get(key) { return arrayContains(this.properties, key) ? undefined : this.parent.get(key); }; OmitSequence.prototype.each = function each(fn) { var inArray = arrayContains, properties = this.properties; return this.parent.each(function(value, key) { if (!inArray(properties, key)) { return fn(value, key); } }); }; /** * Maps the key/value pairs in this sequence to arrays. * * @public * @aka toArray * @returns {Sequence} An sequence of `[key, value]` pairs. * * @examples * var colorCodes = { * red: "#f00", * green: "#0f0", * blue: "#00f" * }; * * Lazy(colorCodes).pairs() // sequence: [["red", "#f00"], ["green", "#0f0"], ["blue", "#00f"]] */ ObjectLikeSequence.prototype.pairs = function pairs() { return this.map(function(v, k) { return [k, v]; }); }; /** * Creates an array from the key/value pairs in this sequence. * * @public * @returns {Array} An array of `[key, value]` elements. * * @examples * var colorCodes = { * red: "#f00", * green: "#0f0", * blue: "#00f" * }; * * Lazy(colorCodes).toArray() // => [["red", "#f00"], ["green", "#0f0"], ["blue", "#00f"]] */ ObjectLikeSequence.prototype.toArray = function toArray() { return this.pairs().toArray(); }; /** * Creates an object with the key/value pairs from this sequence. * * @public * @returns {Object} An object with the same key/value pairs as this sequence. * * @examples * var colorCodes = { * red: "#f00", * green: "#0f0", * blue: "#00f" * }; * * Lazy(colorCodes).toObject() // => { red: "#f00", green: "#0f0", blue: "#00f" } */ ObjectLikeSequence.prototype.toObject = function toObject() { return this.reduce(function(object, value, key) { object[key] = value; return object; }, {}); }; // Now that we've fully initialized the ObjectLikeSequence prototype, we can // actually set the prototypes for GroupedSequence, IndexedSequence, and // CountedSequence. GroupedSequence.prototype = new ObjectLikeSequence(); GroupedSequence.prototype.each = function each(fn) { var keyFn = createCallback(this.keyFn), valFn = createCallback(this.valFn), result; result = this.parent.reduce(function(grouped,e) { var key = keyFn(e), val = valFn(e); if (!(grouped[key] instanceof Array)) { grouped[key] = [val]; } else { grouped[key].push(val); } return grouped; },{}); return transform(function(grouped) { for (var key in grouped) { if (fn(grouped[key], key) === false) { return false; } } }, result); }; IndexedSequence.prototype = new ObjectLikeSequence(); IndexedSequence.prototype.each = function each(fn) { var keyFn = createCallback(this.keyFn), valFn = createCallback(this.valFn), indexed = {}; return this.parent.each(function(e) { var key = keyFn(e), val = valFn(e); if (!indexed[key]) { indexed[key] = val; return fn(val, key); } }); }; CountedSequence.prototype = new ObjectLikeSequence(); CountedSequence.prototype.each = function each(fn) { var keyFn = createCallback(this.keyFn), counted = {}; this.parent.each(function(e) { var key = keyFn(e); if (!counted[key]) { counted[key] = 1; } else { counted[key] += 1; } }); for (var key in counted) { if (fn(counted[key], key) === false) { return false; } } return true; }; /** * Watches for all changes to a specified property (or properties) of an * object and produces a sequence whose elements have the properties * `{ property, value }` indicating which property changed and what it was * changed to. * * Note that this method **only works on directly wrapped objects**; it will * *not* work on any arbitrary {@link ObjectLikeSequence}. * * @public * @param {(string|Array)=} propertyNames A property name or array of property * names to watch. If this parameter is `undefined`, all of the object's * current (enumerable) properties will be watched. * @returns {Sequence} A sequence comprising `{ property, value }` objects * describing each change to the specified property/properties. * * @examples * var obj = {}, * changes = []; * * Lazy(obj).watch('foo').each(function(change) { * changes.push(change); * }); * * obj.foo = 1; * obj.bar = 2; * obj.foo = 3; * * obj.foo; // => 3 * changes; // => [{ property: 'foo', value: 1 }, { property: 'foo', value: 3 }] */ ObjectLikeSequence.prototype.watch = function watch(propertyNames) { throw new Error('You can only call #watch on a directly wrapped object.'); }; /** * @constructor */ function ObjectWrapper(source) { this.source = source; } ObjectWrapper.prototype = new ObjectLikeSequence(); ObjectWrapper.prototype.root = function root() { return this; }; ObjectWrapper.prototype.isAsync = function isAsync() { return false; }; ObjectWrapper.prototype.get = function get(key) { return this.source[key]; }; ObjectWrapper.prototype.each = function each(fn) { var source = this.source, key; for (key in source) { if (fn(source[key], key) === false) { return false; } } return true; }; /** * A `StringLikeSequence` represents a sequence of characters. * * The initial sequence you get by wrapping a string with `Lazy(string)` is a * `StringLikeSequence`. * * All methods of `StringLikeSequence` that conceptually should return * something like a string return another `StringLikeSequence`. * * @public * @constructor * * @examples * function upcase(str) { return str.toUpperCase(); } * * Lazy('foo') // instanceof Lazy.StringLikeSequence * Lazy('foo').toUpperCase() // instanceof Lazy.StringLikeSequence * Lazy('foo').reverse() // instanceof Lazy.StringLikeSequence * Lazy('foo').take(2) // instanceof Lazy.StringLikeSequence * Lazy('foo').drop(1) // instanceof Lazy.StringLikeSequence * Lazy('foo').substring(1) // instanceof Lazy.StringLikeSequence * * // Note that `map` does not create a `StringLikeSequence` because there's * // no guarantee the mapping function will return characters. In the event * // you do want to map a string onto a string-like sequence, use * // `mapString`: * Lazy('foo').map(Lazy.identity) // instanceof Lazy.ArrayLikeSequence * Lazy('foo').mapString(Lazy.identity) // instanceof Lazy.StringLikeSequence */ function StringLikeSequence() {} StringLikeSequence.prototype = new ArrayLikeSequence(); /** * Create a new constructor function for a type inheriting from * `StringLikeSequence`. * * @public * @param {string|Array.} methodName The name(s) of the method(s) to be * used for constructing the new sequence. The method will be attached to * the `StringLikeSequence` prototype so that it can be chained with any other * methods that return string-like sequences. * @param {Object} overrides An object containing function overrides for this * new sequence type. Has the same requirements as * {@link ArrayLikeSequence.define}. * @returns {Function} A constructor for a new type inheriting from * `StringLikeSequence`. * * @examples * Lazy.StringLikeSequence.define("zomg", { * length: function() { * return this.parent.length() + "!!ZOMG!!!1".length; * }, * * get: function(i) { * if (i < this.parent.length()) { * return this.parent.get(i); * } * return "!!ZOMG!!!1".charAt(i - this.parent.length()); * } * }); * * Lazy('foo').zomg() // sequence: "foo!!ZOMG!!!1" */ StringLikeSequence.define = function define(methodName, overrides) { if (!overrides || typeof overrides.get !== 'function') { throw new Error("A custom string-like sequence must implement *at least* get!"); } return defineSequenceType(StringLikeSequence, methodName, overrides); }; StringLikeSequence.prototype.value = function value() { return this.toString(); }; /** * Returns an {@link IndexedIterator} that will step over each character in this * sequence one by one. * * @returns {IndexedIterator} The iterator. */ StringLikeSequence.prototype.getIterator = function getIterator() { return new CharIterator(this); }; /** * @constructor */ function CharIterator(source) { this.source = Lazy(source); this.index = -1; } CharIterator.prototype.current = function current() { return this.source.charAt(this.index); }; CharIterator.prototype.moveNext = function moveNext() { return (++this.index < this.source.length()); }; /** * Returns the character at the given index of this sequence, or the empty * string if the specified index lies outside the bounds of the sequence. * * @public * @param {number} i The index of this sequence. * @returns {string} The character at the specified index. * * @examples * Lazy("foo").charAt(0) // => "f" * Lazy("foo").charAt(-1) // => "" * Lazy("foo").charAt(10) // => "" */ StringLikeSequence.prototype.charAt = function charAt(i) { return this.get(i); }; /** * Returns the character code at the given index of this sequence, or `NaN` if * the index lies outside the bounds of the sequence. * * @public * @param {number} i The index of the character whose character code you want. * @returns {number} The character code. * * @examples * Lazy("abc").charCodeAt(0) // => 97 * Lazy("abc").charCodeAt(-1) // => NaN * Lazy("abc").charCodeAt(10) // => NaN */ StringLikeSequence.prototype.charCodeAt = function charCodeAt(i) { var char = this.charAt(i); if (!char) { return NaN; } return char.charCodeAt(0); }; /** * Returns a {@link StringLikeSequence} comprising the characters from *this* * sequence starting at `start` and ending at `stop` (exclusive), or---if * `stop` is `undefined`, including the rest of the sequence. * * @public * @param {number} start The index where this sequence should begin. * @param {number=} stop The index (exclusive) where this sequence should end. * @returns {StringLikeSequence} The new sequence. * * @examples * Lazy("foo").substring(1) // sequence: "oo" * Lazy("foo").substring(-1) // sequence: "foo" * Lazy("hello").substring(1, 3) // sequence: "el" * Lazy("hello").substring(1, 9) // sequence: "ello" */ StringLikeSequence.prototype.substring = function substring(start, stop) { return new StringSegment(this, start, stop); }; /** * @constructor */ function StringSegment(parent, start, stop) { this.parent = parent; this.start = Math.max(0, start); this.stop = stop; } StringSegment.prototype = new StringLikeSequence(); StringSegment.prototype.get = function get(i) { return this.parent.get(i + this.start); }; StringSegment.prototype.length = function length() { return (typeof this.stop === "number" ? this.stop : this.parent.length()) - this.start; }; /** * An optimized version of {@link Sequence#first} that returns another * {@link StringLikeSequence} (or just the first character, if `count` is * undefined). * * @public * @examples * Lazy('foo').first() // => 'f' * Lazy('fo').first(2) // sequence: 'fo' * Lazy('foo').first(10) // sequence: 'foo' * Lazy('foo').toUpperCase().first() // => 'F' * Lazy('foo').toUpperCase().first(2) // sequence: 'FO' */ StringLikeSequence.prototype.first = function first(count) { if (typeof count === "undefined") { return this.charAt(0); } return this.substring(0, count); }; /** * An optimized version of {@link Sequence#last} that returns another * {@link StringLikeSequence} (or just the last character, if `count` is * undefined). * * @public * @examples * Lazy('foo').last() // => 'o' * Lazy('foo').last(2) // sequence: 'oo' * Lazy('foo').last(10) // sequence: 'foo' * Lazy('foo').toUpperCase().last() // => 'O' * Lazy('foo').toUpperCase().last(2) // sequence: 'OO' */ StringLikeSequence.prototype.last = function last(count) { if (typeof count === "undefined") { return this.charAt(this.length() - 1); } return this.substring(this.length() - count); }; StringLikeSequence.prototype.drop = function drop(count) { return this.substring(count); }; /** * Finds the index of the first occurrence of the given substring within this * sequence, starting from the specified index (or the beginning of the * sequence). * * @public * @param {string} substring The substring to search for. * @param {number=} startIndex The index from which to start the search. * @returns {number} The first index where the given substring is found, or * -1 if it isn't in the sequence. * * @examples * Lazy('canal').indexOf('a') // => 1 * Lazy('canal').indexOf('a', 2) // => 3 * Lazy('canal').indexOf('ana') // => 1 * Lazy('canal').indexOf('andy') // => -1 * Lazy('canal').indexOf('x') // => -1 */ StringLikeSequence.prototype.indexOf = function indexOf(substring, startIndex) { return this.toString().indexOf(substring, startIndex); }; /** * Finds the index of the last occurrence of the given substring within this * sequence, starting from the specified index (or the end of the sequence) * and working backwards. * * @public * @param {string} substring The substring to search for. * @param {number=} startIndex The index from which to start the search. * @returns {number} The last index where the given substring is found, or * -1 if it isn't in the sequence. * * @examples * Lazy('canal').lastIndexOf('a') // => 3 * Lazy('canal').lastIndexOf('a', 2) // => 1 * Lazy('canal').lastIndexOf('ana') // => 1 * Lazy('canal').lastIndexOf('andy') // => -1 * Lazy('canal').lastIndexOf('x') // => -1 */ StringLikeSequence.prototype.lastIndexOf = function lastIndexOf(substring, startIndex) { return this.toString().lastIndexOf(substring, startIndex); }; /** * Checks if this sequence contains a given substring. * * @public * @param {string} substring The substring to check for. * @returns {boolean} Whether or not this sequence contains `substring`. * * @examples * Lazy('hello').contains('ell') // => true * Lazy('hello').contains('') // => true * Lazy('hello').contains('abc') // => false */ StringLikeSequence.prototype.contains = function contains(substring) { return this.indexOf(substring) !== -1; }; /** * Checks if this sequence ends with a given suffix. * * @public * @param {string} suffix The suffix to check for. * @returns {boolean} Whether or not this sequence ends with `suffix`. * * @examples * Lazy('foo').endsWith('oo') // => true * Lazy('foo').endsWith('') // => true * Lazy('foo').endsWith('abc') // => false */ StringLikeSequence.prototype.endsWith = function endsWith(suffix) { return this.substring(this.length() - suffix.length).toString() === suffix; }; /** * Checks if this sequence starts with a given prefix. * * @public * @param {string} prefix The prefix to check for. * @returns {boolean} Whether or not this sequence starts with `prefix`. * * @examples * Lazy('foo').startsWith('fo') // => true * Lazy('foo').startsWith('') // => true * Lazy('foo').startsWith('abc') // => false */ StringLikeSequence.prototype.startsWith = function startsWith(prefix) { return this.substring(0, prefix.length).toString() === prefix; }; /** * Converts all of the characters in this string to uppercase. * * @public * @returns {StringLikeSequence} A new sequence with the same characters as * this sequence, all uppercase. * * @examples * function nextLetter(a) { * return String.fromCharCode(a.charCodeAt(0) + 1); * } * * Lazy('foo').toUpperCase() // sequence: 'FOO' * Lazy('foo').substring(1).toUpperCase() // sequence: 'OO' * Lazy('abc').mapString(nextLetter).toUpperCase() // sequence: 'BCD' */ StringLikeSequence.prototype.toUpperCase = function toUpperCase() { return this.mapString(function(char) { return char.toUpperCase(); }); }; /** * Converts all of the characters in this string to lowercase. * * @public * @returns {StringLikeSequence} A new sequence with the same characters as * this sequence, all lowercase. * * @examples * function nextLetter(a) { * return String.fromCharCode(a.charCodeAt(0) + 1); * } * * Lazy('FOO').toLowerCase() // sequence: 'foo' * Lazy('FOO').substring(1).toLowerCase() // sequence: 'oo' * Lazy('ABC').mapString(nextLetter).toLowerCase() // sequence: 'bcd' */ StringLikeSequence.prototype.toLowerCase = function toLowerCase() { return this.mapString(function(char) { return char.toLowerCase(); }); }; /** * Maps the characters of this sequence onto a new {@link StringLikeSequence}. * * @public * @param {Function} mapFn The function used to map characters from this * sequence onto the new sequence. * @returns {StringLikeSequence} The new sequence. * * @examples * function upcase(char) { return char.toUpperCase(); } * * Lazy("foo").mapString(upcase) // sequence: "FOO" * Lazy("foo").mapString(upcase).charAt(0) // => "F" * Lazy("foo").mapString(upcase).charCodeAt(0) // => 70 * Lazy("foo").mapString(upcase).substring(1) // sequence: "OO" */ StringLikeSequence.prototype.mapString = function mapString(mapFn) { return new MappedStringLikeSequence(this, mapFn); }; /** * @constructor */ function MappedStringLikeSequence(parent, mapFn) { this.parent = parent; this.mapFn = mapFn; } MappedStringLikeSequence.prototype = new StringLikeSequence(); MappedStringLikeSequence.prototype.get = IndexedMappedSequence.prototype.get; MappedStringLikeSequence.prototype.length = IndexedMappedSequence.prototype.length; /** * Returns a copy of this sequence that reads back to front. * * @public * * @examples * Lazy("abcdefg").reverse() // sequence: "gfedcba" */ StringLikeSequence.prototype.reverse = function reverse() { return new ReversedStringLikeSequence(this); }; /** * @constructor */ function ReversedStringLikeSequence(parent) { this.parent = parent; } ReversedStringLikeSequence.prototype = new StringLikeSequence(); ReversedStringLikeSequence.prototype.get = IndexedReversedSequence.prototype.get; ReversedStringLikeSequence.prototype.length = IndexedReversedSequence.prototype.length; StringLikeSequence.prototype.toString = function toString() { return this.join(""); }; /** * Creates a {@link Sequence} comprising all of the matches for the specified * pattern in the underlying string. * * @public * @param {RegExp} pattern The pattern to match. * @returns {Sequence} A sequence of all the matches. * * @examples * Lazy("abracadabra").match(/a[bcd]/) // sequence: ["ab", "ac", "ad", "ab"] * Lazy("fee fi fo fum").match(/\w+/) // sequence: ["fee", "fi", "fo", "fum"] * Lazy("hello").match(/xyz/) // sequence: [] */ StringLikeSequence.prototype.match = function match(pattern) { return new StringMatchSequence(this, pattern); }; /** * @constructor */ function StringMatchSequence(parent, pattern) { this.parent = parent; this.pattern = pattern; } StringMatchSequence.prototype = new Sequence(); StringMatchSequence.prototype.getIterator = function getIterator() { return new StringMatchIterator(this.parent.toString(), this.pattern); }; /** * @constructor */ function StringMatchIterator(source, pattern) { this.source = source; this.pattern = cloneRegex(pattern); } StringMatchIterator.prototype.current = function current() { return this.match[0]; }; StringMatchIterator.prototype.moveNext = function moveNext() { return !!(this.match = this.pattern.exec(this.source)); }; /** * Creates a {@link Sequence} comprising all of the substrings of this string * separated by the given delimiter, which can be either a string or a regular * expression. * * @public * @param {string|RegExp} delimiter The delimiter to use for recognizing * substrings. * @returns {Sequence} A sequence of all the substrings separated by the given * delimiter. * * @examples * Lazy("foo").split("") // sequence: ["f", "o", "o"] * Lazy("yo dawg").split(" ") // sequence: ["yo", "dawg"] * Lazy("bah bah\tblack sheep").split(/\s+/) // sequence: ["bah", "bah", "black", "sheep"] */ StringLikeSequence.prototype.split = function split(delimiter) { return new SplitStringSequence(this, delimiter); }; /** * @constructor */ function SplitStringSequence(parent, pattern) { this.parent = parent; this.pattern = pattern; } SplitStringSequence.prototype = new Sequence(); SplitStringSequence.prototype.getIterator = function getIterator() { var source = this.parent.toString(); if (this.pattern instanceof RegExp) { if (this.pattern.source === "" || this.pattern.source === "(?:)") { return new CharIterator(source); } else { return new SplitWithRegExpIterator(source, this.pattern); } } else if (this.pattern === "") { return new CharIterator(source); } else { return new SplitWithStringIterator(source, this.pattern); } }; /** * @constructor */ function SplitWithRegExpIterator(source, pattern) { this.source = source; this.pattern = cloneRegex(pattern); } SplitWithRegExpIterator.prototype.current = function current() { return this.source.substring(this.start, this.end); }; SplitWithRegExpIterator.prototype.moveNext = function moveNext() { if (!this.pattern) { return false; } var match = this.pattern.exec(this.source); if (match) { this.start = this.nextStart ? this.nextStart : 0; this.end = match.index; this.nextStart = match.index + match[0].length; return true; } else if (this.pattern) { this.start = this.nextStart; this.end = undefined; this.nextStart = undefined; this.pattern = undefined; return true; } return false; }; /** * @constructor */ function SplitWithStringIterator(source, delimiter) { this.source = source; this.delimiter = delimiter; } SplitWithStringIterator.prototype.current = function current() { return this.source.substring(this.leftIndex, this.rightIndex); }; SplitWithStringIterator.prototype.moveNext = function moveNext() { if (!this.finished) { this.leftIndex = typeof this.leftIndex !== "undefined" ? this.rightIndex + this.delimiter.length : 0; this.rightIndex = this.source.indexOf(this.delimiter, this.leftIndex); } if (this.rightIndex === -1) { this.finished = true; this.rightIndex = undefined; return true; } return !this.finished; }; /** * Wraps a string exposing {@link #match} and {@link #split} methods that return * {@link Sequence} objects instead of arrays, improving on the efficiency of * JavaScript's built-in `String#split` and `String.match` methods and * supporting asynchronous iteration. * * @param {string} source The string to wrap. * @constructor */ function StringWrapper(source) { this.source = source; } StringWrapper.prototype = new StringLikeSequence(); StringWrapper.prototype.root = function root() { return this; }; StringWrapper.prototype.isAsync = function isAsync() { return false; }; StringWrapper.prototype.get = function get(i) { return this.source.charAt(i); }; StringWrapper.prototype.length = function length() { return this.source.length; }; StringWrapper.prototype.toString = function toString() { return this.source; }; /** * A `GeneratedSequence` does not wrap an in-memory colllection but rather * determines its elements on-the-fly during iteration according to a generator * function. * * You create a `GeneratedSequence` by calling {@link Lazy.generate}. * * @public * @constructor * @param {function(number):*} generatorFn A function which accepts an index * and returns a value for the element at that position in the sequence. * @param {number=} length The length of the sequence. If this argument is * omitted, the sequence will go on forever. */ function GeneratedSequence(generatorFn, length) { this.get = generatorFn; this.fixedLength = length; } GeneratedSequence.prototype = new Sequence(); GeneratedSequence.prototype.isAsync = function isAsync() { return false; }; /** * Returns the length of this sequence. * * @public * @returns {number} The length, or `undefined` if this is an indefinite * sequence. */ GeneratedSequence.prototype.length = function length() { return this.fixedLength; }; /** * Iterates over the sequence produced by invoking this sequence's generator * function up to its specified length, or, if length is `undefined`, * indefinitely (in which case the sequence will go on forever--you would need * to call, e.g., {@link Sequence#take} to limit iteration). * * @public * @param {Function} fn The function to call on each output from the generator * function. */ GeneratedSequence.prototype.each = function each(fn) { var generatorFn = this.get, length = this.fixedLength, i = 0; while (typeof length === "undefined" || i < length) { if (fn(generatorFn(i), i++) === false) { return false; } } return true; }; GeneratedSequence.prototype.getIterator = function getIterator() { return new GeneratedIterator(this); }; /** * Iterates over a generated sequence. (This allows generated sequences to be * iterated asynchronously.) * * @param {GeneratedSequence} sequence The generated sequence to iterate over. * @constructor */ function GeneratedIterator(sequence) { this.sequence = sequence; this.index = 0; this.currentValue = null; } GeneratedIterator.prototype.current = function current() { return this.currentValue; }; GeneratedIterator.prototype.moveNext = function moveNext() { var sequence = this.sequence; if (typeof sequence.fixedLength === "number" && this.index >= sequence.fixedLength) { return false; } this.currentValue = sequence.get(this.index++); return true; }; /** * An `AsyncSequence` iterates over its elements asynchronously when * {@link #each} is called. * * You get an `AsyncSequence` by calling {@link Sequence#async} on any * sequence. Note that some sequence types may not support asynchronous * iteration. * * Returning values * ---------------- * * Because of its asynchronous nature, an `AsyncSequence` cannot be used in the * same way as other sequences for functions that return values directly (e.g., * `reduce`, `max`, `any`, even `toArray`). * * Instead, these methods return an `AsyncHandle` whose `onComplete` method * accepts a callback that will be called with the final result once iteration * has finished. * * Defining custom asynchronous sequences * -------------------------------------- * * There are plenty of ways to define an asynchronous sequence. Here's one. * * 1. First, implement an {@link Iterator}. This is an object whose prototype * has the methods {@link Iterator#moveNext} (which returns a `boolean`) and * {@link current} (which returns the current value). * 2. Next, create a simple wrapper that inherits from `AsyncSequence`, whose * `getIterator` function returns an instance of the iterator type you just * defined. * * The default implementation for {@link #each} on an `AsyncSequence` is to * create an iterator and then asynchronously call {@link Iterator#moveNext} * (using `setImmediate`, if available, otherwise `setTimeout`) until the iterator * can't move ahead any more. * * @public * @constructor * @param {Sequence} parent A {@link Sequence} to wrap, to expose asynchronous * iteration. * @param {number=} interval How many milliseconds should elapse between each * element when iterating over this sequence. If this argument is omitted, * asynchronous iteration will be executed as fast as possible. */ function AsyncSequence(parent, interval) { if (parent instanceof AsyncSequence) { throw new Error("Sequence is already asynchronous!"); } this.parent = parent; this.interval = interval; this.onNextCallback = getOnNextCallback(interval); this.cancelCallback = getCancelCallback(interval); } AsyncSequence.prototype = new Sequence(); AsyncSequence.prototype.isAsync = function isAsync() { return true; }; /** * Throws an exception. You cannot manually iterate over an asynchronous * sequence. * * @public * @example * Lazy([1, 2, 3]).async().getIterator() // throws */ AsyncSequence.prototype.getIterator = function getIterator() { throw new Error('An AsyncSequence does not support synchronous iteration.'); }; /** * An asynchronous version of {@link Sequence#each}. * * @public * @param {Function} fn The function to invoke asynchronously on each element in * the sequence one by one. * @returns {AsyncHandle} An {@link AsyncHandle} providing the ability to * cancel the asynchronous iteration (by calling `cancel()`) as well as * supply callback(s) for when an error is encountered (`onError`) or when * iteration is complete (`onComplete`). */ AsyncSequence.prototype.each = function each(fn) { var iterator = this.parent.getIterator(), onNextCallback = this.onNextCallback, cancelCallback = this.cancelCallback, i = 0; var handle = new AsyncHandle(function cancel() { if (cancellationId) { cancelCallback(cancellationId); } }); var cancellationId = onNextCallback(function iterate() { cancellationId = null; try { if (iterator.moveNext() && fn(iterator.current(), i++) !== false) { cancellationId = onNextCallback(iterate); } else { handle._resolve(); } } catch (e) { handle._reject(e); } }); return handle; }; /** * An `AsyncHandle` provides a [Promises/A+](http://promises-aplus.github.io/promises-spec/) * compliant interface for an {@link AsyncSequence} that is currently (or was) * iterating over its elements. * * In addition to behaving as a promise, an `AsyncHandle` provides the ability * to {@link AsyncHandle#cancel} iteration (if `cancelFn` is provided) * and also offers convenient {@link AsyncHandle#onComplete} and * {@link AsyncHandle#onError} methods to attach listeners for when iteration * is complete or an error is thrown during iteration. * * @public * @param {Function} cancelFn A function to cancel asynchronous iteration. * This is passed in to support different cancellation mechanisms for * different forms of asynchronous sequences (e.g., timeout-based * sequences, sequences based on I/O, etc.). * @constructor * * @example * // Create a sequence of 100,000 random numbers, in chunks of 100. * var sequence = Lazy.generate(Math.random) * .chunk(100) * .async() * .take(1000); * * // Reduce-style operations -- i.e., operations that return a *value* (as * // opposed to a *sequence*) -- return an AsyncHandle for async sequences. * var handle = sequence.toArray(); * * handle.onComplete(function(array) { * // Do something w/ 1,000-element array. * }); * * // Since an AsyncHandle is a promise, you can also use it to create * // subsequent promises using `then` (see the Promises/A+ spec for more * // info). * var flattened = handle.then(function(array) { * return Lazy(array).flatten(); * }); */ function AsyncHandle(cancelFn) { this.resolveListeners = []; this.rejectListeners = []; this.state = PENDING; this.cancelFn = cancelFn; } // Async handle states var PENDING = 1, RESOLVED = 2, REJECTED = 3; AsyncHandle.prototype.then = function then(onFulfilled, onRejected) { var promise = new AsyncHandle(this.cancelFn); this.resolveListeners.push(function(value) { try { if (typeof onFulfilled !== 'function') { resolve(promise, value); return; } resolve(promise, onFulfilled(value)); } catch (e) { promise._reject(e); } }); this.rejectListeners.push(function(reason) { try { if (typeof onRejected !== 'function') { promise._reject(reason); return; } resolve(promise, onRejected(reason)); } catch (e) { promise._reject(e); } }); if (this.state === RESOLVED) { this._resolve(this.value); } if (this.state === REJECTED) { this._reject(this.reason); } return promise; }; AsyncHandle.prototype._resolve = function _resolve(value) { if (this.state === REJECTED) { return; } if (this.state === PENDING) { this.state = RESOLVED; this.value = value; } consumeListeners(this.resolveListeners, this.value); }; AsyncHandle.prototype._reject = function _reject(reason) { if (this.state === RESOLVED) { return; } if (this.state === PENDING) { this.state = REJECTED; this.reason = reason; } consumeListeners(this.rejectListeners, this.reason); }; /** * Cancels asynchronous iteration. * * @public */ AsyncHandle.prototype.cancel = function cancel() { if (this.cancelFn) { this.cancelFn(); this.cancelFn = null; this._resolve(false); } }; /** * Updates the handle with a callback to execute when iteration is completed. * * @public * @param {Function} callback The function to call when the asynchronous * iteration is completed. * @return {AsyncHandle} A reference to the handle (for chaining). */ AsyncHandle.prototype.onComplete = function onComplete(callback) { this.resolveListeners.push(callback); return this; }; /** * Updates the handle with a callback to execute if/when any error is * encountered during asynchronous iteration. * * @public * @param {Function} callback The function to call, with any associated error * object, when an error occurs. * @return {AsyncHandle} A reference to the handle (for chaining). */ AsyncHandle.prototype.onError = function onError(callback) { this.rejectListeners.push(callback); return this; }; /** * Promise resolution procedure: * http://promises-aplus.github.io/promises-spec/#the_promise_resolution_procedure */ function resolve(promise, x) { if (promise === x) { promise._reject(new TypeError('Cannot resolve a promise to itself')); return; } if (x instanceof AsyncHandle) { x.then( function(value) { resolve(promise, value); }, function(reason) { promise._reject(reason); } ); return; } var then; try { then = (/function|object/).test(typeof x) && x != null && x.then; } catch (e) { promise._reject(e); return; } var thenableState = PENDING; if (typeof then === 'function') { try { then.call( x, function resolvePromise(value) { if (thenableState !== PENDING) { return; } thenableState = RESOLVED; resolve(promise, value); }, function rejectPromise(reason) { if (thenableState !== PENDING) { return; } thenableState = REJECTED; promise._reject(reason); } ); } catch (e) { if (thenableState !== PENDING) { return; } promise._reject(e); } return; } promise._resolve(x); } function consumeListeners(listeners, value, callback) { callback || (callback = getOnNextCallback()); callback(function() { if (listeners.length > 0) { listeners.shift()(value); consumeListeners(listeners, value, callback); } }); } function getOnNextCallback(interval) { if (typeof interval === "undefined") { if (typeof setImmediate === "function") { return setImmediate; } } interval = interval || 0; return function(fn) { return setTimeout(fn, interval); }; } function getCancelCallback(interval) { if (typeof interval === "undefined") { if (typeof clearImmediate === "function") { return clearImmediate; } } return clearTimeout; } /** * Transform a value, whether the value is retrieved asynchronously or directly. * * @private * @param {Function} fn The function that transforms the value. * @param {*} value The value to be transformed. This can be an {@link AsyncHandle} when the value * is retrieved asynchronously, otherwise it can be anything. * @returns {*} An {@link AsyncHandle} when `value` is also an {@link AsyncHandle}, otherwise * whatever `fn` resulted in. */ function transform(fn, value) { if (value instanceof AsyncHandle) { return value.then(function() { fn(value); }); } return fn(value); } /** * An async version of {@link Sequence#reverse}. */ AsyncSequence.prototype.reverse = function reverse() { return this.parent.reverse().async(); }; /** * A version of {@link Sequence#find} which returns an {@link AsyncHandle}. * * @public * @param {Function} predicate A function to call on (potentially) every element * in the sequence. * @returns {AsyncHandle} An {@link AsyncHandle} (promise) which resolves to * the found element, once it is detected, or else `undefined`. */ AsyncSequence.prototype.find = function find(predicate) { var found; var handle = this.each(function(e, i) { if (predicate(e, i)) { found = e; return false; } }); return handle.then(function() { return found; }); }; /** * A version of {@link Sequence#indexOf} which returns an {@link AsyncHandle}. * * @public * @param {*} value The element to search for in the sequence. * @returns {AsyncHandle} An {@link AsyncHandle} (promise) which resolves to * the found index, once it is detected, or -1. */ AsyncSequence.prototype.indexOf = function indexOf(value) { var foundIndex = -1; var handle = this.each(function(e, i) { if (e === value) { foundIndex = i; return false; } }); return handle.then(function() { return foundIndex; }); }; /** * A version of {@link Sequence#contains} which returns an {@link AsyncHandle}. * * @public * @param {*} value The element to search for in the sequence. * @returns {AsyncHandle} An {@link AsyncHandle} (promise) which resolves to * either `true` or `false` to indicate whether the element was found. */ AsyncSequence.prototype.contains = function contains(value) { var found = false; var handle = this.each(function(e) { if (e === value) { found = true; return false; } }); return handle.then(function() { return found; }); }; /** * Just return the same sequence for `AsyncSequence#async` (I see no harm in this). */ AsyncSequence.prototype.async = function async() { return this; }; /** * See {@link ObjectLikeSequence#watch} for docs. */ ObjectWrapper.prototype.watch = function watch(propertyNames) { return new WatchedPropertySequence(this.source, propertyNames); }; function WatchedPropertySequence(object, propertyNames) { this.listeners = []; if (!propertyNames) { propertyNames = Lazy(object).keys().toArray(); } else if (!(propertyNames instanceof Array)) { propertyNames = [propertyNames]; } var listeners = this.listeners, index = 0; Lazy(propertyNames).each(function(propertyName) { var propertyValue = object[propertyName]; Object.defineProperty(object, propertyName, { get: function() { return propertyValue; }, set: function(value) { for (var i = listeners.length - 1; i >= 0; --i) { if (listeners[i]({ property: propertyName, value: value }, index) === false) { listeners.splice(i, 1); } } propertyValue = value; ++index; } }); }); } WatchedPropertySequence.prototype = new AsyncSequence(); WatchedPropertySequence.prototype.each = function each(fn) { this.listeners.push(fn); }; /** * A StreamLikeSequence comprises a sequence of 'chunks' of data, which are * typically multiline strings. * * @constructor */ function StreamLikeSequence() {} StreamLikeSequence.prototype = new AsyncSequence(); StreamLikeSequence.prototype.isAsync = function isAsync() { return true; }; StreamLikeSequence.prototype.split = function split(delimiter) { return new SplitStreamSequence(this, delimiter); }; /** * @constructor */ function SplitStreamSequence(parent, delimiter) { this.parent = parent; this.delimiter = delimiter; this.each = this.getEachForDelimiter(delimiter); } SplitStreamSequence.prototype = new Sequence(); SplitStreamSequence.prototype.getEachForDelimiter = function getEachForDelimiter(delimiter) { if (delimiter instanceof RegExp) { return this.regexEach; } return this.stringEach; }; SplitStreamSequence.prototype.regexEach = function each(fn) { var delimiter = cloneRegex(this.delimiter), buffer = '', start = 0, end, index = 0; var handle = this.parent.each(function(chunk) { buffer += chunk; var match; while (match = delimiter.exec(buffer)) { end = match.index; if (fn(buffer.substring(start, end), index++) === false) { return false; } start = end + match[0].length; } buffer = buffer.substring(start); start = 0; }); handle.onComplete(function() { if (buffer.length > 0) { fn(buffer, index++); } }); return handle; }; SplitStreamSequence.prototype.stringEach = function each(fn) { var delimiter = this.delimiter, pieceIndex = 0, buffer = '', bufferIndex = 0; var handle = this.parent.each(function(chunk) { buffer += chunk; var delimiterIndex; while ((delimiterIndex = buffer.indexOf(delimiter)) >= 0) { var piece = buffer.substr(0,delimiterIndex); buffer = buffer.substr(delimiterIndex+delimiter.length); if (fn(piece,pieceIndex++) === false) { return false; } } return true; }); handle.onComplete(function() { fn(buffer, pieceIndex++); }); return handle; }; StreamLikeSequence.prototype.lines = function lines() { return this.split("\n"); }; StreamLikeSequence.prototype.match = function match(pattern) { return new MatchedStreamSequence(this, pattern); }; /** * @constructor */ function MatchedStreamSequence(parent, pattern) { this.parent = parent; this.pattern = cloneRegex(pattern); } MatchedStreamSequence.prototype = new AsyncSequence(); MatchedStreamSequence.prototype.each = function each(fn) { var pattern = this.pattern, done = false, i = 0; return this.parent.each(function(chunk) { Lazy(chunk).match(pattern).each(function(match) { if (fn(match, i++) === false) { done = true; return false; } }); return !done; }); }; /** * Defines a wrapper for custom {@link StreamLikeSequence}s. This is useful * if you want a way to handle a stream of events as a sequence, but you can't * use Lazy's existing interface (i.e., you're wrapping an object from a * library with its own custom events). * * This method defines a *factory*: that is, it produces a function that can * be used to wrap objects and return a {@link Sequence}. Hopefully the * example will make this clear. * * @public * @param {Function} initializer An initialization function called on objects * created by this factory. `this` will be bound to the created object, * which is an instance of {@link StreamLikeSequence}. Use `emit` to * generate data for the sequence. * @returns {Function} A function that creates a new {@link StreamLikeSequence}, * initializes it using the specified function, and returns it. * * @example * var factory = Lazy.createWrapper(function(eventSource) { * var sequence = this; * * eventSource.handleEvent(function(data) { * sequence.emit(data); * }); * }); * * var eventEmitter = { * triggerEvent: function(data) { * eventEmitter.eventHandler(data); * }, * handleEvent: function(handler) { * eventEmitter.eventHandler = handler; * }, * eventHandler: function() {} * }; * * var events = []; * * factory(eventEmitter).each(function(e) { * events.push(e); * }); * * eventEmitter.triggerEvent('foo'); * eventEmitter.triggerEvent('bar'); * * events // => ['foo', 'bar'] */ Lazy.createWrapper = function createWrapper(initializer) { var ctor = function() { this.listeners = []; }; ctor.prototype = new StreamLikeSequence(); ctor.prototype.each = function(listener) { this.listeners.push(listener); }; ctor.prototype.emit = function(data) { var listeners = this.listeners; for (var len = listeners.length, i = len - 1; i >= 0; --i) { if (listeners[i](data) === false) { listeners.splice(i, 1); } } }; return function() { var sequence = new ctor(); initializer.apply(sequence, arguments); return sequence; }; }; /** * Creates a {@link GeneratedSequence} using the specified generator function * and (optionally) length. * * @public * @param {function(number):*} generatorFn The function used to generate the * sequence. This function accepts an index as a parameter and should return * a value for that index in the resulting sequence. * @param {number=} length The length of the sequence, for sequences with a * definite length. * @returns {GeneratedSequence} The generated sequence. * * @examples * var randomNumbers = Lazy.generate(Math.random); * var countingNumbers = Lazy.generate(function(i) { return i + 1; }, 5); * * randomNumbers // instanceof Lazy.GeneratedSequence * randomNumbers.length() // => undefined * countingNumbers // sequence: [1, 2, 3, 4, 5] * countingNumbers.length() // => 5 */ Lazy.generate = function generate(generatorFn, length) { return new GeneratedSequence(generatorFn, length); }; /** * Creates a sequence from a given starting value, up to a specified stopping * value, incrementing by a given step. Invalid values for any of these * arguments (e.g., a step of 0) result in an empty sequence. * * @public * @returns {GeneratedSequence} The sequence defined by the given ranges. * * @examples * Lazy.range(3) // sequence: [0, 1, 2] * Lazy.range(1, 4) // sequence: [1, 2, 3] * Lazy.range(2, 10, 2) // sequence: [2, 4, 6, 8] * Lazy.range(5, 1, 2) // sequence: [] * Lazy.range(5, 15, -2) // sequence: [] * Lazy.range(3, 10, 3) // sequence: [3, 6, 9] * Lazy.range(5, 2) // sequence: [5, 4, 3] * Lazy.range(7, 2, -2) // sequence: [7, 5, 3] * Lazy.range(3, 5, 0) // sequence: [] */ Lazy.range = function range() { var start = arguments.length > 1 ? arguments[0] : 0, stop = arguments.length > 1 ? arguments[1] : arguments[0], step = arguments.length > 2 && arguments[2]; if (step === false) { step = stop > start ? 1 : -1; } if (step === 0) { return Lazy([]); } return Lazy.generate(function(i) { return start + (step * i); }) .take(Math.ceil((stop - start) / step)); }; /** * Creates a sequence consisting of the given value repeated a specified number * of times. * * @public * @param {*} value The value to repeat. * @param {number=} count The number of times the value should be repeated in * the sequence. If this argument is omitted, the value will repeat forever. * @returns {GeneratedSequence} The sequence containing the repeated value. * * @examples * Lazy.repeat("hi", 3) // sequence: ["hi", "hi", "hi"] * Lazy.repeat("young") // instanceof Lazy.GeneratedSequence * Lazy.repeat("young").length() // => undefined * Lazy.repeat("young").take(3) // sequence: ["young", "young", "young"] */ Lazy.repeat = function repeat(value, count) { return Lazy.generate(function() { return value; }, count); }; Lazy.Sequence = Sequence; Lazy.ArrayLikeSequence = ArrayLikeSequence; Lazy.ObjectLikeSequence = ObjectLikeSequence; Lazy.StringLikeSequence = StringLikeSequence; Lazy.StreamLikeSequence = StreamLikeSequence; Lazy.GeneratedSequence = GeneratedSequence; Lazy.AsyncSequence = AsyncSequence; Lazy.AsyncHandle = AsyncHandle; /*** Useful utility methods ***/ /** * Creates a shallow copy of an array or object. * * @examples * var array = [1, 2, 3], clonedArray, * object = { foo: 1, bar: 2 }, clonedObject; * * clonedArray = Lazy.clone(array); // => [1, 2, 3] * clonedArray.push(4); // clonedArray == [1, 2, 3, 4] * array; // => [1, 2, 3] * * clonedObject = Lazy.clone(object); // => { foo: 1, bar: 2 } * clonedObject.baz = 3; // clonedObject == { foo: 1, bar: 2, baz: 3 } * object; // => { foo: 1, bar: 2 } */ Lazy.clone = function clone(target) { return Lazy(target).value(); }; /** * Marks a method as deprecated, so calling it will issue a console warning. */ Lazy.deprecate = function deprecate(message, fn) { return function() { console.warn(message); return fn.apply(this, arguments); }; }; var arrayPop = Array.prototype.pop, arraySlice = Array.prototype.slice; /** * Creates a callback... you know, Lo-Dash style. * * - for functions, just returns the function * - for strings, returns a pluck-style callback * - for objects, returns a where-style callback * * @private * @param {Function|string|Object} callback A function, string, or object to * convert to a callback. * @param {*} defaultReturn If the callback is undefined, a default return * value to use for the function. * @returns {Function} The callback function. * * @examples * createCallback(function() {}) // instanceof Function * createCallback('foo') // instanceof Function * createCallback('foo')({ foo: 'bar'}) // => 'bar' * createCallback({ foo: 'bar' })({ foo: 'bar' }) // => true * createCallback({ foo: 'bar' })({ foo: 'baz' }) // => false */ function createCallback(callback, defaultValue) { switch (typeof callback) { case "function": return callback; case "string": return function(e) { return e[callback]; }; case "object": return function(e) { return Lazy(callback).all(function(value, key) { return e[key] === value; }); }; case "undefined": return defaultValue ? function() { return defaultValue; } : Lazy.identity; default: throw new Error("Don't know how to make a callback from a " + typeof callback + "!"); } } /** * Takes a function that returns a value for one argument and produces a * function that compares two arguments. * * @private * @param {Function|string|Object} callback A function, string, or object to * convert to a callback using `createCallback`. * @returns {Function} A function that accepts two values and returns 1 if * the first is greater, -1 if the second is greater, or 0 if they are * equivalent. * * @examples * createComparator('a')({ a: 1 }, { a: 2 }); // => -1 * createComparator('a')({ a: 6 }, { a: 2 }); // => 1 * createComparator('a')({ a: 1 }, { a: 1 }); // => 0 * createComparator()(3, 5); // => -1 * createComparator()(7, 5); // => 1 * createComparator()(3, 3); // => 0 */ function createComparator(callback, descending) { if (!callback) { return compare; } callback = createCallback(callback); return function(x, y) { return compare(callback(x), callback(y)); }; } /** * Takes a function and returns a function with the same logic but the * arguments reversed. Only applies to functions w/ arity=2 as this is private * and I can do what I want. * * @private * @param {Function} fn The function to "reverse" * @returns {Function} The "reversed" function * * @examples * reverseArguments(function(x, y) { return x + y; })('a', 'b'); // => 'ba' */ function reverseArguments(fn) { return function(x, y) { return fn(y, x); }; } /** * Creates a Set containing the specified values. * * @param {...Array} values One or more array(s) of values used to populate the * set. * @returns {Set} A new set containing the values passed in. */ function createSet(values) { var set = new Set(); Lazy(values || []).flatten().each(function(e) { set.add(e); }); return set; } /** * Compares two elements for sorting purposes. * * @private * @param {*} x The left element to compare. * @param {*} y The right element to compare. * @returns {number} 1 if x > y, -1 if x < y, or 0 if x and y are equal. * * @examples * compare(1, 2) // => -1 * compare(1, 1) // => 0 * compare(2, 1) // => 1 * compare('a', 'b') // => -1 */ function compare(x, y) { if (x === y) { return 0; } return x > y ? 1 : -1; } /** * Iterates over every element in an array. * * @param {Array} array The array. * @param {Function} fn The function to call on every element, which can return * false to stop the iteration early. * @returns {boolean} True if every element in the entire sequence was iterated, * otherwise false. */ function forEach(array, fn) { var i = -1, len = array.length; while (++i < len) { if (fn(array[i], i) === false) { return false; } } return true; } function getFirst(sequence) { var result; sequence.each(function(e) { result = e; return false; }); return result; } /** * Checks if an element exists in an array. * * @private * @param {Array} array * @param {*} element * @returns {boolean} Whether or not the element exists in the array. * * @examples * arrayContains([1, 2], 2) // => true * arrayContains([1, 2], 3) // => false * arrayContains([undefined], undefined) // => true * arrayContains([NaN], NaN) // => true */ function arrayContains(array, element) { var i = -1, length = array.length; // Special handling for NaN if (element !== element) { while (++i < length) { if (array[i] !== array[i]) { return true; } } return false; } while (++i < length) { if (array[i] === element) { return true; } } return false; } /** * Checks if an element exists in an array before a given index. * * @private * @param {Array} array * @param {*} element * @param {number} index * @param {Function} keyFn * @returns {boolean} * * @examples * arrayContainsBefore([1, 2, 3], 3, 2) // => false * arrayContainsBefore([1, 2, 3], 3, 3) // => true */ function arrayContainsBefore(array, element, index, keyFn) { var i = -1; if (keyFn) { keyFn = createCallback(keyFn); while (++i < index) { if (keyFn(array[i]) === keyFn(element)) { return true; } } } else { while (++i < index) { if (array[i] === element) { return true; } } } return false; } /** * Swaps the elements at two specified positions of an array. * * @private * @param {Array} array * @param {number} i * @param {number} j * * @examples * var array = [1, 2, 3, 4, 5]; * * swap(array, 2, 3) // array == [1, 2, 4, 3, 5] */ function swap(array, i, j) { var temp = array[i]; array[i] = array[j]; array[j] = temp; } /** * "Clones" a regular expression (but makes it always global). * * @private * @param {RegExp|string} pattern * @returns {RegExp} */ function cloneRegex(pattern) { return eval("" + pattern + (!pattern.global ? "g" : "")); }; /** * A collection of unique elements. * * @private * @constructor * * @examples * var set = new Set(), * obj1 = {}, * obj2 = {}, * fn1 = function fn1() {}, * fn2 = function fn2() {}; * * set.add('foo') // => true * set.add('foo') // => false * set.add(1) // => true * set.add(1) // => false * set.add('1') // => true * set.add('1') // => false * set.add(obj1) // => true * set.add(obj1) // => false * set.add(obj2) // => true * set.add(fn1) // => true * set.add(fn2) // => true * set.add(fn2) // => false * set.contains('__proto__') // => false * set.add('__proto__') // => true * set.add('__proto__') // => false * set.contains('add') // => false * set.add('add') // => true * set.add('add') // => false * set.contains(undefined) // => false * set.add(undefined) // => true * set.contains(undefined) // => true * set.contains('undefined') // => false * set.add('undefined') // => true * set.contains('undefined') // => true * set.contains(NaN) // => false * set.add(NaN) // => true * set.contains(NaN) // => true * set.contains('NaN') // => false * set.add('NaN') // => true * set.contains('NaN') // => true * set.contains('@foo') // => false * set.add('@foo') // => true * set.contains('@foo') // => true */ function Set() { this.table = {}; this.objects = []; } /** * Attempts to add a unique value to the set. * * @param {*} value The value to add. * @returns {boolean} True if the value was added to the set (meaning an equal * value was not already present), or else false. */ Set.prototype.add = function add(value) { var table = this.table, type = typeof value, // only applies for strings firstChar, // only applies for objects objects; switch (type) { case "number": case "boolean": case "undefined": if (!table[value]) { table[value] = true; return true; } return false; case "string": // Essentially, escape the first character if it could possibly collide // with a number, boolean, or undefined (or a string that happens to start // with the escape character!), OR if it could override a special property // such as '__proto__' or 'constructor'. switch (value.charAt(0)) { case "_": // e.g., __proto__ case "f": // for 'false' case "t": // for 'true' case "c": // for 'constructor' case "u": // for 'undefined' case "@": // escaped case "0": case "1": case "2": case "3": case "4": case "5": case "6": case "7": case "8": case "9": case "N": // for NaN value = "@" + value; } if (!table[value]) { table[value] = true; return true; } return false; default: // For objects and functions, we can't really do anything other than store // them in an array and do a linear search for reference equality. objects = this.objects; if (!arrayContains(objects, value)) { objects.push(value); return true; } return false; } }; /** * Checks whether the set contains a value. * * @param {*} value The value to check for. * @returns {boolean} True if the set contains the value, or else false. */ Set.prototype.contains = function contains(value) { var type = typeof value, // only applies for strings firstChar; switch (type) { case "number": case "boolean": case "undefined": return !!this.table[value]; case "string": // Essentially, escape the first character if it could possibly collide // with a number, boolean, or undefined (or a string that happens to start // with the escape character!), OR if it could override a special property // such as '__proto__' or 'constructor'. switch (value.charAt(0)) { case "_": // e.g., __proto__ case "f": // for 'false' case "t": // for 'true' case "c": // for 'constructor' case "u": // for 'undefined' case "@": // escaped case "0": case "1": case "2": case "3": case "4": case "5": case "6": case "7": case "8": case "9": case "N": // for NaN value = "@" + value; } return !!this.table[value]; default: // For objects and functions, we can't really do anything other than store // them in an array and do a linear search for reference equality. return arrayContains(this.objects, value); } }; /** * A "rolling" queue, with a fixed capacity. As items are added to the head, * excess items are dropped from the tail. * * @private * @constructor * * @examples * var queue = new Queue(3); * * queue.add(1).toArray() // => [1] * queue.add(2).toArray() // => [1, 2] * queue.add(3).toArray() // => [1, 2, 3] * queue.add(4).toArray() // => [2, 3, 4] * queue.add(5).add(6).toArray() // => [4, 5, 6] * queue.add(7).add(8).toArray() // => [6, 7, 8] * * // also want to check corner cases * new Queue(1).add('foo').add('bar').toArray() // => ['bar'] * new Queue(0).add('foo').toArray() // => [] * new Queue(-1) // throws * * @benchmarks * function populateQueue(count, capacity) { * var q = new Queue(capacity); * for (var i = 0; i < count; ++i) { * q.add(i); * } * } * * function populateArray(count, capacity) { * var arr = []; * for (var i = 0; i < count; ++i) { * if (arr.length === capacity) { arr.shift(); } * arr.push(i); * } * } * * populateQueue(100, 10); // populating a Queue * populateArray(100, 10); // populating an Array */ function Queue(capacity) { this.contents = new Array(capacity); this.start = 0; this.count = 0; } /** * Adds an item to the queue, and returns the queue. */ Queue.prototype.add = function add(element) { var contents = this.contents, capacity = contents.length, start = this.start; if (this.count === capacity) { contents[start] = element; this.start = (start + 1) % capacity; } else { contents[this.count++] = element; } return this; }; /** * Returns an array containing snapshot of the queue's contents. */ Queue.prototype.toArray = function toArray() { var contents = this.contents, start = this.start, count = this.count; var snapshot = contents.slice(start, start + count); if (snapshot.length < count) { snapshot = snapshot.concat(contents.slice(0, count - snapshot.length)); } return snapshot; }; /** * Shared base method for defining new sequence types. */ function defineSequenceType(base, name, overrides) { /** @constructor */ var ctor = function ctor() {}; // Make this type inherit from the specified base. ctor.prototype = new base(); // Attach overrides to the new sequence type's prototype. for (var override in overrides) { ctor.prototype[override] = overrides[override]; } // Define a factory method that sets the new sequence's parent to the caller // and (optionally) applies any additional initialization logic. // Expose this as a chainable method so that we can do: // Lazy(...).map(...).filter(...).blah(...); var factory = function factory() { var sequence = new ctor(); // Every sequence needs a reference to its parent in order to work. sequence.parent = this; // If a custom init function was supplied, call it now. if (sequence.init) { sequence.init.apply(sequence, arguments); } return sequence; }; var methodNames = typeof name === 'string' ? [name] : name; for (var i = 0; i < methodNames.length; ++i) { base.prototype[methodNames[i]] = factory; } return ctor; } return Lazy; }); /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(7).setImmediate, __webpack_require__(7).clearImmediate)) /***/ }, /* 74 */ /***/ function(module, exports) { "use strict"; 'use strict'; module.exports = { createWriteStream: function(filename, options) { return; }, writeFileSync: function() { return; }, openSync: function() { return; }, writeSync: function() { return; } } /***/ }, /* 75 */ /***/ function(module, exports) { "use strict"; 'use strict'; class EventIndex { constructor() { this._index = {}; } get() { return Object.keys(this._index).map((f) => this._index[f]); } updateIndex(oplog, added) { added.reduce((handled, item) => { if(handled.indexOf(item.hash) === -1) { handled.push(item.hash); if(item.payload.op === 'ADD') this._index[item.hash] = item } return handled; }, []); } } module.exports = EventIndex; /***/ }, /* 76 */ /***/ function(module, exports) { /** * Parses an URI * * @author Steven Levithan (MIT license) * @api private */ var re = /^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/; var parts = [ 'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor' ]; module.exports = function parseuri(str) { var src = str, b = str.indexOf('['), e = str.indexOf(']'); if (b != -1 && e != -1) { str = str.substring(0, b) + str.substring(b, e).replace(/:/g, ';') + str.substring(e, str.length); } var m = re.exec(str || ''), uri = {}, i = 14; while (i--) { uri[parts[i]] = m[i] || ''; } if (b != -1 && e != -1) { uri.source = src; uri.host = uri.host.substring(1, uri.host.length - 1).replace(/;/g, ':'); uri.authority = uri.authority.replace('[', '').replace(']', '').replace(/;/g, ':'); uri.ipv6uri = true; } return uri; }; /***/ }, /* 77 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(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. // resolves . and .. elements in a path array with directory names there // must be no slashes, empty elements, or device names (c:\) in the array // (so also no leading and trailing slashes - it does not distinguish // relative and absolute paths) function normalizeArray(parts, allowAboveRoot) { // if the path tries to go above the root, `up` ends up > 0 var up = 0; for (var i = parts.length - 1; i >= 0; i--) { var last = parts[i]; if (last === '.') { parts.splice(i, 1); } else if (last === '..') { parts.splice(i, 1); up++; } else if (up) { parts.splice(i, 1); up--; } } // if the path is allowed to go above the root, restore leading ..s if (allowAboveRoot) { for (; up--; up) { parts.unshift('..'); } } return parts; } // Split a filename into [root, dir, basename, ext], unix version // 'root' is just a slash, or nothing. var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; var splitPath = function(filename) { return splitPathRe.exec(filename).slice(1); }; // path.resolve([from ...], to) // posix version exports.resolve = function() { var resolvedPath = '', resolvedAbsolute = false; for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { var path = (i >= 0) ? arguments[i] : process.cwd(); // Skip empty and invalid entries if (typeof path !== 'string') { throw new TypeError('Arguments to path.resolve must be strings'); } else if (!path) { continue; } resolvedPath = path + '/' + resolvedPath; resolvedAbsolute = path.charAt(0) === '/'; } // At this point the path should be resolved to a full absolute path, but // handle relative paths to be safe (might happen when process.cwd() fails) // Normalize the path resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { return !!p; }), !resolvedAbsolute).join('/'); return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; }; // path.normalize(path) // posix version exports.normalize = function(path) { var isAbsolute = exports.isAbsolute(path), trailingSlash = substr(path, -1) === '/'; // Normalize the path path = normalizeArray(filter(path.split('/'), function(p) { return !!p; }), !isAbsolute).join('/'); if (!path && !isAbsolute) { path = '.'; } if (path && trailingSlash) { path += '/'; } return (isAbsolute ? '/' : '') + path; }; // posix version exports.isAbsolute = function(path) { return path.charAt(0) === '/'; }; // posix version exports.join = function() { var paths = Array.prototype.slice.call(arguments, 0); return exports.normalize(filter(paths, function(p, index) { if (typeof p !== 'string') { throw new TypeError('Arguments to path.join must be strings'); } return p; }).join('/')); }; // path.relative(from, to) // posix version exports.relative = function(from, to) { from = exports.resolve(from).substr(1); to = exports.resolve(to).substr(1); function trim(arr) { var start = 0; for (; start < arr.length; start++) { if (arr[start] !== '') break; } var end = arr.length - 1; for (; end >= 0; end--) { if (arr[end] !== '') break; } if (start > end) return []; return arr.slice(start, end - start + 1); } var fromParts = trim(from.split('/')); var toParts = trim(to.split('/')); var length = Math.min(fromParts.length, toParts.length); var samePartsLength = length; for (var i = 0; i < length; i++) { if (fromParts[i] !== toParts[i]) { samePartsLength = i; break; } } var outputParts = []; for (var i = samePartsLength; i < fromParts.length; i++) { outputParts.push('..'); } outputParts = outputParts.concat(toParts.slice(samePartsLength)); return outputParts.join('/'); }; exports.sep = '/'; exports.delimiter = ':'; exports.dirname = function(path) { var result = splitPath(path), root = result[0], dir = result[1]; if (!root && !dir) { // No dirname whatsoever return '.'; } if (dir) { // It has a dirname, strip trailing slash dir = dir.substr(0, dir.length - 1); } return root + dir; }; exports.basename = function(path, ext) { var f = splitPath(path)[2]; // TODO: make this comparison case-insensitive on windows? if (ext && f.substr(-1 * ext.length) === ext) { f = f.substr(0, f.length - ext.length); } return f; }; exports.extname = function(path) { return splitPath(path)[3]; }; function filter (xs, f) { if (xs.filter) return xs.filter(f); var res = []; for (var i = 0; i < xs.length; i++) { if (f(xs[i], i, xs)) res.push(xs[i]); } return res; } // String.prototype.substr - negative index don't work in IE8 var substr = 'ab'.substr(-1) === 'b' ? function (str, start, len) { return str.substr(start, len) } : function (str, start, len) { if (start < 0) start = str.length + start; return str.substr(start, len); } ; /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(20))) /***/ }, /* 78 */ /***/ function(module, exports, __webpack_require__) { /** * Module dependencies. */ var eio = __webpack_require__(171); var Socket = __webpack_require__(80); var Emitter = __webpack_require__(57); var parser = __webpack_require__(39); var on = __webpack_require__(79); var bind = __webpack_require__(56); var debug = __webpack_require__(3)('socket.io-client:manager'); var indexOf = __webpack_require__(72); var Backoff = __webpack_require__(127); /** * IE6+ hasOwnProperty */ var has = Object.prototype.hasOwnProperty; /** * Module exports */ module.exports = Manager; /** * `Manager` constructor. * * @param {String} engine instance or engine uri/opts * @param {Object} options * @api public */ function Manager(uri, opts){ if (!(this instanceof Manager)) return new Manager(uri, opts); if (uri && ('object' == typeof uri)) { opts = uri; uri = undefined; } opts = opts || {}; opts.path = opts.path || '/socket.io'; this.nsps = {}; this.subs = []; this.opts = opts; this.reconnection(opts.reconnection !== false); this.reconnectionAttempts(opts.reconnectionAttempts || Infinity); this.reconnectionDelay(opts.reconnectionDelay || 1000); this.reconnectionDelayMax(opts.reconnectionDelayMax || 5000); this.randomizationFactor(opts.randomizationFactor || 0.5); this.backoff = new Backoff({ min: this.reconnectionDelay(), max: this.reconnectionDelayMax(), jitter: this.randomizationFactor() }); this.timeout(null == opts.timeout ? 20000 : opts.timeout); this.readyState = 'closed'; this.uri = uri; this.connecting = []; this.lastPing = null; this.encoding = false; this.packetBuffer = []; this.encoder = new parser.Encoder(); this.decoder = new parser.Decoder(); this.autoConnect = opts.autoConnect !== false; if (this.autoConnect) this.open(); } /** * Propagate given event to sockets and emit on `this` * * @api private */ Manager.prototype.emitAll = function() { this.emit.apply(this, arguments); for (var nsp in this.nsps) { if (has.call(this.nsps, nsp)) { this.nsps[nsp].emit.apply(this.nsps[nsp], arguments); } } }; /** * Update `socket.id` of all sockets * * @api private */ Manager.prototype.updateSocketIds = function(){ for (var nsp in this.nsps) { if (has.call(this.nsps, nsp)) { this.nsps[nsp].id = this.engine.id; } } }; /** * Mix in `Emitter`. */ Emitter(Manager.prototype); /** * Sets the `reconnection` config. * * @param {Boolean} true/false if it should automatically reconnect * @return {Manager} self or value * @api public */ Manager.prototype.reconnection = function(v){ if (!arguments.length) return this._reconnection; this._reconnection = !!v; return this; }; /** * Sets the reconnection attempts config. * * @param {Number} max reconnection attempts before giving up * @return {Manager} self or value * @api public */ Manager.prototype.reconnectionAttempts = function(v){ if (!arguments.length) return this._reconnectionAttempts; this._reconnectionAttempts = v; return this; }; /** * Sets the delay between reconnections. * * @param {Number} delay * @return {Manager} self or value * @api public */ Manager.prototype.reconnectionDelay = function(v){ if (!arguments.length) return this._reconnectionDelay; this._reconnectionDelay = v; this.backoff && this.backoff.setMin(v); return this; }; Manager.prototype.randomizationFactor = function(v){ if (!arguments.length) return this._randomizationFactor; this._randomizationFactor = v; this.backoff && this.backoff.setJitter(v); return this; }; /** * Sets the maximum delay between reconnections. * * @param {Number} delay * @return {Manager} self or value * @api public */ Manager.prototype.reconnectionDelayMax = function(v){ if (!arguments.length) return this._reconnectionDelayMax; this._reconnectionDelayMax = v; this.backoff && this.backoff.setMax(v); return this; }; /** * Sets the connection timeout. `false` to disable * * @return {Manager} self or value * @api public */ Manager.prototype.timeout = function(v){ if (!arguments.length) return this._timeout; this._timeout = v; return this; }; /** * Starts trying to reconnect if reconnection is enabled and we have not * started reconnecting yet * * @api private */ Manager.prototype.maybeReconnectOnOpen = function() { // Only try to reconnect if it's the first time we're connecting if (!this.reconnecting && this._reconnection && this.backoff.attempts === 0) { // keeps reconnection from firing twice for the same reconnection loop this.reconnect(); } }; /** * Sets the current transport `socket`. * * @param {Function} optional, callback * @return {Manager} self * @api public */ Manager.prototype.open = Manager.prototype.connect = function(fn){ debug('readyState %s', this.readyState); if (~this.readyState.indexOf('open')) return this; debug('opening %s', this.uri); this.engine = eio(this.uri, this.opts); var socket = this.engine; var self = this; this.readyState = 'opening'; this.skipReconnect = false; // emit `open` var openSub = on(socket, 'open', function() { self.onopen(); fn && fn(); }); // emit `connect_error` var errorSub = on(socket, 'error', function(data){ debug('connect_error'); self.cleanup(); self.readyState = 'closed'; self.emitAll('connect_error', data); if (fn) { var err = new Error('Connection error'); err.data = data; fn(err); } else { // Only do this if there is no fn to handle the error self.maybeReconnectOnOpen(); } }); // emit `connect_timeout` if (false !== this._timeout) { var timeout = this._timeout; debug('connect attempt will timeout after %d', timeout); // set timer var timer = setTimeout(function(){ debug('connect attempt timed out after %d', timeout); openSub.destroy(); socket.close(); socket.emit('error', 'timeout'); self.emitAll('connect_timeout', timeout); }, timeout); this.subs.push({ destroy: function(){ clearTimeout(timer); } }); } this.subs.push(openSub); this.subs.push(errorSub); return this; }; /** * Called upon transport open. * * @api private */ Manager.prototype.onopen = function(){ debug('open'); // clear old subs this.cleanup(); // mark as open this.readyState = 'open'; this.emit('open'); // add new subs var socket = this.engine; this.subs.push(on(socket, 'data', bind(this, 'ondata'))); this.subs.push(on(socket, 'ping', bind(this, 'onping'))); this.subs.push(on(socket, 'pong', bind(this, 'onpong'))); this.subs.push(on(socket, 'error', bind(this, 'onerror'))); this.subs.push(on(socket, 'close', bind(this, 'onclose'))); this.subs.push(on(this.decoder, 'decoded', bind(this, 'ondecoded'))); }; /** * Called upon a ping. * * @api private */ Manager.prototype.onping = function(){ this.lastPing = new Date; this.emitAll('ping'); }; /** * Called upon a packet. * * @api private */ Manager.prototype.onpong = function(){ this.emitAll('pong', new Date - this.lastPing); }; /** * Called with data. * * @api private */ Manager.prototype.ondata = function(data){ this.decoder.add(data); }; /** * Called when parser fully decodes a packet. * * @api private */ Manager.prototype.ondecoded = function(packet) { this.emit('packet', packet); }; /** * Called upon socket error. * * @api private */ Manager.prototype.onerror = function(err){ debug('error', err); this.emitAll('error', err); }; /** * Creates a new socket for the given `nsp`. * * @return {Socket} * @api public */ Manager.prototype.socket = function(nsp){ var socket = this.nsps[nsp]; if (!socket) { socket = new Socket(this, nsp); this.nsps[nsp] = socket; var self = this; socket.on('connecting', onConnecting); socket.on('connect', function(){ socket.id = self.engine.id; }); if (this.autoConnect) { // manually call here since connecting evnet is fired before listening onConnecting(); } } function onConnecting() { if (!~indexOf(self.connecting, socket)) { self.connecting.push(socket); } } return socket; }; /** * Called upon a socket close. * * @param {Socket} socket */ Manager.prototype.destroy = function(socket){ var index = indexOf(this.connecting, socket); if (~index) this.connecting.splice(index, 1); if (this.connecting.length) return; this.close(); }; /** * Writes a packet. * * @param {Object} packet * @api private */ Manager.prototype.packet = function(packet){ debug('writing packet %j', packet); var self = this; if (!self.encoding) { // encode, then write to engine with result self.encoding = true; this.encoder.encode(packet, function(encodedPackets) { for (var i = 0; i < encodedPackets.length; i++) { self.engine.write(encodedPackets[i], packet.options); } self.encoding = false; self.processPacketQueue(); }); } else { // add packet to the queue self.packetBuffer.push(packet); } }; /** * If packet buffer is non-empty, begins encoding the * next packet in line. * * @api private */ Manager.prototype.processPacketQueue = function() { if (this.packetBuffer.length > 0 && !this.encoding) { var pack = this.packetBuffer.shift(); this.packet(pack); } }; /** * Clean up transport subscriptions and packet buffer. * * @api private */ Manager.prototype.cleanup = function(){ debug('cleanup'); var sub; while (sub = this.subs.shift()) sub.destroy(); this.packetBuffer = []; this.encoding = false; this.lastPing = null; this.decoder.destroy(); }; /** * Close the current socket. * * @api private */ Manager.prototype.close = Manager.prototype.disconnect = function(){ debug('disconnect'); this.skipReconnect = true; this.reconnecting = false; if ('opening' == this.readyState) { // `onclose` will not fire because // an open event never happened this.cleanup(); } this.backoff.reset(); this.readyState = 'closed'; if (this.engine) this.engine.close(); }; /** * Called upon engine close. * * @api private */ Manager.prototype.onclose = function(reason){ debug('onclose'); this.cleanup(); this.backoff.reset(); this.readyState = 'closed'; this.emit('close', reason); if (this._reconnection && !this.skipReconnect) { this.reconnect(); } }; /** * Attempt a reconnection. * * @api private */ Manager.prototype.reconnect = function(){ if (this.reconnecting || this.skipReconnect) return this; var self = this; if (this.backoff.attempts >= this._reconnectionAttempts) { debug('reconnect failed'); this.backoff.reset(); this.emitAll('reconnect_failed'); this.reconnecting = false; } else { var delay = this.backoff.duration(); debug('will wait %dms before reconnect attempt', delay); this.reconnecting = true; var timer = setTimeout(function(){ if (self.skipReconnect) return; debug('attempting reconnect'); self.emitAll('reconnect_attempt', self.backoff.attempts); self.emitAll('reconnecting', self.backoff.attempts); // check again for the case socket closed in above events if (self.skipReconnect) return; self.open(function(err){ if (err) { debug('reconnect attempt error'); self.reconnecting = false; self.reconnect(); self.emitAll('reconnect_error', err.data); } else { debug('reconnect success'); self.onreconnect(); } }); }, delay); this.subs.push({ destroy: function(){ clearTimeout(timer); } }); } }; /** * Called upon successful reconnect. * * @api private */ Manager.prototype.onreconnect = function(){ var attempt = this.backoff.attempts; this.reconnecting = false; this.backoff.reset(); this.updateSocketIds(); this.emitAll('reconnect', attempt); }; /***/ }, /* 79 */ /***/ function(module, exports) { /** * Module exports. */ module.exports = on; /** * Helper for subscriptions. * * @param {Object|EventEmitter} obj with `Emitter` mixin or `EventEmitter` * @param {String} event name * @param {Function} callback * @api public */ function on(obj, ev, fn) { obj.on(ev, fn); return { destroy: function(){ obj.removeListener(ev, fn); } }; } /***/ }, /* 80 */ /***/ function(module, exports, __webpack_require__) { /** * Module dependencies. */ var parser = __webpack_require__(39); var Emitter = __webpack_require__(57); var toArray = __webpack_require__(199); var on = __webpack_require__(79); var bind = __webpack_require__(56); var debug = __webpack_require__(3)('socket.io-client:socket'); var hasBin = __webpack_require__(180); /** * Module exports. */ module.exports = exports = Socket; /** * Internal events (blacklisted). * These events can't be emitted by the user. * * @api private */ var events = { connect: 1, connect_error: 1, connect_timeout: 1, connecting: 1, disconnect: 1, error: 1, reconnect: 1, reconnect_attempt: 1, reconnect_failed: 1, reconnect_error: 1, reconnecting: 1, ping: 1, pong: 1 }; /** * Shortcut to `Emitter#emit`. */ var emit = Emitter.prototype.emit; /** * `Socket` constructor. * * @api public */ function Socket(io, nsp){ this.io = io; this.nsp = nsp; this.json = this; // compat this.ids = 0; this.acks = {}; this.receiveBuffer = []; this.sendBuffer = []; this.connected = false; this.disconnected = true; if (this.io.autoConnect) this.open(); } /** * Mix in `Emitter`. */ Emitter(Socket.prototype); /** * Subscribe to open, close and packet events * * @api private */ Socket.prototype.subEvents = function() { if (this.subs) return; var io = this.io; this.subs = [ on(io, 'open', bind(this, 'onopen')), on(io, 'packet', bind(this, 'onpacket')), on(io, 'close', bind(this, 'onclose')) ]; }; /** * "Opens" the socket. * * @api public */ Socket.prototype.open = Socket.prototype.connect = function(){ if (this.connected) return this; this.subEvents(); this.io.open(); // ensure open if ('open' == this.io.readyState) this.onopen(); this.emit('connecting'); return this; }; /** * Sends a `message` event. * * @return {Socket} self * @api public */ Socket.prototype.send = function(){ var args = toArray(arguments); args.unshift('message'); this.emit.apply(this, args); return this; }; /** * Override `emit`. * If the event is in `events`, it's emitted normally. * * @param {String} event name * @return {Socket} self * @api public */ Socket.prototype.emit = function(ev){ if (events.hasOwnProperty(ev)) { emit.apply(this, arguments); return this; } var args = toArray(arguments); var parserType = parser.EVENT; // default if (hasBin(args)) { parserType = parser.BINARY_EVENT; } // binary var packet = { type: parserType, data: args }; packet.options = {}; packet.options.compress = !this.flags || false !== this.flags.compress; // event ack callback if ('function' == typeof args[args.length - 1]) { debug('emitting packet with ack id %d', this.ids); this.acks[this.ids] = args.pop(); packet.id = this.ids++; } if (this.connected) { this.packet(packet); } else { this.sendBuffer.push(packet); } delete this.flags; return this; }; /** * Sends a packet. * * @param {Object} packet * @api private */ Socket.prototype.packet = function(packet){ packet.nsp = this.nsp; this.io.packet(packet); }; /** * Called upon engine `open`. * * @api private */ Socket.prototype.onopen = function(){ debug('transport is open - connecting'); // write connect packet if necessary if ('/' != this.nsp) { this.packet({ type: parser.CONNECT }); } }; /** * Called upon engine `close`. * * @param {String} reason * @api private */ Socket.prototype.onclose = function(reason){ debug('close (%s)', reason); this.connected = false; this.disconnected = true; delete this.id; this.emit('disconnect', reason); }; /** * Called with socket packet. * * @param {Object} packet * @api private */ Socket.prototype.onpacket = function(packet){ if (packet.nsp != this.nsp) return; switch (packet.type) { case parser.CONNECT: this.onconnect(); break; case parser.EVENT: this.onevent(packet); break; case parser.BINARY_EVENT: this.onevent(packet); break; case parser.ACK: this.onack(packet); break; case parser.BINARY_ACK: this.onack(packet); break; case parser.DISCONNECT: this.ondisconnect(); break; case parser.ERROR: this.emit('error', packet.data); break; } }; /** * Called upon a server event. * * @param {Object} packet * @api private */ Socket.prototype.onevent = function(packet){ var args = packet.data || []; debug('emitting event %j', args); if (null != packet.id) { debug('attaching ack callback to event'); args.push(this.ack(packet.id)); } if (this.connected) { emit.apply(this, args); } else { this.receiveBuffer.push(args); } }; /** * Produces an ack callback to emit with an event. * * @api private */ Socket.prototype.ack = function(id){ var self = this; var sent = false; return function(){ // prevent double callbacks if (sent) return; sent = true; var args = toArray(arguments); debug('sending ack %j', args); var type = hasBin(args) ? parser.BINARY_ACK : parser.ACK; self.packet({ type: type, id: id, data: args }); }; }; /** * Called upon a server acknowlegement. * * @param {Object} packet * @api private */ Socket.prototype.onack = function(packet){ var ack = this.acks[packet.id]; if ('function' == typeof ack) { debug('calling ack %s with %j', packet.id, packet.data); ack.apply(this, packet.data); delete this.acks[packet.id]; } else { debug('bad ack %s', packet.id); } }; /** * Called upon server connect. * * @api private */ Socket.prototype.onconnect = function(){ this.connected = true; this.disconnected = false; this.emit('connect'); this.emitBuffered(); }; /** * Emit buffered events (received and emitted). * * @api private */ Socket.prototype.emitBuffered = function(){ var i; for (i = 0; i < this.receiveBuffer.length; i++) { emit.apply(this, this.receiveBuffer[i]); } this.receiveBuffer = []; for (i = 0; i < this.sendBuffer.length; i++) { this.packet(this.sendBuffer[i]); } this.sendBuffer = []; }; /** * Called upon server disconnect. * * @api private */ Socket.prototype.ondisconnect = function(){ debug('server disconnect (%s)', this.nsp); this.destroy(); this.onclose('io server disconnect'); }; /** * Called upon forced client/server side disconnections, * this method ensures the manager stops tracking us and * that reconnections don't get triggered for this. * * @api private. */ Socket.prototype.destroy = function(){ if (this.subs) { // clean subscriptions to avoid reconnections for (var i = 0; i < this.subs.length; i++) { this.subs[i].destroy(); } this.subs = null; } this.io.destroy(this); }; /** * Disconnects the socket manually. * * @return {Socket} self * @api public */ Socket.prototype.close = Socket.prototype.disconnect = function(){ if (this.connected) { debug('performing disconnect (%s)', this.nsp); this.packet({ type: parser.DISCONNECT }); } // remove socket from pool this.destroy(); if (this.connected) { // fire events this.onclose('io client disconnect'); } return this; }; /** * Sets the compress flag. * * @param {Boolean} if `true`, compresses the sending data * @return {Socket} self * @api public */ Socket.prototype.compress = function(compress){ this.flags = this.flags || {}; this.flags.compress = compress; return this; }; /***/ }, /* 81 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(global) { module.exports = isBuf; /** * Returns true if obj is a buffer or an arraybuffer. * * @api private */ function isBuf(obj) { return (global.Buffer && global.Buffer.isBuffer(obj)) || (global.ArrayBuffer && obj instanceof ArrayBuffer); } /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0))) /***/ }, /* 82 */ /***/ function(module, exports) { module.exports = Array.isArray || function (arr) { return Object.prototype.toString.call(arr) == '[object Array]'; }; /***/ }, /* 83 */ /***/ function(module, exports) { "use strict"; 'use strict'; var alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_'.split('') , length = 64 , map = {} , seed = 0 , i = 0 , prev; /** * Return a string representing the specified number. * * @param {Number} num The number to convert. * @returns {String} The string representation of the number. * @api public */ function encode(num) { var encoded = ''; do { encoded = alphabet[num % length] + encoded; num = Math.floor(num / length); } while (num > 0); return encoded; } /** * Return the integer value specified by the given string. * * @param {String} str The string to convert. * @returns {Number} The integer value represented by the string. * @api public */ function decode(str) { var decoded = 0; for (i = 0; i < str.length; i++) { decoded = decoded * length + map[str.charAt(i)]; } return decoded; } /** * Yeast: A tiny growing id generator. * * @returns {String} A unique id. * @api public */ function yeast() { var now = encode(+new Date()); if (now !== prev) return seed = 0, prev = now; return now +'.'+ encode(seed++); } // // Map each character to its index. // for (; i < length; i++) map[alphabet[i]] = i; // // Expose the `yeast`, `encode` and `decode` functions. // yeast.encode = encode; yeast.decode = decode; module.exports = yeast; /***/ }, /* 84 */ /***/ function(module, exports, __webpack_require__) { "use strict"; 'use strict'; var _stringify = __webpack_require__(41); var _stringify2 = _interopRequireDefault(_stringify); var _promise = __webpack_require__(42); var _promise2 = _interopRequireDefault(_promise); var _classCallCheck2 = __webpack_require__(43); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = __webpack_require__(44); var _createClass3 = _interopRequireDefault(_createClass2); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var io = __webpack_require__(195); var logger = __webpack_require__(45).create("orbit-db.Pubsub"); var Pubsub = function () { function Pubsub() { (0, _classCallCheck3.default)(this, Pubsub); this._socket = null; this._subscriptions = {}; } (0, _createClass3.default)(Pubsub, [{ key: 'connect', value: function connect(host, port, username, password) { var _this = this; return new _promise2.default(function (resolve, reject) { if (!_this._socket) _this._socket = io.connect('http://' + host + ':' + port, { 'forceNew': true }); _this._socket.on('connect', resolve); _this._socket.on('connect_error', function (err) { return reject(new Error('Connection refused to Pubsub at \'' + host + ':' + port + '\'')); }); _this._socket.on('disconnect', function (socket) { return logger.warn('Disconnected from Pubsub at \'http://' + host + ':' + port + '\''); }); _this._socket.on('error', function (e) { return logger.error('Pubsub socket error:', e); }); _this._socket.on('message', _this._handleMessage.bind(_this)); _this._socket.on('subscribed', _this._handleMessage.bind(_this)); }); } }, { key: 'disconnect', value: function disconnect() { if (this._socket) this._socket.disconnect(); } }, { key: 'subscribe', value: function subscribe(hash, password, callback) { if (!this._subscriptions[hash]) { this._subscriptions[hash] = { callback: callback }; this._socket.emit('subscribe', { channel: hash }); // calls back with 'subscribed' event } } }, { key: 'unsubscribe', value: function unsubscribe(hash) { if (this._subscriptions[hash]) { this._socket.emit('unsubscribe', { channel: hash }); delete this._subscriptions[hash]; } } }, { key: 'publish', value: function publish(hash, message) { if (this._subscriptions[hash]) this._socket.send((0, _stringify2.default)({ channel: hash, message: message })); } }, { key: '_handleMessage', value: function _handleMessage(hash, message) { if (this._subscriptions[hash] && this._subscriptions[hash].callback) this._subscriptions[hash].callback(hash, message); } }]); return Pubsub; }(); module.exports = Pubsub; /***/ }, /* 85 */ /***/ function(module, exports, __webpack_require__) { "use strict"; 'use strict'; const Store = __webpack_require__(37); const CounterIndex = __webpack_require__(188); class CounterStore extends Store { constructor(ipfs, id, dbname, options) { Object.assign(options || {}, { Index: CounterIndex }); super(ipfs, id, dbname, options) } value() { return this._index.get().value; } inc(amount) { const counter = this._index.get(); if(counter) { counter.increment(amount); return this._addOperation({ op: 'COUNTER', key: null, value: counter.payload, meta: { ts: new Date().getTime() } }); } } } module.exports = CounterStore; /***/ }, /* 86 */ /***/ function(module, exports, __webpack_require__) { "use strict"; 'use strict'; const Lazy = __webpack_require__(73); const EventStore = __webpack_require__(46); const FeedIndex = __webpack_require__(189); class FeedStore extends EventStore { constructor(ipfs, id, dbname, options) { Object.assign(options || {}, { Index: FeedIndex }); super(ipfs, id, dbname, options) } remove(hash) { const operation = { op: 'DEL', key: null, value: hash, meta: { ts: new Date().getTime() } }; return this._addOperation(operation); } } module.exports = FeedStore; /***/ }, /* 87 */ /***/ function(module, exports, __webpack_require__) { "use strict"; 'use strict'; const Store = __webpack_require__(37); const KeyValueIndex = __webpack_require__(190); class KeyValueStore extends Store { constructor(ipfs, id, dbname, options) { Object.assign(options || {}, { Index: KeyValueIndex }); super(ipfs, id, dbname, options) } get(key) { return this._index.get(key); } set(key, data) { this.put(key, data); } put(key, data) { return this._addOperation({ op: 'PUT', key: key, value: data, meta: { ts: new Date().getTime() } }); } del(key) { return this._addOperation({ op: 'DEL', key: key, value: null, meta: { ts: new Date().getTime() } }); } } module.exports = KeyValueStore; /***/ }, /* 88 */ /***/ function(module, exports, __webpack_require__) { module.exports = { "default": __webpack_require__(92), __esModule: true }; /***/ }, /* 89 */ /***/ function(module, exports, __webpack_require__) { module.exports = { "default": __webpack_require__(93), __esModule: true }; /***/ }, /* 90 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(process, global, setImmediate) {/* @preserve * The MIT License (MIT) * * Copyright (c) 2013-2015 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: * * 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. * */ /** * bluebird build version 3.3.5 * Features enabled: core, race, call_get, generators, map, nodeify, promisify, props, reduce, settle, some, using, timers, filter, any, each */ !function(e){if(true)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.Promise=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 _dereq_=="function"&&_dereq_;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof _dereq_=="function"&&_dereq_;for(var o=0;o 0) { var fn = queue.shift(); if (typeof fn !== "function") { fn._settlePromises(); continue; } var receiver = queue.shift(); var arg = queue.shift(); fn.call(receiver, arg); } }; Async.prototype._drainQueues = function () { this._drainQueue(this._normalQueue); this._reset(); this._haveDrainedQueues = true; this._drainQueue(this._lateQueue); }; Async.prototype._queueTick = function () { if (!this._isTickUsed) { this._isTickUsed = true; this._schedule(this.drainQueues); } }; Async.prototype._reset = function () { this._isTickUsed = false; }; module.exports = Async; module.exports.firstLineError = firstLineError; },{"./queue":26,"./schedule":29,"./util":36}],3:[function(_dereq_,module,exports){ "use strict"; module.exports = function(Promise, INTERNAL, tryConvertToPromise, debug) { var calledBind = false; var rejectThis = function(_, e) { this._reject(e); }; var targetRejected = function(e, context) { context.promiseRejectionQueued = true; context.bindingPromise._then(rejectThis, rejectThis, null, this, e); }; var bindingResolved = function(thisArg, context) { if (((this._bitField & 50397184) === 0)) { this._resolveCallback(context.target); } }; var bindingRejected = function(e, context) { if (!context.promiseRejectionQueued) this._reject(e); }; Promise.prototype.bind = function (thisArg) { if (!calledBind) { calledBind = true; Promise.prototype._propagateFrom = debug.propagateFromFunction(); Promise.prototype._boundValue = debug.boundValueFunction(); } var maybePromise = tryConvertToPromise(thisArg); var ret = new Promise(INTERNAL); ret._propagateFrom(this, 1); var target = this._target(); ret._setBoundTo(maybePromise); if (maybePromise instanceof Promise) { var context = { promiseRejectionQueued: false, promise: ret, target: target, bindingPromise: maybePromise }; target._then(INTERNAL, targetRejected, undefined, ret, context); maybePromise._then( bindingResolved, bindingRejected, undefined, ret, context); ret._setOnCancel(maybePromise); } else { ret._resolveCallback(target); } return ret; }; Promise.prototype._setBoundTo = function (obj) { if (obj !== undefined) { this._bitField = this._bitField | 2097152; this._boundTo = obj; } else { this._bitField = this._bitField & (~2097152); } }; Promise.prototype._isBound = function () { return (this._bitField & 2097152) === 2097152; }; Promise.bind = function (thisArg, value) { return Promise.resolve(value).bind(thisArg); }; }; },{}],4:[function(_dereq_,module,exports){ "use strict"; var old; if (typeof Promise !== "undefined") old = Promise; function noConflict() { try { if (Promise === bluebird) Promise = old; } catch (e) {} return bluebird; } var bluebird = _dereq_("./promise")(); bluebird.noConflict = noConflict; module.exports = bluebird; },{"./promise":22}],5:[function(_dereq_,module,exports){ "use strict"; var cr = Object.create; if (cr) { var callerCache = cr(null); var getterCache = cr(null); callerCache[" size"] = getterCache[" size"] = 0; } module.exports = function(Promise) { var util = _dereq_("./util"); var canEvaluate = util.canEvaluate; var isIdentifier = util.isIdentifier; var getMethodCaller; var getGetter; if (false) { var makeMethodCaller = function (methodName) { return new Function("ensureMethod", " \n\ return function(obj) { \n\ 'use strict' \n\ var len = this.length; \n\ ensureMethod(obj, 'methodName'); \n\ switch(len) { \n\ case 1: return obj.methodName(this[0]); \n\ case 2: return obj.methodName(this[0], this[1]); \n\ case 3: return obj.methodName(this[0], this[1], this[2]); \n\ case 0: return obj.methodName(); \n\ default: \n\ return obj.methodName.apply(obj, this); \n\ } \n\ }; \n\ ".replace(/methodName/g, methodName))(ensureMethod); }; var makeGetter = function (propertyName) { return new Function("obj", " \n\ 'use strict'; \n\ return obj.propertyName; \n\ ".replace("propertyName", propertyName)); }; var getCompiled = function(name, compiler, cache) { var ret = cache[name]; if (typeof ret !== "function") { if (!isIdentifier(name)) { return null; } ret = compiler(name); cache[name] = ret; cache[" size"]++; if (cache[" size"] > 512) { var keys = Object.keys(cache); for (var i = 0; i < 256; ++i) delete cache[keys[i]]; cache[" size"] = keys.length - 256; } } return ret; }; getMethodCaller = function(name) { return getCompiled(name, makeMethodCaller, callerCache); }; getGetter = function(name) { return getCompiled(name, makeGetter, getterCache); }; } function ensureMethod(obj, methodName) { var fn; if (obj != null) fn = obj[methodName]; if (typeof fn !== "function") { var message = "Object " + util.classString(obj) + " has no method '" + util.toString(methodName) + "'"; throw new Promise.TypeError(message); } return fn; } function caller(obj) { var methodName = this.pop(); var fn = ensureMethod(obj, methodName); return fn.apply(obj, this); } Promise.prototype.call = function (methodName) { var args = [].slice.call(arguments, 1);; if (false) { if (canEvaluate) { var maybeCaller = getMethodCaller(methodName); if (maybeCaller !== null) { return this._then( maybeCaller, undefined, undefined, args, undefined); } } } args.push(methodName); return this._then(caller, undefined, undefined, args, undefined); }; function namedGetter(obj) { return obj[this]; } function indexedGetter(obj) { var index = +this; if (index < 0) index = Math.max(0, index + obj.length); return obj[index]; } Promise.prototype.get = function (propertyName) { var isIndex = (typeof propertyName === "number"); var getter; if (!isIndex) { if (canEvaluate) { var maybeGetter = getGetter(propertyName); getter = maybeGetter !== null ? maybeGetter : namedGetter; } else { getter = namedGetter; } } else { getter = indexedGetter; } return this._then(getter, undefined, undefined, propertyName, undefined); }; }; },{"./util":36}],6:[function(_dereq_,module,exports){ "use strict"; module.exports = function(Promise, PromiseArray, apiRejection, debug) { var util = _dereq_("./util"); var tryCatch = util.tryCatch; var errorObj = util.errorObj; var async = Promise._async; Promise.prototype["break"] = Promise.prototype.cancel = function() { if (!debug.cancellation()) return this._warn("cancellation is disabled"); var promise = this; var child = promise; while (promise.isCancellable()) { if (!promise._cancelBy(child)) { if (child._isFollowing()) { child._followee().cancel(); } else { child._cancelBranched(); } break; } var parent = promise._cancellationParent; if (parent == null || !parent.isCancellable()) { if (promise._isFollowing()) { promise._followee().cancel(); } else { promise._cancelBranched(); } break; } else { if (promise._isFollowing()) promise._followee().cancel(); child = promise; promise = parent; } } }; Promise.prototype._branchHasCancelled = function() { this._branchesRemainingToCancel--; }; Promise.prototype._enoughBranchesHaveCancelled = function() { return this._branchesRemainingToCancel === undefined || this._branchesRemainingToCancel <= 0; }; Promise.prototype._cancelBy = function(canceller) { if (canceller === this) { this._branchesRemainingToCancel = 0; this._invokeOnCancel(); return true; } else { this._branchHasCancelled(); if (this._enoughBranchesHaveCancelled()) { this._invokeOnCancel(); return true; } } return false; }; Promise.prototype._cancelBranched = function() { if (this._enoughBranchesHaveCancelled()) { this._cancel(); } }; Promise.prototype._cancel = function() { if (!this.isCancellable()) return; this._setCancelled(); async.invoke(this._cancelPromises, this, undefined); }; Promise.prototype._cancelPromises = function() { if (this._length() > 0) this._settlePromises(); }; Promise.prototype._unsetOnCancel = function() { this._onCancelField = undefined; }; Promise.prototype.isCancellable = function() { return this.isPending() && !this.isCancelled(); }; Promise.prototype._doInvokeOnCancel = function(onCancelCallback, internalOnly) { if (util.isArray(onCancelCallback)) { for (var i = 0; i < onCancelCallback.length; ++i) { this._doInvokeOnCancel(onCancelCallback[i], internalOnly); } } else if (onCancelCallback !== undefined) { if (typeof onCancelCallback === "function") { if (!internalOnly) { var e = tryCatch(onCancelCallback).call(this._boundValue()); if (e === errorObj) { this._attachExtraTrace(e.e); async.throwLater(e.e); } } } else { onCancelCallback._resultCancelled(this); } } }; Promise.prototype._invokeOnCancel = function() { var onCancelCallback = this._onCancel(); this._unsetOnCancel(); async.invoke(this._doInvokeOnCancel, this, onCancelCallback); }; Promise.prototype._invokeInternalOnCancel = function() { if (this.isCancellable()) { this._doInvokeOnCancel(this._onCancel(), true); this._unsetOnCancel(); } }; Promise.prototype._resultCancelled = function() { this.cancel(); }; }; },{"./util":36}],7:[function(_dereq_,module,exports){ "use strict"; module.exports = function(NEXT_FILTER) { var util = _dereq_("./util"); var getKeys = _dereq_("./es5").keys; var tryCatch = util.tryCatch; var errorObj = util.errorObj; function catchFilter(instances, cb, promise) { return function(e) { var boundTo = promise._boundValue(); predicateLoop: for (var i = 0; i < instances.length; ++i) { var item = instances[i]; if (item === Error || (item != null && item.prototype instanceof Error)) { if (e instanceof item) { return tryCatch(cb).call(boundTo, e); } } else if (typeof item === "function") { var matchesPredicate = tryCatch(item).call(boundTo, e); if (matchesPredicate === errorObj) { return matchesPredicate; } else if (matchesPredicate) { return tryCatch(cb).call(boundTo, e); } } else if (util.isObject(e)) { var keys = getKeys(item); for (var j = 0; j < keys.length; ++j) { var key = keys[j]; if (item[key] != e[key]) { continue predicateLoop; } } return tryCatch(cb).call(boundTo, e); } } return NEXT_FILTER; }; } return catchFilter; }; },{"./es5":13,"./util":36}],8:[function(_dereq_,module,exports){ "use strict"; module.exports = function(Promise) { var longStackTraces = false; var contextStack = []; Promise.prototype._promiseCreated = function() {}; Promise.prototype._pushContext = function() {}; Promise.prototype._popContext = function() {return null;}; Promise._peekContext = Promise.prototype._peekContext = function() {}; function Context() { this._trace = new Context.CapturedTrace(peekContext()); } Context.prototype._pushContext = function () { if (this._trace !== undefined) { this._trace._promiseCreated = null; contextStack.push(this._trace); } }; Context.prototype._popContext = function () { if (this._trace !== undefined) { var trace = contextStack.pop(); var ret = trace._promiseCreated; trace._promiseCreated = null; return ret; } return null; }; function createContext() { if (longStackTraces) return new Context(); } function peekContext() { var lastIndex = contextStack.length - 1; if (lastIndex >= 0) { return contextStack[lastIndex]; } return undefined; } Context.CapturedTrace = null; Context.create = createContext; Context.deactivateLongStackTraces = function() {}; Context.activateLongStackTraces = function() { var Promise_pushContext = Promise.prototype._pushContext; var Promise_popContext = Promise.prototype._popContext; var Promise_PeekContext = Promise._peekContext; var Promise_peekContext = Promise.prototype._peekContext; var Promise_promiseCreated = Promise.prototype._promiseCreated; Context.deactivateLongStackTraces = function() { Promise.prototype._pushContext = Promise_pushContext; Promise.prototype._popContext = Promise_popContext; Promise._peekContext = Promise_PeekContext; Promise.prototype._peekContext = Promise_peekContext; Promise.prototype._promiseCreated = Promise_promiseCreated; longStackTraces = false; }; longStackTraces = true; Promise.prototype._pushContext = Context.prototype._pushContext; Promise.prototype._popContext = Context.prototype._popContext; Promise._peekContext = Promise.prototype._peekContext = peekContext; Promise.prototype._promiseCreated = function() { var ctx = this._peekContext(); if (ctx && ctx._promiseCreated == null) ctx._promiseCreated = this; }; }; return Context; }; },{}],9:[function(_dereq_,module,exports){ "use strict"; module.exports = function(Promise, Context) { var getDomain = Promise._getDomain; var async = Promise._async; var Warning = _dereq_("./errors").Warning; var util = _dereq_("./util"); var canAttachTrace = util.canAttachTrace; var unhandledRejectionHandled; var possiblyUnhandledRejection; var bluebirdFramePattern = /[\\\/]bluebird[\\\/]js[\\\/](release|debug|instrumented)/; var stackFramePattern = null; var formatStack = null; var indentStackFrames = false; var printWarning; var debugging = !!(util.env("BLUEBIRD_DEBUG") != 0 && (true || util.env("BLUEBIRD_DEBUG") || util.env("NODE_ENV") === "development")); var warnings = !!(util.env("BLUEBIRD_WARNINGS") != 0 && (debugging || util.env("BLUEBIRD_WARNINGS"))); var longStackTraces = !!(util.env("BLUEBIRD_LONG_STACK_TRACES") != 0 && (debugging || util.env("BLUEBIRD_LONG_STACK_TRACES"))); var wForgottenReturn = util.env("BLUEBIRD_W_FORGOTTEN_RETURN") != 0 && (warnings || !!util.env("BLUEBIRD_W_FORGOTTEN_RETURN")); Promise.prototype.suppressUnhandledRejections = function() { var target = this._target(); target._bitField = ((target._bitField & (~1048576)) | 524288); }; Promise.prototype._ensurePossibleRejectionHandled = function () { if ((this._bitField & 524288) !== 0) return; this._setRejectionIsUnhandled(); async.invokeLater(this._notifyUnhandledRejection, this, undefined); }; Promise.prototype._notifyUnhandledRejectionIsHandled = function () { fireRejectionEvent("rejectionHandled", unhandledRejectionHandled, undefined, this); }; Promise.prototype._setReturnedNonUndefined = function() { this._bitField = this._bitField | 268435456; }; Promise.prototype._returnedNonUndefined = function() { return (this._bitField & 268435456) !== 0; }; Promise.prototype._notifyUnhandledRejection = function () { if (this._isRejectionUnhandled()) { var reason = this._settledValue(); this._setUnhandledRejectionIsNotified(); fireRejectionEvent("unhandledRejection", possiblyUnhandledRejection, reason, this); } }; Promise.prototype._setUnhandledRejectionIsNotified = function () { this._bitField = this._bitField | 262144; }; Promise.prototype._unsetUnhandledRejectionIsNotified = function () { this._bitField = this._bitField & (~262144); }; Promise.prototype._isUnhandledRejectionNotified = function () { return (this._bitField & 262144) > 0; }; Promise.prototype._setRejectionIsUnhandled = function () { this._bitField = this._bitField | 1048576; }; Promise.prototype._unsetRejectionIsUnhandled = function () { this._bitField = this._bitField & (~1048576); if (this._isUnhandledRejectionNotified()) { this._unsetUnhandledRejectionIsNotified(); this._notifyUnhandledRejectionIsHandled(); } }; Promise.prototype._isRejectionUnhandled = function () { return (this._bitField & 1048576) > 0; }; Promise.prototype._warn = function(message, shouldUseOwnTrace, promise) { return warn(message, shouldUseOwnTrace, promise || this); }; Promise.onPossiblyUnhandledRejection = function (fn) { var domain = getDomain(); possiblyUnhandledRejection = typeof fn === "function" ? (domain === null ? fn : domain.bind(fn)) : undefined; }; Promise.onUnhandledRejectionHandled = function (fn) { var domain = getDomain(); unhandledRejectionHandled = typeof fn === "function" ? (domain === null ? fn : domain.bind(fn)) : undefined; }; var disableLongStackTraces = function() {}; Promise.longStackTraces = function () { if (async.haveItemsQueued() && !config.longStackTraces) { throw new Error("cannot enable long stack traces after promises have been created\u000a\u000a See http://goo.gl/MqrFmX\u000a"); } if (!config.longStackTraces && longStackTracesIsSupported()) { var Promise_captureStackTrace = Promise.prototype._captureStackTrace; var Promise_attachExtraTrace = Promise.prototype._attachExtraTrace; config.longStackTraces = true; disableLongStackTraces = function() { if (async.haveItemsQueued() && !config.longStackTraces) { throw new Error("cannot enable long stack traces after promises have been created\u000a\u000a See http://goo.gl/MqrFmX\u000a"); } Promise.prototype._captureStackTrace = Promise_captureStackTrace; Promise.prototype._attachExtraTrace = Promise_attachExtraTrace; Context.deactivateLongStackTraces(); async.enableTrampoline(); config.longStackTraces = false; }; Promise.prototype._captureStackTrace = longStackTracesCaptureStackTrace; Promise.prototype._attachExtraTrace = longStackTracesAttachExtraTrace; Context.activateLongStackTraces(); async.disableTrampolineIfNecessary(); } }; Promise.hasLongStackTraces = function () { return config.longStackTraces && longStackTracesIsSupported(); }; var fireDomEvent = (function() { try { var event = document.createEvent("CustomEvent"); event.initCustomEvent("testingtheevent", false, true, {}); util.global.dispatchEvent(event); return function(name, event) { var domEvent = document.createEvent("CustomEvent"); domEvent.initCustomEvent(name.toLowerCase(), false, true, event); return !util.global.dispatchEvent(domEvent); }; } catch (e) {} return function() { return false; }; })(); var fireGlobalEvent = (function() { if (util.isNode) { return function() { return process.emit.apply(process, arguments); }; } else { if (!util.global) { return function() { return false; }; } return function(name) { var methodName = "on" + name.toLowerCase(); var method = util.global[methodName]; if (!method) return false; method.apply(util.global, [].slice.call(arguments, 1)); return true; }; } })(); function generatePromiseLifecycleEventObject(name, promise) { return {promise: promise}; } var eventToObjectGenerator = { promiseCreated: generatePromiseLifecycleEventObject, promiseFulfilled: generatePromiseLifecycleEventObject, promiseRejected: generatePromiseLifecycleEventObject, promiseResolved: generatePromiseLifecycleEventObject, promiseCancelled: generatePromiseLifecycleEventObject, promiseChained: function(name, promise, child) { return {promise: promise, child: child}; }, warning: function(name, warning) { return {warning: warning}; }, unhandledRejection: function (name, reason, promise) { return {reason: reason, promise: promise}; }, rejectionHandled: generatePromiseLifecycleEventObject }; var activeFireEvent = function (name) { var globalEventFired = false; try { globalEventFired = fireGlobalEvent.apply(null, arguments); } catch (e) { async.throwLater(e); globalEventFired = true; } var domEventFired = false; try { domEventFired = fireDomEvent(name, eventToObjectGenerator[name].apply(null, arguments)); } catch (e) { async.throwLater(e); domEventFired = true; } return domEventFired || globalEventFired; }; Promise.config = function(opts) { opts = Object(opts); if ("longStackTraces" in opts) { if (opts.longStackTraces) { Promise.longStackTraces(); } else if (!opts.longStackTraces && Promise.hasLongStackTraces()) { disableLongStackTraces(); } } if ("warnings" in opts) { var warningsOption = opts.warnings; config.warnings = !!warningsOption; wForgottenReturn = config.warnings; if (util.isObject(warningsOption)) { if ("wForgottenReturn" in warningsOption) { wForgottenReturn = !!warningsOption.wForgottenReturn; } } } if ("cancellation" in opts && opts.cancellation && !config.cancellation) { if (async.haveItemsQueued()) { throw new Error( "cannot enable cancellation after promises are in use"); } Promise.prototype._clearCancellationData = cancellationClearCancellationData; Promise.prototype._propagateFrom = cancellationPropagateFrom; Promise.prototype._onCancel = cancellationOnCancel; Promise.prototype._setOnCancel = cancellationSetOnCancel; Promise.prototype._attachCancellationCallback = cancellationAttachCancellationCallback; Promise.prototype._execute = cancellationExecute; propagateFromFunction = cancellationPropagateFrom; config.cancellation = true; } if ("monitoring" in opts) { if (opts.monitoring && !config.monitoring) { config.monitoring = true; Promise.prototype._fireEvent = activeFireEvent; } else if (!opts.monitoring && config.monitoring) { config.monitoring = false; Promise.prototype._fireEvent = defaultFireEvent; } } }; function defaultFireEvent() { return false; } Promise.prototype._fireEvent = defaultFireEvent; Promise.prototype._execute = function(executor, resolve, reject) { try { executor(resolve, reject); } catch (e) { return e; } }; Promise.prototype._onCancel = function () {}; Promise.prototype._setOnCancel = function (handler) { ; }; Promise.prototype._attachCancellationCallback = function(onCancel) { ; }; Promise.prototype._captureStackTrace = function () {}; Promise.prototype._attachExtraTrace = function () {}; Promise.prototype._clearCancellationData = function() {}; Promise.prototype._propagateFrom = function (parent, flags) { ; ; }; function cancellationExecute(executor, resolve, reject) { var promise = this; try { executor(resolve, reject, function(onCancel) { if (typeof onCancel !== "function") { throw new TypeError("onCancel must be a function, got: " + util.toString(onCancel)); } promise._attachCancellationCallback(onCancel); }); } catch (e) { return e; } } function cancellationAttachCancellationCallback(onCancel) { if (!this.isCancellable()) return this; var previousOnCancel = this._onCancel(); if (previousOnCancel !== undefined) { if (util.isArray(previousOnCancel)) { previousOnCancel.push(onCancel); } else { this._setOnCancel([previousOnCancel, onCancel]); } } else { this._setOnCancel(onCancel); } } function cancellationOnCancel() { return this._onCancelField; } function cancellationSetOnCancel(onCancel) { this._onCancelField = onCancel; } function cancellationClearCancellationData() { this._cancellationParent = undefined; this._onCancelField = undefined; } function cancellationPropagateFrom(parent, flags) { if ((flags & 1) !== 0) { this._cancellationParent = parent; var branchesRemainingToCancel = parent._branchesRemainingToCancel; if (branchesRemainingToCancel === undefined) { branchesRemainingToCancel = 0; } parent._branchesRemainingToCancel = branchesRemainingToCancel + 1; } if ((flags & 2) !== 0 && parent._isBound()) { this._setBoundTo(parent._boundTo); } } function bindingPropagateFrom(parent, flags) { if ((flags & 2) !== 0 && parent._isBound()) { this._setBoundTo(parent._boundTo); } } var propagateFromFunction = bindingPropagateFrom; function boundValueFunction() { var ret = this._boundTo; if (ret !== undefined) { if (ret instanceof Promise) { if (ret.isFulfilled()) { return ret.value(); } else { return undefined; } } } return ret; } function longStackTracesCaptureStackTrace() { this._trace = new CapturedTrace(this._peekContext()); } function longStackTracesAttachExtraTrace(error, ignoreSelf) { if (canAttachTrace(error)) { var trace = this._trace; if (trace !== undefined) { if (ignoreSelf) trace = trace._parent; } if (trace !== undefined) { trace.attachExtraTrace(error); } else if (!error.__stackCleaned__) { var parsed = parseStackAndMessage(error); util.notEnumerableProp(error, "stack", parsed.message + "\n" + parsed.stack.join("\n")); util.notEnumerableProp(error, "__stackCleaned__", true); } } } function checkForgottenReturns(returnValue, promiseCreated, name, promise, parent) { if (returnValue === undefined && promiseCreated !== null && wForgottenReturn) { if (parent !== undefined && parent._returnedNonUndefined()) return; if ((promise._bitField & 65535) === 0) return; if (name) name = name + " "; var msg = "a promise was created in a " + name + "handler but was not returned from it"; promise._warn(msg, true, promiseCreated); } } function deprecated(name, replacement) { var message = name + " is deprecated and will be removed in a future version."; if (replacement) message += " Use " + replacement + " instead."; return warn(message); } function warn(message, shouldUseOwnTrace, promise) { if (!config.warnings) return; var warning = new Warning(message); var ctx; if (shouldUseOwnTrace) { promise._attachExtraTrace(warning); } else if (config.longStackTraces && (ctx = Promise._peekContext())) { ctx.attachExtraTrace(warning); } else { var parsed = parseStackAndMessage(warning); warning.stack = parsed.message + "\n" + parsed.stack.join("\n"); } if (!activeFireEvent("warning", warning)) { formatAndLogError(warning, "", true); } } function reconstructStack(message, stacks) { for (var i = 0; i < stacks.length - 1; ++i) { stacks[i].push("From previous event:"); stacks[i] = stacks[i].join("\n"); } if (i < stacks.length) { stacks[i] = stacks[i].join("\n"); } return message + "\n" + stacks.join("\n"); } function removeDuplicateOrEmptyJumps(stacks) { for (var i = 0; i < stacks.length; ++i) { if (stacks[i].length === 0 || ((i + 1 < stacks.length) && stacks[i][0] === stacks[i+1][0])) { stacks.splice(i, 1); i--; } } } function removeCommonRoots(stacks) { var current = stacks[0]; for (var i = 1; i < stacks.length; ++i) { var prev = stacks[i]; var currentLastIndex = current.length - 1; var currentLastLine = current[currentLastIndex]; var commonRootMeetPoint = -1; for (var j = prev.length - 1; j >= 0; --j) { if (prev[j] === currentLastLine) { commonRootMeetPoint = j; break; } } for (var j = commonRootMeetPoint; j >= 0; --j) { var line = prev[j]; if (current[currentLastIndex] === line) { current.pop(); currentLastIndex--; } else { break; } } current = prev; } } function cleanStack(stack) { var ret = []; for (var i = 0; i < stack.length; ++i) { var line = stack[i]; var isTraceLine = " (No stack trace)" === line || stackFramePattern.test(line); var isInternalFrame = isTraceLine && shouldIgnore(line); if (isTraceLine && !isInternalFrame) { if (indentStackFrames && line.charAt(0) !== " ") { line = " " + line; } ret.push(line); } } return ret; } function stackFramesAsArray(error) { var stack = error.stack.replace(/\s+$/g, "").split("\n"); for (var i = 0; i < stack.length; ++i) { var line = stack[i]; if (" (No stack trace)" === line || stackFramePattern.test(line)) { break; } } if (i > 0) { stack = stack.slice(i); } return stack; } function parseStackAndMessage(error) { var stack = error.stack; var message = error.toString(); stack = typeof stack === "string" && stack.length > 0 ? stackFramesAsArray(error) : [" (No stack trace)"]; return { message: message, stack: cleanStack(stack) }; } function formatAndLogError(error, title, isSoft) { if (typeof console !== "undefined") { var message; if (util.isObject(error)) { var stack = error.stack; message = title + formatStack(stack, error); } else { message = title + String(error); } if (typeof printWarning === "function") { printWarning(message, isSoft); } else if (typeof console.log === "function" || typeof console.log === "object") { console.log(message); } } } function fireRejectionEvent(name, localHandler, reason, promise) { var localEventFired = false; try { if (typeof localHandler === "function") { localEventFired = true; if (name === "rejectionHandled") { localHandler(promise); } else { localHandler(reason, promise); } } } catch (e) { async.throwLater(e); } if (name === "unhandledRejection") { if (!activeFireEvent(name, reason, promise) && !localEventFired) { formatAndLogError(reason, "Unhandled rejection "); } } else { activeFireEvent(name, promise); } } function formatNonError(obj) { var str; if (typeof obj === "function") { str = "[function " + (obj.name || "anonymous") + "]"; } else { str = obj && typeof obj.toString === "function" ? obj.toString() : util.toString(obj); 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 longStackTracesIsSupported() { return typeof captureStackTrace === "function"; } var shouldIgnore = function() { return false; }; var parseLineInfoRegex = /[\/<\(]([^:\/]+):(\d+):(?:\d+)\)?\s*$/; function parseLineInfo(line) { var matches = line.match(parseLineInfoRegex); if (matches) { return { fileName: matches[1], line: parseInt(matches[2], 10) }; } } function setBounds(firstLineError, lastLineError) { if (!longStackTracesIsSupported()) return; var firstStackLines = firstLineError.stack.split("\n"); var lastStackLines = lastLineError.stack.split("\n"); var firstIndex = -1; var lastIndex = -1; var firstFileName; var lastFileName; for (var i = 0; i < firstStackLines.length; ++i) { var result = parseLineInfo(firstStackLines[i]); if (result) { firstFileName = result.fileName; firstIndex = result.line; break; } } for (var i = 0; i < lastStackLines.length; ++i) { var result = parseLineInfo(lastStackLines[i]); if (result) { lastFileName = result.fileName; lastIndex = result.line; break; } } if (firstIndex < 0 || lastIndex < 0 || !firstFileName || !lastFileName || firstFileName !== lastFileName || firstIndex >= lastIndex) { return; } shouldIgnore = function(line) { if (bluebirdFramePattern.test(line)) return true; var info = parseLineInfo(line); if (info) { if (info.fileName === firstFileName && (firstIndex <= info.line && info.line <= lastIndex)) { return true; } } return false; }; } function CapturedTrace(parent) { this._parent = parent; this._promisesCreated = 0; var length = this._length = 1 + (parent === undefined ? 0 : parent._length); captureStackTrace(this, CapturedTrace); if (length > 32) this.uncycle(); } util.inherits(CapturedTrace, Error); Context.CapturedTrace = CapturedTrace; CapturedTrace.prototype.uncycle = function() { var length = this._length; if (length < 2) return; var nodes = []; var stackToIndex = {}; for (var i = 0, node = this; node !== undefined; ++i) { nodes.push(node); node = node._parent; } length = this._length = i; for (var i = length - 1; i >= 0; --i) { var stack = nodes[i].stack; if (stackToIndex[stack] === undefined) { stackToIndex[stack] = i; } } for (var i = 0; i < length; ++i) { var currentStack = nodes[i].stack; var index = stackToIndex[currentStack]; if (index !== undefined && index !== i) { if (index > 0) { nodes[index - 1]._parent = undefined; nodes[index - 1]._length = 1; } nodes[i]._parent = undefined; nodes[i]._length = 1; var cycleEdgeNode = i > 0 ? nodes[i - 1] : this; if (index < length - 1) { cycleEdgeNode._parent = nodes[index + 1]; cycleEdgeNode._parent.uncycle(); cycleEdgeNode._length = cycleEdgeNode._parent._length + 1; } else { cycleEdgeNode._parent = undefined; cycleEdgeNode._length = 1; } var currentChildLength = cycleEdgeNode._length + 1; for (var j = i - 2; j >= 0; --j) { nodes[j]._length = currentChildLength; currentChildLength++; } return; } } }; CapturedTrace.prototype.attachExtraTrace = function(error) { if (error.__stackCleaned__) return; this.uncycle(); var parsed = parseStackAndMessage(error); var message = parsed.message; var stacks = [parsed.stack]; var trace = this; while (trace !== undefined) { stacks.push(cleanStack(trace.stack.split("\n"))); trace = trace._parent; } removeCommonRoots(stacks); removeDuplicateOrEmptyJumps(stacks); util.notEnumerableProp(error, "stack", reconstructStack(message, stacks)); util.notEnumerableProp(error, "__stackCleaned__", true); }; var captureStackTrace = (function stackDetection() { var v8stackFramePattern = /^\s*at\s*/; var v8stackFormatter = function(stack, error) { if (typeof stack === "string") return stack; if (error.name !== undefined && error.message !== undefined) { return error.toString(); } return formatNonError(error); }; if (typeof Error.stackTraceLimit === "number" && typeof Error.captureStackTrace === "function") { Error.stackTraceLimit += 6; stackFramePattern = v8stackFramePattern; formatStack = v8stackFormatter; var captureStackTrace = Error.captureStackTrace; shouldIgnore = function(line) { return bluebirdFramePattern.test(line); }; return function(receiver, ignoreUntil) { Error.stackTraceLimit += 6; captureStackTrace(receiver, ignoreUntil); Error.stackTraceLimit -= 6; }; } var err = new Error(); if (typeof err.stack === "string" && err.stack.split("\n")[0].indexOf("stackDetection@") >= 0) { stackFramePattern = /@/; formatStack = v8stackFormatter; indentStackFrames = true; return function captureStackTrace(o) { o.stack = new Error().stack; }; } var hasStackAfterThrow; try { throw new Error(); } catch(e) { hasStackAfterThrow = ("stack" in e); } if (!("stack" in err) && hasStackAfterThrow && typeof Error.stackTraceLimit === "number") { stackFramePattern = v8stackFramePattern; formatStack = v8stackFormatter; return function captureStackTrace(o) { Error.stackTraceLimit += 6; try { throw new Error(); } catch(e) { o.stack = e.stack; } Error.stackTraceLimit -= 6; }; } formatStack = function(stack, error) { if (typeof stack === "string") return stack; if ((typeof error === "object" || typeof error === "function") && error.name !== undefined && error.message !== undefined) { return error.toString(); } return formatNonError(error); }; return null; })([]); if (typeof console !== "undefined" && typeof console.warn !== "undefined") { printWarning = function (message) { console.warn(message); }; if (util.isNode && process.stderr.isTTY) { printWarning = function(message, isSoft) { var color = isSoft ? "\u001b[33m" : "\u001b[31m"; console.warn(color + message + "\u001b[0m\n"); }; } else if (!util.isNode && typeof (new Error().stack) === "string") { printWarning = function(message, isSoft) { console.warn("%c" + message, isSoft ? "color: darkorange" : "color: red"); }; } } var config = { warnings: warnings, longStackTraces: false, cancellation: false, monitoring: false }; if (longStackTraces) Promise.longStackTraces(); return { longStackTraces: function() { return config.longStackTraces; }, warnings: function() { return config.warnings; }, cancellation: function() { return config.cancellation; }, monitoring: function() { return config.monitoring; }, propagateFromFunction: function() { return propagateFromFunction; }, boundValueFunction: function() { return boundValueFunction; }, checkForgottenReturns: checkForgottenReturns, setBounds: setBounds, warn: warn, deprecated: deprecated, CapturedTrace: CapturedTrace, fireDomEvent: fireDomEvent, fireGlobalEvent: fireGlobalEvent }; }; },{"./errors":12,"./util":36}],10:[function(_dereq_,module,exports){ "use strict"; module.exports = function(Promise) { function returner() { return this.value; } function thrower() { throw this.reason; } Promise.prototype["return"] = Promise.prototype.thenReturn = function (value) { if (value instanceof Promise) value.suppressUnhandledRejections(); return this._then( returner, undefined, undefined, {value: value}, undefined); }; Promise.prototype["throw"] = Promise.prototype.thenThrow = function (reason) { return this._then( thrower, undefined, undefined, {reason: reason}, undefined); }; Promise.prototype.catchThrow = function (reason) { if (arguments.length <= 1) { return this._then( undefined, thrower, undefined, {reason: reason}, undefined); } else { var _reason = arguments[1]; var handler = function() {throw _reason;}; return this.caught(reason, handler); } }; Promise.prototype.catchReturn = function (value) { if (arguments.length <= 1) { if (value instanceof Promise) value.suppressUnhandledRejections(); return this._then( undefined, returner, undefined, {value: value}, undefined); } else { var _value = arguments[1]; if (_value instanceof Promise) _value.suppressUnhandledRejections(); var handler = function() {return _value;}; return this.caught(value, handler); } }; }; },{}],11:[function(_dereq_,module,exports){ "use strict"; module.exports = function(Promise, INTERNAL) { var PromiseReduce = Promise.reduce; var PromiseAll = Promise.all; function promiseAllThis() { return PromiseAll(this); } function PromiseMapSeries(promises, fn) { return PromiseReduce(promises, fn, INTERNAL, INTERNAL); } Promise.prototype.each = function (fn) { return this.mapSeries(fn) ._then(promiseAllThis, undefined, undefined, this, undefined); }; Promise.prototype.mapSeries = function (fn) { return PromiseReduce(this, fn, INTERNAL, INTERNAL); }; Promise.each = function (promises, fn) { return PromiseMapSeries(promises, fn) ._then(promiseAllThis, undefined, undefined, promises, undefined); }; Promise.mapSeries = PromiseMapSeries; }; },{}],12:[function(_dereq_,module,exports){ "use strict"; var es5 = _dereq_("./es5"); var Objectfreeze = es5.freeze; var util = _dereq_("./util"); var inherits = util.inherits; var notEnumerableProp = util.notEnumerableProp; function subError(nameProperty, defaultMessage) { function SubError(message) { if (!(this instanceof SubError)) return new SubError(message); notEnumerableProp(this, "message", typeof message === "string" ? message : defaultMessage); notEnumerableProp(this, "name", nameProperty); if (Error.captureStackTrace) { Error.captureStackTrace(this, this.constructor); } else { Error.call(this); } } inherits(SubError, Error); return SubError; } var _TypeError, _RangeError; var Warning = subError("Warning", "warning"); var CancellationError = subError("CancellationError", "cancellation error"); var TimeoutError = subError("TimeoutError", "timeout error"); var AggregateError = subError("AggregateError", "aggregate error"); try { _TypeError = TypeError; _RangeError = RangeError; } catch(e) { _TypeError = subError("TypeError", "type error"); _RangeError = subError("RangeError", "range error"); } var methods = ("join pop push shift unshift slice filter forEach some " + "every map indexOf lastIndexOf reduce reduceRight sort reverse").split(" "); for (var i = 0; i < methods.length; ++i) { if (typeof Array.prototype[methods[i]] === "function") { AggregateError.prototype[methods[i]] = Array.prototype[methods[i]]; } } es5.defineProperty(AggregateError.prototype, "length", { value: 0, configurable: false, writable: true, enumerable: true }); AggregateError.prototype["isOperational"] = true; var level = 0; AggregateError.prototype.toString = function() { var indent = Array(level * 4 + 1).join(" "); var ret = "\n" + indent + "AggregateError of:" + "\n"; level++; indent = Array(level * 4 + 1).join(" "); for (var i = 0; i < this.length; ++i) { var str = this[i] === this ? "[Circular AggregateError]" : this[i] + ""; var lines = str.split("\n"); for (var j = 0; j < lines.length; ++j) { lines[j] = indent + lines[j]; } str = lines.join("\n"); ret += str + "\n"; } level--; return ret; }; function OperationalError(message) { if (!(this instanceof OperationalError)) return new OperationalError(message); notEnumerableProp(this, "name", "OperationalError"); notEnumerableProp(this, "message", message); this.cause = message; this["isOperational"] = true; if (message instanceof Error) { notEnumerableProp(this, "message", message.message); notEnumerableProp(this, "stack", message.stack); } else if (Error.captureStackTrace) { Error.captureStackTrace(this, this.constructor); } } inherits(OperationalError, Error); var errorTypes = Error["__BluebirdErrorTypes__"]; if (!errorTypes) { errorTypes = Objectfreeze({ CancellationError: CancellationError, TimeoutError: TimeoutError, OperationalError: OperationalError, RejectionError: OperationalError, AggregateError: AggregateError }); es5.defineProperty(Error, "__BluebirdErrorTypes__", { value: errorTypes, writable: false, enumerable: false, configurable: false }); } module.exports = { Error: Error, TypeError: _TypeError, RangeError: _RangeError, CancellationError: errorTypes.CancellationError, OperationalError: errorTypes.OperationalError, TimeoutError: errorTypes.TimeoutError, AggregateError: errorTypes.AggregateError, Warning: Warning }; },{"./es5":13,"./util":36}],13:[function(_dereq_,module,exports){ var isES5 = (function(){ "use strict"; return this === undefined; })(); if (isES5) { module.exports = { freeze: Object.freeze, defineProperty: Object.defineProperty, getDescriptor: Object.getOwnPropertyDescriptor, keys: Object.keys, names: Object.getOwnPropertyNames, getPrototypeOf: Object.getPrototypeOf, isArray: Array.isArray, isES5: isES5, propertyIsWritable: function(obj, prop) { var descriptor = Object.getOwnPropertyDescriptor(obj, prop); return !!(!descriptor || descriptor.writable || descriptor.set); } }; } else { var has = {}.hasOwnProperty; var str = {}.toString; var proto = {}.constructor.prototype; var ObjectKeys = function (o) { var ret = []; for (var key in o) { if (has.call(o, key)) { ret.push(key); } } return ret; }; var ObjectGetDescriptor = function(o, key) { return {value: o[key]}; }; var ObjectDefineProperty = function (o, key, desc) { o[key] = desc.value; return o; }; var ObjectFreeze = function (obj) { return obj; }; var ObjectGetPrototypeOf = function (obj) { try { return Object(obj).constructor.prototype; } catch (e) { return proto; } }; var ArrayIsArray = function (obj) { try { return str.call(obj) === "[object Array]"; } catch(e) { return false; } }; module.exports = { isArray: ArrayIsArray, keys: ObjectKeys, names: ObjectKeys, defineProperty: ObjectDefineProperty, getDescriptor: ObjectGetDescriptor, freeze: ObjectFreeze, getPrototypeOf: ObjectGetPrototypeOf, isES5: isES5, propertyIsWritable: function() { return true; } }; } },{}],14:[function(_dereq_,module,exports){ "use strict"; module.exports = function(Promise, INTERNAL) { var PromiseMap = Promise.map; Promise.prototype.filter = function (fn, options) { return PromiseMap(this, fn, options, INTERNAL); }; Promise.filter = function (promises, fn, options) { return PromiseMap(promises, fn, options, INTERNAL); }; }; },{}],15:[function(_dereq_,module,exports){ "use strict"; module.exports = function(Promise, tryConvertToPromise) { var util = _dereq_("./util"); var CancellationError = Promise.CancellationError; var errorObj = util.errorObj; function PassThroughHandlerContext(promise, type, handler) { this.promise = promise; this.type = type; this.handler = handler; this.called = false; this.cancelPromise = null; } PassThroughHandlerContext.prototype.isFinallyHandler = function() { return this.type === 0; }; function FinallyHandlerCancelReaction(finallyHandler) { this.finallyHandler = finallyHandler; } FinallyHandlerCancelReaction.prototype._resultCancelled = function() { checkCancel(this.finallyHandler); }; function checkCancel(ctx, reason) { if (ctx.cancelPromise != null) { if (arguments.length > 1) { ctx.cancelPromise._reject(reason); } else { ctx.cancelPromise._cancel(); } ctx.cancelPromise = null; return true; } return false; } function succeed() { return finallyHandler.call(this, this.promise._target()._settledValue()); } function fail(reason) { if (checkCancel(this, reason)) return; errorObj.e = reason; return errorObj; } function finallyHandler(reasonOrValue) { var promise = this.promise; var handler = this.handler; if (!this.called) { this.called = true; var ret = this.isFinallyHandler() ? handler.call(promise._boundValue()) : handler.call(promise._boundValue(), reasonOrValue); if (ret !== undefined) { promise._setReturnedNonUndefined(); var maybePromise = tryConvertToPromise(ret, promise); if (maybePromise instanceof Promise) { if (this.cancelPromise != null) { if (maybePromise.isCancelled()) { var reason = new CancellationError("late cancellation observer"); promise._attachExtraTrace(reason); errorObj.e = reason; return errorObj; } else if (maybePromise.isPending()) { maybePromise._attachCancellationCallback( new FinallyHandlerCancelReaction(this)); } } return maybePromise._then( succeed, fail, undefined, this, undefined); } } } if (promise.isRejected()) { checkCancel(this); errorObj.e = reasonOrValue; return errorObj; } else { checkCancel(this); return reasonOrValue; } } Promise.prototype._passThrough = function(handler, type, success, fail) { if (typeof handler !== "function") return this.then(); return this._then(success, fail, undefined, new PassThroughHandlerContext(this, type, handler), undefined); }; Promise.prototype.lastly = Promise.prototype["finally"] = function (handler) { return this._passThrough(handler, 0, finallyHandler, finallyHandler); }; Promise.prototype.tap = function (handler) { return this._passThrough(handler, 1, finallyHandler); }; return PassThroughHandlerContext; }; },{"./util":36}],16:[function(_dereq_,module,exports){ "use strict"; module.exports = function(Promise, apiRejection, INTERNAL, tryConvertToPromise, Proxyable, debug) { var errors = _dereq_("./errors"); var TypeError = errors.TypeError; var util = _dereq_("./util"); var errorObj = util.errorObj; var tryCatch = util.tryCatch; var yieldHandlers = []; function promiseFromYieldHandler(value, yieldHandlers, traceParent) { for (var i = 0; i < yieldHandlers.length; ++i) { traceParent._pushContext(); var result = tryCatch(yieldHandlers[i])(value); traceParent._popContext(); if (result === errorObj) { traceParent._pushContext(); var ret = Promise.reject(errorObj.e); traceParent._popContext(); return ret; } var maybePromise = tryConvertToPromise(result, traceParent); if (maybePromise instanceof Promise) return maybePromise; } return null; } function PromiseSpawn(generatorFunction, receiver, yieldHandler, stack) { if (debug.cancellation()) { var internal = new Promise(INTERNAL); var _finallyPromise = this._finallyPromise = new Promise(INTERNAL); this._promise = internal.lastly(function() { return _finallyPromise; }); internal._captureStackTrace(); internal._setOnCancel(this); } else { var promise = this._promise = new Promise(INTERNAL); promise._captureStackTrace(); } this._stack = stack; this._generatorFunction = generatorFunction; this._receiver = receiver; this._generator = undefined; this._yieldHandlers = typeof yieldHandler === "function" ? [yieldHandler].concat(yieldHandlers) : yieldHandlers; this._yieldedPromise = null; this._cancellationPhase = false; } util.inherits(PromiseSpawn, Proxyable); PromiseSpawn.prototype._isResolved = function() { return this._promise === null; }; PromiseSpawn.prototype._cleanup = function() { this._promise = this._generator = null; if (debug.cancellation() && this._finallyPromise !== null) { this._finallyPromise._fulfill(); this._finallyPromise = null; } }; PromiseSpawn.prototype._promiseCancelled = function() { if (this._isResolved()) return; var implementsReturn = typeof this._generator["return"] !== "undefined"; var result; if (!implementsReturn) { var reason = new Promise.CancellationError( "generator .return() sentinel"); Promise.coroutine.returnSentinel = reason; this._promise._attachExtraTrace(reason); this._promise._pushContext(); result = tryCatch(this._generator["throw"]).call(this._generator, reason); this._promise._popContext(); } else { this._promise._pushContext(); result = tryCatch(this._generator["return"]).call(this._generator, undefined); this._promise._popContext(); } this._cancellationPhase = true; this._yieldedPromise = null; this._continue(result); }; PromiseSpawn.prototype._promiseFulfilled = function(value) { this._yieldedPromise = null; this._promise._pushContext(); var result = tryCatch(this._generator.next).call(this._generator, value); this._promise._popContext(); this._continue(result); }; PromiseSpawn.prototype._promiseRejected = function(reason) { this._yieldedPromise = null; this._promise._attachExtraTrace(reason); this._promise._pushContext(); var result = tryCatch(this._generator["throw"]) .call(this._generator, reason); this._promise._popContext(); this._continue(result); }; PromiseSpawn.prototype._resultCancelled = function() { if (this._yieldedPromise instanceof Promise) { var promise = this._yieldedPromise; this._yieldedPromise = null; promise.cancel(); } }; PromiseSpawn.prototype.promise = function () { return this._promise; }; PromiseSpawn.prototype._run = function () { this._generator = this._generatorFunction.call(this._receiver); this._receiver = this._generatorFunction = undefined; this._promiseFulfilled(undefined); }; PromiseSpawn.prototype._continue = function (result) { var promise = this._promise; if (result === errorObj) { this._cleanup(); if (this._cancellationPhase) { return promise.cancel(); } else { return promise._rejectCallback(result.e, false); } } var value = result.value; if (result.done === true) { this._cleanup(); if (this._cancellationPhase) { return promise.cancel(); } else { return promise._resolveCallback(value); } } else { var maybePromise = tryConvertToPromise(value, this._promise); if (!(maybePromise instanceof Promise)) { maybePromise = promiseFromYieldHandler(maybePromise, this._yieldHandlers, this._promise); if (maybePromise === null) { this._promiseRejected( new TypeError( "A value %s was yielded that could not be treated as a promise\u000a\u000a See http://goo.gl/MqrFmX\u000a\u000a".replace("%s", value) + "From coroutine:\u000a" + this._stack.split("\n").slice(1, -7).join("\n") ) ); return; } } maybePromise = maybePromise._target(); var bitField = maybePromise._bitField; ; if (((bitField & 50397184) === 0)) { this._yieldedPromise = maybePromise; maybePromise._proxy(this, null); } else if (((bitField & 33554432) !== 0)) { this._promiseFulfilled(maybePromise._value()); } else if (((bitField & 16777216) !== 0)) { this._promiseRejected(maybePromise._reason()); } else { this._promiseCancelled(); } } }; Promise.coroutine = function (generatorFunction, options) { if (typeof generatorFunction !== "function") { throw new TypeError("generatorFunction must be a function\u000a\u000a See http://goo.gl/MqrFmX\u000a"); } var yieldHandler = Object(options).yieldHandler; var PromiseSpawn$ = PromiseSpawn; var stack = new Error().stack; return function () { var generator = generatorFunction.apply(this, arguments); var spawn = new PromiseSpawn$(undefined, undefined, yieldHandler, stack); var ret = spawn.promise(); spawn._generator = generator; spawn._promiseFulfilled(undefined); return ret; }; }; Promise.coroutine.addYieldHandler = function(fn) { if (typeof fn !== "function") { throw new TypeError("expecting a function but got " + util.classString(fn)); } yieldHandlers.push(fn); }; Promise.spawn = function (generatorFunction) { debug.deprecated("Promise.spawn()", "Promise.coroutine()"); if (typeof generatorFunction !== "function") { return apiRejection("generatorFunction must be a function\u000a\u000a See http://goo.gl/MqrFmX\u000a"); } var spawn = new PromiseSpawn(generatorFunction, this); var ret = spawn.promise(); spawn._run(Promise.spawn); return ret; }; }; },{"./errors":12,"./util":36}],17:[function(_dereq_,module,exports){ "use strict"; module.exports = function(Promise, PromiseArray, tryConvertToPromise, INTERNAL) { var util = _dereq_("./util"); var canEvaluate = util.canEvaluate; var tryCatch = util.tryCatch; var errorObj = util.errorObj; var reject; if (false) { if (canEvaluate) { var thenCallback = function(i) { return new Function("value", "holder", " \n\ 'use strict'; \n\ holder.pIndex = value; \n\ holder.checkFulfillment(this); \n\ ".replace(/Index/g, i)); }; var promiseSetter = function(i) { return new Function("promise", "holder", " \n\ 'use strict'; \n\ holder.pIndex = promise; \n\ ".replace(/Index/g, i)); }; var generateHolderClass = function(total) { var props = new Array(total); for (var i = 0; i < props.length; ++i) { props[i] = "this.p" + (i+1); } var assignment = props.join(" = ") + " = null;"; var cancellationCode= "var promise;\n" + props.map(function(prop) { return " \n\ promise = " + prop + "; \n\ if (promise instanceof Promise) { \n\ promise.cancel(); \n\ } \n\ "; }).join("\n"); var passedArguments = props.join(", "); var name = "Holder$" + total; var code = "return function(tryCatch, errorObj, Promise) { \n\ 'use strict'; \n\ function [TheName](fn) { \n\ [TheProperties] \n\ this.fn = fn; \n\ this.now = 0; \n\ } \n\ [TheName].prototype.checkFulfillment = function(promise) { \n\ var now = ++this.now; \n\ if (now === [TheTotal]) { \n\ promise._pushContext(); \n\ var callback = this.fn; \n\ var ret = tryCatch(callback)([ThePassedArguments]); \n\ promise._popContext(); \n\ if (ret === errorObj) { \n\ promise._rejectCallback(ret.e, false); \n\ } else { \n\ promise._resolveCallback(ret); \n\ } \n\ } \n\ }; \n\ \n\ [TheName].prototype._resultCancelled = function() { \n\ [CancellationCode] \n\ }; \n\ \n\ return [TheName]; \n\ }(tryCatch, errorObj, Promise); \n\ "; code = code.replace(/\[TheName\]/g, name) .replace(/\[TheTotal\]/g, total) .replace(/\[ThePassedArguments\]/g, passedArguments) .replace(/\[TheProperties\]/g, assignment) .replace(/\[CancellationCode\]/g, cancellationCode); return new Function("tryCatch", "errorObj", "Promise", code) (tryCatch, errorObj, Promise); }; var holderClasses = []; var thenCallbacks = []; var promiseSetters = []; for (var i = 0; i < 8; ++i) { holderClasses.push(generateHolderClass(i + 1)); thenCallbacks.push(thenCallback(i + 1)); promiseSetters.push(promiseSetter(i + 1)); } reject = function (reason) { this._reject(reason); }; }} Promise.join = function () { var last = arguments.length - 1; var fn; if (last > 0 && typeof arguments[last] === "function") { fn = arguments[last]; if (false) { if (last <= 8 && canEvaluate) { var ret = new Promise(INTERNAL); ret._captureStackTrace(); var HolderClass = holderClasses[last - 1]; var holder = new HolderClass(fn); var callbacks = thenCallbacks; for (var i = 0; i < last; ++i) { var maybePromise = tryConvertToPromise(arguments[i], ret); if (maybePromise instanceof Promise) { maybePromise = maybePromise._target(); var bitField = maybePromise._bitField; ; if (((bitField & 50397184) === 0)) { maybePromise._then(callbacks[i], reject, undefined, ret, holder); promiseSetters[i](maybePromise, holder); } else if (((bitField & 33554432) !== 0)) { callbacks[i].call(ret, maybePromise._value(), holder); } else if (((bitField & 16777216) !== 0)) { ret._reject(maybePromise._reason()); } else { ret._cancel(); } } else { callbacks[i].call(ret, maybePromise, holder); } } if (!ret._isFateSealed()) { ret._setAsyncGuaranteed(); ret._setOnCancel(holder); } return ret; } } } var args = [].slice.call(arguments);; if (fn) args.pop(); var ret = new PromiseArray(args).promise(); return fn !== undefined ? ret.spread(fn) : ret; }; }; },{"./util":36}],18:[function(_dereq_,module,exports){ "use strict"; module.exports = function(Promise, PromiseArray, apiRejection, tryConvertToPromise, INTERNAL, debug) { var getDomain = Promise._getDomain; var util = _dereq_("./util"); var tryCatch = util.tryCatch; var errorObj = util.errorObj; var EMPTY_ARRAY = []; function MappingPromiseArray(promises, fn, limit, _filter) { this.constructor$(promises); this._promise._captureStackTrace(); var domain = getDomain(); this._callback = domain === null ? fn : domain.bind(fn); this._preservedValues = _filter === INTERNAL ? new Array(this.length()) : null; this._limit = limit; this._inFlight = 0; this._queue = limit >= 1 ? [] : EMPTY_ARRAY; this._init$(undefined, -2); } util.inherits(MappingPromiseArray, PromiseArray); MappingPromiseArray.prototype._init = function () {}; MappingPromiseArray.prototype._promiseFulfilled = function (value, index) { var values = this._values; var length = this.length(); var preservedValues = this._preservedValues; var limit = this._limit; if (index < 0) { index = (index * -1) - 1; values[index] = value; if (limit >= 1) { this._inFlight--; this._drainQueue(); if (this._isResolved()) return true; } } else { if (limit >= 1 && this._inFlight >= limit) { values[index] = value; this._queue.push(index); return false; } if (preservedValues !== null) preservedValues[index] = value; var promise = this._promise; var callback = this._callback; var receiver = promise._boundValue(); promise._pushContext(); var ret = tryCatch(callback).call(receiver, value, index, length); var promiseCreated = promise._popContext(); debug.checkForgottenReturns( ret, promiseCreated, preservedValues !== null ? "Promise.filter" : "Promise.map", promise ); if (ret === errorObj) { this._reject(ret.e); return true; } var maybePromise = tryConvertToPromise(ret, this._promise); if (maybePromise instanceof Promise) { maybePromise = maybePromise._target(); var bitField = maybePromise._bitField; ; if (((bitField & 50397184) === 0)) { if (limit >= 1) this._inFlight++; values[index] = maybePromise; maybePromise._proxy(this, (index + 1) * -1); return false; } else if (((bitField & 33554432) !== 0)) { ret = maybePromise._value(); } else if (((bitField & 16777216) !== 0)) { this._reject(maybePromise._reason()); return true; } else { this._cancel(); return true; } } values[index] = ret; } var totalResolved = ++this._totalResolved; if (totalResolved >= length) { if (preservedValues !== null) { this._filter(values, preservedValues); } else { this._resolve(values); } return true; } return false; }; MappingPromiseArray.prototype._drainQueue = function () { var queue = this._queue; var limit = this._limit; var values = this._values; while (queue.length > 0 && this._inFlight < limit) { if (this._isResolved()) return; var index = queue.pop(); this._promiseFulfilled(values[index], index); } }; MappingPromiseArray.prototype._filter = function (booleans, values) { 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; this._resolve(ret); }; MappingPromiseArray.prototype.preservedValues = function () { return this._preservedValues; }; function map(promises, fn, options, _filter) { if (typeof fn !== "function") { return apiRejection("expecting a function but got " + util.classString(fn)); } var limit = typeof options === "object" && options !== null ? options.concurrency : 0; limit = typeof limit === "number" && isFinite(limit) && limit >= 1 ? limit : 0; return new MappingPromiseArray(promises, fn, limit, _filter).promise(); } Promise.prototype.map = function (fn, options) { return map(this, fn, options, null); }; Promise.map = function (promises, fn, options, _filter) { return map(promises, fn, options, _filter); }; }; },{"./util":36}],19:[function(_dereq_,module,exports){ "use strict"; module.exports = function(Promise, INTERNAL, tryConvertToPromise, apiRejection, debug) { var util = _dereq_("./util"); var tryCatch = util.tryCatch; Promise.method = function (fn) { if (typeof fn !== "function") { throw new Promise.TypeError("expecting a function but got " + util.classString(fn)); } return function () { var ret = new Promise(INTERNAL); ret._captureStackTrace(); ret._pushContext(); var value = tryCatch(fn).apply(this, arguments); var promiseCreated = ret._popContext(); debug.checkForgottenReturns( value, promiseCreated, "Promise.method", ret); ret._resolveFromSyncValue(value); return ret; }; }; Promise.attempt = Promise["try"] = function (fn) { if (typeof fn !== "function") { return apiRejection("expecting a function but got " + util.classString(fn)); } var ret = new Promise(INTERNAL); ret._captureStackTrace(); ret._pushContext(); var value; if (arguments.length > 1) { debug.deprecated("calling Promise.try with more than 1 argument"); var arg = arguments[1]; var ctx = arguments[2]; value = util.isArray(arg) ? tryCatch(fn).apply(ctx, arg) : tryCatch(fn).call(ctx, arg); } else { value = tryCatch(fn)(); } var promiseCreated = ret._popContext(); debug.checkForgottenReturns( value, promiseCreated, "Promise.try", ret); ret._resolveFromSyncValue(value); return ret; }; Promise.prototype._resolveFromSyncValue = function (value) { if (value === util.errorObj) { this._rejectCallback(value.e, false); } else { this._resolveCallback(value, true); } }; }; },{"./util":36}],20:[function(_dereq_,module,exports){ "use strict"; var util = _dereq_("./util"); var maybeWrapAsError = util.maybeWrapAsError; var errors = _dereq_("./errors"); var OperationalError = errors.OperationalError; var es5 = _dereq_("./es5"); function isUntypedError(obj) { return obj instanceof Error && es5.getPrototypeOf(obj) === Error.prototype; } var rErrorKey = /^(?:name|message|stack|cause)$/; function wrapAsOperationalError(obj) { var ret; if (isUntypedError(obj)) { ret = new OperationalError(obj); ret.name = obj.name; ret.message = obj.message; ret.stack = obj.stack; var keys = es5.keys(obj); for (var i = 0; i < keys.length; ++i) { var key = keys[i]; if (!rErrorKey.test(key)) { ret[key] = obj[key]; } } return ret; } util.markAsOriginatingFromRejection(obj); return obj; } function nodebackForPromise(promise, multiArgs) { return function(err, value) { if (promise === null) return; if (err) { var wrapped = wrapAsOperationalError(maybeWrapAsError(err)); promise._attachExtraTrace(wrapped); promise._reject(wrapped); } else if (!multiArgs) { promise._fulfill(value); } else { var args = [].slice.call(arguments, 1);; promise._fulfill(args); } promise = null; }; } module.exports = nodebackForPromise; },{"./errors":12,"./es5":13,"./util":36}],21:[function(_dereq_,module,exports){ "use strict"; module.exports = function(Promise) { var util = _dereq_("./util"); var async = Promise._async; var tryCatch = util.tryCatch; var errorObj = util.errorObj; function spreadAdapter(val, nodeback) { var promise = this; if (!util.isArray(val)) return successAdapter.call(promise, val, nodeback); var ret = tryCatch(nodeback).apply(promise._boundValue(), [null].concat(val)); if (ret === errorObj) { async.throwLater(ret.e); } } function successAdapter(val, nodeback) { var promise = this; var receiver = promise._boundValue(); var ret = val === undefined ? tryCatch(nodeback).call(receiver, null) : tryCatch(nodeback).call(receiver, null, val); if (ret === errorObj) { async.throwLater(ret.e); } } function errorAdapter(reason, nodeback) { var promise = this; if (!reason) { var newReason = new Error(reason + ""); newReason.cause = reason; reason = newReason; } var ret = tryCatch(nodeback).call(promise._boundValue(), reason); if (ret === errorObj) { async.throwLater(ret.e); } } Promise.prototype.asCallback = Promise.prototype.nodeify = function (nodeback, options) { if (typeof nodeback == "function") { var adapter = successAdapter; if (options !== undefined && Object(options).spread) { adapter = spreadAdapter; } this._then( adapter, errorAdapter, undefined, this, nodeback ); } return this; }; }; },{"./util":36}],22:[function(_dereq_,module,exports){ "use strict"; module.exports = function() { var makeSelfResolutionError = function () { return new TypeError("circular promise resolution chain\u000a\u000a See http://goo.gl/MqrFmX\u000a"); }; var reflectHandler = function() { return new Promise.PromiseInspection(this._target()); }; var apiRejection = function(msg) { return Promise.reject(new TypeError(msg)); }; function Proxyable() {} var UNDEFINED_BINDING = {}; var util = _dereq_("./util"); var getDomain; if (util.isNode) { getDomain = function() { var ret = process.domain; if (ret === undefined) ret = null; return ret; }; } else { getDomain = function() { return null; }; } util.notEnumerableProp(Promise, "_getDomain", getDomain); var es5 = _dereq_("./es5"); var Async = _dereq_("./async"); var async = new Async(); es5.defineProperty(Promise, "_async", {value: async}); var errors = _dereq_("./errors"); var TypeError = Promise.TypeError = errors.TypeError; Promise.RangeError = errors.RangeError; var CancellationError = Promise.CancellationError = errors.CancellationError; Promise.TimeoutError = errors.TimeoutError; Promise.OperationalError = errors.OperationalError; Promise.RejectionError = errors.OperationalError; Promise.AggregateError = errors.AggregateError; var INTERNAL = function(){}; var APPLY = {}; var NEXT_FILTER = {}; var tryConvertToPromise = _dereq_("./thenables")(Promise, INTERNAL); var PromiseArray = _dereq_("./promise_array")(Promise, INTERNAL, tryConvertToPromise, apiRejection, Proxyable); var Context = _dereq_("./context")(Promise); /*jshint unused:false*/ var createContext = Context.create; var debug = _dereq_("./debuggability")(Promise, Context); var CapturedTrace = debug.CapturedTrace; var PassThroughHandlerContext = _dereq_("./finally")(Promise, tryConvertToPromise); var catchFilter = _dereq_("./catch_filter")(NEXT_FILTER); var nodebackForPromise = _dereq_("./nodeback"); var errorObj = util.errorObj; var tryCatch = util.tryCatch; function check(self, executor) { if (typeof executor !== "function") { throw new TypeError("expecting a function but got " + util.classString(executor)); } if (self.constructor !== Promise) { throw new TypeError("the promise constructor cannot be invoked directly\u000a\u000a See http://goo.gl/MqrFmX\u000a"); } } function Promise(executor) { this._bitField = 0; this._fulfillmentHandler0 = undefined; this._rejectionHandler0 = undefined; this._promise0 = undefined; this._receiver0 = undefined; if (executor !== INTERNAL) { check(this, executor); this._resolveFromExecutor(executor); } this._promiseCreated(); this._fireEvent("promiseCreated", this); } Promise.prototype.toString = function () { return "[object Promise]"; }; Promise.prototype.caught = Promise.prototype["catch"] = function (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 (util.isObject(item)) { catchInstances[j++] = item; } else { return apiRejection("expecting an object but got " + util.classString(item)); } } catchInstances.length = j; fn = arguments[i]; return this.then(undefined, catchFilter(catchInstances, fn, this)); } return this.then(undefined, fn); }; Promise.prototype.reflect = function () { return this._then(reflectHandler, reflectHandler, undefined, this, undefined); }; Promise.prototype.then = function (didFulfill, didReject) { if (debug.warnings() && arguments.length > 0 && typeof didFulfill !== "function" && typeof didReject !== "function") { var msg = ".then() only accepts functions but was passed: " + util.classString(didFulfill); if (arguments.length > 1) { msg += ", " + util.classString(didReject); } this._warn(msg); } return this._then(didFulfill, didReject, undefined, undefined, undefined); }; Promise.prototype.done = function (didFulfill, didReject) { var promise = this._then(didFulfill, didReject, undefined, undefined, undefined); promise._setIsFinal(); }; Promise.prototype.spread = function (fn) { if (typeof fn !== "function") { return apiRejection("expecting a function but got " + util.classString(fn)); } return this.all()._then(fn, undefined, undefined, APPLY, undefined); }; Promise.prototype.toJSON = function () { var ret = { isFulfilled: false, isRejected: false, fulfillmentValue: undefined, rejectionReason: undefined }; if (this.isFulfilled()) { ret.fulfillmentValue = this.value(); ret.isFulfilled = true; } else if (this.isRejected()) { ret.rejectionReason = this.reason(); ret.isRejected = true; } return ret; }; Promise.prototype.all = function () { if (arguments.length > 0) { this._warn(".all() was passed arguments but it does not take any"); } return new PromiseArray(this).promise(); }; Promise.prototype.error = function (fn) { return this.caught(util.originatesFromRejection, fn); }; Promise.is = function (val) { return val instanceof Promise; }; Promise.fromNode = Promise.fromCallback = function(fn) { var ret = new Promise(INTERNAL); ret._captureStackTrace(); var multiArgs = arguments.length > 1 ? !!Object(arguments[1]).multiArgs : false; var result = tryCatch(fn)(nodebackForPromise(ret, multiArgs)); if (result === errorObj) { ret._rejectCallback(result.e, true); } if (!ret._isFateSealed()) ret._setAsyncGuaranteed(); return ret; }; Promise.all = function (promises) { return new PromiseArray(promises).promise(); }; Promise.cast = function (obj) { var ret = tryConvertToPromise(obj); if (!(ret instanceof Promise)) { ret = new Promise(INTERNAL); ret._captureStackTrace(); ret._setFulfilled(); ret._rejectionHandler0 = obj; } return ret; }; Promise.resolve = Promise.fulfilled = Promise.cast; Promise.reject = Promise.rejected = function (reason) { var ret = new Promise(INTERNAL); ret._captureStackTrace(); ret._rejectCallback(reason, true); return ret; }; Promise.setScheduler = function(fn) { if (typeof fn !== "function") { throw new TypeError("expecting a function but got " + util.classString(fn)); } return async.setScheduler(fn); }; Promise.prototype._then = function ( didFulfill, didReject, _, receiver, internalData ) { var haveInternalData = internalData !== undefined; var promise = haveInternalData ? internalData : new Promise(INTERNAL); var target = this._target(); var bitField = target._bitField; if (!haveInternalData) { promise._propagateFrom(this, 3); promise._captureStackTrace(); if (receiver === undefined && ((this._bitField & 2097152) !== 0)) { if (!((bitField & 50397184) === 0)) { receiver = this._boundValue(); } else { receiver = target === this ? undefined : this._boundTo; } } this._fireEvent("promiseChained", this, promise); } var domain = getDomain(); if (!((bitField & 50397184) === 0)) { var handler, value, settler = target._settlePromiseCtx; if (((bitField & 33554432) !== 0)) { value = target._rejectionHandler0; handler = didFulfill; } else if (((bitField & 16777216) !== 0)) { value = target._fulfillmentHandler0; handler = didReject; target._unsetRejectionIsUnhandled(); } else { settler = target._settlePromiseLateCancellationObserver; value = new CancellationError("late cancellation observer"); target._attachExtraTrace(value); handler = didReject; } async.invoke(settler, target, { handler: domain === null ? handler : (typeof handler === "function" && domain.bind(handler)), promise: promise, receiver: receiver, value: value }); } else { target._addCallbacks(didFulfill, didReject, promise, receiver, domain); } return promise; }; Promise.prototype._length = function () { return this._bitField & 65535; }; Promise.prototype._isFateSealed = function () { return (this._bitField & 117506048) !== 0; }; Promise.prototype._isFollowing = function () { return (this._bitField & 67108864) === 67108864; }; Promise.prototype._setLength = function (len) { this._bitField = (this._bitField & -65536) | (len & 65535); }; Promise.prototype._setFulfilled = function () { this._bitField = this._bitField | 33554432; this._fireEvent("promiseFulfilled", this); }; Promise.prototype._setRejected = function () { this._bitField = this._bitField | 16777216; this._fireEvent("promiseRejected", this); }; Promise.prototype._setFollowing = function () { this._bitField = this._bitField | 67108864; this._fireEvent("promiseResolved", this); }; Promise.prototype._setIsFinal = function () { this._bitField = this._bitField | 4194304; }; Promise.prototype._isFinal = function () { return (this._bitField & 4194304) > 0; }; Promise.prototype._unsetCancelled = function() { this._bitField = this._bitField & (~65536); }; Promise.prototype._setCancelled = function() { this._bitField = this._bitField | 65536; this._fireEvent("promiseCancelled", this); }; Promise.prototype._setAsyncGuaranteed = function() { if (async.hasCustomScheduler()) return; this._bitField = this._bitField | 134217728; }; Promise.prototype._receiverAt = function (index) { var ret = index === 0 ? this._receiver0 : this[ index * 4 - 4 + 3]; if (ret === UNDEFINED_BINDING) { return undefined; } else if (ret === undefined && this._isBound()) { return this._boundValue(); } return ret; }; Promise.prototype._promiseAt = function (index) { return this[ index * 4 - 4 + 2]; }; Promise.prototype._fulfillmentHandlerAt = function (index) { return this[ index * 4 - 4 + 0]; }; Promise.prototype._rejectionHandlerAt = function (index) { return this[ index * 4 - 4 + 1]; }; Promise.prototype._boundValue = function() {}; Promise.prototype._migrateCallback0 = function (follower) { var bitField = follower._bitField; var fulfill = follower._fulfillmentHandler0; var reject = follower._rejectionHandler0; var promise = follower._promise0; var receiver = follower._receiverAt(0); if (receiver === undefined) receiver = UNDEFINED_BINDING; this._addCallbacks(fulfill, reject, promise, receiver, null); }; Promise.prototype._migrateCallbackAt = function (follower, index) { var fulfill = follower._fulfillmentHandlerAt(index); var reject = follower._rejectionHandlerAt(index); var promise = follower._promiseAt(index); var receiver = follower._receiverAt(index); if (receiver === undefined) receiver = UNDEFINED_BINDING; this._addCallbacks(fulfill, reject, promise, receiver, null); }; Promise.prototype._addCallbacks = function ( fulfill, reject, promise, receiver, domain ) { var index = this._length(); if (index >= 65535 - 4) { index = 0; this._setLength(0); } if (index === 0) { this._promise0 = promise; this._receiver0 = receiver; if (typeof fulfill === "function") { this._fulfillmentHandler0 = domain === null ? fulfill : domain.bind(fulfill); } if (typeof reject === "function") { this._rejectionHandler0 = domain === null ? reject : domain.bind(reject); } } else { var base = index * 4 - 4; this[base + 2] = promise; this[base + 3] = receiver; if (typeof fulfill === "function") { this[base + 0] = domain === null ? fulfill : domain.bind(fulfill); } if (typeof reject === "function") { this[base + 1] = domain === null ? reject : domain.bind(reject); } } this._setLength(index + 1); return index; }; Promise.prototype._proxy = function (proxyable, arg) { this._addCallbacks(undefined, undefined, arg, proxyable, null); }; Promise.prototype._resolveCallback = function(value, shouldBind) { if (((this._bitField & 117506048) !== 0)) return; if (value === this) return this._rejectCallback(makeSelfResolutionError(), false); var maybePromise = tryConvertToPromise(value, this); if (!(maybePromise instanceof Promise)) return this._fulfill(value); if (shouldBind) this._propagateFrom(maybePromise, 2); var promise = maybePromise._target(); if (promise === this) { this._reject(makeSelfResolutionError()); return; } var bitField = promise._bitField; if (((bitField & 50397184) === 0)) { var len = this._length(); if (len > 0) promise._migrateCallback0(this); for (var i = 1; i < len; ++i) { promise._migrateCallbackAt(this, i); } this._setFollowing(); this._setLength(0); this._setFollowee(promise); } else if (((bitField & 33554432) !== 0)) { this._fulfill(promise._value()); } else if (((bitField & 16777216) !== 0)) { this._reject(promise._reason()); } else { var reason = new CancellationError("late cancellation observer"); promise._attachExtraTrace(reason); this._reject(reason); } }; Promise.prototype._rejectCallback = function(reason, synchronous, ignoreNonErrorWarnings) { var trace = util.ensureErrorObject(reason); var hasStack = trace === reason; if (!hasStack && !ignoreNonErrorWarnings && debug.warnings()) { var message = "a promise was rejected with a non-error: " + util.classString(reason); this._warn(message, true); } this._attachExtraTrace(trace, synchronous ? hasStack : false); this._reject(reason); }; Promise.prototype._resolveFromExecutor = function (executor) { var promise = this; this._captureStackTrace(); this._pushContext(); var synchronous = true; var r = this._execute(executor, function(value) { promise._resolveCallback(value); }, function (reason) { promise._rejectCallback(reason, synchronous); }); synchronous = false; this._popContext(); if (r !== undefined) { promise._rejectCallback(r, true); } }; Promise.prototype._settlePromiseFromHandler = function ( handler, receiver, value, promise ) { var bitField = promise._bitField; if (((bitField & 65536) !== 0)) return; promise._pushContext(); var x; if (receiver === APPLY) { if (!value || typeof value.length !== "number") { x = errorObj; x.e = new TypeError("cannot .spread() a non-array: " + util.classString(value)); } else { x = tryCatch(handler).apply(this._boundValue(), value); } } else { x = tryCatch(handler).call(receiver, value); } var promiseCreated = promise._popContext(); bitField = promise._bitField; if (((bitField & 65536) !== 0)) return; if (x === NEXT_FILTER) { promise._reject(value); } else if (x === errorObj) { promise._rejectCallback(x.e, false); } else { debug.checkForgottenReturns(x, promiseCreated, "", promise, this); promise._resolveCallback(x); } }; Promise.prototype._target = function() { var ret = this; while (ret._isFollowing()) ret = ret._followee(); return ret; }; Promise.prototype._followee = function() { return this._rejectionHandler0; }; Promise.prototype._setFollowee = function(promise) { this._rejectionHandler0 = promise; }; Promise.prototype._settlePromise = function(promise, handler, receiver, value) { var isPromise = promise instanceof Promise; var bitField = this._bitField; var asyncGuaranteed = ((bitField & 134217728) !== 0); if (((bitField & 65536) !== 0)) { if (isPromise) promise._invokeInternalOnCancel(); if (receiver instanceof PassThroughHandlerContext && receiver.isFinallyHandler()) { receiver.cancelPromise = promise; if (tryCatch(handler).call(receiver, value) === errorObj) { promise._reject(errorObj.e); } } else if (handler === reflectHandler) { promise._fulfill(reflectHandler.call(receiver)); } else if (receiver instanceof Proxyable) { receiver._promiseCancelled(promise); } else if (isPromise || promise instanceof PromiseArray) { promise._cancel(); } else { receiver.cancel(); } } else if (typeof handler === "function") { if (!isPromise) { handler.call(receiver, value, promise); } else { if (asyncGuaranteed) promise._setAsyncGuaranteed(); this._settlePromiseFromHandler(handler, receiver, value, promise); } } else if (receiver instanceof Proxyable) { if (!receiver._isResolved()) { if (((bitField & 33554432) !== 0)) { receiver._promiseFulfilled(value, promise); } else { receiver._promiseRejected(value, promise); } } } else if (isPromise) { if (asyncGuaranteed) promise._setAsyncGuaranteed(); if (((bitField & 33554432) !== 0)) { promise._fulfill(value); } else { promise._reject(value); } } }; Promise.prototype._settlePromiseLateCancellationObserver = function(ctx) { var handler = ctx.handler; var promise = ctx.promise; var receiver = ctx.receiver; var value = ctx.value; if (typeof handler === "function") { if (!(promise instanceof Promise)) { handler.call(receiver, value, promise); } else { this._settlePromiseFromHandler(handler, receiver, value, promise); } } else if (promise instanceof Promise) { promise._reject(value); } }; Promise.prototype._settlePromiseCtx = function(ctx) { this._settlePromise(ctx.promise, ctx.handler, ctx.receiver, ctx.value); }; Promise.prototype._settlePromise0 = function(handler, value, bitField) { var promise = this._promise0; var receiver = this._receiverAt(0); this._promise0 = undefined; this._receiver0 = undefined; this._settlePromise(promise, handler, receiver, value); }; Promise.prototype._clearCallbackDataAtIndex = function(index) { var base = index * 4 - 4; this[base + 2] = this[base + 3] = this[base + 0] = this[base + 1] = undefined; }; Promise.prototype._fulfill = function (value) { var bitField = this._bitField; if (((bitField & 117506048) >>> 16)) return; if (value === this) { var err = makeSelfResolutionError(); this._attachExtraTrace(err); return this._reject(err); } this._setFulfilled(); this._rejectionHandler0 = value; if ((bitField & 65535) > 0) { if (((bitField & 134217728) !== 0)) { this._settlePromises(); } else { async.settlePromises(this); } } }; Promise.prototype._reject = function (reason) { var bitField = this._bitField; if (((bitField & 117506048) >>> 16)) return; this._setRejected(); this._fulfillmentHandler0 = reason; if (this._isFinal()) { return async.fatalError(reason, util.isNode); } if ((bitField & 65535) > 0) { async.settlePromises(this); } else { this._ensurePossibleRejectionHandled(); } }; Promise.prototype._fulfillPromises = function (len, value) { for (var i = 1; i < len; i++) { var handler = this._fulfillmentHandlerAt(i); var promise = this._promiseAt(i); var receiver = this._receiverAt(i); this._clearCallbackDataAtIndex(i); this._settlePromise(promise, handler, receiver, value); } }; Promise.prototype._rejectPromises = function (len, reason) { for (var i = 1; i < len; i++) { var handler = this._rejectionHandlerAt(i); var promise = this._promiseAt(i); var receiver = this._receiverAt(i); this._clearCallbackDataAtIndex(i); this._settlePromise(promise, handler, receiver, reason); } }; Promise.prototype._settlePromises = function () { var bitField = this._bitField; var len = (bitField & 65535); if (len > 0) { if (((bitField & 16842752) !== 0)) { var reason = this._fulfillmentHandler0; this._settlePromise0(this._rejectionHandler0, reason, bitField); this._rejectPromises(len, reason); } else { var value = this._rejectionHandler0; this._settlePromise0(this._fulfillmentHandler0, value, bitField); this._fulfillPromises(len, value); } this._setLength(0); } this._clearCancellationData(); }; Promise.prototype._settledValue = function() { var bitField = this._bitField; if (((bitField & 33554432) !== 0)) { return this._rejectionHandler0; } else if (((bitField & 16777216) !== 0)) { return this._fulfillmentHandler0; } }; function deferResolve(v) {this.promise._resolveCallback(v);} function deferReject(v) {this.promise._rejectCallback(v, false);} Promise.defer = Promise.pending = function() { debug.deprecated("Promise.defer", "new Promise"); var promise = new Promise(INTERNAL); return { promise: promise, resolve: deferResolve, reject: deferReject }; }; util.notEnumerableProp(Promise, "_makeSelfResolutionError", makeSelfResolutionError); _dereq_("./method")(Promise, INTERNAL, tryConvertToPromise, apiRejection, debug); _dereq_("./bind")(Promise, INTERNAL, tryConvertToPromise, debug); _dereq_("./cancel")(Promise, PromiseArray, apiRejection, debug); _dereq_("./direct_resolve")(Promise); _dereq_("./synchronous_inspection")(Promise); _dereq_("./join")( Promise, PromiseArray, tryConvertToPromise, INTERNAL, debug); Promise.Promise = Promise; _dereq_('./map.js')(Promise, PromiseArray, apiRejection, tryConvertToPromise, INTERNAL, debug); _dereq_('./call_get.js')(Promise); _dereq_('./using.js')(Promise, apiRejection, tryConvertToPromise, createContext, INTERNAL, debug); _dereq_('./timers.js')(Promise, INTERNAL, debug); _dereq_('./generators.js')(Promise, apiRejection, INTERNAL, tryConvertToPromise, Proxyable, debug); _dereq_('./nodeify.js')(Promise); _dereq_('./promisify.js')(Promise, INTERNAL); _dereq_('./props.js')(Promise, PromiseArray, tryConvertToPromise, apiRejection); _dereq_('./race.js')(Promise, INTERNAL, tryConvertToPromise, apiRejection); _dereq_('./reduce.js')(Promise, PromiseArray, apiRejection, tryConvertToPromise, INTERNAL, debug); _dereq_('./settle.js')(Promise, PromiseArray, debug); _dereq_('./some.js')(Promise, PromiseArray, apiRejection); _dereq_('./filter.js')(Promise, INTERNAL); _dereq_('./each.js')(Promise, INTERNAL); _dereq_('./any.js')(Promise); util.toFastProperties(Promise); util.toFastProperties(Promise.prototype); function fillTypes(value) { var p = new Promise(INTERNAL); p._fulfillmentHandler0 = value; p._rejectionHandler0 = value; p._promise0 = value; p._receiver0 = value; } // Complete slack tracking, opt out of field-type tracking and // stabilize map fillTypes({a: 1}); fillTypes({b: 2}); fillTypes({c: 3}); fillTypes(1); fillTypes(function(){}); fillTypes(undefined); fillTypes(false); fillTypes(new Promise(INTERNAL)); debug.setBounds(Async.firstLineError, util.lastLineError); return Promise; }; },{"./any.js":1,"./async":2,"./bind":3,"./call_get.js":5,"./cancel":6,"./catch_filter":7,"./context":8,"./debuggability":9,"./direct_resolve":10,"./each.js":11,"./errors":12,"./es5":13,"./filter.js":14,"./finally":15,"./generators.js":16,"./join":17,"./map.js":18,"./method":19,"./nodeback":20,"./nodeify.js":21,"./promise_array":23,"./promisify.js":24,"./props.js":25,"./race.js":27,"./reduce.js":28,"./settle.js":30,"./some.js":31,"./synchronous_inspection":32,"./thenables":33,"./timers.js":34,"./using.js":35,"./util":36}],23:[function(_dereq_,module,exports){ "use strict"; module.exports = function(Promise, INTERNAL, tryConvertToPromise, apiRejection, Proxyable) { var util = _dereq_("./util"); var isArray = util.isArray; function toResolutionValue(val) { switch(val) { case -2: return []; case -3: return {}; } } function PromiseArray(values) { var promise = this._promise = new Promise(INTERNAL); if (values instanceof Promise) { promise._propagateFrom(values, 3); } promise._setOnCancel(this); this._values = values; this._length = 0; this._totalResolved = 0; this._init(undefined, -2); } util.inherits(PromiseArray, Proxyable); PromiseArray.prototype.length = function () { return this._length; }; PromiseArray.prototype.promise = function () { return this._promise; }; PromiseArray.prototype._init = function init(_, resolveValueIfEmpty) { var values = tryConvertToPromise(this._values, this._promise); if (values instanceof Promise) { values = values._target(); var bitField = values._bitField; ; this._values = values; if (((bitField & 50397184) === 0)) { this._promise._setAsyncGuaranteed(); return values._then( init, this._reject, undefined, this, resolveValueIfEmpty ); } else if (((bitField & 33554432) !== 0)) { values = values._value(); } else if (((bitField & 16777216) !== 0)) { return this._reject(values._reason()); } else { return this._cancel(); } } values = util.asArray(values); if (values === null) { var err = apiRejection( "expecting an array or an iterable object but got " + util.classString(values)).reason(); this._promise._rejectCallback(err, false); return; } if (values.length === 0) { if (resolveValueIfEmpty === -5) { this._resolveEmptyArray(); } else { this._resolve(toResolutionValue(resolveValueIfEmpty)); } return; } this._iterate(values); }; PromiseArray.prototype._iterate = function(values) { var len = this.getActualLength(values.length); this._length = len; this._values = this.shouldCopyValues() ? new Array(len) : this._values; var result = this._promise; var isResolved = false; var bitField = null; for (var i = 0; i < len; ++i) { var maybePromise = tryConvertToPromise(values[i], result); if (maybePromise instanceof Promise) { maybePromise = maybePromise._target(); bitField = maybePromise._bitField; } else { bitField = null; } if (isResolved) { if (bitField !== null) { maybePromise.suppressUnhandledRejections(); } } else if (bitField !== null) { if (((bitField & 50397184) === 0)) { maybePromise._proxy(this, i); this._values[i] = maybePromise; } else if (((bitField & 33554432) !== 0)) { isResolved = this._promiseFulfilled(maybePromise._value(), i); } else if (((bitField & 16777216) !== 0)) { isResolved = this._promiseRejected(maybePromise._reason(), i); } else { isResolved = this._promiseCancelled(i); } } else { isResolved = this._promiseFulfilled(maybePromise, i); } } if (!isResolved) result._setAsyncGuaranteed(); }; PromiseArray.prototype._isResolved = function () { return this._values === null; }; PromiseArray.prototype._resolve = function (value) { this._values = null; this._promise._fulfill(value); }; PromiseArray.prototype._cancel = function() { if (this._isResolved() || !this._promise.isCancellable()) return; this._values = null; this._promise._cancel(); }; PromiseArray.prototype._reject = function (reason) { this._values = null; this._promise._rejectCallback(reason, false); }; PromiseArray.prototype._promiseFulfilled = function (value, index) { this._values[index] = value; var totalResolved = ++this._totalResolved; if (totalResolved >= this._length) { this._resolve(this._values); return true; } return false; }; PromiseArray.prototype._promiseCancelled = function() { this._cancel(); return true; }; PromiseArray.prototype._promiseRejected = function (reason) { this._totalResolved++; this._reject(reason); return true; }; PromiseArray.prototype._resultCancelled = function() { if (this._isResolved()) return; var values = this._values; this._cancel(); if (values instanceof Promise) { values.cancel(); } else { for (var i = 0; i < values.length; ++i) { if (values[i] instanceof Promise) { values[i].cancel(); } } } }; PromiseArray.prototype.shouldCopyValues = function () { return true; }; PromiseArray.prototype.getActualLength = function (len) { return len; }; return PromiseArray; }; },{"./util":36}],24:[function(_dereq_,module,exports){ "use strict"; module.exports = function(Promise, INTERNAL) { var THIS = {}; var util = _dereq_("./util"); var nodebackForPromise = _dereq_("./nodeback"); var withAppended = util.withAppended; var maybeWrapAsError = util.maybeWrapAsError; var canEvaluate = util.canEvaluate; var TypeError = _dereq_("./errors").TypeError; var defaultSuffix = "Async"; var defaultPromisified = {__isPromisified__: true}; var noCopyProps = [ "arity", "length", "name", "arguments", "caller", "callee", "prototype", "__isPromisified__" ]; var noCopyPropsPattern = new RegExp("^(?:" + noCopyProps.join("|") + ")$"); var defaultFilter = function(name) { return util.isIdentifier(name) && name.charAt(0) !== "_" && name !== "constructor"; }; function propsFilter(key) { return !noCopyPropsPattern.test(key); } function isPromisified(fn) { try { return fn.__isPromisified__ === true; } catch (e) { return false; } } function hasPromisified(obj, key, suffix) { var val = util.getDataPropertyOrDefault(obj, key + suffix, defaultPromisified); return val ? isPromisified(val) : false; } function checkValid(ret, suffix, suffixRegexp) { for (var i = 0; i < ret.length; i += 2) { var key = ret[i]; if (suffixRegexp.test(key)) { var keyWithoutAsyncSuffix = key.replace(suffixRegexp, ""); 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 '%s'-suffix\u000a\u000a See http://goo.gl/MqrFmX\u000a" .replace("%s", suffix)); } } } } } function promisifiableMethods(obj, suffix, suffixRegexp, filter) { var keys = util.inheritedDataKeys(obj); var ret = []; for (var i = 0; i < keys.length; ++i) { var key = keys[i]; var value = obj[key]; var passesDefaultFilter = filter === defaultFilter ? true : defaultFilter(key, value, obj); if (typeof value === "function" && !isPromisified(value) && !hasPromisified(obj, key, suffix) && filter(key, value, obj, passesDefaultFilter)) { ret.push(key, value); } } checkValid(ret, suffix, suffixRegexp); return ret; } var escapeIdentRegex = function(str) { return str.replace(/([$])/, "\\$"); }; var makeNodePromisifiedEval; if (false) { var switchCaseArgumentOrder = function(likelyArgumentCount) { var ret = [likelyArgumentCount]; var min = Math.max(0, likelyArgumentCount - 1 - 3); for(var i = likelyArgumentCount - 1; i >= min; --i) { ret.push(i); } for(var i = likelyArgumentCount + 1; i <= 3; ++i) { ret.push(i); } return ret; }; var argumentSequence = function(argumentCount) { return util.filledRange(argumentCount, "_arg", ""); }; var parameterDeclaration = function(parameterCount) { return util.filledRange( Math.max(parameterCount, 3), "_arg", ""); }; var parameterCount = function(fn) { if (typeof fn.length === "number") { return Math.max(Math.min(fn.length, 1023 + 1), 0); } return 0; }; makeNodePromisifiedEval = function(callback, receiver, originalName, fn, _, multiArgs) { var newParameterCount = Math.max(0, parameterCount(fn) - 1); var argumentOrder = switchCaseArgumentOrder(newParameterCount); var shouldProxyThis = typeof callback === "string" || receiver === THIS; function generateCallForArgumentCount(count) { var args = argumentSequence(count).join(", "); var comma = count > 0 ? ", " : ""; var ret; if (shouldProxyThis) { ret = "ret = callback.call(this, {{args}}, nodeback); break;\n"; } else { ret = receiver === undefined ? "ret = callback({{args}}, nodeback); break;\n" : "ret = callback.call(receiver, {{args}}, nodeback); break;\n"; } return ret.replace("{{args}}", args).replace(", ", comma); } function generateArgumentSwitchCase() { var ret = ""; for (var i = 0; i < argumentOrder.length; ++i) { ret += "case " + argumentOrder[i] +":" + generateCallForArgumentCount(argumentOrder[i]); } ret += " \n\ default: \n\ var args = new Array(len + 1); \n\ var i = 0; \n\ for (var i = 0; i < len; ++i) { \n\ args[i] = arguments[i]; \n\ } \n\ args[i] = nodeback; \n\ [CodeForCall] \n\ break; \n\ ".replace("[CodeForCall]", (shouldProxyThis ? "ret = callback.apply(this, args);\n" : "ret = callback.apply(receiver, args);\n")); return ret; } var getFunctionCode = typeof callback === "string" ? ("this != null ? this['"+callback+"'] : fn") : "fn"; var body = "'use strict'; \n\ var ret = function (Parameters) { \n\ 'use strict'; \n\ var len = arguments.length; \n\ var promise = new Promise(INTERNAL); \n\ promise._captureStackTrace(); \n\ var nodeback = nodebackForPromise(promise, " + multiArgs + "); \n\ var ret; \n\ var callback = tryCatch([GetFunctionCode]); \n\ switch(len) { \n\ [CodeForSwitchCase] \n\ } \n\ if (ret === errorObj) { \n\ promise._rejectCallback(maybeWrapAsError(ret.e), true, true);\n\ } \n\ if (!promise._isFateSealed()) promise._setAsyncGuaranteed(); \n\ return promise; \n\ }; \n\ notEnumerableProp(ret, '__isPromisified__', true); \n\ return ret; \n\ ".replace("[CodeForSwitchCase]", generateArgumentSwitchCase()) .replace("[GetFunctionCode]", getFunctionCode); body = body.replace("Parameters", parameterDeclaration(newParameterCount)); return new Function("Promise", "fn", "receiver", "withAppended", "maybeWrapAsError", "nodebackForPromise", "tryCatch", "errorObj", "notEnumerableProp", "INTERNAL", body)( Promise, fn, receiver, withAppended, maybeWrapAsError, nodebackForPromise, util.tryCatch, util.errorObj, util.notEnumerableProp, INTERNAL); }; } function makeNodePromisifiedClosure(callback, receiver, _, fn, __, multiArgs) { var defaultThis = (function() {return this;})(); var method = callback; if (typeof method === "string") { callback = fn; } function promisified() { var _receiver = receiver; if (receiver === THIS) _receiver = this; var promise = new Promise(INTERNAL); promise._captureStackTrace(); var cb = typeof method === "string" && this !== defaultThis ? this[method] : callback; var fn = nodebackForPromise(promise, multiArgs); try { cb.apply(_receiver, withAppended(arguments, fn)); } catch(e) { promise._rejectCallback(maybeWrapAsError(e), true, true); } if (!promise._isFateSealed()) promise._setAsyncGuaranteed(); return promise; } util.notEnumerableProp(promisified, "__isPromisified__", true); return promisified; } var makeNodePromisified = canEvaluate ? makeNodePromisifiedEval : makeNodePromisifiedClosure; function promisifyAll(obj, suffix, filter, promisifier, multiArgs) { var suffixRegexp = new RegExp(escapeIdentRegex(suffix) + "$"); var methods = promisifiableMethods(obj, suffix, suffixRegexp, filter); for (var i = 0, len = methods.length; i < len; i+= 2) { var key = methods[i]; var fn = methods[i+1]; var promisifiedKey = key + suffix; if (promisifier === makeNodePromisified) { obj[promisifiedKey] = makeNodePromisified(key, THIS, key, fn, suffix, multiArgs); } else { var promisified = promisifier(fn, function() { return makeNodePromisified(key, THIS, key, fn, suffix, multiArgs); }); util.notEnumerableProp(promisified, "__isPromisified__", true); obj[promisifiedKey] = promisified; } } util.toFastProperties(obj); return obj; } function promisify(callback, receiver, multiArgs) { return makeNodePromisified(callback, receiver, undefined, callback, null, multiArgs); } Promise.promisify = function (fn, options) { if (typeof fn !== "function") { throw new TypeError("expecting a function but got " + util.classString(fn)); } if (isPromisified(fn)) { return fn; } options = Object(options); var receiver = options.context === undefined ? THIS : options.context; var multiArgs = !!options.multiArgs; var ret = promisify(fn, receiver, multiArgs); util.copyDescriptors(fn, ret, propsFilter); return ret; }; Promise.promisifyAll = function (target, options) { if (typeof target !== "function" && typeof target !== "object") { throw new TypeError("the target of promisifyAll must be an object or a function\u000a\u000a See http://goo.gl/MqrFmX\u000a"); } options = Object(options); var multiArgs = !!options.multiArgs; var suffix = options.suffix; if (typeof suffix !== "string") suffix = defaultSuffix; var filter = options.filter; if (typeof filter !== "function") filter = defaultFilter; var promisifier = options.promisifier; if (typeof promisifier !== "function") promisifier = makeNodePromisified; if (!util.isIdentifier(suffix)) { throw new RangeError("suffix must be a valid identifier\u000a\u000a See http://goo.gl/MqrFmX\u000a"); } var keys = util.inheritedDataKeys(target); for (var i = 0; i < keys.length; ++i) { var value = target[keys[i]]; if (keys[i] !== "constructor" && util.isClass(value)) { promisifyAll(value.prototype, suffix, filter, promisifier, multiArgs); promisifyAll(value, suffix, filter, promisifier, multiArgs); } } return promisifyAll(target, suffix, filter, promisifier, multiArgs); }; }; },{"./errors":12,"./nodeback":20,"./util":36}],25:[function(_dereq_,module,exports){ "use strict"; module.exports = function( Promise, PromiseArray, tryConvertToPromise, apiRejection) { var util = _dereq_("./util"); var isObject = util.isObject; var es5 = _dereq_("./es5"); var Es6Map; if (typeof Map === "function") Es6Map = Map; var mapToEntries = (function() { var index = 0; var size = 0; function extractEntry(value, key) { this[index] = value; this[index + size] = key; index++; } return function mapToEntries(map) { size = map.size; index = 0; var ret = new Array(map.size * 2); map.forEach(extractEntry, ret); return ret; }; })(); var entriesToMap = function(entries) { var ret = new Es6Map(); var length = entries.length / 2 | 0; for (var i = 0; i < length; ++i) { var key = entries[length + i]; var value = entries[i]; ret.set(key, value); } return ret; }; function PropertiesPromiseArray(obj) { var isMap = false; var entries; if (Es6Map !== undefined && obj instanceof Es6Map) { entries = mapToEntries(obj); isMap = true; } else { var keys = es5.keys(obj); var len = keys.length; entries = new Array(len * 2); for (var i = 0; i < len; ++i) { var key = keys[i]; entries[i] = obj[key]; entries[i + len] = key; } } this.constructor$(entries); this._isMap = isMap; this._init$(undefined, -3); } util.inherits(PropertiesPromiseArray, PromiseArray); PropertiesPromiseArray.prototype._init = function () {}; PropertiesPromiseArray.prototype._promiseFulfilled = function (value, index) { this._values[index] = value; var totalResolved = ++this._totalResolved; if (totalResolved >= this._length) { var val; if (this._isMap) { val = entriesToMap(this._values); } else { 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); return true; } return false; }; PropertiesPromiseArray.prototype.shouldCopyValues = function () { return false; }; PropertiesPromiseArray.prototype.getActualLength = function (len) { return len >> 1; }; function props(promises) { var ret; var castValue = tryConvertToPromise(promises); if (!isObject(castValue)) { return apiRejection("cannot await properties of a non-object\u000a\u000a See http://goo.gl/MqrFmX\u000a"); } else if (castValue instanceof Promise) { ret = castValue._then( Promise.props, undefined, undefined, undefined, undefined); } else { ret = new PropertiesPromiseArray(castValue).promise(); } if (castValue instanceof Promise) { ret._propagateFrom(castValue, 2); } return ret; } Promise.prototype.props = function () { return props(this); }; Promise.props = function (promises) { return props(promises); }; }; },{"./es5":13,"./util":36}],26:[function(_dereq_,module,exports){ "use strict"; function arrayMove(src, srcIndex, dst, dstIndex, len) { for (var j = 0; j < len; ++j) { dst[j + dstIndex] = src[j + srcIndex]; src[j + srcIndex] = void 0; } } function Queue(capacity) { this._capacity = capacity; this._length = 0; this._front = 0; } Queue.prototype._willBeOverCapacity = function (size) { return this._capacity < size; }; Queue.prototype._pushOne = function (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._unshiftOne = function(value) { var capacity = this._capacity; this._checkCapacity(this.length() + 1); var front = this._front; var i = (((( front - 1 ) & ( capacity - 1) ) ^ capacity ) - capacity ); this[i] = value; this._front = i; this._length = this.length() + 1; }; Queue.prototype.unshift = function(fn, receiver, arg) { this._unshiftOne(arg); this._unshiftOne(receiver); this._unshiftOne(fn); }; Queue.prototype.push = function (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 () { var front = this._front, ret = this[front]; this[front] = undefined; this._front = (front + 1) & (this._capacity - 1); this._length--; return ret; }; Queue.prototype.length = function () { return this._length; }; Queue.prototype._checkCapacity = function (size) { if (this._capacity < size) { this._resizeTo(this._capacity << 1); } }; Queue.prototype._resizeTo = function (capacity) { var oldCapacity = this._capacity; this._capacity = capacity; var front = this._front; var length = this._length; var moveItemsCount = (front + length) & (oldCapacity - 1); arrayMove(this, 0, this, oldCapacity, moveItemsCount); }; module.exports = Queue; },{}],27:[function(_dereq_,module,exports){ "use strict"; module.exports = function( Promise, INTERNAL, tryConvertToPromise, apiRejection) { var util = _dereq_("./util"); var raceLater = function (promise) { return promise.then(function(array) { return race(array, promise); }); }; function race(promises, parent) { var maybePromise = tryConvertToPromise(promises); if (maybePromise instanceof Promise) { return raceLater(maybePromise); } else { promises = util.asArray(promises); if (promises === null) return apiRejection("expecting an array or an iterable object but got " + util.classString(promises)); } var ret = new Promise(INTERNAL); if (parent !== undefined) { ret._propagateFrom(parent, 3); } var fulfill = ret._fulfill; var reject = ret._reject; for (var i = 0, len = promises.length; i < len; ++i) { var val = promises[i]; if (val === undefined && !(i in promises)) { continue; } Promise.cast(val)._then(fulfill, reject, undefined, ret, null); } return ret; } Promise.race = function (promises) { return race(promises, undefined); }; Promise.prototype.race = function () { return race(this, undefined); }; }; },{"./util":36}],28:[function(_dereq_,module,exports){ "use strict"; module.exports = function(Promise, PromiseArray, apiRejection, tryConvertToPromise, INTERNAL, debug) { var getDomain = Promise._getDomain; var util = _dereq_("./util"); var tryCatch = util.tryCatch; function ReductionPromiseArray(promises, fn, initialValue, _each) { this.constructor$(promises); var domain = getDomain(); this._fn = domain === null ? fn : domain.bind(fn); if (initialValue !== undefined) { initialValue = Promise.resolve(initialValue); initialValue._attachCancellationCallback(this); } this._initialValue = initialValue; this._currentCancellable = null; this._eachValues = _each === INTERNAL ? [] : undefined; this._promise._captureStackTrace(); this._init$(undefined, -5); } util.inherits(ReductionPromiseArray, PromiseArray); ReductionPromiseArray.prototype._gotAccum = function(accum) { if (this._eachValues !== undefined && accum !== INTERNAL) { this._eachValues.push(accum); } }; ReductionPromiseArray.prototype._eachComplete = function(value) { this._eachValues.push(value); return this._eachValues; }; ReductionPromiseArray.prototype._init = function() {}; ReductionPromiseArray.prototype._resolveEmptyArray = function() { this._resolve(this._eachValues !== undefined ? this._eachValues : this._initialValue); }; ReductionPromiseArray.prototype.shouldCopyValues = function () { return false; }; ReductionPromiseArray.prototype._resolve = function(value) { this._promise._resolveCallback(value); this._values = null; }; ReductionPromiseArray.prototype._resultCancelled = function(sender) { if (sender === this._initialValue) return this._cancel(); if (this._isResolved()) return; this._resultCancelled$(); if (this._currentCancellable instanceof Promise) { this._currentCancellable.cancel(); } if (this._initialValue instanceof Promise) { this._initialValue.cancel(); } }; ReductionPromiseArray.prototype._iterate = function (values) { this._values = values; var value; var i; var length = values.length; if (this._initialValue !== undefined) { value = this._initialValue; i = 0; } else { value = Promise.resolve(values[0]); i = 1; } this._currentCancellable = value; if (!value.isRejected()) { for (; i < length; ++i) { var ctx = { accum: null, value: values[i], index: i, length: length, array: this }; value = value._then(gotAccum, undefined, undefined, ctx, undefined); } } if (this._eachValues !== undefined) { value = value ._then(this._eachComplete, undefined, undefined, this, undefined); } value._then(completed, completed, undefined, value, this); }; Promise.prototype.reduce = function (fn, initialValue) { return reduce(this, fn, initialValue, null); }; Promise.reduce = function (promises, fn, initialValue, _each) { return reduce(promises, fn, initialValue, _each); }; function completed(valueOrReason, array) { if (this.isFulfilled()) { array._resolve(valueOrReason); } else { array._reject(valueOrReason); } } function reduce(promises, fn, initialValue, _each) { if (typeof fn !== "function") { return apiRejection("expecting a function but got " + util.classString(fn)); } var array = new ReductionPromiseArray(promises, fn, initialValue, _each); return array.promise(); } function gotAccum(accum) { this.accum = accum; this.array._gotAccum(accum); var value = tryConvertToPromise(this.value, this.array._promise); if (value instanceof Promise) { this.array._currentCancellable = value; return value._then(gotValue, undefined, undefined, this, undefined); } else { return gotValue.call(this, value); } } function gotValue(value) { var array = this.array; var promise = array._promise; var fn = tryCatch(array._fn); promise._pushContext(); var ret; if (array._eachValues !== undefined) { ret = fn.call(promise._boundValue(), value, this.index, this.length); } else { ret = fn.call(promise._boundValue(), this.accum, value, this.index, this.length); } if (ret instanceof Promise) { array._currentCancellable = ret; } var promiseCreated = promise._popContext(); debug.checkForgottenReturns( ret, promiseCreated, array._eachValues !== undefined ? "Promise.each" : "Promise.reduce", promise ); return ret; } }; },{"./util":36}],29:[function(_dereq_,module,exports){ "use strict"; var util = _dereq_("./util"); var schedule; var noAsyncScheduler = function() { throw new Error("No async scheduler available\u000a\u000a See http://goo.gl/MqrFmX\u000a"); }; var NativePromise = util.getNativePromise(); if (util.isNode && typeof MutationObserver === "undefined") { var GlobalSetImmediate = global.setImmediate; var ProcessNextTick = process.nextTick; schedule = util.isRecentNode ? function(fn) { GlobalSetImmediate.call(global, fn); } : function(fn) { ProcessNextTick.call(process, fn); }; } else if (typeof NativePromise === "function") { var nativePromise = NativePromise.resolve(); schedule = function(fn) { nativePromise.then(fn); }; } else if ((typeof MutationObserver !== "undefined") && !(typeof window !== "undefined" && window.navigator && window.navigator.standalone)) { schedule = (function() { var div = document.createElement("div"); var opts = {attributes: true}; var toggleScheduled = false; var div2 = document.createElement("div"); var o2 = new MutationObserver(function() { div.classList.toggle("foo"); toggleScheduled = false; }); o2.observe(div2, opts); var scheduleToggle = function() { if (toggleScheduled) return; toggleScheduled = true; div2.classList.toggle("foo"); }; return function schedule(fn) { var o = new MutationObserver(function() { o.disconnect(); fn(); }); o.observe(div, opts); scheduleToggle(); }; })(); } else if (typeof setImmediate !== "undefined") { schedule = function (fn) { setImmediate(fn); }; } else if (typeof setTimeout !== "undefined") { schedule = function (fn) { setTimeout(fn, 0); }; } else { schedule = noAsyncScheduler; } module.exports = schedule; },{"./util":36}],30:[function(_dereq_,module,exports){ "use strict"; module.exports = function(Promise, PromiseArray, debug) { var PromiseInspection = Promise.PromiseInspection; var util = _dereq_("./util"); function SettledPromiseArray(values) { this.constructor$(values); } util.inherits(SettledPromiseArray, PromiseArray); SettledPromiseArray.prototype._promiseResolved = function (index, inspection) { this._values[index] = inspection; var totalResolved = ++this._totalResolved; if (totalResolved >= this._length) { this._resolve(this._values); return true; } return false; }; SettledPromiseArray.prototype._promiseFulfilled = function (value, index) { var ret = new PromiseInspection(); ret._bitField = 33554432; ret._settledValueField = value; return this._promiseResolved(index, ret); }; SettledPromiseArray.prototype._promiseRejected = function (reason, index) { var ret = new PromiseInspection(); ret._bitField = 16777216; ret._settledValueField = reason; return this._promiseResolved(index, ret); }; Promise.settle = function (promises) { debug.deprecated(".settle()", ".reflect()"); return new SettledPromiseArray(promises).promise(); }; Promise.prototype.settle = function () { return Promise.settle(this); }; }; },{"./util":36}],31:[function(_dereq_,module,exports){ "use strict"; module.exports = function(Promise, PromiseArray, apiRejection) { var util = _dereq_("./util"); var RangeError = _dereq_("./errors").RangeError; var AggregateError = _dereq_("./errors").AggregateError; var isArray = util.isArray; var CANCELLATION = {}; function SomePromiseArray(values) { this.constructor$(values); this._howMany = 0; this._unwrap = false; this._initialized = false; } util.inherits(SomePromiseArray, PromiseArray); SomePromiseArray.prototype._init = function () { if (!this._initialized) { return; } if (this._howMany === 0) { this._resolve([]); return; } this._init$(undefined, -5); var isArrayResolved = isArray(this._values); if (!this._isResolved() && isArrayResolved && this._howMany > this._canPossiblyFulfill()) { this._reject(this._getRangeError(this.length())); } }; SomePromiseArray.prototype.init = function () { this._initialized = true; this._init(); }; SomePromiseArray.prototype.setUnwrap = function () { this._unwrap = true; }; SomePromiseArray.prototype.howMany = function () { return this._howMany; }; SomePromiseArray.prototype.setHowMany = function (count) { this._howMany = count; }; SomePromiseArray.prototype._promiseFulfilled = function (value) { 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); } return true; } return false; }; SomePromiseArray.prototype._promiseRejected = function (reason) { this._addRejected(reason); return this._checkOutcome(); }; SomePromiseArray.prototype._promiseCancelled = function () { if (this._values instanceof Promise || this._values == null) { return this._cancel(); } this._addRejected(CANCELLATION); return this._checkOutcome(); }; SomePromiseArray.prototype._checkOutcome = function() { if (this.howMany() > this._canPossiblyFulfill()) { var e = new AggregateError(); for (var i = this.length(); i < this._values.length; ++i) { if (this._values[i] !== CANCELLATION) { e.push(this._values[i]); } } if (e.length > 0) { this._reject(e); } else { this._cancel(); } return true; } return false; }; SomePromiseArray.prototype._fulfilled = function () { return this._totalResolved; }; SomePromiseArray.prototype._rejected = function () { return this._values.length - this.length(); }; SomePromiseArray.prototype._addRejected = function (reason) { this._values.push(reason); }; SomePromiseArray.prototype._addFulfilled = function (value) { this._values[this._totalResolved++] = value; }; SomePromiseArray.prototype._canPossiblyFulfill = function () { return this.length() - this._rejected(); }; SomePromiseArray.prototype._getRangeError = function (count) { var message = "Input array must contain at least " + this._howMany + " items but contains only " + count + " items"; return new RangeError(message); }; SomePromiseArray.prototype._resolveEmptyArray = function () { this._reject(this._getRangeError(0)); }; function some(promises, howMany) { if ((howMany | 0) !== howMany || howMany < 0) { return apiRejection("expecting a positive integer\u000a\u000a See http://goo.gl/MqrFmX\u000a"); } var ret = new SomePromiseArray(promises); var promise = ret.promise(); ret.setHowMany(howMany); ret.init(); return promise; } Promise.some = function (promises, howMany) { return some(promises, howMany); }; Promise.prototype.some = function (howMany) { return some(this, howMany); }; Promise._SomePromiseArray = SomePromiseArray; }; },{"./errors":12,"./util":36}],32:[function(_dereq_,module,exports){ "use strict"; module.exports = function(Promise) { function PromiseInspection(promise) { if (promise !== undefined) { promise = promise._target(); this._bitField = promise._bitField; this._settledValueField = promise._isFateSealed() ? promise._settledValue() : undefined; } else { this._bitField = 0; this._settledValueField = undefined; } } PromiseInspection.prototype._settledValue = function() { return this._settledValueField; }; var value = PromiseInspection.prototype.value = function () { if (!this.isFulfilled()) { throw new TypeError("cannot get fulfillment value of a non-fulfilled promise\u000a\u000a See http://goo.gl/MqrFmX\u000a"); } return this._settledValue(); }; var reason = PromiseInspection.prototype.error = PromiseInspection.prototype.reason = function () { if (!this.isRejected()) { throw new TypeError("cannot get rejection reason of a non-rejected promise\u000a\u000a See http://goo.gl/MqrFmX\u000a"); } return this._settledValue(); }; var isFulfilled = PromiseInspection.prototype.isFulfilled = function() { return (this._bitField & 33554432) !== 0; }; var isRejected = PromiseInspection.prototype.isRejected = function () { return (this._bitField & 16777216) !== 0; }; var isPending = PromiseInspection.prototype.isPending = function () { return (this._bitField & 50397184) === 0; }; var isResolved = PromiseInspection.prototype.isResolved = function () { return (this._bitField & 50331648) !== 0; }; PromiseInspection.prototype.isCancelled = Promise.prototype._isCancelled = function() { return (this._bitField & 65536) === 65536; }; Promise.prototype.isCancelled = function() { return this._target()._isCancelled(); }; Promise.prototype.isPending = function() { return isPending.call(this._target()); }; Promise.prototype.isRejected = function() { return isRejected.call(this._target()); }; Promise.prototype.isFulfilled = function() { return isFulfilled.call(this._target()); }; Promise.prototype.isResolved = function() { return isResolved.call(this._target()); }; Promise.prototype.value = function() { return value.call(this._target()); }; Promise.prototype.reason = function() { var target = this._target(); target._unsetRejectionIsUnhandled(); return reason.call(target); }; Promise.prototype._value = function() { return this._settledValue(); }; Promise.prototype._reason = function() { this._unsetRejectionIsUnhandled(); return this._settledValue(); }; Promise.PromiseInspection = PromiseInspection; }; },{}],33:[function(_dereq_,module,exports){ "use strict"; module.exports = function(Promise, INTERNAL) { var util = _dereq_("./util"); var errorObj = util.errorObj; var isObject = util.isObject; function tryConvertToPromise(obj, context) { if (isObject(obj)) { if (obj instanceof Promise) return obj; var then = getThen(obj); if (then === errorObj) { if (context) context._pushContext(); var ret = Promise.reject(then.e); if (context) context._popContext(); return ret; } else if (typeof then === "function") { if (isAnyBluebirdPromise(obj)) { var ret = new Promise(INTERNAL); obj._then( ret._fulfill, ret._reject, undefined, ret, null ); return ret; } return doThenable(obj, then, context); } } return obj; } function doGetThen(obj) { return obj.then; } function getThen(obj) { try { return doGetThen(obj); } catch (e) { errorObj.e = e; return errorObj; } } var hasProp = {}.hasOwnProperty; function isAnyBluebirdPromise(obj) { return hasProp.call(obj, "_promise0"); } function doThenable(x, then, context) { var promise = new Promise(INTERNAL); var ret = promise; if (context) context._pushContext(); promise._captureStackTrace(); if (context) context._popContext(); var synchronous = true; var result = util.tryCatch(then).call(x, resolve, reject); synchronous = false; if (promise && result === errorObj) { promise._rejectCallback(result.e, true, true); promise = null; } function resolve(value) { if (!promise) return; promise._resolveCallback(value); promise = null; } function reject(reason) { if (!promise) return; promise._rejectCallback(reason, synchronous, true); promise = null; } return ret; } return tryConvertToPromise; }; },{"./util":36}],34:[function(_dereq_,module,exports){ "use strict"; module.exports = function(Promise, INTERNAL, debug) { var util = _dereq_("./util"); var TimeoutError = Promise.TimeoutError; function HandleWrapper(handle) { this.handle = handle; } HandleWrapper.prototype._resultCancelled = function() { clearTimeout(this.handle); }; var afterValue = function(value) { return delay(+this).thenReturn(value); }; var delay = Promise.delay = function (ms, value) { var ret; var handle; if (value !== undefined) { ret = Promise.resolve(value) ._then(afterValue, null, null, ms, undefined); if (debug.cancellation() && value instanceof Promise) { ret._setOnCancel(value); } } else { ret = new Promise(INTERNAL); handle = setTimeout(function() { ret._fulfill(); }, +ms); if (debug.cancellation()) { ret._setOnCancel(new HandleWrapper(handle)); } } ret._setAsyncGuaranteed(); return ret; }; Promise.prototype.delay = function (ms) { return delay(ms, this); }; var afterTimeout = function (promise, message, parent) { var err; if (typeof message !== "string") { if (message instanceof Error) { err = message; } else { err = new TimeoutError("operation timed out"); } } else { err = new TimeoutError(message); } util.markAsOriginatingFromRejection(err); promise._attachExtraTrace(err); promise._reject(err); if (parent != null) { parent.cancel(); } }; function successClear(value) { clearTimeout(this.handle); return value; } function failureClear(reason) { clearTimeout(this.handle); throw reason; } Promise.prototype.timeout = function (ms, message) { ms = +ms; var ret, parent; var handleWrapper = new HandleWrapper(setTimeout(function timeoutTimeout() { if (ret.isPending()) { afterTimeout(ret, message, parent); } }, ms)); if (debug.cancellation()) { parent = this.then(); ret = parent._then(successClear, failureClear, undefined, handleWrapper, undefined); ret._setOnCancel(handleWrapper); } else { ret = this._then(successClear, failureClear, undefined, handleWrapper, undefined); } return ret; }; }; },{"./util":36}],35:[function(_dereq_,module,exports){ "use strict"; module.exports = function (Promise, apiRejection, tryConvertToPromise, createContext, INTERNAL, debug) { var util = _dereq_("./util"); var TypeError = _dereq_("./errors").TypeError; var inherits = _dereq_("./util").inherits; var errorObj = util.errorObj; var tryCatch = util.tryCatch; function thrower(e) { setTimeout(function(){throw e;}, 0); } function castPreservingDisposable(thenable) { var maybePromise = tryConvertToPromise(thenable); if (maybePromise !== thenable && typeof thenable._isDisposable === "function" && typeof thenable._getDisposer === "function" && thenable._isDisposable()) { maybePromise._setDisposable(thenable._getDisposer()); } return maybePromise; } function dispose(resources, inspection) { var i = 0; var len = resources.length; var ret = new Promise(INTERNAL); function iterator() { if (i >= len) return ret._fulfill(); var maybePromise = castPreservingDisposable(resources[i++]); if (maybePromise instanceof Promise && maybePromise._isDisposable()) { try { maybePromise = tryConvertToPromise( maybePromise._getDisposer().tryDispose(inspection), resources.promise); } catch (e) { return thrower(e); } if (maybePromise instanceof Promise) { return maybePromise._then(iterator, thrower, null, null, null); } } iterator(); } iterator(); return ret; } function Disposer(data, promise, context) { this._data = data; this._promise = promise; this._context = context; } Disposer.prototype.data = function () { return this._data; }; Disposer.prototype.promise = function () { return this._promise; }; Disposer.prototype.resource = function () { if (this.promise().isFulfilled()) { return this.promise().value(); } return null; }; Disposer.prototype.tryDispose = function(inspection) { var resource = this.resource(); var context = this._context; if (context !== undefined) context._pushContext(); var ret = resource !== null ? this.doDispose(resource, inspection) : null; if (context !== undefined) context._popContext(); this._promise._unsetDisposable(); this._data = null; return ret; }; Disposer.isDisposer = function (d) { return (d != null && typeof d.resource === "function" && typeof d.tryDispose === "function"); }; function FunctionDisposer(fn, promise, context) { this.constructor$(fn, promise, context); } inherits(FunctionDisposer, Disposer); FunctionDisposer.prototype.doDispose = function (resource, inspection) { var fn = this.data(); return fn.call(resource, resource, inspection); }; function maybeUnwrapDisposer(value) { if (Disposer.isDisposer(value)) { this.resources[this.index]._setDisposable(value); return value.promise(); } return value; } function ResourceList(length) { this.length = length; this.promise = null; this[length-1] = null; } ResourceList.prototype._resultCancelled = function() { var len = this.length; for (var i = 0; i < len; ++i) { var item = this[i]; if (item instanceof Promise) { item.cancel(); } } }; Promise.using = function () { var len = arguments.length; if (len < 2) return apiRejection( "you must pass at least 2 arguments to Promise.using"); var fn = arguments[len - 1]; if (typeof fn !== "function") { return apiRejection("expecting a function but got " + util.classString(fn)); } var input; var spreadArgs = true; if (len === 2 && Array.isArray(arguments[0])) { input = arguments[0]; len = input.length; spreadArgs = false; } else { input = arguments; len--; } var resources = new ResourceList(len); for (var i = 0; i < len; ++i) { var resource = input[i]; if (Disposer.isDisposer(resource)) { var disposer = resource; resource = resource.promise(); resource._setDisposable(disposer); } else { var maybePromise = tryConvertToPromise(resource); if (maybePromise instanceof Promise) { resource = maybePromise._then(maybeUnwrapDisposer, null, null, { resources: resources, index: i }, undefined); } } resources[i] = resource; } var reflectedResources = new Array(resources.length); for (var i = 0; i < reflectedResources.length; ++i) { reflectedResources[i] = Promise.resolve(resources[i]).reflect(); } var resultPromise = Promise.all(reflectedResources) .then(function(inspections) { for (var i = 0; i < inspections.length; ++i) { var inspection = inspections[i]; if (inspection.isRejected()) { errorObj.e = inspection.error(); return errorObj; } else if (!inspection.isFulfilled()) { resultPromise.cancel(); return; } inspections[i] = inspection.value(); } promise._pushContext(); fn = tryCatch(fn); var ret = spreadArgs ? fn.apply(undefined, inspections) : fn(inspections); var promiseCreated = promise._popContext(); debug.checkForgottenReturns( ret, promiseCreated, "Promise.using", promise); return ret; }); var promise = resultPromise.lastly(function() { var inspection = new Promise.PromiseInspection(resultPromise); return dispose(resources, inspection); }); resources.promise = promise; promise._setOnCancel(resources); return promise; }; Promise.prototype._setDisposable = function (disposer) { this._bitField = this._bitField | 131072; this._disposer = disposer; }; Promise.prototype._isDisposable = function () { return (this._bitField & 131072) > 0; }; Promise.prototype._getDisposer = function () { return this._disposer; }; Promise.prototype._unsetDisposable = function () { this._bitField = this._bitField & (~131072); this._disposer = undefined; }; Promise.prototype.disposer = function (fn) { if (typeof fn === "function") { return new FunctionDisposer(fn, this, createContext()); } throw new TypeError(); }; }; },{"./errors":12,"./util":36}],36:[function(_dereq_,module,exports){ "use strict"; var es5 = _dereq_("./es5"); var canEvaluate = typeof navigator == "undefined"; var errorObj = {e: {}}; var tryCatchTarget; var globalObject = typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : this !== undefined ? this : null; function tryCatcher() { try { var target = tryCatchTarget; tryCatchTarget = null; return target.apply(this, arguments); } catch (e) { errorObj.e = e; return errorObj; } } function tryCatch(fn) { tryCatchTarget = fn; return tryCatcher; } 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 isPrimitive(val) { return val == null || val === true || val === false || typeof val === "string" || typeof val === "number"; } function isObject(value) { return typeof value === "function" || typeof value === "object" && value !== null; } function maybeWrapAsError(maybeError) { if (!isPrimitive(maybeError)) return maybeError; return new Error(safeToString(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 getDataPropertyOrDefault(obj, key, defaultValue) { if (es5.isES5) { var desc = Object.getOwnPropertyDescriptor(obj, key); if (desc != null) { return desc.get == null && desc.set == null ? desc.value : defaultValue; } } else { return {}.hasOwnProperty.call(obj, key) ? obj[key] : undefined; } } 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; } function thrower(r) { throw r; } var inheritedDataKeys = (function() { var excludedPrototypes = [ Array.prototype, Object.prototype, Function.prototype ]; var isExcludedProto = function(val) { for (var i = 0; i < excludedPrototypes.length; ++i) { if (excludedPrototypes[i] === val) { return true; } } return false; }; if (es5.isES5) { var getKeys = Object.getOwnPropertyNames; return function(obj) { var ret = []; var visitedKeys = Object.create(null); while (obj != null && !isExcludedProto(obj)) { var keys; try { keys = getKeys(obj); } catch (e) { return ret; } for (var i = 0; i < keys.length; ++i) { var key = keys[i]; if (visitedKeys[key]) continue; visitedKeys[key] = true; var desc = Object.getOwnPropertyDescriptor(obj, key); if (desc != null && desc.get == null && desc.set == null) { ret.push(key); } } obj = es5.getPrototypeOf(obj); } return ret; }; } else { var hasProp = {}.hasOwnProperty; return function(obj) { if (isExcludedProto(obj)) return []; var ret = []; /*jshint forin:false */ enumeration: for (var key in obj) { if (hasProp.call(obj, key)) { ret.push(key); } else { for (var i = 0; i < excludedPrototypes.length; ++i) { if (hasProp.call(excludedPrototypes[i], key)) { continue enumeration; } } ret.push(key); } } return ret; }; } })(); var thisAssignmentPattern = /this\s*\.\s*\S+\s*=/; function isClass(fn) { try { if (typeof fn === "function") { var keys = es5.names(fn.prototype); var hasMethods = es5.isES5 && keys.length > 1; var hasMethodsOtherThanConstructor = keys.length > 0 && !(keys.length === 1 && keys[0] === "constructor"); var hasThisAssignmentAndStaticMethods = thisAssignmentPattern.test(fn + "") && es5.names(fn).length > 0; if (hasMethods || hasMethodsOtherThanConstructor || hasThisAssignmentAndStaticMethods) { return true; } } return false; } catch (e) { return false; } } function toFastProperties(obj) { /*jshint -W027,-W055,-W031*/ function FakeConstructor() {} FakeConstructor.prototype = obj; var l = 8; while (l--) new FakeConstructor(); return obj; eval(obj); } var rident = /^[a-z$_][a-z$_0-9]*$/i; function isIdentifier(str) { return rident.test(str); } function filledRange(count, prefix, suffix) { var ret = new Array(count); for(var i = 0; i < count; ++i) { ret[i] = prefix + i + suffix; } return ret; } function safeToString(obj) { try { return obj + ""; } catch (e) { return "[no string representation]"; } } function isError(obj) { return obj !== null && typeof obj === "object" && typeof obj.message === "string" && typeof obj.name === "string"; } function markAsOriginatingFromRejection(e) { try { notEnumerableProp(e, "isOperational", true); } catch(ignore) {} } function originatesFromRejection(e) { if (e == null) return false; return ((e instanceof Error["__BluebirdErrorTypes__"].OperationalError) || e["isOperational"] === true); } function canAttachTrace(obj) { return isError(obj) && es5.propertyIsWritable(obj, "stack"); } var ensureErrorObject = (function() { if (!("stack" in new Error())) { return function(value) { if (canAttachTrace(value)) return value; try {throw new Error(safeToString(value));} catch(err) {return err;} }; } else { return function(value) { if (canAttachTrace(value)) return value; return new Error(safeToString(value)); }; } })(); function classString(obj) { return {}.toString.call(obj); } function copyDescriptors(from, to, filter) { var keys = es5.names(from); for (var i = 0; i < keys.length; ++i) { var key = keys[i]; if (filter(key)) { try { es5.defineProperty(to, key, es5.getDescriptor(from, key)); } catch (ignore) {} } } } var asArray = function(v) { if (es5.isArray(v)) { return v; } return null; }; if (typeof Symbol !== "undefined" && Symbol.iterator) { var ArrayFrom = typeof Array.from === "function" ? function(v) { return Array.from(v); } : function(v) { var ret = []; var it = v[Symbol.iterator](); var itResult; while (!((itResult = it.next()).done)) { ret.push(itResult.value); } return ret; }; asArray = function(v) { if (es5.isArray(v)) { return v; } else if (v != null && typeof v[Symbol.iterator] === "function") { return ArrayFrom(v); } return null; }; } var isNode = typeof process !== "undefined" && classString(process).toLowerCase() === "[object process]"; function env(key, def) { return isNode ? process.env[key] : def; } function getNativePromise() { if (typeof Promise === "function") { try { var promise = new Promise(function(){}); if ({}.toString.call(promise) === "[object Promise]") { return Promise; } } catch (e) {} } } var ret = { isClass: isClass, isIdentifier: isIdentifier, inheritedDataKeys: inheritedDataKeys, getDataPropertyOrDefault: getDataPropertyOrDefault, thrower: thrower, isArray: es5.isArray, asArray: asArray, notEnumerableProp: notEnumerableProp, isPrimitive: isPrimitive, isObject: isObject, isError: isError, canEvaluate: canEvaluate, errorObj: errorObj, tryCatch: tryCatch, inherits: inherits, withAppended: withAppended, maybeWrapAsError: maybeWrapAsError, toFastProperties: toFastProperties, filledRange: filledRange, toString: safeToString, canAttachTrace: canAttachTrace, ensureErrorObject: ensureErrorObject, originatesFromRejection: originatesFromRejection, markAsOriginatingFromRejection: markAsOriginatingFromRejection, classString: classString, copyDescriptors: copyDescriptors, hasDevTools: typeof chrome !== "undefined" && chrome && typeof chrome.loadTimes === "function", isNode: isNode, env: env, global: globalObject, getNativePromise: getNativePromise }; ret.isRecentNode = ret.isNode && (function() { var version = process.versions.node.split(".").map(Number); return (version[0] === 0 && version[1] > 10) || (version[0] > 0); })(); if (ret.isNode) ret.toFastProperties(process); try {throw new Error(); } catch (e) {ret.lastLineError = e;} module.exports = ret; },{"./es5":13}]},{},[4])(4) }); ;if (typeof window !== 'undefined' && window !== null) { window.P = window.Promise; } else if (typeof self !== 'undefined' && self !== null) { self.P = self.Promise; } /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(20), __webpack_require__(0), __webpack_require__(7).setImmediate)) /***/ }, /* 91 */ /***/ function(module, exports, __webpack_require__) { var core = __webpack_require__(15) , $JSON = core.JSON || (core.JSON = {stringify: JSON.stringify}); module.exports = function stringify(it){ // eslint-disable-line no-unused-vars return $JSON.stringify.apply($JSON, arguments); }; /***/ }, /* 92 */ /***/ function(module, exports, __webpack_require__) { __webpack_require__(117); module.exports = __webpack_require__(15).Object.assign; /***/ }, /* 93 */ /***/ function(module, exports, __webpack_require__) { __webpack_require__(118); var $Object = __webpack_require__(15).Object; module.exports = function defineProperty(it, key, desc){ return $Object.defineProperty(it, key, desc); }; /***/ }, /* 94 */ /***/ function(module, exports) { module.exports = function(it){ if(typeof it != 'function')throw TypeError(it + ' is not a function!'); return it; }; /***/ }, /* 95 */ /***/ function(module, exports, __webpack_require__) { var isObject = __webpack_require__(24); module.exports = function(it){ if(!isObject(it))throw TypeError(it + ' is not an object!'); return it; }; /***/ }, /* 96 */ /***/ function(module, exports, __webpack_require__) { // false -> Array#indexOf // true -> Array#includes var toIObject = __webpack_require__(55) , toLength = __webpack_require__(113) , toIndex = __webpack_require__(112); module.exports = function(IS_INCLUDES){ return function($this, el, fromIndex){ var O = toIObject($this) , length = toLength(O.length) , index = toIndex(fromIndex, length) , value; // Array#includes uses SameValueZero equality algorithm if(IS_INCLUDES && el != el)while(length > index){ value = O[index++]; if(value != value)return true; // Array#toIndex ignores holes, Array#includes - not } else for(;length > index; index++)if(IS_INCLUDES || index in O){ if(O[index] === el)return IS_INCLUDES || index || 0; } return !IS_INCLUDES && -1; }; }; /***/ }, /* 97 */ /***/ function(module, exports) { var toString = {}.toString; module.exports = function(it){ return toString.call(it).slice(8, -1); }; /***/ }, /* 98 */ /***/ function(module, exports, __webpack_require__) { // optional / simple context binding var aFunction = __webpack_require__(94); module.exports = function(fn, that, length){ aFunction(fn); if(that === undefined)return fn; switch(length){ case 1: return function(a){ return fn.call(that, a); }; case 2: return function(a, b){ return fn.call(that, a, b); }; case 3: return function(a, b, c){ return fn.call(that, a, b, c); }; } return function(/* ...args */){ return fn.apply(that, arguments); }; }; /***/ }, /* 99 */ /***/ function(module, exports, __webpack_require__) { var isObject = __webpack_require__(24) , document = __webpack_require__(23).document // in old IE typeof document.createElement is 'object' , is = isObject(document) && isObject(document.createElement); module.exports = function(it){ return is ? document.createElement(it) : {}; }; /***/ }, /* 100 */ /***/ function(module, exports) { // IE 8- don't enum bug keys module.exports = ( 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf' ).split(','); /***/ }, /* 101 */ /***/ function(module, exports) { var hasOwnProperty = {}.hasOwnProperty; module.exports = function(it, key){ return hasOwnProperty.call(it, key); }; /***/ }, /* 102 */ /***/ function(module, exports, __webpack_require__) { var dP = __webpack_require__(53) , createDesc = __webpack_require__(109); module.exports = __webpack_require__(16) ? function(object, key, value){ return dP.f(object, key, createDesc(1, value)); } : function(object, key, value){ object[key] = value; return object; }; /***/ }, /* 103 */ /***/ function(module, exports, __webpack_require__) { module.exports = !__webpack_require__(16) && !__webpack_require__(22)(function(){ return Object.defineProperty(__webpack_require__(99)('div'), 'a', {get: function(){ return 7; }}).a != 7; }); /***/ }, /* 104 */ /***/ function(module, exports, __webpack_require__) { "use strict"; 'use strict'; // 19.1.2.1 Object.assign(target, source, ...) var getKeys = __webpack_require__(107) , gOPS = __webpack_require__(105) , pIE = __webpack_require__(108) , toObject = __webpack_require__(114) , IObject = __webpack_require__(52) , $assign = Object.assign; // should work with symbols and should have deterministic property order (V8 bug) module.exports = !$assign || __webpack_require__(22)(function(){ var A = {} , B = {} , S = Symbol() , K = 'abcdefghijklmnopqrst'; A[S] = 7; K.split('').forEach(function(k){ B[k] = k; }); return $assign({}, A)[S] != 7 || Object.keys($assign({}, B)).join('') != K; }) ? function assign(target, source){ // eslint-disable-line no-unused-vars var T = toObject(target) , aLen = arguments.length , index = 1 , getSymbols = gOPS.f , isEnum = pIE.f; while(aLen > index){ var S = IObject(arguments[index++]) , keys = getSymbols ? getKeys(S).concat(getSymbols(S)) : getKeys(S) , length = keys.length , j = 0 , key; while(length > j)if(isEnum.call(S, key = keys[j++]))T[key] = S[key]; } return T; } : $assign; /***/ }, /* 105 */ /***/ function(module, exports) { exports.f = Object.getOwnPropertySymbols; /***/ }, /* 106 */ /***/ function(module, exports, __webpack_require__) { var has = __webpack_require__(101) , toIObject = __webpack_require__(55) , arrayIndexOf = __webpack_require__(96)(false) , IE_PROTO = __webpack_require__(110)('IE_PROTO'); module.exports = function(object, names){ var O = toIObject(object) , i = 0 , result = [] , key; for(key in O)if(key != IE_PROTO)has(O, key) && result.push(key); // Don't enum bug & hidden keys while(names.length > i)if(has(O, key = names[i++])){ ~arrayIndexOf(result, key) || result.push(key); } return result; }; /***/ }, /* 107 */ /***/ function(module, exports, __webpack_require__) { // 19.1.2.14 / 15.2.3.14 Object.keys(O) var $keys = __webpack_require__(106) , enumBugKeys = __webpack_require__(100); module.exports = Object.keys || function keys(O){ return $keys(O, enumBugKeys); }; /***/ }, /* 108 */ /***/ function(module, exports) { exports.f = {}.propertyIsEnumerable; /***/ }, /* 109 */ /***/ function(module, exports) { module.exports = function(bitmap, value){ return { enumerable : !(bitmap & 1), configurable: !(bitmap & 2), writable : !(bitmap & 4), value : value }; }; /***/ }, /* 110 */ /***/ function(module, exports, __webpack_require__) { var shared = __webpack_require__(111)('keys') , uid = __webpack_require__(116); module.exports = function(key){ return shared[key] || (shared[key] = uid(key)); }; /***/ }, /* 111 */ /***/ function(module, exports, __webpack_require__) { var global = __webpack_require__(23) , SHARED = '__core-js_shared__' , store = global[SHARED] || (global[SHARED] = {}); module.exports = function(key){ return store[key] || (store[key] = {}); }; /***/ }, /* 112 */ /***/ function(module, exports, __webpack_require__) { var toInteger = __webpack_require__(54) , max = Math.max , min = Math.min; module.exports = function(index, length){ index = toInteger(index); return index < 0 ? max(index + length, 0) : min(index, length); }; /***/ }, /* 113 */ /***/ function(module, exports, __webpack_require__) { // 7.1.15 ToLength var toInteger = __webpack_require__(54) , min = Math.min; module.exports = function(it){ return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991 }; /***/ }, /* 114 */ /***/ function(module, exports, __webpack_require__) { // 7.1.13 ToObject(argument) var defined = __webpack_require__(50); module.exports = function(it){ return Object(defined(it)); }; /***/ }, /* 115 */ /***/ function(module, exports, __webpack_require__) { // 7.1.1 ToPrimitive(input [, PreferredType]) var isObject = __webpack_require__(24); // instead of the ES6 spec version, we didn't implement @@toPrimitive case // and the second argument - flag - preferred type is a string module.exports = function(it, S){ if(!isObject(it))return it; var fn, val; if(S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val; if(typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it)))return val; if(!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it)))return val; throw TypeError("Can't convert object to primitive value"); }; /***/ }, /* 116 */ /***/ function(module, exports) { var id = 0 , px = Math.random(); module.exports = function(key){ return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36)); }; /***/ }, /* 117 */ /***/ function(module, exports, __webpack_require__) { // 19.1.3.1 Object.assign(target, source) var $export = __webpack_require__(51); $export($export.S + $export.F, 'Object', {assign: __webpack_require__(104)}); /***/ }, /* 118 */ /***/ function(module, exports, __webpack_require__) { var $export = __webpack_require__(51); // 19.1.2.4 / 15.2.3.6 Object.defineProperty(O, P, Attributes) $export($export.S + $export.F * !__webpack_require__(16), 'Object', {defineProperty: __webpack_require__(53).f}); /***/ }, /* 119 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(setImmediate, clearImmediate) {var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;/* * @name Lazy.js * * @fileOverview * Lazy.js is a lazy evaluation library for JavaScript. * * This has been done before. For examples see: * * - [wu.js](http://fitzgen.github.io/wu.js/) * - [Linq.js](http://linqjs.codeplex.com/) * - [from.js](https://github.com/suckgamoni/fromjs/) * - [IxJS](http://rx.codeplex.com/) * - [sloth.js](http://rfw.name/sloth.js/) * * However, at least at present, Lazy.js is faster (on average) than any of * those libraries. It is also more complete, with nearly all of the * functionality of [Underscore](http://underscorejs.org/) and * [Lo-Dash](http://lodash.com/). * * Finding your way around the code * -------------------------------- * * At the heart of Lazy.js is the {@link Sequence} object. You create an initial * sequence using {@link Lazy}, which can accept an array, object, or string. * You can then "chain" together methods from this sequence, creating a new * sequence with each call. * * Here's an example: * * var data = getReallyBigArray(); * * var statistics = Lazy(data) * .map(transform) * .filter(validate) * .reduce(aggregate); * * {@link Sequence} is the foundation of other, more specific sequence types. * * An {@link ArrayLikeSequence} provides indexed access to its elements. * * An {@link ObjectLikeSequence} consists of key/value pairs. * * A {@link StringLikeSequence} is like a string (duh): actually, it is an * {@link ArrayLikeSequence} whose elements happen to be characters. * * An {@link AsyncSequence} is special: it iterates over its elements * asynchronously (so calling `each` generally begins an asynchronous loop and * returns immediately). * * For more information * -------------------- * * I wrote a blog post that explains a little bit more about Lazy.js, which you * can read [here](http://philosopherdeveloper.com/posts/introducing-lazy-js.html). * * You can also [create an issue on GitHub](https://github.com/dtao/lazy.js/issues) * if you have any issues with the library. I work through them eventually. * * [@dtao](https://github.com/dtao) */ (function(root, factory) { if (true) { !(__WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); } else if (typeof exports === 'object') { module.exports = factory(); } else { root.Lazy = factory(); } })(this, function(context) { /** * Wraps an object and returns a {@link Sequence}. For `null` or `undefined`, * simply returns an empty sequence (see {@link Lazy.strict} for a stricter * implementation). * * - For **arrays**, Lazy will create a sequence comprising the elements in * the array (an {@link ArrayLikeSequence}). * - For **objects**, Lazy will create a sequence of key/value pairs * (an {@link ObjectLikeSequence}). * - For **strings**, Lazy will create a sequence of characters (a * {@link StringLikeSequence}). * * @public * @param {Array|Object|string} source An array, object, or string to wrap. * @returns {Sequence} The wrapped lazy object. * * @exampleHelpers * // Utility functions to provide to all examples * function increment(x) { return x + 1; } * function isEven(x) { return x % 2 === 0; } * function isPositive(x) { return x > 0; } * function isNegative(x) { return x < 0; } * * @examples * Lazy([1, 2, 4]) // instanceof Lazy.ArrayLikeSequence * Lazy({ foo: "bar" }) // instanceof Lazy.ObjectLikeSequence * Lazy("hello, world!") // instanceof Lazy.StringLikeSequence * Lazy() // sequence: [] * Lazy(null) // sequence: [] */ function Lazy(source) { if (source instanceof Array) { return new ArrayWrapper(source); } else if (typeof source === "string") { return new StringWrapper(source); } else if (source instanceof Sequence) { return source; } if (Lazy.extensions) { var extensions = Lazy.extensions, length = extensions.length, result; while (!result && length--) { result = extensions[length](source); } if (result) { return result; } } return new ObjectWrapper(source); } Lazy.VERSION = '0.4.2'; /*** Utility methods of questionable value ***/ Lazy.noop = function noop() {}; Lazy.identity = function identity(x) { return x; }; /** * Provides a stricter version of {@link Lazy} which throws an error when * attempting to wrap `null`, `undefined`, or numeric or boolean values as a * sequence. * * @public * @returns {Function} A stricter version of the {@link Lazy} helper function. * * @examples * var Strict = Lazy.strict(); * * Strict() // throws * Strict(null) // throws * Strict(true) // throws * Strict(5) // throws * Strict([1, 2, 3]) // instanceof Lazy.ArrayLikeSequence * Strict({ foo: "bar" }) // instanceof Lazy.ObjectLikeSequence * Strict("hello, world!") // instanceof Lazy.StringLikeSequence * * // Let's also ensure the static functions are still there. * Strict.range(3) // sequence: [0, 1, 2] * Strict.generate(Date.now) // instanceof Lazy.GeneratedSequence */ Lazy.strict = function strict() { function StrictLazy(source) { if (source == null) { throw new Error("You cannot wrap null or undefined using Lazy."); } if (typeof source === "number" || typeof source === "boolean") { throw new Error("You cannot wrap primitive values using Lazy."); } return Lazy(source); }; Lazy(Lazy).each(function(property, name) { StrictLazy[name] = property; }); return StrictLazy; }; /** * The `Sequence` object provides a unified API encapsulating the notion of * zero or more consecutive elements in a collection, stream, etc. * * Lazy evaluation * --------------- * * Generally speaking, creating a sequence should not be an expensive operation, * and should not iterate over an underlying source or trigger any side effects. * This means that chaining together methods that return sequences incurs only * the cost of creating the `Sequence` objects themselves and not the cost of * iterating an underlying data source multiple times. * * The following code, for example, creates 4 sequences and does nothing with * `source`: * * var seq = Lazy(source) // 1st sequence * .map(func) // 2nd * .filter(pred) // 3rd * .reverse(); // 4th * * Lazy's convention is to hold off on iterating or otherwise *doing* anything * (aside from creating `Sequence` objects) until you call `each`: * * seq.each(function(x) { console.log(x); }); * * Defining custom sequences * ------------------------- * * Defining your own type of sequence is relatively simple: * * 1. Pass a *method name* and an object containing *function overrides* to * {@link Sequence.define}. If the object includes a function called `init`, * this function will be called upon initialization. * 2. The object should include at least either a `getIterator` method or an * `each` method. The former supports both asynchronous and synchronous * iteration, but is slightly more cumbersome to implement. The latter * supports synchronous iteration and can be automatically implemented in * terms of the former. You can also implement both if you want, e.g. to * optimize performance. For more info, see {@link Iterator} and * {@link AsyncSequence}. * * As a trivial example, the following code defines a new method, `sample`, * which randomly may or may not include each element from its parent. * * Lazy.Sequence.define("sample", { * each: function(fn) { * return this.parent.each(function(e) { * // 50/50 chance of including this element. * if (Math.random() > 0.5) { * return fn(e); * } * }); * } * }); * * (Of course, the above could also easily have been implemented using * {@link #filter} instead of creating a custom sequence. But I *did* say this * was a trivial example, to be fair.) * * Now it will be possible to create this type of sequence from any parent * sequence by calling the method name you specified. In other words, you can * now do this: * * Lazy(arr).sample(); * Lazy(arr).map(func).sample(); * Lazy(arr).map(func).filter(pred).sample(); * * Etc., etc. * * @public * @constructor */ function Sequence() {} /** * Create a new constructor function for a type inheriting from `Sequence`. * * @public * @param {string|Array.} methodName The name(s) of the method(s) to be * used for constructing the new sequence. The method will be attached to * the `Sequence` prototype so that it can be chained with any other * sequence methods, like {@link #map}, {@link #filter}, etc. * @param {Object} overrides An object containing function overrides for this * new sequence type. **Must** include either `getIterator` or `each` (or * both). *May* include an `init` method as well. For these overrides, * `this` will be the new sequence, and `this.parent` will be the base * sequence from which the new sequence was constructed. * @returns {Function} A constructor for a new type inheriting from `Sequence`. * * @examples * // This sequence type logs every element to the specified logger as it * // iterates over it. * Lazy.Sequence.define("verbose", { * init: function(logger) { * this.logger = logger; * }, * * each: function(fn) { * var logger = this.logger; * return this.parent.each(function(e, i) { * logger(e); * return fn(e, i); * }); * } * }); * * Lazy([1, 2, 3]).verbose(logger).each(Lazy.noop) // calls logger 3 times */ Sequence.define = function define(methodName, overrides) { if (!overrides || (!overrides.getIterator && !overrides.each)) { throw new Error("A custom sequence must implement *at least* getIterator or each!"); } return defineSequenceType(Sequence, methodName, overrides); }; /** * Gets the number of elements in the sequence. In some cases, this may * require eagerly evaluating the sequence. * * @public * @returns {number} The number of elements in the sequence. * * @examples * Lazy([1, 2, 3]).size(); // => 3 * Lazy([1, 2]).map(Lazy.identity).size(); // => 2 * Lazy([1, 2, 3]).reject(isEven).size(); // => 2 * Lazy([1, 2, 3]).take(1).size(); // => 1 * Lazy({ foo: 1, bar: 2 }).size(); // => 2 * Lazy('hello').size(); // => 5 */ Sequence.prototype.size = function size() { return this.getIndex().length(); }; /** * Creates an {@link Iterator} object with two methods, `moveNext` -- returning * true or false -- and `current` -- returning the current value. * * This method is used when asynchronously iterating over sequences. Any type * inheriting from `Sequence` must implement this method or it can't support * asynchronous iteration. * * Note that **this method is not intended to be used directly by application * code.** Rather, it is intended as a means for implementors to potentially * define custom sequence types that support either synchronous or * asynchronous iteration. * * @public * @returns {Iterator} An iterator object. * * @examples * var iterator = Lazy([1, 2]).getIterator(); * * iterator.moveNext(); // => true * iterator.current(); // => 1 * iterator.moveNext(); // => true * iterator.current(); // => 2 * iterator.moveNext(); // => false */ Sequence.prototype.getIterator = function getIterator() { return new Iterator(this); }; /** * Gets the root sequence underlying the current chain of sequences. */ Sequence.prototype.root = function root() { return this.parent.root(); }; /** * Whether or not the current sequence is an asynchronous one. This is more * accurate than checking `instanceof {@link AsyncSequence}` because, for * example, `Lazy([1, 2, 3]).async().map(Lazy.identity)` returns a sequence * that iterates asynchronously even though it's not an instance of * `AsyncSequence`. * * @returns {boolean} Whether or not the current sequence is an asynchronous one. */ Sequence.prototype.isAsync = function isAsync() { return this.parent ? this.parent.isAsync() : false; }; /** * Evaluates the sequence and produces the appropriate value (an array in most * cases, an object for {@link ObjectLikeSequence}s or a string for * {@link StringLikeSequence}s). * * @returns {Array|string|Object} The value resulting from fully evaluating * the sequence. */ Sequence.prototype.value = function value() { return this.toArray(); }; /** * Applies the current transformation chain to a given source, returning the * resulting value. * * @examples * var sequence = Lazy([]) * .map(function(x) { return x * -1; }) * .filter(function(x) { return x % 2 === 0; }); * * sequence.apply([1, 2, 3, 4]); // => [-2, -4] */ Sequence.prototype.apply = function apply(source) { var root = this.root(), previousSource = root.source, result; try { root.source = source; result = this.value(); } finally { root.source = previousSource; } return result; }; /** * The Iterator object provides an API for iterating over a sequence. * * The purpose of the `Iterator` type is mainly to offer an agnostic way of * iterating over a sequence -- either synchronous (i.e. with a `while` loop) * or asynchronously (with recursive calls to either `setTimeout` or --- if * available --- `setImmediate`). It is not intended to be used directly by * application code. * * @public * @constructor * @param {Sequence} sequence The sequence to iterate over. */ function Iterator(sequence) { this.sequence = sequence; this.index = -1; } /** * Gets the current item this iterator is pointing to. * * @public * @returns {*} The current item. */ Iterator.prototype.current = function current() { return this.cachedIndex && this.cachedIndex.get(this.index); }; /** * Moves the iterator to the next item in a sequence, if possible. * * @public * @returns {boolean} True if the iterator is able to move to a new item, or else * false. */ Iterator.prototype.moveNext = function moveNext() { var cachedIndex = this.cachedIndex; if (!cachedIndex) { cachedIndex = this.cachedIndex = this.sequence.getIndex(); } if (this.index >= cachedIndex.length() - 1) { return false; } ++this.index; return true; }; /** * Creates an array snapshot of a sequence. * * Note that for indefinite sequences, this method may raise an exception or * (worse) cause the environment to hang. * * @public * @returns {Array} An array containing the current contents of the sequence. * * @examples * Lazy([1, 2, 3]).toArray() // => [1, 2, 3] */ Sequence.prototype.toArray = function toArray() { return this.reduce(function(arr, element) { arr.push(element); return arr; }, []); }; /** * Provides an indexed view into the sequence. * * For sequences that are already indexed, this will simply return the * sequence. For non-indexed sequences, this will eagerly evaluate the * sequence. * * @returns {ArrayLikeSequence} A sequence containing the current contents of * the sequence. * * @examples * Lazy([1, 2, 3]).filter(isEven) // instanceof Lazy.Sequence * Lazy([1, 2, 3]).filter(isEven).getIndex() // instanceof Lazy.ArrayLikeSequence */ Sequence.prototype.getIndex = function getIndex() { return new ArrayWrapper(this.toArray()); }; /** * Returns the element at the specified index. Note that, for sequences that * are not {@link ArrayLikeSequence}s, this may require partially evaluating * the sequence, iterating to reach the result. (In other words for such * sequences this method is not O(1).) * * @public * @param {number} i The index to access. * @returns {*} The element. * */ Sequence.prototype.get = function get(i) { var element; this.each(function(e, index) { if (index === i) { element = e; return false; } }); return element; }; /** * Provides an indexed, memoized view into the sequence. This will cache the * result whenever the sequence is first iterated, so that subsequent * iterations will access the same element objects. * * @public * @returns {ArrayLikeSequence} An indexed, memoized sequence containing this * sequence's elements, cached after the first iteration. * * @example * function createObject() { return new Object(); } * * var plain = Lazy.generate(createObject, 10), * memoized = Lazy.generate(createObject, 10).memoize(); * * plain.toArray()[0] === plain.toArray()[0]; // => false * memoized.toArray()[0] === memoized.toArray()[0]; // => true */ Sequence.prototype.memoize = function memoize() { return new MemoizedSequence(this); }; /** * @constructor */ function MemoizedSequence(parent) { this.parent = parent; } // MemoizedSequence needs to have its prototype set up after ArrayLikeSequence /** * Creates an object from a sequence of key/value pairs. * * @public * @returns {Object} An object with keys and values corresponding to the pairs * of elements in the sequence. * * @examples * var details = [ * ["first", "Dan"], * ["last", "Tao"], * ["age", 29] * ]; * * Lazy(details).toObject() // => { first: "Dan", last: "Tao", age: 29 } */ Sequence.prototype.toObject = function toObject() { return this.reduce(function(object, pair) { object[pair[0]] = pair[1]; return object; }, {}); }; /** * Iterates over this sequence and executes a function for every element. * * @public * @aka forEach * @param {Function} fn The function to call on each element in the sequence. * Return false from the function to end the iteration. * @returns {boolean} `true` if the iteration evaluated the entire sequence, * or `false` if iteration was ended early. * * @examples * Lazy([1, 2, 3, 4]).each(fn) // calls fn 4 times */ Sequence.prototype.each = function each(fn) { var iterator = this.getIterator(), i = -1; while (iterator.moveNext()) { if (fn(iterator.current(), ++i) === false) { return false; } } return true; }; Sequence.prototype.forEach = function forEach(fn) { return this.each(fn); }; /** * Creates a new sequence whose values are calculated by passing this sequence's * elements through some mapping function. * * @public * @aka collect * @param {Function} mapFn The mapping function used to project this sequence's * elements onto a new sequence. This function takes up to two arguments: * the element, and the current index. * @returns {Sequence} The new sequence. * * @examples * function addIndexToValue(e, i) { return e + i; } * * Lazy([]).map(increment) // sequence: [] * Lazy([1, 2, 3]).map(increment) // sequence: [2, 3, 4] * Lazy([1, 2, 3]).map(addIndexToValue) // sequence: [1, 3, 5] * * @benchmarks * function increment(x) { return x + 1; } * * var smArr = Lazy.range(10).toArray(), * lgArr = Lazy.range(100).toArray(); * * Lazy(smArr).map(increment).each(Lazy.noop) // lazy - 10 elements * Lazy(lgArr).map(increment).each(Lazy.noop) // lazy - 100 elements * _.each(_.map(smArr, increment), _.noop) // lodash - 10 elements * _.each(_.map(lgArr, increment), _.noop) // lodash - 100 elements */ Sequence.prototype.map = function map(mapFn) { return new MappedSequence(this, createCallback(mapFn)); }; Sequence.prototype.collect = function collect(mapFn) { return this.map(mapFn); }; /** * @constructor */ function MappedSequence(parent, mapFn) { this.parent = parent; this.mapFn = mapFn; } MappedSequence.prototype = new Sequence(); MappedSequence.prototype.getIterator = function getIterator() { return new MappingIterator(this.parent, this.mapFn); }; MappedSequence.prototype.each = function each(fn) { var mapFn = this.mapFn; return this.parent.each(function(e, i) { return fn(mapFn(e, i), i); }); }; /** * @constructor */ function MappingIterator(sequence, mapFn) { this.iterator = sequence.getIterator(); this.mapFn = mapFn; this.index = -1; } MappingIterator.prototype.current = function current() { return this.mapFn(this.iterator.current(), this.index); }; MappingIterator.prototype.moveNext = function moveNext() { if (this.iterator.moveNext()) { ++this.index; return true; } return false; }; /** * Creates a new sequence whose values are calculated by accessing the specified * property from each element in this sequence. * * @public * @param {string} propertyName The name of the property to access for every * element in this sequence. * @returns {Sequence} The new sequence. * * @examples * var people = [ * { first: "Dan", last: "Tao" }, * { first: "Bob", last: "Smith" } * ]; * * Lazy(people).pluck("last") // sequence: ["Tao", "Smith"] */ Sequence.prototype.pluck = function pluck(property) { return this.map(property); }; /** * Creates a new sequence whose values are calculated by invoking the specified * function on each element in this sequence. * * @public * @param {string} methodName The name of the method to invoke for every element * in this sequence. * @returns {Sequence} The new sequence. * * @examples * function Person(first, last) { * this.fullName = function fullName() { * return first + " " + last; * }; * } * * var people = [ * new Person("Dan", "Tao"), * new Person("Bob", "Smith") * ]; * * Lazy(people).invoke("fullName") // sequence: ["Dan Tao", "Bob Smith"] */ Sequence.prototype.invoke = function invoke(methodName) { return this.map(function(e) { return e[methodName](); }); }; /** * Creates a new sequence whose values are the elements of this sequence which * satisfy the specified predicate. * * @public * @aka select * @param {Function} filterFn The predicate to call on each element in this * sequence, which returns true if the element should be included. * @returns {Sequence} The new sequence. * * @examples * var numbers = [1, 2, 3, 4, 5, 6]; * * Lazy(numbers).filter(isEven) // sequence: [2, 4, 6] * * @benchmarks * function isEven(x) { return x % 2 === 0; } * * var smArr = Lazy.range(10).toArray(), * lgArr = Lazy.range(100).toArray(); * * Lazy(smArr).filter(isEven).each(Lazy.noop) // lazy - 10 elements * Lazy(lgArr).filter(isEven).each(Lazy.noop) // lazy - 100 elements * _.each(_.filter(smArr, isEven), _.noop) // lodash - 10 elements * _.each(_.filter(lgArr, isEven), _.noop) // lodash - 100 elements */ Sequence.prototype.filter = function filter(filterFn) { return new FilteredSequence(this, createCallback(filterFn)); }; Sequence.prototype.select = function select(filterFn) { return this.filter(filterFn); }; /** * @constructor */ function FilteredSequence(parent, filterFn) { this.parent = parent; this.filterFn = filterFn; } FilteredSequence.prototype = new Sequence(); FilteredSequence.prototype.getIterator = function getIterator() { return new FilteringIterator(this.parent, this.filterFn); }; FilteredSequence.prototype.each = function each(fn) { var filterFn = this.filterFn, j = 0; return this.parent.each(function(e, i) { if (filterFn(e, i)) { return fn(e, j++); } }); }; FilteredSequence.prototype.reverse = function reverse() { return this.parent.reverse().filter(this.filterFn); }; /** * @constructor */ function FilteringIterator(sequence, filterFn) { this.iterator = sequence.getIterator(); this.filterFn = filterFn; this.index = 0; } FilteringIterator.prototype.current = function current() { return this.value; }; FilteringIterator.prototype.moveNext = function moveNext() { var iterator = this.iterator, filterFn = this.filterFn, value; while (iterator.moveNext()) { value = iterator.current(); if (filterFn(value, this.index++)) { this.value = value; return true; } } this.value = undefined; return false; }; /** * Creates a new sequence whose values exclude the elements of this sequence * identified by the specified predicate. * * @public * @param {Function} rejectFn The predicate to call on each element in this * sequence, which returns true if the element should be omitted. * @returns {Sequence} The new sequence. * * @examples * Lazy([1, 2, 3, 4, 5]).reject(isEven) // sequence: [1, 3, 5] * Lazy([{ foo: 1 }, { bar: 2 }]).reject('foo') // sequence: [{ bar: 2 }] * Lazy([{ foo: 1 }, { foo: 2 }]).reject({ foo: 2 }) // sequence: [{ foo: 1 }] */ Sequence.prototype.reject = function reject(rejectFn) { rejectFn = createCallback(rejectFn); return this.filter(function(e) { return !rejectFn(e); }); }; /** * Creates a new sequence whose values have the specified type, as determined * by the `typeof` operator. * * @public * @param {string} type The type of elements to include from the underlying * sequence, i.e. where `typeof [element] === [type]`. * @returns {Sequence} The new sequence, comprising elements of the specified * type. * * @examples * Lazy([1, 2, 'foo', 'bar']).ofType('number') // sequence: [1, 2] * Lazy([1, 2, 'foo', 'bar']).ofType('string') // sequence: ['foo', 'bar'] * Lazy([1, 2, 'foo', 'bar']).ofType('boolean') // sequence: [] */ Sequence.prototype.ofType = function ofType(type) { return this.filter(function(e) { return typeof e === type; }); }; /** * Creates a new sequence whose values are the elements of this sequence with * property names and values matching those of the specified object. * * @public * @param {Object} properties The properties that should be found on every * element that is to be included in this sequence. * @returns {Sequence} The new sequence. * * @examples * var people = [ * { first: "Dan", last: "Tao" }, * { first: "Bob", last: "Smith" } * ]; * * Lazy(people).where({ first: "Dan" }) // sequence: [{ first: "Dan", last: "Tao" }] * * @benchmarks * var animals = ["dog", "cat", "mouse", "horse", "pig", "snake"]; * * Lazy(animals).where({ length: 3 }).each(Lazy.noop) // lazy * _.each(_.where(animals, { length: 3 }), _.noop) // lodash */ Sequence.prototype.where = function where(properties) { return this.filter(properties); }; /** * Creates a new sequence with the same elements as this one, but to be iterated * in the opposite order. * * Note that in some (but not all) cases, the only way to create such a sequence * may require iterating the entire underlying source when `each` is called. * * @public * @returns {Sequence} The new sequence. * * @examples * Lazy([1, 2, 3]).reverse() // sequence: [3, 2, 1] * Lazy([]).reverse() // sequence: [] */ Sequence.prototype.reverse = function reverse() { return new ReversedSequence(this); }; /** * @constructor */ function ReversedSequence(parent) { this.parent = parent; } ReversedSequence.prototype = new Sequence(); ReversedSequence.prototype.getIterator = function getIterator() { return new ReversedIterator(this.parent); }; /** * @constuctor */ function ReversedIterator(sequence) { this.sequence = sequence; } ReversedIterator.prototype.current = function current() { return this.getIndex().get(this.index); }; ReversedIterator.prototype.moveNext = function moveNext() { var index = this.getIndex(), length = index.length(); if (typeof this.index === "undefined") { this.index = length; } return (--this.index >= 0); }; ReversedIterator.prototype.getIndex = function getIndex() { if (!this.cachedIndex) { this.cachedIndex = this.sequence.getIndex(); } return this.cachedIndex; }; /** * Creates a new sequence with all of the elements of this one, plus those of * the given array(s). * * @public * @param {...*} var_args One or more values (or arrays of values) to use for * additional items after this sequence. * @returns {Sequence} The new sequence. * * @examples * var left = [1, 2, 3]; * var right = [4, 5, 6]; * * Lazy(left).concat(right) // sequence: [1, 2, 3, 4, 5, 6] * Lazy(left).concat(Lazy(right)) // sequence: [1, 2, 3, 4, 5, 6] * Lazy(left).concat(right, [7, 8]) // sequence: [1, 2, 3, 4, 5, 6, 7, 8] */ Sequence.prototype.concat = function concat(var_args) { return new ConcatenatedSequence(this, arraySlice.call(arguments, 0)); }; /** * @constructor */ function ConcatenatedSequence(parent, arrays) { this.parent = parent; this.arrays = arrays; } ConcatenatedSequence.prototype = new Sequence(); ConcatenatedSequence.prototype.each = function each(fn) { var done = false, i = 0; this.parent.each(function(e) { if (fn(e, i++) === false) { done = true; return false; } }); if (!done) { Lazy(this.arrays).flatten().each(function(e) { if (fn(e, i++) === false) { return false; } }); } }; /** * Creates a new sequence comprising the first N elements from this sequence, OR * (if N is `undefined`) simply returns the first element of this sequence. * * @public * @aka head, take * @param {number=} count The number of elements to take from this sequence. If * this value exceeds the length of the sequence, the resulting sequence * will be essentially the same as this one. * @returns {*} The new sequence (or the first element from this sequence if * no count was given). * * @examples * function powerOfTwo(exp) { * return Math.pow(2, exp); * } * * Lazy.generate(powerOfTwo).first() // => 1 * Lazy.generate(powerOfTwo).first(5) // sequence: [1, 2, 4, 8, 16] * Lazy.generate(powerOfTwo).skip(2).first() // => 4 * Lazy.generate(powerOfTwo).skip(2).first(2) // sequence: [4, 8] */ Sequence.prototype.first = function first(count) { if (typeof count === "undefined") { return getFirst(this); } return new TakeSequence(this, count); }; Sequence.prototype.head = Sequence.prototype.take = function (count) { return this.first(count); }; /** * @constructor */ function TakeSequence(parent, count) { this.parent = parent; this.count = count; } TakeSequence.prototype = new Sequence(); TakeSequence.prototype.getIterator = function getIterator() { return new TakeIterator(this.parent, this.count); }; TakeSequence.prototype.each = function each(fn) { var count = this.count, i = 0; var result; var handle = this.parent.each(function(e) { if (i < count) { result = fn(e, i++); } if (i >= count) { return false; } return result; }); if (handle instanceof AsyncHandle) { return handle; } return i === count && result !== false; }; /** * @constructor */ function TakeIterator(sequence, count) { this.iterator = sequence.getIterator(); this.count = count; } TakeIterator.prototype.current = function current() { return this.iterator.current(); }; TakeIterator.prototype.moveNext = function moveNext() { return ((--this.count >= 0) && this.iterator.moveNext()); }; /** * Creates a new sequence comprising the elements from the head of this sequence * that satisfy some predicate. Once an element is encountered that doesn't * satisfy the predicate, iteration will stop. * * @public * @param {Function} predicate * @returns {Sequence} The new sequence * * @examples * function lessThan(x) { * return function(y) { * return y < x; * }; * } * * Lazy([1, 2, 3, 4]).takeWhile(lessThan(3)) // sequence: [1, 2] * Lazy([1, 2, 3, 4]).takeWhile(lessThan(0)) // sequence: [] */ Sequence.prototype.takeWhile = function takeWhile(predicate) { return new TakeWhileSequence(this, predicate); }; /** * @constructor */ function TakeWhileSequence(parent, predicate) { this.parent = parent; this.predicate = predicate; } TakeWhileSequence.prototype = new Sequence(); TakeWhileSequence.prototype.each = function each(fn) { var predicate = this.predicate, finished = false, j = 0; var result = this.parent.each(function(e, i) { if (!predicate(e, i)) { finished = true; return false; } return fn(e, j++); }); if (result instanceof AsyncHandle) { return result; } return finished; }; /** * Creates a new sequence comprising all but the last N elements of this * sequence. * * @public * @param {number=} count The number of items to omit from the end of the * sequence (defaults to 1). * @returns {Sequence} The new sequence. * * @examples * Lazy([1, 2, 3, 4]).initial() // sequence: [1, 2, 3] * Lazy([1, 2, 3, 4]).initial(2) // sequence: [1, 2] * Lazy([1, 2, 3]).filter(Lazy.identity).initial() // sequence: [1, 2] */ Sequence.prototype.initial = function initial(count) { return new InitialSequence(this, count); }; function InitialSequence(parent, count) { this.parent = parent; this.count = typeof count === "number" ? count : 1; } InitialSequence.prototype = new Sequence(); InitialSequence.prototype.each = function each(fn) { var index = this.parent.getIndex(); return index.take(index.length() - this.count).each(fn); }; /** * Creates a new sequence comprising the last N elements of this sequence, OR * (if N is `undefined`) simply returns the last element of this sequence. * * @public * @param {number=} count The number of items to take from the end of the * sequence. * @returns {*} The new sequence (or the last element from this sequence * if no count was given). * * @examples * Lazy([1, 2, 3]).last() // => 3 * Lazy([1, 2, 3]).last(2) // sequence: [2, 3] * Lazy([1, 2, 3]).filter(isEven).last(2) // sequence: [2] */ Sequence.prototype.last = function last(count) { if (typeof count === "undefined") { return this.reverse().first(); } return this.reverse().take(count).reverse(); }; /** * Returns the first element in this sequence with property names and values * matching those of the specified object. * * @public * @param {Object} properties The properties that should be found on some * element in this sequence. * @returns {*} The found element, or `undefined` if none exists in this * sequence. * * @examples * var words = ["foo", "bar"]; * * Lazy(words).findWhere({ 0: "f" }); // => "foo" * Lazy(words).findWhere({ 0: "z" }); // => undefined */ Sequence.prototype.findWhere = function findWhere(properties) { return this.where(properties).first(); }; /** * Creates a new sequence comprising all but the first N elements of this * sequence. * * @public * @aka skip, tail, rest * @param {number=} count The number of items to omit from the beginning of the * sequence (defaults to 1). * @returns {Sequence} The new sequence. * * @examples * Lazy([1, 2, 3, 4]).rest() // sequence: [2, 3, 4] * Lazy([1, 2, 3, 4]).rest(0) // sequence: [1, 2, 3, 4] * Lazy([1, 2, 3, 4]).rest(2) // sequence: [3, 4] * Lazy([1, 2, 3, 4]).rest(5) // sequence: [] */ Sequence.prototype.rest = function rest(count) { return new DropSequence(this, count); }; Sequence.prototype.skip = Sequence.prototype.tail = Sequence.prototype.drop = function drop(count) { return this.rest(count); }; /** * @constructor */ function DropSequence(parent, count) { this.parent = parent; this.count = typeof count === "number" ? count : 1; } DropSequence.prototype = new Sequence(); DropSequence.prototype.each = function each(fn) { var count = this.count, dropped = 0, i = 0; return this.parent.each(function(e) { if (dropped++ < count) { return; } return fn(e, i++); }); }; /** * Creates a new sequence comprising the elements from this sequence *after* * those that satisfy some predicate. The sequence starts with the first * element that does not match the predicate. * * @public * @aka skipWhile * @param {Function} predicate * @returns {Sequence} The new sequence */ Sequence.prototype.dropWhile = function dropWhile(predicate) { return new DropWhileSequence(this, predicate); }; Sequence.prototype.skipWhile = function skipWhile(predicate) { return this.dropWhile(predicate); }; /** * @constructor */ function DropWhileSequence(parent, predicate) { this.parent = parent; this.predicate = predicate; } DropWhileSequence.prototype = new Sequence(); DropWhileSequence.prototype.each = function each(fn) { var predicate = this.predicate, done = false; return this.parent.each(function(e) { if (!done) { if (predicate(e)) { return; } done = true; } return fn(e); }); }; /** * Creates a new sequence with the same elements as this one, but ordered * using the specified comparison function. * * This has essentially the same behavior as calling * [`Array#sort`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort), * but obviously instead of modifying the collection it returns a new * {@link Sequence} object. * * @public * @param {Function=} sortFn The function used to compare elements in the * sequence. The function will be passed two elements and should return: * - 1 if the first is greater * - -1 if the second is greater * - 0 if the two values are the same * @param {boolean} descending Whether or not the resulting sequence should be * in descending order (defaults to `false`). * @returns {Sequence} The new sequence. * * @examples * Lazy([5, 10, 1]).sort() // sequence: [1, 5, 10] * Lazy(['foo', 'bar']).sort() // sequence: ['bar', 'foo'] * Lazy(['b', 'c', 'a']).sort(null, true) // sequence: ['c', 'b', 'a'] * Lazy([5, 10, 1]).sort(null, true) // sequence: [10, 5, 1] * * // Sorting w/ custom comparison function * Lazy(['a', 'ab', 'aa', 'ba', 'b', 'abc']).sort(function compare(x, y) { * if (x.length && (x.length !== y.length)) { return compare(x.length, y.length); } * if (x === y) { return 0; } * return x > y ? 1 : -1; * }); * // => sequence: ['a', 'b', 'aa', 'ab', 'ba', 'abc'] */ Sequence.prototype.sort = function sort(sortFn, descending) { sortFn || (sortFn = compare); if (descending) { sortFn = reverseArguments(sortFn); } return new SortedSequence(this, sortFn); }; /** * Creates a new sequence with the same elements as this one, but ordered by * the results of the given function. * * You can pass: * * - a *string*, to sort by the named property * - a function, to sort by the result of calling the function on each element * * @public * @param {Function} sortFn The function to call on the elements in this * sequence, in order to sort them. * @param {boolean} descending Whether or not the resulting sequence should be * in descending order (defaults to `false`). * @returns {Sequence} The new sequence. * * @examples * function population(country) { * return country.pop; * } * * function area(country) { * return country.sqkm; * } * * var countries = [ * { name: "USA", pop: 320000000, sqkm: 9600000 }, * { name: "Brazil", pop: 194000000, sqkm: 8500000 }, * { name: "Nigeria", pop: 174000000, sqkm: 924000 }, * { name: "China", pop: 1350000000, sqkm: 9700000 }, * { name: "Russia", pop: 143000000, sqkm: 17000000 }, * { name: "Australia", pop: 23000000, sqkm: 7700000 } * ]; * * Lazy(countries).sortBy(population).last(3).pluck('name') // sequence: ["Brazil", "USA", "China"] * Lazy(countries).sortBy(area).last(3).pluck('name') // sequence: ["USA", "China", "Russia"] * Lazy(countries).sortBy(area, true).first(3).pluck('name') // sequence: ["Russia", "China", "USA"] * * @benchmarks * var randoms = Lazy.generate(Math.random).take(100).toArray(); * * Lazy(randoms).sortBy(Lazy.identity).each(Lazy.noop) // lazy * _.each(_.sortBy(randoms, Lazy.identity), _.noop) // lodash */ Sequence.prototype.sortBy = function sortBy(sortFn, descending) { sortFn = createComparator(sortFn); if (descending) { sortFn = reverseArguments(sortFn); } return new SortedSequence(this, sortFn); }; /** * @constructor */ function SortedSequence(parent, sortFn) { this.parent = parent; this.sortFn = sortFn; } SortedSequence.prototype = new Sequence(); SortedSequence.prototype.each = function each(fn) { var sortFn = this.sortFn, result = this.parent.toArray(); result.sort(sortFn); return forEach(result, fn); }; /** * @examples * var items = [{ a: 4 }, { a: 3 }, { a: 5 }]; * * Lazy(items).sortBy('a').reverse(); * // => sequence: [{ a: 5 }, { a: 4 }, { a: 3 }] * * Lazy(items).sortBy('a').reverse().reverse(); * // => sequence: [{ a: 3 }, { a: 4 }, { a: 5 }] */ SortedSequence.prototype.reverse = function reverse() { return new SortedSequence(this.parent, reverseArguments(this.sortFn)); }; /** * Creates a new {@link ObjectLikeSequence} comprising the elements in this * one, grouped together according to some key. The value associated with each * key in the resulting object-like sequence is an array containing all of * the elements in this sequence with that key. * * @public * @param {Function|string} keyFn The function to call on the elements in this * sequence to obtain a key by which to group them, or a string representing * a parameter to read from all the elements in this sequence. * @param {Function|string} valFn (Optional) The function to call on the elements * in this sequence to assign to the value for each instance to appear in the * group, or a string representing a parameter to read from all the elements * in this sequence. * @returns {ObjectLikeSequence} The new sequence. * * @examples * function oddOrEven(x) { * return x % 2 === 0 ? 'even' : 'odd'; * } * function square(x) { * return x*x; * } * * var numbers = [1, 2, 3, 4, 5]; * * Lazy(numbers).groupBy(oddOrEven) // sequence: { odd: [1, 3, 5], even: [2, 4] } * Lazy(numbers).groupBy(oddOrEven).get("odd") // => [1, 3, 5] * Lazy(numbers).groupBy(oddOrEven).get("foo") // => undefined * Lazy(numbers).groupBy(oddOrEven, square).get("even") // => [4, 16] * * Lazy([ * { name: 'toString' }, * { name: 'toString' } * ]).groupBy('name'); * // => sequence: { * 'toString': [ * { name: 'toString' }, * { name: 'toString' } * ] * } */ Sequence.prototype.groupBy = function groupBy(keyFn, valFn) { return new GroupedSequence(this, keyFn, valFn); }; /** * @constructor */ function GroupedSequence(parent, keyFn, valFn) { this.parent = parent; this.keyFn = keyFn; this.valFn = valFn; } // GroupedSequence must have its prototype set after ObjectLikeSequence has // been fully initialized. /** * Creates a new {@link ObjectLikeSequence} comprising the elements in this * one, indexed according to some key. * * @public * @param {Function|string} keyFn The function to call on the elements in this * sequence to obtain a key by which to index them, or a string * representing a property to read from all the elements in this sequence. * @param {Function|string} valFn (Optional) The function to call on the elements * in this sequence to assign to the value of the indexed object, or a string * representing a parameter to read from all the elements in this sequence. * @returns {Sequence} The new sequence. * * @examples * var people = [ * { name: 'Bob', age: 25 }, * { name: 'Fred', age: 34 } * ]; * * var bob = people[0], * fred = people[1]; * * Lazy(people).indexBy('name') // sequence: { 'Bob': bob, 'Fred': fred } * Lazy(people).indexBy('name', 'age') // sequence: { 'Bob': 25, 'Fred': 34 } */ Sequence.prototype.indexBy = function(keyFn, valFn) { return new IndexedSequence(this, keyFn, valFn); }; /** * @constructor */ function IndexedSequence(parent, keyFn, valFn) { this.parent = parent; this.keyFn = keyFn; this.valFn = valFn; } // IndexedSequence must have its prototype set after ObjectLikeSequence has // been fully initialized. /** * Creates a new {@link ObjectLikeSequence} containing the unique keys of all * the elements in this sequence, each paired with the number of elements * in this sequence having that key. * * @public * @param {Function|string} keyFn The function to call on the elements in this * sequence to obtain a key by which to count them, or a string representing * a parameter to read from all the elements in this sequence. * @returns {Sequence} The new sequence. * * @examples * function oddOrEven(x) { * return x % 2 === 0 ? 'even' : 'odd'; * } * * var numbers = [1, 2, 3, 4, 5]; * * Lazy(numbers).countBy(oddOrEven) // sequence: { odd: 3, even: 2 } * Lazy(numbers).countBy(oddOrEven).get("odd") // => 3 * Lazy(numbers).countBy(oddOrEven).get("foo") // => undefined */ Sequence.prototype.countBy = function countBy(keyFn) { return new CountedSequence(this, keyFn); }; /** * @constructor */ function CountedSequence(parent, keyFn) { this.parent = parent; this.keyFn = keyFn; } // CountedSequence, like GroupedSequence, must have its prototype set after // ObjectLikeSequence has been fully initialized. /** * Creates a new sequence with every unique element from this one appearing * exactly once (i.e., with duplicates removed). * * @public * @aka unique * @param {Function} keyFn An optional function to produce the key for each * object. This key is then tested for uniqueness as opposed to the * object reference. * @returns {Sequence} The new sequence. * * @examples * Lazy([1, 2, 2, 3, 3, 3]).uniq() // sequence: [1, 2, 3] * Lazy([{ name: 'mike' }, * { name: 'sarah' }, * { name: 'mike' } * ]).uniq('name') * // sequence: [{ name: 'mike' }, { name: 'sarah' }] * * @benchmarks * function randomOf(array) { * return function() { * return array[Math.floor(Math.random() * array.length)]; * }; * } * * var mostUnique = Lazy.generate(randomOf(_.range(100)), 100).toArray(), * someUnique = Lazy.generate(randomOf(_.range(50)), 100).toArray(), * mostDupes = Lazy.generate(randomOf(_.range(5)), 100).toArray(); * * Lazy(mostUnique).uniq().each(Lazy.noop) // lazy - mostly unique elements * Lazy(someUnique).uniq().each(Lazy.noop) // lazy - some unique elements * Lazy(mostDupes).uniq().each(Lazy.noop) // lazy - mostly duplicate elements * _.each(_.uniq(mostUnique), _.noop) // lodash - mostly unique elements * _.each(_.uniq(someUnique), _.noop) // lodash - some unique elements * _.each(_.uniq(mostDupes), _.noop) // lodash - mostly duplicate elements */ Sequence.prototype.uniq = function uniq(keyFn) { return new UniqueSequence(this, keyFn); }; Sequence.prototype.unique = function unique(keyFn) { return this.uniq(keyFn); }; /** * @constructor */ function UniqueSequence(parent, keyFn) { this.parent = parent; this.keyFn = keyFn; } UniqueSequence.prototype = new Sequence(); UniqueSequence.prototype.each = function each(fn) { var cache = new Set(), keyFn = this.keyFn, i = 0; if (keyFn) { keyFn = createCallback(keyFn); return this.parent.each(function(e) { if (cache.add(keyFn(e))) { return fn(e, i++); } }); } else { return this.parent.each(function(e) { if (cache.add(e)) { return fn(e, i++); } }); } }; /** * Creates a new sequence by combining the elements from this sequence with * corresponding elements from the specified array(s). * * @public * @param {...Array} var_args One or more arrays of elements to combine with * those of this sequence. * @returns {Sequence} The new sequence. * * @examples * Lazy([1, 2]).zip([3, 4]) // sequence: [[1, 3], [2, 4]] * * @benchmarks * var smArrL = Lazy.range(10).toArray(), * smArrR = Lazy.range(10, 20).toArray(), * lgArrL = Lazy.range(100).toArray(), * lgArrR = Lazy.range(100, 200).toArray(); * * Lazy(smArrL).zip(smArrR).each(Lazy.noop) // lazy - zipping 10-element arrays * Lazy(lgArrL).zip(lgArrR).each(Lazy.noop) // lazy - zipping 100-element arrays * _.each(_.zip(smArrL, smArrR), _.noop) // lodash - zipping 10-element arrays * _.each(_.zip(lgArrL, lgArrR), _.noop) // lodash - zipping 100-element arrays */ Sequence.prototype.zip = function zip(var_args) { if (arguments.length === 1) { return new SimpleZippedSequence(this, (/** @type {Array} */ var_args)); } else { return new ZippedSequence(this, arraySlice.call(arguments, 0)); } }; /** * @constructor */ function ZippedSequence(parent, arrays) { this.parent = parent; this.arrays = arrays; } ZippedSequence.prototype = new Sequence(); ZippedSequence.prototype.each = function each(fn) { var arrays = this.arrays, i = 0; this.parent.each(function(e) { var group = [e]; for (var j = 0; j < arrays.length; ++j) { if (arrays[j].length > i) { group.push(arrays[j][i]); } } return fn(group, i++); }); }; /** * Creates a new sequence with the same elements as this one, in a randomized * order. * * @public * @returns {Sequence} The new sequence. * * @examples * Lazy([1, 2, 3, 4, 5]).shuffle().value() // =~ [1, 2, 3, 4, 5] */ Sequence.prototype.shuffle = function shuffle() { return new ShuffledSequence(this); }; /** * @constructor */ function ShuffledSequence(parent) { this.parent = parent; } ShuffledSequence.prototype = new Sequence(); ShuffledSequence.prototype.each = function each(fn) { var shuffled = this.parent.toArray(), floor = Math.floor, random = Math.random, j = 0; for (var i = shuffled.length - 1; i > 0; --i) { swap(shuffled, i, floor(random() * (i + 1))); if (fn(shuffled[i], j++) === false) { return; } } fn(shuffled[0], j); }; /** * Creates a new sequence with every element from this sequence, and with arrays * exploded so that a sequence of arrays (of arrays) becomes a flat sequence of * values. * * @public * @returns {Sequence} The new sequence. * * @examples * Lazy([1, [2, 3], [4, [5]]]).flatten() // sequence: [1, 2, 3, 4, 5] * Lazy([1, Lazy([2, 3])]).flatten() // sequence: [1, 2, 3] */ Sequence.prototype.flatten = function flatten() { return new FlattenedSequence(this); }; /** * @constructor */ function FlattenedSequence(parent) { this.parent = parent; } FlattenedSequence.prototype = new Sequence(); FlattenedSequence.prototype.each = function each(fn) { var index = 0; return this.parent.each(function recurseVisitor(e) { if (e instanceof Array) { return forEach(e, recurseVisitor); } if (e instanceof Sequence) { return e.each(recurseVisitor); } return fn(e, index++); }); }; /** * Creates a new sequence with the same elements as this one, except for all * falsy values (`false`, `0`, `""`, `null`, and `undefined`). * * @public * @returns {Sequence} The new sequence. * * @examples * Lazy(["foo", null, "bar", undefined]).compact() // sequence: ["foo", "bar"] */ Sequence.prototype.compact = function compact() { return this.filter(function(e) { return !!e; }); }; /** * Creates a new sequence with all the elements of this sequence that are not * also among the specified arguments. * * @public * @aka difference * @param {...*} var_args The values, or array(s) of values, to be excluded from the * resulting sequence. * @returns {Sequence} The new sequence. * * @examples * Lazy([1, 2, 3, 4, 5]).without(2, 3) // sequence: [1, 4, 5] * Lazy([1, 2, 3, 4, 5]).without([4, 5]) // sequence: [1, 2, 3] */ Sequence.prototype.without = function without(var_args) { return new WithoutSequence(this, arraySlice.call(arguments, 0)); }; Sequence.prototype.difference = function difference(var_args) { return this.without.apply(this, arguments); }; /** * @constructor */ function WithoutSequence(parent, values) { this.parent = parent; this.values = values; } WithoutSequence.prototype = new Sequence(); WithoutSequence.prototype.each = function each(fn) { var set = createSet(this.values), i = 0; return this.parent.each(function(e) { if (!set.contains(e)) { return fn(e, i++); } }); }; /** * Creates a new sequence with all the unique elements either in this sequence * or among the specified arguments. * * @public * @param {...*} var_args The values, or array(s) of values, to be additionally * included in the resulting sequence. * @returns {Sequence} The new sequence. * * @examples * Lazy(["foo", "bar"]).union([]) // sequence: ["foo", "bar"] * Lazy(["foo", "bar"]).union(["bar", "baz"]) // sequence: ["foo", "bar", "baz"] */ Sequence.prototype.union = function union(var_args) { return this.concat(var_args).uniq(); }; /** * Creates a new sequence with all the elements of this sequence that also * appear among the specified arguments. * * @public * @param {...*} var_args The values, or array(s) of values, in which elements * from this sequence must also be included to end up in the resulting sequence. * @returns {Sequence} The new sequence. * * @examples * Lazy(["foo", "bar"]).intersection([]) // sequence: [] * Lazy(["foo", "bar"]).intersection(["bar", "baz"]) // sequence: ["bar"] */ Sequence.prototype.intersection = function intersection(var_args) { if (arguments.length === 1 && arguments[0] instanceof Array) { return new SimpleIntersectionSequence(this, (/** @type {Array} */ var_args)); } else { return new IntersectionSequence(this, arraySlice.call(arguments, 0)); } }; /** * @constructor */ function IntersectionSequence(parent, arrays) { this.parent = parent; this.arrays = arrays; } IntersectionSequence.prototype = new Sequence(); IntersectionSequence.prototype.each = function each(fn) { var sets = Lazy(this.arrays).map(function(values) { return new UniqueMemoizer(Lazy(values).getIterator()); }); var setIterator = new UniqueMemoizer(sets.getIterator()), i = 0; return this.parent.each(function(e) { var includedInAll = true; setIterator.each(function(set) { if (!set.contains(e)) { includedInAll = false; return false; } }); if (includedInAll) { return fn(e, i++); } }); }; /** * @constructor */ function UniqueMemoizer(iterator) { this.iterator = iterator; this.set = new Set(); this.memo = []; this.currentValue = undefined; } UniqueMemoizer.prototype.current = function current() { return this.currentValue; }; UniqueMemoizer.prototype.moveNext = function moveNext() { var iterator = this.iterator, set = this.set, memo = this.memo, current; while (iterator.moveNext()) { current = iterator.current(); if (set.add(current)) { memo.push(current); this.currentValue = current; return true; } } return false; }; UniqueMemoizer.prototype.each = function each(fn) { var memo = this.memo, length = memo.length, i = -1; while (++i < length) { if (fn(memo[i], i) === false) { return false; } } while (this.moveNext()) { if (fn(this.currentValue, i++) === false) { break; } } }; UniqueMemoizer.prototype.contains = function contains(e) { if (this.set.contains(e)) { return true; } while (this.moveNext()) { if (this.currentValue === e) { return true; } } return false; }; /** * Checks whether every element in this sequence satisfies a given predicate. * * @public * @aka all * @param {Function} predicate A function to call on (potentially) every element * in this sequence. * @returns {boolean} True if `predicate` returns true for every element in the * sequence (or the sequence is empty). False if `predicate` returns false * for at least one element. * * @examples * var numbers = [1, 2, 3, 4, 5]; * * var objects = [{ foo: true }, { foo: false, bar: true }]; * * Lazy(numbers).every(isEven) // => false * Lazy(numbers).every(isPositive) // => true * Lazy(objects).all('foo') // => false * Lazy(objects).all('bar') // => false */ Sequence.prototype.every = function every(predicate) { predicate = createCallback(predicate); return this.each(function(e, i) { return !!predicate(e, i); }); }; Sequence.prototype.all = function all(predicate) { return this.every(predicate); }; /** * Checks whether at least one element in this sequence satisfies a given * predicate (or, if no predicate is specified, whether the sequence contains at * least one element). * * @public * @aka any * @param {Function=} predicate A function to call on (potentially) every element * in this sequence. * @returns {boolean} True if `predicate` returns true for at least one element * in the sequence. False if `predicate` returns false for every element (or * the sequence is empty). * * @examples * var numbers = [1, 2, 3, 4, 5]; * * Lazy(numbers).some() // => true * Lazy(numbers).some(isEven) // => true * Lazy(numbers).some(isNegative) // => false * Lazy([]).some() // => false */ Sequence.prototype.some = function some(predicate) { predicate = createCallback(predicate, true); var success = false; this.each(function(e) { if (predicate(e)) { success = true; return false; } }); return success; }; Sequence.prototype.any = function any(predicate) { return this.some(predicate); }; /** * Checks whether NO elements in this sequence satisfy the given predicate * (the opposite of {@link Sequence#all}, basically). * * @public * @param {Function=} predicate A function to call on (potentially) every element * in this sequence. * @returns {boolean} True if `predicate` does not return true for any element * in the sequence. False if `predicate` returns true for at least one * element. * * @examples * var numbers = [1, 2, 3, 4, 5]; * * Lazy(numbers).none() // => false * Lazy(numbers).none(isEven) // => false * Lazy(numbers).none(isNegative) // => true * Lazy([]).none(isEven) // => true * Lazy([]).none(isNegative) // => true * Lazy([]).none() // => true */ Sequence.prototype.none = function none(predicate) { return !this.any(predicate); }; /** * Checks whether the sequence has no elements. * * @public * @returns {boolean} True if the sequence is empty, false if it contains at * least one element. * * @examples * Lazy([]).isEmpty() // => true * Lazy([1, 2, 3]).isEmpty() // => false */ Sequence.prototype.isEmpty = function isEmpty() { return !this.any(); }; /** * Performs (at worst) a linear search from the head of this sequence, * returning the first index at which the specified value is found. * * @public * @param {*} value The element to search for in the sequence. * @returns {number} The index within this sequence where the given value is * located, or -1 if the sequence doesn't contain the value. * * @examples * function reciprocal(x) { return 1 / x; } * * Lazy(["foo", "bar", "baz"]).indexOf("bar") // => 1 * Lazy([1, 2, 3]).indexOf(4) // => -1 * Lazy([1, 2, 3]).map(reciprocal).indexOf(0.5) // => 1 */ Sequence.prototype.indexOf = function indexOf(value) { var foundIndex = -1; this.each(function(e, i) { if (e === value) { foundIndex = i; return false; } }); return foundIndex; }; /** * Performs (at worst) a linear search from the tail of this sequence, * returning the last index at which the specified value is found. * * @public * @param {*} value The element to search for in the sequence. * @returns {number} The last index within this sequence where the given value * is located, or -1 if the sequence doesn't contain the value. * * @examples * Lazy(["a", "b", "c", "b", "a"]).lastIndexOf("b") // => 3 * Lazy([1, 2, 3]).lastIndexOf(0) // => -1 * Lazy([2, 2, 1, 2, 4]).filter(isEven).lastIndexOf(2) // 2 */ Sequence.prototype.lastIndexOf = function lastIndexOf(value) { var reversed = this.getIndex().reverse(), index = reversed.indexOf(value); if (index !== -1) { index = reversed.length() - index - 1; } return index; }; /** * Performs a binary search of this sequence, returning the lowest index where * the given value is either found, or where it belongs (if it is not already * in the sequence). * * This method assumes the sequence is in sorted order and will fail otherwise. * * @public * @param {*} value The element to search for in the sequence. * @returns {number} An index within this sequence where the given value is * located, or where it belongs in sorted order. * * @examples * Lazy([1, 3, 6, 9]).sortedIndex(3) // => 1 * Lazy([1, 3, 6, 9]).sortedIndex(7) // => 3 * Lazy([5, 10, 15, 20]).filter(isEven).sortedIndex(10) // => 0 * Lazy([5, 10, 15, 20]).filter(isEven).sortedIndex(12) // => 1 */ Sequence.prototype.sortedIndex = function sortedIndex(value) { var indexed = this.getIndex(), lower = 0, upper = indexed.length(), i; while (lower < upper) { i = (lower + upper) >>> 1; if (compare(indexed.get(i), value) === -1) { lower = i + 1; } else { upper = i; } } return lower; }; /** * Checks whether the given value is in this sequence. * * @public * @param {*} value The element to search for in the sequence. * @returns {boolean} True if the sequence contains the value, false if not. * * @examples * var numbers = [5, 10, 15, 20]; * * Lazy(numbers).contains(15) // => true * Lazy(numbers).contains(13) // => false */ Sequence.prototype.contains = function contains(value) { return this.indexOf(value) !== -1; }; /** * Aggregates a sequence into a single value according to some accumulator * function. * * For an asynchronous sequence, instead of immediately returning a result * (which it can't, obviously), this method returns an {@link AsyncHandle} * whose `onComplete` method can be called to supply a callback to handle the * final result once iteration has completed. * * @public * @aka inject, foldl * @param {Function} aggregator The function through which to pass every element * in the sequence. For every element, the function will be passed the total * aggregated result thus far and the element itself, and should return a * new aggregated result. * @param {*=} memo The starting value to use for the aggregated result * (defaults to the first element in the sequence). * @returns {*} The result of the aggregation, or, for asynchronous sequences, * an {@link AsyncHandle} whose `onComplete` method accepts a callback to * handle the final result. * * @examples * function multiply(x, y) { return x * y; } * * var numbers = [1, 2, 3, 4]; * * Lazy(numbers).reduce(multiply) // => 24 * Lazy(numbers).reduce(multiply, 5) // => 120 */ Sequence.prototype.reduce = function reduce(aggregator, memo) { if (arguments.length < 2) { return this.tail().reduce(aggregator, this.head()); } var eachResult = this.each(function(e, i) { memo = aggregator(memo, e, i); }); // TODO: Think of a way more efficient solution to this problem. if (eachResult instanceof AsyncHandle) { return eachResult.then(function() { return memo; }); } return memo; }; Sequence.prototype.inject = Sequence.prototype.foldl = function foldl(aggregator, memo) { return this.reduce(aggregator, memo); }; /** * Aggregates a sequence, from the tail, into a single value according to some * accumulator function. * * @public * @aka foldr * @param {Function} aggregator The function through which to pass every element * in the sequence. For every element, the function will be passed the total * aggregated result thus far and the element itself, and should return a * new aggregated result. * @param {*} memo The starting value to use for the aggregated result. * @returns {*} The result of the aggregation. * * @examples * function append(s1, s2) { * return s1 + s2; * } * * function isVowel(str) { * return "aeiou".indexOf(str) !== -1; * } * * Lazy("abcde").reduceRight(append) // => "edcba" * Lazy("abcde").filter(isVowel).reduceRight(append) // => "ea" */ Sequence.prototype.reduceRight = function reduceRight(aggregator, memo) { if (arguments.length < 2) { return this.initial(1).reduceRight(aggregator, this.last()); } // This bothers me... but frankly, calling reverse().reduce() is potentially // going to eagerly evaluate the sequence anyway; so it's really not an issue. var indexed = this.getIndex(), i = indexed.length() - 1; return indexed.reverse().reduce(function(m, e) { return aggregator(m, e, i--); }, memo); }; Sequence.prototype.foldr = function foldr(aggregator, memo) { return this.reduceRight(aggregator, memo); }; /** * Groups this sequence into consecutive (overlapping) segments of a specified * length. If the underlying sequence has fewer elements than the specfied * length, then this sequence will be empty. * * @public * @param {number} length The length of each consecutive segment. * @returns {Sequence} The resulting sequence of consecutive segments. * * @examples * Lazy([]).consecutive(2) // => sequence: [] * Lazy([1]).consecutive(2) // => sequence: [] * Lazy([1, 2]).consecutive(2) // => sequence: [[1, 2]] * Lazy([1, 2, 3]).consecutive(2) // => sequence: [[1, 2], [2, 3]] * Lazy([1, 2, 3]).consecutive(0) // => sequence: [[]] * Lazy([1, 2, 3]).consecutive(1) // => sequence: [[1], [2], [3]] */ Sequence.prototype.consecutive = function consecutive(count) { var queue = new Queue(count); var segments = this.map(function(element) { if (queue.add(element).count === count) { return queue.toArray(); } }); return segments.compact(); }; /** * Breaks this sequence into chunks (arrays) of a specified length. * * @public * @param {number} size The size of each chunk. * @returns {Sequence} The resulting sequence of chunks. * * @examples * Lazy([]).chunk(2) // sequence: [] * Lazy([1, 2, 3]).chunk(2) // sequence: [[1, 2], [3]] * Lazy([1, 2, 3]).chunk(1) // sequence: [[1], [2], [3]] * Lazy([1, 2, 3]).chunk(4) // sequence: [[1, 2, 3]] * Lazy([1, 2, 3]).chunk(0) // throws */ Sequence.prototype.chunk = function chunk(size) { if (size < 1) { throw new Error("You must specify a positive chunk size."); } return new ChunkedSequence(this, size); }; /** * @constructor */ function ChunkedSequence(parent, size) { this.parent = parent; this.chunkSize = size; } ChunkedSequence.prototype = new Sequence(); ChunkedSequence.prototype.getIterator = function getIterator() { return new ChunkedIterator(this.parent, this.chunkSize); }; /** * @constructor */ function ChunkedIterator(sequence, size) { this.iterator = sequence.getIterator(); this.size = size; } ChunkedIterator.prototype.current = function current() { return this.currentChunk; }; ChunkedIterator.prototype.moveNext = function moveNext() { var iterator = this.iterator, chunkSize = this.size, chunk = []; while (chunk.length < chunkSize && iterator.moveNext()) { chunk.push(iterator.current()); } if (chunk.length === 0) { return false; } this.currentChunk = chunk; return true; }; /** * Passes each element in the sequence to the specified callback during * iteration. This is like {@link Sequence#each}, except that it can be * inserted anywhere in the middle of a chain of methods to "intercept" the * values in the sequence at that point. * * @public * @param {Function} callback A function to call on every element in the * sequence during iteration. The return value of this function does not * matter. * @returns {Sequence} A sequence comprising the same elements as this one. * * @examples * Lazy([1, 2, 3]).tap(fn).each(Lazy.noop); // calls fn 3 times */ Sequence.prototype.tap = function tap(callback) { return new TappedSequence(this, callback); }; /** * @constructor */ function TappedSequence(parent, callback) { this.parent = parent; this.callback = callback; } TappedSequence.prototype = new Sequence(); TappedSequence.prototype.each = function each(fn) { var callback = this.callback; return this.parent.each(function(e, i) { callback(e, i); return fn(e, i); }); }; /** * Seaches for the first element in the sequence satisfying a given predicate. * * @public * @aka detect * @param {Function} predicate A function to call on (potentially) every element * in the sequence. * @returns {*} The first element in the sequence for which `predicate` returns * `true`, or `undefined` if no such element is found. * * @examples * function divisibleBy3(x) { * return x % 3 === 0; * } * * var numbers = [5, 6, 7, 8, 9, 10]; * * Lazy(numbers).find(divisibleBy3) // => 6 * Lazy(numbers).find(isNegative) // => undefined */ Sequence.prototype.find = function find(predicate) { return this.filter(predicate).first(); }; Sequence.prototype.detect = function detect(predicate) { return this.find(predicate); }; /** * Gets the minimum value in the sequence. * * @public * @param {Function=} valueFn The function by which the value for comparison is * calculated for each element in the sequence. * @returns {*} The element with the lowest value in the sequence, or * `Infinity` if the sequence is empty. * * @examples * function negate(x) { return x * -1; } * * Lazy([]).min() // => Infinity * Lazy([6, 18, 2, 49, 34]).min() // => 2 * Lazy([6, 18, 2, 49, 34]).min(negate) // => 49 */ Sequence.prototype.min = function min(valueFn) { if (typeof valueFn !== "undefined") { return this.minBy(valueFn); } return this.reduce(function(x, y) { return y < x ? y : x; }, Infinity); }; Sequence.prototype.minBy = function minBy(valueFn) { valueFn = createCallback(valueFn); return this.reduce(function(x, y) { return valueFn(y) < valueFn(x) ? y : x; }); }; /** * Gets the maximum value in the sequence. * * @public * @param {Function=} valueFn The function by which the value for comparison is * calculated for each element in the sequence. * @returns {*} The element with the highest value in the sequence, or * `-Infinity` if the sequence is empty. * * @examples * function reverseDigits(x) { * return Number(String(x).split('').reverse().join('')); * } * * Lazy([]).max() // => -Infinity * Lazy([6, 18, 2, 48, 29]).max() // => 48 * Lazy([6, 18, 2, 48, 29]).max(reverseDigits) // => 29 */ Sequence.prototype.max = function max(valueFn) { if (typeof valueFn !== "undefined") { return this.maxBy(valueFn); } return this.reduce(function(x, y) { return y > x ? y : x; }, -Infinity); }; Sequence.prototype.maxBy = function maxBy(valueFn) { valueFn = createCallback(valueFn); return this.reduce(function(x, y) { return valueFn(y) > valueFn(x) ? y : x; }); }; /** * Gets the sum of the values in the sequence. * * @public * @param {Function=} valueFn The function used to select the values that will * be summed up. * @returns {*} The sum. * * @examples * Lazy([]).sum() // => 0 * Lazy([1, 2, 3, 4]).sum() // => 10 * Lazy([1.2, 3.4]).sum(Math.floor) // => 4 * Lazy(['foo', 'bar']).sum('length') // => 6 */ Sequence.prototype.sum = function sum(valueFn) { if (typeof valueFn !== "undefined") { return this.sumBy(valueFn); } return this.reduce(function(x, y) { return x + y; }, 0); }; Sequence.prototype.sumBy = function sumBy(valueFn) { valueFn = createCallback(valueFn); return this.reduce(function(x, y) { return x + valueFn(y); }, 0); }; /** * Creates a string from joining together all of the elements in this sequence, * separated by the given delimiter. * * @public * @aka toString * @param {string=} delimiter The separator to insert between every element from * this sequence in the resulting string (defaults to `","`). * @returns {string} The delimited string. * * @examples * Lazy([6, 29, 1984]).join("/") // => "6/29/1984" * Lazy(["a", "b", "c"]).join() // => "a,b,c" * Lazy(["a", "b", "c"]).join("") // => "abc" * Lazy([1, 2, 3]).join() // => "1,2,3" * Lazy([1, 2, 3]).join("") // => "123" * Lazy(["", "", ""]).join(",") // => ",," */ Sequence.prototype.join = function join(delimiter) { delimiter = typeof delimiter === "string" ? delimiter : ","; return this.reduce(function(str, e, i) { if (i > 0) { str += delimiter; } return str + e; }, ""); }; Sequence.prototype.toString = function toString(delimiter) { return this.join(delimiter); }; /** * Creates a sequence, with the same elements as this one, that will be iterated * over asynchronously when calling `each`. * * @public * @param {number=} interval The approximate period, in milliseconds, that * should elapse between each element in the resulting sequence. Omitting * this argument will result in the fastest possible asynchronous iteration. * @returns {AsyncSequence} The new asynchronous sequence. * * @examples * Lazy([1, 2, 3]).async(100).each(fn) // calls fn 3 times asynchronously */ Sequence.prototype.async = function async(interval) { return new AsyncSequence(this, interval); }; /** * @constructor */ function SimpleIntersectionSequence(parent, array) { this.parent = parent; this.array = array; this.each = getEachForIntersection(array); } SimpleIntersectionSequence.prototype = new Sequence(); SimpleIntersectionSequence.prototype.eachMemoizerCache = function eachMemoizerCache(fn) { var iterator = new UniqueMemoizer(Lazy(this.array).getIterator()), i = 0; return this.parent.each(function(e) { if (iterator.contains(e)) { return fn(e, i++); } }); }; SimpleIntersectionSequence.prototype.eachArrayCache = function eachArrayCache(fn) { var array = this.array, find = arrayContains, i = 0; return this.parent.each(function(e) { if (find(array, e)) { return fn(e, i++); } }); }; function getEachForIntersection(source) { if (source.length < 40) { return SimpleIntersectionSequence.prototype.eachArrayCache; } else { return SimpleIntersectionSequence.prototype.eachMemoizerCache; } } /** * An optimized version of {@link ZippedSequence}, when zipping a sequence with * only one array. * * @param {Sequence} parent The underlying sequence. * @param {Array} array The array with which to zip the sequence. * @constructor */ function SimpleZippedSequence(parent, array) { this.parent = parent; this.array = array; } SimpleZippedSequence.prototype = new Sequence(); SimpleZippedSequence.prototype.each = function each(fn) { var array = this.array; return this.parent.each(function(e, i) { return fn([e, array[i]], i); }); }; /** * An `ArrayLikeSequence` is a {@link Sequence} that provides random access to * its elements. This extends the API for iterating with the additional methods * {@link #get} and {@link #length}, allowing a sequence to act as a "view" into * a collection or other indexed data source. * * The initial sequence created by wrapping an array with `Lazy(array)` is an * `ArrayLikeSequence`. * * All methods of `ArrayLikeSequence` that conceptually should return * something like a array (with indexed access) return another * `ArrayLikeSequence`, for example: * * - {@link Sequence#map} * - {@link ArrayLikeSequence#slice} * - {@link Sequence#take} and {@link Sequence#drop} * - {@link Sequence#reverse} * * The above is not an exhaustive list. There are also certain other cases * where it might be possible to return an `ArrayLikeSequence` (e.g., calling * {@link Sequence#concat} with a single array argument), but this is not * guaranteed by the API. * * Note that in many cases, it is not possible to provide indexed access * without first performing at least a partial iteration of the underlying * sequence. In these cases an `ArrayLikeSequence` will not be returned: * * - {@link Sequence#filter} * - {@link Sequence#uniq} * - {@link Sequence#union} * - {@link Sequence#intersect} * * etc. The above methods only return ordinary {@link Sequence} objects. * * Defining custom array-like sequences * ------------------------------------ * * Creating a custom `ArrayLikeSequence` is essentially the same as creating a * custom {@link Sequence}. You just have a couple more methods you need to * implement: `get` and (optionally) `length`. * * Here's an example. Let's define a sequence type called `OffsetSequence` that * offsets each of its parent's elements by a set distance, and circles back to * the beginning after reaching the end. **Remember**: the initialization * function you pass to {@link #define} should always accept a `parent` as its * first parameter. * * ArrayLikeSequence.define("offset", { * init: function(parent, offset) { * this.offset = offset; * }, * * get: function(i) { * return this.parent.get((i + this.offset) % this.parent.length()); * } * }); * * It's worth noting a couple of things here. * * First, Lazy's default implementation of `length` simply returns the parent's * length. In this case, since an `OffsetSequence` will always have the same * number of elements as its parent, that implementation is fine; so we don't * need to override it. * * Second, the default implementation of `each` uses `get` and `length` to * essentially create a `for` loop, which is fine here. If you want to implement * `each` your own way, you can do that; but in most cases (as here), you can * probably just stick with the default. * * So we're already done, after only implementing `get`! Pretty easy, huh? * * Now the `offset` method will be chainable from any `ArrayLikeSequence`. So * for example: * * Lazy([1, 2, 3]).map(mapFn).offset(3); * * ...will work, but: * * Lazy([1, 2, 3]).filter(mapFn).offset(3); * * ...will not (because `filter` does not return an `ArrayLikeSequence`). * * (Also, as with the example provided for defining custom {@link Sequence} * types, this example really could have been implemented using a function * already available as part of Lazy.js: in this case, {@link Sequence#map}.) * * @public * @constructor * * @examples * Lazy([1, 2, 3]) // instanceof Lazy.ArrayLikeSequence * Lazy([1, 2, 3]).map(Lazy.identity) // instanceof Lazy.ArrayLikeSequence * Lazy([1, 2, 3]).take(2) // instanceof Lazy.ArrayLikeSequence * Lazy([1, 2, 3]).drop(2) // instanceof Lazy.ArrayLikeSequence * Lazy([1, 2, 3]).reverse() // instanceof Lazy.ArrayLikeSequence * Lazy([1, 2, 3]).slice(1, 2) // instanceof Lazy.ArrayLikeSequence */ function ArrayLikeSequence() {} ArrayLikeSequence.prototype = new Sequence(); /** * Create a new constructor function for a type inheriting from * `ArrayLikeSequence`. * * @public * @param {string|Array.} methodName The name(s) of the method(s) to be * used for constructing the new sequence. The method will be attached to * the `ArrayLikeSequence` prototype so that it can be chained with any other * methods that return array-like sequences. * @param {Object} overrides An object containing function overrides for this * new sequence type. **Must** include `get`. *May* include `init`, * `length`, `getIterator`, and `each`. For each function, `this` will be * the new sequence and `this.parent` will be the source sequence. * @returns {Function} A constructor for a new type inheriting from * `ArrayLikeSequence`. * * @examples * Lazy.ArrayLikeSequence.define("offset", { * init: function(offset) { * this.offset = offset; * }, * * get: function(i) { * return this.parent.get((i + this.offset) % this.parent.length()); * } * }); * * Lazy([1, 2, 3]).offset(1) // sequence: [2, 3, 1] */ ArrayLikeSequence.define = function define(methodName, overrides) { if (!overrides || typeof overrides.get !== 'function') { throw new Error("A custom array-like sequence must implement *at least* get!"); } return defineSequenceType(ArrayLikeSequence, methodName, overrides); }; /** * Returns the element at the specified index. * * @public * @param {number} i The index to access. * @returns {*} The element. * * @examples * function increment(x) { return x + 1; } * * Lazy([1, 2, 3]).get(1) // => 2 * Lazy([1, 2, 3]).get(-1) // => undefined * Lazy([1, 2, 3]).map(increment).get(1) // => 3 */ ArrayLikeSequence.prototype.get = function get(i) { return this.parent.get(i); }; /** * Returns the length of the sequence. * * @public * @returns {number} The length. * * @examples * function increment(x) { return x + 1; } * * Lazy([]).length() // => 0 * Lazy([1, 2, 3]).length() // => 3 * Lazy([1, 2, 3]).map(increment).length() // => 3 */ ArrayLikeSequence.prototype.length = function length() { return this.parent.length(); }; /** * Returns the current sequence (since it is already indexed). */ ArrayLikeSequence.prototype.getIndex = function getIndex() { return this; }; /** * An optimized version of {@link Sequence#getIterator}. */ ArrayLikeSequence.prototype.getIterator = function getIterator() { return new IndexedIterator(this); }; /** * An optimized version of {@link Iterator} meant to work with already-indexed * sequences. * * @param {ArrayLikeSequence} sequence The sequence to iterate over. * @constructor */ function IndexedIterator(sequence) { this.sequence = sequence; this.index = -1; } IndexedIterator.prototype.current = function current() { return this.sequence.get(this.index); }; IndexedIterator.prototype.moveNext = function moveNext() { if (this.index >= this.sequence.length() - 1) { return false; } ++this.index; return true; }; /** * An optimized version of {@link Sequence#each}. */ ArrayLikeSequence.prototype.each = function each(fn) { var length = this.length(), i = -1; while (++i < length) { if (fn(this.get(i), i) === false) { return false; } } return true; }; /** * Returns a new sequence with the same elements as this one, minus the last * element. * * @public * @returns {ArrayLikeSequence} The new array-like sequence. * * @examples * Lazy([1, 2, 3]).pop() // sequence: [1, 2] * Lazy([]).pop() // sequence: [] */ ArrayLikeSequence.prototype.pop = function pop() { return this.initial(); }; /** * Returns a new sequence with the same elements as this one, minus the first * element. * * @public * @returns {ArrayLikeSequence} The new array-like sequence. * * @examples * Lazy([1, 2, 3]).shift() // sequence: [2, 3] * Lazy([]).shift() // sequence: [] */ ArrayLikeSequence.prototype.shift = function shift() { return this.drop(); }; /** * Returns a new sequence comprising the portion of this sequence starting * from the specified starting index and continuing until the specified ending * index or to the end of the sequence. * * @public * @param {number} begin The index at which the new sequence should start. * @param {number=} end The index at which the new sequence should end. * @returns {ArrayLikeSequence} The new array-like sequence. * * @examples * Lazy([1, 2, 3, 4, 5]).slice(0) // sequence: [1, 2, 3, 4, 5] * Lazy([1, 2, 3, 4, 5]).slice(2) // sequence: [3, 4, 5] * Lazy([1, 2, 3, 4, 5]).slice(2, 4) // sequence: [3, 4] * Lazy([1, 2, 3, 4, 5]).slice(-1) // sequence: [5] * Lazy([1, 2, 3, 4, 5]).slice(1, -1) // sequence: [2, 3, 4] * Lazy([1, 2, 3, 4, 5]).slice(0, 10) // sequence: [1, 2, 3, 4, 5] */ ArrayLikeSequence.prototype.slice = function slice(begin, end) { var length = this.length(); if (begin < 0) { begin = length + begin; } var result = this.drop(begin); if (typeof end === "number") { if (end < 0) { end = length + end; } result = result.take(end - begin); } return result; }; /** * An optimized version of {@link Sequence#map}, which creates an * {@link ArrayLikeSequence} so that the result still provides random access. * * @public * * @examples * Lazy([1, 2, 3]).map(Lazy.identity) // instanceof Lazy.ArrayLikeSequence */ ArrayLikeSequence.prototype.map = function map(mapFn) { return new IndexedMappedSequence(this, createCallback(mapFn)); }; /** * @constructor */ function IndexedMappedSequence(parent, mapFn) { this.parent = parent; this.mapFn = mapFn; } IndexedMappedSequence.prototype = new ArrayLikeSequence(); IndexedMappedSequence.prototype.get = function get(i) { if (i < 0 || i >= this.parent.length()) { return undefined; } return this.mapFn(this.parent.get(i), i); }; /** * An optimized version of {@link Sequence#filter}. */ ArrayLikeSequence.prototype.filter = function filter(filterFn) { return new IndexedFilteredSequence(this, createCallback(filterFn)); }; /** * @constructor */ function IndexedFilteredSequence(parent, filterFn) { this.parent = parent; this.filterFn = filterFn; } IndexedFilteredSequence.prototype = new FilteredSequence(); IndexedFilteredSequence.prototype.each = function each(fn) { var parent = this.parent, filterFn = this.filterFn, length = this.parent.length(), i = -1, j = 0, e; while (++i < length) { e = parent.get(i); if (filterFn(e, i) && fn(e, j++) === false) { return false; } } return true; }; /** * An optimized version of {@link Sequence#reverse}, which creates an * {@link ArrayLikeSequence} so that the result still provides random access. * * @public * * @examples * Lazy([1, 2, 3]).reverse() // instanceof Lazy.ArrayLikeSequence */ ArrayLikeSequence.prototype.reverse = function reverse() { return new IndexedReversedSequence(this); }; /** * @constructor */ function IndexedReversedSequence(parent) { this.parent = parent; } IndexedReversedSequence.prototype = new ArrayLikeSequence(); IndexedReversedSequence.prototype.get = function get(i) { return this.parent.get(this.length() - i - 1); }; /** * An optimized version of {@link Sequence#first}, which creates an * {@link ArrayLikeSequence} so that the result still provides random access. * * @public * * @examples * Lazy([1, 2, 3]).first(2) // instanceof Lazy.ArrayLikeSequence */ ArrayLikeSequence.prototype.first = function first(count) { if (typeof count === "undefined") { return this.get(0); } return new IndexedTakeSequence(this, count); }; /** * @constructor */ function IndexedTakeSequence(parent, count) { this.parent = parent; this.count = count; } IndexedTakeSequence.prototype = new ArrayLikeSequence(); IndexedTakeSequence.prototype.length = function length() { var parentLength = this.parent.length(); return this.count <= parentLength ? this.count : parentLength; }; /** * An optimized version of {@link Sequence#rest}, which creates an * {@link ArrayLikeSequence} so that the result still provides random access. * * @public * * @examples * Lazy([1, 2, 3]).rest() // instanceof Lazy.ArrayLikeSequence */ ArrayLikeSequence.prototype.rest = function rest(count) { return new IndexedDropSequence(this, count); }; /** * @constructor */ function IndexedDropSequence(parent, count) { this.parent = parent; this.count = typeof count === "number" ? count : 1; } IndexedDropSequence.prototype = new ArrayLikeSequence(); IndexedDropSequence.prototype.get = function get(i) { return this.parent.get(this.count + i); }; IndexedDropSequence.prototype.length = function length() { var parentLength = this.parent.length(); return this.count <= parentLength ? parentLength - this.count : 0; }; /** * An optimized version of {@link Sequence#concat} that returns another * {@link ArrayLikeSequence} *if* the argument is an array. * * @public * @param {...*} var_args * * @examples * Lazy([1, 2]).concat([3, 4]) // instanceof Lazy.ArrayLikeSequence * Lazy([1, 2]).concat([3, 4]) // sequence: [1, 2, 3, 4] */ ArrayLikeSequence.prototype.concat = function concat(var_args) { if (arguments.length === 1 && arguments[0] instanceof Array) { return new IndexedConcatenatedSequence(this, (/** @type {Array} */ var_args)); } else { return Sequence.prototype.concat.apply(this, arguments); } }; /** * @constructor */ function IndexedConcatenatedSequence(parent, other) { this.parent = parent; this.other = other; } IndexedConcatenatedSequence.prototype = new ArrayLikeSequence(); IndexedConcatenatedSequence.prototype.get = function get(i) { var parentLength = this.parent.length(); if (i < parentLength) { return this.parent.get(i); } else { return this.other[i - parentLength]; } }; IndexedConcatenatedSequence.prototype.length = function length() { return this.parent.length() + this.other.length; }; /** * An optimized version of {@link Sequence#uniq}. */ ArrayLikeSequence.prototype.uniq = function uniq(keyFn) { return new IndexedUniqueSequence(this, createCallback(keyFn)); }; /** * @param {ArrayLikeSequence} parent * @constructor */ function IndexedUniqueSequence(parent, keyFn) { this.parent = parent; this.each = getEachForParent(parent); this.keyFn = keyFn; } IndexedUniqueSequence.prototype = new Sequence(); IndexedUniqueSequence.prototype.eachArrayCache = function eachArrayCache(fn) { // Basically the same implementation as w/ the set, but using an array because // it's cheaper for smaller sequences. var parent = this.parent, keyFn = this.keyFn, length = parent.length(), cache = [], find = arrayContains, key, value, i = -1, j = 0; while (++i < length) { value = parent.get(i); key = keyFn(value); if (!find(cache, key)) { cache.push(key); if (fn(value, j++) === false) { return false; } } } }; IndexedUniqueSequence.prototype.eachSetCache = UniqueSequence.prototype.each; function getEachForParent(parent) { if (parent.length() < 100) { return IndexedUniqueSequence.prototype.eachArrayCache; } else { return UniqueSequence.prototype.each; } } // Now that we've fully initialized the ArrayLikeSequence prototype, we can // set the prototype for MemoizedSequence. MemoizedSequence.prototype = new ArrayLikeSequence(); MemoizedSequence.prototype.cache = function cache() { return this.cachedResult || (this.cachedResult = this.parent.toArray()); }; MemoizedSequence.prototype.get = function get(i) { return this.cache()[i]; }; MemoizedSequence.prototype.length = function length() { return this.cache().length; }; MemoizedSequence.prototype.slice = function slice(begin, end) { return this.cache().slice(begin, end); }; MemoizedSequence.prototype.toArray = function toArray() { return this.cache().slice(0); }; /** * ArrayWrapper is the most basic {@link Sequence}. It directly wraps an array * and implements the same methods as {@link ArrayLikeSequence}, but more * efficiently. * * @constructor */ function ArrayWrapper(source) { this.source = source; } ArrayWrapper.prototype = new ArrayLikeSequence(); ArrayWrapper.prototype.root = function root() { return this; }; ArrayWrapper.prototype.isAsync = function isAsync() { return false; }; /** * Returns the element at the specified index in the source array. * * @param {number} i The index to access. * @returns {*} The element. */ ArrayWrapper.prototype.get = function get(i) { return this.source[i]; }; /** * Returns the length of the source array. * * @returns {number} The length. */ ArrayWrapper.prototype.length = function length() { return this.source.length; }; /** * An optimized version of {@link Sequence#each}. */ ArrayWrapper.prototype.each = function each(fn) { return forEach(this.source, fn); }; /** * An optimized version of {@link Sequence#map}. */ ArrayWrapper.prototype.map = function map(mapFn) { return new MappedArrayWrapper(this, createCallback(mapFn)); }; /** * An optimized version of {@link Sequence#filter}. */ ArrayWrapper.prototype.filter = function filter(filterFn) { return new FilteredArrayWrapper(this, createCallback(filterFn)); }; /** * An optimized version of {@link Sequence#uniq}. */ ArrayWrapper.prototype.uniq = function uniq(keyFn) { return new UniqueArrayWrapper(this, keyFn); }; /** * An optimized version of {@link ArrayLikeSequence#concat}. * * @param {...*} var_args */ ArrayWrapper.prototype.concat = function concat(var_args) { if (arguments.length === 1 && arguments[0] instanceof Array) { return new ConcatArrayWrapper(this, (/** @type {Array} */ var_args)); } else { return ArrayLikeSequence.prototype.concat.apply(this, arguments); } }; /** * An optimized version of {@link Sequence#toArray}. */ ArrayWrapper.prototype.toArray = function toArray() { return this.source.slice(0); }; /** * @constructor */ function MappedArrayWrapper(parent, mapFn) { this.parent = parent; this.mapFn = mapFn; } MappedArrayWrapper.prototype = new ArrayLikeSequence(); MappedArrayWrapper.prototype.get = function get(i) { var source = this.parent.source; if (i < 0 || i >= source.length) { return undefined; } return this.mapFn(source[i]); }; MappedArrayWrapper.prototype.length = function length() { return this.parent.source.length; }; MappedArrayWrapper.prototype.each = function each(fn) { var source = this.parent.source, length = source.length, mapFn = this.mapFn, i = -1; while (++i < length) { if (fn(mapFn(source[i], i), i) === false) { return false; } } return true; }; /** * @constructor */ function FilteredArrayWrapper(parent, filterFn) { this.parent = parent; this.filterFn = filterFn; } FilteredArrayWrapper.prototype = new FilteredSequence(); FilteredArrayWrapper.prototype.each = function each(fn) { var source = this.parent.source, filterFn = this.filterFn, length = source.length, i = -1, j = 0, e; while (++i < length) { e = source[i]; if (filterFn(e, i) && fn(e, j++) === false) { return false; } } return true; }; /** * @constructor */ function UniqueArrayWrapper(parent, keyFn) { this.parent = parent; this.each = getEachForSource(parent.source); this.keyFn = keyFn; } UniqueArrayWrapper.prototype = new Sequence(); UniqueArrayWrapper.prototype.eachNoCache = function eachNoCache(fn) { var source = this.parent.source, keyFn = this.keyFn, length = source.length, find = arrayContainsBefore, value, // Yes, this is hideous. // Trying to get performance first, will refactor next! i = -1, k = 0; while (++i < length) { value = source[i]; if (!find(source, value, i, keyFn) && fn(value, k++) === false) { return false; } } return true; }; UniqueArrayWrapper.prototype.eachArrayCache = function eachArrayCache(fn) { // Basically the same implementation as w/ the set, but using an array because // it's cheaper for smaller sequences. var source = this.parent.source, keyFn = this.keyFn, length = source.length, cache = [], find = arrayContains, key, value, i = -1, j = 0; if (keyFn) { keyFn = createCallback(keyFn); while (++i < length) { value = source[i]; key = keyFn(value); if (!find(cache, key)) { cache.push(key); if (fn(value, j++) === false) { return false; } } } } else { while (++i < length) { value = source[i]; if (!find(cache, value)) { cache.push(value); if (fn(value, j++) === false) { return false; } } } } return true; }; UniqueArrayWrapper.prototype.eachSetCache = UniqueSequence.prototype.each; /** * My latest findings here... * * So I hadn't really given the set-based approach enough credit. The main issue * was that my Set implementation was totally not optimized at all. After pretty * heavily optimizing it (just take a look; it's a monstrosity now!), it now * becomes the fastest option for much smaller values of N. */ function getEachForSource(source) { if (source.length < 40) { return UniqueArrayWrapper.prototype.eachNoCache; } else if (source.length < 100) { return UniqueArrayWrapper.prototype.eachArrayCache; } else { return UniqueArrayWrapper.prototype.eachSetCache; } } /** * @constructor */ function ConcatArrayWrapper(parent, other) { this.parent = parent; this.other = other; } ConcatArrayWrapper.prototype = new ArrayLikeSequence(); ConcatArrayWrapper.prototype.get = function get(i) { var source = this.parent.source, sourceLength = source.length; if (i < sourceLength) { return source[i]; } else { return this.other[i - sourceLength]; } }; ConcatArrayWrapper.prototype.length = function length() { return this.parent.source.length + this.other.length; }; ConcatArrayWrapper.prototype.each = function each(fn) { var source = this.parent.source, sourceLength = source.length, other = this.other, otherLength = other.length, i = 0, j = -1; while (++j < sourceLength) { if (fn(source[j], i++) === false) { return false; } } j = -1; while (++j < otherLength) { if (fn(other[j], i++) === false) { return false; } } return true; }; /** * An `ObjectLikeSequence` object represents a sequence of key/value pairs. * * The initial sequence you get by wrapping an object with `Lazy(object)` is * an `ObjectLikeSequence`. * * All methods of `ObjectLikeSequence` that conceptually should return * something like an object return another `ObjectLikeSequence`. * * @public * @constructor * * @examples * var obj = { foo: 'bar' }; * * Lazy(obj).assign({ bar: 'baz' }) // instanceof Lazy.ObjectLikeSequence * Lazy(obj).defaults({ bar: 'baz' }) // instanceof Lazy.ObjectLikeSequence * Lazy(obj).invert() // instanceof Lazy.ObjectLikeSequence */ function ObjectLikeSequence() {} ObjectLikeSequence.prototype = new Sequence(); /** * Create a new constructor function for a type inheriting from * `ObjectLikeSequence`. * * @public * @param {string|Array.} methodName The name(s) of the method(s) to be * used for constructing the new sequence. The method will be attached to * the `ObjectLikeSequence` prototype so that it can be chained with any other * methods that return object-like sequences. * @param {Object} overrides An object containing function overrides for this * new sequence type. **Must** include `each`. *May* include `init` and * `get` (for looking up an element by key). * @returns {Function} A constructor for a new type inheriting from * `ObjectLikeSequence`. * * @examples * function downcaseKey(value, key) { * return [key.toLowerCase(), value]; * } * * Lazy.ObjectLikeSequence.define("caseInsensitive", { * init: function() { * var downcased = this.parent * .map(downcaseKey) * .toObject(); * this.downcased = Lazy(downcased); * }, * * get: function(key) { * return this.downcased.get(key.toLowerCase()); * }, * * each: function(fn) { * return this.downcased.each(fn); * } * }); * * Lazy({ Foo: 'bar' }).caseInsensitive() // sequence: { foo: 'bar' } * Lazy({ FOO: 'bar' }).caseInsensitive().get('foo') // => 'bar' * Lazy({ FOO: 'bar' }).caseInsensitive().get('FOO') // => 'bar' */ ObjectLikeSequence.define = function define(methodName, overrides) { if (!overrides || typeof overrides.each !== 'function') { throw new Error("A custom object-like sequence must implement *at least* each!"); } return defineSequenceType(ObjectLikeSequence, methodName, overrides); }; ObjectLikeSequence.prototype.value = function value() { return this.toObject(); }; /** * Gets the element at the specified key in this sequence. * * @public * @param {string} key The key. * @returns {*} The element. * * @examples * Lazy({ foo: "bar" }).get("foo") // => "bar" * Lazy({ foo: "bar" }).extend({ foo: "baz" }).get("foo") // => "baz" * Lazy({ foo: "bar" }).defaults({ bar: "baz" }).get("bar") // => "baz" * Lazy({ foo: "bar" }).invert().get("bar") // => "foo" * Lazy({ foo: 1, bar: 2 }).pick(["foo"]).get("foo") // => 1 * Lazy({ foo: 1, bar: 2 }).pick(["foo"]).get("bar") // => undefined * Lazy({ foo: 1, bar: 2 }).omit(["foo"]).get("bar") // => 2 * Lazy({ foo: 1, bar: 2 }).omit(["foo"]).get("foo") // => undefined */ ObjectLikeSequence.prototype.get = function get(key) { var pair = this.pairs().find(function(pair) { return pair[0] === key; }); return pair ? pair[1] : undefined; }; /** * Returns a {@link Sequence} whose elements are the keys of this object-like * sequence. * * @public * @returns {Sequence} The sequence based on this sequence's keys. * * @examples * Lazy({ hello: "hola", goodbye: "hasta luego" }).keys() // sequence: ["hello", "goodbye"] */ ObjectLikeSequence.prototype.keys = function keys() { return this.map(function(v, k) { return k; }); }; /** * Returns a {@link Sequence} whose elements are the values of this object-like * sequence. * * @public * @returns {Sequence} The sequence based on this sequence's values. * * @examples * Lazy({ hello: "hola", goodbye: "hasta luego" }).values() // sequence: ["hola", "hasta luego"] */ ObjectLikeSequence.prototype.values = function values() { return this.map(function(v, k) { return v; }); }; /** * Throws an exception. Asynchronous iteration over object-like sequences is * not supported. * * @public * @examples * Lazy({ foo: 'bar' }).async() // throws */ ObjectLikeSequence.prototype.async = function async() { throw new Error('An ObjectLikeSequence does not support asynchronous iteration.'); }; ObjectLikeSequence.prototype.filter = function filter(filterFn) { return new FilteredObjectLikeSequence(this, createCallback(filterFn)); }; function FilteredObjectLikeSequence(parent, filterFn) { this.parent = parent; this.filterFn = filterFn; } FilteredObjectLikeSequence.prototype = new ObjectLikeSequence(); FilteredObjectLikeSequence.prototype.each = function each(fn) { var filterFn = this.filterFn; return this.parent.each(function(v, k) { if (filterFn(v, k)) { return fn(v, k); } }); }; /** * Returns this same sequence. (Reversing an object-like sequence doesn't make * any sense.) */ ObjectLikeSequence.prototype.reverse = function reverse() { return this; }; /** * Returns an {@link ObjectLikeSequence} whose elements are the combination of * this sequence and another object. In the case of a key appearing in both this * sequence and the given object, the other object's value will override the * one in this sequence. * * @public * @aka extend * @param {Object} other The other object to assign to this sequence. * @returns {ObjectLikeSequence} A new sequence comprising elements from this * sequence plus the contents of `other`. * * @examples * Lazy({ "uno": 1, "dos": 2 }).assign({ "tres": 3 }) // sequence: { uno: 1, dos: 2, tres: 3 } * Lazy({ foo: "bar" }).assign({ foo: "baz" }); // sequence: { foo: "baz" } */ ObjectLikeSequence.prototype.assign = function assign(other) { return new AssignSequence(this, other); }; ObjectLikeSequence.prototype.extend = function extend(other) { return this.assign(other); }; /** * @constructor */ function AssignSequence(parent, other) { this.parent = parent; this.other = other; } AssignSequence.prototype = new ObjectLikeSequence(); AssignSequence.prototype.get = function get(key) { return this.other[key] || this.parent.get(key); }; AssignSequence.prototype.each = function each(fn) { var merged = new Set(), done = false; Lazy(this.other).each(function(value, key) { if (fn(value, key) === false) { done = true; return false; } merged.add(key); }); if (!done) { return this.parent.each(function(value, key) { if (!merged.contains(key) && fn(value, key) === false) { return false; } }); } }; /** * Returns an {@link ObjectLikeSequence} whose elements are the combination of * this sequence and a 'default' object. In the case of a key appearing in both * this sequence and the given object, this sequence's value will override the * default object's. * * @public * @param {Object} defaults The 'default' object to use for missing keys in this * sequence. * @returns {ObjectLikeSequence} A new sequence comprising elements from this * sequence supplemented by the contents of `defaults`. * * @examples * Lazy({ name: "Dan" }).defaults({ name: "User", password: "passw0rd" }) // sequence: { name: "Dan", password: "passw0rd" } */ ObjectLikeSequence.prototype.defaults = function defaults(defaults) { return new DefaultsSequence(this, defaults); }; /** * @constructor */ function DefaultsSequence(parent, defaults) { this.parent = parent; this.defaults = defaults; } DefaultsSequence.prototype = new ObjectLikeSequence(); DefaultsSequence.prototype.get = function get(key) { return this.parent.get(key) || this.defaults[key]; }; DefaultsSequence.prototype.each = function each(fn) { var merged = new Set(), done = false; this.parent.each(function(value, key) { if (fn(value, key) === false) { done = true; return false; } if (typeof value !== "undefined") { merged.add(key); } }); if (!done) { Lazy(this.defaults).each(function(value, key) { if (!merged.contains(key) && fn(value, key) === false) { return false; } }); } }; /** * Returns an {@link ObjectLikeSequence} whose values are this sequence's keys, * and whose keys are this sequence's values. * * @public * @returns {ObjectLikeSequence} A new sequence comprising the inverted keys and * values from this sequence. * * @examples * Lazy({ first: "Dan", last: "Tao" }).invert() // sequence: { Dan: "first", Tao: "last" } */ ObjectLikeSequence.prototype.invert = function invert() { return new InvertedSequence(this); }; /** * @constructor */ function InvertedSequence(parent) { this.parent = parent; } InvertedSequence.prototype = new ObjectLikeSequence(); InvertedSequence.prototype.each = function each(fn) { this.parent.each(function(value, key) { return fn(key, value); }); }; /** * Produces an {@link ObjectLikeSequence} consisting of all the recursively * merged values from this and the given object(s) or sequence(s). * * Note that by default this method only merges "vanilla" objects (bags of * key/value pairs), not arrays or any other custom object types. To customize * how merging works, you can provide the mergeFn argument, e.g. to handling * merging arrays, strings, or other types of objects. * * @public * @param {...Object|ObjectLikeSequence} others The other object(s) or * sequence(s) whose values will be merged into this one. * @param {Function=} mergeFn An optional function used to customize merging * behavior. The function should take two values as parameters and return * whatever the "merged" form of those values is. If the function returns * undefined then the new value will simply replace the old one in the * final result. * @returns {ObjectLikeSequence} The new sequence consisting of merged values. * * @examples * // These examples are completely stolen from Lo-Dash's documentation: * // lodash.com/docs#merge * * var names = { * 'characters': [ * { 'name': 'barney' }, * { 'name': 'fred' } * ] * }; * * var ages = { * 'characters': [ * { 'age': 36 }, * { 'age': 40 } * ] * }; * * var food = { * 'fruits': ['apple'], * 'vegetables': ['beet'] * }; * * var otherFood = { * 'fruits': ['banana'], * 'vegetables': ['carrot'] * }; * * function mergeArrays(a, b) { * return Array.isArray(a) ? a.concat(b) : undefined; * } * * Lazy(names).merge(ages); // => sequence: { 'characters': [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 }] } * Lazy(food).merge(otherFood, mergeArrays); // => sequence: { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] } * * // ----- Now for my own tests: ----- * * // merges objects * Lazy({ foo: 1 }).merge({ foo: 2 }); // => sequence: { foo: 2 } * Lazy({ foo: 1 }).merge({ bar: 2 }); // => sequence: { foo: 1, bar: 2 } * * // goes deep * Lazy({ foo: { bar: 1 } }).merge({ foo: { bar: 2 } }); // => sequence: { foo: { bar: 2 } } * Lazy({ foo: { bar: 1 } }).merge({ foo: { baz: 2 } }); // => sequence: { foo: { bar: 1, baz: 2 } } * Lazy({ foo: { bar: 1 } }).merge({ foo: { baz: 2 } }); // => sequence: { foo: { bar: 1, baz: 2 } } * * // gives precedence to later sources * Lazy({ foo: 1 }).merge({ bar: 2 }, { bar: 3 }); // => sequence: { foo: 1, bar: 3 } * * // undefined gets passed over * Lazy({ foo: 1 }).merge({ foo: undefined }); // => sequence: { foo: 1 } * * // null doesn't get passed over * Lazy({ foo: 1 }).merge({ foo: null }); // => sequence: { foo: null } * * // array contents get merged as well * Lazy({ foo: [{ bar: 1 }] }).merge({ foo: [{ baz: 2 }] }); // => sequence: { foo: [{ bar: 1, baz: 2}] } */ ObjectLikeSequence.prototype.merge = function merge(var_args) { var mergeFn = arguments.length > 1 && typeof arguments[arguments.length - 1] === "function" ? arrayPop.call(arguments) : null; return new MergedSequence(this, arraySlice.call(arguments, 0), mergeFn); }; /** * @constructor */ function MergedSequence(parent, others, mergeFn) { this.parent = parent; this.others = others; this.mergeFn = mergeFn; } MergedSequence.prototype = new ObjectLikeSequence(); MergedSequence.prototype.each = function each(fn) { var others = this.others, mergeFn = this.mergeFn || mergeObjects, keys = {}; var iteratedFullSource = this.parent.each(function(value, key) { var merged = value; forEach(others, function(other) { if (key in other) { merged = mergeFn(merged, other[key]); } }); keys[key] = true; return fn(merged, key); }); if (iteratedFullSource === false) { return false; } var remaining = {}; forEach(others, function(other) { for (var k in other) { if (!keys[k]) { remaining[k] = mergeFn(remaining[k], other[k]); } } }); return Lazy(remaining).each(fn); }; /** * @private * @examples * mergeObjects({ foo: 1 }, { bar: 2 }); // => { foo: 1, bar: 2 } * mergeObjects({ foo: { bar: 1 } }, { foo: { baz: 2 } }); // => { foo: { bar: 1, baz: 2 } } * mergeObjects({ foo: { bar: 1 } }, { foo: undefined }); // => { foo: { bar: 1 } } * mergeObjects({ foo: { bar: 1 } }, { foo: null }); // => { foo: null } * mergeObjects({ array: [0, 1, 2] }, { array: [3, 4, 5] }).array; // instanceof Array * mergeObjects({ date: new Date() }, { date: new Date() }).date; // instanceof Date * mergeObjects([{ foo: 1 }], [{ bar: 2 }]); // => [{ foo: 1, bar: 2 }] */ function mergeObjects(a, b) { var merged, prop; if (typeof b === 'undefined') { return a; } // Check that we're dealing with two objects or two arrays. if (isVanillaObject(a) && isVanillaObject(b)) { merged = {}; } else if (a instanceof Array && b instanceof Array) { merged = []; } else { // Otherwise there's no merging to do -- just replace a w/ b. return b; } for (prop in a) { merged[prop] = mergeObjects(a[prop], b[prop]); } for (prop in b) { if (!merged[prop]) { merged[prop] = b[prop]; } } return merged; } /** * Checks whether an object is a "vanilla" object, i.e. {'foo': 'bar'} as * opposed to an array, date, etc. * * @private * @examples * isVanillaObject({foo: 'bar'}); // => true * isVanillaObject(new Date()); // => false * isVanillaObject([1, 2, 3]); // => false */ function isVanillaObject(object) { return object && object.constructor === Object; } /** * Creates a {@link Sequence} consisting of the keys from this sequence whose * values are functions. * * @public * @aka methods * @returns {Sequence} The new sequence. * * @examples * var dog = { * name: "Fido", * breed: "Golden Retriever", * bark: function() { console.log("Woof!"); }, * wagTail: function() { console.log("TODO: implement robotic dog interface"); } * }; * * Lazy(dog).functions() // sequence: ["bark", "wagTail"] */ ObjectLikeSequence.prototype.functions = function functions() { return this .filter(function(v, k) { return typeof(v) === "function"; }) .map(function(v, k) { return k; }); }; ObjectLikeSequence.prototype.methods = function methods() { return this.functions(); }; /** * Creates an {@link ObjectLikeSequence} consisting of the key/value pairs from * this sequence whose keys are included in the given array of property names. * * @public * @param {Array} properties An array of the properties to "pick" from this * sequence. * @returns {ObjectLikeSequence} The new sequence. * * @examples * var players = { * "who": "first", * "what": "second", * "i don't know": "third" * }; * * Lazy(players).pick(["who", "what"]) // sequence: { who: "first", what: "second" } */ ObjectLikeSequence.prototype.pick = function pick(properties) { return new PickSequence(this, properties); }; /** * @constructor */ function PickSequence(parent, properties) { this.parent = parent; this.properties = properties; } PickSequence.prototype = new ObjectLikeSequence(); PickSequence.prototype.get = function get(key) { return arrayContains(this.properties, key) ? this.parent.get(key) : undefined; }; PickSequence.prototype.each = function each(fn) { var inArray = arrayContains, properties = this.properties; return this.parent.each(function(value, key) { if (inArray(properties, key)) { return fn(value, key); } }); }; /** * Creates an {@link ObjectLikeSequence} consisting of the key/value pairs from * this sequence excluding those with the specified keys. * * @public * @param {Array} properties An array of the properties to *omit* from this * sequence. * @returns {ObjectLikeSequence} The new sequence. * * @examples * var players = { * "who": "first", * "what": "second", * "i don't know": "third" * }; * * Lazy(players).omit(["who", "what"]) // sequence: { "i don't know": "third" } */ ObjectLikeSequence.prototype.omit = function omit(properties) { return new OmitSequence(this, properties); }; /** * @constructor */ function OmitSequence(parent, properties) { this.parent = parent; this.properties = properties; } OmitSequence.prototype = new ObjectLikeSequence(); OmitSequence.prototype.get = function get(key) { return arrayContains(this.properties, key) ? undefined : this.parent.get(key); }; OmitSequence.prototype.each = function each(fn) { var inArray = arrayContains, properties = this.properties; return this.parent.each(function(value, key) { if (!inArray(properties, key)) { return fn(value, key); } }); }; /** * Maps the key/value pairs in this sequence to arrays. * * @public * @aka toArray * @returns {Sequence} An sequence of `[key, value]` pairs. * * @examples * var colorCodes = { * red: "#f00", * green: "#0f0", * blue: "#00f" * }; * * Lazy(colorCodes).pairs() // sequence: [["red", "#f00"], ["green", "#0f0"], ["blue", "#00f"]] */ ObjectLikeSequence.prototype.pairs = function pairs() { return this.map(function(v, k) { return [k, v]; }); }; /** * Creates an array from the key/value pairs in this sequence. * * @public * @returns {Array} An array of `[key, value]` elements. * * @examples * var colorCodes = { * red: "#f00", * green: "#0f0", * blue: "#00f" * }; * * Lazy(colorCodes).toArray() // => [["red", "#f00"], ["green", "#0f0"], ["blue", "#00f"]] */ ObjectLikeSequence.prototype.toArray = function toArray() { return this.pairs().toArray(); }; /** * Creates an object with the key/value pairs from this sequence. * * @public * @returns {Object} An object with the same key/value pairs as this sequence. * * @examples * var colorCodes = { * red: "#f00", * green: "#0f0", * blue: "#00f" * }; * * Lazy(colorCodes).toObject() // => { red: "#f00", green: "#0f0", blue: "#00f" } */ ObjectLikeSequence.prototype.toObject = function toObject() { return this.reduce(function(object, value, key) { object[key] = value; return object; }, {}); }; // Now that we've fully initialized the ObjectLikeSequence prototype, we can // actually set the prototypes for GroupedSequence, IndexedSequence, and // CountedSequence. GroupedSequence.prototype = new ObjectLikeSequence(); GroupedSequence.prototype.each = function each(fn) { var keyFn = createCallback(this.keyFn), valFn = createCallback(this.valFn), result; result = this.parent.reduce(function(grouped,e) { var key = keyFn(e), val = valFn(e); if (!(grouped[key] instanceof Array)) { grouped[key] = [val]; } else { grouped[key].push(val); } return grouped; },{}); return transform(function(grouped) { for (var key in grouped) { if (fn(grouped[key], key) === false) { return false; } } }, result); }; IndexedSequence.prototype = new ObjectLikeSequence(); IndexedSequence.prototype.each = function each(fn) { var keyFn = createCallback(this.keyFn), valFn = createCallback(this.valFn), indexed = {}; return this.parent.each(function(e) { var key = keyFn(e), val = valFn(e); if (!indexed[key]) { indexed[key] = val; return fn(val, key); } }); }; CountedSequence.prototype = new ObjectLikeSequence(); CountedSequence.prototype.each = function each(fn) { var keyFn = createCallback(this.keyFn), counted = {}; this.parent.each(function(e) { var key = keyFn(e); if (!counted[key]) { counted[key] = 1; } else { counted[key] += 1; } }); for (var key in counted) { if (fn(counted[key], key) === false) { return false; } } return true; }; /** * Watches for all changes to a specified property (or properties) of an * object and produces a sequence whose elements have the properties * `{ property, value }` indicating which property changed and what it was * changed to. * * Note that this method **only works on directly wrapped objects**; it will * *not* work on any arbitrary {@link ObjectLikeSequence}. * * @public * @param {(string|Array)=} propertyNames A property name or array of property * names to watch. If this parameter is `undefined`, all of the object's * current (enumerable) properties will be watched. * @returns {Sequence} A sequence comprising `{ property, value }` objects * describing each change to the specified property/properties. * * @examples * var obj = {}, * changes = []; * * Lazy(obj).watch('foo').each(function(change) { * changes.push(change); * }); * * obj.foo = 1; * obj.bar = 2; * obj.foo = 3; * * obj.foo; // => 3 * changes; // => [{ property: 'foo', value: 1 }, { property: 'foo', value: 3 }] */ ObjectLikeSequence.prototype.watch = function watch(propertyNames) { throw new Error('You can only call #watch on a directly wrapped object.'); }; /** * @constructor */ function ObjectWrapper(source) { this.source = source; } ObjectWrapper.prototype = new ObjectLikeSequence(); ObjectWrapper.prototype.root = function root() { return this; }; ObjectWrapper.prototype.isAsync = function isAsync() { return false; }; ObjectWrapper.prototype.get = function get(key) { return this.source[key]; }; ObjectWrapper.prototype.each = function each(fn) { var source = this.source, key; for (key in source) { if (fn(source[key], key) === false) { return false; } } return true; }; /** * A `StringLikeSequence` represents a sequence of characters. * * The initial sequence you get by wrapping a string with `Lazy(string)` is a * `StringLikeSequence`. * * All methods of `StringLikeSequence` that conceptually should return * something like a string return another `StringLikeSequence`. * * @public * @constructor * * @examples * function upcase(str) { return str.toUpperCase(); } * * Lazy('foo') // instanceof Lazy.StringLikeSequence * Lazy('foo').toUpperCase() // instanceof Lazy.StringLikeSequence * Lazy('foo').reverse() // instanceof Lazy.StringLikeSequence * Lazy('foo').take(2) // instanceof Lazy.StringLikeSequence * Lazy('foo').drop(1) // instanceof Lazy.StringLikeSequence * Lazy('foo').substring(1) // instanceof Lazy.StringLikeSequence * * // Note that `map` does not create a `StringLikeSequence` because there's * // no guarantee the mapping function will return characters. In the event * // you do want to map a string onto a string-like sequence, use * // `mapString`: * Lazy('foo').map(Lazy.identity) // instanceof Lazy.ArrayLikeSequence * Lazy('foo').mapString(Lazy.identity) // instanceof Lazy.StringLikeSequence */ function StringLikeSequence() {} StringLikeSequence.prototype = new ArrayLikeSequence(); /** * Create a new constructor function for a type inheriting from * `StringLikeSequence`. * * @public * @param {string|Array.} methodName The name(s) of the method(s) to be * used for constructing the new sequence. The method will be attached to * the `StringLikeSequence` prototype so that it can be chained with any other * methods that return string-like sequences. * @param {Object} overrides An object containing function overrides for this * new sequence type. Has the same requirements as * {@link ArrayLikeSequence.define}. * @returns {Function} A constructor for a new type inheriting from * `StringLikeSequence`. * * @examples * Lazy.StringLikeSequence.define("zomg", { * length: function() { * return this.parent.length() + "!!ZOMG!!!1".length; * }, * * get: function(i) { * if (i < this.parent.length()) { * return this.parent.get(i); * } * return "!!ZOMG!!!1".charAt(i - this.parent.length()); * } * }); * * Lazy('foo').zomg() // sequence: "foo!!ZOMG!!!1" */ StringLikeSequence.define = function define(methodName, overrides) { if (!overrides || typeof overrides.get !== 'function') { throw new Error("A custom string-like sequence must implement *at least* get!"); } return defineSequenceType(StringLikeSequence, methodName, overrides); }; StringLikeSequence.prototype.value = function value() { return this.toString(); }; /** * Returns an {@link IndexedIterator} that will step over each character in this * sequence one by one. * * @returns {IndexedIterator} The iterator. */ StringLikeSequence.prototype.getIterator = function getIterator() { return new CharIterator(this); }; /** * @constructor */ function CharIterator(source) { this.source = Lazy(source); this.index = -1; } CharIterator.prototype.current = function current() { return this.source.charAt(this.index); }; CharIterator.prototype.moveNext = function moveNext() { return (++this.index < this.source.length()); }; /** * Returns the character at the given index of this sequence, or the empty * string if the specified index lies outside the bounds of the sequence. * * @public * @param {number} i The index of this sequence. * @returns {string} The character at the specified index. * * @examples * Lazy("foo").charAt(0) // => "f" * Lazy("foo").charAt(-1) // => "" * Lazy("foo").charAt(10) // => "" */ StringLikeSequence.prototype.charAt = function charAt(i) { return this.get(i); }; /** * Returns the character code at the given index of this sequence, or `NaN` if * the index lies outside the bounds of the sequence. * * @public * @param {number} i The index of the character whose character code you want. * @returns {number} The character code. * * @examples * Lazy("abc").charCodeAt(0) // => 97 * Lazy("abc").charCodeAt(-1) // => NaN * Lazy("abc").charCodeAt(10) // => NaN */ StringLikeSequence.prototype.charCodeAt = function charCodeAt(i) { var char = this.charAt(i); if (!char) { return NaN; } return char.charCodeAt(0); }; /** * Returns a {@link StringLikeSequence} comprising the characters from *this* * sequence starting at `start` and ending at `stop` (exclusive), or---if * `stop` is `undefined`, including the rest of the sequence. * * @public * @param {number} start The index where this sequence should begin. * @param {number=} stop The index (exclusive) where this sequence should end. * @returns {StringLikeSequence} The new sequence. * * @examples * Lazy("foo").substring(1) // sequence: "oo" * Lazy("foo").substring(-1) // sequence: "foo" * Lazy("hello").substring(1, 3) // sequence: "el" * Lazy("hello").substring(1, 9) // sequence: "ello" */ StringLikeSequence.prototype.substring = function substring(start, stop) { return new StringSegment(this, start, stop); }; /** * @constructor */ function StringSegment(parent, start, stop) { this.parent = parent; this.start = Math.max(0, start); this.stop = stop; } StringSegment.prototype = new StringLikeSequence(); StringSegment.prototype.get = function get(i) { return this.parent.get(i + this.start); }; StringSegment.prototype.length = function length() { return (typeof this.stop === "number" ? this.stop : this.parent.length()) - this.start; }; /** * An optimized version of {@link Sequence#first} that returns another * {@link StringLikeSequence} (or just the first character, if `count` is * undefined). * * @public * @examples * Lazy('foo').first() // => 'f' * Lazy('fo').first(2) // sequence: 'fo' * Lazy('foo').first(10) // sequence: 'foo' * Lazy('foo').toUpperCase().first() // => 'F' * Lazy('foo').toUpperCase().first(2) // sequence: 'FO' */ StringLikeSequence.prototype.first = function first(count) { if (typeof count === "undefined") { return this.charAt(0); } return this.substring(0, count); }; /** * An optimized version of {@link Sequence#last} that returns another * {@link StringLikeSequence} (or just the last character, if `count` is * undefined). * * @public * @examples * Lazy('foo').last() // => 'o' * Lazy('foo').last(2) // sequence: 'oo' * Lazy('foo').last(10) // sequence: 'foo' * Lazy('foo').toUpperCase().last() // => 'O' * Lazy('foo').toUpperCase().last(2) // sequence: 'OO' */ StringLikeSequence.prototype.last = function last(count) { if (typeof count === "undefined") { return this.charAt(this.length() - 1); } return this.substring(this.length() - count); }; StringLikeSequence.prototype.drop = function drop(count) { return this.substring(count); }; /** * Finds the index of the first occurrence of the given substring within this * sequence, starting from the specified index (or the beginning of the * sequence). * * @public * @param {string} substring The substring to search for. * @param {number=} startIndex The index from which to start the search. * @returns {number} The first index where the given substring is found, or * -1 if it isn't in the sequence. * * @examples * Lazy('canal').indexOf('a') // => 1 * Lazy('canal').indexOf('a', 2) // => 3 * Lazy('canal').indexOf('ana') // => 1 * Lazy('canal').indexOf('andy') // => -1 * Lazy('canal').indexOf('x') // => -1 */ StringLikeSequence.prototype.indexOf = function indexOf(substring, startIndex) { return this.toString().indexOf(substring, startIndex); }; /** * Finds the index of the last occurrence of the given substring within this * sequence, starting from the specified index (or the end of the sequence) * and working backwards. * * @public * @param {string} substring The substring to search for. * @param {number=} startIndex The index from which to start the search. * @returns {number} The last index where the given substring is found, or * -1 if it isn't in the sequence. * * @examples * Lazy('canal').lastIndexOf('a') // => 3 * Lazy('canal').lastIndexOf('a', 2) // => 1 * Lazy('canal').lastIndexOf('ana') // => 1 * Lazy('canal').lastIndexOf('andy') // => -1 * Lazy('canal').lastIndexOf('x') // => -1 */ StringLikeSequence.prototype.lastIndexOf = function lastIndexOf(substring, startIndex) { return this.toString().lastIndexOf(substring, startIndex); }; /** * Checks if this sequence contains a given substring. * * @public * @param {string} substring The substring to check for. * @returns {boolean} Whether or not this sequence contains `substring`. * * @examples * Lazy('hello').contains('ell') // => true * Lazy('hello').contains('') // => true * Lazy('hello').contains('abc') // => false */ StringLikeSequence.prototype.contains = function contains(substring) { return this.indexOf(substring) !== -1; }; /** * Checks if this sequence ends with a given suffix. * * @public * @param {string} suffix The suffix to check for. * @returns {boolean} Whether or not this sequence ends with `suffix`. * * @examples * Lazy('foo').endsWith('oo') // => true * Lazy('foo').endsWith('') // => true * Lazy('foo').endsWith('abc') // => false */ StringLikeSequence.prototype.endsWith = function endsWith(suffix) { return this.substring(this.length() - suffix.length).toString() === suffix; }; /** * Checks if this sequence starts with a given prefix. * * @public * @param {string} prefix The prefix to check for. * @returns {boolean} Whether or not this sequence starts with `prefix`. * * @examples * Lazy('foo').startsWith('fo') // => true * Lazy('foo').startsWith('') // => true * Lazy('foo').startsWith('abc') // => false */ StringLikeSequence.prototype.startsWith = function startsWith(prefix) { return this.substring(0, prefix.length).toString() === prefix; }; /** * Converts all of the characters in this string to uppercase. * * @public * @returns {StringLikeSequence} A new sequence with the same characters as * this sequence, all uppercase. * * @examples * function nextLetter(a) { * return String.fromCharCode(a.charCodeAt(0) + 1); * } * * Lazy('foo').toUpperCase() // sequence: 'FOO' * Lazy('foo').substring(1).toUpperCase() // sequence: 'OO' * Lazy('abc').mapString(nextLetter).toUpperCase() // sequence: 'BCD' */ StringLikeSequence.prototype.toUpperCase = function toUpperCase() { return this.mapString(function(char) { return char.toUpperCase(); }); }; /** * Converts all of the characters in this string to lowercase. * * @public * @returns {StringLikeSequence} A new sequence with the same characters as * this sequence, all lowercase. * * @examples * function nextLetter(a) { * return String.fromCharCode(a.charCodeAt(0) + 1); * } * * Lazy('FOO').toLowerCase() // sequence: 'foo' * Lazy('FOO').substring(1).toLowerCase() // sequence: 'oo' * Lazy('ABC').mapString(nextLetter).toLowerCase() // sequence: 'bcd' */ StringLikeSequence.prototype.toLowerCase = function toLowerCase() { return this.mapString(function(char) { return char.toLowerCase(); }); }; /** * Maps the characters of this sequence onto a new {@link StringLikeSequence}. * * @public * @param {Function} mapFn The function used to map characters from this * sequence onto the new sequence. * @returns {StringLikeSequence} The new sequence. * * @examples * function upcase(char) { return char.toUpperCase(); } * * Lazy("foo").mapString(upcase) // sequence: "FOO" * Lazy("foo").mapString(upcase).charAt(0) // => "F" * Lazy("foo").mapString(upcase).charCodeAt(0) // => 70 * Lazy("foo").mapString(upcase).substring(1) // sequence: "OO" */ StringLikeSequence.prototype.mapString = function mapString(mapFn) { return new MappedStringLikeSequence(this, mapFn); }; /** * @constructor */ function MappedStringLikeSequence(parent, mapFn) { this.parent = parent; this.mapFn = mapFn; } MappedStringLikeSequence.prototype = new StringLikeSequence(); MappedStringLikeSequence.prototype.get = IndexedMappedSequence.prototype.get; MappedStringLikeSequence.prototype.length = IndexedMappedSequence.prototype.length; /** * Returns a copy of this sequence that reads back to front. * * @public * * @examples * Lazy("abcdefg").reverse() // sequence: "gfedcba" */ StringLikeSequence.prototype.reverse = function reverse() { return new ReversedStringLikeSequence(this); }; /** * @constructor */ function ReversedStringLikeSequence(parent) { this.parent = parent; } ReversedStringLikeSequence.prototype = new StringLikeSequence(); ReversedStringLikeSequence.prototype.get = IndexedReversedSequence.prototype.get; ReversedStringLikeSequence.prototype.length = IndexedReversedSequence.prototype.length; StringLikeSequence.prototype.toString = function toString() { return this.join(""); }; /** * Creates a {@link Sequence} comprising all of the matches for the specified * pattern in the underlying string. * * @public * @param {RegExp} pattern The pattern to match. * @returns {Sequence} A sequence of all the matches. * * @examples * Lazy("abracadabra").match(/a[bcd]/) // sequence: ["ab", "ac", "ad", "ab"] * Lazy("fee fi fo fum").match(/\w+/) // sequence: ["fee", "fi", "fo", "fum"] * Lazy("hello").match(/xyz/) // sequence: [] */ StringLikeSequence.prototype.match = function match(pattern) { return new StringMatchSequence(this, pattern); }; /** * @constructor */ function StringMatchSequence(parent, pattern) { this.parent = parent; this.pattern = pattern; } StringMatchSequence.prototype = new Sequence(); StringMatchSequence.prototype.getIterator = function getIterator() { return new StringMatchIterator(this.parent.toString(), this.pattern); }; /** * @constructor */ function StringMatchIterator(source, pattern) { this.source = source; this.pattern = cloneRegex(pattern); } StringMatchIterator.prototype.current = function current() { return this.match[0]; }; StringMatchIterator.prototype.moveNext = function moveNext() { return !!(this.match = this.pattern.exec(this.source)); }; /** * Creates a {@link Sequence} comprising all of the substrings of this string * separated by the given delimiter, which can be either a string or a regular * expression. * * @public * @param {string|RegExp} delimiter The delimiter to use for recognizing * substrings. * @returns {Sequence} A sequence of all the substrings separated by the given * delimiter. * * @examples * Lazy("foo").split("") // sequence: ["f", "o", "o"] * Lazy("yo dawg").split(" ") // sequence: ["yo", "dawg"] * Lazy("bah bah\tblack sheep").split(/\s+/) // sequence: ["bah", "bah", "black", "sheep"] */ StringLikeSequence.prototype.split = function split(delimiter) { return new SplitStringSequence(this, delimiter); }; /** * @constructor */ function SplitStringSequence(parent, pattern) { this.parent = parent; this.pattern = pattern; } SplitStringSequence.prototype = new Sequence(); SplitStringSequence.prototype.getIterator = function getIterator() { var source = this.parent.toString(); if (this.pattern instanceof RegExp) { if (this.pattern.source === "" || this.pattern.source === "(?:)") { return new CharIterator(source); } else { return new SplitWithRegExpIterator(source, this.pattern); } } else if (this.pattern === "") { return new CharIterator(source); } else { return new SplitWithStringIterator(source, this.pattern); } }; /** * @constructor */ function SplitWithRegExpIterator(source, pattern) { this.source = source; this.pattern = cloneRegex(pattern); } SplitWithRegExpIterator.prototype.current = function current() { return this.source.substring(this.start, this.end); }; SplitWithRegExpIterator.prototype.moveNext = function moveNext() { if (!this.pattern) { return false; } var match = this.pattern.exec(this.source); if (match) { this.start = this.nextStart ? this.nextStart : 0; this.end = match.index; this.nextStart = match.index + match[0].length; return true; } else if (this.pattern) { this.start = this.nextStart; this.end = undefined; this.nextStart = undefined; this.pattern = undefined; return true; } return false; }; /** * @constructor */ function SplitWithStringIterator(source, delimiter) { this.source = source; this.delimiter = delimiter; } SplitWithStringIterator.prototype.current = function current() { return this.source.substring(this.leftIndex, this.rightIndex); }; SplitWithStringIterator.prototype.moveNext = function moveNext() { if (!this.finished) { this.leftIndex = typeof this.leftIndex !== "undefined" ? this.rightIndex + this.delimiter.length : 0; this.rightIndex = this.source.indexOf(this.delimiter, this.leftIndex); } if (this.rightIndex === -1) { this.finished = true; this.rightIndex = undefined; return true; } return !this.finished; }; /** * Wraps a string exposing {@link #match} and {@link #split} methods that return * {@link Sequence} objects instead of arrays, improving on the efficiency of * JavaScript's built-in `String#split` and `String.match` methods and * supporting asynchronous iteration. * * @param {string} source The string to wrap. * @constructor */ function StringWrapper(source) { this.source = source; } StringWrapper.prototype = new StringLikeSequence(); StringWrapper.prototype.root = function root() { return this; }; StringWrapper.prototype.isAsync = function isAsync() { return false; }; StringWrapper.prototype.get = function get(i) { return this.source.charAt(i); }; StringWrapper.prototype.length = function length() { return this.source.length; }; StringWrapper.prototype.toString = function toString() { return this.source; }; /** * A `GeneratedSequence` does not wrap an in-memory colllection but rather * determines its elements on-the-fly during iteration according to a generator * function. * * You create a `GeneratedSequence` by calling {@link Lazy.generate}. * * @public * @constructor * @param {function(number):*} generatorFn A function which accepts an index * and returns a value for the element at that position in the sequence. * @param {number=} length The length of the sequence. If this argument is * omitted, the sequence will go on forever. */ function GeneratedSequence(generatorFn, length) { this.get = generatorFn; this.fixedLength = length; } GeneratedSequence.prototype = new Sequence(); GeneratedSequence.prototype.isAsync = function isAsync() { return false; }; /** * Returns the length of this sequence. * * @public * @returns {number} The length, or `undefined` if this is an indefinite * sequence. */ GeneratedSequence.prototype.length = function length() { return this.fixedLength; }; /** * Iterates over the sequence produced by invoking this sequence's generator * function up to its specified length, or, if length is `undefined`, * indefinitely (in which case the sequence will go on forever--you would need * to call, e.g., {@link Sequence#take} to limit iteration). * * @public * @param {Function} fn The function to call on each output from the generator * function. */ GeneratedSequence.prototype.each = function each(fn) { var generatorFn = this.get, length = this.fixedLength, i = 0; while (typeof length === "undefined" || i < length) { if (fn(generatorFn(i), i++) === false) { return false; } } return true; }; GeneratedSequence.prototype.getIterator = function getIterator() { return new GeneratedIterator(this); }; /** * Iterates over a generated sequence. (This allows generated sequences to be * iterated asynchronously.) * * @param {GeneratedSequence} sequence The generated sequence to iterate over. * @constructor */ function GeneratedIterator(sequence) { this.sequence = sequence; this.index = 0; this.currentValue = null; } GeneratedIterator.prototype.current = function current() { return this.currentValue; }; GeneratedIterator.prototype.moveNext = function moveNext() { var sequence = this.sequence; if (typeof sequence.fixedLength === "number" && this.index >= sequence.fixedLength) { return false; } this.currentValue = sequence.get(this.index++); return true; }; /** * An `AsyncSequence` iterates over its elements asynchronously when * {@link #each} is called. * * You get an `AsyncSequence` by calling {@link Sequence#async} on any * sequence. Note that some sequence types may not support asynchronous * iteration. * * Returning values * ---------------- * * Because of its asynchronous nature, an `AsyncSequence` cannot be used in the * same way as other sequences for functions that return values directly (e.g., * `reduce`, `max`, `any`, even `toArray`). * * Instead, these methods return an `AsyncHandle` whose `onComplete` method * accepts a callback that will be called with the final result once iteration * has finished. * * Defining custom asynchronous sequences * -------------------------------------- * * There are plenty of ways to define an asynchronous sequence. Here's one. * * 1. First, implement an {@link Iterator}. This is an object whose prototype * has the methods {@link Iterator#moveNext} (which returns a `boolean`) and * {@link current} (which returns the current value). * 2. Next, create a simple wrapper that inherits from `AsyncSequence`, whose * `getIterator` function returns an instance of the iterator type you just * defined. * * The default implementation for {@link #each} on an `AsyncSequence` is to * create an iterator and then asynchronously call {@link Iterator#moveNext} * (using `setImmediate`, if available, otherwise `setTimeout`) until the iterator * can't move ahead any more. * * @public * @constructor * @param {Sequence} parent A {@link Sequence} to wrap, to expose asynchronous * iteration. * @param {number=} interval How many milliseconds should elapse between each * element when iterating over this sequence. If this argument is omitted, * asynchronous iteration will be executed as fast as possible. */ function AsyncSequence(parent, interval) { if (parent instanceof AsyncSequence) { throw new Error("Sequence is already asynchronous!"); } this.parent = parent; this.interval = interval; this.onNextCallback = getOnNextCallback(interval); this.cancelCallback = getCancelCallback(interval); } AsyncSequence.prototype = new Sequence(); AsyncSequence.prototype.isAsync = function isAsync() { return true; }; /** * Throws an exception. You cannot manually iterate over an asynchronous * sequence. * * @public * @example * Lazy([1, 2, 3]).async().getIterator() // throws */ AsyncSequence.prototype.getIterator = function getIterator() { throw new Error('An AsyncSequence does not support synchronous iteration.'); }; /** * An asynchronous version of {@link Sequence#each}. * * @public * @param {Function} fn The function to invoke asynchronously on each element in * the sequence one by one. * @returns {AsyncHandle} An {@link AsyncHandle} providing the ability to * cancel the asynchronous iteration (by calling `cancel()`) as well as * supply callback(s) for when an error is encountered (`onError`) or when * iteration is complete (`onComplete`). */ AsyncSequence.prototype.each = function each(fn) { var iterator = this.parent.getIterator(), onNextCallback = this.onNextCallback, cancelCallback = this.cancelCallback, i = 0; var handle = new AsyncHandle(function cancel() { if (cancellationId) { cancelCallback(cancellationId); } }); var cancellationId = onNextCallback(function iterate() { cancellationId = null; try { if (iterator.moveNext() && fn(iterator.current(), i++) !== false) { cancellationId = onNextCallback(iterate); } else { handle._resolve(); } } catch (e) { handle._reject(e); } }); return handle; }; /** * An `AsyncHandle` provides a [Promises/A+](http://promises-aplus.github.io/promises-spec/) * compliant interface for an {@link AsyncSequence} that is currently (or was) * iterating over its elements. * * In addition to behaving as a promise, an `AsyncHandle` provides the ability * to {@link AsyncHandle#cancel} iteration (if `cancelFn` is provided) * and also offers convenient {@link AsyncHandle#onComplete} and * {@link AsyncHandle#onError} methods to attach listeners for when iteration * is complete or an error is thrown during iteration. * * @public * @param {Function} cancelFn A function to cancel asynchronous iteration. * This is passed in to support different cancellation mechanisms for * different forms of asynchronous sequences (e.g., timeout-based * sequences, sequences based on I/O, etc.). * @constructor * * @example * // Create a sequence of 100,000 random numbers, in chunks of 100. * var sequence = Lazy.generate(Math.random) * .chunk(100) * .async() * .take(1000); * * // Reduce-style operations -- i.e., operations that return a *value* (as * // opposed to a *sequence*) -- return an AsyncHandle for async sequences. * var handle = sequence.toArray(); * * handle.onComplete(function(array) { * // Do something w/ 1,000-element array. * }); * * // Since an AsyncHandle is a promise, you can also use it to create * // subsequent promises using `then` (see the Promises/A+ spec for more * // info). * var flattened = handle.then(function(array) { * return Lazy(array).flatten(); * }); */ function AsyncHandle(cancelFn) { this.resolveListeners = []; this.rejectListeners = []; this.state = PENDING; this.cancelFn = cancelFn; } // Async handle states var PENDING = 1, RESOLVED = 2, REJECTED = 3; AsyncHandle.prototype.then = function then(onFulfilled, onRejected) { var promise = new AsyncHandle(this.cancelFn); this.resolveListeners.push(function(value) { try { if (typeof onFulfilled !== 'function') { resolve(promise, value); return; } resolve(promise, onFulfilled(value)); } catch (e) { promise._reject(e); } }); this.rejectListeners.push(function(reason) { try { if (typeof onRejected !== 'function') { promise._reject(reason); return; } resolve(promise, onRejected(reason)); } catch (e) { promise._reject(e); } }); if (this.state === RESOLVED) { this._resolve(this.value); } if (this.state === REJECTED) { this._reject(this.reason); } return promise; }; AsyncHandle.prototype._resolve = function _resolve(value) { if (this.state === REJECTED) { return; } if (this.state === PENDING) { this.state = RESOLVED; this.value = value; } consumeListeners(this.resolveListeners, this.value); }; AsyncHandle.prototype._reject = function _reject(reason) { if (this.state === RESOLVED) { return; } if (this.state === PENDING) { this.state = REJECTED; this.reason = reason; } consumeListeners(this.rejectListeners, this.reason); }; /** * Cancels asynchronous iteration. * * @public */ AsyncHandle.prototype.cancel = function cancel() { if (this.cancelFn) { this.cancelFn(); this.cancelFn = null; this._resolve(false); } }; /** * Updates the handle with a callback to execute when iteration is completed. * * @public * @param {Function} callback The function to call when the asynchronous * iteration is completed. * @return {AsyncHandle} A reference to the handle (for chaining). */ AsyncHandle.prototype.onComplete = function onComplete(callback) { this.resolveListeners.push(callback); return this; }; /** * Updates the handle with a callback to execute if/when any error is * encountered during asynchronous iteration. * * @public * @param {Function} callback The function to call, with any associated error * object, when an error occurs. * @return {AsyncHandle} A reference to the handle (for chaining). */ AsyncHandle.prototype.onError = function onError(callback) { this.rejectListeners.push(callback); return this; }; /** * Promise resolution procedure: * http://promises-aplus.github.io/promises-spec/#the_promise_resolution_procedure */ function resolve(promise, x) { if (promise === x) { promise._reject(new TypeError('Cannot resolve a promise to itself')); return; } if (x instanceof AsyncHandle) { x.then( function(value) { resolve(promise, value); }, function(reason) { promise._reject(reason); } ); return; } var then; try { then = (/function|object/).test(typeof x) && x != null && x.then; } catch (e) { promise._reject(e); return; } var thenableState = PENDING; if (typeof then === 'function') { try { then.call( x, function resolvePromise(value) { if (thenableState !== PENDING) { return; } thenableState = RESOLVED; resolve(promise, value); }, function rejectPromise(reason) { if (thenableState !== PENDING) { return; } thenableState = REJECTED; promise._reject(reason); } ); } catch (e) { if (thenableState !== PENDING) { return; } promise._reject(e); } return; } promise._resolve(x); } function consumeListeners(listeners, value, callback) { callback || (callback = getOnNextCallback()); callback(function() { if (listeners.length > 0) { listeners.shift()(value); consumeListeners(listeners, value, callback); } }); } function getOnNextCallback(interval) { if (typeof interval === "undefined") { if (typeof setImmediate === "function") { return setImmediate; } } interval = interval || 0; return function(fn) { return setTimeout(fn, interval); }; } function getCancelCallback(interval) { if (typeof interval === "undefined") { if (typeof clearImmediate === "function") { return clearImmediate; } } return clearTimeout; } /** * Transform a value, whether the value is retrieved asynchronously or directly. * * @private * @param {Function} fn The function that transforms the value. * @param {*} value The value to be transformed. This can be an {@link AsyncHandle} when the value * is retrieved asynchronously, otherwise it can be anything. * @returns {*} An {@link AsyncHandle} when `value` is also an {@link AsyncHandle}, otherwise * whatever `fn` resulted in. */ function transform(fn, value) { if (value instanceof AsyncHandle) { return value.then(function() { fn(value); }); } return fn(value); } /** * An async version of {@link Sequence#reverse}. */ AsyncSequence.prototype.reverse = function reverse() { return this.parent.reverse().async(); }; /** * A version of {@link Sequence#find} which returns an {@link AsyncHandle}. * * @public * @param {Function} predicate A function to call on (potentially) every element * in the sequence. * @returns {AsyncHandle} An {@link AsyncHandle} (promise) which resolves to * the found element, once it is detected, or else `undefined`. */ AsyncSequence.prototype.find = function find(predicate) { var found; var handle = this.each(function(e, i) { if (predicate(e, i)) { found = e; return false; } }); return handle.then(function() { return found; }); }; /** * A version of {@link Sequence#indexOf} which returns an {@link AsyncHandle}. * * @public * @param {*} value The element to search for in the sequence. * @returns {AsyncHandle} An {@link AsyncHandle} (promise) which resolves to * the found index, once it is detected, or -1. */ AsyncSequence.prototype.indexOf = function indexOf(value) { var foundIndex = -1; var handle = this.each(function(e, i) { if (e === value) { foundIndex = i; return false; } }); return handle.then(function() { return foundIndex; }); }; /** * A version of {@link Sequence#contains} which returns an {@link AsyncHandle}. * * @public * @param {*} value The element to search for in the sequence. * @returns {AsyncHandle} An {@link AsyncHandle} (promise) which resolves to * either `true` or `false` to indicate whether the element was found. */ AsyncSequence.prototype.contains = function contains(value) { var found = false; var handle = this.each(function(e) { if (e === value) { found = true; return false; } }); return handle.then(function() { return found; }); }; /** * Just return the same sequence for `AsyncSequence#async` (I see no harm in this). */ AsyncSequence.prototype.async = function async() { return this; }; /** * See {@link ObjectLikeSequence#watch} for docs. */ ObjectWrapper.prototype.watch = function watch(propertyNames) { return new WatchedPropertySequence(this.source, propertyNames); }; function WatchedPropertySequence(object, propertyNames) { this.listeners = []; if (!propertyNames) { propertyNames = Lazy(object).keys().toArray(); } else if (!(propertyNames instanceof Array)) { propertyNames = [propertyNames]; } var listeners = this.listeners, index = 0; Lazy(propertyNames).each(function(propertyName) { var propertyValue = object[propertyName]; Object.defineProperty(object, propertyName, { get: function() { return propertyValue; }, set: function(value) { for (var i = listeners.length - 1; i >= 0; --i) { if (listeners[i]({ property: propertyName, value: value }, index) === false) { listeners.splice(i, 1); } } propertyValue = value; ++index; } }); }); } WatchedPropertySequence.prototype = new AsyncSequence(); WatchedPropertySequence.prototype.each = function each(fn) { this.listeners.push(fn); }; /** * A StreamLikeSequence comprises a sequence of 'chunks' of data, which are * typically multiline strings. * * @constructor */ function StreamLikeSequence() {} StreamLikeSequence.prototype = new AsyncSequence(); StreamLikeSequence.prototype.isAsync = function isAsync() { return true; }; StreamLikeSequence.prototype.split = function split(delimiter) { return new SplitStreamSequence(this, delimiter); }; /** * @constructor */ function SplitStreamSequence(parent, delimiter) { this.parent = parent; this.delimiter = delimiter; this.each = this.getEachForDelimiter(delimiter); } SplitStreamSequence.prototype = new Sequence(); SplitStreamSequence.prototype.getEachForDelimiter = function getEachForDelimiter(delimiter) { if (delimiter instanceof RegExp) { return this.regexEach; } return this.stringEach; }; SplitStreamSequence.prototype.regexEach = function each(fn) { var delimiter = cloneRegex(this.delimiter), buffer = '', start = 0, end, index = 0; var handle = this.parent.each(function(chunk) { buffer += chunk; var match; while (match = delimiter.exec(buffer)) { end = match.index; if (fn(buffer.substring(start, end), index++) === false) { return false; } start = end + match[0].length; } buffer = buffer.substring(start); start = 0; }); handle.onComplete(function() { if (buffer.length > 0) { fn(buffer, index++); } }); return handle; }; SplitStreamSequence.prototype.stringEach = function each(fn) { var delimiter = this.delimiter, pieceIndex = 0, buffer = '', bufferIndex = 0; var handle = this.parent.each(function(chunk) { buffer += chunk; var delimiterIndex; while ((delimiterIndex = buffer.indexOf(delimiter)) >= 0) { var piece = buffer.substr(0,delimiterIndex); buffer = buffer.substr(delimiterIndex+delimiter.length); if (fn(piece,pieceIndex++) === false) { return false; } } return true; }); handle.onComplete(function() { fn(buffer, pieceIndex++); }); return handle; }; StreamLikeSequence.prototype.lines = function lines() { return this.split("\n"); }; StreamLikeSequence.prototype.match = function match(pattern) { return new MatchedStreamSequence(this, pattern); }; /** * @constructor */ function MatchedStreamSequence(parent, pattern) { this.parent = parent; this.pattern = cloneRegex(pattern); } MatchedStreamSequence.prototype = new AsyncSequence(); MatchedStreamSequence.prototype.each = function each(fn) { var pattern = this.pattern, done = false, i = 0; return this.parent.each(function(chunk) { Lazy(chunk).match(pattern).each(function(match) { if (fn(match, i++) === false) { done = true; return false; } }); return !done; }); }; /** * Defines a wrapper for custom {@link StreamLikeSequence}s. This is useful * if you want a way to handle a stream of events as a sequence, but you can't * use Lazy's existing interface (i.e., you're wrapping an object from a * library with its own custom events). * * This method defines a *factory*: that is, it produces a function that can * be used to wrap objects and return a {@link Sequence}. Hopefully the * example will make this clear. * * @public * @param {Function} initializer An initialization function called on objects * created by this factory. `this` will be bound to the created object, * which is an instance of {@link StreamLikeSequence}. Use `emit` to * generate data for the sequence. * @returns {Function} A function that creates a new {@link StreamLikeSequence}, * initializes it using the specified function, and returns it. * * @example * var factory = Lazy.createWrapper(function(eventSource) { * var sequence = this; * * eventSource.handleEvent(function(data) { * sequence.emit(data); * }); * }); * * var eventEmitter = { * triggerEvent: function(data) { * eventEmitter.eventHandler(data); * }, * handleEvent: function(handler) { * eventEmitter.eventHandler = handler; * }, * eventHandler: function() {} * }; * * var events = []; * * factory(eventEmitter).each(function(e) { * events.push(e); * }); * * eventEmitter.triggerEvent('foo'); * eventEmitter.triggerEvent('bar'); * * events // => ['foo', 'bar'] */ Lazy.createWrapper = function createWrapper(initializer) { var ctor = function() { this.listeners = []; }; ctor.prototype = new StreamLikeSequence(); ctor.prototype.each = function(listener) { this.listeners.push(listener); }; ctor.prototype.emit = function(data) { var listeners = this.listeners; for (var len = listeners.length, i = len - 1; i >= 0; --i) { if (listeners[i](data) === false) { listeners.splice(i, 1); } } }; return function() { var sequence = new ctor(); initializer.apply(sequence, arguments); return sequence; }; }; /** * Creates a {@link GeneratedSequence} using the specified generator function * and (optionally) length. * * @public * @param {function(number):*} generatorFn The function used to generate the * sequence. This function accepts an index as a parameter and should return * a value for that index in the resulting sequence. * @param {number=} length The length of the sequence, for sequences with a * definite length. * @returns {GeneratedSequence} The generated sequence. * * @examples * var randomNumbers = Lazy.generate(Math.random); * var countingNumbers = Lazy.generate(function(i) { return i + 1; }, 5); * * randomNumbers // instanceof Lazy.GeneratedSequence * randomNumbers.length() // => undefined * countingNumbers // sequence: [1, 2, 3, 4, 5] * countingNumbers.length() // => 5 */ Lazy.generate = function generate(generatorFn, length) { return new GeneratedSequence(generatorFn, length); }; /** * Creates a sequence from a given starting value, up to a specified stopping * value, incrementing by a given step. Invalid values for any of these * arguments (e.g., a step of 0) result in an empty sequence. * * @public * @returns {GeneratedSequence} The sequence defined by the given ranges. * * @examples * Lazy.range(3) // sequence: [0, 1, 2] * Lazy.range(1, 4) // sequence: [1, 2, 3] * Lazy.range(2, 10, 2) // sequence: [2, 4, 6, 8] * Lazy.range(5, 1, 2) // sequence: [] * Lazy.range(5, 15, -2) // sequence: [] * Lazy.range(3, 10, 3) // sequence: [3, 6, 9] * Lazy.range(5, 2) // sequence: [5, 4, 3] * Lazy.range(7, 2, -2) // sequence: [7, 5, 3] * Lazy.range(3, 5, 0) // sequence: [] */ Lazy.range = function range() { var start = arguments.length > 1 ? arguments[0] : 0, stop = arguments.length > 1 ? arguments[1] : arguments[0], step = arguments.length > 2 && arguments[2]; if (step === false) { step = stop > start ? 1 : -1; } if (step === 0) { return Lazy([]); } return Lazy.generate(function(i) { return start + (step * i); }) .take(Math.ceil((stop - start) / step)); }; /** * Creates a sequence consisting of the given value repeated a specified number * of times. * * @public * @param {*} value The value to repeat. * @param {number=} count The number of times the value should be repeated in * the sequence. If this argument is omitted, the value will repeat forever. * @returns {GeneratedSequence} The sequence containing the repeated value. * * @examples * Lazy.repeat("hi", 3) // sequence: ["hi", "hi", "hi"] * Lazy.repeat("young") // instanceof Lazy.GeneratedSequence * Lazy.repeat("young").length() // => undefined * Lazy.repeat("young").take(3) // sequence: ["young", "young", "young"] */ Lazy.repeat = function repeat(value, count) { return Lazy.generate(function() { return value; }, count); }; Lazy.Sequence = Sequence; Lazy.ArrayLikeSequence = ArrayLikeSequence; Lazy.ObjectLikeSequence = ObjectLikeSequence; Lazy.StringLikeSequence = StringLikeSequence; Lazy.StreamLikeSequence = StreamLikeSequence; Lazy.GeneratedSequence = GeneratedSequence; Lazy.AsyncSequence = AsyncSequence; Lazy.AsyncHandle = AsyncHandle; /*** Useful utility methods ***/ /** * Creates a shallow copy of an array or object. * * @examples * var array = [1, 2, 3], clonedArray, * object = { foo: 1, bar: 2 }, clonedObject; * * clonedArray = Lazy.clone(array); // => [1, 2, 3] * clonedArray.push(4); // clonedArray == [1, 2, 3, 4] * array; // => [1, 2, 3] * * clonedObject = Lazy.clone(object); // => { foo: 1, bar: 2 } * clonedObject.baz = 3; // clonedObject == { foo: 1, bar: 2, baz: 3 } * object; // => { foo: 1, bar: 2 } */ Lazy.clone = function clone(target) { return Lazy(target).value(); }; /** * Marks a method as deprecated, so calling it will issue a console warning. */ Lazy.deprecate = function deprecate(message, fn) { return function() { console.warn(message); return fn.apply(this, arguments); }; }; var arrayPop = Array.prototype.pop, arraySlice = Array.prototype.slice; /** * Creates a callback... you know, Lo-Dash style. * * - for functions, just returns the function * - for strings, returns a pluck-style callback * - for objects, returns a where-style callback * * @private * @param {Function|string|Object} callback A function, string, or object to * convert to a callback. * @param {*} defaultReturn If the callback is undefined, a default return * value to use for the function. * @returns {Function} The callback function. * * @examples * createCallback(function() {}) // instanceof Function * createCallback('foo') // instanceof Function * createCallback('foo')({ foo: 'bar'}) // => 'bar' * createCallback({ foo: 'bar' })({ foo: 'bar' }) // => true * createCallback({ foo: 'bar' })({ foo: 'baz' }) // => false */ function createCallback(callback, defaultValue) { switch (typeof callback) { case "function": return callback; case "string": return function(e) { return e[callback]; }; case "object": return function(e) { return Lazy(callback).all(function(value, key) { return e[key] === value; }); }; case "undefined": return defaultValue ? function() { return defaultValue; } : Lazy.identity; default: throw new Error("Don't know how to make a callback from a " + typeof callback + "!"); } } /** * Takes a function that returns a value for one argument and produces a * function that compares two arguments. * * @private * @param {Function|string|Object} callback A function, string, or object to * convert to a callback using `createCallback`. * @returns {Function} A function that accepts two values and returns 1 if * the first is greater, -1 if the second is greater, or 0 if they are * equivalent. * * @examples * createComparator('a')({ a: 1 }, { a: 2 }); // => -1 * createComparator('a')({ a: 6 }, { a: 2 }); // => 1 * createComparator('a')({ a: 1 }, { a: 1 }); // => 0 * createComparator()(3, 5); // => -1 * createComparator()(7, 5); // => 1 * createComparator()(3, 3); // => 0 */ function createComparator(callback, descending) { if (!callback) { return compare; } callback = createCallback(callback); return function(x, y) { return compare(callback(x), callback(y)); }; } /** * Takes a function and returns a function with the same logic but the * arguments reversed. Only applies to functions w/ arity=2 as this is private * and I can do what I want. * * @private * @param {Function} fn The function to "reverse" * @returns {Function} The "reversed" function * * @examples * reverseArguments(function(x, y) { return x + y; })('a', 'b'); // => 'ba' */ function reverseArguments(fn) { return function(x, y) { return fn(y, x); }; } /** * Creates a Set containing the specified values. * * @param {...Array} values One or more array(s) of values used to populate the * set. * @returns {Set} A new set containing the values passed in. */ function createSet(values) { var set = new Set(); Lazy(values || []).flatten().each(function(e) { set.add(e); }); return set; } /** * Compares two elements for sorting purposes. * * @private * @param {*} x The left element to compare. * @param {*} y The right element to compare. * @returns {number} 1 if x > y, -1 if x < y, or 0 if x and y are equal. * * @examples * compare(1, 2) // => -1 * compare(1, 1) // => 0 * compare(2, 1) // => 1 * compare('a', 'b') // => -1 */ function compare(x, y) { if (x === y) { return 0; } return x > y ? 1 : -1; } /** * Iterates over every element in an array. * * @param {Array} array The array. * @param {Function} fn The function to call on every element, which can return * false to stop the iteration early. * @returns {boolean} True if every element in the entire sequence was iterated, * otherwise false. */ function forEach(array, fn) { var i = -1, len = array.length; while (++i < len) { if (fn(array[i], i) === false) { return false; } } return true; } function getFirst(sequence) { var result; sequence.each(function(e) { result = e; return false; }); return result; } /** * Checks if an element exists in an array. * * @private * @param {Array} array * @param {*} element * @returns {boolean} Whether or not the element exists in the array. * * @examples * arrayContains([1, 2], 2) // => true * arrayContains([1, 2], 3) // => false * arrayContains([undefined], undefined) // => true * arrayContains([NaN], NaN) // => true */ function arrayContains(array, element) { var i = -1, length = array.length; // Special handling for NaN if (element !== element) { while (++i < length) { if (array[i] !== array[i]) { return true; } } return false; } while (++i < length) { if (array[i] === element) { return true; } } return false; } /** * Checks if an element exists in an array before a given index. * * @private * @param {Array} array * @param {*} element * @param {number} index * @param {Function} keyFn * @returns {boolean} * * @examples * arrayContainsBefore([1, 2, 3], 3, 2) // => false * arrayContainsBefore([1, 2, 3], 3, 3) // => true */ function arrayContainsBefore(array, element, index, keyFn) { var i = -1; if (keyFn) { keyFn = createCallback(keyFn); while (++i < index) { if (keyFn(array[i]) === keyFn(element)) { return true; } } } else { while (++i < index) { if (array[i] === element) { return true; } } } return false; } /** * Swaps the elements at two specified positions of an array. * * @private * @param {Array} array * @param {number} i * @param {number} j * * @examples * var array = [1, 2, 3, 4, 5]; * * swap(array, 2, 3) // array == [1, 2, 4, 3, 5] */ function swap(array, i, j) { var temp = array[i]; array[i] = array[j]; array[j] = temp; } /** * "Clones" a regular expression (but makes it always global). * * @private * @param {RegExp|string} pattern * @returns {RegExp} */ function cloneRegex(pattern) { return eval("" + pattern + (!pattern.global ? "g" : "")); }; /** * A collection of unique elements. * * @private * @constructor * * @examples * var set = new Set(), * obj1 = {}, * obj2 = {}, * fn1 = function fn1() {}, * fn2 = function fn2() {}; * * set.add('foo') // => true * set.add('foo') // => false * set.add(1) // => true * set.add(1) // => false * set.add('1') // => true * set.add('1') // => false * set.add(obj1) // => true * set.add(obj1) // => false * set.add(obj2) // => true * set.add(fn1) // => true * set.add(fn2) // => true * set.add(fn2) // => false * set.contains('__proto__') // => false * set.add('__proto__') // => true * set.add('__proto__') // => false * set.contains('add') // => false * set.add('add') // => true * set.add('add') // => false * set.contains(undefined) // => false * set.add(undefined) // => true * set.contains(undefined) // => true * set.contains('undefined') // => false * set.add('undefined') // => true * set.contains('undefined') // => true * set.contains(NaN) // => false * set.add(NaN) // => true * set.contains(NaN) // => true * set.contains('NaN') // => false * set.add('NaN') // => true * set.contains('NaN') // => true * set.contains('@foo') // => false * set.add('@foo') // => true * set.contains('@foo') // => true */ function Set() { this.table = {}; this.objects = []; } /** * Attempts to add a unique value to the set. * * @param {*} value The value to add. * @returns {boolean} True if the value was added to the set (meaning an equal * value was not already present), or else false. */ Set.prototype.add = function add(value) { var table = this.table, type = typeof value, // only applies for strings firstChar, // only applies for objects objects; switch (type) { case "number": case "boolean": case "undefined": if (!table[value]) { table[value] = true; return true; } return false; case "string": // Essentially, escape the first character if it could possibly collide // with a number, boolean, or undefined (or a string that happens to start // with the escape character!), OR if it could override a special property // such as '__proto__' or 'constructor'. switch (value.charAt(0)) { case "_": // e.g., __proto__ case "f": // for 'false' case "t": // for 'true' case "c": // for 'constructor' case "u": // for 'undefined' case "@": // escaped case "0": case "1": case "2": case "3": case "4": case "5": case "6": case "7": case "8": case "9": case "N": // for NaN value = "@" + value; } if (!table[value]) { table[value] = true; return true; } return false; default: // For objects and functions, we can't really do anything other than store // them in an array and do a linear search for reference equality. objects = this.objects; if (!arrayContains(objects, value)) { objects.push(value); return true; } return false; } }; /** * Checks whether the set contains a value. * * @param {*} value The value to check for. * @returns {boolean} True if the set contains the value, or else false. */ Set.prototype.contains = function contains(value) { var type = typeof value, // only applies for strings firstChar; switch (type) { case "number": case "boolean": case "undefined": return !!this.table[value]; case "string": // Essentially, escape the first character if it could possibly collide // with a number, boolean, or undefined (or a string that happens to start // with the escape character!), OR if it could override a special property // such as '__proto__' or 'constructor'. switch (value.charAt(0)) { case "_": // e.g., __proto__ case "f": // for 'false' case "t": // for 'true' case "c": // for 'constructor' case "u": // for 'undefined' case "@": // escaped case "0": case "1": case "2": case "3": case "4": case "5": case "6": case "7": case "8": case "9": case "N": // for NaN value = "@" + value; } return !!this.table[value]; default: // For objects and functions, we can't really do anything other than store // them in an array and do a linear search for reference equality. return arrayContains(this.objects, value); } }; /** * A "rolling" queue, with a fixed capacity. As items are added to the head, * excess items are dropped from the tail. * * @private * @constructor * * @examples * var queue = new Queue(3); * * queue.add(1).toArray() // => [1] * queue.add(2).toArray() // => [1, 2] * queue.add(3).toArray() // => [1, 2, 3] * queue.add(4).toArray() // => [2, 3, 4] * queue.add(5).add(6).toArray() // => [4, 5, 6] * queue.add(7).add(8).toArray() // => [6, 7, 8] * * // also want to check corner cases * new Queue(1).add('foo').add('bar').toArray() // => ['bar'] * new Queue(0).add('foo').toArray() // => [] * new Queue(-1) // throws * * @benchmarks * function populateQueue(count, capacity) { * var q = new Queue(capacity); * for (var i = 0; i < count; ++i) { * q.add(i); * } * } * * function populateArray(count, capacity) { * var arr = []; * for (var i = 0; i < count; ++i) { * if (arr.length === capacity) { arr.shift(); } * arr.push(i); * } * } * * populateQueue(100, 10); // populating a Queue * populateArray(100, 10); // populating an Array */ function Queue(capacity) { this.contents = new Array(capacity); this.start = 0; this.count = 0; } /** * Adds an item to the queue, and returns the queue. */ Queue.prototype.add = function add(element) { var contents = this.contents, capacity = contents.length, start = this.start; if (this.count === capacity) { contents[start] = element; this.start = (start + 1) % capacity; } else { contents[this.count++] = element; } return this; }; /** * Returns an array containing snapshot of the queue's contents. */ Queue.prototype.toArray = function toArray() { var contents = this.contents, start = this.start, count = this.count; var snapshot = contents.slice(start, start + count); if (snapshot.length < count) { snapshot = snapshot.concat(contents.slice(0, count - snapshot.length)); } return snapshot; }; /** * Shared base method for defining new sequence types. */ function defineSequenceType(base, name, overrides) { /** @constructor */ var ctor = function ctor() {}; // Make this type inherit from the specified base. ctor.prototype = new base(); // Attach overrides to the new sequence type's prototype. for (var override in overrides) { ctor.prototype[override] = overrides[override]; } // Define a factory method that sets the new sequence's parent to the caller // and (optionally) applies any additional initialization logic. // Expose this as a chainable method so that we can do: // Lazy(...).map(...).filter(...).blah(...); var factory = function factory() { var sequence = new ctor(); // Every sequence needs a reference to its parent in order to work. sequence.parent = this; // If a custom init function was supplied, call it now. if (sequence.init) { sequence.init.apply(sequence, arguments); } return sequence; }; var methodNames = typeof name === 'string' ? [name] : name; for (var i = 0; i < methodNames.length; ++i) { base.prototype[methodNames[i]] = factory; } return ctor; } return Lazy; }); /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(7).setImmediate, __webpack_require__(7).clearImmediate)) /***/ }, /* 120 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(module, global) {var __WEBPACK_AMD_DEFINE_RESULT__;/** * @license * lodash * Copyright jQuery Foundation and other contributors * Released under MIT license * Based on Underscore.js 1.8.3 * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors */ ;(function() { /** Used as a safe reference for `undefined` in pre-ES5 environments. */ var undefined; /** Used as the semantic version number. */ var VERSION = '4.12.0'; /** Used as the size to enable large array optimizations. */ var LARGE_ARRAY_SIZE = 200; /** Used as the `TypeError` message for "Functions" methods. */ var FUNC_ERROR_TEXT = 'Expected a function'; /** Used to stand-in for `undefined` hash values. */ var HASH_UNDEFINED = '__lodash_hash_undefined__'; /** Used as the internal argument placeholder. */ var PLACEHOLDER = '__lodash_placeholder__'; /** Used to compose bitmasks for wrapper metadata. */ var BIND_FLAG = 1, BIND_KEY_FLAG = 2, CURRY_BOUND_FLAG = 4, CURRY_FLAG = 8, CURRY_RIGHT_FLAG = 16, PARTIAL_FLAG = 32, PARTIAL_RIGHT_FLAG = 64, ARY_FLAG = 128, REARG_FLAG = 256, FLIP_FLAG = 512; /** Used to compose bitmasks for comparison styles. */ var UNORDERED_COMPARE_FLAG = 1, PARTIAL_COMPARE_FLAG = 2; /** Used as default options for `_.truncate`. */ var DEFAULT_TRUNC_LENGTH = 30, DEFAULT_TRUNC_OMISSION = '...'; /** Used to detect hot functions by number of calls within a span of milliseconds. */ var HOT_COUNT = 150, HOT_SPAN = 16; /** Used to indicate the type of lazy iteratees. */ var LAZY_FILTER_FLAG = 1, LAZY_MAP_FLAG = 2, LAZY_WHILE_FLAG = 3; /** Used as references for various `Number` constants. */ var INFINITY = 1 / 0, MAX_SAFE_INTEGER = 9007199254740991, MAX_INTEGER = 1.7976931348623157e+308, NAN = 0 / 0; /** Used as references for the maximum length and index of an array. */ var MAX_ARRAY_LENGTH = 4294967295, MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; /** `Object#toString` result references. */ var argsTag = '[object Arguments]', arrayTag = '[object Array]', boolTag = '[object Boolean]', dateTag = '[object Date]', errorTag = '[object Error]', funcTag = '[object Function]', genTag = '[object GeneratorFunction]', mapTag = '[object Map]', numberTag = '[object Number]', objectTag = '[object Object]', promiseTag = '[object Promise]', regexpTag = '[object RegExp]', setTag = '[object Set]', stringTag = '[object String]', symbolTag = '[object Symbol]', weakMapTag = '[object WeakMap]', weakSetTag = '[object WeakSet]'; var arrayBufferTag = '[object ArrayBuffer]', dataViewTag = '[object DataView]', float32Tag = '[object Float32Array]', float64Tag = '[object Float64Array]', int8Tag = '[object Int8Array]', int16Tag = '[object Int16Array]', int32Tag = '[object Int32Array]', uint8Tag = '[object Uint8Array]', uint8ClampedTag = '[object Uint8ClampedArray]', uint16Tag = '[object Uint16Array]', uint32Tag = '[object Uint32Array]'; /** 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 and HTML characters. */ var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g, reUnescapedHtml = /[&<>"'`]/g, reHasEscapedHtml = RegExp(reEscapedHtml.source), reHasUnescapedHtml = RegExp(reUnescapedHtml.source); /** Used to match template delimiters. */ var reEscape = /<%-([\s\S]+?)%>/g, reEvaluate = /<%([\s\S]+?)%>/g, reInterpolate = /<%=([\s\S]+?)%>/g; /** Used to match property names within property paths. */ var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/, rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]/g; /** * Used to match `RegExp` * [syntax characters](http://ecma-international.org/ecma-262/6.0/#sec-patterns). */ var reRegExpChar = /[\\^$.*+?()[\]{}|]/g, reHasRegExpChar = RegExp(reRegExpChar.source); /** Used to match leading and trailing whitespace. */ var reTrim = /^\s+|\s+$/g, reTrimStart = /^\s+/, reTrimEnd = /\s+$/; /** Used to match non-compound words composed of alphanumeric characters. */ var reBasicWord = /[a-zA-Z0-9]+/g; /** Used to match backslashes in property paths. */ var reEscapeChar = /\\(\\)?/g; /** * Used to match * [ES template delimiters](http://ecma-international.org/ecma-262/6.0/#sec-template-literal-lexical-components). */ var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; /** Used to match `RegExp` flags from their coerced string values. */ var reFlags = /\w*$/; /** Used to detect hexadecimal string values. */ var reHasHexPrefix = /^0x/i; /** Used to detect bad signed hexadecimal string values. */ var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; /** Used to detect binary string values. */ var reIsBinary = /^0b[01]+$/i; /** Used to detect host constructors (Safari). */ var reIsHostCtor = /^\[object .+?Constructor\]$/; /** Used to detect octal string values. */ var reIsOctal = /^0o[0-7]+$/i; /** Used to detect unsigned integer values. */ var reIsUint = /^(?:0|[1-9]\d*)$/; /** Used to match latin-1 supplementary letters (excluding mathematical operators). */ var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g; /** Used to ensure capturing order of template delimiters. */ var reNoMatch = /($^)/; /** Used to match unescaped characters in compiled string literals. */ var reUnescapedString = /['\n\r\u2028\u2029\\]/g; /** Used to compose unicode character classes. */ var rsAstralRange = '\\ud800-\\udfff', rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23', rsComboSymbolsRange = '\\u20d0-\\u20f0', rsDingbatRange = '\\u2700-\\u27bf', rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff', rsMathOpRange = '\\xac\\xb1\\xd7\\xf7', rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf', rsPunctuationRange = '\\u2000-\\u206f', rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000', rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde', rsVarRange = '\\ufe0e\\ufe0f', rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange; /** Used to compose unicode capture groups. */ var rsApos = "['\u2019]", rsAstral = '[' + rsAstralRange + ']', rsBreak = '[' + rsBreakRange + ']', rsCombo = '[' + rsComboMarksRange + rsComboSymbolsRange + ']', rsDigits = '\\d+', rsDingbat = '[' + rsDingbatRange + ']', rsLower = '[' + rsLowerRange + ']', rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']', rsFitz = '\\ud83c[\\udffb-\\udfff]', rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', rsNonAstral = '[^' + rsAstralRange + ']', rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', rsUpper = '[' + rsUpperRange + ']', rsZWJ = '\\u200d'; /** Used to compose unicode regexes. */ var rsLowerMisc = '(?:' + rsLower + '|' + rsMisc + ')', rsUpperMisc = '(?:' + rsUpper + '|' + rsMisc + ')', rsOptLowerContr = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?', rsOptUpperContr = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?', reOptMod = rsModifier + '?', rsOptVar = '[' + rsVarRange + ']?', rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', rsSeq = rsOptVar + reOptMod + rsOptJoin, rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq, rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')'; /** Used to match apostrophes. */ var reApos = RegExp(rsApos, 'g'); /** * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols). */ var reComboMark = RegExp(rsCombo, 'g'); /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ var reComplexSymbol = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g'); /** Used to match complex or compound words. */ var reComplexWord = RegExp([ rsUpper + '?' + rsLower + '+' + rsOptLowerContr + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')', rsUpperMisc + '+' + rsOptUpperContr + '(?=' + [rsBreak, rsUpper + rsLowerMisc, '$'].join('|') + ')', rsUpper + '?' + rsLowerMisc + '+' + rsOptLowerContr, rsUpper + '+' + rsOptUpperContr, rsDigits, rsEmoji ].join('|'), 'g'); /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */ var reHasComplexSymbol = RegExp('[' + rsZWJ + rsAstralRange + rsComboMarksRange + rsComboSymbolsRange + rsVarRange + ']'); /** Used to detect strings that need a more robust regexp to match words. */ var reHasComplexWord = /[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/; /** Used to assign default `context` object properties. */ var contextProps = [ 'Array', 'Buffer', 'DataView', 'Date', 'Error', 'Float32Array', 'Float64Array', 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object', 'Promise', 'Reflect', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array', 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', '_', 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout' ]; /** Used to make template sourceURLs easier to identify. */ var templateCounter = -1; /** Used to identify `toStringTag` values of typed arrays. */ var typedArrayTags = {}; typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true; typedArrayTags[argsTag] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = typedArrayTags[errorTag] = typedArrayTags[funcTag] = typedArrayTags[mapTag] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false; /** Used to identify `toStringTag` values supported by `_.clone`. */ var cloneableTags = {}; cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[mapTag] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[regexpTag] = cloneableTags[setTag] = cloneableTags[stringTag] = cloneableTags[symbolTag] = cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[weakMapTag] = false; /** Used to map latin-1 supplementary letters to basic latin letters. */ var deburredLetters = { '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A', '\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a', '\xc7': 'C', '\xe7': 'c', '\xd0': 'D', '\xf0': 'd', '\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E', '\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e', '\xcC': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I', '\xeC': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i', '\xd1': 'N', '\xf1': 'n', '\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O', '\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o', '\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U', '\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u', '\xdd': 'Y', '\xfd': 'y', '\xff': 'y', '\xc6': 'Ae', '\xe6': 'ae', '\xde': 'Th', '\xfe': 'th', '\xdf': 'ss' }; /** Used to map characters to HTML entities. */ var htmlEscapes = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', '`': '`' }; /** Used to map HTML entities to characters. */ var htmlUnescapes = { '&': '&', '<': '<', '>': '>', '"': '"', ''': "'", '`': '`' }; /** Used to determine if values are of the language type `Object`. */ var objectTypes = { 'function': true, 'object': true }; /** Used to escape characters for inclusion in compiled string literals. */ var stringEscapes = { '\\': '\\', "'": "'", '\n': 'n', '\r': 'r', '\u2028': 'u2028', '\u2029': 'u2029' }; /** Built-in method references without a dependency on `root`. */ var freeParseFloat = parseFloat, freeParseInt = parseInt; /** Detect free variable `exports`. */ var freeExports = (objectTypes[typeof exports] && exports && !exports.nodeType) ? exports : undefined; /** Detect free variable `module`. */ var freeModule = (objectTypes[typeof module] && module && !module.nodeType) ? module : undefined; /** Detect the popular CommonJS extension `module.exports`. */ var moduleExports = (freeModule && freeModule.exports === freeExports) ? freeExports : undefined; /** Detect free variable `global` from Node.js. */ var freeGlobal = checkGlobal(freeExports && freeModule && typeof global == 'object' && global); /** Detect free variable `self`. */ var freeSelf = checkGlobal(objectTypes[typeof self] && self); /** Detect free variable `window`. */ var freeWindow = checkGlobal(objectTypes[typeof window] && window); /** Detect `this` as the global object. */ var thisGlobal = checkGlobal(objectTypes[typeof this] && this); /** * Used as a reference to the global object. * * The `this` value is used if it's the global object to avoid Greasemonkey's * restricted `window` object, otherwise the `window` object is used. */ var root = freeGlobal || ((freeWindow !== (thisGlobal && thisGlobal.window)) && freeWindow) || freeSelf || thisGlobal || Function('return this')(); /*--------------------------------------------------------------------------*/ /** * Adds the key-value `pair` to `map`. * * @private * @param {Object} map The map to modify. * @param {Array} pair The key-value pair to add. * @returns {Object} Returns `map`. */ function addMapEntry(map, pair) { // Don't return `Map#set` because it doesn't return the map instance in IE 11. map.set(pair[0], pair[1]); return map; } /** * Adds `value` to `set`. * * @private * @param {Object} set The set to modify. * @param {*} value The value to add. * @returns {Object} Returns `set`. */ function addSetEntry(set, value) { set.add(value); return set; } /** * A faster alternative to `Function#apply`, this function invokes `func` * with the `this` binding of `thisArg` and the arguments of `args`. * * @private * @param {Function} func The function to invoke. * @param {*} thisArg The `this` binding of `func`. * @param {Array} args The arguments to invoke `func` with. * @returns {*} Returns the result of `func`. */ function apply(func, thisArg, args) { var length = args.length; switch (length) { case 0: return func.call(thisArg); case 1: return func.call(thisArg, args[0]); case 2: return func.call(thisArg, args[0], args[1]); case 3: return func.call(thisArg, args[0], args[1], args[2]); } return func.apply(thisArg, args); } /** * A specialized version of `baseAggregator` for arrays. * * @private * @param {Array} array The array to iterate over. * @param {Function} setter The function to set `accumulator` values. * @param {Function} iteratee The iteratee to transform keys. * @param {Object} accumulator The initial aggregated object. * @returns {Function} Returns `accumulator`. */ function arrayAggregator(array, setter, iteratee, accumulator) { var index = -1, length = array.length; while (++index < length) { var value = array[index]; setter(accumulator, value, iteratee(value), array); } return accumulator; } /** * A specialized version of `_.forEach` for arrays without support for * iteratee shorthands. * * @private * @param {Array} array The array to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns `array`. */ function arrayEach(array, iteratee) { var index = -1, length = array.length; while (++index < length) { if (iteratee(array[index], index, array) === false) { break; } } return array; } /** * A specialized version of `_.forEachRight` for arrays without support for * iteratee shorthands. * * @private * @param {Array} array The array to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns `array`. */ function arrayEachRight(array, iteratee) { var length = array.length; while (length--) { if (iteratee(array[length], length, array) === false) { break; } } return array; } /** * A specialized version of `_.every` for arrays without support for * iteratee shorthands. * * @private * @param {Array} array The array to iterate over. * @param {Function} predicate The function invoked per iteration. * @returns {boolean} Returns `true` if all elements pass the predicate check, * else `false`. */ function arrayEvery(array, predicate) { var index = -1, length = array.length; while (++index < length) { if (!predicate(array[index], index, array)) { return false; } } return true; } /** * A specialized version of `_.filter` for arrays without support for * iteratee shorthands. * * @private * @param {Array} array The array to iterate over. * @param {Function} predicate The function invoked per iteration. * @returns {Array} Returns the new filtered array. */ function arrayFilter(array, predicate) { var index = -1, length = array.length, resIndex = 0, result = []; while (++index < length) { var value = array[index]; if (predicate(value, index, array)) { result[resIndex++] = value; } } return result; } /** * A specialized version of `_.includes` for arrays without support for * specifying an index to search from. * * @private * @param {Array} array The array to search. * @param {*} target The value to search for. * @returns {boolean} Returns `true` if `target` is found, else `false`. */ function arrayIncludes(array, value) { return !!array.length && baseIndexOf(array, value, 0) > -1; } /** * This function is like `arrayIncludes` except that it accepts a comparator. * * @private * @param {Array} array The array to search. * @param {*} target The value to search for. * @param {Function} comparator The comparator invoked per element. * @returns {boolean} Returns `true` if `target` is found, else `false`. */ function arrayIncludesWith(array, value, comparator) { var index = -1, length = array.length; while (++index < length) { if (comparator(value, array[index])) { return true; } } return false; } /** * A specialized version of `_.map` for arrays without support for iteratee * shorthands. * * @private * @param {Array} array The array to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns the new mapped array. */ function arrayMap(array, iteratee) { var index = -1, length = array.length, result = Array(length); while (++index < length) { result[index] = iteratee(array[index], index, array); } return result; } /** * Appends the elements of `values` to `array`. * * @private * @param {Array} array The array to modify. * @param {Array} values The values to append. * @returns {Array} Returns `array`. */ function arrayPush(array, values) { var index = -1, length = values.length, offset = array.length; while (++index < length) { array[offset + index] = values[index]; } return array; } /** * A specialized version of `_.reduce` for arrays without support for * iteratee shorthands. * * @private * @param {Array} array The array to iterate over. * @param {Function} iteratee The function invoked per iteration. * @param {*} [accumulator] The initial value. * @param {boolean} [initAccum] Specify using the first element of `array` as * the initial value. * @returns {*} Returns the accumulated value. */ function arrayReduce(array, iteratee, accumulator, initAccum) { var index = -1, length = array.length; if (initAccum && length) { accumulator = array[++index]; } while (++index < length) { accumulator = iteratee(accumulator, array[index], index, array); } return accumulator; } /** * A specialized version of `_.reduceRight` for arrays without support for * iteratee shorthands. * * @private * @param {Array} array The array to iterate over. * @param {Function} iteratee The function invoked per iteration. * @param {*} [accumulator] The initial value. * @param {boolean} [initAccum] Specify using the last element of `array` as * the initial value. * @returns {*} Returns the accumulated value. */ function arrayReduceRight(array, iteratee, accumulator, initAccum) { var length = array.length; if (initAccum && length) { accumulator = array[--length]; } while (length--) { accumulator = iteratee(accumulator, array[length], length, array); } return accumulator; } /** * A specialized version of `_.some` for arrays without support for iteratee * shorthands. * * @private * @param {Array} array The array to iterate over. * @param {Function} predicate The function invoked per iteration. * @returns {boolean} Returns `true` if any element passes the predicate check, * else `false`. */ function arraySome(array, predicate) { var index = -1, length = array.length; while (++index < length) { if (predicate(array[index], index, array)) { return true; } } return false; } /** * The base implementation of methods like `_.find` and `_.findKey`, without * support for iteratee shorthands, which iterates over `collection` using * `eachFunc`. * * @private * @param {Array|Object} collection The collection to search. * @param {Function} predicate The function invoked per iteration. * @param {Function} eachFunc The function to iterate over `collection`. * @param {boolean} [retKey] Specify returning the key of the found element * instead of the element itself. * @returns {*} Returns the found element or its key, else `undefined`. */ function baseFind(collection, predicate, eachFunc, retKey) { var result; eachFunc(collection, function(value, key, collection) { if (predicate(value, key, collection)) { result = retKey ? key : value; return false; } }); return result; } /** * The base implementation of `_.findIndex` and `_.findLastIndex` without * support for iteratee shorthands. * * @private * @param {Array} array The array to search. * @param {Function} predicate The function invoked per iteration. * @param {boolean} [fromRight] Specify iterating from right to left. * @returns {number} Returns the index of the matched value, else `-1`. */ function baseFindIndex(array, predicate, fromRight) { var length = array.length, index = fromRight ? length : -1; while ((fromRight ? index-- : ++index < length)) { if (predicate(array[index], index, array)) { return index; } } return -1; } /** * The base implementation of `_.indexOf` without `fromIndex` bounds checks. * * @private * @param {Array} array The array to search. * @param {*} value The value to search for. * @param {number} fromIndex The index to search from. * @returns {number} Returns the index of the matched value, else `-1`. */ function baseIndexOf(array, value, fromIndex) { if (value !== value) { return indexOfNaN(array, fromIndex); } var index = fromIndex - 1, length = array.length; while (++index < length) { if (array[index] === value) { return index; } } return -1; } /** * This function is like `baseIndexOf` except that it accepts a comparator. * * @private * @param {Array} array The array to search. * @param {*} value The value to search for. * @param {number} fromIndex The index to search from. * @param {Function} comparator The comparator invoked per element. * @returns {number} Returns the index of the matched value, else `-1`. */ function baseIndexOfWith(array, value, fromIndex, comparator) { var index = fromIndex - 1, length = array.length; while (++index < length) { if (comparator(array[index], value)) { return index; } } return -1; } /** * The base implementation of `_.mean` and `_.meanBy` without support for * iteratee shorthands. * * @private * @param {Array} array The array to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {number} Returns the mean. */ function baseMean(array, iteratee) { var length = array ? array.length : 0; return length ? (baseSum(array, iteratee) / length) : NAN; } /** * The base implementation of `_.reduce` and `_.reduceRight`, without support * for iteratee shorthands, which iterates over `collection` using `eachFunc`. * * @private * @param {Array|Object} collection The collection to iterate over. * @param {Function} iteratee The function invoked per iteration. * @param {*} accumulator The initial value. * @param {boolean} initAccum Specify using the first or last element of * `collection` as the initial value. * @param {Function} eachFunc The function to iterate over `collection`. * @returns {*} Returns the accumulated value. */ function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) { eachFunc(collection, function(value, index, collection) { accumulator = initAccum ? (initAccum = false, value) : iteratee(accumulator, value, index, collection); }); return accumulator; } /** * The base implementation of `_.sortBy` which uses `comparer` to define the * sort order of `array` and replaces criteria objects with their corresponding * values. * * @private * @param {Array} array The array to sort. * @param {Function} comparer The function to define sort order. * @returns {Array} Returns `array`. */ function baseSortBy(array, comparer) { var length = array.length; array.sort(comparer); while (length--) { array[length] = array[length].value; } return array; } /** * The base implementation of `_.sum` and `_.sumBy` without support for * iteratee shorthands. * * @private * @param {Array} array The array to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {number} Returns the sum. */ function baseSum(array, iteratee) { var result, index = -1, length = array.length; while (++index < length) { var current = iteratee(array[index]); if (current !== undefined) { result = result === undefined ? current : (result + current); } } return result; } /** * The base implementation of `_.times` without support for iteratee shorthands * or max array length checks. * * @private * @param {number} n The number of times to invoke `iteratee`. * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns the array of results. */ function baseTimes(n, iteratee) { var index = -1, result = Array(n); while (++index < n) { result[index] = iteratee(index); } return result; } /** * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array * of key-value pairs for `object` corresponding to the property names of `props`. * * @private * @param {Object} object The object to query. * @param {Array} props The property names to get values for. * @returns {Object} Returns the key-value pairs. */ function baseToPairs(object, props) { return arrayMap(props, function(key) { return [key, object[key]]; }); } /** * The base implementation of `_.unary` without support for storing wrapper metadata. * * @private * @param {Function} func The function to cap arguments for. * @returns {Function} Returns the new capped function. */ function baseUnary(func) { return function(value) { return func(value); }; } /** * The base implementation of `_.values` and `_.valuesIn` which creates an * array of `object` property values corresponding to the property names * of `props`. * * @private * @param {Object} object The object to query. * @param {Array} props The property names to get values for. * @returns {Object} Returns the array of property values. */ function baseValues(object, props) { return arrayMap(props, function(key) { return object[key]; }); } /** * Checks if a cache value for `key` exists. * * @private * @param {Object} cache The cache to query. * @param {string} key The key of the entry to check. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. */ function cacheHas(cache, key) { return cache.has(key); } /** * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol * that is not found in the character symbols. * * @private * @param {Array} strSymbols The string symbols to inspect. * @param {Array} chrSymbols The character symbols to find. * @returns {number} Returns the index of the first unmatched string symbol. */ function charsStartIndex(strSymbols, chrSymbols) { var index = -1, length = strSymbols.length; while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} return index; } /** * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol * that is not found in the character symbols. * * @private * @param {Array} strSymbols The string symbols to inspect. * @param {Array} chrSymbols The character symbols to find. * @returns {number} Returns the index of the last unmatched string symbol. */ function charsEndIndex(strSymbols, chrSymbols) { var index = strSymbols.length; while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} return index; } /** * Checks if `value` is a global object. * * @private * @param {*} value The value to check. * @returns {null|Object} Returns `value` if it's a global object, else `null`. */ function checkGlobal(value) { return (value && value.Object === Object) ? value : null; } /** * Gets the number of `placeholder` occurrences in `array`. * * @private * @param {Array} array The array to inspect. * @param {*} placeholder The placeholder to search for. * @returns {number} Returns the placeholder count. */ function countHolders(array, placeholder) { var length = array.length, result = 0; while (length--) { if (array[length] === placeholder) { result++; } } return result; } /** * Used by `_.deburr` to convert latin-1 supplementary letters to basic latin letters. * * @private * @param {string} letter The matched letter to deburr. * @returns {string} Returns the deburred letter. */ function deburrLetter(letter) { return deburredLetters[letter]; } /** * Used by `_.escape` to convert characters to HTML entities. * * @private * @param {string} chr The matched character to escape. * @returns {string} Returns the escaped character. */ function escapeHtmlChar(chr) { return htmlEscapes[chr]; } /** * Used by `_.template` to escape characters for inclusion in compiled string literals. * * @private * @param {string} chr The matched character to escape. * @returns {string} Returns the escaped character. */ function escapeStringChar(chr) { return '\\' + stringEscapes[chr]; } /** * Gets the index at which the first occurrence of `NaN` is found in `array`. * * @private * @param {Array} array The array to search. * @param {number} fromIndex The index to search from. * @param {boolean} [fromRight] Specify iterating from right to left. * @returns {number} Returns the index of the matched `NaN`, else `-1`. */ function indexOfNaN(array, fromIndex, fromRight) { var length = array.length, index = fromIndex + (fromRight ? 0 : -1); while ((fromRight ? index-- : ++index < length)) { var other = array[index]; if (other !== other) { return index; } } return -1; } /** * Checks if `value` is a host object in IE < 9. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a host object, else `false`. */ function isHostObject(value) { // Many host objects are `Object` objects that can coerce to strings // despite having improperly defined `toString` methods. var result = false; if (value != null && typeof value.toString != 'function') { try { result = !!(value + ''); } catch (e) {} } return result; } /** * Converts `iterator` to an array. * * @private * @param {Object} iterator The iterator to convert. * @returns {Array} Returns the converted array. */ function iteratorToArray(iterator) { var data, result = []; while (!(data = iterator.next()).done) { result.push(data.value); } return result; } /** * Converts `map` to its key-value pairs. * * @private * @param {Object} map The map to convert. * @returns {Array} Returns the key-value pairs. */ function mapToArray(map) { var index = -1, result = Array(map.size); map.forEach(function(value, key) { result[++index] = [key, value]; }); return result; } /** * Replaces all `placeholder` elements in `array` with an internal placeholder * and returns an array of their indexes. * * @private * @param {Array} array The array to modify. * @param {*} placeholder The placeholder to replace. * @returns {Array} Returns the new array of placeholder indexes. */ function replaceHolders(array, placeholder) { var index = -1, length = array.length, resIndex = 0, result = []; while (++index < length) { var value = array[index]; if (value === placeholder || value === PLACEHOLDER) { array[index] = PLACEHOLDER; result[resIndex++] = index; } } return result; } /** * Converts `set` to an array of its values. * * @private * @param {Object} set The set to convert. * @returns {Array} Returns the values. */ function setToArray(set) { var index = -1, result = Array(set.size); set.forEach(function(value) { result[++index] = value; }); return result; } /** * Converts `set` to its value-value pairs. * * @private * @param {Object} set The set to convert. * @returns {Array} Returns the value-value pairs. */ function setToPairs(set) { var index = -1, result = Array(set.size); set.forEach(function(value) { result[++index] = [value, value]; }); return result; } /** * Gets the number of symbols in `string`. * * @private * @param {string} string The string to inspect. * @returns {number} Returns the string size. */ function stringSize(string) { if (!(string && reHasComplexSymbol.test(string))) { return string.length; } var result = reComplexSymbol.lastIndex = 0; while (reComplexSymbol.test(string)) { result++; } return result; } /** * Converts `string` to an array. * * @private * @param {string} string The string to convert. * @returns {Array} Returns the converted array. */ function stringToArray(string) { return string.match(reComplexSymbol); } /** * Used by `_.unescape` to convert HTML entities to characters. * * @private * @param {string} chr The matched character to unescape. * @returns {string} Returns the unescaped character. */ function unescapeHtmlChar(chr) { return htmlUnescapes[chr]; } /*--------------------------------------------------------------------------*/ /** * Create a new pristine `lodash` function using the `context` object. * * @static * @memberOf _ * @since 1.1.0 * @category Util * @param {Object} [context=root] The context object. * @returns {Function} Returns a new `lodash` function. * @example * * _.mixin({ 'foo': _.constant('foo') }); * * var lodash = _.runInContext(); * lodash.mixin({ 'bar': lodash.constant('bar') }); * * _.isFunction(_.foo); * // => true * _.isFunction(_.bar); * // => false * * lodash.isFunction(lodash.foo); * // => false * lodash.isFunction(lodash.bar); * // => true * * // Use `context` to mock `Date#getTime` use in `_.now`. * var mock = _.runInContext({ * 'Date': function() { * return { 'getTime': getTimeMock }; * } * }); * * // Create a suped-up `defer` in Node.js. * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer; */ function runInContext(context) { context = context ? _.defaults({}, context, _.pick(root, contextProps)) : root; /** Built-in constructor references. */ var Date = context.Date, Error = context.Error, Math = context.Math, RegExp = context.RegExp, TypeError = context.TypeError; /** Used for built-in method references. */ var arrayProto = context.Array.prototype, objectProto = context.Object.prototype, stringProto = context.String.prototype; /** Used to resolve the decompiled source of functions. */ var funcToString = context.Function.prototype.toString; /** Used to check objects for own properties. */ var hasOwnProperty = objectProto.hasOwnProperty; /** Used to generate unique IDs. */ var idCounter = 0; /** Used to infer the `Object` constructor. */ var objectCtorString = funcToString.call(Object); /** * Used to resolve the * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) * of values. */ var objectToString = objectProto.toString; /** Used to restore the original `_` reference in `_.noConflict`. */ var oldDash = root._; /** Used to detect if a method is native. */ var reIsNative = RegExp('^' + funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&') .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' ); /** Built-in value references. */ var Buffer = moduleExports ? context.Buffer : undefined, Reflect = context.Reflect, Symbol = context.Symbol, Uint8Array = context.Uint8Array, clearTimeout = context.clearTimeout, enumerate = Reflect ? Reflect.enumerate : undefined, getOwnPropertySymbols = Object.getOwnPropertySymbols, iteratorSymbol = typeof (iteratorSymbol = Symbol && Symbol.iterator) == 'symbol' ? iteratorSymbol : undefined, objectCreate = Object.create, propertyIsEnumerable = objectProto.propertyIsEnumerable, setTimeout = context.setTimeout, splice = arrayProto.splice; /* Built-in method references for those with the same name as other `lodash` methods. */ var nativeCeil = Math.ceil, nativeFloor = Math.floor, nativeGetPrototype = Object.getPrototypeOf, nativeIsFinite = context.isFinite, nativeJoin = arrayProto.join, nativeKeys = Object.keys, nativeMax = Math.max, nativeMin = Math.min, nativeParseInt = context.parseInt, nativeRandom = Math.random, nativeReplace = stringProto.replace, nativeReverse = arrayProto.reverse, nativeSplit = stringProto.split; /* Built-in method references that are verified to be native. */ var DataView = getNative(context, 'DataView'), Map = getNative(context, 'Map'), Promise = getNative(context, 'Promise'), Set = getNative(context, 'Set'), WeakMap = getNative(context, 'WeakMap'), nativeCreate = getNative(Object, 'create'); /** Used to store function metadata. */ var metaMap = WeakMap && new WeakMap; /** Detect if properties shadowing those on `Object.prototype` are non-enumerable. */ var nonEnumShadows = !propertyIsEnumerable.call({ 'valueOf': 1 }, 'valueOf'); /** Used to lookup unminified function names. */ var realNames = {}; /** Used to detect maps, sets, and weakmaps. */ var dataViewCtorString = toSource(DataView), mapCtorString = toSource(Map), promiseCtorString = toSource(Promise), setCtorString = toSource(Set), weakMapCtorString = toSource(WeakMap); /** Used to convert symbols to primitives and strings. */ var symbolProto = Symbol ? Symbol.prototype : undefined, symbolValueOf = symbolProto ? symbolProto.valueOf : undefined, symbolToString = symbolProto ? symbolProto.toString : undefined; /*------------------------------------------------------------------------*/ /** * Creates a `lodash` object which wraps `value` to enable implicit method * chain sequences. Methods that operate on and return arrays, collections, * and functions can be chained together. Methods that retrieve a single value * or may return a primitive value will automatically end the chain sequence * and return the unwrapped value. Otherwise, the value must be unwrapped * with `_#value`. * * Explicit chain sequences, which must be unwrapped with `_#value`, may be * enabled using `_.chain`. * * The execution of chained methods is lazy, that is, it's deferred until * `_#value` is implicitly or explicitly called. * * Lazy evaluation allows several methods to support shortcut fusion. * Shortcut fusion is an optimization to merge iteratee calls; this avoids * the creation of intermediate arrays and can greatly reduce the number of * iteratee executions. Sections of a chain sequence qualify for shortcut * fusion if the section is applied to an array of at least `200` elements * and any iteratees accept only one argument. The heuristic for whether a * section qualifies for shortcut fusion is subject to change. * * Chaining is supported in custom builds as long as the `_#value` method is * directly or indirectly included in the build. * * In addition to lodash methods, wrappers have `Array` and `String` methods. * * The wrapper `Array` methods are: * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift` * * The wrapper `String` methods are: * `replace` and `split` * * The wrapper methods that support shortcut fusion are: * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`, * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`, * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray` * * The chainable wrapper methods are: * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`, * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`, * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`, * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`, * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`, * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`, * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`, * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`, * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`, * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`, * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`, * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`, * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`, * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`, * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`, * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`, * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`, * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`, * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`, * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`, * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`, * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`, * `zipObject`, `zipObjectDeep`, and `zipWith` * * The wrapper methods that are **not** chainable by default are: * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`, * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `deburr`, `divide`, `each`, * `eachRight`, `endsWith`, `eq`, `escape`, `escapeRegExp`, `every`, `find`, * `findIndex`, `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `first`, * `floor`, `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, * `forOwnRight`, `get`, `gt`, `gte`, `has`, `hasIn`, `head`, `identity`, * `includes`, `indexOf`, `inRange`, `invoke`, `isArguments`, `isArray`, * `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`, `isBoolean`, * `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`, `isEqualWith`, * `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`, `isMap`, * `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`, `isNumber`, * `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`, `isSafeInteger`, * `isSet`, `isString`, `isUndefined`, `isTypedArray`, `isWeakMap`, `isWeakSet`, * `join`, `kebabCase`, `last`, `lastIndexOf`, `lowerCase`, `lowerFirst`, * `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`, `min`, `minBy`, `multiply`, * `noConflict`, `noop`, `now`, `nth`, `pad`, `padEnd`, `padStart`, `parseInt`, * `pop`, `random`, `reduce`, `reduceRight`, `repeat`, `result`, `round`, * `runInContext`, `sample`, `shift`, `size`, `snakeCase`, `some`, `sortedIndex`, * `sortedIndexBy`, `sortedLastIndex`, `sortedLastIndexBy`, `startCase`, * `startsWith`, `subtract`, `sum`, `sumBy`, `template`, `times`, `toFinite`, * `toInteger`, `toJSON`, `toLength`, `toLower`, `toNumber`, `toSafeInteger`, * `toString`, `toUpper`, `trim`, `trimEnd`, `trimStart`, `truncate`, `unescape`, * `uniqueId`, `upperCase`, `upperFirst`, `value`, and `words` * * @name _ * @constructor * @category Seq * @param {*} value The value to wrap in a `lodash` instance. * @returns {Object} Returns the new `lodash` wrapper instance. * @example * * function square(n) { * return n * n; * } * * var wrapped = _([1, 2, 3]); * * // Returns an unwrapped value. * wrapped.reduce(_.add); * // => 6 * * // Returns a wrapped value. * var squares = wrapped.map(square); * * _.isArray(squares); * // => false * * _.isArray(squares.value()); * // => true */ function lodash(value) { if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { if (value instanceof LodashWrapper) { return value; } if (hasOwnProperty.call(value, '__wrapped__')) { return wrapperClone(value); } } return new LodashWrapper(value); } /** * The function whose prototype chain sequence wrappers inherit from. * * @private */ function baseLodash() { // No operation performed. } /** * The base constructor for creating `lodash` wrapper objects. * * @private * @param {*} value The value to wrap. * @param {boolean} [chainAll] Enable explicit method chain sequences. */ function LodashWrapper(value, chainAll) { this.__wrapped__ = value; this.__actions__ = []; this.__chain__ = !!chainAll; this.__index__ = 0; this.__values__ = undefined; } /** * By default, the template delimiters used by lodash are like 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': reEscape, /** * Used to detect code to be evaluated. * * @memberOf _.templateSettings * @type {RegExp} */ 'evaluate': reEvaluate, /** * 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 } }; // Ensure wrappers are instances of `baseLodash`. lodash.prototype = baseLodash.prototype; lodash.prototype.constructor = lodash; LodashWrapper.prototype = baseCreate(baseLodash.prototype); LodashWrapper.prototype.constructor = LodashWrapper; /*------------------------------------------------------------------------*/ /** * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation. * * @private * @constructor * @param {*} value The value to wrap. */ function LazyWrapper(value) { this.__wrapped__ = value; this.__actions__ = []; this.__dir__ = 1; this.__filtered__ = false; this.__iteratees__ = []; this.__takeCount__ = MAX_ARRAY_LENGTH; this.__views__ = []; } /** * Creates a clone of the lazy wrapper object. * * @private * @name clone * @memberOf LazyWrapper * @returns {Object} Returns the cloned `LazyWrapper` object. */ function lazyClone() { var result = new LazyWrapper(this.__wrapped__); result.__actions__ = copyArray(this.__actions__); result.__dir__ = this.__dir__; result.__filtered__ = this.__filtered__; result.__iteratees__ = copyArray(this.__iteratees__); result.__takeCount__ = this.__takeCount__; result.__views__ = copyArray(this.__views__); return result; } /** * Reverses the direction of lazy iteration. * * @private * @name reverse * @memberOf LazyWrapper * @returns {Object} Returns the new reversed `LazyWrapper` object. */ function lazyReverse() { if (this.__filtered__) { var result = new LazyWrapper(this); result.__dir__ = -1; result.__filtered__ = true; } else { result = this.clone(); result.__dir__ *= -1; } return result; } /** * Extracts the unwrapped value from its lazy wrapper. * * @private * @name value * @memberOf LazyWrapper * @returns {*} Returns the unwrapped value. */ function lazyValue() { var array = this.__wrapped__.value(), dir = this.__dir__, isArr = isArray(array), isRight = dir < 0, arrLength = isArr ? array.length : 0, view = getView(0, arrLength, this.__views__), start = view.start, end = view.end, length = end - start, index = isRight ? end : (start - 1), iteratees = this.__iteratees__, iterLength = iteratees.length, resIndex = 0, takeCount = nativeMin(length, this.__takeCount__); if (!isArr || arrLength < LARGE_ARRAY_SIZE || (arrLength == length && takeCount == length)) { return baseWrapperValue(array, this.__actions__); } var result = []; outer: while (length-- && resIndex < takeCount) { index += dir; var iterIndex = -1, value = array[index]; while (++iterIndex < iterLength) { var data = iteratees[iterIndex], iteratee = data.iteratee, type = data.type, computed = iteratee(value); if (type == LAZY_MAP_FLAG) { value = computed; } else if (!computed) { if (type == LAZY_FILTER_FLAG) { continue outer; } else { break outer; } } } result[resIndex++] = value; } return result; } // Ensure `LazyWrapper` is an instance of `baseLodash`. LazyWrapper.prototype = baseCreate(baseLodash.prototype); LazyWrapper.prototype.constructor = LazyWrapper; /*------------------------------------------------------------------------*/ /** * Creates a hash object. * * @private * @constructor * @param {Array} [entries] The key-value pairs to cache. */ function Hash(entries) { var index = -1, length = entries ? entries.length : 0; this.clear(); while (++index < length) { var entry = entries[index]; this.set(entry[0], entry[1]); } } /** * Removes all key-value entries from the hash. * * @private * @name clear * @memberOf Hash */ function hashClear() { this.__data__ = nativeCreate ? nativeCreate(null) : {}; } /** * Removes `key` and its value from the hash. * * @private * @name delete * @memberOf Hash * @param {Object} hash The hash to modify. * @param {string} key The key of the value to remove. * @returns {boolean} Returns `true` if the entry was removed, else `false`. */ function hashDelete(key) { return this.has(key) && delete this.__data__[key]; } /** * Gets the hash value for `key`. * * @private * @name get * @memberOf Hash * @param {string} key The key of the value to get. * @returns {*} Returns the entry value. */ function hashGet(key) { var data = this.__data__; if (nativeCreate) { var result = data[key]; return result === HASH_UNDEFINED ? undefined : result; } return hasOwnProperty.call(data, key) ? data[key] : undefined; } /** * Checks if a hash value for `key` exists. * * @private * @name has * @memberOf Hash * @param {string} key The key of the entry to check. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. */ function hashHas(key) { var data = this.__data__; return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key); } /** * Sets the hash `key` to `value`. * * @private * @name set * @memberOf Hash * @param {string} key The key of the value to set. * @param {*} value The value to set. * @returns {Object} Returns the hash instance. */ function hashSet(key, value) { var data = this.__data__; data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; return this; } // Add methods to `Hash`. Hash.prototype.clear = hashClear; Hash.prototype['delete'] = hashDelete; Hash.prototype.get = hashGet; Hash.prototype.has = hashHas; Hash.prototype.set = hashSet; /*------------------------------------------------------------------------*/ /** * Creates an list cache object. * * @private * @constructor * @param {Array} [entries] The key-value pairs to cache. */ function ListCache(entries) { var index = -1, length = entries ? entries.length : 0; this.clear(); while (++index < length) { var entry = entries[index]; this.set(entry[0], entry[1]); } } /** * Removes all key-value entries from the list cache. * * @private * @name clear * @memberOf ListCache */ function listCacheClear() { this.__data__ = []; } /** * Removes `key` and its value from the list cache. * * @private * @name delete * @memberOf ListCache * @param {string} key The key of the value to remove. * @returns {boolean} Returns `true` if the entry was removed, else `false`. */ function listCacheDelete(key) { var data = this.__data__, index = assocIndexOf(data, key); if (index < 0) { return false; } var lastIndex = data.length - 1; if (index == lastIndex) { data.pop(); } else { splice.call(data, index, 1); } return true; } /** * Gets the list cache value for `key`. * * @private * @name get * @memberOf ListCache * @param {string} key The key of the value to get. * @returns {*} Returns the entry value. */ function listCacheGet(key) { var data = this.__data__, index = assocIndexOf(data, key); return index < 0 ? undefined : data[index][1]; } /** * Checks if a list cache value for `key` exists. * * @private * @name has * @memberOf ListCache * @param {string} key The key of the entry to check. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. */ function listCacheHas(key) { return assocIndexOf(this.__data__, key) > -1; } /** * Sets the list cache `key` to `value`. * * @private * @name set * @memberOf ListCache * @param {string} key The key of the value to set. * @param {*} value The value to set. * @returns {Object} Returns the list cache instance. */ function listCacheSet(key, value) { var data = this.__data__, index = assocIndexOf(data, key); if (index < 0) { data.push([key, value]); } else { data[index][1] = value; } return this; } // Add methods to `ListCache`. ListCache.prototype.clear = listCacheClear; ListCache.prototype['delete'] = listCacheDelete; ListCache.prototype.get = listCacheGet; ListCache.prototype.has = listCacheHas; ListCache.prototype.set = listCacheSet; /*------------------------------------------------------------------------*/ /** * Creates a map cache object to store key-value pairs. * * @private * @constructor * @param {Array} [entries] The key-value pairs to cache. */ function MapCache(entries) { var index = -1, length = entries ? entries.length : 0; this.clear(); while (++index < length) { var entry = entries[index]; this.set(entry[0], entry[1]); } } /** * Removes all key-value entries from the map. * * @private * @name clear * @memberOf MapCache */ function mapCacheClear() { this.__data__ = { 'hash': new Hash, 'map': new (Map || ListCache), 'string': new Hash }; } /** * Removes `key` and its value from the map. * * @private * @name delete * @memberOf MapCache * @param {string} key The key of the value to remove. * @returns {boolean} Returns `true` if the entry was removed, else `false`. */ function mapCacheDelete(key) { return getMapData(this, key)['delete'](key); } /** * Gets the map value for `key`. * * @private * @name get * @memberOf MapCache * @param {string} key The key of the value to get. * @returns {*} Returns the entry value. */ function mapCacheGet(key) { return getMapData(this, key).get(key); } /** * Checks if a map value for `key` exists. * * @private * @name has * @memberOf MapCache * @param {string} key The key of the entry to check. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. */ function mapCacheHas(key) { return getMapData(this, key).has(key); } /** * Sets the map `key` to `value`. * * @private * @name set * @memberOf MapCache * @param {string} key The key of the value to set. * @param {*} value The value to set. * @returns {Object} Returns the map cache instance. */ function mapCacheSet(key, value) { getMapData(this, key).set(key, value); return this; } // Add methods to `MapCache`. MapCache.prototype.clear = mapCacheClear; MapCache.prototype['delete'] = mapCacheDelete; MapCache.prototype.get = mapCacheGet; MapCache.prototype.has = mapCacheHas; MapCache.prototype.set = mapCacheSet; /*------------------------------------------------------------------------*/ /** * * Creates an array cache object to store unique values. * * @private * @constructor * @param {Array} [values] The values to cache. */ function SetCache(values) { var index = -1, length = values ? values.length : 0; this.__data__ = new MapCache; while (++index < length) { this.add(values[index]); } } /** * Adds `value` to the array cache. * * @private * @name add * @memberOf SetCache * @alias push * @param {*} value The value to cache. * @returns {Object} Returns the cache instance. */ function setCacheAdd(value) { this.__data__.set(value, HASH_UNDEFINED); return this; } /** * Checks if `value` is in the array cache. * * @private * @name has * @memberOf SetCache * @param {*} value The value to search for. * @returns {number} Returns `true` if `value` is found, else `false`. */ function setCacheHas(value) { return this.__data__.has(value); } // Add methods to `SetCache`. SetCache.prototype.add = SetCache.prototype.push = setCacheAdd; SetCache.prototype.has = setCacheHas; /*------------------------------------------------------------------------*/ /** * Creates a stack cache object to store key-value pairs. * * @private * @constructor * @param {Array} [entries] The key-value pairs to cache. */ function Stack(entries) { this.__data__ = new ListCache(entries); } /** * Removes all key-value entries from the stack. * * @private * @name clear * @memberOf Stack */ function stackClear() { this.__data__ = new ListCache; } /** * Removes `key` and its value from the stack. * * @private * @name delete * @memberOf Stack * @param {string} key The key of the value to remove. * @returns {boolean} Returns `true` if the entry was removed, else `false`. */ function stackDelete(key) { return this.__data__['delete'](key); } /** * Gets the stack value for `key`. * * @private * @name get * @memberOf Stack * @param {string} key The key of the value to get. * @returns {*} Returns the entry value. */ function stackGet(key) { return this.__data__.get(key); } /** * Checks if a stack value for `key` exists. * * @private * @name has * @memberOf Stack * @param {string} key The key of the entry to check. * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. */ function stackHas(key) { return this.__data__.has(key); } /** * Sets the stack `key` to `value`. * * @private * @name set * @memberOf Stack * @param {string} key The key of the value to set. * @param {*} value The value to set. * @returns {Object} Returns the stack cache instance. */ function stackSet(key, value) { var cache = this.__data__; if (cache instanceof ListCache && cache.__data__.length == LARGE_ARRAY_SIZE) { cache = this.__data__ = new MapCache(cache.__data__); } cache.set(key, value); return this; } // Add methods to `Stack`. Stack.prototype.clear = stackClear; Stack.prototype['delete'] = stackDelete; Stack.prototype.get = stackGet; Stack.prototype.has = stackHas; Stack.prototype.set = stackSet; /*------------------------------------------------------------------------*/ /** * Used by `_.defaults` to customize its `_.assignIn` use. * * @private * @param {*} objValue The destination value. * @param {*} srcValue The source value. * @param {string} key The key of the property to assign. * @param {Object} object The parent object of `objValue`. * @returns {*} Returns the value to assign. */ function assignInDefaults(objValue, srcValue, key, object) { if (objValue === undefined || (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) { return srcValue; } return objValue; } /** * This function is like `assignValue` except that it doesn't assign * `undefined` values. * * @private * @param {Object} object The object to modify. * @param {string} key The key of the property to assign. * @param {*} value The value to assign. */ function assignMergeValue(object, key, value) { if ((value !== undefined && !eq(object[key], value)) || (typeof key == 'number' && value === undefined && !(key in object))) { object[key] = value; } } /** * Assigns `value` to `key` of `object` if the existing value is not equivalent * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. * * @private * @param {Object} object The object to modify. * @param {string} key The key of the property to assign. * @param {*} value The value to assign. */ function assignValue(object, key, value) { var objValue = object[key]; if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || (value === undefined && !(key in object))) { object[key] = value; } } /** * Gets the index at which the `key` is found in `array` of key-value pairs. * * @private * @param {Array} array The array to search. * @param {*} key The key to search for. * @returns {number} Returns the index of the matched value, else `-1`. */ function assocIndexOf(array, key) { var length = array.length; while (length--) { if (eq(array[length][0], key)) { return length; } } return -1; } /** * Aggregates elements of `collection` on `accumulator` with keys transformed * by `iteratee` and values set by `setter`. * * @private * @param {Array|Object} collection The collection to iterate over. * @param {Function} setter The function to set `accumulator` values. * @param {Function} iteratee The iteratee to transform keys. * @param {Object} accumulator The initial aggregated object. * @returns {Function} Returns `accumulator`. */ function baseAggregator(collection, setter, iteratee, accumulator) { baseEach(collection, function(value, key, collection) { setter(accumulator, value, iteratee(value), collection); }); return accumulator; } /** * The base implementation of `_.assign` without support for multiple sources * or `customizer` functions. * * @private * @param {Object} object The destination object. * @param {Object} source The source object. * @returns {Object} Returns `object`. */ function baseAssign(object, source) { return object && copyObject(source, keys(source), object); } /** * The base implementation of `_.at` without support for individual paths. * * @private * @param {Object} object The object to iterate over. * @param {string[]} paths The property paths of elements to pick. * @returns {Array} Returns the picked elements. */ function baseAt(object, paths) { var index = -1, isNil = object == null, length = paths.length, result = Array(length); while (++index < length) { result[index] = isNil ? undefined : get(object, paths[index]); } return result; } /** * The base implementation of `_.clamp` which doesn't coerce arguments to numbers. * * @private * @param {number} number The number to clamp. * @param {number} [lower] The lower bound. * @param {number} upper The upper bound. * @returns {number} Returns the clamped number. */ function baseClamp(number, lower, upper) { if (number === number) { if (upper !== undefined) { number = number <= upper ? number : upper; } if (lower !== undefined) { number = number >= lower ? number : lower; } } return number; } /** * The base implementation of `_.clone` and `_.cloneDeep` which tracks * traversed objects. * * @private * @param {*} value The value to clone. * @param {boolean} [isDeep] Specify a deep clone. * @param {boolean} [isFull] Specify a clone including symbols. * @param {Function} [customizer] The function to customize cloning. * @param {string} [key] The key of `value`. * @param {Object} [object] The parent object of `value`. * @param {Object} [stack] Tracks traversed objects and their clone counterparts. * @returns {*} Returns the cloned value. */ function baseClone(value, isDeep, isFull, customizer, key, object, stack) { var result; if (customizer) { result = object ? customizer(value, key, object, stack) : customizer(value); } if (result !== undefined) { return result; } if (!isObject(value)) { return value; } var isArr = isArray(value); if (isArr) { result = initCloneArray(value); if (!isDeep) { return copyArray(value, result); } } else { var tag = getTag(value), isFunc = tag == funcTag || tag == genTag; if (isBuffer(value)) { return cloneBuffer(value, isDeep); } if (tag == objectTag || tag == argsTag || (isFunc && !object)) { if (isHostObject(value)) { return object ? value : {}; } result = initCloneObject(isFunc ? {} : value); if (!isDeep) { return copySymbols(value, baseAssign(result, value)); } } else { if (!cloneableTags[tag]) { return object ? value : {}; } result = initCloneByTag(value, tag, baseClone, isDeep); } } // Check for circular references and return its corresponding clone. stack || (stack = new Stack); var stacked = stack.get(value); if (stacked) { return stacked; } stack.set(value, result); if (!isArr) { var props = isFull ? getAllKeys(value) : keys(value); } // Recursively populate clone (susceptible to call stack limits). arrayEach(props || value, function(subValue, key) { if (props) { key = subValue; subValue = value[key]; } assignValue(result, key, baseClone(subValue, isDeep, isFull, customizer, key, value, stack)); }); return result; } /** * The base implementation of `_.conforms` which doesn't clone `source`. * * @private * @param {Object} source The object of property predicates to conform to. * @returns {Function} Returns the new spec function. */ function baseConforms(source) { var props = keys(source), length = props.length; return function(object) { if (object == null) { return !length; } var index = length; while (index--) { var key = props[index], predicate = source[key], value = object[key]; if ((value === undefined && !(key in Object(object))) || !predicate(value)) { return false; } } return true; }; } /** * The base implementation of `_.create` without support for assigning * properties to the created object. * * @private * @param {Object} prototype The object to inherit from. * @returns {Object} Returns the new object. */ function baseCreate(proto) { return isObject(proto) ? objectCreate(proto) : {}; } /** * The base implementation of `_.delay` and `_.defer` which accepts an array * of `func` arguments. * * @private * @param {Function} func The function to delay. * @param {number} wait The number of milliseconds to delay invocation. * @param {Object} args The arguments to provide to `func`. * @returns {number} Returns the timer id. */ function baseDelay(func, wait, args) { if (typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } return setTimeout(function() { func.apply(undefined, args); }, wait); } /** * The base implementation of methods like `_.difference` without support * for excluding multiple arrays or iteratee shorthands. * * @private * @param {Array} array The array to inspect. * @param {Array} values The values to exclude. * @param {Function} [iteratee] The iteratee invoked per element. * @param {Function} [comparator] The comparator invoked per element. * @returns {Array} Returns the new array of filtered values. */ function baseDifference(array, values, iteratee, comparator) { var index = -1, includes = arrayIncludes, isCommon = true, length = array.length, result = [], valuesLength = values.length; if (!length) { return result; } if (iteratee) { values = arrayMap(values, baseUnary(iteratee)); } if (comparator) { includes = arrayIncludesWith; isCommon = false; } else if (values.length >= LARGE_ARRAY_SIZE) { includes = cacheHas; isCommon = false; values = new SetCache(values); } outer: while (++index < length) { var value = array[index], computed = iteratee ? iteratee(value) : value; value = (comparator || value !== 0) ? value : 0; if (isCommon && computed === computed) { var valuesIndex = valuesLength; while (valuesIndex--) { if (values[valuesIndex] === computed) { continue outer; } } result.push(value); } else if (!includes(values, computed, comparator)) { result.push(value); } } return result; } /** * The base implementation of `_.forEach` without support for iteratee shorthands. * * @private * @param {Array|Object} collection The collection to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Array|Object} Returns `collection`. */ var baseEach = createBaseEach(baseForOwn); /** * The base implementation of `_.forEachRight` without support for iteratee shorthands. * * @private * @param {Array|Object} collection The collection to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Array|Object} Returns `collection`. */ var baseEachRight = createBaseEach(baseForOwnRight, true); /** * The base implementation of `_.every` without support for iteratee shorthands. * * @private * @param {Array|Object} collection The collection to iterate over. * @param {Function} predicate The function invoked per iteration. * @returns {boolean} Returns `true` if all elements pass the predicate check, * else `false` */ function baseEvery(collection, predicate) { var result = true; baseEach(collection, function(value, index, collection) { result = !!predicate(value, index, collection); return result; }); return result; } /** * The base implementation of methods like `_.max` and `_.min` which accepts a * `comparator` to determine the extremum value. * * @private * @param {Array} array The array to iterate over. * @param {Function} iteratee The iteratee invoked per iteration. * @param {Function} comparator The comparator used to compare values. * @returns {*} Returns the extremum value. */ function baseExtremum(array, iteratee, comparator) { var index = -1, length = array.length; while (++index < length) { var value = array[index], current = iteratee(value); if (current != null && (computed === undefined ? (current === current && !isSymbol(current)) : comparator(current, computed) )) { var computed = current, result = value; } } return result; } /** * The base implementation of `_.fill` without an iteratee call guard. * * @private * @param {Array} array The array to fill. * @param {*} value The value to fill `array` with. * @param {number} [start=0] The start position. * @param {number} [end=array.length] The end position. * @returns {Array} Returns `array`. */ function baseFill(array, value, start, end) { var length = array.length; start = toInteger(start); if (start < 0) { start = -start > length ? 0 : (length + start); } end = (end === undefined || end > length) ? length : toInteger(end); if (end < 0) { end += length; } end = start > end ? 0 : toLength(end); while (start < end) { array[start++] = value; } return array; } /** * The base implementation of `_.filter` without support for iteratee shorthands. * * @private * @param {Array|Object} collection The collection to iterate over. * @param {Function} predicate The function invoked per iteration. * @returns {Array} Returns the new filtered array. */ function baseFilter(collection, predicate) { var result = []; baseEach(collection, function(value, index, collection) { if (predicate(value, index, collection)) { result.push(value); } }); return result; } /** * The base implementation of `_.flatten` with support for restricting flattening. * * @private * @param {Array} array The array to flatten. * @param {number} depth The maximum recursion depth. * @param {boolean} [predicate=isFlattenable] The function invoked per iteration. * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks. * @param {Array} [result=[]] The initial result value. * @returns {Array} Returns the new flattened array. */ function baseFlatten(array, depth, predicate, isStrict, result) { var index = -1, length = array.length; predicate || (predicate = isFlattenable); result || (result = []); while (++index < length) { var value = array[index]; if (depth > 0 && predicate(value)) { if (depth > 1) { // Recursively flatten arrays (susceptible to call stack limits). baseFlatten(value, depth - 1, predicate, isStrict, result); } else { arrayPush(result, value); } } else if (!isStrict) { result[result.length] = value; } } return result; } /** * The base implementation of `baseForOwn` which iterates over `object` * properties returned by `keysFunc` and invokes `iteratee` for each property. * Iteratee functions may exit iteration early by explicitly returning `false`. * * @private * @param {Object} object The object to iterate over. * @param {Function} iteratee The function invoked per iteration. * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ var baseFor = createBaseFor(); /** * This function is like `baseFor` except that it iterates over properties * in the opposite order. * * @private * @param {Object} object The object to iterate over. * @param {Function} iteratee The function invoked per iteration. * @param {Function} keysFunc The function to get the keys of `object`. * @returns {Object} Returns `object`. */ var baseForRight = createBaseFor(true); /** * The base implementation of `_.forOwn` without support for iteratee shorthands. * * @private * @param {Object} object The object to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Object} Returns `object`. */ function baseForOwn(object, iteratee) { return object && baseFor(object, iteratee, keys); } /** * The base implementation of `_.forOwnRight` without support for iteratee shorthands. * * @private * @param {Object} object The object to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Object} Returns `object`. */ function baseForOwnRight(object, iteratee) { return object && baseForRight(object, iteratee, keys); } /** * The base implementation of `_.functions` which creates an array of * `object` function property names filtered from `props`. * * @private * @param {Object} object The object to inspect. * @param {Array} props The property names to filter. * @returns {Array} Returns the function names. */ function baseFunctions(object, props) { return arrayFilter(props, function(key) { return isFunction(object[key]); }); } /** * The base implementation of `_.get` without support for default values. * * @private * @param {Object} object The object to query. * @param {Array|string} path The path of the property to get. * @returns {*} Returns the resolved value. */ function baseGet(object, path) { path = isKey(path, object) ? [path] : castPath(path); var index = 0, length = path.length; while (object != null && index < length) { object = object[toKey(path[index++])]; } return (index && index == length) ? object : undefined; } /** * The base implementation of `getAllKeys` and `getAllKeysIn` which uses * `keysFunc` and `symbolsFunc` to get the enumerable property names and * symbols of `object`. * * @private * @param {Object} object The object to query. * @param {Function} keysFunc The function to get the keys of `object`. * @param {Function} symbolsFunc The function to get the symbols of `object`. * @returns {Array} Returns the array of property names and symbols. */ function baseGetAllKeys(object, keysFunc, symbolsFunc) { var result = keysFunc(object); return isArray(object) ? result : arrayPush(result, symbolsFunc(object)); } /** * The base implementation of `_.gt` which doesn't coerce arguments to numbers. * * @private * @param {*} value The value to compare. * @param {*} other The other value to compare. * @returns {boolean} Returns `true` if `value` is greater than `other`, * else `false`. */ function baseGt(value, other) { return value > other; } /** * The base implementation of `_.has` without support for deep paths. * * @private * @param {Object} object The object to query. * @param {Array|string} key The key to check. * @returns {boolean} Returns `true` if `key` exists, else `false`. */ function baseHas(object, key) { // Avoid a bug in IE 10-11 where objects with a [[Prototype]] of `null`, // that are composed entirely of index properties, return `false` for // `hasOwnProperty` checks of them. return hasOwnProperty.call(object, key) || (typeof object == 'object' && key in object && getPrototype(object) === null); } /** * The base implementation of `_.hasIn` without support for deep paths. * * @private * @param {Object} object The object to query. * @param {Array|string} key The key to check. * @returns {boolean} Returns `true` if `key` exists, else `false`. */ function baseHasIn(object, key) { return key in Object(object); } /** * The base implementation of `_.inRange` which doesn't coerce arguments to numbers. * * @private * @param {number} number The number to check. * @param {number} start The start of the range. * @param {number} end The end of the range. * @returns {boolean} Returns `true` if `number` is in the range, else `false`. */ function baseInRange(number, start, end) { return number >= nativeMin(start, end) && number < nativeMax(start, end); } /** * The base implementation of methods like `_.intersection`, without support * for iteratee shorthands, that accepts an array of arrays to inspect. * * @private * @param {Array} arrays The arrays to inspect. * @param {Function} [iteratee] The iteratee invoked per element. * @param {Function} [comparator] The comparator invoked per element. * @returns {Array} Returns the new array of shared values. */ function baseIntersection(arrays, iteratee, comparator) { var includes = comparator ? arrayIncludesWith : arrayIncludes, length = arrays[0].length, othLength = arrays.length, othIndex = othLength, caches = Array(othLength), maxLength = Infinity, result = []; while (othIndex--) { var array = arrays[othIndex]; if (othIndex && iteratee) { array = arrayMap(array, baseUnary(iteratee)); } maxLength = nativeMin(array.length, maxLength); caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120)) ? new SetCache(othIndex && array) : undefined; } array = arrays[0]; var index = -1, seen = caches[0]; outer: while (++index < length && result.length < maxLength) { var value = array[index], computed = iteratee ? iteratee(value) : value; value = (comparator || value !== 0) ? value : 0; if (!(seen ? cacheHas(seen, computed) : includes(result, computed, comparator) )) { othIndex = othLength; while (--othIndex) { var cache = caches[othIndex]; if (!(cache ? cacheHas(cache, computed) : includes(arrays[othIndex], computed, comparator)) ) { continue outer; } } if (seen) { seen.push(computed); } result.push(value); } } return result; } /** * The base implementation of `_.invert` and `_.invertBy` which inverts * `object` with values transformed by `iteratee` and set by `setter`. * * @private * @param {Object} object The object to iterate over. * @param {Function} setter The function to set `accumulator` values. * @param {Function} iteratee The iteratee to transform values. * @param {Object} accumulator The initial inverted object. * @returns {Function} Returns `accumulator`. */ function baseInverter(object, setter, iteratee, accumulator) { baseForOwn(object, function(value, key, object) { setter(accumulator, iteratee(value), key, object); }); return accumulator; } /** * The base implementation of `_.invoke` without support for individual * method arguments. * * @private * @param {Object} object The object to query. * @param {Array|string} path The path of the method to invoke. * @param {Array} args The arguments to invoke the method with. * @returns {*} Returns the result of the invoked method. */ function baseInvoke(object, path, args) { if (!isKey(path, object)) { path = castPath(path); object = parent(object, path); path = last(path); } var func = object == null ? object : object[toKey(path)]; return func == null ? undefined : apply(func, object, args); } /** * The base implementation of `_.isEqual` which supports partial comparisons * and tracks traversed objects. * * @private * @param {*} value The value to compare. * @param {*} other The other value to compare. * @param {Function} [customizer] The function to customize comparisons. * @param {boolean} [bitmask] The bitmask of comparison flags. * The bitmask may be composed of the following flags: * 1 - Unordered comparison * 2 - Partial comparison * @param {Object} [stack] Tracks traversed `value` and `other` objects. * @returns {boolean} Returns `true` if the values are equivalent, else `false`. */ function baseIsEqual(value, other, customizer, bitmask, stack) { if (value === other) { return true; } if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) { return value !== value && other !== other; } return baseIsEqualDeep(value, other, baseIsEqual, customizer, bitmask, stack); } /** * A specialized version of `baseIsEqual` for arrays and objects which performs * deep comparisons and tracks traversed objects enabling objects with circular * references to be compared. * * @private * @param {Object} object The object to compare. * @param {Object} other The other object to compare. * @param {Function} equalFunc The function to determine equivalents of values. * @param {Function} [customizer] The function to customize comparisons. * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual` * for more details. * @param {Object} [stack] Tracks traversed `object` and `other` objects. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ function baseIsEqualDeep(object, other, equalFunc, customizer, bitmask, stack) { var objIsArr = isArray(object), othIsArr = isArray(other), objTag = arrayTag, othTag = arrayTag; if (!objIsArr) { objTag = getTag(object); objTag = objTag == argsTag ? objectTag : objTag; } if (!othIsArr) { othTag = getTag(other); othTag = othTag == argsTag ? objectTag : othTag; } var objIsObj = objTag == objectTag && !isHostObject(object), othIsObj = othTag == objectTag && !isHostObject(other), isSameTag = objTag == othTag; if (isSameTag && !objIsObj) { stack || (stack = new Stack); return (objIsArr || isTypedArray(object)) ? equalArrays(object, other, equalFunc, customizer, bitmask, stack) : equalByTag(object, other, objTag, equalFunc, customizer, bitmask, stack); } if (!(bitmask & PARTIAL_COMPARE_FLAG)) { var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); if (objIsWrapped || othIsWrapped) { var objUnwrapped = objIsWrapped ? object.value() : object, othUnwrapped = othIsWrapped ? other.value() : other; stack || (stack = new Stack); return equalFunc(objUnwrapped, othUnwrapped, customizer, bitmask, stack); } } if (!isSameTag) { return false; } stack || (stack = new Stack); return equalObjects(object, other, equalFunc, customizer, bitmask, stack); } /** * The base implementation of `_.isMatch` without support for iteratee shorthands. * * @private * @param {Object} object The object to inspect. * @param {Object} source The object of property values to match. * @param {Array} matchData The property names, values, and compare flags to match. * @param {Function} [customizer] The function to customize comparisons. * @returns {boolean} Returns `true` if `object` is a match, else `false`. */ function baseIsMatch(object, source, matchData, customizer) { var index = matchData.length, length = index, noCustomizer = !customizer; if (object == null) { return !length; } object = Object(object); while (index--) { var data = matchData[index]; if ((noCustomizer && data[2]) ? data[1] !== object[data[0]] : !(data[0] in object) ) { return false; } } while (++index < length) { data = matchData[index]; var key = data[0], objValue = object[key], srcValue = data[1]; if (noCustomizer && data[2]) { if (objValue === undefined && !(key in object)) { return false; } } else { var stack = new Stack; if (customizer) { var result = customizer(objValue, srcValue, key, object, source, stack); } if (!(result === undefined ? baseIsEqual(srcValue, objValue, customizer, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG, stack) : result )) { return false; } } } return true; } /** * The base implementation of `_.iteratee`. * * @private * @param {*} [value=_.identity] The value to convert to an iteratee. * @returns {Function} Returns the iteratee. */ function baseIteratee(value) { // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9. // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details. if (typeof value == 'function') { return value; } if (value == null) { return identity; } if (typeof value == 'object') { return isArray(value) ? baseMatchesProperty(value[0], value[1]) : baseMatches(value); } return property(value); } /** * The base implementation of `_.keys` which doesn't skip the constructor * property of prototypes or treat sparse arrays as dense. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the array of property names. */ function baseKeys(object) { return nativeKeys(Object(object)); } /** * The base implementation of `_.keysIn` which doesn't skip the constructor * property of prototypes or treat sparse arrays as dense. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the array of property names. */ function baseKeysIn(object) { object = object == null ? object : Object(object); var result = []; for (var key in object) { result.push(key); } return result; } // Fallback for IE < 9 with es6-shim. if (enumerate && !propertyIsEnumerable.call({ 'valueOf': 1 }, 'valueOf')) { baseKeysIn = function(object) { return iteratorToArray(enumerate(object)); }; } /** * The base implementation of `_.lt` which doesn't coerce arguments to numbers. * * @private * @param {*} value The value to compare. * @param {*} other The other value to compare. * @returns {boolean} Returns `true` if `value` is less than `other`, * else `false`. */ function baseLt(value, other) { return value < other; } /** * The base implementation of `_.map` without support for iteratee shorthands. * * @private * @param {Array|Object} collection The collection to iterate over. * @param {Function} iteratee The function invoked per iteration. * @returns {Array} Returns the new mapped array. */ function baseMap(collection, iteratee) { var index = -1, result = isArrayLike(collection) ? Array(collection.length) : []; baseEach(collection, function(value, key, collection) { result[++index] = iteratee(value, key, collection); }); return result; } /** * The base implementation of `_.matches` which doesn't clone `source`. * * @private * @param {Object} source The object of property values to match. * @returns {Function} Returns the new spec function. */ function baseMatches(source) { var matchData = getMatchData(source); if (matchData.length == 1 && matchData[0][2]) { return matchesStrictComparable(matchData[0][0], matchData[0][1]); } return function(object) { return object === source || baseIsMatch(object, source, matchData); }; } /** * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`. * * @private * @param {string} path The path of the property to get. * @param {*} srcValue The value to match. * @returns {Function} Returns the new spec function. */ function baseMatchesProperty(path, srcValue) { if (isKey(path) && isStrictComparable(srcValue)) { return matchesStrictComparable(toKey(path), srcValue); } return function(object) { var objValue = get(object, path); return (objValue === undefined && objValue === srcValue) ? hasIn(object, path) : baseIsEqual(srcValue, objValue, undefined, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG); }; } /** * The base implementation of `_.merge` without support for multiple sources. * * @private * @param {Object} object The destination object. * @param {Object} source The source object. * @param {number} srcIndex The index of `source`. * @param {Function} [customizer] The function to customize merged values. * @param {Object} [stack] Tracks traversed source values and their merged * counterparts. */ function baseMerge(object, source, srcIndex, customizer, stack) { if (object === source) { return; } if (!(isArray(source) || isTypedArray(source))) { var props = keysIn(source); } arrayEach(props || source, function(srcValue, key) { if (props) { key = srcValue; srcValue = source[key]; } if (isObject(srcValue)) { stack || (stack = new Stack); baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack); } else { var newValue = customizer ? customizer(object[key], srcValue, (key + ''), object, source, stack) : undefined; if (newValue === undefined) { newValue = srcValue; } assignMergeValue(object, key, newValue); } }); } /** * A specialized version of `baseMerge` for arrays and objects which performs * deep merges and tracks traversed objects enabling objects with circular * references to be merged. * * @private * @param {Object} object The destination object. * @param {Object} source The source object. * @param {string} key The key of the value to merge. * @param {number} srcIndex The index of `source`. * @param {Function} mergeFunc The function to merge values. * @param {Function} [customizer] The function to customize assigned values. * @param {Object} [stack] Tracks traversed source values and their merged * counterparts. */ function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) { var objValue = object[key], srcValue = source[key], stacked = stack.get(srcValue); if (stacked) { assignMergeValue(object, key, stacked); return; } var newValue = customizer ? customizer(objValue, srcValue, (key + ''), object, source, stack) : undefined; var isCommon = newValue === undefined; if (isCommon) { newValue = srcValue; if (isArray(srcValue) || isTypedArray(srcValue)) { if (isArray(objValue)) { newValue = objValue; } else if (isArrayLikeObject(objValue)) { newValue = copyArray(objValue); } else { isCommon = false; newValue = baseClone(srcValue, true); } } else if (isPlainObject(srcValue) || isArguments(srcValue)) { if (isArguments(objValue)) { newValue = toPlainObject(objValue); } else if (!isObject(objValue) || (srcIndex && isFunction(objValue))) { isCommon = false; newValue = baseClone(srcValue, true); } else { newValue = objValue; } } else { isCommon = false; } } stack.set(srcValue, newValue); if (isCommon) { // Recursively merge objects and arrays (susceptible to call stack limits). mergeFunc(newValue, srcValue, srcIndex, customizer, stack); } stack['delete'](srcValue); assignMergeValue(object, key, newValue); } /** * The base implementation of `_.nth` which doesn't coerce `n` to an integer. * * @private * @param {Array} array The array to query. * @param {number} n The index of the element to return. * @returns {*} Returns the nth element of `array`. */ function baseNth(array, n) { var length = array.length; if (!length) { return; } n += n < 0 ? length : 0; return isIndex(n, length) ? array[n] : undefined; } /** * The base implementation of `_.orderBy` without param guards. * * @private * @param {Array|Object} collection The collection to iterate over. * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by. * @param {string[]} orders The sort orders of `iteratees`. * @returns {Array} Returns the new sorted array. */ function baseOrderBy(collection, iteratees, orders) { var index = -1; iteratees = arrayMap(iteratees.length ? iteratees : [identity], baseUnary(getIteratee())); var result = baseMap(collection, function(value, key, collection) { var criteria = arrayMap(iteratees, function(iteratee) { return iteratee(value); }); return { 'criteria': criteria, 'index': ++index, 'value': value }; }); return baseSortBy(result, function(object, other) { return compareMultiple(object, other, orders); }); } /** * The base implementation of `_.pick` without support for individual * property identifiers. * * @private * @param {Object} object The source object. * @param {string[]} props The property identifiers to pick. * @returns {Object} Returns the new object. */ function basePick(object, props) { object = Object(object); return arrayReduce(props, function(result, key) { if (key in object) { result[key] = object[key]; } return result; }, {}); } /** * The base implementation of `_.pickBy` without support for iteratee shorthands. * * @private * @param {Object} object The source object. * @param {Function} predicate The function invoked per property. * @returns {Object} Returns the new object. */ function basePickBy(object, predicate) { var index = -1, props = getAllKeysIn(object), length = props.length, result = {}; while (++index < length) { var key = props[index], value = object[key]; if (predicate(value, key)) { result[key] = value; } } return result; } /** * The base implementation of `_.property` without support for deep paths. * * @private * @param {string} key The key of the property to get. * @returns {Function} Returns the new accessor function. */ function baseProperty(key) { return function(object) { return object == null ? undefined : object[key]; }; } /** * A specialized version of `baseProperty` which supports deep paths. * * @private * @param {Array|string} path The path of the property to get. * @returns {Function} Returns the new accessor function. */ function basePropertyDeep(path) { return function(object) { return baseGet(object, path); }; } /** * The base implementation of `_.pullAllBy` without support for iteratee * shorthands. * * @private * @param {Array} array The array to modify. * @param {Array} values The values to remove. * @param {Function} [iteratee] The iteratee invoked per element. * @param {Function} [comparator] The comparator invoked per element. * @returns {Array} Returns `array`. */ function basePullAll(array, values, iteratee, comparator) { var indexOf = comparator ? baseIndexOfWith : baseIndexOf, index = -1, length = values.length, seen = array; if (iteratee) { seen = arrayMap(array, baseUnary(iteratee)); } while (++index < length) { var fromIndex = 0, value = values[index], computed = iteratee ? iteratee(value) : value; while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) { if (seen !== array) { splice.call(seen, fromIndex, 1); } splice.call(array, fromIndex, 1); } } return array; } /** * The base implementation of `_.pullAt` without support for individual * indexes or capturing the removed elements. * * @private * @param {Array} array The array to modify. * @param {number[]} indexes The indexes of elements to remove. * @returns {Array} Returns `array`. */ function basePullAt(array, indexes) { var length = array ? indexes.length : 0, lastIndex = length - 1; while (length--) { var index = indexes[length]; if (length == lastIndex || index !== previous) { var previous = index; if (isIndex(index)) { splice.call(array, index, 1); } else if (!isKey(index, array)) { var path = castPath(index), object = parent(array, path); if (object != null) { delete object[toKey(last(path))]; } } else { delete array[toKey(index)]; } } } return array; } /** * The base implementation of `_.random` without support for returning * floating-point numbers. * * @private * @param {number} lower The lower bound. * @param {number} upper The upper bound. * @returns {number} Returns the random number. */ function baseRandom(lower, upper) { return lower + nativeFloor(nativeRandom() * (upper - lower + 1)); } /** * The base implementation of `_.range` and `_.rangeRight` which doesn't * coerce arguments to numbers. * * @private * @param {number} start The start of the range. * @param {number} end The end of the range. * @param {number} step The value to increment or decrement by. * @param {boolean} [fromRight] Specify iterating from right to left. * @returns {Array} Returns the range of numbers. */ function baseRange(start, end, step, fromRight) { var index = -1, length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), result = Array(length); while (length--) { result[fromRight ? length : ++index] = start; start += step; } return result; } /** * The base implementation of `_.repeat` which doesn't coerce arguments. * * @private * @param {string} string The string to repeat. * @param {number} n The number of times to repeat the string. * @returns {string} Returns the repeated string. */ function baseRepeat(string, n) { var result = ''; if (!string || n < 1 || n > MAX_SAFE_INTEGER) { return result; } // Leverage the exponentiation by squaring algorithm for a faster repeat. // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details. do { if (n % 2) { result += string; } n = nativeFloor(n / 2); if (n) { string += string; } } while (n); return result; } /** * The base implementation of `_.set`. * * @private * @param {Object} object The object to query. * @param {Array|string} path The path of the property to set. * @param {*} value The value to set. * @param {Function} [customizer] The function to customize path creation. * @returns {Object} Returns `object`. */ function baseSet(object, path, value, customizer) { path = isKey(path, object) ? [path] : castPath(path); var index = -1, length = path.length, lastIndex = length - 1, nested = object; while (nested != null && ++index < length) { var key = toKey(path[index]); if (isObject(nested)) { var newValue = value; if (index != lastIndex) { var objValue = nested[key]; newValue = customizer ? customizer(objValue, key, nested) : undefined; if (newValue === undefined) { newValue = objValue == null ? (isIndex(path[index + 1]) ? [] : {}) : objValue; } } assignValue(nested, key, newValue); } nested = nested[key]; } return object; } /** * The base implementation of `setData` without support for hot loop detection. * * @private * @param {Function} func The function to associate metadata with. * @param {*} data The metadata. * @returns {Function} Returns `func`. */ var baseSetData = !metaMap ? identity : function(func, data) { metaMap.set(func, data); return func; }; /** * The base implementation of `_.slice` without an iteratee call guard. * * @private * @param {Array} array The array to slice. * @param {number} [start=0] The start position. * @param {number} [end=array.length] The end position. * @returns {Array} Returns the slice of `array`. */ function baseSlice(array, start, end) { var index = -1, length = array.length; if (start < 0) { start = -start > length ? 0 : (length + start); } end = end > length ? length : end; if (end < 0) { end += length; } length = start > end ? 0 : ((end - start) >>> 0); start >>>= 0; var result = Array(length); while (++index < length) { result[index] = array[index + start]; } return result; } /** * The base implementation of `_.some` without support for iteratee shorthands. * * @private * @param {Array|Object} collection The collection to iterate over. * @param {Function} predicate The function invoked per iteration. * @returns {boolean} Returns `true` if any element passes the predicate check, * else `false`. */ function baseSome(collection, predicate) { var result; baseEach(collection, function(value, index, collection) { result = predicate(value, index, collection); return !result; }); return !!result; } /** * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which * performs a binary search of `array` to determine the index at which `value` * should be inserted into `array` in order to maintain its sort order. * * @private * @param {Array} array The sorted array to inspect. * @param {*} value The value to evaluate. * @param {boolean} [retHighest] Specify returning the highest qualified index. * @returns {number} Returns the index at which `value` should be inserted * into `array`. */ function baseSortedIndex(array, value, retHighest) { var low = 0, high = array ? array.length : low; if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) { while (low < high) { var mid = (low + high) >>> 1, computed = array[mid]; if (computed !== null && !isSymbol(computed) && (retHighest ? (computed <= value) : (computed < value))) { low = mid + 1; } else { high = mid; } } return high; } return baseSortedIndexBy(array, value, identity, retHighest); } /** * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy` * which invokes `iteratee` for `value` and each element of `array` to compute * their sort ranking. The iteratee is invoked with one argument; (value). * * @private * @param {Array} array The sorted array to inspect. * @param {*} value The value to evaluate. * @param {Function} iteratee The iteratee invoked per element. * @param {boolean} [retHighest] Specify returning the highest qualified index. * @returns {number} Returns the index at which `value` should be inserted * into `array`. */ function baseSortedIndexBy(array, value, iteratee, retHighest) { value = iteratee(value); var low = 0, high = array ? array.length : 0, valIsNaN = value !== value, valIsNull = value === null, valIsSymbol = isSymbol(value), valIsUndefined = value === undefined; while (low < high) { var mid = nativeFloor((low + high) / 2), computed = iteratee(array[mid]), othIsDefined = computed !== undefined, othIsNull = computed === null, othIsReflexive = computed === computed, othIsSymbol = isSymbol(computed); if (valIsNaN) { var setLow = retHighest || othIsReflexive; } else if (valIsUndefined) { setLow = othIsReflexive && (retHighest || othIsDefined); } else if (valIsNull) { setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull); } else if (valIsSymbol) { setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol); } else if (othIsNull || othIsSymbol) { setLow = false; } else { setLow = retHighest ? (computed <= value) : (computed < value); } if (setLow) { low = mid + 1; } else { high = mid; } } return nativeMin(high, MAX_ARRAY_INDEX); } /** * The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without * support for iteratee shorthands. * * @private * @param {Array} array The array to inspect. * @param {Function} [iteratee] The iteratee invoked per element. * @returns {Array} Returns the new duplicate free array. */ function baseSortedUniq(array, iteratee) { var index = -1, length = array.length, resIndex = 0, result = []; while (++index < length) { var value = array[index], computed = iteratee ? iteratee(value) : value; if (!index || !eq(computed, seen)) { var seen = computed; result[resIndex++] = value === 0 ? 0 : value; } } return result; } /** * The base implementation of `_.toNumber` which doesn't ensure correct * conversions of binary, hexadecimal, or octal string values. * * @private * @param {*} value The value to process. * @returns {number} Returns the number. */ function baseToNumber(value) { if (typeof value == 'number') { return value; } if (isSymbol(value)) { return NAN; } return +value; } /** * The base implementation of `_.toString` which doesn't convert nullish * values to empty strings. * * @private * @param {*} value The value to process. * @returns {string} Returns the string. */ function baseToString(value) { // Exit early for strings to avoid a performance hit in some environments. if (typeof value == 'string') { return value; } if (isSymbol(value)) { return symbolToString ? symbolToString.call(value) : ''; } var result = (value + ''); return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; } /** * The base implementation of `_.uniqBy` without support for iteratee shorthands. * * @private * @param {Array} array The array to inspect. * @param {Function} [iteratee] The iteratee invoked per element. * @param {Function} [comparator] The comparator invoked per element. * @returns {Array} Returns the new duplicate free array. */ function baseUniq(array, iteratee, comparator) { var index = -1, includes = arrayIncludes, length = array.length, isCommon = true, result = [], seen = result; if (comparator) { isCommon = false; includes = arrayIncludesWith; } else if (length >= LARGE_ARRAY_SIZE) { var set = iteratee ? null : createSet(array); if (set) { return setToArray(set); } isCommon = false; includes = cacheHas; seen = new SetCache; } else { seen = iteratee ? [] : result; } outer: while (++index < length) { var value = array[index], computed = iteratee ? iteratee(value) : value; value = (comparator || value !== 0) ? value : 0; if (isCommon && computed === computed) { var seenIndex = seen.length; while (seenIndex--) { if (seen[seenIndex] === computed) { continue outer; } } if (iteratee) { seen.push(computed); } result.push(value); } else if (!includes(seen, computed, comparator)) { if (seen !== result) { seen.push(computed); } result.push(value); } } return result; } /** * The base implementation of `_.unset`. * * @private * @param {Object} object The object to modify. * @param {Array|string} path The path of the property to unset. * @returns {boolean} Returns `true` if the property is deleted, else `false`. */ function baseUnset(object, path) { path = isKey(path, object) ? [path] : castPath(path); object = parent(object, path); var key = toKey(last(path)); return !(object != null && baseHas(object, key)) || delete object[key]; } /** * The base implementation of `_.update`. * * @private * @param {Object} object The object to query. * @param {Array|string} path The path of the property to update. * @param {Function} updater The function to produce the updated value. * @param {Function} [customizer] The function to customize path creation. * @returns {Object} Returns `object`. */ function baseUpdate(object, path, updater, customizer) { return baseSet(object, path, updater(baseGet(object, path)), customizer); } /** * The base implementation of methods like `_.dropWhile` and `_.takeWhile` * without support for iteratee shorthands. * * @private * @param {Array} array The array to query. * @param {Function} predicate The function invoked per iteration. * @param {boolean} [isDrop] Specify dropping elements instead of taking them. * @param {boolean} [fromRight] Specify iterating from right to left. * @returns {Array} Returns the slice of `array`. */ function baseWhile(array, predicate, isDrop, fromRight) { var length = array.length, index = fromRight ? length : -1; while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {} return isDrop ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length)) : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index)); } /** * The base implementation of `wrapperValue` which returns the result of * performing a sequence of actions on the unwrapped `value`, where each * successive action is supplied the return value of the previous. * * @private * @param {*} value The unwrapped value. * @param {Array} actions Actions to perform to resolve the unwrapped value. * @returns {*} Returns the resolved value. */ function baseWrapperValue(value, actions) { var result = value; if (result instanceof LazyWrapper) { result = result.value(); } return arrayReduce(actions, function(result, action) { return action.func.apply(action.thisArg, arrayPush([result], action.args)); }, result); } /** * The base implementation of methods like `_.xor`, without support for * iteratee shorthands, that accepts an array of arrays to inspect. * * @private * @param {Array} arrays The arrays to inspect. * @param {Function} [iteratee] The iteratee invoked per element. * @param {Function} [comparator] The comparator invoked per element. * @returns {Array} Returns the new array of values. */ function baseXor(arrays, iteratee, comparator) { var index = -1, length = arrays.length; while (++index < length) { var result = result ? arrayPush( baseDifference(result, arrays[index], iteratee, comparator), baseDifference(arrays[index], result, iteratee, comparator) ) : arrays[index]; } return (result && result.length) ? baseUniq(result, iteratee, comparator) : []; } /** * This base implementation of `_.zipObject` which assigns values using `assignFunc`. * * @private * @param {Array} props The property identifiers. * @param {Array} values The property values. * @param {Function} assignFunc The function to assign values. * @returns {Object} Returns the new object. */ function baseZipObject(props, values, assignFunc) { var index = -1, length = props.length, valsLength = values.length, result = {}; while (++index < length) { var value = index < valsLength ? values[index] : undefined; assignFunc(result, props[index], value); } return result; } /** * Casts `value` to an empty array if it's not an array like object. * * @private * @param {*} value The value to inspect. * @returns {Array|Object} Returns the cast array-like object. */ function castArrayLikeObject(value) { return isArrayLikeObject(value) ? value : []; } /** * Casts `value` to `identity` if it's not a function. * * @private * @param {*} value The value to inspect. * @returns {Function} Returns cast function. */ function castFunction(value) { return typeof value == 'function' ? value : identity; } /** * Casts `value` to a path array if it's not one. * * @private * @param {*} value The value to inspect. * @returns {Array} Returns the cast property path array. */ function castPath(value) { return isArray(value) ? value : stringToPath(value); } /** * Casts `array` to a slice if it's needed. * * @private * @param {Array} array The array to inspect. * @param {number} start The start position. * @param {number} [end=array.length] The end position. * @returns {Array} Returns the cast slice. */ function castSlice(array, start, end) { var length = array.length; end = end === undefined ? length : end; return (!start && end >= length) ? array : baseSlice(array, start, end); } /** * Creates a clone of `buffer`. * * @private * @param {Buffer} buffer The buffer to clone. * @param {boolean} [isDeep] Specify a deep clone. * @returns {Buffer} Returns the cloned buffer. */ function cloneBuffer(buffer, isDeep) { if (isDeep) { return buffer.slice(); } var result = new buffer.constructor(buffer.length); buffer.copy(result); return result; } /** * Creates a clone of `arrayBuffer`. * * @private * @param {ArrayBuffer} arrayBuffer The array buffer to clone. * @returns {ArrayBuffer} Returns the cloned array buffer. */ function cloneArrayBuffer(arrayBuffer) { var result = new arrayBuffer.constructor(arrayBuffer.byteLength); new Uint8Array(result).set(new Uint8Array(arrayBuffer)); return result; } /** * Creates a clone of `dataView`. * * @private * @param {Object} dataView The data view to clone. * @param {boolean} [isDeep] Specify a deep clone. * @returns {Object} Returns the cloned data view. */ function cloneDataView(dataView, isDeep) { var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer; return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength); } /** * Creates a clone of `map`. * * @private * @param {Object} map The map to clone. * @param {Function} cloneFunc The function to clone values. * @param {boolean} [isDeep] Specify a deep clone. * @returns {Object} Returns the cloned map. */ function cloneMap(map, isDeep, cloneFunc) { var array = isDeep ? cloneFunc(mapToArray(map), true) : mapToArray(map); return arrayReduce(array, addMapEntry, new map.constructor); } /** * Creates a clone of `regexp`. * * @private * @param {Object} regexp The regexp to clone. * @returns {Object} Returns the cloned regexp. */ function cloneRegExp(regexp) { var result = new regexp.constructor(regexp.source, reFlags.exec(regexp)); result.lastIndex = regexp.lastIndex; return result; } /** * Creates a clone of `set`. * * @private * @param {Object} set The set to clone. * @param {Function} cloneFunc The function to clone values. * @param {boolean} [isDeep] Specify a deep clone. * @returns {Object} Returns the cloned set. */ function cloneSet(set, isDeep, cloneFunc) { var array = isDeep ? cloneFunc(setToArray(set), true) : setToArray(set); return arrayReduce(array, addSetEntry, new set.constructor); } /** * Creates a clone of the `symbol` object. * * @private * @param {Object} symbol The symbol object to clone. * @returns {Object} Returns the cloned symbol object. */ function cloneSymbol(symbol) { return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {}; } /** * Creates a clone of `typedArray`. * * @private * @param {Object} typedArray The typed array to clone. * @param {boolean} [isDeep] Specify a deep clone. * @returns {Object} Returns the cloned typed array. */ function cloneTypedArray(typedArray, isDeep) { var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer; return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length); } /** * Compares values to sort them in ascending order. * * @private * @param {*} value The value to compare. * @param {*} other The other value to compare. * @returns {number} Returns the sort order indicator for `value`. */ function compareAscending(value, other) { if (value !== other) { var valIsDefined = value !== undefined, valIsNull = value === null, valIsReflexive = value === value, valIsSymbol = isSymbol(value); var othIsDefined = other !== undefined, othIsNull = other === null, othIsReflexive = other === other, othIsSymbol = isSymbol(other); if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) || (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) || (valIsNull && othIsDefined && othIsReflexive) || (!valIsDefined && othIsReflexive) || !valIsReflexive) { return 1; } if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) || (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) || (othIsNull && valIsDefined && valIsReflexive) || (!othIsDefined && valIsReflexive) || !othIsReflexive) { return -1; } } return 0; } /** * Used by `_.orderBy` to compare multiple properties of a value to another * and stable sort them. * * If `orders` is unspecified, all values are sorted in ascending order. Otherwise, * specify an order of "desc" for descending or "asc" for ascending sort order * of corresponding values. * * @private * @param {Object} object The object to compare. * @param {Object} other The other object to compare. * @param {boolean[]|string[]} orders The order to sort by for each property. * @returns {number} Returns the sort order indicator for `object`. */ function compareMultiple(object, other, orders) { var index = -1, objCriteria = object.criteria, othCriteria = other.criteria, length = objCriteria.length, ordersLength = orders.length; while (++index < length) { var result = compareAscending(objCriteria[index], othCriteria[index]); if (result) { if (index >= ordersLength) { return result; } var order = orders[index]; return result * (order == 'desc' ? -1 : 1); } } // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications // that causes it, under certain circumstances, to provide the same value for // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247 // for more details. // // This also ensures a stable sort in V8 and other engines. // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details. return object.index - other.index; } /** * Creates an array that is the composition of partially applied arguments, * placeholders, and provided arguments into a single array of arguments. * * @private * @param {Array} args The provided arguments. * @param {Array} partials The arguments to prepend to those provided. * @param {Array} holders The `partials` placeholder indexes. * @params {boolean} [isCurried] Specify composing for a curried function. * @returns {Array} Returns the new array of composed arguments. */ function composeArgs(args, partials, holders, isCurried) { var argsIndex = -1, argsLength = args.length, holdersLength = holders.length, leftIndex = -1, leftLength = partials.length, rangeLength = nativeMax(argsLength - holdersLength, 0), result = Array(leftLength + rangeLength), isUncurried = !isCurried; while (++leftIndex < leftLength) { result[leftIndex] = partials[leftIndex]; } while (++argsIndex < holdersLength) { if (isUncurried || argsIndex < argsLength) { result[holders[argsIndex]] = args[argsIndex]; } } while (rangeLength--) { result[leftIndex++] = args[argsIndex++]; } return result; } /** * This function is like `composeArgs` except that the arguments composition * is tailored for `_.partialRight`. * * @private * @param {Array} args The provided arguments. * @param {Array} partials The arguments to append to those provided. * @param {Array} holders The `partials` placeholder indexes. * @params {boolean} [isCurried] Specify composing for a curried function. * @returns {Array} Returns the new array of composed arguments. */ function composeArgsRight(args, partials, holders, isCurried) { var argsIndex = -1, argsLength = args.length, holdersIndex = -1, holdersLength = holders.length, rightIndex = -1, rightLength = partials.length, rangeLength = nativeMax(argsLength - holdersLength, 0), result = Array(rangeLength + rightLength), isUncurried = !isCurried; while (++argsIndex < rangeLength) { result[argsIndex] = args[argsIndex]; } var offset = argsIndex; while (++rightIndex < rightLength) { result[offset + rightIndex] = partials[rightIndex]; } while (++holdersIndex < holdersLength) { if (isUncurried || argsIndex < argsLength) { result[offset + holders[holdersIndex]] = args[argsIndex++]; } } return result; } /** * Copies the values of `source` to `array`. * * @private * @param {Array} source The array to copy values from. * @param {Array} [array=[]] The array to copy values to. * @returns {Array} Returns `array`. */ function copyArray(source, array) { var index = -1, length = source.length; array || (array = Array(length)); while (++index < length) { array[index] = source[index]; } return array; } /** * Copies properties of `source` to `object`. * * @private * @param {Object} source The object to copy properties from. * @param {Array} props The property identifiers to copy. * @param {Object} [object={}] The object to copy properties to. * @param {Function} [customizer] The function to customize copied values. * @returns {Object} Returns `object`. */ function copyObject(source, props, object, customizer) { object || (object = {}); var index = -1, length = props.length; while (++index < length) { var key = props[index]; var newValue = customizer ? customizer(object[key], source[key], key, object, source) : source[key]; assignValue(object, key, newValue); } return object; } /** * Copies own symbol properties of `source` to `object`. * * @private * @param {Object} source The object to copy symbols from. * @param {Object} [object={}] The object to copy symbols to. * @returns {Object} Returns `object`. */ function copySymbols(source, object) { return copyObject(source, getSymbols(source), object); } /** * Creates a function like `_.groupBy`. * * @private * @param {Function} setter The function to set accumulator values. * @param {Function} [initializer] The accumulator object initializer. * @returns {Function} Returns the new aggregator function. */ function createAggregator(setter, initializer) { return function(collection, iteratee) { var func = isArray(collection) ? arrayAggregator : baseAggregator, accumulator = initializer ? initializer() : {}; return func(collection, setter, getIteratee(iteratee), accumulator); }; } /** * Creates a function like `_.assign`. * * @private * @param {Function} assigner The function to assign values. * @returns {Function} Returns the new assigner function. */ function createAssigner(assigner) { return rest(function(object, sources) { var index = -1, length = sources.length, customizer = length > 1 ? sources[length - 1] : undefined, guard = length > 2 ? sources[2] : undefined; customizer = (assigner.length > 3 && typeof customizer == 'function') ? (length--, customizer) : undefined; if (guard && isIterateeCall(sources[0], sources[1], guard)) { customizer = length < 3 ? undefined : customizer; length = 1; } object = Object(object); while (++index < length) { var source = sources[index]; if (source) { assigner(object, source, index, customizer); } } return object; }); } /** * Creates a `baseEach` or `baseEachRight` function. * * @private * @param {Function} eachFunc The function to iterate over a collection. * @param {boolean} [fromRight] Specify iterating from right to left. * @returns {Function} Returns the new base function. */ function createBaseEach(eachFunc, fromRight) { return function(collection, iteratee) { if (collection == null) { return collection; } if (!isArrayLike(collection)) { return eachFunc(collection, iteratee); } var length = collection.length, index = fromRight ? length : -1, iterable = Object(collection); while ((fromRight ? index-- : ++index < length)) { if (iteratee(iterable[index], index, iterable) === false) { break; } } return collection; }; } /** * Creates a base function for methods like `_.forIn` and `_.forOwn`. * * @private * @param {boolean} [fromRight] Specify iterating from right to left. * @returns {Function} Returns the new base function. */ function createBaseFor(fromRight) { return function(object, iteratee, keysFunc) { var index = -1, iterable = Object(object), props = keysFunc(object), length = props.length; while (length--) { var key = props[fromRight ? length : ++index]; if (iteratee(iterable[key], key, iterable) === false) { break; } } return object; }; } /** * Creates a function that wraps `func` to invoke it with the optional `this` * binding of `thisArg`. * * @private * @param {Function} func The function to wrap. * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper` * for more details. * @param {*} [thisArg] The `this` binding of `func`. * @returns {Function} Returns the new wrapped function. */ function createBaseWrapper(func, bitmask, thisArg) { var isBind = bitmask & BIND_FLAG, Ctor = createCtorWrapper(func); function wrapper() { var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; return fn.apply(isBind ? thisArg : this, arguments); } return wrapper; } /** * Creates a function like `_.lowerFirst`. * * @private * @param {string} methodName The name of the `String` case method to use. * @returns {Function} Returns the new case function. */ function createCaseFirst(methodName) { return function(string) { string = toString(string); var strSymbols = reHasComplexSymbol.test(string) ? stringToArray(string) : undefined; var chr = strSymbols ? strSymbols[0] : string.charAt(0); var trailing = strSymbols ? castSlice(strSymbols, 1).join('') : string.slice(1); return chr[methodName]() + trailing; }; } /** * Creates a function like `_.camelCase`. * * @private * @param {Function} callback The function to combine each word. * @returns {Function} Returns the new compounder function. */ function createCompounder(callback) { return function(string) { return arrayReduce(words(deburr(string).replace(reApos, '')), callback, ''); }; } /** * Creates a function that produces an instance of `Ctor` regardless of * whether it was invoked as part of a `new` expression or by `call` or `apply`. * * @private * @param {Function} Ctor The constructor to wrap. * @returns {Function} Returns the new wrapped function. */ function createCtorWrapper(Ctor) { return function() { // Use a `switch` statement to work with class constructors. See // http://ecma-international.org/ecma-262/6.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist // for more details. var args = arguments; switch (args.length) { case 0: return new Ctor; case 1: return new Ctor(args[0]); case 2: return new Ctor(args[0], args[1]); case 3: return new Ctor(args[0], args[1], args[2]); case 4: return new Ctor(args[0], args[1], args[2], args[3]); case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]); case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); } var thisBinding = baseCreate(Ctor.prototype), result = Ctor.apply(thisBinding, args); // Mimic the constructor's `return` behavior. // See https://es5.github.io/#x13.2.2 for more details. return isObject(result) ? result : thisBinding; }; } /** * Creates a function that wraps `func` to enable currying. * * @private * @param {Function} func The function to wrap. * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper` * for more details. * @param {number} arity The arity of `func`. * @returns {Function} Returns the new wrapped function. */ function createCurryWrapper(func, bitmask, arity) { var Ctor = createCtorWrapper(func); function wrapper() { var length = arguments.length, args = Array(length), index = length, placeholder = getHolder(wrapper); while (index--) { args[index] = arguments[index]; } var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder) ? [] : replaceHolders(args, placeholder); length -= holders.length; if (length < arity) { return createRecurryWrapper( func, bitmask, createHybridWrapper, wrapper.placeholder, undefined, args, holders, undefined, undefined, arity - length); } var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; return apply(fn, this, args); } return wrapper; } /** * Creates a `_.flow` or `_.flowRight` function. * * @private * @param {boolean} [fromRight] Specify iterating from right to left. * @returns {Function} Returns the new flow function. */ function createFlow(fromRight) { return rest(function(funcs) { funcs = baseFlatten(funcs, 1); var length = funcs.length, index = length, prereq = LodashWrapper.prototype.thru; if (fromRight) { funcs.reverse(); } while (index--) { var func = funcs[index]; if (typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } if (prereq && !wrapper && getFuncName(func) == 'wrapper') { var wrapper = new LodashWrapper([], true); } } index = wrapper ? index : length; while (++index < length) { func = funcs[index]; var funcName = getFuncName(func), data = funcName == 'wrapper' ? getData(func) : undefined; if (data && isLaziable(data[0]) && data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) && !data[4].length && data[9] == 1 ) { wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); } else { wrapper = (func.length == 1 && isLaziable(func)) ? wrapper[funcName]() : wrapper.thru(func); } } return function() { var args = arguments, value = args[0]; if (wrapper && args.length == 1 && isArray(value) && value.length >= LARGE_ARRAY_SIZE) { return wrapper.plant(value).value(); } var index = 0, result = length ? funcs[index].apply(this, args) : value; while (++index < length) { result = funcs[index].call(this, result); } return result; }; }); } /** * Creates a function that wraps `func` to invoke it with optional `this` * binding of `thisArg`, partial application, and currying. * * @private * @param {Function|string} func The function or method name to wrap. * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper` * for more details. * @param {*} [thisArg] The `this` binding of `func`. * @param {Array} [partials] The arguments to prepend to those provided to * the new function. * @param {Array} [holders] The `partials` placeholder indexes. * @param {Array} [partialsRight] The arguments to append to those provided * to the new function. * @param {Array} [holdersRight] The `partialsRight` placeholder indexes. * @param {Array} [argPos] The argument positions of the new function. * @param {number} [ary] The arity cap of `func`. * @param {number} [arity] The arity of `func`. * @returns {Function} Returns the new wrapped function. */ function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { var isAry = bitmask & ARY_FLAG, isBind = bitmask & BIND_FLAG, isBindKey = bitmask & BIND_KEY_FLAG, isCurried = bitmask & (CURRY_FLAG | CURRY_RIGHT_FLAG), isFlip = bitmask & FLIP_FLAG, Ctor = isBindKey ? undefined : createCtorWrapper(func); function wrapper() { var length = arguments.length, args = Array(length), index = length; while (index--) { args[index] = arguments[index]; } if (isCurried) { var placeholder = getHolder(wrapper), holdersCount = countHolders(args, placeholder); } if (partials) { args = composeArgs(args, partials, holders, isCurried); } if (partialsRight) { args = composeArgsRight(args, partialsRight, holdersRight, isCurried); } length -= holdersCount; if (isCurried && length < arity) { var newHolders = replaceHolders(args, placeholder); return createRecurryWrapper( func, bitmask, createHybridWrapper, wrapper.placeholder, thisArg, args, newHolders, argPos, ary, arity - length ); } var thisBinding = isBind ? thisArg : this, fn = isBindKey ? thisBinding[func] : func; length = args.length; if (argPos) { args = reorder(args, argPos); } else if (isFlip && length > 1) { args.reverse(); } if (isAry && ary < length) { args.length = ary; } if (this && this !== root && this instanceof wrapper) { fn = Ctor || createCtorWrapper(fn); } return fn.apply(thisBinding, args); } return wrapper; } /** * Creates a function like `_.invertBy`. * * @private * @param {Function} setter The function to set accumulator values. * @param {Function} toIteratee The function to resolve iteratees. * @returns {Function} Returns the new inverter function. */ function createInverter(setter, toIteratee) { return function(object, iteratee) { return baseInverter(object, setter, toIteratee(iteratee), {}); }; } /** * Creates a function that performs a mathematical operation on two values. * * @private * @param {Function} operator The function to perform the operation. * @returns {Function} Returns the new mathematical operation function. */ function createMathOperation(operator) { return function(value, other) { var result; if (value === undefined && other === undefined) { return 0; } if (value !== undefined) { result = value; } if (other !== undefined) { if (result === undefined) { return other; } if (typeof value == 'string' || typeof other == 'string') { value = baseToString(value); other = baseToString(other); } else { value = baseToNumber(value); other = baseToNumber(other); } result = operator(value, other); } return result; }; } /** * Creates a function like `_.over`. * * @private * @param {Function} arrayFunc The function to iterate over iteratees. * @returns {Function} Returns the new over function. */ function createOver(arrayFunc) { return rest(function(iteratees) { iteratees = (iteratees.length == 1 && isArray(iteratees[0])) ? arrayMap(iteratees[0], baseUnary(getIteratee())) : arrayMap(baseFlatten(iteratees, 1, isFlattenableIteratee), baseUnary(getIteratee())); return rest(function(args) { var thisArg = this; return arrayFunc(iteratees, function(iteratee) { return apply(iteratee, thisArg, args); }); }); }); } /** * Creates the padding for `string` based on `length`. The `chars` string * is truncated if the number of characters exceeds `length`. * * @private * @param {number} length The padding length. * @param {string} [chars=' '] The string used as padding. * @returns {string} Returns the padding for `string`. */ function createPadding(length, chars) { chars = chars === undefined ? ' ' : baseToString(chars); var charsLength = chars.length; if (charsLength < 2) { return charsLength ? baseRepeat(chars, length) : chars; } var result = baseRepeat(chars, nativeCeil(length / stringSize(chars))); return reHasComplexSymbol.test(chars) ? castSlice(stringToArray(result), 0, length).join('') : result.slice(0, length); } /** * Creates a function that wraps `func` to invoke it with the `this` binding * of `thisArg` and `partials` prepended to the arguments it receives. * * @private * @param {Function} func The function to wrap. * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper` * for more details. * @param {*} thisArg The `this` binding of `func`. * @param {Array} partials The arguments to prepend to those provided to * the new function. * @returns {Function} Returns the new wrapped function. */ function createPartialWrapper(func, bitmask, thisArg, partials) { var isBind = bitmask & BIND_FLAG, Ctor = createCtorWrapper(func); function wrapper() { var argsIndex = -1, argsLength = arguments.length, leftIndex = -1, leftLength = partials.length, args = Array(leftLength + argsLength), fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; while (++leftIndex < leftLength) { args[leftIndex] = partials[leftIndex]; } while (argsLength--) { args[leftIndex++] = arguments[++argsIndex]; } return apply(fn, isBind ? thisArg : this, args); } return wrapper; } /** * Creates a `_.range` or `_.rangeRight` function. * * @private * @param {boolean} [fromRight] Specify iterating from right to left. * @returns {Function} Returns the new range function. */ function createRange(fromRight) { return function(start, end, step) { if (step && typeof step != 'number' && isIterateeCall(start, end, step)) { end = step = undefined; } // Ensure the sign of `-0` is preserved. start = toNumber(start); start = start === start ? start : 0; if (end === undefined) { end = start; start = 0; } else { end = toNumber(end) || 0; } step = step === undefined ? (start < end ? 1 : -1) : (toNumber(step) || 0); return baseRange(start, end, step, fromRight); }; } /** * Creates a function that performs a relational operation on two values. * * @private * @param {Function} operator The function to perform the operation. * @returns {Function} Returns the new relational operation function. */ function createRelationalOperation(operator) { return function(value, other) { if (!(typeof value == 'string' && typeof other == 'string')) { value = toNumber(value); other = toNumber(other); } return operator(value, other); }; } /** * Creates a function that wraps `func` to continue currying. * * @private * @param {Function} func The function to wrap. * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper` * for more details. * @param {Function} wrapFunc The function to create the `func` wrapper. * @param {*} placeholder The placeholder value. * @param {*} [thisArg] The `this` binding of `func`. * @param {Array} [partials] The arguments to prepend to those provided to * the new function. * @param {Array} [holders] The `partials` placeholder indexes. * @param {Array} [argPos] The argument positions of the new function. * @param {number} [ary] The arity cap of `func`. * @param {number} [arity] The arity of `func`. * @returns {Function} Returns the new wrapped function. */ function createRecurryWrapper(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) { var isCurry = bitmask & CURRY_FLAG, newHolders = isCurry ? holders : undefined, newHoldersRight = isCurry ? undefined : holders, newPartials = isCurry ? partials : undefined, newPartialsRight = isCurry ? undefined : partials; bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG); bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); if (!(bitmask & CURRY_BOUND_FLAG)) { bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); } var newData = [ func, bitmask, thisArg, newPartials, newHolders, newPartialsRight, newHoldersRight, argPos, ary, arity ]; var result = wrapFunc.apply(undefined, newData); if (isLaziable(func)) { setData(result, newData); } result.placeholder = placeholder; return result; } /** * Creates a function like `_.round`. * * @private * @param {string} methodName The name of the `Math` method to use when rounding. * @returns {Function} Returns the new round function. */ function createRound(methodName) { var func = Math[methodName]; return function(number, precision) { number = toNumber(number); precision = toInteger(precision); if (precision) { // Shift with exponential notation to avoid floating-point issues. // See [MDN](https://mdn.io/round#Examples) for more details. var pair = (toString(number) + 'e').split('e'), value = func(pair[0] + 'e' + (+pair[1] + precision)); pair = (toString(value) + 'e').split('e'); return +(pair[0] + 'e' + (+pair[1] - precision)); } return func(number); }; } /** * Creates a set of `values`. * * @private * @param {Array} values The values to add to the set. * @returns {Object} Returns the new set. */ var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) { return new Set(values); }; /** * Creates a `_.toPairs` or `_.toPairsIn` function. * * @private * @param {Function} keysFunc The function to get the keys of a given object. * @returns {Function} Returns the new pairs function. */ function createToPairs(keysFunc) { return function(object) { var tag = getTag(object); if (tag == mapTag) { return mapToArray(object); } if (tag == setTag) { return setToPairs(object); } return baseToPairs(object, keysFunc(object)); }; } /** * Creates a function that either curries or invokes `func` with optional * `this` binding and partially applied arguments. * * @private * @param {Function|string} func The function or method name to wrap. * @param {number} bitmask The bitmask of wrapper flags. * The bitmask may be composed of the following flags: * 1 - `_.bind` * 2 - `_.bindKey` * 4 - `_.curry` or `_.curryRight` of a bound function * 8 - `_.curry` * 16 - `_.curryRight` * 32 - `_.partial` * 64 - `_.partialRight` * 128 - `_.rearg` * 256 - `_.ary` * 512 - `_.flip` * @param {*} [thisArg] The `this` binding of `func`. * @param {Array} [partials] The arguments to be partially applied. * @param {Array} [holders] The `partials` placeholder indexes. * @param {Array} [argPos] The argument positions of the new function. * @param {number} [ary] The arity cap of `func`. * @param {number} [arity] The arity of `func`. * @returns {Function} Returns the new wrapped function. */ function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { var isBindKey = bitmask & BIND_KEY_FLAG; if (!isBindKey && typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } var length = partials ? partials.length : 0; if (!length) { bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG); partials = holders = undefined; } ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0); arity = arity === undefined ? arity : toInteger(arity); length -= holders ? holders.length : 0; if (bitmask & PARTIAL_RIGHT_FLAG) { var partialsRight = partials, holdersRight = holders; partials = holders = undefined; } var data = isBindKey ? undefined : getData(func); var newData = [ func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity ]; if (data) { mergeData(newData, data); } func = newData[0]; bitmask = newData[1]; thisArg = newData[2]; partials = newData[3]; holders = newData[4]; arity = newData[9] = newData[9] == null ? (isBindKey ? 0 : func.length) : nativeMax(newData[9] - length, 0); if (!arity && bitmask & (CURRY_FLAG | CURRY_RIGHT_FLAG)) { bitmask &= ~(CURRY_FLAG | CURRY_RIGHT_FLAG); } if (!bitmask || bitmask == BIND_FLAG) { var result = createBaseWrapper(func, bitmask, thisArg); } else if (bitmask == CURRY_FLAG || bitmask == CURRY_RIGHT_FLAG) { result = createCurryWrapper(func, bitmask, arity); } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !holders.length) { result = createPartialWrapper(func, bitmask, thisArg, partials); } else { result = createHybridWrapper.apply(undefined, newData); } var setter = data ? baseSetData : setData; return setter(result, newData); } /** * A specialized version of `baseIsEqualDeep` for arrays with support for * partial deep comparisons. * * @private * @param {Array} array The array to compare. * @param {Array} other The other array to compare. * @param {Function} equalFunc The function to determine equivalents of values. * @param {Function} customizer The function to customize comparisons. * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual` * for more details. * @param {Object} stack Tracks traversed `array` and `other` objects. * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. */ function equalArrays(array, other, equalFunc, customizer, bitmask, stack) { var isPartial = bitmask & PARTIAL_COMPARE_FLAG, arrLength = array.length, othLength = other.length; if (arrLength != othLength && !(isPartial && othLength > arrLength)) { return false; } // Assume cyclic values are equal. var stacked = stack.get(array); if (stacked) { return stacked == other; } var index = -1, result = true, seen = (bitmask & UNORDERED_COMPARE_FLAG) ? new SetCache : undefined; stack.set(array, other); // Ignore non-index properties. while (++index < arrLength) { var arrValue = array[index], othValue = other[index]; if (customizer) { var compared = isPartial ? customizer(othValue, arrValue, index, other, array, stack) : customizer(arrValue, othValue, index, array, other, stack); } if (compared !== undefined) { if (compared) { continue; } result = false; break; } // Recursively compare arrays (susceptible to call stack limits). if (seen) { if (!arraySome(other, function(othValue, othIndex) { if (!seen.has(othIndex) && (arrValue === othValue || equalFunc(arrValue, othValue, customizer, bitmask, stack))) { return seen.add(othIndex); } })) { result = false; break; } } else if (!( arrValue === othValue || equalFunc(arrValue, othValue, customizer, bitmask, stack) )) { result = false; break; } } stack['delete'](array); return result; } /** * A specialized version of `baseIsEqualDeep` for comparing objects of * the same `toStringTag`. * * **Note:** This function only supports comparing values with tags of * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. * * @private * @param {Object} object The object to compare. * @param {Object} other The other object to compare. * @param {string} tag The `toStringTag` of the objects to compare. * @param {Function} equalFunc The function to determine equivalents of values. * @param {Function} customizer The function to customize comparisons. * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual` * for more details. * @param {Object} stack Tracks traversed `object` and `other` objects. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ function equalByTag(object, other, tag, equalFunc, customizer, bitmask, stack) { switch (tag) { case dataViewTag: if ((object.byteLength != other.byteLength) || (object.byteOffset != other.byteOffset)) { return false; } object = object.buffer; other = other.buffer; case arrayBufferTag: if ((object.byteLength != other.byteLength) || !equalFunc(new Uint8Array(object), new Uint8Array(other))) { return false; } return true; case boolTag: case dateTag: // 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 +object == +other; case errorTag: return object.name == other.name && object.message == other.message; case numberTag: // Treat `NaN` vs. `NaN` as equal. return (object != +object) ? other != +other : object == +other; case regexpTag: case stringTag: // Coerce regexes to strings and treat strings, primitives and objects, // as equal. See http://www.ecma-international.org/ecma-262/6.0/#sec-regexp.prototype.tostring // for more details. return object == (other + ''); case mapTag: var convert = mapToArray; case setTag: var isPartial = bitmask & PARTIAL_COMPARE_FLAG; convert || (convert = setToArray); if (object.size != other.size && !isPartial) { return false; } // Assume cyclic values are equal. var stacked = stack.get(object); if (stacked) { return stacked == other; } bitmask |= UNORDERED_COMPARE_FLAG; stack.set(object, other); // Recursively compare objects (susceptible to call stack limits). return equalArrays(convert(object), convert(other), equalFunc, customizer, bitmask, stack); case symbolTag: if (symbolValueOf) { return symbolValueOf.call(object) == symbolValueOf.call(other); } } return false; } /** * A specialized version of `baseIsEqualDeep` for objects with support for * partial deep comparisons. * * @private * @param {Object} object The object to compare. * @param {Object} other The other object to compare. * @param {Function} equalFunc The function to determine equivalents of values. * @param {Function} customizer The function to customize comparisons. * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual` * for more details. * @param {Object} stack Tracks traversed `object` and `other` objects. * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. */ function equalObjects(object, other, equalFunc, customizer, bitmask, stack) { var isPartial = bitmask & PARTIAL_COMPARE_FLAG, objProps = keys(object), objLength = objProps.length, othProps = keys(other), othLength = othProps.length; if (objLength != othLength && !isPartial) { return false; } var index = objLength; while (index--) { var key = objProps[index]; if (!(isPartial ? key in other : baseHas(other, key))) { return false; } } // Assume cyclic values are equal. var stacked = stack.get(object); if (stacked) { return stacked == other; } var result = true; stack.set(object, other); var skipCtor = isPartial; while (++index < objLength) { key = objProps[index]; var objValue = object[key], othValue = other[key]; if (customizer) { var compared = isPartial ? customizer(othValue, objValue, key, other, object, stack) : customizer(objValue, othValue, key, object, other, stack); } // Recursively compare objects (susceptible to call stack limits). if (!(compared === undefined ? (objValue === othValue || equalFunc(objValue, othValue, customizer, bitmask, stack)) : compared )) { result = false; break; } skipCtor || (skipCtor = key == 'constructor'); } if (result && !skipCtor) { var objCtor = object.constructor, othCtor = other.constructor; // Non `Object` object instances with different constructors are not equal. if (objCtor != othCtor && ('constructor' in object && 'constructor' in other) && !(typeof objCtor == 'function' && objCtor instanceof objCtor && typeof othCtor == 'function' && othCtor instanceof othCtor)) { result = false; } } stack['delete'](object); return result; } /** * Creates an array of own enumerable property names and symbols of `object`. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the array of property names and symbols. */ function getAllKeys(object) { return baseGetAllKeys(object, keys, getSymbols); } /** * Creates an array of own and inherited enumerable property names and * symbols of `object`. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the array of property names and symbols. */ function getAllKeysIn(object) { return baseGetAllKeys(object, keysIn, getSymbolsIn); } /** * Gets metadata for `func`. * * @private * @param {Function} func The function to query. * @returns {*} Returns the metadata for `func`. */ var getData = !metaMap ? noop : function(func) { return metaMap.get(func); }; /** * Gets the name of `func`. * * @private * @param {Function} func The function to query. * @returns {string} Returns the function name. */ function getFuncName(func) { var result = (func.name + ''), array = realNames[result], length = hasOwnProperty.call(realNames, result) ? array.length : 0; while (length--) { var data = array[length], otherFunc = data.func; if (otherFunc == null || otherFunc == func) { return data.name; } } return result; } /** * Gets the argument placeholder value for `func`. * * @private * @param {Function} func The function to inspect. * @returns {*} Returns the placeholder value. */ function getHolder(func) { var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func; return object.placeholder; } /** * Gets the appropriate "iteratee" function. If `_.iteratee` is customized, * this function returns the custom method, otherwise it returns `baseIteratee`. * If arguments are provided, the chosen function is invoked with them and * its result is returned. * * @private * @param {*} [value] The value to convert to an iteratee. * @param {number} [arity] The arity of the created iteratee. * @returns {Function} Returns the chosen function or its result. */ function getIteratee() { var result = lodash.iteratee || iteratee; result = result === iteratee ? baseIteratee : result; return arguments.length ? result(arguments[0], arguments[1]) : result; } /** * Gets the "length" property value of `object`. * * **Note:** This function is used to avoid a * [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792) that affects * Safari on at least iOS 8.1-8.3 ARM64. * * @private * @param {Object} object The object to query. * @returns {*} Returns the "length" value. */ var getLength = baseProperty('length'); /** * Gets the data for `map`. * * @private * @param {Object} map The map to query. * @param {string} key The reference key. * @returns {*} Returns the map data. */ function getMapData(map, key) { var data = map.__data__; return isKeyable(key) ? data[typeof key == 'string' ? 'string' : 'hash'] : data.map; } /** * Gets the property names, values, and compare flags of `object`. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the match data of `object`. */ function getMatchData(object) { var result = toPairs(object), length = result.length; while (length--) { result[length][2] = isStrictComparable(result[length][1]); } return result; } /** * Gets the native function at `key` of `object`. * * @private * @param {Object} object The object to query. * @param {string} key The key of the method to get. * @returns {*} Returns the function if it's native, else `undefined`. */ function getNative(object, key) { var value = object[key]; return isNative(value) ? value : undefined; } /** * Gets the `[[Prototype]]` of `value`. * * @private * @param {*} value The value to query. * @returns {null|Object} Returns the `[[Prototype]]`. */ function getPrototype(value) { return nativeGetPrototype(Object(value)); } /** * Creates an array of the own enumerable symbol properties of `object`. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the array of symbols. */ function getSymbols(object) { // Coerce `object` to an object to avoid non-object errors in V8. // See https://bugs.chromium.org/p/v8/issues/detail?id=3443 for more details. return getOwnPropertySymbols(Object(object)); } // Fallback for IE < 11. if (!getOwnPropertySymbols) { getSymbols = function() { return []; }; } /** * Creates an array of the own and inherited enumerable symbol properties * of `object`. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the array of symbols. */ var getSymbolsIn = !getOwnPropertySymbols ? getSymbols : function(object) { var result = []; while (object) { arrayPush(result, getSymbols(object)); object = getPrototype(object); } return result; }; /** * Gets the `toStringTag` of `value`. * * @private * @param {*} value The value to query. * @returns {string} Returns the `toStringTag`. */ function getTag(value) { return objectToString.call(value); } // Fallback for data views, maps, sets, and weak maps in IE 11, // for data views in Edge, and promises in Node.js. if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) || (Map && getTag(new Map) != mapTag) || (Promise && getTag(Promise.resolve()) != promiseTag) || (Set && getTag(new Set) != setTag) || (WeakMap && getTag(new WeakMap) != weakMapTag)) { getTag = function(value) { var result = objectToString.call(value), Ctor = result == objectTag ? value.constructor : undefined, ctorString = Ctor ? toSource(Ctor) : undefined; if (ctorString) { switch (ctorString) { case dataViewCtorString: return dataViewTag; case mapCtorString: return mapTag; case promiseCtorString: return promiseTag; case setCtorString: return setTag; case weakMapCtorString: return weakMapTag; } } return result; }; } /** * Gets the view, applying any `transforms` to the `start` and `end` positions. * * @private * @param {number} start The start of the view. * @param {number} end The end of the view. * @param {Array} transforms The transformations to apply to the view. * @returns {Object} Returns an object containing the `start` and `end` * positions of the view. */ function getView(start, end, transforms) { var index = -1, length = transforms.length; while (++index < length) { var data = transforms[index], size = data.size; switch (data.type) { case 'drop': start += size; break; case 'dropRight': end -= size; break; case 'take': end = nativeMin(end, start + size); break; case 'takeRight': start = nativeMax(start, end - size); break; } } return { 'start': start, 'end': end }; } /** * Checks if `path` exists on `object`. * * @private * @param {Object} object The object to query. * @param {Array|string} path The path to check. * @param {Function} hasFunc The function to check properties. * @returns {boolean} Returns `true` if `path` exists, else `false`. */ function hasPath(object, path, hasFunc) { path = isKey(path, object) ? [path] : castPath(path); var result, index = -1, length = path.length; while (++index < length) { var key = toKey(path[index]); if (!(result = object != null && hasFunc(object, key))) { break; } object = object[key]; } if (result) { return result; } var length = object ? object.length : 0; return !!length && isLength(length) && isIndex(key, length) && (isArray(object) || isString(object) || isArguments(object)); } /** * Initializes an array clone. * * @private * @param {Array} array The array to clone. * @returns {Array} Returns the initialized clone. */ function initCloneArray(array) { var length = array.length, result = array.constructor(length); // Add properties assigned by `RegExp#exec`. if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) { result.index = array.index; result.input = array.input; } return result; } /** * Initializes an object clone. * * @private * @param {Object} object The object to clone. * @returns {Object} Returns the initialized clone. */ function initCloneObject(object) { return (typeof object.constructor == 'function' && !isPrototype(object)) ? baseCreate(getPrototype(object)) : {}; } /** * Initializes an object clone based on its `toStringTag`. * * **Note:** This function only supports cloning values with tags of * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. * * @private * @param {Object} object The object to clone. * @param {string} tag The `toStringTag` of the object to clone. * @param {Function} cloneFunc The function to clone values. * @param {boolean} [isDeep] Specify a deep clone. * @returns {Object} Returns the initialized clone. */ function initCloneByTag(object, tag, cloneFunc, isDeep) { var Ctor = object.constructor; switch (tag) { case arrayBufferTag: return cloneArrayBuffer(object); case boolTag: case dateTag: return new Ctor(+object); case dataViewTag: return cloneDataView(object, isDeep); case float32Tag: case float64Tag: case int8Tag: case int16Tag: case int32Tag: case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag: return cloneTypedArray(object, isDeep); case mapTag: return cloneMap(object, isDeep, cloneFunc); case numberTag: case stringTag: return new Ctor(object); case regexpTag: return cloneRegExp(object); case setTag: return cloneSet(object, isDeep, cloneFunc); case symbolTag: return cloneSymbol(object); } } /** * Creates an array of index keys for `object` values of arrays, * `arguments` objects, and strings, otherwise `null` is returned. * * @private * @param {Object} object The object to query. * @returns {Array|null} Returns index keys, else `null`. */ function indexKeys(object) { var length = object ? object.length : undefined; if (isLength(length) && (isArray(object) || isString(object) || isArguments(object))) { return baseTimes(length, String); } return null; } /** * Checks if `value` is a flattenable `arguments` object or array. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is flattenable, else `false`. */ function isFlattenable(value) { return isArray(value) || isArguments(value); } /** * Checks if `value` is a flattenable array and not a `_.matchesProperty` * iteratee shorthand. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is flattenable, else `false`. */ function isFlattenableIteratee(value) { return isArray(value) && !(value.length == 2 && !isFunction(value[0])); } /** * Checks if `value` is a valid array-like index. * * @private * @param {*} value The value to check. * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. */ function isIndex(value, length) { length = length == null ? MAX_SAFE_INTEGER : length; return !!length && (typeof value == 'number' || reIsUint.test(value)) && (value > -1 && value % 1 == 0 && value < length); } /** * Checks if the given arguments are from an iteratee call. * * @private * @param {*} value The potential iteratee value argument. * @param {*} index The potential iteratee index or key argument. * @param {*} object The potential iteratee object argument. * @returns {boolean} Returns `true` if the arguments are from an iteratee call, * else `false`. */ function isIterateeCall(value, index, object) { if (!isObject(object)) { return false; } var type = typeof index; if (type == 'number' ? (isArrayLike(object) && isIndex(index, object.length)) : (type == 'string' && index in object) ) { return eq(object[index], value); } return false; } /** * Checks if `value` is a property name and not a property path. * * @private * @param {*} value The value to check. * @param {Object} [object] The object to query keys on. * @returns {boolean} Returns `true` if `value` is a property name, else `false`. */ function isKey(value, object) { if (isArray(value)) { return false; } var type = typeof value; if (type == 'number' || type == 'symbol' || type == 'boolean' || value == null || isSymbol(value)) { return true; } return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || (object != null && value in Object(object)); } /** * Checks if `value` is suitable for use as unique object key. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is suitable, else `false`. */ function isKeyable(value) { var type = typeof value; return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') ? (value !== '__proto__') : (value === null); } /** * Checks if `func` has a lazy counterpart. * * @private * @param {Function} func The function to check. * @returns {boolean} Returns `true` if `func` has a lazy counterpart, * else `false`. */ function isLaziable(func) { var funcName = getFuncName(func), other = lodash[funcName]; if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) { return false; } if (func === other) { return true; } var data = getData(other); return !!data && func === data[0]; } /** * Checks if `value` is likely a prototype object. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a prototype, else `false`. */ function isPrototype(value) { var Ctor = value && value.constructor, proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto; return value === proto; } /** * Checks if `value` is suitable for strict equality comparisons, i.e. `===`. * * @private * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` if suitable for strict * equality comparisons, else `false`. */ function isStrictComparable(value) { return value === value && !isObject(value); } /** * A specialized version of `matchesProperty` for source values suitable * for strict equality comparisons, i.e. `===`. * * @private * @param {string} key The key of the property to get. * @param {*} srcValue The value to match. * @returns {Function} Returns the new spec function. */ function matchesStrictComparable(key, srcValue) { return function(object) { if (object == null) { return false; } return object[key] === srcValue && (srcValue !== undefined || (key in Object(object))); }; } /** * Merges the function metadata of `source` into `data`. * * Merging metadata reduces the number of wrappers used to invoke a function. * This is possible because methods like `_.bind`, `_.curry`, and `_.partial` * may be applied regardless of execution order. Methods like `_.ary` and * `_.rearg` modify function arguments, making the order in which they are * executed important, preventing the merging of metadata. However, we make * an exception for a safe combined case where curried functions have `_.ary` * and or `_.rearg` applied. * * @private * @param {Array} data The destination metadata. * @param {Array} source The source metadata. * @returns {Array} Returns `data`. */ function mergeData(data, source) { var bitmask = data[1], srcBitmask = source[1], newBitmask = bitmask | srcBitmask, isCommon = newBitmask < (BIND_FLAG | BIND_KEY_FLAG | ARY_FLAG); var isCombo = ((srcBitmask == ARY_FLAG) && (bitmask == CURRY_FLAG)) || ((srcBitmask == ARY_FLAG) && (bitmask == REARG_FLAG) && (data[7].length <= source[8])) || ((srcBitmask == (ARY_FLAG | REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == CURRY_FLAG)); // Exit early if metadata can't be merged. if (!(isCommon || isCombo)) { return data; } // Use source `thisArg` if available. if (srcBitmask & BIND_FLAG) { data[2] = source[2]; // Set when currying a bound function. newBitmask |= bitmask & BIND_FLAG ? 0 : CURRY_BOUND_FLAG; } // Compose partial arguments. var value = source[3]; if (value) { var partials = data[3]; data[3] = partials ? composeArgs(partials, value, source[4]) : value; data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4]; } // Compose partial right arguments. value = source[5]; if (value) { partials = data[5]; data[5] = partials ? composeArgsRight(partials, value, source[6]) : value; data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6]; } // Use source `argPos` if available. value = source[7]; if (value) { data[7] = value; } // Use source `ary` if it's smaller. if (srcBitmask & ARY_FLAG) { data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); } // Use source `arity` if one is not provided. if (data[9] == null) { data[9] = source[9]; } // Use source `func` and merge bitmasks. data[0] = source[0]; data[1] = newBitmask; return data; } /** * Used by `_.defaultsDeep` to customize its `_.merge` use. * * @private * @param {*} objValue The destination value. * @param {*} srcValue The source value. * @param {string} key The key of the property to merge. * @param {Object} object The parent object of `objValue`. * @param {Object} source The parent object of `srcValue`. * @param {Object} [stack] Tracks traversed source values and their merged * counterparts. * @returns {*} Returns the value to assign. */ function mergeDefaults(objValue, srcValue, key, object, source, stack) { if (isObject(objValue) && isObject(srcValue)) { baseMerge(objValue, srcValue, undefined, mergeDefaults, stack.set(srcValue, objValue)); } return objValue; } /** * Gets the parent value at `path` of `object`. * * @private * @param {Object} object The object to query. * @param {Array} path The path to get the parent value of. * @returns {*} Returns the parent value. */ function parent(object, path) { return path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); } /** * Reorder `array` according to the specified indexes where the element at * the first index is assigned as the first element, the element at * the second index is assigned as the second element, and so on. * * @private * @param {Array} array The array to reorder. * @param {Array} indexes The arranged array indexes. * @returns {Array} Returns `array`. */ function reorder(array, indexes) { var arrLength = array.length, length = nativeMin(indexes.length, arrLength), oldArray = copyArray(array); while (length--) { var index = indexes[length]; array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; } return array; } /** * Sets metadata for `func`. * * **Note:** If this function becomes hot, i.e. is invoked a lot in a short * period of time, it will trip its breaker and transition to an identity * function to avoid garbage collection pauses in V8. See * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070) * for more details. * * @private * @param {Function} func The function to associate metadata with. * @param {*} data The metadata. * @returns {Function} Returns `func`. */ var setData = (function() { var count = 0, lastCalled = 0; return function(key, value) { var stamp = now(), remaining = HOT_SPAN - (stamp - lastCalled); lastCalled = stamp; if (remaining > 0) { if (++count >= HOT_COUNT) { return key; } } else { count = 0; } return baseSetData(key, value); }; }()); /** * Converts `string` to a property path array. * * @private * @param {string} string The string to convert. * @returns {Array} Returns the property path array. */ var stringToPath = memoize(function(string) { var result = []; toString(string).replace(rePropName, function(match, number, quote, string) { result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match)); }); return result; }); /** * Converts `value` to a string key if it's not a string or symbol. * * @private * @param {*} value The value to inspect. * @returns {string|symbol} Returns the key. */ function toKey(value) { if (typeof value == 'string' || isSymbol(value)) { return value; } var result = (value + ''); return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; } /** * Converts `func` to its source code. * * @private * @param {Function} func The function to process. * @returns {string} Returns the source code. */ function toSource(func) { if (func != null) { try { return funcToString.call(func); } catch (e) {} try { return (func + ''); } catch (e) {} } return ''; } /** * Creates a clone of `wrapper`. * * @private * @param {Object} wrapper The wrapper to clone. * @returns {Object} Returns the cloned wrapper. */ function wrapperClone(wrapper) { if (wrapper instanceof LazyWrapper) { return wrapper.clone(); } var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__); result.__actions__ = copyArray(wrapper.__actions__); result.__index__ = wrapper.__index__; result.__values__ = wrapper.__values__; return result; } /*------------------------------------------------------------------------*/ /** * Creates an array of elements split into groups the length of `size`. * If `array` can't be split evenly, the final chunk will be the remaining * elements. * * @static * @memberOf _ * @since 3.0.0 * @category Array * @param {Array} array The array to process. * @param {number} [size=1] The length of each chunk * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. * @returns {Array} Returns the new array of chunks. * @example * * _.chunk(['a', 'b', 'c', 'd'], 2); * // => [['a', 'b'], ['c', 'd']] * * _.chunk(['a', 'b', 'c', 'd'], 3); * // => [['a', 'b', 'c'], ['d']] */ function chunk(array, size, guard) { if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) { size = 1; } else { size = nativeMax(toInteger(size), 0); } var length = array ? array.length : 0; if (!length || size < 1) { return []; } var index = 0, resIndex = 0, result = Array(nativeCeil(length / size)); while (index < length) { result[resIndex++] = baseSlice(array, index, (index += size)); } return result; } /** * Creates an array with all falsey values removed. The values `false`, `null`, * `0`, `""`, `undefined`, and `NaN` are falsey. * * @static * @memberOf _ * @since 0.1.0 * @category Array * @param {Array} array The array to compact. * @returns {Array} Returns the new array of filtered values. * @example * * _.compact([0, 1, false, 2, '', 3]); * // => [1, 2, 3] */ function compact(array) { var index = -1, length = array ? array.length : 0, resIndex = 0, result = []; while (++index < length) { var value = array[index]; if (value) { result[resIndex++] = value; } } return result; } /** * Creates a new array concatenating `array` with any additional arrays * and/or values. * * @static * @memberOf _ * @since 4.0.0 * @category Array * @param {Array} array The array to concatenate. * @param {...*} [values] The values to concatenate. * @returns {Array} Returns the new concatenated array. * @example * * var array = [1]; * var other = _.concat(array, 2, [3], [[4]]); * * console.log(other); * // => [1, 2, 3, [4]] * * console.log(array); * // => [1] */ function concat() { var length = arguments.length, args = Array(length ? length - 1 : 0), array = arguments[0], index = length; while (index--) { args[index - 1] = arguments[index]; } return length ? arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1)) : []; } /** * Creates an array of unique `array` values not included in the other given * arrays using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. The order of result values is determined by the * order they occur in the first array. * * @static * @memberOf _ * @since 0.1.0 * @category Array * @param {Array} array The array to inspect. * @param {...Array} [values] The values to exclude. * @returns {Array} Returns the new array of filtered values. * @see _.without, _.xor * @example * * _.difference([3, 2, 1], [4, 2]); * // => [3, 1] */ var difference = rest(function(array, values) { return isArrayLikeObject(array) ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true)) : []; }); /** * This method is like `_.difference` except that it accepts `iteratee` which * is invoked for each element of `array` and `values` to generate the criterion * by which they're compared. Result values are chosen from the first array. * The iteratee is invoked with one argument: (value). * * @static * @memberOf _ * @since 4.0.0 * @category Array * @param {Array} array The array to inspect. * @param {...Array} [values] The values to exclude. * @param {Array|Function|Object|string} [iteratee=_.identity] * The iteratee invoked per element. * @returns {Array} Returns the new array of filtered values. * @example * * _.differenceBy([3.1, 2.2, 1.3], [4.4, 2.5], Math.floor); * // => [3.1, 1.3] * * // The `_.property` iteratee shorthand. * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x'); * // => [{ 'x': 2 }] */ var differenceBy = rest(function(array, values) { var iteratee = last(values); if (isArrayLikeObject(iteratee)) { iteratee = undefined; } return isArrayLikeObject(array) ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee)) : []; }); /** * This method is like `_.difference` except that it accepts `comparator` * which is invoked to compare elements of `array` to `values`. Result values * are chosen from the first array. The comparator is invoked with two arguments: * (arrVal, othVal). * * @static * @memberOf _ * @since 4.0.0 * @category Array * @param {Array} array The array to inspect. * @param {...Array} [values] The values to exclude. * @param {Function} [comparator] The comparator invoked per element. * @returns {Array} Returns the new array of filtered values. * @example * * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; * * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual); * // => [{ 'x': 2, 'y': 1 }] */ var differenceWith = rest(function(array, values) { var comparator = last(values); if (isArrayLikeObject(comparator)) { comparator = undefined; } return isArrayLikeObject(array) ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined, comparator) : []; }); /** * Creates a slice of `array` with `n` elements dropped from the beginning. * * @static * @memberOf _ * @since 0.5.0 * @category Array * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to drop. * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. * @returns {Array} Returns the slice of `array`. * @example * * _.drop([1, 2, 3]); * // => [2, 3] * * _.drop([1, 2, 3], 2); * // => [3] * * _.drop([1, 2, 3], 5); * // => [] * * _.drop([1, 2, 3], 0); * // => [1, 2, 3] */ function drop(array, n, guard) { var length = array ? array.length : 0; if (!length) { return []; } n = (guard || n === undefined) ? 1 : toInteger(n); return baseSlice(array, n < 0 ? 0 : n, length); } /** * Creates a slice of `array` with `n` elements dropped from the end. * * @static * @memberOf _ * @since 3.0.0 * @category Array * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to drop. * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. * @returns {Array} Returns the slice of `array`. * @example * * _.dropRight([1, 2, 3]); * // => [1, 2] * * _.dropRight([1, 2, 3], 2); * // => [1] * * _.dropRight([1, 2, 3], 5); * // => [] * * _.dropRight([1, 2, 3], 0); * // => [1, 2, 3] */ function dropRight(array, n, guard) { var length = array ? array.length : 0; if (!length) { return []; } n = (guard || n === undefined) ? 1 : toInteger(n); n = length - n; return baseSlice(array, 0, n < 0 ? 0 : n); } /** * Creates a slice of `array` excluding elements dropped from the end. * Elements are dropped until `predicate` returns falsey. The predicate is * invoked with three arguments: (value, index, array). * * @static * @memberOf _ * @since 3.0.0 * @category Array * @param {Array} array The array to query. * @param {Array|Function|Object|string} [predicate=_.identity] * The function invoked per iteration. * @returns {Array} Returns the slice of `array`. * @example * * var users = [ * { 'user': 'barney', 'active': true }, * { 'user': 'fred', 'active': false }, * { 'user': 'pebbles', 'active': false } * ]; * * _.dropRightWhile(users, function(o) { return !o.active; }); * // => objects for ['barney'] * * // The `_.matches` iteratee shorthand. * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false }); * // => objects for ['barney', 'fred'] * * // The `_.matchesProperty` iteratee shorthand. * _.dropRightWhile(users, ['active', false]); * // => objects for ['barney'] * * // The `_.property` iteratee shorthand. * _.dropRightWhile(users, 'active'); * // => objects for ['barney', 'fred', 'pebbles'] */ function dropRightWhile(array, predicate) { return (array && array.length) ? baseWhile(array, getIteratee(predicate, 3), true, true) : []; } /** * Creates a slice of `array` excluding elements dropped from the beginning. * Elements are dropped until `predicate` returns falsey. The predicate is * invoked with three arguments: (value, index, array). * * @static * @memberOf _ * @since 3.0.0 * @category Array * @param {Array} array The array to query. * @param {Array|Function|Object|string} [predicate=_.identity] * The function invoked per iteration. * @returns {Array} Returns the slice of `array`. * @example * * var users = [ * { 'user': 'barney', 'active': false }, * { 'user': 'fred', 'active': false }, * { 'user': 'pebbles', 'active': true } * ]; * * _.dropWhile(users, function(o) { return !o.active; }); * // => objects for ['pebbles'] * * // The `_.matches` iteratee shorthand. * _.dropWhile(users, { 'user': 'barney', 'active': false }); * // => objects for ['fred', 'pebbles'] * * // The `_.matchesProperty` iteratee shorthand. * _.dropWhile(users, ['active', false]); * // => objects for ['pebbles'] * * // The `_.property` iteratee shorthand. * _.dropWhile(users, 'active'); * // => objects for ['barney', 'fred', 'pebbles'] */ function dropWhile(array, predicate) { return (array && array.length) ? baseWhile(array, getIteratee(predicate, 3), true) : []; } /** * Fills elements of `array` with `value` from `start` up to, but not * including, `end`. * * **Note:** This method mutates `array`. * * @static * @memberOf _ * @since 3.2.0 * @category Array * @param {Array} array The array to fill. * @param {*} value The value to fill `array` with. * @param {number} [start=0] The start position. * @param {number} [end=array.length] The end position. * @returns {Array} Returns `array`. * @example * * var array = [1, 2, 3]; * * _.fill(array, 'a'); * console.log(array); * // => ['a', 'a', 'a'] * * _.fill(Array(3), 2); * // => [2, 2, 2] * * _.fill([4, 6, 8, 10], '*', 1, 3); * // => [4, '*', '*', 10] */ function fill(array, value, start, end) { var length = array ? array.length : 0; if (!length) { return []; } if (start && typeof start != 'number' && isIterateeCall(array, value, start)) { start = 0; end = length; } return baseFill(array, value, start, end); } /** * This method is like `_.find` except that it returns the index of the first * element `predicate` returns truthy for instead of the element itself. * * @static * @memberOf _ * @since 1.1.0 * @category Array * @param {Array} array The array to search. * @param {Array|Function|Object|string} [predicate=_.identity] * The function invoked per iteration. * @returns {number} Returns the index of the found element, else `-1`. * @example * * var users = [ * { 'user': 'barney', 'active': false }, * { 'user': 'fred', 'active': false }, * { 'user': 'pebbles', 'active': true } * ]; * * _.findIndex(users, function(o) { return o.user == 'barney'; }); * // => 0 * * // The `_.matches` iteratee shorthand. * _.findIndex(users, { 'user': 'fred', 'active': false }); * // => 1 * * // The `_.matchesProperty` iteratee shorthand. * _.findIndex(users, ['active', false]); * // => 0 * * // The `_.property` iteratee shorthand. * _.findIndex(users, 'active'); * // => 2 */ function findIndex(array, predicate) { return (array && array.length) ? baseFindIndex(array, getIteratee(predicate, 3)) : -1; } /** * This method is like `_.findIndex` except that it iterates over elements * of `collection` from right to left. * * @static * @memberOf _ * @since 2.0.0 * @category Array * @param {Array} array The array to search. * @param {Array|Function|Object|string} [predicate=_.identity] * The function invoked per iteration. * @returns {number} Returns the index of the found element, else `-1`. * @example * * var users = [ * { 'user': 'barney', 'active': true }, * { 'user': 'fred', 'active': false }, * { 'user': 'pebbles', 'active': false } * ]; * * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; }); * // => 2 * * // The `_.matches` iteratee shorthand. * _.findLastIndex(users, { 'user': 'barney', 'active': true }); * // => 0 * * // The `_.matchesProperty` iteratee shorthand. * _.findLastIndex(users, ['active', false]); * // => 2 * * // The `_.property` iteratee shorthand. * _.findLastIndex(users, 'active'); * // => 0 */ function findLastIndex(array, predicate) { return (array && array.length) ? baseFindIndex(array, getIteratee(predicate, 3), true) : -1; } /** * Flattens `array` a single level deep. * * @static * @memberOf _ * @since 0.1.0 * @category Array * @param {Array} array The array to flatten. * @returns {Array} Returns the new flattened array. * @example * * _.flatten([1, [2, [3, [4]], 5]]); * // => [1, 2, [3, [4]], 5] */ function flatten(array) { var length = array ? array.length : 0; return length ? baseFlatten(array, 1) : []; } /** * Recursively flattens `array`. * * @static * @memberOf _ * @since 3.0.0 * @category Array * @param {Array} array The array to flatten. * @returns {Array} Returns the new flattened array. * @example * * _.flattenDeep([1, [2, [3, [4]], 5]]); * // => [1, 2, 3, 4, 5] */ function flattenDeep(array) { var length = array ? array.length : 0; return length ? baseFlatten(array, INFINITY) : []; } /** * Recursively flatten `array` up to `depth` times. * * @static * @memberOf _ * @since 4.4.0 * @category Array * @param {Array} array The array to flatten. * @param {number} [depth=1] The maximum recursion depth. * @returns {Array} Returns the new flattened array. * @example * * var array = [1, [2, [3, [4]], 5]]; * * _.flattenDepth(array, 1); * // => [1, 2, [3, [4]], 5] * * _.flattenDepth(array, 2); * // => [1, 2, 3, [4], 5] */ function flattenDepth(array, depth) { var length = array ? array.length : 0; if (!length) { return []; } depth = depth === undefined ? 1 : toInteger(depth); return baseFlatten(array, depth); } /** * The inverse of `_.toPairs`; this method returns an object composed * from key-value `pairs`. * * @static * @memberOf _ * @since 4.0.0 * @category Array * @param {Array} pairs The key-value pairs. * @returns {Object} Returns the new object. * @example * * _.fromPairs([['fred', 30], ['barney', 40]]); * // => { 'fred': 30, 'barney': 40 } */ function fromPairs(pairs) { var index = -1, length = pairs ? pairs.length : 0, result = {}; while (++index < length) { var pair = pairs[index]; result[pair[0]] = pair[1]; } return result; } /** * Gets the first element of `array`. * * @static * @memberOf _ * @since 0.1.0 * @alias first * @category Array * @param {Array} array The array to query. * @returns {*} Returns the first element of `array`. * @example * * _.head([1, 2, 3]); * // => 1 * * _.head([]); * // => undefined */ function head(array) { return (array && array.length) ? array[0] : undefined; } /** * Gets the index at which the first occurrence of `value` is found in `array` * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. If `fromIndex` is negative, it's used as the * offset from the end of `array`. * * @static * @memberOf _ * @since 0.1.0 * @category Array * @param {Array} array The array to search. * @param {*} value The value to search for. * @param {number} [fromIndex=0] The index to search from. * @returns {number} Returns the index of the matched value, else `-1`. * @example * * _.indexOf([1, 2, 1, 2], 2); * // => 1 * * // Search from the `fromIndex`. * _.indexOf([1, 2, 1, 2], 2, 2); * // => 3 */ function indexOf(array, value, fromIndex) { var length = array ? array.length : 0; if (!length) { return -1; } fromIndex = toInteger(fromIndex); if (fromIndex < 0) { fromIndex = nativeMax(length + fromIndex, 0); } return baseIndexOf(array, value, fromIndex); } /** * Gets all but the last element of `array`. * * @static * @memberOf _ * @since 0.1.0 * @category Array * @param {Array} array The array to query. * @returns {Array} Returns the slice of `array`. * @example * * _.initial([1, 2, 3]); * // => [1, 2] */ function initial(array) { return dropRight(array, 1); } /** * Creates an array of unique values that are included in all given arrays * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. The order of result values is determined by the * order they occur in the first array. * * @static * @memberOf _ * @since 0.1.0 * @category Array * @param {...Array} [arrays] The arrays to inspect. * @returns {Array} Returns the new array of intersecting values. * @example * * _.intersection([2, 1], [4, 2], [1, 2]); * // => [2] */ var intersection = rest(function(arrays) { var mapped = arrayMap(arrays, castArrayLikeObject); return (mapped.length && mapped[0] === arrays[0]) ? baseIntersection(mapped) : []; }); /** * This method is like `_.intersection` except that it accepts `iteratee` * which is invoked for each element of each `arrays` to generate the criterion * by which they're compared. Result values are chosen from the first array. * The iteratee is invoked with one argument: (value). * * @static * @memberOf _ * @since 4.0.0 * @category Array * @param {...Array} [arrays] The arrays to inspect. * @param {Array|Function|Object|string} [iteratee=_.identity] * The iteratee invoked per element. * @returns {Array} Returns the new array of intersecting values. * @example * * _.intersectionBy([2.1, 1.2], [4.3, 2.4], Math.floor); * // => [2.1] * * // The `_.property` iteratee shorthand. * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); * // => [{ 'x': 1 }] */ var intersectionBy = rest(function(arrays) { var iteratee = last(arrays), mapped = arrayMap(arrays, castArrayLikeObject); if (iteratee === last(mapped)) { iteratee = undefined; } else { mapped.pop(); } return (mapped.length && mapped[0] === arrays[0]) ? baseIntersection(mapped, getIteratee(iteratee)) : []; }); /** * This method is like `_.intersection` except that it accepts `comparator` * which is invoked to compare elements of `arrays`. Result values are chosen * from the first array. The comparator is invoked with two arguments: * (arrVal, othVal). * * @static * @memberOf _ * @since 4.0.0 * @category Array * @param {...Array} [arrays] The arrays to inspect. * @param {Function} [comparator] The comparator invoked per element. * @returns {Array} Returns the new array of intersecting values. * @example * * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; * * _.intersectionWith(objects, others, _.isEqual); * // => [{ 'x': 1, 'y': 2 }] */ var intersectionWith = rest(function(arrays) { var comparator = last(arrays), mapped = arrayMap(arrays, castArrayLikeObject); if (comparator === last(mapped)) { comparator = undefined; } else { mapped.pop(); } return (mapped.length && mapped[0] === arrays[0]) ? baseIntersection(mapped, undefined, comparator) : []; }); /** * Converts all elements in `array` into a string separated by `separator`. * * @static * @memberOf _ * @since 4.0.0 * @category Array * @param {Array} array The array to convert. * @param {string} [separator=','] The element separator. * @returns {string} Returns the joined string. * @example * * _.join(['a', 'b', 'c'], '~'); * // => 'a~b~c' */ function join(array, separator) { return array ? nativeJoin.call(array, separator) : ''; } /** * Gets the last element of `array`. * * @static * @memberOf _ * @since 0.1.0 * @category Array * @param {Array} array The array to query. * @returns {*} Returns the last element of `array`. * @example * * _.last([1, 2, 3]); * // => 3 */ function last(array) { var length = array ? array.length : 0; return length ? array[length - 1] : undefined; } /** * This method is like `_.indexOf` except that it iterates over elements of * `array` from right to left. * * @static * @memberOf _ * @since 0.1.0 * @category Array * @param {Array} array The array to search. * @param {*} 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, else `-1`. * @example * * _.lastIndexOf([1, 2, 1, 2], 2); * // => 3 * * // Search from the `fromIndex`. * _.lastIndexOf([1, 2, 1, 2], 2, 2); * // => 1 */ function lastIndexOf(array, value, fromIndex) { var length = array ? array.length : 0; if (!length) { return -1; } var index = length; if (fromIndex !== undefined) { index = toInteger(fromIndex); index = ( index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1) ) + 1; } if (value !== value) { return indexOfNaN(array, index, true); } while (index--) { if (array[index] === value) { return index; } } return -1; } /** * Gets the element at `n` index of `array`. If `n` is negative, the nth * element from the end is returned. * * @static * @memberOf _ * @since 4.11.0 * @category Array * @param {Array} array The array to query. * @param {number} [n=0] The index of the element to return. * @returns {*} Returns the nth element of `array`. * @example * * var array = ['a', 'b', 'c', 'd']; * * _.nth(array, 1); * // => 'b' * * _.nth(array, -2); * // => 'c'; */ function nth(array, n) { return (array && array.length) ? baseNth(array, toInteger(n)) : undefined; } /** * Removes all given values from `array` using * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. * * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove` * to remove elements from an array by predicate. * * @static * @memberOf _ * @since 2.0.0 * @category Array * @param {Array} array The array to modify. * @param {...*} [values] The values to remove. * @returns {Array} Returns `array`. * @example * * var array = [1, 2, 3, 1, 2, 3]; * * _.pull(array, 2, 3); * console.log(array); * // => [1, 1] */ var pull = rest(pullAll); /** * This method is like `_.pull` except that it accepts an array of values to remove. * * **Note:** Unlike `_.difference`, this method mutates `array`. * * @static * @memberOf _ * @since 4.0.0 * @category Array * @param {Array} array The array to modify. * @param {Array} values The values to remove. * @returns {Array} Returns `array`. * @example * * var array = [1, 2, 3, 1, 2, 3]; * * _.pullAll(array, [2, 3]); * console.log(array); * // => [1, 1] */ function pullAll(array, values) { return (array && array.length && values && values.length) ? basePullAll(array, values) : array; } /** * This method is like `_.pullAll` except that it accepts `iteratee` which is * invoked for each element of `array` and `values` to generate the criterion * by which they're compared. The iteratee is invoked with one argument: (value). * * **Note:** Unlike `_.differenceBy`, this method mutates `array`. * * @static * @memberOf _ * @since 4.0.0 * @category Array * @param {Array} array The array to modify. * @param {Array} values The values to remove. * @param {Array|Function|Object|string} [iteratee=_.identity] * The iteratee invoked per element. * @returns {Array} Returns `array`. * @example * * var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }]; * * _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x'); * console.log(array); * // => [{ 'x': 2 }] */ function pullAllBy(array, values, iteratee) { return (array && array.length && values && values.length) ? basePullAll(array, values, getIteratee(iteratee)) : array; } /** * This method is like `_.pullAll` except that it accepts `comparator` which * is invoked to compare elements of `array` to `values`. The comparator is * invoked with two arguments: (arrVal, othVal). * * **Note:** Unlike `_.differenceWith`, this method mutates `array`. * * @static * @memberOf _ * @since 4.6.0 * @category Array * @param {Array} array The array to modify. * @param {Array} values The values to remove. * @param {Function} [comparator] The comparator invoked per element. * @returns {Array} Returns `array`. * @example * * var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }]; * * _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual); * console.log(array); * // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }] */ function pullAllWith(array, values, comparator) { return (array && array.length && values && values.length) ? basePullAll(array, values, undefined, comparator) : array; } /** * Removes elements from `array` corresponding to `indexes` and returns an * array of removed elements. * * **Note:** Unlike `_.at`, this method mutates `array`. * * @static * @memberOf _ * @since 3.0.0 * @category Array * @param {Array} array The array to modify. * @param {...(number|number[])} [indexes] The indexes of elements to remove. * @returns {Array} Returns the new array of removed elements. * @example * * var array = [5, 10, 15, 20]; * var evens = _.pullAt(array, 1, 3); * * console.log(array); * // => [5, 15] * * console.log(evens); * // => [10, 20] */ var pullAt = rest(function(array, indexes) { indexes = baseFlatten(indexes, 1); var length = array ? array.length : 0, result = baseAt(array, indexes); basePullAt(array, arrayMap(indexes, function(index) { return isIndex(index, length) ? +index : index; }).sort(compareAscending)); return result; }); /** * Removes all elements from `array` that `predicate` returns truthy for * and returns an array of the removed elements. The predicate is invoked * with three arguments: (value, index, array). * * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull` * to pull elements from an array by value. * * @static * @memberOf _ * @since 2.0.0 * @category Array * @param {Array} array The array to modify. * @param {Array|Function|Object|string} [predicate=_.identity] * The function invoked per iteration. * @returns {Array} Returns the new array of removed elements. * @example * * var array = [1, 2, 3, 4]; * var evens = _.remove(array, function(n) { * return n % 2 == 0; * }); * * console.log(array); * // => [1, 3] * * console.log(evens); * // => [2, 4] */ function remove(array, predicate) { var result = []; if (!(array && array.length)) { return result; } var index = -1, indexes = [], length = array.length; predicate = getIteratee(predicate, 3); while (++index < length) { var value = array[index]; if (predicate(value, index, array)) { result.push(value); indexes.push(index); } } basePullAt(array, indexes); return result; } /** * Reverses `array` so that the first element becomes the last, the second * element becomes the second to last, and so on. * * **Note:** This method mutates `array` and is based on * [`Array#reverse`](https://mdn.io/Array/reverse). * * @static * @memberOf _ * @since 4.0.0 * @category Array * @param {Array} array The array to modify. * @returns {Array} Returns `array`. * @example * * var array = [1, 2, 3]; * * _.reverse(array); * // => [3, 2, 1] * * console.log(array); * // => [3, 2, 1] */ function reverse(array) { return array ? nativeReverse.call(array) : array; } /** * Creates a slice of `array` from `start` up to, but not including, `end`. * * **Note:** This method is used instead of * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are * returned. * * @static * @memberOf _ * @since 3.0.0 * @category Array * @param {Array} array The array to slice. * @param {number} [start=0] The start position. * @param {number} [end=array.length] The end position. * @returns {Array} Returns the slice of `array`. */ function slice(array, start, end) { var length = array ? array.length : 0; if (!length) { return []; } if (end && typeof end != 'number' && isIterateeCall(array, start, end)) { start = 0; end = length; } else { start = start == null ? 0 : toInteger(start); end = end === undefined ? length : toInteger(end); } return baseSlice(array, start, end); } /** * Uses a binary search to determine the lowest index at which `value` * should be inserted into `array` in order to maintain its sort order. * * @static * @memberOf _ * @since 0.1.0 * @category Array * @param {Array} array The sorted array to inspect. * @param {*} value The value to evaluate. * @returns {number} Returns the index at which `value` should be inserted * into `array`. * @example * * _.sortedIndex([30, 50], 40); * // => 1 * * _.sortedIndex([4, 5], 4); * // => 0 */ function sortedIndex(array, value) { return baseSortedIndex(array, value); } /** * This method is like `_.sortedIndex` except that it accepts `iteratee` * which is invoked for `value` and each element of `array` to compute their * sort ranking. The iteratee is invoked with one argument: (value). * * @static * @memberOf _ * @since 4.0.0 * @category Array * @param {Array} array The sorted array to inspect. * @param {*} value The value to evaluate. * @param {Array|Function|Object|string} [iteratee=_.identity] * The iteratee invoked per element. * @returns {number} Returns the index at which `value` should be inserted * into `array`. * @example * * var dict = { 'thirty': 30, 'forty': 40, 'fifty': 50 }; * * _.sortedIndexBy(['thirty', 'fifty'], 'forty', _.propertyOf(dict)); * // => 1 * * // The `_.property` iteratee shorthand. * _.sortedIndexBy([{ 'x': 4 }, { 'x': 5 }], { 'x': 4 }, 'x'); * // => 0 */ function sortedIndexBy(array, value, iteratee) { return baseSortedIndexBy(array, value, getIteratee(iteratee)); } /** * This method is like `_.indexOf` except that it performs a binary * search on a sorted `array`. * * @static * @memberOf _ * @since 4.0.0 * @category Array * @param {Array} array The array to search. * @param {*} value The value to search for. * @returns {number} Returns the index of the matched value, else `-1`. * @example * * _.sortedIndexOf([1, 1, 2, 2], 2); * // => 2 */ function sortedIndexOf(array, value) { var length = array ? array.length : 0; if (length) { var index = baseSortedIndex(array, value); if (index < length && eq(array[index], value)) { return index; } } return -1; } /** * This method is like `_.sortedIndex` except that it returns the highest * index at which `value` should be inserted into `array` in order to * maintain its sort order. * * @static * @memberOf _ * @since 3.0.0 * @category Array * @param {Array} array The sorted array to inspect. * @param {*} value The value to evaluate. * @returns {number} Returns the index at which `value` should be inserted * into `array`. * @example * * _.sortedLastIndex([4, 5], 4); * // => 1 */ function sortedLastIndex(array, value) { return baseSortedIndex(array, value, true); } /** * This method is like `_.sortedLastIndex` except that it accepts `iteratee` * which is invoked for `value` and each element of `array` to compute their * sort ranking. The iteratee is invoked with one argument: (value). * * @static * @memberOf _ * @since 4.0.0 * @category Array * @param {Array} array The sorted array to inspect. * @param {*} value The value to evaluate. * @param {Array|Function|Object|string} [iteratee=_.identity] * The iteratee invoked per element. * @returns {number} Returns the index at which `value` should be inserted * into `array`. * @example * * // The `_.property` iteratee shorthand. * _.sortedLastIndexBy([{ 'x': 4 }, { 'x': 5 }], { 'x': 4 }, 'x'); * // => 1 */ function sortedLastIndexBy(array, value, iteratee) { return baseSortedIndexBy(array, value, getIteratee(iteratee), true); } /** * This method is like `_.lastIndexOf` except that it performs a binary * search on a sorted `array`. * * @static * @memberOf _ * @since 4.0.0 * @category Array * @param {Array} array The array to search. * @param {*} value The value to search for. * @returns {number} Returns the index of the matched value, else `-1`. * @example * * _.sortedLastIndexOf([1, 1, 2, 2], 2); * // => 3 */ function sortedLastIndexOf(array, value) { var length = array ? array.length : 0; if (length) { var index = baseSortedIndex(array, value, true) - 1; if (eq(array[index], value)) { return index; } } return -1; } /** * This method is like `_.uniq` except that it's designed and optimized * for sorted arrays. * * @static * @memberOf _ * @since 4.0.0 * @category Array * @param {Array} array The array to inspect. * @returns {Array} Returns the new duplicate free array. * @example * * _.sortedUniq([1, 1, 2]); * // => [1, 2] */ function sortedUniq(array) { return (array && array.length) ? baseSortedUniq(array) : []; } /** * This method is like `_.uniqBy` except that it's designed and optimized * for sorted arrays. * * @static * @memberOf _ * @since 4.0.0 * @category Array * @param {Array} array The array to inspect. * @param {Function} [iteratee] The iteratee invoked per element. * @returns {Array} Returns the new duplicate free array. * @example * * _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor); * // => [1.1, 2.3] */ function sortedUniqBy(array, iteratee) { return (array && array.length) ? baseSortedUniq(array, getIteratee(iteratee)) : []; } /** * Gets all but the first element of `array`. * * @static * @memberOf _ * @since 4.0.0 * @category Array * @param {Array} array The array to query. * @returns {Array} Returns the slice of `array`. * @example * * _.tail([1, 2, 3]); * // => [2, 3] */ function tail(array) { return drop(array, 1); } /** * Creates a slice of `array` with `n` elements taken from the beginning. * * @static * @memberOf _ * @since 0.1.0 * @category Array * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to take. * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. * @returns {Array} Returns the slice of `array`. * @example * * _.take([1, 2, 3]); * // => [1] * * _.take([1, 2, 3], 2); * // => [1, 2] * * _.take([1, 2, 3], 5); * // => [1, 2, 3] * * _.take([1, 2, 3], 0); * // => [] */ function take(array, n, guard) { if (!(array && array.length)) { return []; } n = (guard || n === undefined) ? 1 : toInteger(n); return baseSlice(array, 0, n < 0 ? 0 : n); } /** * Creates a slice of `array` with `n` elements taken from the end. * * @static * @memberOf _ * @since 3.0.0 * @category Array * @param {Array} array The array to query. * @param {number} [n=1] The number of elements to take. * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. * @returns {Array} Returns the slice of `array`. * @example * * _.takeRight([1, 2, 3]); * // => [3] * * _.takeRight([1, 2, 3], 2); * // => [2, 3] * * _.takeRight([1, 2, 3], 5); * // => [1, 2, 3] * * _.takeRight([1, 2, 3], 0); * // => [] */ function takeRight(array, n, guard) { var length = array ? array.length : 0; if (!length) { return []; } n = (guard || n === undefined) ? 1 : toInteger(n); n = length - n; return baseSlice(array, n < 0 ? 0 : n, length); } /** * Creates a slice of `array` with elements taken from the end. Elements are * taken until `predicate` returns falsey. The predicate is invoked with * three arguments: (value, index, array). * * @static * @memberOf _ * @since 3.0.0 * @category Array * @param {Array} array The array to query. * @param {Array|Function|Object|string} [predicate=_.identity] * The function invoked per iteration. * @returns {Array} Returns the slice of `array`. * @example * * var users = [ * { 'user': 'barney', 'active': true }, * { 'user': 'fred', 'active': false }, * { 'user': 'pebbles', 'active': false } * ]; * * _.takeRightWhile(users, function(o) { return !o.active; }); * // => objects for ['fred', 'pebbles'] * * // The `_.matches` iteratee shorthand. * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false }); * // => objects for ['pebbles'] * * // The `_.matchesProperty` iteratee shorthand. * _.takeRightWhile(users, ['active', false]); * // => objects for ['fred', 'pebbles'] * * // The `_.property` iteratee shorthand. * _.takeRightWhile(users, 'active'); * // => [] */ function takeRightWhile(array, predicate) { return (array && array.length) ? baseWhile(array, getIteratee(predicate, 3), false, true) : []; } /** * Creates a slice of `array` with elements taken from the beginning. Elements * are taken until `predicate` returns falsey. The predicate is invoked with * three arguments: (value, index, array). * * @static * @memberOf _ * @since 3.0.0 * @category Array * @param {Array} array The array to query. * @param {Array|Function|Object|string} [predicate=_.identity] * The function invoked per iteration. * @returns {Array} Returns the slice of `array`. * @example * * var users = [ * { 'user': 'barney', 'active': false }, * { 'user': 'fred', 'active': false}, * { 'user': 'pebbles', 'active': true } * ]; * * _.takeWhile(users, function(o) { return !o.active; }); * // => objects for ['barney', 'fred'] * * // The `_.matches` iteratee shorthand. * _.takeWhile(users, { 'user': 'barney', 'active': false }); * // => objects for ['barney'] * * // The `_.matchesProperty` iteratee shorthand. * _.takeWhile(users, ['active', false]); * // => objects for ['barney', 'fred'] * * // The `_.property` iteratee shorthand. * _.takeWhile(users, 'active'); * // => [] */ function takeWhile(array, predicate) { return (array && array.length) ? baseWhile(array, getIteratee(predicate, 3)) : []; } /** * Creates an array of unique values, in order, from all given arrays using * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. * * @static * @memberOf _ * @since 0.1.0 * @category Array * @param {...Array} [arrays] The arrays to inspect. * @returns {Array} Returns the new array of combined values. * @example * * _.union([2, 1], [4, 2], [1, 2]); * // => [2, 1, 4] */ var union = rest(function(arrays) { return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true)); }); /** * This method is like `_.union` except that it accepts `iteratee` which is * invoked for each element of each `arrays` to generate the criterion by * which uniqueness is computed. The iteratee is invoked with one argument: * (value). * * @static * @memberOf _ * @since 4.0.0 * @category Array * @param {...Array} [arrays] The arrays to inspect. * @param {Array|Function|Object|string} [iteratee=_.identity] * The iteratee invoked per element. * @returns {Array} Returns the new array of combined values. * @example * * _.unionBy([2.1, 1.2], [4.3, 2.4], Math.floor); * // => [2.1, 1.2, 4.3] * * // The `_.property` iteratee shorthand. * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); * // => [{ 'x': 1 }, { 'x': 2 }] */ var unionBy = rest(function(arrays) { var iteratee = last(arrays); if (isArrayLikeObject(iteratee)) { iteratee = undefined; } return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee)); }); /** * This method is like `_.union` except that it accepts `comparator` which * is invoked to compare elements of `arrays`. The comparator is invoked * with two arguments: (arrVal, othVal). * * @static * @memberOf _ * @since 4.0.0 * @category Array * @param {...Array} [arrays] The arrays to inspect. * @param {Function} [comparator] The comparator invoked per element. * @returns {Array} Returns the new array of combined values. * @example * * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; * * _.unionWith(objects, others, _.isEqual); * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }] */ var unionWith = rest(function(arrays) { var comparator = last(arrays); if (isArrayLikeObject(comparator)) { comparator = undefined; } return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined, comparator); }); /** * Creates a duplicate-free version of an array, using * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons, in which only the first occurrence of each * element is kept. * * @static * @memberOf _ * @since 0.1.0 * @category Array * @param {Array} array The array to inspect. * @returns {Array} Returns the new duplicate free array. * @example * * _.uniq([2, 1, 2]); * // => [2, 1] */ function uniq(array) { return (array && array.length) ? baseUniq(array) : []; } /** * This method is like `_.uniq` except that it accepts `iteratee` which is * invoked for each element in `array` to generate the criterion by which * uniqueness is computed. The iteratee is invoked with one argument: (value). * * @static * @memberOf _ * @since 4.0.0 * @category Array * @param {Array} array The array to inspect. * @param {Array|Function|Object|string} [iteratee=_.identity] * The iteratee invoked per element. * @returns {Array} Returns the new duplicate free array. * @example * * _.uniqBy([2.1, 1.2, 2.3], Math.floor); * // => [2.1, 1.2] * * // The `_.property` iteratee shorthand. * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); * // => [{ 'x': 1 }, { 'x': 2 }] */ function uniqBy(array, iteratee) { return (array && array.length) ? baseUniq(array, getIteratee(iteratee)) : []; } /** * This method is like `_.uniq` except that it accepts `comparator` which * is invoked to compare elements of `array`. The comparator is invoked with * two arguments: (arrVal, othVal). * * @static * @memberOf _ * @since 4.0.0 * @category Array * @param {Array} array The array to inspect. * @param {Function} [comparator] The comparator invoked per element. * @returns {Array} Returns the new duplicate free array. * @example * * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }]; * * _.uniqWith(objects, _.isEqual); * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }] */ function uniqWith(array, comparator) { return (array && array.length) ? baseUniq(array, undefined, comparator) : []; } /** * This method is like `_.zip` except that it accepts an array of grouped * elements and creates an array regrouping the elements to their pre-zip * configuration. * * @static * @memberOf _ * @since 1.2.0 * @category Array * @param {Array} array The array of grouped elements to process. * @returns {Array} Returns the new array of regrouped elements. * @example * * var zipped = _.zip(['fred', 'barney'], [30, 40], [true, false]); * // => [['fred', 30, true], ['barney', 40, false]] * * _.unzip(zipped); * // => [['fred', 'barney'], [30, 40], [true, false]] */ function unzip(array) { if (!(array && array.length)) { return []; } var length = 0; array = arrayFilter(array, function(group) { if (isArrayLikeObject(group)) { length = nativeMax(group.length, length); return true; } }); return baseTimes(length, function(index) { return arrayMap(array, baseProperty(index)); }); } /** * This method is like `_.unzip` except that it accepts `iteratee` to specify * how regrouped values should be combined. The iteratee is invoked with the * elements of each group: (...group). * * @static * @memberOf _ * @since 3.8.0 * @category Array * @param {Array} array The array of grouped elements to process. * @param {Function} [iteratee=_.identity] The function to combine * regrouped values. * @returns {Array} Returns the new array of regrouped elements. * @example * * var zipped = _.zip([1, 2], [10, 20], [100, 200]); * // => [[1, 10, 100], [2, 20, 200]] * * _.unzipWith(zipped, _.add); * // => [3, 30, 300] */ function unzipWith(array, iteratee) { if (!(array && array.length)) { return []; } var result = unzip(array); if (iteratee == null) { return result; } return arrayMap(result, function(group) { return apply(iteratee, undefined, group); }); } /** * Creates an array excluding all given values using * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * for equality comparisons. * * @static * @memberOf _ * @since 0.1.0 * @category Array * @param {Array} array The array to inspect. * @param {...*} [values] The values to exclude. * @returns {Array} Returns the new array of filtered values. * @see _.difference, _.xor * @example * * _.without([1, 2, 1, 3], 1, 2); * // => [3] */ var without = rest(function(array, values) { return isArrayLikeObject(array) ? baseDifference(array, values) : []; }); /** * Creates an array of unique values that is the * [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference) * of the given arrays. The order of result values is determined by the order * they occur in the arrays. * * @static * @memberOf _ * @since 2.4.0 * @category Array * @param {...Array} [arrays] The arrays to inspect. * @returns {Array} Returns the new array of filtered values. * @see _.difference, _.without * @example * * _.xor([2, 1], [4, 2]); * // => [1, 4] */ var xor = rest(function(arrays) { return baseXor(arrayFilter(arrays, isArrayLikeObject)); }); /** * This method is like `_.xor` except that it accepts `iteratee` which is * invoked for each element of each `arrays` to generate the criterion by * which by which they're compared. The iteratee is invoked with one argument: * (value). * * @static * @memberOf _ * @since 4.0.0 * @category Array * @param {...Array} [arrays] The arrays to inspect. * @param {Array|Function|Object|string} [iteratee=_.identity] * The iteratee invoked per element. * @returns {Array} Returns the new array of filtered values. * @example * * _.xorBy([2.1, 1.2], [4.3, 2.4], Math.floor); * // => [1.2, 4.3] * * // The `_.property` iteratee shorthand. * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); * // => [{ 'x': 2 }] */ var xorBy = rest(function(arrays) { var iteratee = last(arrays); if (isArrayLikeObject(iteratee)) { iteratee = undefined; } return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee)); }); /** * This method is like `_.xor` except that it accepts `comparator` which is * invoked to compare elements of `arrays`. The comparator is invoked with * two arguments: (arrVal, othVal). * * @static * @memberOf _ * @since 4.0.0 * @category Array * @param {...Array} [arrays] The arrays to inspect. * @param {Function} [comparator] The comparator invoked per element. * @returns {Array} Returns the new array of filtered values. * @example * * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; * * _.xorWith(objects, others, _.isEqual); * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }] */ var xorWith = rest(function(arrays) { var comparator = last(arrays); if (isArrayLikeObject(comparator)) { comparator = undefined; } return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined, comparator); }); /** * Creates an array of grouped elements, the first of which contains the * first elements of the given arrays, the second of which contains the * second elements of the given arrays, and so on. * * @static * @memberOf _ * @since 0.1.0 * @category Array * @param {...Array} [arrays] The arrays to process. * @returns {Array} Returns the new array of grouped elements. * @example * * _.zip(['fred', 'barney'], [30, 40], [true, false]); * // => [['fred', 30, true], ['barney', 40, false]] */ var zip = rest(unzip); /** * This method is like `_.fromPairs` except that it accepts two arrays, * one of property identifiers and one of corresponding values. * * @static * @memberOf _ * @since 0.4.0 * @category Array * @param {Array} [props=[]] The property identifiers. * @param {Array} [values=[]] The property values. * @returns {Object} Returns the new object. * @example * * _.zipObject(['a', 'b'], [1, 2]); * // => { 'a': 1, 'b': 2 } */ function zipObject(props, values) { return baseZipObject(props || [], values || [], assignValue); } /** * This method is like `_.zipObject` except that it supports property paths. * * @static * @memberOf _ * @since 4.1.0 * @category Array * @param {Array} [props=[]] The property identifiers. * @param {Array} [values=[]] The property values. * @returns {Object} Returns the new object. * @example * * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]); * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } } */ function zipObjectDeep(props, values) { return baseZipObject(props || [], values || [], baseSet); } /** * This method is like `_.zip` except that it accepts `iteratee` to specify * how grouped values should be combined. The iteratee is invoked with the * elements of each group: (...group). * * @static * @memberOf _ * @since 3.8.0 * @category Array * @param {...Array} [arrays] The arrays to process. * @param {Function} [iteratee=_.identity] The function to combine grouped values. * @returns {Array} Returns the new array of grouped elements. * @example * * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) { * return a + b + c; * }); * // => [111, 222] */ var zipWith = rest(function(arrays) { var length = arrays.length, iteratee = length > 1 ? arrays[length - 1] : undefined; iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined; return unzipWith(arrays, iteratee); }); /*------------------------------------------------------------------------*/ /** * Creates a `lodash` wrapper instance that wraps `value` with explicit method * chain sequences enabled. The result of such sequences must be unwrapped * with `_#value`. * * @static * @memberOf _ * @since 1.3.0 * @category Seq * @param {*} value The value to wrap. * @returns {Object} Returns the new `lodash` wrapper instance. * @example * * var users = [ * { 'user': 'barney', 'age': 36 }, * { 'user': 'fred', 'age': 40 }, * { 'user': 'pebbles', 'age': 1 } * ]; * * var youngest = _ * .chain(users) * .sortBy('age') * .map(function(o) { * return o.user + ' is ' + o.age; * }) * .head() * .value(); * // => 'pebbles is 1' */ function chain(value) { var result = lodash(value); result.__chain__ = true; return result; } /** * This method invokes `interceptor` and returns `value`. The interceptor * is invoked with one argument; (value). The purpose of this method is to * "tap into" a method chain sequence in order to modify intermediate results. * * @static * @memberOf _ * @since 0.1.0 * @category Seq * @param {*} value The value to provide to `interceptor`. * @param {Function} interceptor The function to invoke. * @returns {*} Returns `value`. * @example * * _([1, 2, 3]) * .tap(function(array) { * // Mutate input array. * array.pop(); * }) * .reverse() * .value(); * // => [2, 1] */ function tap(value, interceptor) { interceptor(value); return value; } /** * This method is like `_.tap` except that it returns the result of `interceptor`. * The purpose of this method is to "pass thru" values replacing intermediate * results in a method chain sequence. * * @static * @memberOf _ * @since 3.0.0 * @category Seq * @param {*} value The value to provide to `interceptor`. * @param {Function} interceptor The function to invoke. * @returns {*} Returns the result of `interceptor`. * @example * * _(' abc ') * .chain() * .trim() * .thru(function(value) { * return [value]; * }) * .value(); * // => ['abc'] */ function thru(value, interceptor) { return interceptor(value); } /** * This method is the wrapper version of `_.at`. * * @name at * @memberOf _ * @since 1.0.0 * @category Seq * @param {...(string|string[])} [paths] The property paths of elements to pick. * @returns {Object} Returns the new `lodash` wrapper instance. * @example * * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] }; * * _(object).at(['a[0].b.c', 'a[1]']).value(); * // => [3, 4] * * _(['a', 'b', 'c']).at(0, 2).value(); * // => ['a', 'c'] */ var wrapperAt = rest(function(paths) { paths = baseFlatten(paths, 1); var length = paths.length, start = length ? paths[0] : 0, value = this.__wrapped__, interceptor = function(object) { return baseAt(object, paths); }; if (length > 1 || this.__actions__.length || !(value instanceof LazyWrapper) || !isIndex(start)) { return this.thru(interceptor); } value = value.slice(start, +start + (length ? 1 : 0)); value.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined }); return new LodashWrapper(value, this.__chain__).thru(function(array) { if (length && !array.length) { array.push(undefined); } return array; }); }); /** * Creates a `lodash` wrapper instance with explicit method chain sequences enabled. * * @name chain * @memberOf _ * @since 0.1.0 * @category Seq * @returns {Object} Returns the new `lodash` wrapper instance. * @example * * var users = [ * { 'user': 'barney', 'age': 36 }, * { 'user': 'fred', 'age': 40 } * ]; * * // A sequence without explicit chaining. * _(users).head(); * // => { 'user': 'barney', 'age': 36 } * * // A sequence with explicit chaining. * _(users) * .chain() * .head() * .pick('user') * .value(); * // => { 'user': 'barney' } */ function wrapperChain() { return chain(this); } /** * Executes the chain sequence and returns the wrapped result. * * @name commit * @memberOf _ * @since 3.2.0 * @category Seq * @returns {Object} Returns the new `lodash` wrapper instance. * @example * * var array = [1, 2]; * var wrapped = _(array).push(3); * * console.log(array); * // => [1, 2] * * wrapped = wrapped.commit(); * console.log(array); * // => [1, 2, 3] * * wrapped.last(); * // => 3 * * console.log(array); * // => [1, 2, 3] */ function wrapperCommit() { return new LodashWrapper(this.value(), this.__chain__); } /** * Gets the next value on a wrapped object following the * [iterator protocol](https://mdn.io/iteration_protocols#iterator). * * @name next * @memberOf _ * @since 4.0.0 * @category Seq * @returns {Object} Returns the next iterator value. * @example * * var wrapped = _([1, 2]); * * wrapped.next(); * // => { 'done': false, 'value': 1 } * * wrapped.next(); * // => { 'done': false, 'value': 2 } * * wrapped.next(); * // => { 'done': true, 'value': undefined } */ function wrapperNext() { if (this.__values__ === undefined) { this.__values__ = toArray(this.value()); } var done = this.__index__ >= this.__values__.length, value = done ? undefined : this.__values__[this.__index__++]; return { 'done': done, 'value': value }; } /** * Enables the wrapper to be iterable. * * @name Symbol.iterator * @memberOf _ * @since 4.0.0 * @category Seq * @returns {Object} Returns the wrapper object. * @example * * var wrapped = _([1, 2]); * * wrapped[Symbol.iterator]() === wrapped; * // => true * * Array.from(wrapped); * // => [1, 2] */ function wrapperToIterator() { return this; } /** * Creates a clone of the chain sequence planting `value` as the wrapped value. * * @name plant * @memberOf _ * @since 3.2.0 * @category Seq * @param {*} value The value to plant. * @returns {Object} Returns the new `lodash` wrapper instance. * @example * * function square(n) { * return n * n; * } * * var wrapped = _([1, 2]).map(square); * var other = wrapped.plant([3, 4]); * * other.value(); * // => [9, 16] * * wrapped.value(); * // => [1, 4] */ function wrapperPlant(value) { var result, parent = this; while (parent instanceof baseLodash) { var clone = wrapperClone(parent); clone.__index__ = 0; clone.__values__ = undefined; if (result) { previous.__wrapped__ = clone; } else { result = clone; } var previous = clone; parent = parent.__wrapped__; } previous.__wrapped__ = value; return result; } /** * This method is the wrapper version of `_.reverse`. * * **Note:** This method mutates the wrapped array. * * @name reverse * @memberOf _ * @since 0.1.0 * @category Seq * @returns {Object} Returns the new `lodash` wrapper instance. * @example * * var array = [1, 2, 3]; * * _(array).reverse().value() * // => [3, 2, 1] * * console.log(array); * // => [3, 2, 1] */ function wrapperReverse() { var value = this.__wrapped__; if (value instanceof LazyWrapper) { var wrapped = value; if (this.__actions__.length) { wrapped = new LazyWrapper(this); } wrapped = wrapped.reverse(); wrapped.__actions__.push({ 'func': thru, 'args': [reverse], 'thisArg': undefined }); return new LodashWrapper(wrapped, this.__chain__); } return this.thru(reverse); } /** * Executes the chain sequence to resolve the unwrapped value. * * @name value * @memberOf _ * @since 0.1.0 * @alias toJSON, valueOf * @category Seq * @returns {*} Returns the resolved unwrapped value. * @example * * _([1, 2, 3]).value(); * // => [1, 2, 3] */ function wrapperValue() { return baseWrapperValue(this.__wrapped__, this.__actions__); } /*------------------------------------------------------------------------*/ /** * Creates an object composed of keys generated from the results of running * each element of `collection` thru `iteratee`. The corresponding value of * each key is the number of times the key was returned by `iteratee`. The * iteratee is invoked with one argument: (value). * * @static * @memberOf _ * @since 0.5.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. * @param {Array|Function|Object|string} [iteratee=_.identity] * The iteratee to transform keys. * @returns {Object} Returns the composed aggregate object. * @example * * _.countBy([6.1, 4.2, 6.3], Math.floor); * // => { '4': 1, '6': 2 } * * _.countBy(['one', 'two', 'three'], 'length'); * // => { '3': 2, '5': 1 } */ var countBy = createAggregator(function(result, value, key) { hasOwnProperty.call(result, key) ? ++result[key] : (result[key] = 1); }); /** * Checks if `predicate` returns truthy for **all** elements of `collection`. * Iteration is stopped once `predicate` returns falsey. The predicate is * invoked with three arguments: (value, index|key, collection). * * @static * @memberOf _ * @since 0.1.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. * @param {Array|Function|Object|string} [predicate=_.identity] * The function invoked per iteration. * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. * @returns {boolean} Returns `true` if all elements pass the predicate check, * else `false`. * @example * * _.every([true, 1, null, 'yes'], Boolean); * // => false * * var users = [ * { 'user': 'barney', 'age': 36, 'active': false }, * { 'user': 'fred', 'age': 40, 'active': false } * ]; * * // The `_.matches` iteratee shorthand. * _.every(users, { 'user': 'barney', 'active': false }); * // => false * * // The `_.matchesProperty` iteratee shorthand. * _.every(users, ['active', false]); * // => true * * // The `_.property` iteratee shorthand. * _.every(users, 'active'); * // => false */ function every(collection, predicate, guard) { var func = isArray(collection) ? arrayEvery : baseEvery; if (guard && isIterateeCall(collection, predicate, guard)) { predicate = undefined; } return func(collection, getIteratee(predicate, 3)); } /** * Iterates over elements of `collection`, returning an array of all elements * `predicate` returns truthy for. The predicate is invoked with three * arguments: (value, index|key, collection). * * @static * @memberOf _ * @since 0.1.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. * @param {Array|Function|Object|string} [predicate=_.identity] * The function invoked per iteration. * @returns {Array} Returns the new filtered array. * @see _.reject * @example * * var users = [ * { 'user': 'barney', 'age': 36, 'active': true }, * { 'user': 'fred', 'age': 40, 'active': false } * ]; * * _.filter(users, function(o) { return !o.active; }); * // => objects for ['fred'] * * // The `_.matches` iteratee shorthand. * _.filter(users, { 'age': 36, 'active': true }); * // => objects for ['barney'] * * // The `_.matchesProperty` iteratee shorthand. * _.filter(users, ['active', false]); * // => objects for ['fred'] * * // The `_.property` iteratee shorthand. * _.filter(users, 'active'); * // => objects for ['barney'] */ function filter(collection, predicate) { var func = isArray(collection) ? arrayFilter : baseFilter; return func(collection, getIteratee(predicate, 3)); } /** * Iterates over elements of `collection`, returning the first element * `predicate` returns truthy for. The predicate is invoked with three * arguments: (value, index|key, collection). * * @static * @memberOf _ * @since 0.1.0 * @category Collection * @param {Array|Object} collection The collection to search. * @param {Array|Function|Object|string} [predicate=_.identity] * The function invoked per iteration. * @returns {*} Returns the matched element, else `undefined`. * @example * * var users = [ * { 'user': 'barney', 'age': 36, 'active': true }, * { 'user': 'fred', 'age': 40, 'active': false }, * { 'user': 'pebbles', 'age': 1, 'active': true } * ]; * * _.find(users, function(o) { return o.age < 40; }); * // => object for 'barney' * * // The `_.matches` iteratee shorthand. * _.find(users, { 'age': 1, 'active': true }); * // => object for 'pebbles' * * // The `_.matchesProperty` iteratee shorthand. * _.find(users, ['active', false]); * // => object for 'fred' * * // The `_.property` iteratee shorthand. * _.find(users, 'active'); * // => object for 'barney' */ function find(collection, predicate) { predicate = getIteratee(predicate, 3); if (isArray(collection)) { var index = baseFindIndex(collection, predicate); return index > -1 ? collection[index] : undefined; } return baseFind(collection, predicate, baseEach); } /** * This method is like `_.find` except that it iterates over elements of * `collection` from right to left. * * @static * @memberOf _ * @since 2.0.0 * @category Collection * @param {Array|Object} collection The collection to search. * @param {Array|Function|Object|string} [predicate=_.identity] * The function invoked per iteration. * @returns {*} Returns the matched element, else `undefined`. * @example * * _.findLast([1, 2, 3, 4], function(n) { * return n % 2 == 1; * }); * // => 3 */ function findLast(collection, predicate) { predicate = getIteratee(predicate, 3); if (isArray(collection)) { var index = baseFindIndex(collection, predicate, true); return index > -1 ? collection[index] : undefined; } return baseFind(collection, predicate, baseEachRight); } /** * Creates a flattened array of values by running each element in `collection` * thru `iteratee` and flattening the mapped results. The iteratee is invoked * with three arguments: (value, index|key, collection). * * @static * @memberOf _ * @since 4.0.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. * @param {Array|Function|Object|string} [iteratee=_.identity] * The function invoked per iteration. * @returns {Array} Returns the new flattened array. * @example * * function duplicate(n) { * return [n, n]; * } * * _.flatMap([1, 2], duplicate); * // => [1, 1, 2, 2] */ function flatMap(collection, iteratee) { return baseFlatten(map(collection, iteratee), 1); } /** * This method is like `_.flatMap` except that it recursively flattens the * mapped results. * * @static * @memberOf _ * @since 4.7.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. * @param {Array|Function|Object|string} [iteratee=_.identity] * The function invoked per iteration. * @returns {Array} Returns the new flattened array. * @example * * function duplicate(n) { * return [[[n, n]]]; * } * * _.flatMapDeep([1, 2], duplicate); * // => [1, 1, 2, 2] */ function flatMapDeep(collection, iteratee) { return baseFlatten(map(collection, iteratee), INFINITY); } /** * This method is like `_.flatMap` except that it recursively flattens the * mapped results up to `depth` times. * * @static * @memberOf _ * @since 4.7.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. * @param {Array|Function|Object|string} [iteratee=_.identity] * The function invoked per iteration. * @param {number} [depth=1] The maximum recursion depth. * @returns {Array} Returns the new flattened array. * @example * * function duplicate(n) { * return [[[n, n]]]; * } * * _.flatMapDepth([1, 2], duplicate, 2); * // => [[1, 1], [2, 2]] */ function flatMapDepth(collection, iteratee, depth) { depth = depth === undefined ? 1 : toInteger(depth); return baseFlatten(map(collection, iteratee), depth); } /** * Iterates over elements of `collection` and invokes `iteratee` for each element. * The iteratee is invoked with three arguments: (value, index|key, collection). * Iteratee functions may exit iteration early by explicitly returning `false`. * * **Note:** As with other "Collections" methods, objects with a "length" * property are iterated like arrays. To avoid this behavior use `_.forIn` * or `_.forOwn` for object iteration. * * @static * @memberOf _ * @since 0.1.0 * @alias each * @category Collection * @param {Array|Object} collection The collection to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @returns {Array|Object} Returns `collection`. * @see _.forEachRight * @example * * _([1, 2]).forEach(function(value) { * console.log(value); * }); * // => Logs `1` then `2`. * * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) { * console.log(key); * }); * // => Logs 'a' then 'b' (iteration order is not guaranteed). */ function forEach(collection, iteratee) { var func = isArray(collection) ? arrayEach : baseEach; return func(collection, getIteratee(iteratee, 3)); } /** * This method is like `_.forEach` except that it iterates over elements of * `collection` from right to left. * * @static * @memberOf _ * @since 2.0.0 * @alias eachRight * @category Collection * @param {Array|Object} collection The collection to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @returns {Array|Object} Returns `collection`. * @see _.forEach * @example * * _.forEachRight([1, 2], function(value) { * console.log(value); * }); * // => Logs `2` then `1`. */ function forEachRight(collection, iteratee) { var func = isArray(collection) ? arrayEachRight : baseEachRight; return func(collection, getIteratee(iteratee, 3)); } /** * Creates an object composed of keys generated from the results of running * each element of `collection` thru `iteratee`. The order of grouped values * is determined by the order they occur in `collection`. The corresponding * value of each key is an array of elements responsible for generating the * key. The iteratee is invoked with one argument: (value). * * @static * @memberOf _ * @since 0.1.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. * @param {Array|Function|Object|string} [iteratee=_.identity] * The iteratee to transform keys. * @returns {Object} Returns the composed aggregate object. * @example * * _.groupBy([6.1, 4.2, 6.3], Math.floor); * // => { '4': [4.2], '6': [6.1, 6.3] } * * // The `_.property` iteratee shorthand. * _.groupBy(['one', 'two', 'three'], 'length'); * // => { '3': ['one', 'two'], '5': ['three'] } */ var groupBy = createAggregator(function(result, value, key) { if (hasOwnProperty.call(result, key)) { result[key].push(value); } else { result[key] = [value]; } }); /** * Checks if `value` is in `collection`. If `collection` is a string, it's * checked for a substring of `value`, otherwise * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * is used for equality comparisons. If `fromIndex` is negative, it's used as * the offset from the end of `collection`. * * @static * @memberOf _ * @since 0.1.0 * @category Collection * @param {Array|Object|string} collection The collection to search. * @param {*} value The value to search for. * @param {number} [fromIndex=0] The index to search from. * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`. * @returns {boolean} Returns `true` if `value` is found, else `false`. * @example * * _.includes([1, 2, 3], 1); * // => true * * _.includes([1, 2, 3], 1, 2); * // => false * * _.includes({ 'user': 'fred', 'age': 40 }, 'fred'); * // => true * * _.includes('pebbles', 'eb'); * // => true */ function includes(collection, value, fromIndex, guard) { collection = isArrayLike(collection) ? collection : values(collection); fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0; var length = collection.length; if (fromIndex < 0) { fromIndex = nativeMax(length + fromIndex, 0); } return isString(collection) ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1) : (!!length && baseIndexOf(collection, value, fromIndex) > -1); } /** * Invokes the method at `path` of each element in `collection`, returning * an array of the results of each invoked method. Any additional arguments * are provided to each invoked method. If `methodName` is a function, it's * invoked for and `this` bound to, each element in `collection`. * * @static * @memberOf _ * @since 4.0.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. * @param {Array|Function|string} path The path of the method to invoke or * the function invoked per iteration. * @param {...*} [args] The arguments to invoke each method with. * @returns {Array} Returns the array of results. * @example * * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort'); * // => [[1, 5, 7], [1, 2, 3]] * * _.invokeMap([123, 456], String.prototype.split, ''); * // => [['1', '2', '3'], ['4', '5', '6']] */ var invokeMap = rest(function(collection, path, args) { var index = -1, isFunc = typeof path == 'function', isProp = isKey(path), result = isArrayLike(collection) ? Array(collection.length) : []; baseEach(collection, function(value) { var func = isFunc ? path : ((isProp && value != null) ? value[path] : undefined); result[++index] = func ? apply(func, value, args) : baseInvoke(value, path, args); }); return result; }); /** * Creates an object composed of keys generated from the results of running * each element of `collection` thru `iteratee`. The corresponding value of * each key is the last element responsible for generating the key. The * iteratee is invoked with one argument: (value). * * @static * @memberOf _ * @since 4.0.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. * @param {Array|Function|Object|string} [iteratee=_.identity] * The iteratee to transform keys. * @returns {Object} Returns the composed aggregate object. * @example * * var array = [ * { 'dir': 'left', 'code': 97 }, * { 'dir': 'right', 'code': 100 } * ]; * * _.keyBy(array, function(o) { * return String.fromCharCode(o.code); * }); * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } * * _.keyBy(array, 'dir'); * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } } */ var keyBy = createAggregator(function(result, value, key) { result[key] = value; }); /** * Creates an array of values by running each element in `collection` thru * `iteratee`. The iteratee is invoked with three arguments: * (value, index|key, collection). * * Many lodash methods are guarded to work as iteratees for methods like * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`. * * The guarded methods are: * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`, * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`, * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`, * `template`, `trim`, `trimEnd`, `trimStart`, and `words` * * @static * @memberOf _ * @since 0.1.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. * @param {Array|Function|Object|string} [iteratee=_.identity] * The function invoked per iteration. * @returns {Array} Returns the new mapped array. * @example * * function square(n) { * return n * n; * } * * _.map([4, 8], square); * // => [16, 64] * * _.map({ 'a': 4, 'b': 8 }, square); * // => [16, 64] (iteration order is not guaranteed) * * var users = [ * { 'user': 'barney' }, * { 'user': 'fred' } * ]; * * // The `_.property` iteratee shorthand. * _.map(users, 'user'); * // => ['barney', 'fred'] */ function map(collection, iteratee) { var func = isArray(collection) ? arrayMap : baseMap; return func(collection, getIteratee(iteratee, 3)); } /** * This method is like `_.sortBy` except that it allows specifying the sort * orders of the iteratees to sort by. If `orders` is unspecified, all values * are sorted in ascending order. Otherwise, specify an order of "desc" for * descending or "asc" for ascending sort order of corresponding values. * * @static * @memberOf _ * @since 4.0.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. * @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]] * The iteratees to sort by. * @param {string[]} [orders] The sort orders of `iteratees`. * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`. * @returns {Array} Returns the new sorted array. * @example * * var users = [ * { 'user': 'fred', 'age': 48 }, * { 'user': 'barney', 'age': 34 }, * { 'user': 'fred', 'age': 40 }, * { 'user': 'barney', 'age': 36 } * ]; * * // Sort by `user` in ascending order and by `age` in descending order. * _.orderBy(users, ['user', 'age'], ['asc', 'desc']); * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]] */ function orderBy(collection, iteratees, orders, guard) { if (collection == null) { return []; } if (!isArray(iteratees)) { iteratees = iteratees == null ? [] : [iteratees]; } orders = guard ? undefined : orders; if (!isArray(orders)) { orders = orders == null ? [] : [orders]; } return baseOrderBy(collection, iteratees, orders); } /** * Creates an array of elements split into two groups, the first of which * contains elements `predicate` returns truthy for, the second of which * contains elements `predicate` returns falsey for. The predicate is * invoked with one argument: (value). * * @static * @memberOf _ * @since 3.0.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. * @param {Array|Function|Object|string} [predicate=_.identity] * The function invoked per iteration. * @returns {Array} Returns the array of grouped elements. * @example * * var users = [ * { 'user': 'barney', 'age': 36, 'active': false }, * { 'user': 'fred', 'age': 40, 'active': true }, * { 'user': 'pebbles', 'age': 1, 'active': false } * ]; * * _.partition(users, function(o) { return o.active; }); * // => objects for [['fred'], ['barney', 'pebbles']] * * // The `_.matches` iteratee shorthand. * _.partition(users, { 'age': 1, 'active': false }); * // => objects for [['pebbles'], ['barney', 'fred']] * * // The `_.matchesProperty` iteratee shorthand. * _.partition(users, ['active', false]); * // => objects for [['barney', 'pebbles'], ['fred']] * * // The `_.property` iteratee shorthand. * _.partition(users, 'active'); * // => objects for [['fred'], ['barney', 'pebbles']] */ var partition = createAggregator(function(result, value, key) { result[key ? 0 : 1].push(value); }, function() { return [[], []]; }); /** * Reduces `collection` to a value which is the accumulated result of running * each element in `collection` thru `iteratee`, where each successive * invocation is supplied the return value of the previous. If `accumulator` * is not given, the first element of `collection` is used as the initial * value. The iteratee is invoked with four arguments: * (accumulator, value, index|key, collection). * * Many lodash methods are guarded to work as iteratees for methods like * `_.reduce`, `_.reduceRight`, and `_.transform`. * * The guarded methods are: * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`, * and `sortBy` * * @static * @memberOf _ * @since 0.1.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @param {*} [accumulator] The initial value. * @returns {*} Returns the accumulated value. * @see _.reduceRight * @example * * _.reduce([1, 2], function(sum, n) { * return sum + n; * }, 0); * // => 3 * * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) { * (result[value] || (result[value] = [])).push(key); * return result; * }, {}); * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed) */ function reduce(collection, iteratee, accumulator) { var func = isArray(collection) ? arrayReduce : baseReduce, initAccum = arguments.length < 3; return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach); } /** * This method is like `_.reduce` except that it iterates over elements of * `collection` from right to left. * * @static * @memberOf _ * @since 0.1.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @param {*} [accumulator] The initial value. * @returns {*} Returns the accumulated value. * @see _.reduce * @example * * var array = [[0, 1], [2, 3], [4, 5]]; * * _.reduceRight(array, function(flattened, other) { * return flattened.concat(other); * }, []); * // => [4, 5, 2, 3, 0, 1] */ function reduceRight(collection, iteratee, accumulator) { var func = isArray(collection) ? arrayReduceRight : baseReduce, initAccum = arguments.length < 3; return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight); } /** * The opposite of `_.filter`; this method returns the elements of `collection` * that `predicate` does **not** return truthy for. * * @static * @memberOf _ * @since 0.1.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. * @param {Array|Function|Object|string} [predicate=_.identity] * The function invoked per iteration. * @returns {Array} Returns the new filtered array. * @see _.filter * @example * * var users = [ * { 'user': 'barney', 'age': 36, 'active': false }, * { 'user': 'fred', 'age': 40, 'active': true } * ]; * * _.reject(users, function(o) { return !o.active; }); * // => objects for ['fred'] * * // The `_.matches` iteratee shorthand. * _.reject(users, { 'age': 40, 'active': true }); * // => objects for ['barney'] * * // The `_.matchesProperty` iteratee shorthand. * _.reject(users, ['active', false]); * // => objects for ['fred'] * * // The `_.property` iteratee shorthand. * _.reject(users, 'active'); * // => objects for ['barney'] */ function reject(collection, predicate) { var func = isArray(collection) ? arrayFilter : baseFilter; predicate = getIteratee(predicate, 3); return func(collection, function(value, index, collection) { return !predicate(value, index, collection); }); } /** * Gets a random element from `collection`. * * @static * @memberOf _ * @since 2.0.0 * @category Collection * @param {Array|Object} collection The collection to sample. * @returns {*} Returns the random element. * @example * * _.sample([1, 2, 3, 4]); * // => 2 */ function sample(collection) { var array = isArrayLike(collection) ? collection : values(collection), length = array.length; return length > 0 ? array[baseRandom(0, length - 1)] : undefined; } /** * Gets `n` random elements at unique keys from `collection` up to the * size of `collection`. * * @static * @memberOf _ * @since 4.0.0 * @category Collection * @param {Array|Object} collection The collection to sample. * @param {number} [n=1] The number of elements to sample. * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. * @returns {Array} Returns the random elements. * @example * * _.sampleSize([1, 2, 3], 2); * // => [3, 1] * * _.sampleSize([1, 2, 3], 4); * // => [2, 3, 1] */ function sampleSize(collection, n, guard) { var index = -1, result = toArray(collection), length = result.length, lastIndex = length - 1; if ((guard ? isIterateeCall(collection, n, guard) : n === undefined)) { n = 1; } else { n = baseClamp(toInteger(n), 0, length); } while (++index < n) { var rand = baseRandom(index, lastIndex), value = result[rand]; result[rand] = result[index]; result[index] = value; } result.length = n; return result; } /** * Creates an array of shuffled values, using a version of the * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle). * * @static * @memberOf _ * @since 0.1.0 * @category Collection * @param {Array|Object} collection The collection to shuffle. * @returns {Array} Returns the new shuffled array. * @example * * _.shuffle([1, 2, 3, 4]); * // => [4, 1, 3, 2] */ function shuffle(collection) { return sampleSize(collection, MAX_ARRAY_LENGTH); } /** * Gets the size of `collection` by returning its length for array-like * values or the number of own enumerable string keyed properties for objects. * * @static * @memberOf _ * @since 0.1.0 * @category Collection * @param {Array|Object} collection The collection to inspect. * @returns {number} Returns the collection size. * @example * * _.size([1, 2, 3]); * // => 3 * * _.size({ 'a': 1, 'b': 2 }); * // => 2 * * _.size('pebbles'); * // => 7 */ function size(collection) { if (collection == null) { return 0; } if (isArrayLike(collection)) { var result = collection.length; return (result && isString(collection)) ? stringSize(collection) : result; } if (isObjectLike(collection)) { var tag = getTag(collection); if (tag == mapTag || tag == setTag) { return collection.size; } } return keys(collection).length; } /** * Checks if `predicate` returns truthy for **any** element of `collection`. * Iteration is stopped once `predicate` returns truthy. The predicate is * invoked with three arguments: (value, index|key, collection). * * @static * @memberOf _ * @since 0.1.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. * @param {Array|Function|Object|string} [predicate=_.identity] * The function invoked per iteration. * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. * @returns {boolean} Returns `true` if any element passes the predicate check, * else `false`. * @example * * _.some([null, 0, 'yes', false], Boolean); * // => true * * var users = [ * { 'user': 'barney', 'active': true }, * { 'user': 'fred', 'active': false } * ]; * * // The `_.matches` iteratee shorthand. * _.some(users, { 'user': 'barney', 'active': false }); * // => false * * // The `_.matchesProperty` iteratee shorthand. * _.some(users, ['active', false]); * // => true * * // The `_.property` iteratee shorthand. * _.some(users, 'active'); * // => true */ function some(collection, predicate, guard) { var func = isArray(collection) ? arraySome : baseSome; if (guard && isIterateeCall(collection, predicate, guard)) { predicate = undefined; } return func(collection, getIteratee(predicate, 3)); } /** * Creates an array of elements, sorted in ascending order by the results of * running each element in a collection thru each iteratee. This method * performs a stable sort, that is, it preserves the original sort order of * equal elements. The iteratees are invoked with one argument: (value). * * @static * @memberOf _ * @since 0.1.0 * @category Collection * @param {Array|Object} collection The collection to iterate over. * @param {...(Array|Array[]|Function|Function[]|Object|Object[]|string|string[])} * [iteratees=[_.identity]] The iteratees to sort by. * @returns {Array} Returns the new sorted array. * @example * * var users = [ * { 'user': 'fred', 'age': 48 }, * { 'user': 'barney', 'age': 36 }, * { 'user': 'fred', 'age': 40 }, * { 'user': 'barney', 'age': 34 } * ]; * * _.sortBy(users, function(o) { return o.user; }); * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]] * * _.sortBy(users, ['user', 'age']); * // => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]] * * _.sortBy(users, 'user', function(o) { * return Math.floor(o.age / 10); * }); * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]] */ var sortBy = rest(function(collection, iteratees) { if (collection == null) { return []; } var length = iteratees.length; if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) { iteratees = []; } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) { iteratees = [iteratees[0]]; } iteratees = (iteratees.length == 1 && isArray(iteratees[0])) ? iteratees[0] : baseFlatten(iteratees, 1, isFlattenableIteratee); return baseOrderBy(collection, iteratees, []); }); /*------------------------------------------------------------------------*/ /** * Gets the timestamp of the number of milliseconds that have elapsed since * the Unix epoch (1 January 1970 00:00:00 UTC). * * @static * @memberOf _ * @since 2.4.0 * @type {Function} * @category Date * @returns {number} Returns the timestamp. * @example * * _.defer(function(stamp) { * console.log(_.now() - stamp); * }, _.now()); * // => Logs the number of milliseconds it took for the deferred function to be invoked. */ var now = Date.now; /*------------------------------------------------------------------------*/ /** * The opposite of `_.before`; this method creates a function that invokes * `func` once it's called `n` or more times. * * @static * @memberOf _ * @since 0.1.0 * @category Function * @param {number} n The number of calls before `func` is invoked. * @param {Function} func The function to restrict. * @returns {Function} Returns the new restricted function. * @example * * var saves = ['profile', 'settings']; * * var done = _.after(saves.length, function() { * console.log('done saving!'); * }); * * _.forEach(saves, function(type) { * asyncSave({ 'type': type, 'complete': done }); * }); * // => Logs 'done saving!' after the two async saves have completed. */ function after(n, func) { if (typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } n = toInteger(n); return function() { if (--n < 1) { return func.apply(this, arguments); } }; } /** * Creates a function that invokes `func`, with up to `n` arguments, * ignoring any additional arguments. * * @static * @memberOf _ * @since 3.0.0 * @category Function * @param {Function} func The function to cap arguments for. * @param {number} [n=func.length] The arity cap. * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. * @returns {Function} Returns the new capped function. * @example * * _.map(['6', '8', '10'], _.ary(parseInt, 1)); * // => [6, 8, 10] */ function ary(func, n, guard) { n = guard ? undefined : n; n = (func && n == null) ? func.length : n; return createWrapper(func, ARY_FLAG, undefined, undefined, undefined, undefined, n); } /** * Creates a function that invokes `func`, with the `this` binding and arguments * of the created function, while it's called less than `n` times. Subsequent * calls to the created function return the result of the last `func` invocation. * * @static * @memberOf _ * @since 3.0.0 * @category Function * @param {number} n The number of calls at which `func` is no longer invoked. * @param {Function} func The function to restrict. * @returns {Function} Returns the new restricted function. * @example * * jQuery(element).on('click', _.before(5, addContactToList)); * // => allows adding up to 4 contacts to the list */ function before(n, func) { var result; if (typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } n = toInteger(n); return function() { if (--n > 0) { result = func.apply(this, arguments); } if (n <= 1) { func = undefined; } return result; }; } /** * Creates a function that invokes `func` with the `this` binding of `thisArg` * and `partials` prepended to the arguments it receives. * * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds, * may be used as a placeholder for partially applied arguments. * * **Note:** Unlike native `Function#bind` this method doesn't set the "length" * property of bound functions. * * @static * @memberOf _ * @since 0.1.0 * @category Function * @param {Function} func The function to bind. * @param {*} thisArg The `this` binding of `func`. * @param {...*} [partials] The arguments to be partially applied. * @returns {Function} Returns the new bound function. * @example * * var greet = function(greeting, punctuation) { * return greeting + ' ' + this.user + punctuation; * }; * * var object = { 'user': 'fred' }; * * var bound = _.bind(greet, object, 'hi'); * bound('!'); * // => 'hi fred!' * * // Bound with placeholders. * var bound = _.bind(greet, object, _, '!'); * bound('hi'); * // => 'hi fred!' */ var bind = rest(function(func, thisArg, partials) { var bitmask = BIND_FLAG; if (partials.length) { var holders = replaceHolders(partials, getHolder(bind)); bitmask |= PARTIAL_FLAG; } return createWrapper(func, bitmask, thisArg, partials, holders); }); /** * Creates a function that invokes the method at `object[key]` with `partials` * prepended to the arguments it receives. * * This method differs from `_.bind` by allowing bound functions to reference * methods that may be redefined or don't yet exist. See * [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern) * for more details. * * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic * builds, may be used as a placeholder for partially applied arguments. * * @static * @memberOf _ * @since 0.10.0 * @category Function * @param {Object} object The object to invoke the method on. * @param {string} key The key of the method. * @param {...*} [partials] The arguments to be partially applied. * @returns {Function} Returns the new bound function. * @example * * var object = { * 'user': 'fred', * 'greet': function(greeting, punctuation) { * return greeting + ' ' + this.user + punctuation; * } * }; * * var bound = _.bindKey(object, 'greet', 'hi'); * bound('!'); * // => 'hi fred!' * * object.greet = function(greeting, punctuation) { * return greeting + 'ya ' + this.user + punctuation; * }; * * bound('!'); * // => 'hiya fred!' * * // Bound with placeholders. * var bound = _.bindKey(object, 'greet', _, '!'); * bound('hi'); * // => 'hiya fred!' */ var bindKey = rest(function(object, key, partials) { var bitmask = BIND_FLAG | BIND_KEY_FLAG; if (partials.length) { var holders = replaceHolders(partials, getHolder(bindKey)); bitmask |= PARTIAL_FLAG; } return createWrapper(key, bitmask, object, partials, holders); }); /** * Creates a function that accepts arguments of `func` and either invokes * `func` returning its result, if at least `arity` number of arguments have * been provided, or returns a function that accepts the remaining `func` * arguments, and so on. The arity of `func` may be specified if `func.length` * is not sufficient. * * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds, * may be used as a placeholder for provided arguments. * * **Note:** This method doesn't set the "length" property of curried functions. * * @static * @memberOf _ * @since 2.0.0 * @category Function * @param {Function} func The function to curry. * @param {number} [arity=func.length] The arity of `func`. * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. * @returns {Function} Returns the new curried function. * @example * * var abc = function(a, b, c) { * return [a, b, c]; * }; * * var curried = _.curry(abc); * * curried(1)(2)(3); * // => [1, 2, 3] * * curried(1, 2)(3); * // => [1, 2, 3] * * curried(1, 2, 3); * // => [1, 2, 3] * * // Curried with placeholders. * curried(1)(_, 3)(2); * // => [1, 2, 3] */ function curry(func, arity, guard) { arity = guard ? undefined : arity; var result = createWrapper(func, CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity); result.placeholder = curry.placeholder; return result; } /** * This method is like `_.curry` except that arguments are applied to `func` * in the manner of `_.partialRight` instead of `_.partial`. * * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic * builds, may be used as a placeholder for provided arguments. * * **Note:** This method doesn't set the "length" property of curried functions. * * @static * @memberOf _ * @since 3.0.0 * @category Function * @param {Function} func The function to curry. * @param {number} [arity=func.length] The arity of `func`. * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. * @returns {Function} Returns the new curried function. * @example * * var abc = function(a, b, c) { * return [a, b, c]; * }; * * var curried = _.curryRight(abc); * * curried(3)(2)(1); * // => [1, 2, 3] * * curried(2, 3)(1); * // => [1, 2, 3] * * curried(1, 2, 3); * // => [1, 2, 3] * * // Curried with placeholders. * curried(3)(1, _)(2); * // => [1, 2, 3] */ function curryRight(func, arity, guard) { arity = guard ? undefined : arity; var result = createWrapper(func, CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity); result.placeholder = curryRight.placeholder; return result; } /** * Creates a debounced function that delays invoking `func` until after `wait` * milliseconds have elapsed since the last time the debounced function was * invoked. The debounced function comes with a `cancel` method to cancel * delayed `func` invocations and a `flush` method to immediately invoke them. * Provide an options object to indicate whether `func` should be invoked on * the leading and/or trailing edge of the `wait` timeout. The `func` is invoked * with the last arguments provided to the debounced function. Subsequent calls * to the debounced function return the result of the last `func` invocation. * * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked * on the trailing edge of the timeout only if the debounced function is * invoked more than once during the `wait` timeout. * * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) * for details over the differences between `_.debounce` and `_.throttle`. * * @static * @memberOf _ * @since 0.1.0 * @category Function * @param {Function} func The function to debounce. * @param {number} [wait=0] The number of milliseconds to delay. * @param {Object} [options={}] The options object. * @param {boolean} [options.leading=false] * Specify invoking on the leading edge of the timeout. * @param {number} [options.maxWait] * The maximum time `func` is allowed to be delayed before it's invoked. * @param {boolean} [options.trailing=true] * Specify invoking on the trailing edge of the timeout. * @returns {Function} Returns the new debounced function. * @example * * // Avoid costly calculations while the window size is in flux. * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); * * // Invoke `sendMail` when clicked, debouncing subsequent calls. * jQuery(element).on('click', _.debounce(sendMail, 300, { * 'leading': true, * 'trailing': false * })); * * // Ensure `batchLog` is invoked once after 1 second of debounced calls. * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 }); * var source = new EventSource('/stream'); * jQuery(source).on('message', debounced); * * // Cancel the trailing debounced invocation. * jQuery(window).on('popstate', debounced.cancel); */ function debounce(func, wait, options) { var lastArgs, lastThis, maxWait, result, timerId, lastCallTime = 0, lastInvokeTime = 0, leading = false, maxing = false, trailing = true; if (typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } wait = toNumber(wait) || 0; if (isObject(options)) { leading = !!options.leading; maxing = 'maxWait' in options; maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait; trailing = 'trailing' in options ? !!options.trailing : trailing; } function invokeFunc(time) { var args = lastArgs, thisArg = lastThis; lastArgs = lastThis = undefined; lastInvokeTime = time; result = func.apply(thisArg, args); return result; } function leadingEdge(time) { // Reset any `maxWait` timer. lastInvokeTime = time; // Start the timer for the trailing edge. timerId = setTimeout(timerExpired, wait); // Invoke the leading edge. return leading ? invokeFunc(time) : result; } function remainingWait(time) { var timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime, result = wait - timeSinceLastCall; return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result; } function shouldInvoke(time) { var timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime; // Either this is the first call, activity has stopped and we're at the // trailing edge, the system time has gone backwards and we're treating // it as the trailing edge, or we've hit the `maxWait` limit. return (!lastCallTime || (timeSinceLastCall >= wait) || (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)); } function timerExpired() { var time = now(); if (shouldInvoke(time)) { return trailingEdge(time); } // Restart the timer. timerId = setTimeout(timerExpired, remainingWait(time)); } function trailingEdge(time) { clearTimeout(timerId); timerId = undefined; // Only invoke if we have `lastArgs` which means `func` has been // debounced at least once. if (trailing && lastArgs) { return invokeFunc(time); } lastArgs = lastThis = undefined; return result; } function cancel() { if (timerId !== undefined) { clearTimeout(timerId); } lastCallTime = lastInvokeTime = 0; lastArgs = lastThis = timerId = undefined; } function flush() { return timerId === undefined ? result : trailingEdge(now()); } function debounced() { var time = now(), isInvoking = shouldInvoke(time); lastArgs = arguments; lastThis = this; lastCallTime = time; if (isInvoking) { if (timerId === undefined) { return leadingEdge(lastCallTime); } if (maxing) { // Handle invocations in a tight loop. clearTimeout(timerId); timerId = setTimeout(timerExpired, wait); return invokeFunc(lastCallTime); } } if (timerId === undefined) { timerId = setTimeout(timerExpired, wait); } return result; } debounced.cancel = cancel; debounced.flush = flush; return debounced; } /** * Defers invoking the `func` until the current call stack has cleared. Any * additional arguments are provided to `func` when it's invoked. * * @static * @memberOf _ * @since 0.1.0 * @category Function * @param {Function} func The function to defer. * @param {...*} [args] The arguments to invoke `func` with. * @returns {number} Returns the timer id. * @example * * _.defer(function(text) { * console.log(text); * }, 'deferred'); * // => Logs 'deferred' after one or more milliseconds. */ var defer = rest(function(func, args) { return baseDelay(func, 1, args); }); /** * Invokes `func` after `wait` milliseconds. Any additional arguments are * provided to `func` when it's invoked. * * @static * @memberOf _ * @since 0.1.0 * @category Function * @param {Function} func The function to delay. * @param {number} wait The number of milliseconds to delay invocation. * @param {...*} [args] The arguments to invoke `func` with. * @returns {number} Returns the timer id. * @example * * _.delay(function(text) { * console.log(text); * }, 1000, 'later'); * // => Logs 'later' after one second. */ var delay = rest(function(func, wait, args) { return baseDelay(func, toNumber(wait) || 0, args); }); /** * Creates a function that invokes `func` with arguments reversed. * * @static * @memberOf _ * @since 4.0.0 * @category Function * @param {Function} func The function to flip arguments for. * @returns {Function} Returns the new flipped function. * @example * * var flipped = _.flip(function() { * return _.toArray(arguments); * }); * * flipped('a', 'b', 'c', 'd'); * // => ['d', 'c', 'b', 'a'] */ function flip(func) { return createWrapper(func, FLIP_FLAG); } /** * Creates a function that memoizes the result of `func`. If `resolver` is * provided, it determines the cache key for storing the result based on the * arguments provided to the memoized function. By default, the first argument * provided to the memoized function is used as the map cache key. The `func` * is invoked with the `this` binding of the memoized function. * * **Note:** The cache is exposed as the `cache` property on the memoized * function. Its creation may be customized by replacing the `_.memoize.Cache` * constructor with one whose instances implement the * [`Map`](http://ecma-international.org/ecma-262/6.0/#sec-properties-of-the-map-prototype-object) * method interface of `delete`, `get`, `has`, and `set`. * * @static * @memberOf _ * @since 0.1.0 * @category Function * @param {Function} func The function to have its output memoized. * @param {Function} [resolver] The function to resolve the cache key. * @returns {Function} Returns the new memoized function. * @example * * var object = { 'a': 1, 'b': 2 }; * var other = { 'c': 3, 'd': 4 }; * * var values = _.memoize(_.values); * values(object); * // => [1, 2] * * values(other); * // => [3, 4] * * object.a = 2; * values(object); * // => [1, 2] * * // Modify the result cache. * values.cache.set(object, ['a', 'b']); * values(object); * // => ['a', 'b'] * * // Replace `_.memoize.Cache`. * _.memoize.Cache = WeakMap; */ function memoize(func, resolver) { if (typeof func != 'function' || (resolver && typeof resolver != 'function')) { throw new TypeError(FUNC_ERROR_TEXT); } var memoized = function() { var args = arguments, key = resolver ? resolver.apply(this, args) : args[0], cache = memoized.cache; if (cache.has(key)) { return cache.get(key); } var result = func.apply(this, args); memoized.cache = cache.set(key, result); return result; }; memoized.cache = new (memoize.Cache || MapCache); return memoized; } // Assign cache to `_.memoize`. memoize.Cache = MapCache; /** * Creates a function that negates the result of the predicate `func`. The * `func` predicate is invoked with the `this` binding and arguments of the * created function. * * @static * @memberOf _ * @since 3.0.0 * @category Function * @param {Function} predicate The predicate to negate. * @returns {Function} Returns the new negated function. * @example * * function isEven(n) { * return n % 2 == 0; * } * * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)); * // => [1, 3, 5] */ function negate(predicate) { if (typeof predicate != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } return function() { return !predicate.apply(this, arguments); }; } /** * Creates a function that is restricted to invoking `func` once. Repeat calls * to the function return the value of the first invocation. The `func` is * invoked with the `this` binding and arguments of the created function. * * @static * @memberOf _ * @since 0.1.0 * @category Function * @param {Function} func The function to restrict. * @returns {Function} Returns the new restricted function. * @example * * var initialize = _.once(createApplication); * initialize(); * initialize(); * // `initialize` invokes `createApplication` once */ function once(func) { return before(2, func); } /** * Creates a function that invokes `func` with arguments transformed by * corresponding `transforms`. * * @static * @since 4.0.0 * @memberOf _ * @category Function * @param {Function} func The function to wrap. * @param {...(Array|Array[]|Function|Function[]|Object|Object[]|string|string[])} * [transforms[_.identity]] The functions to transform. * @returns {Function} Returns the new function. * @example * * function doubled(n) { * return n * 2; * } * * function square(n) { * return n * n; * } * * var func = _.overArgs(function(x, y) { * return [x, y]; * }, square, doubled); * * func(9, 3); * // => [81, 6] * * func(10, 5); * // => [100, 10] */ var overArgs = rest(function(func, transforms) { transforms = (transforms.length == 1 && isArray(transforms[0])) ? arrayMap(transforms[0], baseUnary(getIteratee())) : arrayMap(baseFlatten(transforms, 1, isFlattenableIteratee), baseUnary(getIteratee())); var funcsLength = transforms.length; return rest(function(args) { var index = -1, length = nativeMin(args.length, funcsLength); while (++index < length) { args[index] = transforms[index].call(this, args[index]); } return apply(func, this, args); }); }); /** * Creates a function that invokes `func` with `partials` prepended to the * arguments it receives. This method is like `_.bind` except it does **not** * alter the `this` binding. * * The `_.partial.placeholder` value, which defaults to `_` in monolithic * builds, may be used as a placeholder for partially applied arguments. * * **Note:** This method doesn't set the "length" property of partially * applied functions. * * @static * @memberOf _ * @since 0.2.0 * @category Function * @param {Function} func The function to partially apply arguments to. * @param {...*} [partials] The arguments to be partially applied. * @returns {Function} Returns the new partially applied function. * @example * * var greet = function(greeting, name) { * return greeting + ' ' + name; * }; * * var sayHelloTo = _.partial(greet, 'hello'); * sayHelloTo('fred'); * // => 'hello fred' * * // Partially applied with placeholders. * var greetFred = _.partial(greet, _, 'fred'); * greetFred('hi'); * // => 'hi fred' */ var partial = rest(function(func, partials) { var holders = replaceHolders(partials, getHolder(partial)); return createWrapper(func, PARTIAL_FLAG, undefined, partials, holders); }); /** * This method is like `_.partial` except that partially applied arguments * are appended to the arguments it receives. * * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic * builds, may be used as a placeholder for partially applied arguments. * * **Note:** This method doesn't set the "length" property of partially * applied functions. * * @static * @memberOf _ * @since 1.0.0 * @category Function * @param {Function} func The function to partially apply arguments to. * @param {...*} [partials] The arguments to be partially applied. * @returns {Function} Returns the new partially applied function. * @example * * var greet = function(greeting, name) { * return greeting + ' ' + name; * }; * * var greetFred = _.partialRight(greet, 'fred'); * greetFred('hi'); * // => 'hi fred' * * // Partially applied with placeholders. * var sayHelloTo = _.partialRight(greet, 'hello', _); * sayHelloTo('fred'); * // => 'hello fred' */ var partialRight = rest(function(func, partials) { var holders = replaceHolders(partials, getHolder(partialRight)); return createWrapper(func, PARTIAL_RIGHT_FLAG, undefined, partials, holders); }); /** * Creates a function that invokes `func` with arguments arranged according * to the specified `indexes` where the argument value at the first index is * provided as the first argument, the argument value at the second index is * provided as the second argument, and so on. * * @static * @memberOf _ * @since 3.0.0 * @category Function * @param {Function} func The function to rearrange arguments for. * @param {...(number|number[])} indexes The arranged argument indexes. * @returns {Function} Returns the new function. * @example * * var rearged = _.rearg(function(a, b, c) { * return [a, b, c]; * }, 2, 0, 1); * * rearged('b', 'c', 'a') * // => ['a', 'b', 'c'] */ var rearg = rest(function(func, indexes) { return createWrapper(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes, 1)); }); /** * Creates a function that invokes `func` with the `this` binding of the * created function and arguments from `start` and beyond provided as * an array. * * **Note:** This method is based on the * [rest parameter](https://mdn.io/rest_parameters). * * @static * @memberOf _ * @since 4.0.0 * @category Function * @param {Function} func The function to apply a rest parameter to. * @param {number} [start=func.length-1] The start position of the rest parameter. * @returns {Function} Returns the new function. * @example * * var say = _.rest(function(what, names) { * return what + ' ' + _.initial(names).join(', ') + * (_.size(names) > 1 ? ', & ' : '') + _.last(names); * }); * * say('hello', 'fred', 'barney', 'pebbles'); * // => 'hello fred, barney, & pebbles' */ function rest(func, start) { if (typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } start = nativeMax(start === undefined ? (func.length - 1) : toInteger(start), 0); return function() { var args = arguments, index = -1, length = nativeMax(args.length - start, 0), array = Array(length); while (++index < length) { array[index] = args[start + index]; } switch (start) { case 0: return func.call(this, array); case 1: return func.call(this, args[0], array); case 2: return func.call(this, args[0], args[1], array); } var otherArgs = Array(start + 1); index = -1; while (++index < start) { otherArgs[index] = args[index]; } otherArgs[start] = array; return apply(func, this, otherArgs); }; } /** * Creates a function that invokes `func` with the `this` binding of the * create function and an array of arguments much like * [`Function#apply`](http://www.ecma-international.org/ecma-262/6.0/#sec-function.prototype.apply). * * **Note:** This method is based on the * [spread operator](https://mdn.io/spread_operator). * * @static * @memberOf _ * @since 3.2.0 * @category Function * @param {Function} func The function to spread arguments over. * @param {number} [start=0] The start position of the spread. * @returns {Function} Returns the new function. * @example * * var say = _.spread(function(who, what) { * return who + ' says ' + what; * }); * * say(['fred', 'hello']); * // => 'fred says hello' * * var numbers = Promise.all([ * Promise.resolve(40), * Promise.resolve(36) * ]); * * numbers.then(_.spread(function(x, y) { * return x + y; * })); * // => a Promise of 76 */ function spread(func, start) { if (typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } start = start === undefined ? 0 : nativeMax(toInteger(start), 0); return rest(function(args) { var array = args[start], otherArgs = castSlice(args, 0, start); if (array) { arrayPush(otherArgs, array); } return apply(func, this, otherArgs); }); } /** * Creates a throttled function that only invokes `func` at most once per * every `wait` milliseconds. The throttled function comes with a `cancel` * method to cancel delayed `func` invocations and a `flush` method to * immediately invoke them. Provide an options object to indicate whether * `func` should be invoked on the leading and/or trailing edge of the `wait` * timeout. The `func` is invoked with the last arguments provided to the * throttled function. Subsequent calls to the throttled function return the * result of the last `func` invocation. * * **Note:** If `leading` and `trailing` options are `true`, `func` is * invoked on the trailing edge of the timeout only if the throttled function * is invoked more than once during the `wait` timeout. * * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) * for details over the differences between `_.throttle` and `_.debounce`. * * @static * @memberOf _ * @since 0.1.0 * @category Function * @param {Function} func The function to throttle. * @param {number} [wait=0] The number of milliseconds to throttle invocations to. * @param {Object} [options={}] The options object. * @param {boolean} [options.leading=true] * Specify invoking on the leading edge of the timeout. * @param {boolean} [options.trailing=true] * Specify invoking on the trailing edge of the timeout. * @returns {Function} Returns the new throttled function. * @example * * // Avoid excessively updating the position while scrolling. * jQuery(window).on('scroll', _.throttle(updatePosition, 100)); * * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes. * var throttled = _.throttle(renewToken, 300000, { 'trailing': false }); * jQuery(element).on('click', throttled); * * // Cancel the trailing throttled invocation. * jQuery(window).on('popstate', throttled.cancel); */ function throttle(func, wait, options) { var leading = true, trailing = true; if (typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } if (isObject(options)) { leading = 'leading' in options ? !!options.leading : leading; trailing = 'trailing' in options ? !!options.trailing : trailing; } return debounce(func, wait, { 'leading': leading, 'maxWait': wait, 'trailing': trailing }); } /** * Creates a function that accepts up to one argument, ignoring any * additional arguments. * * @static * @memberOf _ * @since 4.0.0 * @category Function * @param {Function} func The function to cap arguments for. * @returns {Function} Returns the new capped function. * @example * * _.map(['6', '8', '10'], _.unary(parseInt)); * // => [6, 8, 10] */ function unary(func) { return ary(func, 1); } /** * Creates a function that provides `value` to the wrapper function as its * first argument. Any additional arguments provided to the function are * appended to those provided to the wrapper function. The wrapper is invoked * with the `this` binding of the created function. * * @static * @memberOf _ * @since 0.1.0 * @category Function * @param {*} value The value to wrap. * @param {Function} [wrapper=identity] The wrapper function. * @returns {Function} Returns the new function. * @example * * var p = _.wrap(_.escape, function(func, text) { * return '

' + func(text) + '

'; * }); * * p('fred, barney, & pebbles'); * // => '

fred, barney, & pebbles

' */ function wrap(value, wrapper) { wrapper = wrapper == null ? identity : wrapper; return partial(wrapper, value); } /*------------------------------------------------------------------------*/ /** * Casts `value` as an array if it's not one. * * @static * @memberOf _ * @since 4.4.0 * @category Lang * @param {*} value The value to inspect. * @returns {Array} Returns the cast array. * @example * * _.castArray(1); * // => [1] * * _.castArray({ 'a': 1 }); * // => [{ 'a': 1 }] * * _.castArray('abc'); * // => ['abc'] * * _.castArray(null); * // => [null] * * _.castArray(undefined); * // => [undefined] * * _.castArray(); * // => [] * * var array = [1, 2, 3]; * console.log(_.castArray(array) === array); * // => true */ function castArray() { if (!arguments.length) { return []; } var value = arguments[0]; return isArray(value) ? value : [value]; } /** * Creates a shallow clone of `value`. * * **Note:** This method is loosely based on the * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm) * and supports cloning arrays, array buffers, booleans, date objects, maps, * numbers, `Object` objects, regexes, sets, strings, symbols, and typed * arrays. The own enumerable properties of `arguments` objects are cloned * as plain objects. An empty object is returned for uncloneable values such * as error objects, functions, DOM nodes, and WeakMaps. * * @static * @memberOf _ * @since 0.1.0 * @category Lang * @param {*} value The value to clone. * @returns {*} Returns the cloned value. * @see _.cloneDeep * @example * * var objects = [{ 'a': 1 }, { 'b': 2 }]; * * var shallow = _.clone(objects); * console.log(shallow[0] === objects[0]); * // => true */ function clone(value) { return baseClone(value, false, true); } /** * This method is like `_.clone` except that it accepts `customizer` which * is invoked to produce the cloned value. If `customizer` returns `undefined`, * cloning is handled by the method instead. The `customizer` is invoked with * up to four arguments; (value [, index|key, object, stack]). * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to clone. * @param {Function} [customizer] The function to customize cloning. * @returns {*} Returns the cloned value. * @see _.cloneDeepWith * @example * * function customizer(value) { * if (_.isElement(value)) { * return value.cloneNode(false); * } * } * * var el = _.cloneWith(document.body, customizer); * * console.log(el === document.body); * // => false * console.log(el.nodeName); * // => 'BODY' * console.log(el.childNodes.length); * // => 0 */ function cloneWith(value, customizer) { return baseClone(value, false, true, customizer); } /** * This method is like `_.clone` except that it recursively clones `value`. * * @static * @memberOf _ * @since 1.0.0 * @category Lang * @param {*} value The value to recursively clone. * @returns {*} Returns the deep cloned value. * @see _.clone * @example * * var objects = [{ 'a': 1 }, { 'b': 2 }]; * * var deep = _.cloneDeep(objects); * console.log(deep[0] === objects[0]); * // => false */ function cloneDeep(value) { return baseClone(value, true, true); } /** * This method is like `_.cloneWith` except that it recursively clones `value`. * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to recursively clone. * @param {Function} [customizer] The function to customize cloning. * @returns {*} Returns the deep cloned value. * @see _.cloneWith * @example * * function customizer(value) { * if (_.isElement(value)) { * return value.cloneNode(true); * } * } * * var el = _.cloneDeepWith(document.body, customizer); * * console.log(el === document.body); * // => false * console.log(el.nodeName); * // => 'BODY' * console.log(el.childNodes.length); * // => 20 */ function cloneDeepWith(value, customizer) { return baseClone(value, true, true, customizer); } /** * Performs a * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) * comparison between two values to determine if they are equivalent. * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to compare. * @param {*} other The other value to compare. * @returns {boolean} Returns `true` if the values are equivalent, else `false`. * @example * * var object = { 'user': 'fred' }; * var other = { 'user': 'fred' }; * * _.eq(object, object); * // => true * * _.eq(object, other); * // => false * * _.eq('a', 'a'); * // => true * * _.eq('a', Object('a')); * // => false * * _.eq(NaN, NaN); * // => true */ function eq(value, other) { return value === other || (value !== value && other !== other); } /** * Checks if `value` is greater than `other`. * * @static * @memberOf _ * @since 3.9.0 * @category Lang * @param {*} value The value to compare. * @param {*} other The other value to compare. * @returns {boolean} Returns `true` if `value` is greater than `other`, * else `false`. * @see _.lt * @example * * _.gt(3, 1); * // => true * * _.gt(3, 3); * // => false * * _.gt(1, 3); * // => false */ var gt = createRelationalOperation(baseGt); /** * Checks if `value` is greater than or equal to `other`. * * @static * @memberOf _ * @since 3.9.0 * @category Lang * @param {*} value The value to compare. * @param {*} other The other value to compare. * @returns {boolean} Returns `true` if `value` is greater than or equal to * `other`, else `false`. * @see _.lte * @example * * _.gte(3, 1); * // => true * * _.gte(3, 3); * // => true * * _.gte(1, 3); * // => false */ var gte = createRelationalOperation(function(value, other) { return value >= other; }); /** * Checks if `value` is likely an `arguments` object. * * @static * @memberOf _ * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, * else `false`. * @example * * _.isArguments(function() { return arguments; }()); * // => true * * _.isArguments([1, 2, 3]); * // => false */ function isArguments(value) { // Safari 8.1 incorrectly makes `arguments.callee` enumerable in strict mode. return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') && (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag); } /** * Checks if `value` is classified as an `Array` object. * * @static * @memberOf _ * @since 0.1.0 * @type {Function} * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, * else `false`. * @example * * _.isArray([1, 2, 3]); * // => true * * _.isArray(document.body.children); * // => false * * _.isArray('abc'); * // => false * * _.isArray(_.noop); * // => false */ var isArray = Array.isArray; /** * Checks if `value` is classified as an `ArrayBuffer` object. * * @static * @memberOf _ * @since 4.3.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, * else `false`. * @example * * _.isArrayBuffer(new ArrayBuffer(2)); * // => true * * _.isArrayBuffer(new Array(2)); * // => false */ function isArrayBuffer(value) { return isObjectLike(value) && objectToString.call(value) == arrayBufferTag; } /** * Checks if `value` is array-like. A value is considered array-like if it's * not a function and has a `value.length` that's an integer greater than or * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is array-like, else `false`. * @example * * _.isArrayLike([1, 2, 3]); * // => true * * _.isArrayLike(document.body.children); * // => true * * _.isArrayLike('abc'); * // => true * * _.isArrayLike(_.noop); * // => false */ function isArrayLike(value) { return value != null && isLength(getLength(value)) && !isFunction(value); } /** * This method is like `_.isArrayLike` except that it also checks if `value` * is an object. * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an array-like object, * else `false`. * @example * * _.isArrayLikeObject([1, 2, 3]); * // => true * * _.isArrayLikeObject(document.body.children); * // => true * * _.isArrayLikeObject('abc'); * // => false * * _.isArrayLikeObject(_.noop); * // => false */ function isArrayLikeObject(value) { return isObjectLike(value) && isArrayLike(value); } /** * Checks if `value` is classified as a boolean primitive or object. * * @static * @memberOf _ * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, * else `false`. * @example * * _.isBoolean(false); * // => true * * _.isBoolean(null); * // => false */ function isBoolean(value) { return value === true || value === false || (isObjectLike(value) && objectToString.call(value) == boolTag); } /** * Checks if `value` is a buffer. * * @static * @memberOf _ * @since 4.3.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a buffer, else `false`. * @example * * _.isBuffer(new Buffer(2)); * // => true * * _.isBuffer(new Uint8Array(2)); * // => false */ var isBuffer = !Buffer ? constant(false) : function(value) { return value instanceof Buffer; }; /** * Checks if `value` is classified as a `Date` object. * * @static * @memberOf _ * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, * else `false`. * @example * * _.isDate(new Date); * // => true * * _.isDate('Mon April 23 2012'); * // => false */ function isDate(value) { return isObjectLike(value) && objectToString.call(value) == dateTag; } /** * Checks if `value` is likely a DOM element. * * @static * @memberOf _ * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a DOM element, * else `false`. * @example * * _.isElement(document.body); * // => true * * _.isElement(''); * // => false */ function isElement(value) { return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value); } /** * Checks if `value` is an empty object, collection, map, or set. * * Objects are considered empty if they have no own enumerable string keyed * properties. * * Array-like values such as `arguments` objects, arrays, buffers, strings, or * jQuery-like collections are considered empty if they have a `length` of `0`. * Similarly, maps and sets are considered empty if they have a `size` of `0`. * * @static * @memberOf _ * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is empty, else `false`. * @example * * _.isEmpty(null); * // => true * * _.isEmpty(true); * // => true * * _.isEmpty(1); * // => true * * _.isEmpty([1, 2, 3]); * // => false * * _.isEmpty({ 'a': 1 }); * // => false */ function isEmpty(value) { if (isArrayLike(value) && (isArray(value) || isString(value) || isFunction(value.splice) || isArguments(value) || isBuffer(value))) { return !value.length; } if (isObjectLike(value)) { var tag = getTag(value); if (tag == mapTag || tag == setTag) { return !value.size; } } for (var key in value) { if (hasOwnProperty.call(value, key)) { return false; } } return !(nonEnumShadows && keys(value).length); } /** * Performs a deep comparison between two values to determine if they are * equivalent. * * **Note:** This method supports comparing arrays, array buffers, booleans, * date objects, error objects, maps, numbers, `Object` objects, regexes, * sets, strings, symbols, and typed arrays. `Object` objects are compared * by their own, not inherited, enumerable properties. Functions and DOM * nodes are **not** supported. * * @static * @memberOf _ * @since 0.1.0 * @category Lang * @param {*} value The value to compare. * @param {*} other The other value to compare. * @returns {boolean} Returns `true` if the values are equivalent, * else `false`. * @example * * var object = { 'user': 'fred' }; * var other = { 'user': 'fred' }; * * _.isEqual(object, other); * // => true * * object === other; * // => false */ function isEqual(value, other) { return baseIsEqual(value, other); } /** * This method is like `_.isEqual` except that it accepts `customizer` which * is invoked to compare values. If `customizer` returns `undefined`, comparisons * are handled by the method instead. The `customizer` is invoked with up to * six arguments: (objValue, othValue [, index|key, object, other, stack]). * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to compare. * @param {*} other The other value to compare. * @param {Function} [customizer] The function to customize comparisons. * @returns {boolean} Returns `true` if the values are equivalent, * else `false`. * @example * * function isGreeting(value) { * return /^h(?:i|ello)$/.test(value); * } * * function customizer(objValue, othValue) { * if (isGreeting(objValue) && isGreeting(othValue)) { * return true; * } * } * * var array = ['hello', 'goodbye']; * var other = ['hi', 'goodbye']; * * _.isEqualWith(array, other, customizer); * // => true */ function isEqualWith(value, other, customizer) { customizer = typeof customizer == 'function' ? customizer : undefined; var result = customizer ? customizer(value, other) : undefined; return result === undefined ? baseIsEqual(value, other, customizer) : !!result; } /** * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`, * `SyntaxError`, `TypeError`, or `URIError` object. * * @static * @memberOf _ * @since 3.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an error object, * else `false`. * @example * * _.isError(new Error); * // => true * * _.isError(Error); * // => false */ function isError(value) { if (!isObjectLike(value)) { return false; } return (objectToString.call(value) == errorTag) || (typeof value.message == 'string' && typeof value.name == 'string'); } /** * Checks if `value` is a finite primitive number. * * **Note:** This method is based on * [`Number.isFinite`](https://mdn.io/Number/isFinite). * * @static * @memberOf _ * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a finite number, * else `false`. * @example * * _.isFinite(3); * // => true * * _.isFinite(Number.MIN_VALUE); * // => true * * _.isFinite(Infinity); * // => false * * _.isFinite('3'); * // => false */ function isFinite(value) { return typeof value == 'number' && nativeIsFinite(value); } /** * Checks if `value` is classified as a `Function` object. * * @static * @memberOf _ * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, * else `false`. * @example * * _.isFunction(_); * // => true * * _.isFunction(/abc/); * // => false */ function isFunction(value) { // The use of `Object#toString` avoids issues with the `typeof` operator // in Safari 8 which returns 'object' for typed array and weak map constructors, // and PhantomJS 1.9 which returns 'function' for `NodeList` instances. var tag = isObject(value) ? objectToString.call(value) : ''; return tag == funcTag || tag == genTag; } /** * Checks if `value` is an integer. * * **Note:** This method is based on * [`Number.isInteger`](https://mdn.io/Number/isInteger). * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an integer, else `false`. * @example * * _.isInteger(3); * // => true * * _.isInteger(Number.MIN_VALUE); * // => false * * _.isInteger(Infinity); * // => false * * _.isInteger('3'); * // => false */ function isInteger(value) { return typeof value == 'number' && value == toInteger(value); } /** * Checks if `value` is a valid array-like length. * * **Note:** This function is loosely based on * [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength). * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a valid length, * else `false`. * @example * * _.isLength(3); * // => true * * _.isLength(Number.MIN_VALUE); * // => false * * _.isLength(Infinity); * // => false * * _.isLength('3'); * // => false */ function isLength(value) { return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; } /** * Checks if `value` is the * [language type](http://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-language-types) * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) * * @static * @memberOf _ * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an object, else `false`. * @example * * _.isObject({}); * // => true * * _.isObject([1, 2, 3]); * // => true * * _.isObject(_.noop); * // => true * * _.isObject(null); * // => false */ function isObject(value) { var type = typeof value; return !!value && (type == 'object' || type == 'function'); } /** * Checks if `value` is object-like. A value is object-like if it's not `null` * and has a `typeof` result of "object". * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is object-like, else `false`. * @example * * _.isObjectLike({}); * // => true * * _.isObjectLike([1, 2, 3]); * // => true * * _.isObjectLike(_.noop); * // => false * * _.isObjectLike(null); * // => false */ function isObjectLike(value) { return !!value && typeof value == 'object'; } /** * Checks if `value` is classified as a `Map` object. * * @static * @memberOf _ * @since 4.3.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, * else `false`. * @example * * _.isMap(new Map); * // => true * * _.isMap(new WeakMap); * // => false */ function isMap(value) { return isObjectLike(value) && getTag(value) == mapTag; } /** * Performs a partial deep comparison between `object` and `source` to * determine if `object` contains equivalent property values. This method is * equivalent to a `_.matches` function when `source` is partially applied. * * **Note:** This method supports comparing the same values as `_.isEqual`. * * @static * @memberOf _ * @since 3.0.0 * @category Lang * @param {Object} object The object to inspect. * @param {Object} source The object of property values to match. * @returns {boolean} Returns `true` if `object` is a match, else `false`. * @example * * var object = { 'user': 'fred', 'age': 40 }; * * _.isMatch(object, { 'age': 40 }); * // => true * * _.isMatch(object, { 'age': 36 }); * // => false */ function isMatch(object, source) { return object === source || baseIsMatch(object, source, getMatchData(source)); } /** * This method is like `_.isMatch` except that it accepts `customizer` which * is invoked to compare values. If `customizer` returns `undefined`, comparisons * are handled by the method instead. The `customizer` is invoked with five * arguments: (objValue, srcValue, index|key, object, source). * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {Object} object The object to inspect. * @param {Object} source The object of property values to match. * @param {Function} [customizer] The function to customize comparisons. * @returns {boolean} Returns `true` if `object` is a match, else `false`. * @example * * function isGreeting(value) { * return /^h(?:i|ello)$/.test(value); * } * * function customizer(objValue, srcValue) { * if (isGreeting(objValue) && isGreeting(srcValue)) { * return true; * } * } * * var object = { 'greeting': 'hello' }; * var source = { 'greeting': 'hi' }; * * _.isMatchWith(object, source, customizer); * // => true */ function isMatchWith(object, source, customizer) { customizer = typeof customizer == 'function' ? customizer : undefined; return baseIsMatch(object, source, getMatchData(source), customizer); } /** * Checks if `value` is `NaN`. * * **Note:** This method is based on * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for * `undefined` and other non-number values. * * @static * @memberOf _ * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. * @example * * _.isNaN(NaN); * // => true * * _.isNaN(new Number(NaN)); * // => true * * isNaN(undefined); * // => true * * _.isNaN(undefined); * // => false */ function isNaN(value) { // An `NaN` primitive is the only value that is not equal to itself. // Perform the `toStringTag` check first to avoid errors with some // ActiveX objects in IE. return isNumber(value) && value != +value; } /** * Checks if `value` is a native function. * * @static * @memberOf _ * @since 3.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a native function, * else `false`. * @example * * _.isNative(Array.prototype.push); * // => true * * _.isNative(_); * // => false */ function isNative(value) { if (!isObject(value)) { return false; } var pattern = (isFunction(value) || isHostObject(value)) ? reIsNative : reIsHostCtor; return pattern.test(toSource(value)); } /** * Checks if `value` is `null`. * * @static * @memberOf _ * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is `null`, else `false`. * @example * * _.isNull(null); * // => true * * _.isNull(void 0); * // => false */ function isNull(value) { return value === null; } /** * Checks if `value` is `null` or `undefined`. * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is nullish, else `false`. * @example * * _.isNil(null); * // => true * * _.isNil(void 0); * // => true * * _.isNil(NaN); * // => false */ function isNil(value) { return value == null; } /** * Checks if `value` is classified as a `Number` primitive or object. * * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are * classified as numbers, use the `_.isFinite` method. * * @static * @memberOf _ * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, * else `false`. * @example * * _.isNumber(3); * // => true * * _.isNumber(Number.MIN_VALUE); * // => true * * _.isNumber(Infinity); * // => true * * _.isNumber('3'); * // => false */ function isNumber(value) { return typeof value == 'number' || (isObjectLike(value) && objectToString.call(value) == numberTag); } /** * Checks if `value` is a plain object, that is, an object created by the * `Object` constructor or one with a `[[Prototype]]` of `null`. * * @static * @memberOf _ * @since 0.8.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a plain object, * else `false`. * @example * * function Foo() { * this.a = 1; * } * * _.isPlainObject(new Foo); * // => false * * _.isPlainObject([1, 2, 3]); * // => false * * _.isPlainObject({ 'x': 0, 'y': 0 }); * // => true * * _.isPlainObject(Object.create(null)); * // => true */ function isPlainObject(value) { if (!isObjectLike(value) || objectToString.call(value) != objectTag || isHostObject(value)) { return false; } var proto = getPrototype(value); if (proto === null) { return true; } var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor; return (typeof Ctor == 'function' && Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString); } /** * Checks if `value` is classified as a `RegExp` object. * * @static * @memberOf _ * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, * else `false`. * @example * * _.isRegExp(/abc/); * // => true * * _.isRegExp('/abc/'); * // => false */ function isRegExp(value) { return isObject(value) && objectToString.call(value) == regexpTag; } /** * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754 * double precision number which isn't the result of a rounded unsafe integer. * * **Note:** This method is based on * [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger). * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a safe integer, * else `false`. * @example * * _.isSafeInteger(3); * // => true * * _.isSafeInteger(Number.MIN_VALUE); * // => false * * _.isSafeInteger(Infinity); * // => false * * _.isSafeInteger('3'); * // => false */ function isSafeInteger(value) { return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER; } /** * Checks if `value` is classified as a `Set` object. * * @static * @memberOf _ * @since 4.3.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, * else `false`. * @example * * _.isSet(new Set); * // => true * * _.isSet(new WeakSet); * // => false */ function isSet(value) { return isObjectLike(value) && getTag(value) == setTag; } /** * Checks if `value` is classified as a `String` primitive or object. * * @static * @since 0.1.0 * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, * else `false`. * @example * * _.isString('abc'); * // => true * * _.isString(1); * // => false */ function isString(value) { return typeof value == 'string' || (!isArray(value) && isObjectLike(value) && objectToString.call(value) == stringTag); } /** * Checks if `value` is classified as a `Symbol` primitive or object. * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, * else `false`. * @example * * _.isSymbol(Symbol.iterator); * // => true * * _.isSymbol('abc'); * // => false */ function isSymbol(value) { return typeof value == 'symbol' || (isObjectLike(value) && objectToString.call(value) == symbolTag); } /** * Checks if `value` is classified as a typed array. * * @static * @memberOf _ * @since 3.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, * else `false`. * @example * * _.isTypedArray(new Uint8Array); * // => true * * _.isTypedArray([]); * // => false */ function isTypedArray(value) { return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objectToString.call(value)]; } /** * Checks if `value` is `undefined`. * * @static * @since 0.1.0 * @memberOf _ * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`. * @example * * _.isUndefined(void 0); * // => true * * _.isUndefined(null); * // => false */ function isUndefined(value) { return value === undefined; } /** * Checks if `value` is classified as a `WeakMap` object. * * @static * @memberOf _ * @since 4.3.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, * else `false`. * @example * * _.isWeakMap(new WeakMap); * // => true * * _.isWeakMap(new Map); * // => false */ function isWeakMap(value) { return isObjectLike(value) && getTag(value) == weakMapTag; } /** * Checks if `value` is classified as a `WeakSet` object. * * @static * @memberOf _ * @since 4.3.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is correctly classified, * else `false`. * @example * * _.isWeakSet(new WeakSet); * // => true * * _.isWeakSet(new Set); * // => false */ function isWeakSet(value) { return isObjectLike(value) && objectToString.call(value) == weakSetTag; } /** * Checks if `value` is less than `other`. * * @static * @memberOf _ * @since 3.9.0 * @category Lang * @param {*} value The value to compare. * @param {*} other The other value to compare. * @returns {boolean} Returns `true` if `value` is less than `other`, * else `false`. * @see _.gt * @example * * _.lt(1, 3); * // => true * * _.lt(3, 3); * // => false * * _.lt(3, 1); * // => false */ var lt = createRelationalOperation(baseLt); /** * Checks if `value` is less than or equal to `other`. * * @static * @memberOf _ * @since 3.9.0 * @category Lang * @param {*} value The value to compare. * @param {*} other The other value to compare. * @returns {boolean} Returns `true` if `value` is less than or equal to * `other`, else `false`. * @see _.gte * @example * * _.lte(1, 3); * // => true * * _.lte(3, 3); * // => true * * _.lte(3, 1); * // => false */ var lte = createRelationalOperation(function(value, other) { return value <= other; }); /** * Converts `value` to an array. * * @static * @since 0.1.0 * @memberOf _ * @category Lang * @param {*} value The value to convert. * @returns {Array} Returns the converted array. * @example * * _.toArray({ 'a': 1, 'b': 2 }); * // => [1, 2] * * _.toArray('abc'); * // => ['a', 'b', 'c'] * * _.toArray(1); * // => [] * * _.toArray(null); * // => [] */ function toArray(value) { if (!value) { return []; } if (isArrayLike(value)) { return isString(value) ? stringToArray(value) : copyArray(value); } if (iteratorSymbol && value[iteratorSymbol]) { return iteratorToArray(value[iteratorSymbol]()); } var tag = getTag(value), func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values); return func(value); } /** * Converts `value` to a finite number. * * @static * @memberOf _ * @since 4.12.0 * @category Lang * @param {*} value The value to convert. * @returns {number} Returns the converted number. * @example * * _.toFinite(3.2); * // => 3.2 * * _.toFinite(Number.MIN_VALUE); * // => 5e-324 * * _.toFinite(Infinity); * // => 1.7976931348623157e+308 * * _.toFinite('3.2'); * // => 3.2 */ function toFinite(value) { if (!value) { return value === 0 ? value : 0; } value = toNumber(value); if (value === INFINITY || value === -INFINITY) { var sign = (value < 0 ? -1 : 1); return sign * MAX_INTEGER; } return value === value ? value : 0; } /** * Converts `value` to an integer. * * **Note:** This function is loosely based on * [`ToInteger`](http://www.ecma-international.org/ecma-262/6.0/#sec-tointeger). * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to convert. * @returns {number} Returns the converted integer. * @example * * _.toInteger(3.2); * // => 3 * * _.toInteger(Number.MIN_VALUE); * // => 0 * * _.toInteger(Infinity); * // => 1.7976931348623157e+308 * * _.toInteger('3.2'); * // => 3 */ function toInteger(value) { var result = toFinite(value), remainder = result % 1; return result === result ? (remainder ? result - remainder : result) : 0; } /** * Converts `value` to an integer suitable for use as the length of an * array-like object. * * **Note:** This method is based on * [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength). * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to convert. * @returns {number} Returns the converted integer. * @example * * _.toLength(3.2); * // => 3 * * _.toLength(Number.MIN_VALUE); * // => 0 * * _.toLength(Infinity); * // => 4294967295 * * _.toLength('3.2'); * // => 3 */ function toLength(value) { return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0; } /** * Converts `value` to a number. * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to process. * @returns {number} Returns the number. * @example * * _.toNumber(3.2); * // => 3.2 * * _.toNumber(Number.MIN_VALUE); * // => 5e-324 * * _.toNumber(Infinity); * // => Infinity * * _.toNumber('3.2'); * // => 3.2 */ function toNumber(value) { if (typeof value == 'number') { return value; } if (isSymbol(value)) { return NAN; } if (isObject(value)) { var other = isFunction(value.valueOf) ? value.valueOf() : value; value = isObject(other) ? (other + '') : other; } if (typeof value != 'string') { return value === 0 ? value : +value; } value = value.replace(reTrim, ''); var isBinary = reIsBinary.test(value); return (isBinary || reIsOctal.test(value)) ? freeParseInt(value.slice(2), isBinary ? 2 : 8) : (reIsBadHex.test(value) ? NAN : +value); } /** * Converts `value` to a plain object flattening inherited enumerable string * keyed properties of `value` to own properties of the plain object. * * @static * @memberOf _ * @since 3.0.0 * @category Lang * @param {*} value The value to convert. * @returns {Object} Returns the converted plain object. * @example * * function Foo() { * this.b = 2; * } * * Foo.prototype.c = 3; * * _.assign({ 'a': 1 }, new Foo); * // => { 'a': 1, 'b': 2 } * * _.assign({ 'a': 1 }, _.toPlainObject(new Foo)); * // => { 'a': 1, 'b': 2, 'c': 3 } */ function toPlainObject(value) { return copyObject(value, keysIn(value)); } /** * Converts `value` to a safe integer. A safe integer can be compared and * represented correctly. * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to convert. * @returns {number} Returns the converted integer. * @example * * _.toSafeInteger(3.2); * // => 3 * * _.toSafeInteger(Number.MIN_VALUE); * // => 0 * * _.toSafeInteger(Infinity); * // => 9007199254740991 * * _.toSafeInteger('3.2'); * // => 3 */ function toSafeInteger(value) { return baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER); } /** * Converts `value` to a string. An empty string is returned for `null` * and `undefined` values. The sign of `-0` is preserved. * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to process. * @returns {string} Returns the string. * @example * * _.toString(null); * // => '' * * _.toString(-0); * // => '-0' * * _.toString([1, 2, 3]); * // => '1,2,3' */ function toString(value) { return value == null ? '' : baseToString(value); } /*------------------------------------------------------------------------*/ /** * Assigns own enumerable string keyed properties of source objects to the * destination object. Source objects are applied from left to right. * Subsequent sources overwrite property assignments of previous sources. * * **Note:** This method mutates `object` and is loosely based on * [`Object.assign`](https://mdn.io/Object/assign). * * @static * @memberOf _ * @since 0.10.0 * @category Object * @param {Object} object The destination object. * @param {...Object} [sources] The source objects. * @returns {Object} Returns `object`. * @see _.assignIn * @example * * function Foo() { * this.c = 3; * } * * function Bar() { * this.e = 5; * } * * Foo.prototype.d = 4; * Bar.prototype.f = 6; * * _.assign({ 'a': 1 }, new Foo, new Bar); * // => { 'a': 1, 'c': 3, 'e': 5 } */ var assign = createAssigner(function(object, source) { if (nonEnumShadows || isPrototype(source) || isArrayLike(source)) { copyObject(source, keys(source), object); return; } for (var key in source) { if (hasOwnProperty.call(source, key)) { assignValue(object, key, source[key]); } } }); /** * This method is like `_.assign` except that it iterates over own and * inherited source properties. * * **Note:** This method mutates `object`. * * @static * @memberOf _ * @since 4.0.0 * @alias extend * @category Object * @param {Object} object The destination object. * @param {...Object} [sources] The source objects. * @returns {Object} Returns `object`. * @see _.assign * @example * * function Foo() { * this.b = 2; * } * * function Bar() { * this.d = 4; * } * * Foo.prototype.c = 3; * Bar.prototype.e = 5; * * _.assignIn({ 'a': 1 }, new Foo, new Bar); * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5 } */ var assignIn = createAssigner(function(object, source) { if (nonEnumShadows || isPrototype(source) || isArrayLike(source)) { copyObject(source, keysIn(source), object); return; } for (var key in source) { assignValue(object, key, source[key]); } }); /** * This method is like `_.assignIn` except that it accepts `customizer` * which is invoked to produce the assigned values. If `customizer` returns * `undefined`, assignment is handled by the method instead. The `customizer` * is invoked with five arguments: (objValue, srcValue, key, object, source). * * **Note:** This method mutates `object`. * * @static * @memberOf _ * @since 4.0.0 * @alias extendWith * @category Object * @param {Object} object The destination object. * @param {...Object} sources The source objects. * @param {Function} [customizer] The function to customize assigned values. * @returns {Object} Returns `object`. * @see _.assignWith * @example * * function customizer(objValue, srcValue) { * return _.isUndefined(objValue) ? srcValue : objValue; * } * * var defaults = _.partialRight(_.assignInWith, customizer); * * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); * // => { 'a': 1, 'b': 2 } */ var assignInWith = createAssigner(function(object, source, srcIndex, customizer) { copyObject(source, keysIn(source), object, customizer); }); /** * This method is like `_.assign` except that it accepts `customizer` * which is invoked to produce the assigned values. If `customizer` returns * `undefined`, assignment is handled by the method instead. The `customizer` * is invoked with five arguments: (objValue, srcValue, key, object, source). * * **Note:** This method mutates `object`. * * @static * @memberOf _ * @since 4.0.0 * @category Object * @param {Object} object The destination object. * @param {...Object} sources The source objects. * @param {Function} [customizer] The function to customize assigned values. * @returns {Object} Returns `object`. * @see _.assignInWith * @example * * function customizer(objValue, srcValue) { * return _.isUndefined(objValue) ? srcValue : objValue; * } * * var defaults = _.partialRight(_.assignWith, customizer); * * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); * // => { 'a': 1, 'b': 2 } */ var assignWith = createAssigner(function(object, source, srcIndex, customizer) { copyObject(source, keys(source), object, customizer); }); /** * Creates an array of values corresponding to `paths` of `object`. * * @static * @memberOf _ * @since 1.0.0 * @category Object * @param {Object} object The object to iterate over. * @param {...(string|string[])} [paths] The property paths of elements to pick. * @returns {Array} Returns the picked values. * @example * * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] }; * * _.at(object, ['a[0].b.c', 'a[1]']); * // => [3, 4] * * _.at(['a', 'b', 'c'], 0, 2); * // => ['a', 'c'] */ var at = rest(function(object, paths) { return baseAt(object, baseFlatten(paths, 1)); }); /** * Creates an object that inherits from the `prototype` object. If a * `properties` object is given, its own enumerable string keyed properties * are assigned to the created object. * * @static * @memberOf _ * @since 2.3.0 * @category Object * @param {Object} prototype The object to inherit from. * @param {Object} [properties] The properties to assign to the object. * @returns {Object} Returns the new object. * @example * * function Shape() { * this.x = 0; * this.y = 0; * } * * function Circle() { * Shape.call(this); * } * * Circle.prototype = _.create(Shape.prototype, { * 'constructor': Circle * }); * * var circle = new Circle; * circle instanceof Circle; * // => true * * circle instanceof Shape; * // => true */ function create(prototype, properties) { var result = baseCreate(prototype); return properties ? baseAssign(result, properties) : result; } /** * Assigns own and inherited enumerable string keyed properties of source * objects to the destination object for all destination properties that * resolve to `undefined`. Source objects are applied from left to right. * Once a property is set, additional values of the same property are ignored. * * **Note:** This method mutates `object`. * * @static * @since 0.1.0 * @memberOf _ * @category Object * @param {Object} object The destination object. * @param {...Object} [sources] The source objects. * @returns {Object} Returns `object`. * @see _.defaultsDeep * @example * * _.defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' }); * // => { 'user': 'barney', 'age': 36 } */ var defaults = rest(function(args) { args.push(undefined, assignInDefaults); return apply(assignInWith, undefined, args); }); /** * This method is like `_.defaults` except that it recursively assigns * default properties. * * **Note:** This method mutates `object`. * * @static * @memberOf _ * @since 3.10.0 * @category Object * @param {Object} object The destination object. * @param {...Object} [sources] The source objects. * @returns {Object} Returns `object`. * @see _.defaults * @example * * _.defaultsDeep({ 'user': { 'name': 'barney' } }, { 'user': { 'name': 'fred', 'age': 36 } }); * // => { 'user': { 'name': 'barney', 'age': 36 } } * */ var defaultsDeep = rest(function(args) { args.push(undefined, mergeDefaults); return apply(mergeWith, undefined, args); }); /** * This method is like `_.find` except that it returns the key of the first * element `predicate` returns truthy for instead of the element itself. * * @static * @memberOf _ * @since 1.1.0 * @category Object * @param {Object} object The object to search. * @param {Array|Function|Object|string} [predicate=_.identity] * The function invoked per iteration. * @returns {string|undefined} Returns the key of the matched element, * else `undefined`. * @example * * var users = { * 'barney': { 'age': 36, 'active': true }, * 'fred': { 'age': 40, 'active': false }, * 'pebbles': { 'age': 1, 'active': true } * }; * * _.findKey(users, function(o) { return o.age < 40; }); * // => 'barney' (iteration order is not guaranteed) * * // The `_.matches` iteratee shorthand. * _.findKey(users, { 'age': 1, 'active': true }); * // => 'pebbles' * * // The `_.matchesProperty` iteratee shorthand. * _.findKey(users, ['active', false]); * // => 'fred' * * // The `_.property` iteratee shorthand. * _.findKey(users, 'active'); * // => 'barney' */ function findKey(object, predicate) { return baseFind(object, getIteratee(predicate, 3), baseForOwn, true); } /** * This method is like `_.findKey` except that it iterates over elements of * a collection in the opposite order. * * @static * @memberOf _ * @since 2.0.0 * @category Object * @param {Object} object The object to search. * @param {Array|Function|Object|string} [predicate=_.identity] * The function invoked per iteration. * @returns {string|undefined} Returns the key of the matched element, * else `undefined`. * @example * * var users = { * 'barney': { 'age': 36, 'active': true }, * 'fred': { 'age': 40, 'active': false }, * 'pebbles': { 'age': 1, 'active': true } * }; * * _.findLastKey(users, function(o) { return o.age < 40; }); * // => returns 'pebbles' assuming `_.findKey` returns 'barney' * * // The `_.matches` iteratee shorthand. * _.findLastKey(users, { 'age': 36, 'active': true }); * // => 'barney' * * // The `_.matchesProperty` iteratee shorthand. * _.findLastKey(users, ['active', false]); * // => 'fred' * * // The `_.property` iteratee shorthand. * _.findLastKey(users, 'active'); * // => 'pebbles' */ function findLastKey(object, predicate) { return baseFind(object, getIteratee(predicate, 3), baseForOwnRight, true); } /** * Iterates over own and inherited enumerable string keyed properties of an * object and invokes `iteratee` for each property. The iteratee is invoked * with three arguments: (value, key, object). Iteratee functions may exit * iteration early by explicitly returning `false`. * * @static * @memberOf _ * @since 0.3.0 * @category Object * @param {Object} object The object to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @returns {Object} Returns `object`. * @see _.forInRight * @example * * function Foo() { * this.a = 1; * this.b = 2; * } * * Foo.prototype.c = 3; * * _.forIn(new Foo, function(value, key) { * console.log(key); * }); * // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed). */ function forIn(object, iteratee) { return object == null ? object : baseFor(object, getIteratee(iteratee, 3), keysIn); } /** * This method is like `_.forIn` except that it iterates over properties of * `object` in the opposite order. * * @static * @memberOf _ * @since 2.0.0 * @category Object * @param {Object} object The object to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @returns {Object} Returns `object`. * @see _.forIn * @example * * function Foo() { * this.a = 1; * this.b = 2; * } * * Foo.prototype.c = 3; * * _.forInRight(new Foo, function(value, key) { * console.log(key); * }); * // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'. */ function forInRight(object, iteratee) { return object == null ? object : baseForRight(object, getIteratee(iteratee, 3), keysIn); } /** * Iterates over own enumerable string keyed properties of an object and * invokes `iteratee` for each property. The iteratee is invoked with three * arguments: (value, key, object). Iteratee functions may exit iteration * early by explicitly returning `false`. * * @static * @memberOf _ * @since 0.3.0 * @category Object * @param {Object} object The object to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @returns {Object} Returns `object`. * @see _.forOwnRight * @example * * function Foo() { * this.a = 1; * this.b = 2; * } * * Foo.prototype.c = 3; * * _.forOwn(new Foo, function(value, key) { * console.log(key); * }); * // => Logs 'a' then 'b' (iteration order is not guaranteed). */ function forOwn(object, iteratee) { return object && baseForOwn(object, getIteratee(iteratee, 3)); } /** * This method is like `_.forOwn` except that it iterates over properties of * `object` in the opposite order. * * @static * @memberOf _ * @since 2.0.0 * @category Object * @param {Object} object The object to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @returns {Object} Returns `object`. * @see _.forOwn * @example * * function Foo() { * this.a = 1; * this.b = 2; * } * * Foo.prototype.c = 3; * * _.forOwnRight(new Foo, function(value, key) { * console.log(key); * }); * // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'. */ function forOwnRight(object, iteratee) { return object && baseForOwnRight(object, getIteratee(iteratee, 3)); } /** * Creates an array of function property names from own enumerable properties * of `object`. * * @static * @since 0.1.0 * @memberOf _ * @category Object * @param {Object} object The object to inspect. * @returns {Array} Returns the function names. * @see _.functionsIn * @example * * function Foo() { * this.a = _.constant('a'); * this.b = _.constant('b'); * } * * Foo.prototype.c = _.constant('c'); * * _.functions(new Foo); * // => ['a', 'b'] */ function functions(object) { return object == null ? [] : baseFunctions(object, keys(object)); } /** * Creates an array of function property names from own and inherited * enumerable properties of `object`. * * @static * @memberOf _ * @since 4.0.0 * @category Object * @param {Object} object The object to inspect. * @returns {Array} Returns the function names. * @see _.functions * @example * * function Foo() { * this.a = _.constant('a'); * this.b = _.constant('b'); * } * * Foo.prototype.c = _.constant('c'); * * _.functionsIn(new Foo); * // => ['a', 'b', 'c'] */ function functionsIn(object) { return object == null ? [] : baseFunctions(object, keysIn(object)); } /** * Gets the value at `path` of `object`. If the resolved value is * `undefined`, the `defaultValue` is used in its place. * * @static * @memberOf _ * @since 3.7.0 * @category Object * @param {Object} object The object to query. * @param {Array|string} path The path of the property to get. * @param {*} [defaultValue] The value returned for `undefined` resolved values. * @returns {*} Returns the resolved value. * @example * * var object = { 'a': [{ 'b': { 'c': 3 } }] }; * * _.get(object, 'a[0].b.c'); * // => 3 * * _.get(object, ['a', '0', 'b', 'c']); * // => 3 * * _.get(object, 'a.b.c', 'default'); * // => 'default' */ function get(object, path, defaultValue) { var result = object == null ? undefined : baseGet(object, path); return result === undefined ? defaultValue : result; } /** * Checks if `path` is a direct property of `object`. * * @static * @since 0.1.0 * @memberOf _ * @category Object * @param {Object} object The object to query. * @param {Array|string} path The path to check. * @returns {boolean} Returns `true` if `path` exists, else `false`. * @example * * var object = { 'a': { 'b': 2 } }; * var other = _.create({ 'a': _.create({ 'b': 2 }) }); * * _.has(object, 'a'); * // => true * * _.has(object, 'a.b'); * // => true * * _.has(object, ['a', 'b']); * // => true * * _.has(other, 'a'); * // => false */ function has(object, path) { return object != null && hasPath(object, path, baseHas); } /** * Checks if `path` is a direct or inherited property of `object`. * * @static * @memberOf _ * @since 4.0.0 * @category Object * @param {Object} object The object to query. * @param {Array|string} path The path to check. * @returns {boolean} Returns `true` if `path` exists, else `false`. * @example * * var object = _.create({ 'a': _.create({ 'b': 2 }) }); * * _.hasIn(object, 'a'); * // => true * * _.hasIn(object, 'a.b'); * // => true * * _.hasIn(object, ['a', 'b']); * // => true * * _.hasIn(object, 'b'); * // => false */ function hasIn(object, path) { return object != null && hasPath(object, path, baseHasIn); } /** * Creates an object composed of the inverted keys and values of `object`. * If `object` contains duplicate values, subsequent values overwrite * property assignments of previous values. * * @static * @memberOf _ * @since 0.7.0 * @category Object * @param {Object} object The object to invert. * @returns {Object} Returns the new inverted object. * @example * * var object = { 'a': 1, 'b': 2, 'c': 1 }; * * _.invert(object); * // => { '1': 'c', '2': 'b' } */ var invert = createInverter(function(result, value, key) { result[value] = key; }, constant(identity)); /** * This method is like `_.invert` except that the inverted object is generated * from the results of running each element of `object` thru `iteratee`. The * corresponding inverted value of each inverted key is an array of keys * responsible for generating the inverted value. The iteratee is invoked * with one argument: (value). * * @static * @memberOf _ * @since 4.1.0 * @category Object * @param {Object} object The object to invert. * @param {Array|Function|Object|string} [iteratee=_.identity] * The iteratee invoked per element. * @returns {Object} Returns the new inverted object. * @example * * var object = { 'a': 1, 'b': 2, 'c': 1 }; * * _.invertBy(object); * // => { '1': ['a', 'c'], '2': ['b'] } * * _.invertBy(object, function(value) { * return 'group' + value; * }); * // => { 'group1': ['a', 'c'], 'group2': ['b'] } */ var invertBy = createInverter(function(result, value, key) { if (hasOwnProperty.call(result, value)) { result[value].push(key); } else { result[value] = [key]; } }, getIteratee); /** * Invokes the method at `path` of `object`. * * @static * @memberOf _ * @since 4.0.0 * @category Object * @param {Object} object The object to query. * @param {Array|string} path The path of the method to invoke. * @param {...*} [args] The arguments to invoke the method with. * @returns {*} Returns the result of the invoked method. * @example * * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] }; * * _.invoke(object, 'a[0].b.c.slice', 1, 3); * // => [2, 3] */ var invoke = rest(baseInvoke); /** * Creates an array of the own enumerable property names of `object`. * * **Note:** Non-object values are coerced to objects. See the * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys) * for more details. * * @static * @since 0.1.0 * @memberOf _ * @category Object * @param {Object} object The object to query. * @returns {Array} Returns the array of property names. * @example * * function Foo() { * this.a = 1; * this.b = 2; * } * * Foo.prototype.c = 3; * * _.keys(new Foo); * // => ['a', 'b'] (iteration order is not guaranteed) * * _.keys('hi'); * // => ['0', '1'] */ function keys(object) { var isProto = isPrototype(object); if (!(isProto || isArrayLike(object))) { return baseKeys(object); } var indexes = indexKeys(object), skipIndexes = !!indexes, result = indexes || [], length = result.length; for (var key in object) { if (baseHas(object, key) && !(skipIndexes && (key == 'length' || isIndex(key, length))) && !(isProto && key == 'constructor')) { result.push(key); } } return result; } /** * Creates an array of the own and inherited enumerable property names of `object`. * * **Note:** Non-object values are coerced to objects. * * @static * @memberOf _ * @since 3.0.0 * @category Object * @param {Object} object The object to query. * @returns {Array} Returns the array of property names. * @example * * function Foo() { * this.a = 1; * this.b = 2; * } * * Foo.prototype.c = 3; * * _.keysIn(new Foo); * // => ['a', 'b', 'c'] (iteration order is not guaranteed) */ function keysIn(object) { var index = -1, isProto = isPrototype(object), props = baseKeysIn(object), propsLength = props.length, indexes = indexKeys(object), skipIndexes = !!indexes, result = indexes || [], length = result.length; while (++index < propsLength) { var key = props[index]; if (!(skipIndexes && (key == 'length' || isIndex(key, length))) && !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { result.push(key); } } return result; } /** * The opposite of `_.mapValues`; this method creates an object with the * same values as `object` and keys generated by running each own enumerable * string keyed property of `object` thru `iteratee`. The iteratee is invoked * with three arguments: (value, key, object). * * @static * @memberOf _ * @since 3.8.0 * @category Object * @param {Object} object The object to iterate over. * @param {Array|Function|Object|string} [iteratee=_.identity] * The function invoked per iteration. * @returns {Object} Returns the new mapped object. * @see _.mapValues * @example * * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) { * return key + value; * }); * // => { 'a1': 1, 'b2': 2 } */ function mapKeys(object, iteratee) { var result = {}; iteratee = getIteratee(iteratee, 3); baseForOwn(object, function(value, key, object) { result[iteratee(value, key, object)] = value; }); return result; } /** * Creates an object with the same keys as `object` and values generated * by running each own enumerable string keyed property of `object` thru * `iteratee`. The iteratee is invoked with three arguments: * (value, key, object). * * @static * @memberOf _ * @since 2.4.0 * @category Object * @param {Object} object The object to iterate over. * @param {Array|Function|Object|string} [iteratee=_.identity] * The function invoked per iteration. * @returns {Object} Returns the new mapped object. * @see _.mapKeys * @example * * var users = { * 'fred': { 'user': 'fred', 'age': 40 }, * 'pebbles': { 'user': 'pebbles', 'age': 1 } * }; * * _.mapValues(users, function(o) { return o.age; }); * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) * * // The `_.property` iteratee shorthand. * _.mapValues(users, 'age'); * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) */ function mapValues(object, iteratee) { var result = {}; iteratee = getIteratee(iteratee, 3); baseForOwn(object, function(value, key, object) { result[key] = iteratee(value, key, object); }); return result; } /** * This method is like `_.assign` except that it recursively merges own and * inherited enumerable string keyed properties of source objects into the * destination object. Source properties that resolve to `undefined` are * skipped if a destination value exists. Array and plain object properties * are merged recursively. Other objects and value types are overridden by * assignment. Source objects are applied from left to right. Subsequent * sources overwrite property assignments of previous sources. * * **Note:** This method mutates `object`. * * @static * @memberOf _ * @since 0.5.0 * @category Object * @param {Object} object The destination object. * @param {...Object} [sources] The source objects. * @returns {Object} Returns `object`. * @example * * var users = { * 'data': [{ 'user': 'barney' }, { 'user': 'fred' }] * }; * * var ages = { * 'data': [{ 'age': 36 }, { 'age': 40 }] * }; * * _.merge(users, ages); * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] } */ var merge = createAssigner(function(object, source, srcIndex) { baseMerge(object, source, srcIndex); }); /** * This method is like `_.merge` except that it accepts `customizer` which * is invoked to produce the merged values of the destination and source * properties. If `customizer` returns `undefined`, merging is handled by the * method instead. The `customizer` is invoked with seven arguments: * (objValue, srcValue, key, object, source, stack). * * **Note:** This method mutates `object`. * * @static * @memberOf _ * @since 4.0.0 * @category Object * @param {Object} object The destination object. * @param {...Object} sources The source objects. * @param {Function} customizer The function to customize assigned values. * @returns {Object} Returns `object`. * @example * * function customizer(objValue, srcValue) { * if (_.isArray(objValue)) { * return objValue.concat(srcValue); * } * } * * var object = { * 'fruits': ['apple'], * 'vegetables': ['beet'] * }; * * var other = { * 'fruits': ['banana'], * 'vegetables': ['carrot'] * }; * * _.mergeWith(object, other, customizer); * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] } */ var mergeWith = createAssigner(function(object, source, srcIndex, customizer) { baseMerge(object, source, srcIndex, customizer); }); /** * The opposite of `_.pick`; this method creates an object composed of the * own and inherited enumerable string keyed properties of `object` that are * not omitted. * * @static * @since 0.1.0 * @memberOf _ * @category Object * @param {Object} object The source object. * @param {...(string|string[])} [props] The property identifiers to omit. * @returns {Object} Returns the new object. * @example * * var object = { 'a': 1, 'b': '2', 'c': 3 }; * * _.omit(object, ['a', 'c']); * // => { 'b': '2' } */ var omit = rest(function(object, props) { if (object == null) { return {}; } props = arrayMap(baseFlatten(props, 1), toKey); return basePick(object, baseDifference(getAllKeysIn(object), props)); }); /** * The opposite of `_.pickBy`; this method creates an object composed of * the own and inherited enumerable string keyed properties of `object` that * `predicate` doesn't return truthy for. The predicate is invoked with two * arguments: (value, key). * * @static * @memberOf _ * @since 4.0.0 * @category Object * @param {Object} object The source object. * @param {Array|Function|Object|string} [predicate=_.identity] * The function invoked per property. * @returns {Object} Returns the new object. * @example * * var object = { 'a': 1, 'b': '2', 'c': 3 }; * * _.omitBy(object, _.isNumber); * // => { 'b': '2' } */ function omitBy(object, predicate) { predicate = getIteratee(predicate); return basePickBy(object, function(value, key) { return !predicate(value, key); }); } /** * Creates an object composed of the picked `object` properties. * * @static * @since 0.1.0 * @memberOf _ * @category Object * @param {Object} object The source object. * @param {...(string|string[])} [props] The property identifiers to pick. * @returns {Object} Returns the new object. * @example * * var object = { 'a': 1, 'b': '2', 'c': 3 }; * * _.pick(object, ['a', 'c']); * // => { 'a': 1, 'c': 3 } */ var pick = rest(function(object, props) { return object == null ? {} : basePick(object, arrayMap(baseFlatten(props, 1), toKey)); }); /** * Creates an object composed of the `object` properties `predicate` returns * truthy for. The predicate is invoked with two arguments: (value, key). * * @static * @memberOf _ * @since 4.0.0 * @category Object * @param {Object} object The source object. * @param {Array|Function|Object|string} [predicate=_.identity] * The function invoked per property. * @returns {Object} Returns the new object. * @example * * var object = { 'a': 1, 'b': '2', 'c': 3 }; * * _.pickBy(object, _.isNumber); * // => { 'a': 1, 'c': 3 } */ function pickBy(object, predicate) { return object == null ? {} : basePickBy(object, getIteratee(predicate)); } /** * This method is like `_.get` except that if the resolved value is a * function it's invoked with the `this` binding of its parent object and * its result is returned. * * @static * @since 0.1.0 * @memberOf _ * @category Object * @param {Object} object The object to query. * @param {Array|string} path The path of the property to resolve. * @param {*} [defaultValue] The value returned for `undefined` resolved values. * @returns {*} Returns the resolved value. * @example * * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] }; * * _.result(object, 'a[0].b.c1'); * // => 3 * * _.result(object, 'a[0].b.c2'); * // => 4 * * _.result(object, 'a[0].b.c3', 'default'); * // => 'default' * * _.result(object, 'a[0].b.c3', _.constant('default')); * // => 'default' */ function result(object, path, defaultValue) { path = isKey(path, object) ? [path] : castPath(path); var index = -1, length = path.length; // Ensure the loop is entered when path is empty. if (!length) { object = undefined; length = 1; } while (++index < length) { var value = object == null ? undefined : object[toKey(path[index])]; if (value === undefined) { index = length; value = defaultValue; } object = isFunction(value) ? value.call(object) : value; } return object; } /** * Sets the value at `path` of `object`. If a portion of `path` doesn't exist, * it's created. Arrays are created for missing index properties while objects * are created for all other missing properties. Use `_.setWith` to customize * `path` creation. * * **Note:** This method mutates `object`. * * @static * @memberOf _ * @since 3.7.0 * @category Object * @param {Object} object The object to modify. * @param {Array|string} path The path of the property to set. * @param {*} value The value to set. * @returns {Object} Returns `object`. * @example * * var object = { 'a': [{ 'b': { 'c': 3 } }] }; * * _.set(object, 'a[0].b.c', 4); * console.log(object.a[0].b.c); * // => 4 * * _.set(object, ['x', '0', 'y', 'z'], 5); * console.log(object.x[0].y.z); * // => 5 */ function set(object, path, value) { return object == null ? object : baseSet(object, path, value); } /** * This method is like `_.set` except that it accepts `customizer` which is * invoked to produce the objects of `path`. If `customizer` returns `undefined` * path creation is handled by the method instead. The `customizer` is invoked * with three arguments: (nsValue, key, nsObject). * * **Note:** This method mutates `object`. * * @static * @memberOf _ * @since 4.0.0 * @category Object * @param {Object} object The object to modify. * @param {Array|string} path The path of the property to set. * @param {*} value The value to set. * @param {Function} [customizer] The function to customize assigned values. * @returns {Object} Returns `object`. * @example * * var object = {}; * * _.setWith(object, '[0][1]', 'a', Object); * // => { '0': { '1': 'a' } } */ function setWith(object, path, value, customizer) { customizer = typeof customizer == 'function' ? customizer : undefined; return object == null ? object : baseSet(object, path, value, customizer); } /** * Creates an array of own enumerable string keyed-value pairs for `object` * which can be consumed by `_.fromPairs`. If `object` is a map or set, its * entries are returned. * * @static * @memberOf _ * @since 4.0.0 * @alias entries * @category Object * @param {Object} object The object to query. * @returns {Array} Returns the key-value pairs. * @example * * function Foo() { * this.a = 1; * this.b = 2; * } * * Foo.prototype.c = 3; * * _.toPairs(new Foo); * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed) */ var toPairs = createToPairs(keys); /** * Creates an array of own and inherited enumerable string keyed-value pairs * for `object` which can be consumed by `_.fromPairs`. If `object` is a map * or set, its entries are returned. * * @static * @memberOf _ * @since 4.0.0 * @alias entriesIn * @category Object * @param {Object} object The object to query. * @returns {Array} Returns the key-value pairs. * @example * * function Foo() { * this.a = 1; * this.b = 2; * } * * Foo.prototype.c = 3; * * _.toPairsIn(new Foo); * // => [['a', 1], ['b', 2], ['c', 3]] (iteration order is not guaranteed) */ var toPairsIn = createToPairs(keysIn); /** * An alternative to `_.reduce`; this method transforms `object` to a new * `accumulator` object which is the result of running each of its own * enumerable string keyed properties thru `iteratee`, with each invocation * potentially mutating the `accumulator` object. The iteratee is invoked * with four arguments: (accumulator, value, key, object). Iteratee functions * may exit iteration early by explicitly returning `false`. * * @static * @memberOf _ * @since 1.3.0 * @category Object * @param {Array|Object} object The object to iterate over. * @param {Function} [iteratee=_.identity] The function invoked per iteration. * @param {*} [accumulator] The custom accumulator value. * @returns {*} Returns the accumulated value. * @example * * _.transform([2, 3, 4], function(result, n) { * result.push(n *= n); * return n % 2 == 0; * }, []); * // => [4, 9] * * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) { * (result[value] || (result[value] = [])).push(key); * }, {}); * // => { '1': ['a', 'c'], '2': ['b'] } */ function transform(object, iteratee, accumulator) { var isArr = isArray(object) || isTypedArray(object); iteratee = getIteratee(iteratee, 4); if (accumulator == null) { if (isArr || isObject(object)) { var Ctor = object.constructor; if (isArr) { accumulator = isArray(object) ? new Ctor : []; } else { accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {}; } } else { accumulator = {}; } } (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) { return iteratee(accumulator, value, index, object); }); return accumulator; } /** * Removes the property at `path` of `object`. * * **Note:** This method mutates `object`. * * @static * @memberOf _ * @since 4.0.0 * @category Object * @param {Object} object The object to modify. * @param {Array|string} path The path of the property to unset. * @returns {boolean} Returns `true` if the property is deleted, else `false`. * @example * * var object = { 'a': [{ 'b': { 'c': 7 } }] }; * _.unset(object, 'a[0].b.c'); * // => true * * console.log(object); * // => { 'a': [{ 'b': {} }] }; * * _.unset(object, ['a', '0', 'b', 'c']); * // => true * * console.log(object); * // => { 'a': [{ 'b': {} }] }; */ function unset(object, path) { return object == null ? true : baseUnset(object, path); } /** * This method is like `_.set` except that accepts `updater` to produce the * value to set. Use `_.updateWith` to customize `path` creation. The `updater` * is invoked with one argument: (value). * * **Note:** This method mutates `object`. * * @static * @memberOf _ * @since 4.6.0 * @category Object * @param {Object} object The object to modify. * @param {Array|string} path The path of the property to set. * @param {Function} updater The function to produce the updated value. * @returns {Object} Returns `object`. * @example * * var object = { 'a': [{ 'b': { 'c': 3 } }] }; * * _.update(object, 'a[0].b.c', function(n) { return n * n; }); * console.log(object.a[0].b.c); * // => 9 * * _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; }); * console.log(object.x[0].y.z); * // => 0 */ function update(object, path, updater) { return object == null ? object : baseUpdate(object, path, castFunction(updater)); } /** * This method is like `_.update` except that it accepts `customizer` which is * invoked to produce the objects of `path`. If `customizer` returns `undefined` * path creation is handled by the method instead. The `customizer` is invoked * with three arguments: (nsValue, key, nsObject). * * **Note:** This method mutates `object`. * * @static * @memberOf _ * @since 4.6.0 * @category Object * @param {Object} object The object to modify. * @param {Array|string} path The path of the property to set. * @param {Function} updater The function to produce the updated value. * @param {Function} [customizer] The function to customize assigned values. * @returns {Object} Returns `object`. * @example * * var object = {}; * * _.updateWith(object, '[0][1]', _.constant('a'), Object); * // => { '0': { '1': 'a' } } */ function updateWith(object, path, updater, customizer) { customizer = typeof customizer == 'function' ? customizer : undefined; return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer); } /** * Creates an array of the own enumerable string keyed property values of `object`. * * **Note:** Non-object values are coerced to objects. * * @static * @since 0.1.0 * @memberOf _ * @category Object * @param {Object} object The object to query. * @returns {Array} Returns the array of property values. * @example * * function Foo() { * this.a = 1; * this.b = 2; * } * * Foo.prototype.c = 3; * * _.values(new Foo); * // => [1, 2] (iteration order is not guaranteed) * * _.values('hi'); * // => ['h', 'i'] */ function values(object) { return object ? baseValues(object, keys(object)) : []; } /** * Creates an array of the own and inherited enumerable string keyed property * values of `object`. * * **Note:** Non-object values are coerced to objects. * * @static * @memberOf _ * @since 3.0.0 * @category Object * @param {Object} object The object to query. * @returns {Array} Returns the array of property values. * @example * * function Foo() { * this.a = 1; * this.b = 2; * } * * Foo.prototype.c = 3; * * _.valuesIn(new Foo); * // => [1, 2, 3] (iteration order is not guaranteed) */ function valuesIn(object) { return object == null ? [] : baseValues(object, keysIn(object)); } /*------------------------------------------------------------------------*/ /** * Clamps `number` within the inclusive `lower` and `upper` bounds. * * @static * @memberOf _ * @since 4.0.0 * @category Number * @param {number} number The number to clamp. * @param {number} [lower] The lower bound. * @param {number} upper The upper bound. * @returns {number} Returns the clamped number. * @example * * _.clamp(-10, -5, 5); * // => -5 * * _.clamp(10, -5, 5); * // => 5 */ function clamp(number, lower, upper) { if (upper === undefined) { upper = lower; lower = undefined; } if (upper !== undefined) { upper = toNumber(upper); upper = upper === upper ? upper : 0; } if (lower !== undefined) { lower = toNumber(lower); lower = lower === lower ? lower : 0; } return baseClamp(toNumber(number), lower, upper); } /** * Checks if `n` is between `start` and up to, but not including, `end`. If * `end` is not specified, it's set to `start` with `start` then set to `0`. * If `start` is greater than `end` the params are swapped to support * negative ranges. * * @static * @memberOf _ * @since 3.3.0 * @category Number * @param {number} number The number to check. * @param {number} [start=0] The start of the range. * @param {number} end The end of the range. * @returns {boolean} Returns `true` if `number` is in the range, else `false`. * @see _.range, _.rangeRight * @example * * _.inRange(3, 2, 4); * // => true * * _.inRange(4, 8); * // => true * * _.inRange(4, 2); * // => false * * _.inRange(2, 2); * // => false * * _.inRange(1.2, 2); * // => true * * _.inRange(5.2, 4); * // => false * * _.inRange(-3, -2, -6); * // => true */ function inRange(number, start, end) { start = toNumber(start) || 0; if (end === undefined) { end = start; start = 0; } else { end = toNumber(end) || 0; } number = toNumber(number); return baseInRange(number, start, end); } /** * Produces a random number between the inclusive `lower` and `upper` bounds. * If only one argument is provided a number between `0` and the given number * is returned. If `floating` is `true`, or either `lower` or `upper` are * floats, a floating-point number is returned instead of an integer. * * **Note:** JavaScript follows the IEEE-754 standard for resolving * floating-point values which can produce unexpected results. * * @static * @memberOf _ * @since 0.7.0 * @category Number * @param {number} [lower=0] The lower bound. * @param {number} [upper=1] The upper bound. * @param {boolean} [floating] Specify returning a floating-point number. * @returns {number} Returns the random number. * @example * * _.random(0, 5); * // => an integer between 0 and 5 * * _.random(5); * // => also an integer between 0 and 5 * * _.random(5, true); * // => a floating-point number between 0 and 5 * * _.random(1.2, 5.2); * // => a floating-point number between 1.2 and 5.2 */ function random(lower, upper, floating) { if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) { upper = floating = undefined; } if (floating === undefined) { if (typeof upper == 'boolean') { floating = upper; upper = undefined; } else if (typeof lower == 'boolean') { floating = lower; lower = undefined; } } if (lower === undefined && upper === undefined) { lower = 0; upper = 1; } else { lower = toNumber(lower) || 0; if (upper === undefined) { upper = lower; lower = 0; } else { upper = toNumber(upper) || 0; } } if (lower > upper) { var temp = lower; lower = upper; upper = temp; } if (floating || lower % 1 || upper % 1) { var rand = nativeRandom(); return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1)))), upper); } return baseRandom(lower, upper); } /*------------------------------------------------------------------------*/ /** * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase). * * @static * @memberOf _ * @since 3.0.0 * @category String * @param {string} [string=''] The string to convert. * @returns {string} Returns the camel cased string. * @example * * _.camelCase('Foo Bar'); * // => 'fooBar' * * _.camelCase('--foo-bar--'); * // => 'fooBar' * * _.camelCase('__FOO_BAR__'); * // => 'fooBar' */ var camelCase = createCompounder(function(result, word, index) { word = word.toLowerCase(); return result + (index ? capitalize(word) : word); }); /** * Converts the first character of `string` to upper case and the remaining * to lower case. * * @static * @memberOf _ * @since 3.0.0 * @category String * @param {string} [string=''] The string to capitalize. * @returns {string} Returns the capitalized string. * @example * * _.capitalize('FRED'); * // => 'Fred' */ function capitalize(string) { return upperFirst(toString(string).toLowerCase()); } /** * Deburrs `string` by converting * [latin-1 supplementary letters](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) * to basic latin letters and removing * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). * * @static * @memberOf _ * @since 3.0.0 * @category String * @param {string} [string=''] The string to deburr. * @returns {string} Returns the deburred string. * @example * * _.deburr('déjà vu'); * // => 'deja vu' */ function deburr(string) { string = toString(string); return string && string.replace(reLatin1, deburrLetter).replace(reComboMark, ''); } /** * Checks if `string` ends with the given target string. * * @static * @memberOf _ * @since 3.0.0 * @category String * @param {string} [string=''] The string to search. * @param {string} [target] The string to search for. * @param {number} [position=string.length] The position to search from. * @returns {boolean} Returns `true` if `string` ends with `target`, * else `false`. * @example * * _.endsWith('abc', 'c'); * // => true * * _.endsWith('abc', 'b'); * // => false * * _.endsWith('abc', 'b', 2); * // => true */ function endsWith(string, target, position) { string = toString(string); target = baseToString(target); var length = string.length; position = position === undefined ? length : baseClamp(toInteger(position), 0, length); position -= target.length; return position >= 0 && string.indexOf(target, position) == position; } /** * Converts the characters "&", "<", ">", '"', "'", and "\`" in `string` to * their corresponding HTML entities. * * **Note:** No other characters are escaped. To escape additional * characters use a third-party library like [_he_](https://mths.be/he). * * Though the ">" character is escaped for symmetry, characters like * ">" and "/" don't need escaping in HTML and have no special meaning * unless they're part of a tag or unquoted attribute value. See * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands) * (under "semi-related fun fact") for more details. * * Backticks are escaped because in IE < 9, they can break out of * attribute values or HTML comments. See [#59](https://html5sec.org/#59), * [#102](https://html5sec.org/#102), [#108](https://html5sec.org/#108), and * [#133](https://html5sec.org/#133) of the * [HTML5 Security Cheatsheet](https://html5sec.org/) for more details. * * When working with HTML you should always * [quote attribute values](http://wonko.com/post/html-escaping) to reduce * XSS vectors. * * @static * @since 0.1.0 * @memberOf _ * @category String * @param {string} [string=''] The string to escape. * @returns {string} Returns the escaped string. * @example * * _.escape('fred, barney, & pebbles'); * // => 'fred, barney, & pebbles' */ function escape(string) { string = toString(string); return (string && reHasUnescapedHtml.test(string)) ? string.replace(reUnescapedHtml, escapeHtmlChar) : string; } /** * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+", * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`. * * @static * @memberOf _ * @since 3.0.0 * @category String * @param {string} [string=''] The string to escape. * @returns {string} Returns the escaped string. * @example * * _.escapeRegExp('[lodash](https://lodash.com/)'); * // => '\[lodash\]\(https://lodash\.com/\)' */ function escapeRegExp(string) { string = toString(string); return (string && reHasRegExpChar.test(string)) ? string.replace(reRegExpChar, '\\$&') : string; } /** * Converts `string` to * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles). * * @static * @memberOf _ * @since 3.0.0 * @category String * @param {string} [string=''] The string to convert. * @returns {string} Returns the kebab cased string. * @example * * _.kebabCase('Foo Bar'); * // => 'foo-bar' * * _.kebabCase('fooBar'); * // => 'foo-bar' * * _.kebabCase('__FOO_BAR__'); * // => 'foo-bar' */ var kebabCase = createCompounder(function(result, word, index) { return result + (index ? '-' : '') + word.toLowerCase(); }); /** * Converts `string`, as space separated words, to lower case. * * @static * @memberOf _ * @since 4.0.0 * @category String * @param {string} [string=''] The string to convert. * @returns {string} Returns the lower cased string. * @example * * _.lowerCase('--Foo-Bar--'); * // => 'foo bar' * * _.lowerCase('fooBar'); * // => 'foo bar' * * _.lowerCase('__FOO_BAR__'); * // => 'foo bar' */ var lowerCase = createCompounder(function(result, word, index) { return result + (index ? ' ' : '') + word.toLowerCase(); }); /** * Converts the first character of `string` to lower case. * * @static * @memberOf _ * @since 4.0.0 * @category String * @param {string} [string=''] The string to convert. * @returns {string} Returns the converted string. * @example * * _.lowerFirst('Fred'); * // => 'fred' * * _.lowerFirst('FRED'); * // => 'fRED' */ var lowerFirst = createCaseFirst('toLowerCase'); /** * Pads `string` on the left and right sides if it's shorter than `length`. * Padding characters are truncated if they can't be evenly divided by `length`. * * @static * @memberOf _ * @since 3.0.0 * @category String * @param {string} [string=''] The string to pad. * @param {number} [length=0] The padding length. * @param {string} [chars=' '] The string used as padding. * @returns {string} Returns the padded string. * @example * * _.pad('abc', 8); * // => ' abc ' * * _.pad('abc', 8, '_-'); * // => '_-abc_-_' * * _.pad('abc', 3); * // => 'abc' */ function pad(string, length, chars) { string = toString(string); length = toInteger(length); var strLength = length ? stringSize(string) : 0; if (!length || strLength >= length) { return string; } var mid = (length - strLength) / 2; return ( createPadding(nativeFloor(mid), chars) + string + createPadding(nativeCeil(mid), chars) ); } /** * Pads `string` on the right side if it's shorter than `length`. Padding * characters are truncated if they exceed `length`. * * @static * @memberOf _ * @since 4.0.0 * @category String * @param {string} [string=''] The string to pad. * @param {number} [length=0] The padding length. * @param {string} [chars=' '] The string used as padding. * @returns {string} Returns the padded string. * @example * * _.padEnd('abc', 6); * // => 'abc ' * * _.padEnd('abc', 6, '_-'); * // => 'abc_-_' * * _.padEnd('abc', 3); * // => 'abc' */ function padEnd(string, length, chars) { string = toString(string); length = toInteger(length); var strLength = length ? stringSize(string) : 0; return (length && strLength < length) ? (string + createPadding(length - strLength, chars)) : string; } /** * Pads `string` on the left side if it's shorter than `length`. Padding * characters are truncated if they exceed `length`. * * @static * @memberOf _ * @since 4.0.0 * @category String * @param {string} [string=''] The string to pad. * @param {number} [length=0] The padding length. * @param {string} [chars=' '] The string used as padding. * @returns {string} Returns the padded string. * @example * * _.padStart('abc', 6); * // => ' abc' * * _.padStart('abc', 6, '_-'); * // => '_-_abc' * * _.padStart('abc', 3); * // => 'abc' */ function padStart(string, length, chars) { string = toString(string); length = toInteger(length); var strLength = length ? stringSize(string) : 0; return (length && strLength < length) ? (createPadding(length - strLength, chars) + string) : string; } /** * Converts `string` to an integer of the specified radix. If `radix` is * `undefined` or `0`, a `radix` of `10` is used unless `value` is a * hexadecimal, in which case a `radix` of `16` is used. * * **Note:** This method aligns with the * [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`. * * @static * @memberOf _ * @since 1.1.0 * @category String * @param {string} string The string to convert. * @param {number} [radix=10] The radix to interpret `value` by. * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. * @returns {number} Returns the converted integer. * @example * * _.parseInt('08'); * // => 8 * * _.map(['6', '08', '10'], _.parseInt); * // => [6, 8, 10] */ function parseInt(string, radix, guard) { // Chrome fails to trim leading whitespace characters. // See https://bugs.chromium.org/p/v8/issues/detail?id=3109 for more details. if (guard || radix == null) { radix = 0; } else if (radix) { radix = +radix; } string = toString(string).replace(reTrim, ''); return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10)); } /** * Repeats the given string `n` times. * * @static * @memberOf _ * @since 3.0.0 * @category String * @param {string} [string=''] The string to repeat. * @param {number} [n=1] The number of times to repeat the string. * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. * @returns {string} Returns the repeated string. * @example * * _.repeat('*', 3); * // => '***' * * _.repeat('abc', 2); * // => 'abcabc' * * _.repeat('abc', 0); * // => '' */ function repeat(string, n, guard) { if ((guard ? isIterateeCall(string, n, guard) : n === undefined)) { n = 1; } else { n = toInteger(n); } return baseRepeat(toString(string), n); } /** * Replaces matches for `pattern` in `string` with `replacement`. * * **Note:** This method is based on * [`String#replace`](https://mdn.io/String/replace). * * @static * @memberOf _ * @since 4.0.0 * @category String * @param {string} [string=''] The string to modify. * @param {RegExp|string} pattern The pattern to replace. * @param {Function|string} replacement The match replacement. * @returns {string} Returns the modified string. * @example * * _.replace('Hi Fred', 'Fred', 'Barney'); * // => 'Hi Barney' */ function replace() { var args = arguments, string = toString(args[0]); return args.length < 3 ? string : nativeReplace.call(string, args[1], args[2]); } /** * Converts `string` to * [snake case](https://en.wikipedia.org/wiki/Snake_case). * * @static * @memberOf _ * @since 3.0.0 * @category String * @param {string} [string=''] The string to convert. * @returns {string} Returns the snake cased string. * @example * * _.snakeCase('Foo Bar'); * // => 'foo_bar' * * _.snakeCase('fooBar'); * // => 'foo_bar' * * _.snakeCase('--FOO-BAR--'); * // => 'foo_bar' */ var snakeCase = createCompounder(function(result, word, index) { return result + (index ? '_' : '') + word.toLowerCase(); }); /** * Splits `string` by `separator`. * * **Note:** This method is based on * [`String#split`](https://mdn.io/String/split). * * @static * @memberOf _ * @since 4.0.0 * @category String * @param {string} [string=''] The string to split. * @param {RegExp|string} separator The separator pattern to split by. * @param {number} [limit] The length to truncate results to. * @returns {Array} Returns the string segments. * @example * * _.split('a-b-c', '-', 2); * // => ['a', 'b'] */ function split(string, separator, limit) { if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) { separator = limit = undefined; } limit = limit === undefined ? MAX_ARRAY_LENGTH : limit >>> 0; if (!limit) { return []; } string = toString(string); if (string && ( typeof separator == 'string' || (separator != null && !isRegExp(separator)) )) { separator = baseToString(separator); if (separator == '' && reHasComplexSymbol.test(string)) { return castSlice(stringToArray(string), 0, limit); } } return nativeSplit.call(string, separator, limit); } /** * Converts `string` to * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage). * * @static * @memberOf _ * @since 3.1.0 * @category String * @param {string} [string=''] The string to convert. * @returns {string} Returns the start cased string. * @example * * _.startCase('--foo-bar--'); * // => 'Foo Bar' * * _.startCase('fooBar'); * // => 'Foo Bar' * * _.startCase('__FOO_BAR__'); * // => 'FOO BAR' */ var startCase = createCompounder(function(result, word, index) { return result + (index ? ' ' : '') + upperFirst(word); }); /** * Checks if `string` starts with the given target string. * * @static * @memberOf _ * @since 3.0.0 * @category String * @param {string} [string=''] The string to search. * @param {string} [target] The string to search for. * @param {number} [position=0] The position to search from. * @returns {boolean} Returns `true` if `string` starts with `target`, * else `false`. * @example * * _.startsWith('abc', 'a'); * // => true * * _.startsWith('abc', 'b'); * // => false * * _.startsWith('abc', 'b', 1); * // => true */ function startsWith(string, target, position) { string = toString(string); position = baseClamp(toInteger(position), 0, string.length); return string.lastIndexOf(baseToString(target), position) == position; } /** * Creates a compiled template function that can interpolate data properties * in "interpolate" delimiters, HTML-escape interpolated data properties in * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data * properties may be accessed as free variables in the template. If a setting * object is given, it takes precedence over `_.templateSettings` values. * * **Note:** In the development build `_.template` utilizes * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) * for easier debugging. * * For more information on precompiling templates see * [lodash's custom builds documentation](https://lodash.com/custom-builds). * * For more information on Chrome extension sandboxes see * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval). * * @static * @since 0.1.0 * @memberOf _ * @category String * @param {string} [string=''] The template string. * @param {Object} [options={}] The options object. * @param {RegExp} [options.escape=_.templateSettings.escape] * The HTML "escape" delimiter. * @param {RegExp} [options.evaluate=_.templateSettings.evaluate] * The "evaluate" delimiter. * @param {Object} [options.imports=_.templateSettings.imports] * An object to import into the template as free variables. * @param {RegExp} [options.interpolate=_.templateSettings.interpolate] * The "interpolate" delimiter. * @param {string} [options.sourceURL='lodash.templateSources[n]'] * The sourceURL of the compiled template. * @param {string} [options.variable='obj'] * The data object variable name. * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. * @returns {Function} Returns the compiled template function. * @example * * // Use the "interpolate" delimiter to create a compiled template. * var compiled = _.template('hello <%= user %>!'); * compiled({ 'user': 'fred' }); * // => 'hello fred!' * * // Use the HTML "escape" delimiter to escape data property values. * var compiled = _.template('<%- value %>'); * compiled({ 'value': '