mirror of
https://github.com/orbitdb/orbitdb.git
synced 2025-05-21 14:26:38 +00:00
42646 lines
1.2 MiB
42646 lines
1.2 MiB
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;
|
||
|
||
/******/ // identity function for calling harmory imports with the correct context
|
||
/******/ __webpack_require__.i = function(value) { return value; };
|
||
|
||
/******/ // define getter function for harmory exports
|
||
/******/ __webpack_require__.d = function(exports, name, getter) {
|
||
/******/ Object.defineProperty(exports, name, {
|
||
/******/ configurable: false,
|
||
/******/ enumerable: true,
|
||
/******/ get: getter
|
||
/******/ });
|
||
/******/ };
|
||
|
||
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||
/******/ __webpack_require__.n = function(module) {
|
||
/******/ var getter = module && module.__esModule ?
|
||
/******/ function getDefault() { return module['default']; } :
|
||
/******/ function getModuleExports() { return module; };
|
||
/******/ __webpack_require__.d(getter, 'a', getter);
|
||
/******/ return getter;
|
||
/******/ };
|
||
|
||
/******/ // Object.prototype.hasOwnProperty.call
|
||
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
||
|
||
/******/ // __webpack_public_path__
|
||
/******/ __webpack_require__.p = "";
|
||
|
||
/******/ // Load entry module and return exports
|
||
/******/ return __webpack_require__(__webpack_require__.s = 160);
|
||
/******/ })
|
||
/************************************************************************/
|
||
/******/ ([
|
||
/* 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__(52)('wks')
|
||
, uid = __webpack_require__(56)
|
||
, 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) {
|
||
|
||
var core = module.exports = {version: '2.4.0'};
|
||
if(typeof __e == 'number')__e = core; // eslint-disable-line no-undef
|
||
|
||
/***/ },
|
||
/* 4 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
|
||
/**
|
||
* This is the web browser implementation of `debug()`.
|
||
*
|
||
* Expose `debug()` as the module.
|
||
*/
|
||
|
||
exports = module.exports = __webpack_require__(122);
|
||
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) {}
|
||
}
|
||
|
||
|
||
/***/ },
|
||
/* 5 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
var isObject = __webpack_require__(17);
|
||
module.exports = function(it){
|
||
if(!isObject(it))throw TypeError(it + ' is not an object!');
|
||
return it;
|
||
};
|
||
|
||
/***/ },
|
||
/* 6 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
// Thank's IE8 for his funny defineProperty
|
||
module.exports = !__webpack_require__(23)(function(){
|
||
return Object.defineProperty({}, 'a', {get: function(){ return 7; }}).a != 7;
|
||
});
|
||
|
||
/***/ },
|
||
/* 7 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
var dP = __webpack_require__(10)
|
||
, createDesc = __webpack_require__(51);
|
||
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;
|
||
};
|
||
|
||
/***/ },
|
||
/* 8 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
/* WEBPACK VAR INJECTION */(function(global) {/**
|
||
* Module dependencies.
|
||
*/
|
||
|
||
var keys = __webpack_require__(129);
|
||
var hasBinary = __webpack_require__(130);
|
||
var sliceBuffer = __webpack_require__(76);
|
||
var base64encoder = __webpack_require__(79);
|
||
var after = __webpack_require__(75);
|
||
var utf8 = __webpack_require__(155);
|
||
|
||
/**
|
||
* 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__(81);
|
||
|
||
/**
|
||
* Encodes a packet.
|
||
*
|
||
* <packet type id> [ <data> ]
|
||
*
|
||
* 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).
|
||
*
|
||
* <length>: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><number from 0-9><number from 0-9>[...]<number
|
||
* 255><data>
|
||
*
|
||
* 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)))
|
||
|
||
/***/ },
|
||
/* 9 */
|
||
/***/ function(module, exports) {
|
||
|
||
module.exports = {};
|
||
|
||
/***/ },
|
||
/* 10 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
var anObject = __webpack_require__(5)
|
||
, IE8_DOM_DEFINE = __webpack_require__(91)
|
||
, toPrimitive = __webpack_require__(111)
|
||
, 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;
|
||
};
|
||
|
||
/***/ },
|
||
/* 11 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
/* WEBPACK VAR INJECTION */(function(setImmediate, clearImmediate) {var nextTick = __webpack_require__(149).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__(11).setImmediate, __webpack_require__(11).clearImmediate))
|
||
|
||
/***/ },
|
||
/* 12 */
|
||
/***/ function(module, exports) {
|
||
|
||
|
||
module.exports = function(a, b){
|
||
var fn = function(){};
|
||
fn.prototype = b.prototype;
|
||
a.prototype = new fn;
|
||
a.prototype.constructor = a;
|
||
};
|
||
|
||
/***/ },
|
||
/* 13 */
|
||
/***/ function(module, exports) {
|
||
|
||
var toString = {}.toString;
|
||
|
||
module.exports = function(it){
|
||
return toString.call(it).slice(8, -1);
|
||
};
|
||
|
||
/***/ },
|
||
/* 14 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
// optional / simple context binding
|
||
var aFunction = __webpack_require__(20);
|
||
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);
|
||
};
|
||
};
|
||
|
||
/***/ },
|
||
/* 15 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
var global = __webpack_require__(2)
|
||
, core = __webpack_require__(3)
|
||
, ctx = __webpack_require__(14)
|
||
, hide = __webpack_require__(7)
|
||
, 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;
|
||
|
||
/***/ },
|
||
/* 16 */
|
||
/***/ function(module, exports) {
|
||
|
||
var hasOwnProperty = {}.hasOwnProperty;
|
||
module.exports = function(it, key){
|
||
return hasOwnProperty.call(it, key);
|
||
};
|
||
|
||
/***/ },
|
||
/* 17 */
|
||
/***/ function(module, exports) {
|
||
|
||
module.exports = function(it){
|
||
return typeof it === 'object' ? it !== null : typeof it === 'function';
|
||
};
|
||
|
||
/***/ },
|
||
/* 18 */
|
||
/***/ 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__(63);
|
||
cwd = path.resolve(dir, cwd);
|
||
};
|
||
})();
|
||
|
||
exports.exit = exports.kill =
|
||
exports.umask = exports.dlopen =
|
||
exports.uptime = exports.memoryUsage =
|
||
exports.uvCounters = function() {};
|
||
exports.features = {};
|
||
|
||
|
||
/***/ },
|
||
/* 19 */
|
||
/***/ 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 <feross@feross.org> <http://feross.org>
|
||
* @license MIT
|
||
*/
|
||
/* eslint-disable no-proto */
|
||
|
||
'use strict'
|
||
|
||
var base64 = __webpack_require__(80)
|
||
var ieee754 = __webpack_require__(135)
|
||
var isArray = __webpack_require__(139)
|
||
|
||
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.__proto__ = {__proto__: Uint8Array.prototype, 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 (byteOffset === undefined && length === undefined) {
|
||
array = new Uint8Array(array)
|
||
} else 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':
|
||
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 ' + str + '>'
|
||
}
|
||
|
||
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 = byteOffset; i < arrLength; ++i) {
|
||
if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) {
|
||
if (foundIndex === -1) foundIndex = i
|
||
if (i - foundIndex + 1 === valLength) return 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__(19).Buffer, __webpack_require__(0)))
|
||
|
||
/***/ },
|
||
/* 20 */
|
||
/***/ function(module, exports) {
|
||
|
||
module.exports = function(it){
|
||
if(typeof it != 'function')throw TypeError(it + ' is not a function!');
|
||
return it;
|
||
};
|
||
|
||
/***/ },
|
||
/* 21 */
|
||
/***/ 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;
|
||
};
|
||
|
||
/***/ },
|
||
/* 22 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
var isObject = __webpack_require__(17)
|
||
, 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) : {};
|
||
};
|
||
|
||
/***/ },
|
||
/* 23 */
|
||
/***/ function(module, exports) {
|
||
|
||
module.exports = function(exec){
|
||
try {
|
||
return !!exec();
|
||
} catch(e){
|
||
return true;
|
||
}
|
||
};
|
||
|
||
/***/ },
|
||
/* 24 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
var def = __webpack_require__(10).f
|
||
, has = __webpack_require__(16)
|
||
, 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});
|
||
};
|
||
|
||
/***/ },
|
||
/* 25 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
var shared = __webpack_require__(52)('keys')
|
||
, uid = __webpack_require__(56);
|
||
module.exports = function(key){
|
||
return shared[key] || (shared[key] = uid(key));
|
||
};
|
||
|
||
/***/ },
|
||
/* 26 */
|
||
/***/ 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);
|
||
};
|
||
|
||
/***/ },
|
||
/* 27 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
// to indexed object, toObject with fallback for non-array-like ES3 strings
|
||
var IObject = __webpack_require__(93)
|
||
, defined = __webpack_require__(21);
|
||
module.exports = function(it){
|
||
return IObject(defined(it));
|
||
};
|
||
|
||
/***/ },
|
||
/* 28 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
/**
|
||
* Module dependencies.
|
||
*/
|
||
|
||
var parser = __webpack_require__(8);
|
||
var Emitter = __webpack_require__(30);
|
||
|
||
/**
|
||
* 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');
|
||
};
|
||
|
||
|
||
/***/ },
|
||
/* 29 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
// browser shim for xmlhttprequest module
|
||
var hasCORS = __webpack_require__(134);
|
||
|
||
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) { }
|
||
}
|
||
}
|
||
|
||
|
||
/***/ },
|
||
/* 30 */
|
||
/***/ 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;
|
||
};
|
||
|
||
|
||
/***/ },
|
||
/* 31 */
|
||
/***/ 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.<string>} 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.<string>} 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.<string>} 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.<string>} 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__(11).setImmediate, __webpack_require__(11).clearImmediate))
|
||
|
||
/***/ },
|
||
/* 32 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
'use strict';
|
||
|
||
const EventEmitter = __webpack_require__(40).EventEmitter;
|
||
const Log = __webpack_require__(138);
|
||
const Index = __webpack_require__(147);
|
||
const Cache = __webpack_require__(146);
|
||
|
||
const DefaultMaxHistory = 256;
|
||
|
||
class Store {
|
||
constructor(ipfs, id, dbname, options) {
|
||
this.id = id;
|
||
this.dbname = dbname;
|
||
this.events = new EventEmitter();
|
||
|
||
if(!options) options = {};
|
||
if(options.Index === undefined) Object.assign(options, { Index: Index });
|
||
if(options.cacheFile === undefined) Object.assign(options, { cacheFile: null });
|
||
if(options.maxHistory === undefined) Object.assign(options, { maxHistory: DefaultMaxHistory });
|
||
|
||
this.options = options;
|
||
this._index = new this.options.Index(this.id);
|
||
this._oplog = null;
|
||
this._ipfs = ipfs;
|
||
this._lastWrite = [];
|
||
}
|
||
|
||
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) {
|
||
if(this._lastWrite.indexOf(cached) > -1) this._lastWrite.push(cached);
|
||
return Log.fromIpfsHash(this._ipfs, cached, this.options)
|
||
.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 || this._lastWrite.indexOf(hash) > -1) {
|
||
this.events.emit('updated', this.dbname, []);
|
||
return Promise.resolve([]);
|
||
}
|
||
|
||
let newItems = [];
|
||
this.events.emit('sync', this.dbname);
|
||
this._lastWrite.push(hash);
|
||
const startTime = new Date().getTime();
|
||
return Log.fromIpfsHash(this._ipfs, hash, this.options)
|
||
.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) {
|
||
// console.log("Sync took", (new Date().getTime() - startTime) + "ms", this.id)
|
||
// }
|
||
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.push(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;
|
||
|
||
|
||
/***/ },
|
||
/* 33 */
|
||
/***/ 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;
|
||
};
|
||
|
||
|
||
/***/ },
|
||
/* 34 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
|
||
/**
|
||
* Module dependencies.
|
||
*/
|
||
|
||
var debug = __webpack_require__(4)('socket.io-parser');
|
||
var json = __webpack_require__(140);
|
||
var isArray = __webpack_require__(68);
|
||
var Emitter = __webpack_require__(153);
|
||
var binary = __webpack_require__(152);
|
||
var isBuf = __webpack_require__(67);
|
||
|
||
/**
|
||
* 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'
|
||
};
|
||
}
|
||
|
||
|
||
/***/ },
|
||
/* 35 */
|
||
/***/ function(module, exports) {
|
||
|
||
module.exports = function(module) {
|
||
if(!module.webpackPolyfill) {
|
||
module.deprecate = function() {};
|
||
module.paths = [];
|
||
// module.parent = undefined by default
|
||
if(!module.children) 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;
|
||
}
|
||
|
||
|
||
/***/ },
|
||
/* 36 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
module.exports = { "default": __webpack_require__(83), __esModule: true };
|
||
|
||
/***/ },
|
||
/* 37 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
module.exports = { "default": __webpack_require__(86), __esModule: true };
|
||
|
||
/***/ },
|
||
/* 38 */
|
||
/***/ 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");
|
||
}
|
||
};
|
||
|
||
/***/ },
|
||
/* 39 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
"use strict";
|
||
|
||
exports.__esModule = true;
|
||
|
||
var _defineProperty = __webpack_require__(77);
|
||
|
||
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;
|
||
};
|
||
}();
|
||
|
||
/***/ },
|
||
/* 40 */
|
||
/***/ 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
|
||
} else {
|
||
// At least give some kind of context to the user
|
||
var err = new Error('Uncaught, unspecified "error" event. (' + er + ')');
|
||
err.context = er;
|
||
throw err;
|
||
}
|
||
}
|
||
}
|
||
|
||
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;
|
||
}
|
||
|
||
|
||
/***/ },
|
||
/* 41 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
/* WEBPACK VAR INJECTION */(function(process) {'use strict';
|
||
|
||
const fs = __webpack_require__(60);
|
||
const format = __webpack_require__(157).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__(18)))
|
||
|
||
/***/ },
|
||
/* 42 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
'use strict';
|
||
|
||
const Lazy = __webpack_require__(31);
|
||
const Store = __webpack_require__(32);
|
||
const EventIndex = __webpack_require__(61);
|
||
|
||
class EventStore extends Store {
|
||
constructor(ipfs, id, dbname, options) {
|
||
if(!options) options = {};
|
||
if(options.Index === undefined) 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()
|
||
}
|
||
});
|
||
}
|
||
|
||
get(hash) {
|
||
return this.iterator({ gte: hash, limit: 1 }).collect()[0];
|
||
}
|
||
|
||
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;
|
||
|
||
|
||
/***/ },
|
||
/* 43 */
|
||
/***/ 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)));
|
||
}
|
||
};
|
||
|
||
|
||
/***/ },
|
||
/* 44 */
|
||
/***/ 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;
|
||
};
|
||
|
||
|
||
/***/ },
|
||
/* 45 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
// getting tag from 19.1.3.6 Object.prototype.toString()
|
||
var cof = __webpack_require__(13)
|
||
, 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;
|
||
};
|
||
|
||
/***/ },
|
||
/* 46 */
|
||
/***/ function(module, exports) {
|
||
|
||
// IE 8- don't enum bug keys
|
||
module.exports = (
|
||
'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf'
|
||
).split(',');
|
||
|
||
/***/ },
|
||
/* 47 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
module.exports = __webpack_require__(2).document && document.documentElement;
|
||
|
||
/***/ },
|
||
/* 48 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
'use strict';
|
||
var LIBRARY = __webpack_require__(49)
|
||
, $export = __webpack_require__(15)
|
||
, redefine = __webpack_require__(106)
|
||
, hide = __webpack_require__(7)
|
||
, has = __webpack_require__(16)
|
||
, Iterators = __webpack_require__(9)
|
||
, $iterCreate = __webpack_require__(96)
|
||
, setToStringTag = __webpack_require__(24)
|
||
, getPrototypeOf = __webpack_require__(102)
|
||
, 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;
|
||
};
|
||
|
||
/***/ },
|
||
/* 49 */
|
||
/***/ function(module, exports) {
|
||
|
||
module.exports = true;
|
||
|
||
/***/ },
|
||
/* 50 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
// 19.1.2.14 / 15.2.3.14 Object.keys(O)
|
||
var $keys = __webpack_require__(103)
|
||
, enumBugKeys = __webpack_require__(46);
|
||
|
||
module.exports = Object.keys || function keys(O){
|
||
return $keys(O, enumBugKeys);
|
||
};
|
||
|
||
/***/ },
|
||
/* 51 */
|
||
/***/ function(module, exports) {
|
||
|
||
module.exports = function(bitmap, value){
|
||
return {
|
||
enumerable : !(bitmap & 1),
|
||
configurable: !(bitmap & 2),
|
||
writable : !(bitmap & 4),
|
||
value : value
|
||
};
|
||
};
|
||
|
||
/***/ },
|
||
/* 52 */
|
||
/***/ 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] = {});
|
||
};
|
||
|
||
/***/ },
|
||
/* 53 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
var ctx = __webpack_require__(14)
|
||
, invoke = __webpack_require__(92)
|
||
, html = __webpack_require__(47)
|
||
, cel = __webpack_require__(22)
|
||
, 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__(13)(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
|
||
};
|
||
|
||
/***/ },
|
||
/* 54 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
// 7.1.15 ToLength
|
||
var toInteger = __webpack_require__(26)
|
||
, min = Math.min;
|
||
module.exports = function(it){
|
||
return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991
|
||
};
|
||
|
||
/***/ },
|
||
/* 55 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
// 7.1.13 ToObject(argument)
|
||
var defined = __webpack_require__(21);
|
||
module.exports = function(it){
|
||
return Object(defined(it));
|
||
};
|
||
|
||
/***/ },
|
||
/* 56 */
|
||
/***/ function(module, exports) {
|
||
|
||
var id = 0
|
||
, px = Math.random();
|
||
module.exports = function(key){
|
||
return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36));
|
||
};
|
||
|
||
/***/ },
|
||
/* 57 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
/* WEBPACK VAR INJECTION */(function(global) {/**
|
||
* Module dependencies
|
||
*/
|
||
|
||
var XMLHttpRequest = __webpack_require__(29);
|
||
var XHR = __webpack_require__(127);
|
||
var JSONP = __webpack_require__(126);
|
||
var websocket = __webpack_require__(128);
|
||
|
||
/**
|
||
* 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)))
|
||
|
||
/***/ },
|
||
/* 58 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
/**
|
||
* Module dependencies.
|
||
*/
|
||
|
||
var Transport = __webpack_require__(28);
|
||
var parseqs = __webpack_require__(33);
|
||
var parser = __webpack_require__(8);
|
||
var inherit = __webpack_require__(12);
|
||
var yeast = __webpack_require__(69);
|
||
var debug = __webpack_require__(4)('engine.io-client:polling');
|
||
|
||
/**
|
||
* Module exports.
|
||
*/
|
||
|
||
module.exports = Polling;
|
||
|
||
/**
|
||
* Is XHR2 supported?
|
||
*/
|
||
|
||
var hasXHR2 = (function() {
|
||
var XMLHttpRequest = __webpack_require__(29);
|
||
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;
|
||
};
|
||
|
||
|
||
/***/ },
|
||
/* 59 */
|
||
/***/ 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;
|
||
};
|
||
|
||
/***/ },
|
||
/* 60 */
|
||
/***/ function(module, exports) {
|
||
|
||
"use strict";
|
||
'use strict';
|
||
|
||
module.exports = {
|
||
createWriteStream: function(filename, options) {
|
||
return;
|
||
},
|
||
writeFileSync: function() {
|
||
return;
|
||
},
|
||
openSync: function() {
|
||
return;
|
||
},
|
||
writeSync: function() {
|
||
return;
|
||
}
|
||
}
|
||
|
||
|
||
/***/ },
|
||
/* 61 */
|
||
/***/ 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;
|
||
|
||
|
||
/***/ },
|
||
/* 62 */
|
||
/***/ function(module, exports) {
|
||
|
||
/**
|
||
* Parses an URI
|
||
*
|
||
* @author Steven Levithan <stevenlevithan.com> (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;
|
||
};
|
||
|
||
|
||
/***/ },
|
||
/* 63 */
|
||
/***/ 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__(18)))
|
||
|
||
/***/ },
|
||
/* 64 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
|
||
/**
|
||
* Module dependencies.
|
||
*/
|
||
|
||
var eio = __webpack_require__(123);
|
||
var Socket = __webpack_require__(66);
|
||
var Emitter = __webpack_require__(44);
|
||
var parser = __webpack_require__(34);
|
||
var on = __webpack_require__(65);
|
||
var bind = __webpack_require__(43);
|
||
var debug = __webpack_require__(4)('socket.io-client:manager');
|
||
var indexOf = __webpack_require__(59);
|
||
var Backoff = __webpack_require__(78);
|
||
|
||
/**
|
||
* 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);
|
||
};
|
||
|
||
|
||
/***/ },
|
||
/* 65 */
|
||
/***/ 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);
|
||
}
|
||
};
|
||
}
|
||
|
||
|
||
/***/ },
|
||
/* 66 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
|
||
/**
|
||
* Module dependencies.
|
||
*/
|
||
|
||
var parser = __webpack_require__(34);
|
||
var Emitter = __webpack_require__(44);
|
||
var toArray = __webpack_require__(154);
|
||
var on = __webpack_require__(65);
|
||
var bind = __webpack_require__(43);
|
||
var debug = __webpack_require__(4)('socket.io-client:socket');
|
||
var hasBin = __webpack_require__(132);
|
||
|
||
/**
|
||
* 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;
|
||
};
|
||
|
||
|
||
/***/ },
|
||
/* 67 */
|
||
/***/ 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)))
|
||
|
||
/***/ },
|
||
/* 68 */
|
||
/***/ function(module, exports) {
|
||
|
||
module.exports = Array.isArray || function (arr) {
|
||
return Object.prototype.toString.call(arr) == '[object Array]';
|
||
};
|
||
|
||
|
||
/***/ },
|
||
/* 69 */
|
||
/***/ 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;
|
||
|
||
|
||
/***/ },
|
||
/* 70 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
'use strict';
|
||
|
||
var _stringify = __webpack_require__(36);
|
||
|
||
var _stringify2 = _interopRequireDefault(_stringify);
|
||
|
||
var _promise = __webpack_require__(37);
|
||
|
||
var _promise2 = _interopRequireDefault(_promise);
|
||
|
||
var _classCallCheck2 = __webpack_require__(38);
|
||
|
||
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
|
||
|
||
var _createClass2 = __webpack_require__(39);
|
||
|
||
var _createClass3 = _interopRequireDefault(_createClass2);
|
||
|
||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||
|
||
var io = __webpack_require__(150);
|
||
var logger = __webpack_require__(41).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._handleSubscribed.bind(_this));
|
||
});
|
||
}
|
||
}, {
|
||
key: 'disconnect',
|
||
value: function disconnect() {
|
||
if (this._socket) this._socket.disconnect();
|
||
}
|
||
}, {
|
||
key: 'subscribe',
|
||
value: function subscribe(hash, password, callback, fetchHistory) {
|
||
if (!this._subscriptions[hash]) {
|
||
this._subscriptions[hash] = { callback: callback, history: fetchHistory };
|
||
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) {
|
||
var subscription = this._subscriptions[hash];
|
||
if (subscription && subscription.callback) subscription.callback(hash, message);
|
||
}
|
||
}, {
|
||
key: '_handleSubscribed',
|
||
value: function _handleSubscribed(hash, message) {
|
||
var subscription = this._subscriptions[hash];
|
||
if (subscription && subscription.history && subscription.callback) subscription.callback(hash, message);
|
||
}
|
||
}]);
|
||
return Pubsub;
|
||
}();
|
||
|
||
module.exports = Pubsub;
|
||
|
||
/***/ },
|
||
/* 71 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
module.exports = { "default": __webpack_require__(85), __esModule: true };
|
||
|
||
/***/ },
|
||
/* 72 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
'use strict';
|
||
|
||
const Store = __webpack_require__(32);
|
||
const CounterIndex = __webpack_require__(143);
|
||
|
||
class CounterStore extends Store {
|
||
constructor(ipfs, id, dbname, options) {
|
||
if(!options) options = {};
|
||
if(!options.Index) 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;
|
||
|
||
|
||
/***/ },
|
||
/* 73 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
'use strict';
|
||
|
||
const Lazy = __webpack_require__(31);
|
||
const EventStore = __webpack_require__(42);
|
||
const FeedIndex = __webpack_require__(144);
|
||
|
||
class FeedStore extends EventStore {
|
||
constructor(ipfs, id, dbname, options) {
|
||
if(!options) options = {};
|
||
if(!options.Index) 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;
|
||
|
||
|
||
/***/ },
|
||
/* 74 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
'use strict';
|
||
|
||
const Store = __webpack_require__(32);
|
||
const KeyValueIndex = __webpack_require__(145);
|
||
|
||
class KeyValueStore extends Store {
|
||
constructor(ipfs, id, dbname, options) {
|
||
if(!options) options = {};
|
||
if(!options.Index) 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;
|
||
|
||
|
||
/***/ },
|
||
/* 75 */
|
||
/***/ function(module, exports) {
|
||
|
||
module.exports = after
|
||
|
||
function after(count, callback, err_cb) {
|
||
var bail = false
|
||
err_cb = err_cb || noop
|
||
proxy.count = count
|
||
|
||
return (count === 0) ? callback() : proxy
|
||
|
||
function proxy(err, result) {
|
||
if (proxy.count <= 0) {
|
||
throw new Error('after called too many times')
|
||
}
|
||
--proxy.count
|
||
|
||
// after first error, rest are passed to err_cb
|
||
if (err) {
|
||
bail = true
|
||
callback(err)
|
||
// future error callbacks will go to error handler
|
||
callback = err_cb
|
||
} else if (proxy.count === 0 && !bail) {
|
||
callback(null, result)
|
||
}
|
||
}
|
||
}
|
||
|
||
function noop() {}
|
||
|
||
|
||
/***/ },
|
||
/* 76 */
|
||
/***/ function(module, exports) {
|
||
|
||
/**
|
||
* An abstraction for slicing an arraybuffer even when
|
||
* ArrayBuffer.prototype.slice is not supported
|
||
*
|
||
* @api public
|
||
*/
|
||
|
||
module.exports = function(arraybuffer, start, end) {
|
||
var bytes = arraybuffer.byteLength;
|
||
start = start || 0;
|
||
end = end || bytes;
|
||
|
||
if (arraybuffer.slice) { return arraybuffer.slice(start, end); }
|
||
|
||
if (start < 0) { start += bytes; }
|
||
if (end < 0) { end += bytes; }
|
||
if (end > bytes) { end = bytes; }
|
||
|
||
if (start >= bytes || start >= end || bytes === 0) {
|
||
return new ArrayBuffer(0);
|
||
}
|
||
|
||
var abv = new Uint8Array(arraybuffer);
|
||
var result = new Uint8Array(end - start);
|
||
for (var i = start, ii = 0; i < end; i++, ii++) {
|
||
result[ii] = abv[i];
|
||
}
|
||
return result.buffer;
|
||
};
|
||
|
||
|
||
/***/ },
|
||
/* 77 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
module.exports = { "default": __webpack_require__(84), __esModule: true };
|
||
|
||
/***/ },
|
||
/* 78 */
|
||
/***/ function(module, exports) {
|
||
|
||
|
||
/**
|
||
* Expose `Backoff`.
|
||
*/
|
||
|
||
module.exports = Backoff;
|
||
|
||
/**
|
||
* Initialize backoff timer with `opts`.
|
||
*
|
||
* - `min` initial timeout in milliseconds [100]
|
||
* - `max` max timeout [10000]
|
||
* - `jitter` [0]
|
||
* - `factor` [2]
|
||
*
|
||
* @param {Object} opts
|
||
* @api public
|
||
*/
|
||
|
||
function Backoff(opts) {
|
||
opts = opts || {};
|
||
this.ms = opts.min || 100;
|
||
this.max = opts.max || 10000;
|
||
this.factor = opts.factor || 2;
|
||
this.jitter = opts.jitter > 0 && opts.jitter <= 1 ? opts.jitter : 0;
|
||
this.attempts = 0;
|
||
}
|
||
|
||
/**
|
||
* Return the backoff duration.
|
||
*
|
||
* @return {Number}
|
||
* @api public
|
||
*/
|
||
|
||
Backoff.prototype.duration = function(){
|
||
var ms = this.ms * Math.pow(this.factor, this.attempts++);
|
||
if (this.jitter) {
|
||
var rand = Math.random();
|
||
var deviation = Math.floor(rand * this.jitter * ms);
|
||
ms = (Math.floor(rand * 10) & 1) == 0 ? ms - deviation : ms + deviation;
|
||
}
|
||
return Math.min(ms, this.max) | 0;
|
||
};
|
||
|
||
/**
|
||
* Reset the number of attempts.
|
||
*
|
||
* @api public
|
||
*/
|
||
|
||
Backoff.prototype.reset = function(){
|
||
this.attempts = 0;
|
||
};
|
||
|
||
/**
|
||
* Set the minimum duration
|
||
*
|
||
* @api public
|
||
*/
|
||
|
||
Backoff.prototype.setMin = function(min){
|
||
this.ms = min;
|
||
};
|
||
|
||
/**
|
||
* Set the maximum duration
|
||
*
|
||
* @api public
|
||
*/
|
||
|
||
Backoff.prototype.setMax = function(max){
|
||
this.max = max;
|
||
};
|
||
|
||
/**
|
||
* Set the jitter
|
||
*
|
||
* @api public
|
||
*/
|
||
|
||
Backoff.prototype.setJitter = function(jitter){
|
||
this.jitter = jitter;
|
||
};
|
||
|
||
|
||
|
||
/***/ },
|
||
/* 79 */
|
||
/***/ function(module, exports) {
|
||
|
||
/*
|
||
* base64-arraybuffer
|
||
* https://github.com/niklasvh/base64-arraybuffer
|
||
*
|
||
* Copyright (c) 2012 Niklas von Hertzen
|
||
* Licensed under the MIT license.
|
||
*/
|
||
(function(chars){
|
||
"use strict";
|
||
|
||
exports.encode = function(arraybuffer) {
|
||
var bytes = new Uint8Array(arraybuffer),
|
||
i, len = bytes.length, base64 = "";
|
||
|
||
for (i = 0; i < len; i+=3) {
|
||
base64 += chars[bytes[i] >> 2];
|
||
base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];
|
||
base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];
|
||
base64 += chars[bytes[i + 2] & 63];
|
||
}
|
||
|
||
if ((len % 3) === 2) {
|
||
base64 = base64.substring(0, base64.length - 1) + "=";
|
||
} else if (len % 3 === 1) {
|
||
base64 = base64.substring(0, base64.length - 2) + "==";
|
||
}
|
||
|
||
return base64;
|
||
};
|
||
|
||
exports.decode = function(base64) {
|
||
var bufferLength = base64.length * 0.75,
|
||
len = base64.length, i, p = 0,
|
||
encoded1, encoded2, encoded3, encoded4;
|
||
|
||
if (base64[base64.length - 1] === "=") {
|
||
bufferLength--;
|
||
if (base64[base64.length - 2] === "=") {
|
||
bufferLength--;
|
||
}
|
||
}
|
||
|
||
var arraybuffer = new ArrayBuffer(bufferLength),
|
||
bytes = new Uint8Array(arraybuffer);
|
||
|
||
for (i = 0; i < len; i+=4) {
|
||
encoded1 = chars.indexOf(base64[i]);
|
||
encoded2 = chars.indexOf(base64[i+1]);
|
||
encoded3 = chars.indexOf(base64[i+2]);
|
||
encoded4 = chars.indexOf(base64[i+3]);
|
||
|
||
bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
|
||
bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
|
||
bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
|
||
}
|
||
|
||
return arraybuffer;
|
||
};
|
||
})("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
|
||
|
||
|
||
/***/ },
|
||
/* 80 */
|
||
/***/ function(module, exports) {
|
||
|
||
"use strict";
|
||
'use strict'
|
||
|
||
exports.toByteArray = toByteArray
|
||
exports.fromByteArray = fromByteArray
|
||
|
||
var lookup = []
|
||
var revLookup = []
|
||
var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array
|
||
|
||
function init () {
|
||
var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
||
for (var i = 0, len = code.length; i < len; ++i) {
|
||
lookup[i] = code[i]
|
||
revLookup[code.charCodeAt(i)] = i
|
||
}
|
||
|
||
revLookup['-'.charCodeAt(0)] = 62
|
||
revLookup['_'.charCodeAt(0)] = 63
|
||
}
|
||
|
||
init()
|
||
|
||
function toByteArray (b64) {
|
||
var i, j, l, tmp, placeHolders, arr
|
||
var len = b64.length
|
||
|
||
if (len % 4 > 0) {
|
||
throw new Error('Invalid string. Length must be a multiple of 4')
|
||
}
|
||
|
||
// the number of equal signs (place holders)
|
||
// if there are two placeholders, than the two characters before it
|
||
// represent one byte
|
||
// if there is only one, then the three characters before it represent 2 bytes
|
||
// this is just a cheap hack to not do indexOf twice
|
||
placeHolders = b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0
|
||
|
||
// base64 is 4/3 + up to two characters of the original data
|
||
arr = new Arr(len * 3 / 4 - placeHolders)
|
||
|
||
// if there are placeholders, only get up to the last complete 4 chars
|
||
l = placeHolders > 0 ? len - 4 : len
|
||
|
||
var L = 0
|
||
|
||
for (i = 0, j = 0; i < l; i += 4, j += 3) {
|
||
tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)]
|
||
arr[L++] = (tmp >> 16) & 0xFF
|
||
arr[L++] = (tmp >> 8) & 0xFF
|
||
arr[L++] = tmp & 0xFF
|
||
}
|
||
|
||
if (placeHolders === 2) {
|
||
tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4)
|
||
arr[L++] = tmp & 0xFF
|
||
} else if (placeHolders === 1) {
|
||
tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2)
|
||
arr[L++] = (tmp >> 8) & 0xFF
|
||
arr[L++] = tmp & 0xFF
|
||
}
|
||
|
||
return arr
|
||
}
|
||
|
||
function tripletToBase64 (num) {
|
||
return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F]
|
||
}
|
||
|
||
function encodeChunk (uint8, start, end) {
|
||
var tmp
|
||
var output = []
|
||
for (var i = start; i < end; i += 3) {
|
||
tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
|
||
output.push(tripletToBase64(tmp))
|
||
}
|
||
return output.join('')
|
||
}
|
||
|
||
function fromByteArray (uint8) {
|
||
var tmp
|
||
var len = uint8.length
|
||
var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes
|
||
var output = ''
|
||
var parts = []
|
||
var maxChunkLength = 16383 // must be multiple of 3
|
||
|
||
// go through the array every three bytes, we'll deal with trailing stuff later
|
||
for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
|
||
parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)))
|
||
}
|
||
|
||
// pad the end with zeros, but make sure to not forget the extra bytes
|
||
if (extraBytes === 1) {
|
||
tmp = uint8[len - 1]
|
||
output += lookup[tmp >> 2]
|
||
output += lookup[(tmp << 4) & 0x3F]
|
||
output += '=='
|
||
} else if (extraBytes === 2) {
|
||
tmp = (uint8[len - 2] << 8) + (uint8[len - 1])
|
||
output += lookup[tmp >> 10]
|
||
output += lookup[(tmp >> 4) & 0x3F]
|
||
output += lookup[(tmp << 2) & 0x3F]
|
||
output += '='
|
||
}
|
||
|
||
parts.push(output)
|
||
|
||
return parts.join('')
|
||
}
|
||
|
||
|
||
/***/ },
|
||
/* 81 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
/* WEBPACK VAR INJECTION */(function(global) {/**
|
||
* Create a blob builder even when vendor prefixes exist
|
||
*/
|
||
|
||
var BlobBuilder = global.BlobBuilder
|
||
|| global.WebKitBlobBuilder
|
||
|| global.MSBlobBuilder
|
||
|| global.MozBlobBuilder;
|
||
|
||
/**
|
||
* Check if Blob constructor is supported
|
||
*/
|
||
|
||
var blobSupported = (function() {
|
||
try {
|
||
var a = new Blob(['hi']);
|
||
return a.size === 2;
|
||
} catch(e) {
|
||
return false;
|
||
}
|
||
})();
|
||
|
||
/**
|
||
* Check if Blob constructor supports ArrayBufferViews
|
||
* Fails in Safari 6, so we need to map to ArrayBuffers there.
|
||
*/
|
||
|
||
var blobSupportsArrayBufferView = blobSupported && (function() {
|
||
try {
|
||
var b = new Blob([new Uint8Array([1,2])]);
|
||
return b.size === 2;
|
||
} catch(e) {
|
||
return false;
|
||
}
|
||
})();
|
||
|
||
/**
|
||
* Check if BlobBuilder is supported
|
||
*/
|
||
|
||
var blobBuilderSupported = BlobBuilder
|
||
&& BlobBuilder.prototype.append
|
||
&& BlobBuilder.prototype.getBlob;
|
||
|
||
/**
|
||
* Helper function that maps ArrayBufferViews to ArrayBuffers
|
||
* Used by BlobBuilder constructor and old browsers that didn't
|
||
* support it in the Blob constructor.
|
||
*/
|
||
|
||
function mapArrayBufferViews(ary) {
|
||
for (var i = 0; i < ary.length; i++) {
|
||
var chunk = ary[i];
|
||
if (chunk.buffer instanceof ArrayBuffer) {
|
||
var buf = chunk.buffer;
|
||
|
||
// if this is a subarray, make a copy so we only
|
||
// include the subarray region from the underlying buffer
|
||
if (chunk.byteLength !== buf.byteLength) {
|
||
var copy = new Uint8Array(chunk.byteLength);
|
||
copy.set(new Uint8Array(buf, chunk.byteOffset, chunk.byteLength));
|
||
buf = copy.buffer;
|
||
}
|
||
|
||
ary[i] = buf;
|
||
}
|
||
}
|
||
}
|
||
|
||
function BlobBuilderConstructor(ary, options) {
|
||
options = options || {};
|
||
|
||
var bb = new BlobBuilder();
|
||
mapArrayBufferViews(ary);
|
||
|
||
for (var i = 0; i < ary.length; i++) {
|
||
bb.append(ary[i]);
|
||
}
|
||
|
||
return (options.type) ? bb.getBlob(options.type) : bb.getBlob();
|
||
};
|
||
|
||
function BlobConstructor(ary, options) {
|
||
mapArrayBufferViews(ary);
|
||
return new Blob(ary, options || {});
|
||
};
|
||
|
||
module.exports = (function() {
|
||
if (blobSupported) {
|
||
return blobSupportsArrayBufferView ? global.Blob : BlobConstructor;
|
||
} else if (blobBuilderSupported) {
|
||
return BlobBuilderConstructor;
|
||
} else {
|
||
return undefined;
|
||
}
|
||
})();
|
||
|
||
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
|
||
|
||
/***/ },
|
||
/* 82 */
|
||
/***/ 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.4.1
|
||
* 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<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
|
||
"use strict";
|
||
module.exports = function(Promise) {
|
||
var SomePromiseArray = Promise._SomePromiseArray;
|
||
function any(promises) {
|
||
var ret = new SomePromiseArray(promises);
|
||
var promise = ret.promise();
|
||
ret.setHowMany(1);
|
||
ret.setUnwrap();
|
||
ret.init();
|
||
return promise;
|
||
}
|
||
|
||
Promise.any = function (promises) {
|
||
return any(promises);
|
||
};
|
||
|
||
Promise.prototype.any = function () {
|
||
return any(this);
|
||
};
|
||
|
||
};
|
||
|
||
},{}],2:[function(_dereq_,module,exports){
|
||
"use strict";
|
||
var firstLineError;
|
||
try {throw new Error(); } catch (e) {firstLineError = e;}
|
||
var schedule = _dereq_("./schedule");
|
||
var Queue = _dereq_("./queue");
|
||
var util = _dereq_("./util");
|
||
|
||
function Async() {
|
||
this._customScheduler = false;
|
||
this._isTickUsed = false;
|
||
this._lateQueue = new Queue(16);
|
||
this._normalQueue = new Queue(16);
|
||
this._haveDrainedQueues = false;
|
||
this._trampolineEnabled = true;
|
||
var self = this;
|
||
this.drainQueues = function () {
|
||
self._drainQueues();
|
||
};
|
||
this._schedule = schedule;
|
||
}
|
||
|
||
Async.prototype.setScheduler = function(fn) {
|
||
var prev = this._schedule;
|
||
this._schedule = fn;
|
||
this._customScheduler = true;
|
||
return prev;
|
||
};
|
||
|
||
Async.prototype.hasCustomScheduler = function() {
|
||
return this._customScheduler;
|
||
};
|
||
|
||
Async.prototype.enableTrampoline = function() {
|
||
this._trampolineEnabled = true;
|
||
};
|
||
|
||
Async.prototype.disableTrampolineIfNecessary = function() {
|
||
if (util.hasDevTools) {
|
||
this._trampolineEnabled = false;
|
||
}
|
||
};
|
||
|
||
Async.prototype.haveItemsQueued = function () {
|
||
return this._isTickUsed || this._haveDrainedQueues;
|
||
};
|
||
|
||
|
||
Async.prototype.fatalError = function(e, isNode) {
|
||
if (isNode) {
|
||
process.stderr.write("Fatal " + (e instanceof Error ? e.stack : e) +
|
||
"\n");
|
||
process.exit(2);
|
||
} else {
|
||
this.throwLater(e);
|
||
}
|
||
};
|
||
|
||
Async.prototype.throwLater = function(fn, arg) {
|
||
if (arguments.length === 1) {
|
||
arg = fn;
|
||
fn = function () { throw arg; };
|
||
}
|
||
if (typeof setTimeout !== "undefined") {
|
||
setTimeout(function() {
|
||
fn(arg);
|
||
}, 0);
|
||
} else try {
|
||
this._schedule(function() {
|
||
fn(arg);
|
||
});
|
||
} catch (e) {
|
||
throw new Error("No async scheduler available\u000a\u000a See http://goo.gl/MqrFmX\u000a");
|
||
}
|
||
};
|
||
|
||
function AsyncInvokeLater(fn, receiver, arg) {
|
||
this._lateQueue.push(fn, receiver, arg);
|
||
this._queueTick();
|
||
}
|
||
|
||
function AsyncInvoke(fn, receiver, arg) {
|
||
this._normalQueue.push(fn, receiver, arg);
|
||
this._queueTick();
|
||
}
|
||
|
||
function AsyncSettlePromises(promise) {
|
||
this._normalQueue._pushOne(promise);
|
||
this._queueTick();
|
||
}
|
||
|
||
if (!util.hasDevTools) {
|
||
Async.prototype.invokeLater = AsyncInvokeLater;
|
||
Async.prototype.invoke = AsyncInvoke;
|
||
Async.prototype.settlePromises = AsyncSettlePromises;
|
||
} else {
|
||
Async.prototype.invokeLater = function (fn, receiver, arg) {
|
||
if (this._trampolineEnabled) {
|
||
AsyncInvokeLater.call(this, fn, receiver, arg);
|
||
} else {
|
||
this._schedule(function() {
|
||
setTimeout(function() {
|
||
fn.call(receiver, arg);
|
||
}, 100);
|
||
});
|
||
}
|
||
};
|
||
|
||
Async.prototype.invoke = function (fn, receiver, arg) {
|
||
if (this._trampolineEnabled) {
|
||
AsyncInvoke.call(this, fn, receiver, arg);
|
||
} else {
|
||
this._schedule(function() {
|
||
fn.call(receiver, arg);
|
||
});
|
||
}
|
||
};
|
||
|
||
Async.prototype.settlePromises = function(promise) {
|
||
if (this._trampolineEnabled) {
|
||
AsyncSettlePromises.call(this, promise);
|
||
} else {
|
||
this._schedule(function() {
|
||
promise._settlePromises();
|
||
});
|
||
}
|
||
};
|
||
}
|
||
|
||
Async.prototype.invokeFirst = function (fn, receiver, arg) {
|
||
this._normalQueue.unshift(fn, receiver, arg);
|
||
this._queueTick();
|
||
};
|
||
|
||
Async.prototype._drainQueue = function(queue) {
|
||
while (queue.length() > 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 = 0;
|
||
if (options !== undefined) {
|
||
if (typeof options === "object" && options !== null) {
|
||
if (typeof options.concurrency !== "number") {
|
||
return Promise.reject(
|
||
new TypeError("'concurrency' must be a number but it is " +
|
||
util.classString(options.concurrency)));
|
||
}
|
||
limit = options.concurrency;
|
||
} else {
|
||
return Promise.reject(new TypeError(
|
||
"options argument must be an object but it is " +
|
||
util.classString(options)));
|
||
}
|
||
}
|
||
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.getNewLibraryCopy = module.exports;
|
||
|
||
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;
|
||
Promise.version = "3.4.0";
|
||
_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) {
|
||
try {
|
||
return hasProp.call(obj, "_promise0");
|
||
} catch (e) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
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;
|
||
var NULL = {};
|
||
|
||
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__(18), __webpack_require__(0), __webpack_require__(11).setImmediate))
|
||
|
||
/***/ },
|
||
/* 83 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
var core = __webpack_require__(3)
|
||
, $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);
|
||
};
|
||
|
||
/***/ },
|
||
/* 84 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
__webpack_require__(114);
|
||
var $Object = __webpack_require__(3).Object;
|
||
module.exports = function defineProperty(it, key, desc){
|
||
return $Object.defineProperty(it, key, desc);
|
||
};
|
||
|
||
/***/ },
|
||
/* 85 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
__webpack_require__(115);
|
||
module.exports = __webpack_require__(3).Object.keys;
|
||
|
||
/***/ },
|
||
/* 86 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
__webpack_require__(116);
|
||
__webpack_require__(118);
|
||
__webpack_require__(119);
|
||
__webpack_require__(117);
|
||
module.exports = __webpack_require__(3).Promise;
|
||
|
||
/***/ },
|
||
/* 87 */
|
||
/***/ function(module, exports) {
|
||
|
||
module.exports = function(){ /* empty */ };
|
||
|
||
/***/ },
|
||
/* 88 */
|
||
/***/ function(module, exports) {
|
||
|
||
module.exports = function(it, Constructor, name, forbiddenField){
|
||
if(!(it instanceof Constructor) || (forbiddenField !== undefined && forbiddenField in it)){
|
||
throw TypeError(name + ': incorrect invocation!');
|
||
} return it;
|
||
};
|
||
|
||
/***/ },
|
||
/* 89 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
// false -> Array#indexOf
|
||
// true -> Array#includes
|
||
var toIObject = __webpack_require__(27)
|
||
, toLength = __webpack_require__(54)
|
||
, toIndex = __webpack_require__(110);
|
||
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;
|
||
};
|
||
};
|
||
|
||
/***/ },
|
||
/* 90 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
var ctx = __webpack_require__(14)
|
||
, call = __webpack_require__(95)
|
||
, isArrayIter = __webpack_require__(94)
|
||
, anObject = __webpack_require__(5)
|
||
, toLength = __webpack_require__(54)
|
||
, getIterFn = __webpack_require__(112)
|
||
, BREAK = {}
|
||
, RETURN = {};
|
||
var exports = module.exports = function(iterable, entries, fn, that, ITERATOR){
|
||
var iterFn = ITERATOR ? function(){ return iterable; } : getIterFn(iterable)
|
||
, f = ctx(fn, that, entries ? 2 : 1)
|
||
, index = 0
|
||
, length, step, iterator, result;
|
||
if(typeof iterFn != 'function')throw TypeError(iterable + ' is not iterable!');
|
||
// fast case for arrays with default iterator
|
||
if(isArrayIter(iterFn))for(length = toLength(iterable.length); length > index; index++){
|
||
result = entries ? f(anObject(step = iterable[index])[0], step[1]) : f(iterable[index]);
|
||
if(result === BREAK || result === RETURN)return result;
|
||
} else for(iterator = iterFn.call(iterable); !(step = iterator.next()).done; ){
|
||
result = call(iterator, f, step.value, entries);
|
||
if(result === BREAK || result === RETURN)return result;
|
||
}
|
||
};
|
||
exports.BREAK = BREAK;
|
||
exports.RETURN = RETURN;
|
||
|
||
/***/ },
|
||
/* 91 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
module.exports = !__webpack_require__(6) && !__webpack_require__(23)(function(){
|
||
return Object.defineProperty(__webpack_require__(22)('div'), 'a', {get: function(){ return 7; }}).a != 7;
|
||
});
|
||
|
||
/***/ },
|
||
/* 92 */
|
||
/***/ function(module, exports) {
|
||
|
||
// fast apply, http://jsperf.lnkit.com/fast-apply/5
|
||
module.exports = function(fn, args, that){
|
||
var un = that === undefined;
|
||
switch(args.length){
|
||
case 0: return un ? fn()
|
||
: fn.call(that);
|
||
case 1: return un ? fn(args[0])
|
||
: fn.call(that, args[0]);
|
||
case 2: return un ? fn(args[0], args[1])
|
||
: fn.call(that, args[0], args[1]);
|
||
case 3: return un ? fn(args[0], args[1], args[2])
|
||
: fn.call(that, args[0], args[1], args[2]);
|
||
case 4: return un ? fn(args[0], args[1], args[2], args[3])
|
||
: fn.call(that, args[0], args[1], args[2], args[3]);
|
||
} return fn.apply(that, args);
|
||
};
|
||
|
||
/***/ },
|
||
/* 93 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
// fallback for non-array-like ES3 and non-enumerable old V8 strings
|
||
var cof = __webpack_require__(13);
|
||
module.exports = Object('z').propertyIsEnumerable(0) ? Object : function(it){
|
||
return cof(it) == 'String' ? it.split('') : Object(it);
|
||
};
|
||
|
||
/***/ },
|
||
/* 94 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
// check on default Array iterator
|
||
var Iterators = __webpack_require__(9)
|
||
, ITERATOR = __webpack_require__(1)('iterator')
|
||
, ArrayProto = Array.prototype;
|
||
|
||
module.exports = function(it){
|
||
return it !== undefined && (Iterators.Array === it || ArrayProto[ITERATOR] === it);
|
||
};
|
||
|
||
/***/ },
|
||
/* 95 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
// call something on iterator step with safe closing on error
|
||
var anObject = __webpack_require__(5);
|
||
module.exports = function(iterator, fn, value, entries){
|
||
try {
|
||
return entries ? fn(anObject(value)[0], value[1]) : fn(value);
|
||
// 7.4.6 IteratorClose(iterator, completion)
|
||
} catch(e){
|
||
var ret = iterator['return'];
|
||
if(ret !== undefined)anObject(ret.call(iterator));
|
||
throw e;
|
||
}
|
||
};
|
||
|
||
/***/ },
|
||
/* 96 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
'use strict';
|
||
var create = __webpack_require__(100)
|
||
, descriptor = __webpack_require__(51)
|
||
, setToStringTag = __webpack_require__(24)
|
||
, IteratorPrototype = {};
|
||
|
||
// 25.1.2.1.1 %IteratorPrototype%[@@iterator]()
|
||
__webpack_require__(7)(IteratorPrototype, __webpack_require__(1)('iterator'), function(){ return this; });
|
||
|
||
module.exports = function(Constructor, NAME, next){
|
||
Constructor.prototype = create(IteratorPrototype, {next: descriptor(1, next)});
|
||
setToStringTag(Constructor, NAME + ' Iterator');
|
||
};
|
||
|
||
/***/ },
|
||
/* 97 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
var ITERATOR = __webpack_require__(1)('iterator')
|
||
, SAFE_CLOSING = false;
|
||
|
||
try {
|
||
var riter = [7][ITERATOR]();
|
||
riter['return'] = function(){ SAFE_CLOSING = true; };
|
||
Array.from(riter, function(){ throw 2; });
|
||
} catch(e){ /* empty */ }
|
||
|
||
module.exports = function(exec, skipClosing){
|
||
if(!skipClosing && !SAFE_CLOSING)return false;
|
||
var safe = false;
|
||
try {
|
||
var arr = [7]
|
||
, iter = arr[ITERATOR]();
|
||
iter.next = function(){ return {done: safe = true}; };
|
||
arr[ITERATOR] = function(){ return iter; };
|
||
exec(arr);
|
||
} catch(e){ /* empty */ }
|
||
return safe;
|
||
};
|
||
|
||
/***/ },
|
||
/* 98 */
|
||
/***/ function(module, exports) {
|
||
|
||
module.exports = function(done, value){
|
||
return {value: value, done: !!done};
|
||
};
|
||
|
||
/***/ },
|
||
/* 99 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
var global = __webpack_require__(2)
|
||
, macrotask = __webpack_require__(53).set
|
||
, Observer = global.MutationObserver || global.WebKitMutationObserver
|
||
, process = global.process
|
||
, Promise = global.Promise
|
||
, isNode = __webpack_require__(13)(process) == 'process';
|
||
|
||
module.exports = function(){
|
||
var head, last, notify;
|
||
|
||
var flush = function(){
|
||
var parent, fn;
|
||
if(isNode && (parent = process.domain))parent.exit();
|
||
while(head){
|
||
fn = head.fn;
|
||
head = head.next;
|
||
try {
|
||
fn();
|
||
} catch(e){
|
||
if(head)notify();
|
||
else last = undefined;
|
||
throw e;
|
||
}
|
||
} last = undefined;
|
||
if(parent)parent.enter();
|
||
};
|
||
|
||
// Node.js
|
||
if(isNode){
|
||
notify = function(){
|
||
process.nextTick(flush);
|
||
};
|
||
// browsers with MutationObserver
|
||
} else if(Observer){
|
||
var toggle = true
|
||
, node = document.createTextNode('');
|
||
new Observer(flush).observe(node, {characterData: true}); // eslint-disable-line no-new
|
||
notify = function(){
|
||
node.data = toggle = !toggle;
|
||
};
|
||
// environments with maybe non-completely correct, but existent Promise
|
||
} else if(Promise && Promise.resolve){
|
||
var promise = Promise.resolve();
|
||
notify = function(){
|
||
promise.then(flush);
|
||
};
|
||
// for other environments - macrotask based on:
|
||
// - setImmediate
|
||
// - MessageChannel
|
||
// - window.postMessag
|
||
// - onreadystatechange
|
||
// - setTimeout
|
||
} else {
|
||
notify = function(){
|
||
// strange IE + webpack dev server bug - use .call(global)
|
||
macrotask.call(global, flush);
|
||
};
|
||
}
|
||
|
||
return function(fn){
|
||
var task = {fn: fn, next: undefined};
|
||
if(last)last.next = task;
|
||
if(!head){
|
||
head = task;
|
||
notify();
|
||
} last = task;
|
||
};
|
||
};
|
||
|
||
/***/ },
|
||
/* 100 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
// 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties])
|
||
var anObject = __webpack_require__(5)
|
||
, dPs = __webpack_require__(101)
|
||
, enumBugKeys = __webpack_require__(46)
|
||
, IE_PROTO = __webpack_require__(25)('IE_PROTO')
|
||
, Empty = function(){ /* empty */ }
|
||
, PROTOTYPE = 'prototype';
|
||
|
||
// Create object with fake `null` prototype: use iframe Object with cleared prototype
|
||
var createDict = function(){
|
||
// Thrash, waste and sodomy: IE GC bug
|
||
var iframe = __webpack_require__(22)('iframe')
|
||
, i = enumBugKeys.length
|
||
, lt = '<'
|
||
, gt = '>'
|
||
, iframeDocument;
|
||
iframe.style.display = 'none';
|
||
__webpack_require__(47).appendChild(iframe);
|
||
iframe.src = 'javascript:'; // eslint-disable-line no-script-url
|
||
// createDict = iframe.contentWindow.Object;
|
||
// html.removeChild(iframe);
|
||
iframeDocument = iframe.contentWindow.document;
|
||
iframeDocument.open();
|
||
iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt);
|
||
iframeDocument.close();
|
||
createDict = iframeDocument.F;
|
||
while(i--)delete createDict[PROTOTYPE][enumBugKeys[i]];
|
||
return createDict();
|
||
};
|
||
|
||
module.exports = Object.create || function create(O, Properties){
|
||
var result;
|
||
if(O !== null){
|
||
Empty[PROTOTYPE] = anObject(O);
|
||
result = new Empty;
|
||
Empty[PROTOTYPE] = null;
|
||
// add "__proto__" for Object.getPrototypeOf polyfill
|
||
result[IE_PROTO] = O;
|
||
} else result = createDict();
|
||
return Properties === undefined ? result : dPs(result, Properties);
|
||
};
|
||
|
||
|
||
/***/ },
|
||
/* 101 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
var dP = __webpack_require__(10)
|
||
, anObject = __webpack_require__(5)
|
||
, getKeys = __webpack_require__(50);
|
||
|
||
module.exports = __webpack_require__(6) ? Object.defineProperties : function defineProperties(O, Properties){
|
||
anObject(O);
|
||
var keys = getKeys(Properties)
|
||
, length = keys.length
|
||
, i = 0
|
||
, P;
|
||
while(length > i)dP.f(O, P = keys[i++], Properties[P]);
|
||
return O;
|
||
};
|
||
|
||
/***/ },
|
||
/* 102 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
// 19.1.2.9 / 15.2.3.2 Object.getPrototypeOf(O)
|
||
var has = __webpack_require__(16)
|
||
, toObject = __webpack_require__(55)
|
||
, IE_PROTO = __webpack_require__(25)('IE_PROTO')
|
||
, ObjectProto = Object.prototype;
|
||
|
||
module.exports = Object.getPrototypeOf || function(O){
|
||
O = toObject(O);
|
||
if(has(O, IE_PROTO))return O[IE_PROTO];
|
||
if(typeof O.constructor == 'function' && O instanceof O.constructor){
|
||
return O.constructor.prototype;
|
||
} return O instanceof Object ? ObjectProto : null;
|
||
};
|
||
|
||
/***/ },
|
||
/* 103 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
var has = __webpack_require__(16)
|
||
, toIObject = __webpack_require__(27)
|
||
, arrayIndexOf = __webpack_require__(89)(false)
|
||
, IE_PROTO = __webpack_require__(25)('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;
|
||
};
|
||
|
||
/***/ },
|
||
/* 104 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
// most Object methods by ES6 should accept primitives
|
||
var $export = __webpack_require__(15)
|
||
, core = __webpack_require__(3)
|
||
, fails = __webpack_require__(23);
|
||
module.exports = function(KEY, exec){
|
||
var fn = (core.Object || {})[KEY] || Object[KEY]
|
||
, exp = {};
|
||
exp[KEY] = exec(fn);
|
||
$export($export.S + $export.F * fails(function(){ fn(1); }), 'Object', exp);
|
||
};
|
||
|
||
/***/ },
|
||
/* 105 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
var hide = __webpack_require__(7);
|
||
module.exports = function(target, src, safe){
|
||
for(var key in src){
|
||
if(safe && target[key])target[key] = src[key];
|
||
else hide(target, key, src[key]);
|
||
} return target;
|
||
};
|
||
|
||
/***/ },
|
||
/* 106 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
module.exports = __webpack_require__(7);
|
||
|
||
/***/ },
|
||
/* 107 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
'use strict';
|
||
var global = __webpack_require__(2)
|
||
, core = __webpack_require__(3)
|
||
, dP = __webpack_require__(10)
|
||
, DESCRIPTORS = __webpack_require__(6)
|
||
, SPECIES = __webpack_require__(1)('species');
|
||
|
||
module.exports = function(KEY){
|
||
var C = typeof core[KEY] == 'function' ? core[KEY] : global[KEY];
|
||
if(DESCRIPTORS && C && !C[SPECIES])dP.f(C, SPECIES, {
|
||
configurable: true,
|
||
get: function(){ return this; }
|
||
});
|
||
};
|
||
|
||
/***/ },
|
||
/* 108 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
// 7.3.20 SpeciesConstructor(O, defaultConstructor)
|
||
var anObject = __webpack_require__(5)
|
||
, aFunction = __webpack_require__(20)
|
||
, SPECIES = __webpack_require__(1)('species');
|
||
module.exports = function(O, D){
|
||
var C = anObject(O).constructor, S;
|
||
return C === undefined || (S = anObject(C)[SPECIES]) == undefined ? D : aFunction(S);
|
||
};
|
||
|
||
/***/ },
|
||
/* 109 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
var toInteger = __webpack_require__(26)
|
||
, defined = __webpack_require__(21);
|
||
// true -> String#at
|
||
// false -> String#codePointAt
|
||
module.exports = function(TO_STRING){
|
||
return function(that, pos){
|
||
var s = String(defined(that))
|
||
, i = toInteger(pos)
|
||
, l = s.length
|
||
, a, b;
|
||
if(i < 0 || i >= l)return TO_STRING ? '' : undefined;
|
||
a = s.charCodeAt(i);
|
||
return a < 0xd800 || a > 0xdbff || i + 1 === l || (b = s.charCodeAt(i + 1)) < 0xdc00 || b > 0xdfff
|
||
? TO_STRING ? s.charAt(i) : a
|
||
: TO_STRING ? s.slice(i, i + 2) : (a - 0xd800 << 10) + (b - 0xdc00) + 0x10000;
|
||
};
|
||
};
|
||
|
||
/***/ },
|
||
/* 110 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
var toInteger = __webpack_require__(26)
|
||
, max = Math.max
|
||
, min = Math.min;
|
||
module.exports = function(index, length){
|
||
index = toInteger(index);
|
||
return index < 0 ? max(index + length, 0) : min(index, length);
|
||
};
|
||
|
||
/***/ },
|
||
/* 111 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
// 7.1.1 ToPrimitive(input [, PreferredType])
|
||
var isObject = __webpack_require__(17);
|
||
// 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");
|
||
};
|
||
|
||
/***/ },
|
||
/* 112 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
var classof = __webpack_require__(45)
|
||
, ITERATOR = __webpack_require__(1)('iterator')
|
||
, Iterators = __webpack_require__(9);
|
||
module.exports = __webpack_require__(3).getIteratorMethod = function(it){
|
||
if(it != undefined)return it[ITERATOR]
|
||
|| it['@@iterator']
|
||
|| Iterators[classof(it)];
|
||
};
|
||
|
||
/***/ },
|
||
/* 113 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
'use strict';
|
||
var addToUnscopables = __webpack_require__(87)
|
||
, step = __webpack_require__(98)
|
||
, Iterators = __webpack_require__(9)
|
||
, toIObject = __webpack_require__(27);
|
||
|
||
// 22.1.3.4 Array.prototype.entries()
|
||
// 22.1.3.13 Array.prototype.keys()
|
||
// 22.1.3.29 Array.prototype.values()
|
||
// 22.1.3.30 Array.prototype[@@iterator]()
|
||
module.exports = __webpack_require__(48)(Array, 'Array', function(iterated, kind){
|
||
this._t = toIObject(iterated); // target
|
||
this._i = 0; // next index
|
||
this._k = kind; // kind
|
||
// 22.1.5.2.1 %ArrayIteratorPrototype%.next()
|
||
}, function(){
|
||
var O = this._t
|
||
, kind = this._k
|
||
, index = this._i++;
|
||
if(!O || index >= O.length){
|
||
this._t = undefined;
|
||
return step(1);
|
||
}
|
||
if(kind == 'keys' )return step(0, index);
|
||
if(kind == 'values')return step(0, O[index]);
|
||
return step(0, [index, O[index]]);
|
||
}, 'values');
|
||
|
||
// argumentsList[@@iterator] is %ArrayProto_values% (9.4.4.6, 9.4.4.7)
|
||
Iterators.Arguments = Iterators.Array;
|
||
|
||
addToUnscopables('keys');
|
||
addToUnscopables('values');
|
||
addToUnscopables('entries');
|
||
|
||
/***/ },
|
||
/* 114 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
var $export = __webpack_require__(15);
|
||
// 19.1.2.4 / 15.2.3.6 Object.defineProperty(O, P, Attributes)
|
||
$export($export.S + $export.F * !__webpack_require__(6), 'Object', {defineProperty: __webpack_require__(10).f});
|
||
|
||
/***/ },
|
||
/* 115 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
// 19.1.2.14 Object.keys(O)
|
||
var toObject = __webpack_require__(55)
|
||
, $keys = __webpack_require__(50);
|
||
|
||
__webpack_require__(104)('keys', function(){
|
||
return function keys(it){
|
||
return $keys(toObject(it));
|
||
};
|
||
});
|
||
|
||
/***/ },
|
||
/* 116 */
|
||
/***/ function(module, exports) {
|
||
|
||
|
||
|
||
/***/ },
|
||
/* 117 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
'use strict';
|
||
var LIBRARY = __webpack_require__(49)
|
||
, global = __webpack_require__(2)
|
||
, ctx = __webpack_require__(14)
|
||
, classof = __webpack_require__(45)
|
||
, $export = __webpack_require__(15)
|
||
, isObject = __webpack_require__(17)
|
||
, aFunction = __webpack_require__(20)
|
||
, anInstance = __webpack_require__(88)
|
||
, forOf = __webpack_require__(90)
|
||
, speciesConstructor = __webpack_require__(108)
|
||
, task = __webpack_require__(53).set
|
||
, microtask = __webpack_require__(99)()
|
||
, PROMISE = 'Promise'
|
||
, TypeError = global.TypeError
|
||
, process = global.process
|
||
, $Promise = global[PROMISE]
|
||
, process = global.process
|
||
, isNode = classof(process) == 'process'
|
||
, empty = function(){ /* empty */ }
|
||
, Internal, GenericPromiseCapability, Wrapper;
|
||
|
||
var USE_NATIVE = !!function(){
|
||
try {
|
||
// correct subclassing with @@species support
|
||
var promise = $Promise.resolve(1)
|
||
, FakePromise = (promise.constructor = {})[__webpack_require__(1)('species')] = function(exec){ exec(empty, empty); };
|
||
// unhandled rejections tracking support, NodeJS Promise without it fails @@species test
|
||
return (isNode || typeof PromiseRejectionEvent == 'function') && promise.then(empty) instanceof FakePromise;
|
||
} catch(e){ /* empty */ }
|
||
}();
|
||
|
||
// helpers
|
||
var sameConstructor = function(a, b){
|
||
// with library wrapper special case
|
||
return a === b || a === $Promise && b === Wrapper;
|
||
};
|
||
var isThenable = function(it){
|
||
var then;
|
||
return isObject(it) && typeof (then = it.then) == 'function' ? then : false;
|
||
};
|
||
var newPromiseCapability = function(C){
|
||
return sameConstructor($Promise, C)
|
||
? new PromiseCapability(C)
|
||
: new GenericPromiseCapability(C);
|
||
};
|
||
var PromiseCapability = GenericPromiseCapability = function(C){
|
||
var resolve, reject;
|
||
this.promise = new C(function($$resolve, $$reject){
|
||
if(resolve !== undefined || reject !== undefined)throw TypeError('Bad Promise constructor');
|
||
resolve = $$resolve;
|
||
reject = $$reject;
|
||
});
|
||
this.resolve = aFunction(resolve);
|
||
this.reject = aFunction(reject);
|
||
};
|
||
var perform = function(exec){
|
||
try {
|
||
exec();
|
||
} catch(e){
|
||
return {error: e};
|
||
}
|
||
};
|
||
var notify = function(promise, isReject){
|
||
if(promise._n)return;
|
||
promise._n = true;
|
||
var chain = promise._c;
|
||
microtask(function(){
|
||
var value = promise._v
|
||
, ok = promise._s == 1
|
||
, i = 0;
|
||
var run = function(reaction){
|
||
var handler = ok ? reaction.ok : reaction.fail
|
||
, resolve = reaction.resolve
|
||
, reject = reaction.reject
|
||
, domain = reaction.domain
|
||
, result, then;
|
||
try {
|
||
if(handler){
|
||
if(!ok){
|
||
if(promise._h == 2)onHandleUnhandled(promise);
|
||
promise._h = 1;
|
||
}
|
||
if(handler === true)result = value;
|
||
else {
|
||
if(domain)domain.enter();
|
||
result = handler(value);
|
||
if(domain)domain.exit();
|
||
}
|
||
if(result === reaction.promise){
|
||
reject(TypeError('Promise-chain cycle'));
|
||
} else if(then = isThenable(result)){
|
||
then.call(result, resolve, reject);
|
||
} else resolve(result);
|
||
} else reject(value);
|
||
} catch(e){
|
||
reject(e);
|
||
}
|
||
};
|
||
while(chain.length > i)run(chain[i++]); // variable length - can't use forEach
|
||
promise._c = [];
|
||
promise._n = false;
|
||
if(isReject && !promise._h)onUnhandled(promise);
|
||
});
|
||
};
|
||
var onUnhandled = function(promise){
|
||
task.call(global, function(){
|
||
var value = promise._v
|
||
, abrupt, handler, console;
|
||
if(isUnhandled(promise)){
|
||
abrupt = perform(function(){
|
||
if(isNode){
|
||
process.emit('unhandledRejection', value, promise);
|
||
} else if(handler = global.onunhandledrejection){
|
||
handler({promise: promise, reason: value});
|
||
} else if((console = global.console) && console.error){
|
||
console.error('Unhandled promise rejection', value);
|
||
}
|
||
});
|
||
// Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should
|
||
promise._h = isNode || isUnhandled(promise) ? 2 : 1;
|
||
} promise._a = undefined;
|
||
if(abrupt)throw abrupt.error;
|
||
});
|
||
};
|
||
var isUnhandled = function(promise){
|
||
if(promise._h == 1)return false;
|
||
var chain = promise._a || promise._c
|
||
, i = 0
|
||
, reaction;
|
||
while(chain.length > i){
|
||
reaction = chain[i++];
|
||
if(reaction.fail || !isUnhandled(reaction.promise))return false;
|
||
} return true;
|
||
};
|
||
var onHandleUnhandled = function(promise){
|
||
task.call(global, function(){
|
||
var handler;
|
||
if(isNode){
|
||
process.emit('rejectionHandled', promise);
|
||
} else if(handler = global.onrejectionhandled){
|
||
handler({promise: promise, reason: promise._v});
|
||
}
|
||
});
|
||
};
|
||
var $reject = function(value){
|
||
var promise = this;
|
||
if(promise._d)return;
|
||
promise._d = true;
|
||
promise = promise._w || promise; // unwrap
|
||
promise._v = value;
|
||
promise._s = 2;
|
||
if(!promise._a)promise._a = promise._c.slice();
|
||
notify(promise, true);
|
||
};
|
||
var $resolve = function(value){
|
||
var promise = this
|
||
, then;
|
||
if(promise._d)return;
|
||
promise._d = true;
|
||
promise = promise._w || promise; // unwrap
|
||
try {
|
||
if(promise === value)throw TypeError("Promise can't be resolved itself");
|
||
if(then = isThenable(value)){
|
||
microtask(function(){
|
||
var wrapper = {_w: promise, _d: false}; // wrap
|
||
try {
|
||
then.call(value, ctx($resolve, wrapper, 1), ctx($reject, wrapper, 1));
|
||
} catch(e){
|
||
$reject.call(wrapper, e);
|
||
}
|
||
});
|
||
} else {
|
||
promise._v = value;
|
||
promise._s = 1;
|
||
notify(promise, false);
|
||
}
|
||
} catch(e){
|
||
$reject.call({_w: promise, _d: false}, e); // wrap
|
||
}
|
||
};
|
||
|
||
// constructor polyfill
|
||
if(!USE_NATIVE){
|
||
// 25.4.3.1 Promise(executor)
|
||
$Promise = function Promise(executor){
|
||
anInstance(this, $Promise, PROMISE, '_h');
|
||
aFunction(executor);
|
||
Internal.call(this);
|
||
try {
|
||
executor(ctx($resolve, this, 1), ctx($reject, this, 1));
|
||
} catch(err){
|
||
$reject.call(this, err);
|
||
}
|
||
};
|
||
Internal = function Promise(executor){
|
||
this._c = []; // <- awaiting reactions
|
||
this._a = undefined; // <- checked in isUnhandled reactions
|
||
this._s = 0; // <- state
|
||
this._d = false; // <- done
|
||
this._v = undefined; // <- value
|
||
this._h = 0; // <- rejection state, 0 - default, 1 - handled, 2 - unhandled
|
||
this._n = false; // <- notify
|
||
};
|
||
Internal.prototype = __webpack_require__(105)($Promise.prototype, {
|
||
// 25.4.5.3 Promise.prototype.then(onFulfilled, onRejected)
|
||
then: function then(onFulfilled, onRejected){
|
||
var reaction = newPromiseCapability(speciesConstructor(this, $Promise));
|
||
reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true;
|
||
reaction.fail = typeof onRejected == 'function' && onRejected;
|
||
reaction.domain = isNode ? process.domain : undefined;
|
||
this._c.push(reaction);
|
||
if(this._a)this._a.push(reaction);
|
||
if(this._s)notify(this, false);
|
||
return reaction.promise;
|
||
},
|
||
// 25.4.5.1 Promise.prototype.catch(onRejected)
|
||
'catch': function(onRejected){
|
||
return this.then(undefined, onRejected);
|
||
}
|
||
});
|
||
PromiseCapability = function(){
|
||
var promise = new Internal;
|
||
this.promise = promise;
|
||
this.resolve = ctx($resolve, promise, 1);
|
||
this.reject = ctx($reject, promise, 1);
|
||
};
|
||
}
|
||
|
||
$export($export.G + $export.W + $export.F * !USE_NATIVE, {Promise: $Promise});
|
||
__webpack_require__(24)($Promise, PROMISE);
|
||
__webpack_require__(107)(PROMISE);
|
||
Wrapper = __webpack_require__(3)[PROMISE];
|
||
|
||
// statics
|
||
$export($export.S + $export.F * !USE_NATIVE, PROMISE, {
|
||
// 25.4.4.5 Promise.reject(r)
|
||
reject: function reject(r){
|
||
var capability = newPromiseCapability(this)
|
||
, $$reject = capability.reject;
|
||
$$reject(r);
|
||
return capability.promise;
|
||
}
|
||
});
|
||
$export($export.S + $export.F * (LIBRARY || !USE_NATIVE), PROMISE, {
|
||
// 25.4.4.6 Promise.resolve(x)
|
||
resolve: function resolve(x){
|
||
// instanceof instead of internal slot check because we should fix it without replacement native Promise core
|
||
if(x instanceof $Promise && sameConstructor(x.constructor, this))return x;
|
||
var capability = newPromiseCapability(this)
|
||
, $$resolve = capability.resolve;
|
||
$$resolve(x);
|
||
return capability.promise;
|
||
}
|
||
});
|
||
$export($export.S + $export.F * !(USE_NATIVE && __webpack_require__(97)(function(iter){
|
||
$Promise.all(iter)['catch'](empty);
|
||
})), PROMISE, {
|
||
// 25.4.4.1 Promise.all(iterable)
|
||
all: function all(iterable){
|
||
var C = this
|
||
, capability = newPromiseCapability(C)
|
||
, resolve = capability.resolve
|
||
, reject = capability.reject;
|
||
var abrupt = perform(function(){
|
||
var values = []
|
||
, index = 0
|
||
, remaining = 1;
|
||
forOf(iterable, false, function(promise){
|
||
var $index = index++
|
||
, alreadyCalled = false;
|
||
values.push(undefined);
|
||
remaining++;
|
||
C.resolve(promise).then(function(value){
|
||
if(alreadyCalled)return;
|
||
alreadyCalled = true;
|
||
values[$index] = value;
|
||
--remaining || resolve(values);
|
||
}, reject);
|
||
});
|
||
--remaining || resolve(values);
|
||
});
|
||
if(abrupt)reject(abrupt.error);
|
||
return capability.promise;
|
||
},
|
||
// 25.4.4.4 Promise.race(iterable)
|
||
race: function race(iterable){
|
||
var C = this
|
||
, capability = newPromiseCapability(C)
|
||
, reject = capability.reject;
|
||
var abrupt = perform(function(){
|
||
forOf(iterable, false, function(promise){
|
||
C.resolve(promise).then(capability.resolve, reject);
|
||
});
|
||
});
|
||
if(abrupt)reject(abrupt.error);
|
||
return capability.promise;
|
||
}
|
||
});
|
||
|
||
/***/ },
|
||
/* 118 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
'use strict';
|
||
var $at = __webpack_require__(109)(true);
|
||
|
||
// 21.1.3.27 String.prototype[@@iterator]()
|
||
__webpack_require__(48)(String, 'String', function(iterated){
|
||
this._t = String(iterated); // target
|
||
this._i = 0; // next index
|
||
// 21.1.5.2.1 %StringIteratorPrototype%.next()
|
||
}, function(){
|
||
var O = this._t
|
||
, index = this._i
|
||
, point;
|
||
if(index >= O.length)return {value: undefined, done: true};
|
||
point = $at(O, index);
|
||
this._i += point.length;
|
||
return {value: point, done: false};
|
||
});
|
||
|
||
/***/ },
|
||
/* 119 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
__webpack_require__(113);
|
||
var global = __webpack_require__(2)
|
||
, hide = __webpack_require__(7)
|
||
, Iterators = __webpack_require__(9)
|
||
, TO_STRING_TAG = __webpack_require__(1)('toStringTag');
|
||
|
||
for(var collections = ['NodeList', 'DOMTokenList', 'MediaList', 'StyleSheetList', 'CSSRuleList'], i = 0; i < 5; i++){
|
||
var NAME = collections[i]
|
||
, Collection = global[NAME]
|
||
, proto = Collection && Collection.prototype;
|
||
if(proto && !proto[TO_STRING_TAG])hide(proto, TO_STRING_TAG, NAME);
|
||
Iterators[NAME] = Iterators.Array;
|
||
}
|
||
|
||
/***/ },
|
||
/* 120 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
'use strict';
|
||
|
||
const isEqual = __webpack_require__(121).isEqual;
|
||
|
||
class GCounter {
|
||
constructor(id, payload) {
|
||
this.id = id;
|
||
this._counters = payload ? payload : {};
|
||
this._counters[this.id] = this._counters[this.id] ? this._counters[this.id] : 0;
|
||
}
|
||
|
||
increment(amount) {
|
||
if(!amount) amount = 1;
|
||
this._counters[this.id] = this._counters[this.id] + amount;
|
||
}
|
||
|
||
get value() {
|
||
return Object.keys(this._counters)
|
||
.map((f) => this._counters[f])
|
||
.reduce((previousValue, currentValue) => previousValue + currentValue, 0);
|
||
}
|
||
|
||
get payload() {
|
||
return { id: this.id, counters: this._counters };
|
||
}
|
||
|
||
compare(other) {
|
||
if(other.id !== this.id)
|
||
return false;
|
||
|
||
return isEqual(other._counters, this._counters);
|
||
}
|
||
|
||
merge(other) {
|
||
Object.keys(other._counters).forEach((f) => {
|
||
this._counters[f] = Math.max(this._counters[f] ? this._counters[f] : 0, other._counters[f]);
|
||
});
|
||
}
|
||
|
||
static from(payload) {
|
||
return new GCounter(payload.id, payload.counters);
|
||
}
|
||
|
||
}
|
||
|
||
module.exports = GCounter;
|
||
|
||
|
||
/***/ },
|
||
/* 121 */
|
||
/***/ function(module, exports) {
|
||
|
||
"use strict";
|
||
'use strict';
|
||
|
||
exports.isEqual = (a, b) => {
|
||
const propsA = Object.getOwnPropertyNames(a);
|
||
const propsB = Object.getOwnPropertyNames(b);
|
||
|
||
if(propsA.length !== propsB.length)
|
||
return false;
|
||
|
||
for(let i = 0; i < propsA.length; i ++) {
|
||
const prop = propsA[i];
|
||
if(a[prop] !== b[prop])
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
/***/ },
|
||
/* 122 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
|
||
/**
|
||
* This is the common logic for both the Node.js and web browser
|
||
* implementations of `debug()`.
|
||
*
|
||
* Expose `debug()` as the module.
|
||
*/
|
||
|
||
exports = module.exports = debug;
|
||
exports.coerce = coerce;
|
||
exports.disable = disable;
|
||
exports.enable = enable;
|
||
exports.enabled = enabled;
|
||
exports.humanize = __webpack_require__(142);
|
||
|
||
/**
|
||
* The currently active debug mode names, and names to skip.
|
||
*/
|
||
|
||
exports.names = [];
|
||
exports.skips = [];
|
||
|
||
/**
|
||
* Map of special "%n" handling functions, for the debug "format" argument.
|
||
*
|
||
* Valid key names are a single, lowercased letter, i.e. "n".
|
||
*/
|
||
|
||
exports.formatters = {};
|
||
|
||
/**
|
||
* Previously assigned color.
|
||
*/
|
||
|
||
var prevColor = 0;
|
||
|
||
/**
|
||
* Previous log timestamp.
|
||
*/
|
||
|
||
var prevTime;
|
||
|
||
/**
|
||
* Select a color.
|
||
*
|
||
* @return {Number}
|
||
* @api private
|
||
*/
|
||
|
||
function selectColor() {
|
||
return exports.colors[prevColor++ % exports.colors.length];
|
||
}
|
||
|
||
/**
|
||
* Create a debugger with the given `namespace`.
|
||
*
|
||
* @param {String} namespace
|
||
* @return {Function}
|
||
* @api public
|
||
*/
|
||
|
||
function debug(namespace) {
|
||
|
||
// define the `disabled` version
|
||
function disabled() {
|
||
}
|
||
disabled.enabled = false;
|
||
|
||
// define the `enabled` version
|
||
function enabled() {
|
||
|
||
var self = enabled;
|
||
|
||
// set `diff` timestamp
|
||
var curr = +new Date();
|
||
var ms = curr - (prevTime || curr);
|
||
self.diff = ms;
|
||
self.prev = prevTime;
|
||
self.curr = curr;
|
||
prevTime = curr;
|
||
|
||
// add the `color` if not set
|
||
if (null == self.useColors) self.useColors = exports.useColors();
|
||
if (null == self.color && self.useColors) self.color = selectColor();
|
||
|
||
var args = Array.prototype.slice.call(arguments);
|
||
|
||
args[0] = exports.coerce(args[0]);
|
||
|
||
if ('string' !== typeof args[0]) {
|
||
// anything else let's inspect with %o
|
||
args = ['%o'].concat(args);
|
||
}
|
||
|
||
// apply any `formatters` transformations
|
||
var index = 0;
|
||
args[0] = args[0].replace(/%([a-z%])/g, function(match, format) {
|
||
// if we encounter an escaped % then don't increase the array index
|
||
if (match === '%%') return match;
|
||
index++;
|
||
var formatter = exports.formatters[format];
|
||
if ('function' === typeof formatter) {
|
||
var val = args[index];
|
||
match = formatter.call(self, val);
|
||
|
||
// now we need to remove `args[index]` since it's inlined in the `format`
|
||
args.splice(index, 1);
|
||
index--;
|
||
}
|
||
return match;
|
||
});
|
||
|
||
if ('function' === typeof exports.formatArgs) {
|
||
args = exports.formatArgs.apply(self, args);
|
||
}
|
||
var logFn = enabled.log || exports.log || console.log.bind(console);
|
||
logFn.apply(self, args);
|
||
}
|
||
enabled.enabled = true;
|
||
|
||
var fn = exports.enabled(namespace) ? enabled : disabled;
|
||
|
||
fn.namespace = namespace;
|
||
|
||
return fn;
|
||
}
|
||
|
||
/**
|
||
* Enables a debug mode by namespaces. This can include modes
|
||
* separated by a colon and wildcards.
|
||
*
|
||
* @param {String} namespaces
|
||
* @api public
|
||
*/
|
||
|
||
function enable(namespaces) {
|
||
exports.save(namespaces);
|
||
|
||
var split = (namespaces || '').split(/[\s,]+/);
|
||
var len = split.length;
|
||
|
||
for (var i = 0; i < len; i++) {
|
||
if (!split[i]) continue; // ignore empty strings
|
||
namespaces = split[i].replace(/\*/g, '.*?');
|
||
if (namespaces[0] === '-') {
|
||
exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
|
||
} else {
|
||
exports.names.push(new RegExp('^' + namespaces + '$'));
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Disable debug output.
|
||
*
|
||
* @api public
|
||
*/
|
||
|
||
function disable() {
|
||
exports.enable('');
|
||
}
|
||
|
||
/**
|
||
* Returns true if the given mode name is enabled, false otherwise.
|
||
*
|
||
* @param {String} name
|
||
* @return {Boolean}
|
||
* @api public
|
||
*/
|
||
|
||
function enabled(name) {
|
||
var i, len;
|
||
for (i = 0, len = exports.skips.length; i < len; i++) {
|
||
if (exports.skips[i].test(name)) {
|
||
return false;
|
||
}
|
||
}
|
||
for (i = 0, len = exports.names.length; i < len; i++) {
|
||
if (exports.names[i].test(name)) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* Coerce `val`.
|
||
*
|
||
* @param {Mixed} val
|
||
* @return {Mixed}
|
||
* @api private
|
||
*/
|
||
|
||
function coerce(val) {
|
||
if (val instanceof Error) return val.stack || val.message;
|
||
return val;
|
||
}
|
||
|
||
|
||
/***/ },
|
||
/* 123 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
|
||
module.exports = __webpack_require__(124);
|
||
|
||
|
||
/***/ },
|
||
/* 124 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
|
||
module.exports = __webpack_require__(125);
|
||
|
||
/**
|
||
* Exports parser
|
||
*
|
||
* @api public
|
||
*
|
||
*/
|
||
module.exports.parser = __webpack_require__(8);
|
||
|
||
|
||
/***/ },
|
||
/* 125 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
/* WEBPACK VAR INJECTION */(function(global) {/**
|
||
* Module dependencies.
|
||
*/
|
||
|
||
var transports = __webpack_require__(57);
|
||
var Emitter = __webpack_require__(30);
|
||
var debug = __webpack_require__(4)('engine.io-client:socket');
|
||
var index = __webpack_require__(59);
|
||
var parser = __webpack_require__(8);
|
||
var parseuri = __webpack_require__(62);
|
||
var parsejson = __webpack_require__(148);
|
||
var parseqs = __webpack_require__(33);
|
||
|
||
/**
|
||
* Module exports.
|
||
*/
|
||
|
||
module.exports = Socket;
|
||
|
||
/**
|
||
* Noop function.
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
function noop(){}
|
||
|
||
/**
|
||
* Socket constructor.
|
||
*
|
||
* @param {String|Object} uri or options
|
||
* @param {Object} options
|
||
* @api public
|
||
*/
|
||
|
||
function Socket(uri, opts){
|
||
if (!(this instanceof Socket)) return new Socket(uri, opts);
|
||
|
||
opts = opts || {};
|
||
|
||
if (uri && 'object' == typeof uri) {
|
||
opts = uri;
|
||
uri = null;
|
||
}
|
||
|
||
if (uri) {
|
||
uri = parseuri(uri);
|
||
opts.hostname = uri.host;
|
||
opts.secure = uri.protocol == 'https' || uri.protocol == 'wss';
|
||
opts.port = uri.port;
|
||
if (uri.query) opts.query = uri.query;
|
||
} else if (opts.host) {
|
||
opts.hostname = parseuri(opts.host).host;
|
||
}
|
||
|
||
this.secure = null != opts.secure ? opts.secure :
|
||
(global.location && 'https:' == location.protocol);
|
||
|
||
if (opts.hostname && !opts.port) {
|
||
// if no port is specified manually, use the protocol default
|
||
opts.port = this.secure ? '443' : '80';
|
||
}
|
||
|
||
this.agent = opts.agent || false;
|
||
this.hostname = opts.hostname ||
|
||
(global.location ? location.hostname : 'localhost');
|
||
this.port = opts.port || (global.location && location.port ?
|
||
location.port :
|
||
(this.secure ? 443 : 80));
|
||
this.query = opts.query || {};
|
||
if ('string' == typeof this.query) this.query = parseqs.decode(this.query);
|
||
this.upgrade = false !== opts.upgrade;
|
||
this.path = (opts.path || '/engine.io').replace(/\/$/, '') + '/';
|
||
this.forceJSONP = !!opts.forceJSONP;
|
||
this.jsonp = false !== opts.jsonp;
|
||
this.forceBase64 = !!opts.forceBase64;
|
||
this.enablesXDR = !!opts.enablesXDR;
|
||
this.timestampParam = opts.timestampParam || 't';
|
||
this.timestampRequests = opts.timestampRequests;
|
||
this.transports = opts.transports || ['polling', 'websocket'];
|
||
this.readyState = '';
|
||
this.writeBuffer = [];
|
||
this.policyPort = opts.policyPort || 843;
|
||
this.rememberUpgrade = opts.rememberUpgrade || false;
|
||
this.binaryType = null;
|
||
this.onlyBinaryUpgrades = opts.onlyBinaryUpgrades;
|
||
this.perMessageDeflate = false !== opts.perMessageDeflate ? (opts.perMessageDeflate || {}) : false;
|
||
|
||
if (true === this.perMessageDeflate) this.perMessageDeflate = {};
|
||
if (this.perMessageDeflate && null == this.perMessageDeflate.threshold) {
|
||
this.perMessageDeflate.threshold = 1024;
|
||
}
|
||
|
||
// SSL options for Node.js client
|
||
this.pfx = opts.pfx || null;
|
||
this.key = opts.key || null;
|
||
this.passphrase = opts.passphrase || null;
|
||
this.cert = opts.cert || null;
|
||
this.ca = opts.ca || null;
|
||
this.ciphers = opts.ciphers || null;
|
||
this.rejectUnauthorized = opts.rejectUnauthorized === undefined ? true : opts.rejectUnauthorized;
|
||
|
||
// other options for Node.js client
|
||
var freeGlobal = typeof global == 'object' && global;
|
||
if (freeGlobal.global === freeGlobal) {
|
||
if (opts.extraHeaders && Object.keys(opts.extraHeaders).length > 0) {
|
||
this.extraHeaders = opts.extraHeaders;
|
||
}
|
||
}
|
||
|
||
this.open();
|
||
}
|
||
|
||
Socket.priorWebsocketSuccess = false;
|
||
|
||
/**
|
||
* Mix in `Emitter`.
|
||
*/
|
||
|
||
Emitter(Socket.prototype);
|
||
|
||
/**
|
||
* Protocol version.
|
||
*
|
||
* @api public
|
||
*/
|
||
|
||
Socket.protocol = parser.protocol; // this is an int
|
||
|
||
/**
|
||
* Expose deps for legacy compatibility
|
||
* and standalone browser access.
|
||
*/
|
||
|
||
Socket.Socket = Socket;
|
||
Socket.Transport = __webpack_require__(28);
|
||
Socket.transports = __webpack_require__(57);
|
||
Socket.parser = __webpack_require__(8);
|
||
|
||
/**
|
||
* Creates transport of the given type.
|
||
*
|
||
* @param {String} transport name
|
||
* @return {Transport}
|
||
* @api private
|
||
*/
|
||
|
||
Socket.prototype.createTransport = function (name) {
|
||
debug('creating transport "%s"', name);
|
||
var query = clone(this.query);
|
||
|
||
// append engine.io protocol identifier
|
||
query.EIO = parser.protocol;
|
||
|
||
// transport name
|
||
query.transport = name;
|
||
|
||
// session id if we already have one
|
||
if (this.id) query.sid = this.id;
|
||
|
||
var transport = new transports[name]({
|
||
agent: this.agent,
|
||
hostname: this.hostname,
|
||
port: this.port,
|
||
secure: this.secure,
|
||
path: this.path,
|
||
query: query,
|
||
forceJSONP: this.forceJSONP,
|
||
jsonp: this.jsonp,
|
||
forceBase64: this.forceBase64,
|
||
enablesXDR: this.enablesXDR,
|
||
timestampRequests: this.timestampRequests,
|
||
timestampParam: this.timestampParam,
|
||
policyPort: this.policyPort,
|
||
socket: this,
|
||
pfx: this.pfx,
|
||
key: this.key,
|
||
passphrase: this.passphrase,
|
||
cert: this.cert,
|
||
ca: this.ca,
|
||
ciphers: this.ciphers,
|
||
rejectUnauthorized: this.rejectUnauthorized,
|
||
perMessageDeflate: this.perMessageDeflate,
|
||
extraHeaders: this.extraHeaders
|
||
});
|
||
|
||
return transport;
|
||
};
|
||
|
||
function clone (obj) {
|
||
var o = {};
|
||
for (var i in obj) {
|
||
if (obj.hasOwnProperty(i)) {
|
||
o[i] = obj[i];
|
||
}
|
||
}
|
||
return o;
|
||
}
|
||
|
||
/**
|
||
* Initializes transport to use and starts probe.
|
||
*
|
||
* @api private
|
||
*/
|
||
Socket.prototype.open = function () {
|
||
var transport;
|
||
if (this.rememberUpgrade && Socket.priorWebsocketSuccess && this.transports.indexOf('websocket') != -1) {
|
||
transport = 'websocket';
|
||
} else if (0 === this.transports.length) {
|
||
// Emit error on next tick so it can be listened to
|
||
var self = this;
|
||
setTimeout(function() {
|
||
self.emit('error', 'No transports available');
|
||
}, 0);
|
||
return;
|
||
} else {
|
||
transport = this.transports[0];
|
||
}
|
||
this.readyState = 'opening';
|
||
|
||
// Retry with the next transport if the transport is disabled (jsonp: false)
|
||
try {
|
||
transport = this.createTransport(transport);
|
||
} catch (e) {
|
||
this.transports.shift();
|
||
this.open();
|
||
return;
|
||
}
|
||
|
||
transport.open();
|
||
this.setTransport(transport);
|
||
};
|
||
|
||
/**
|
||
* Sets the current transport. Disables the existing one (if any).
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
Socket.prototype.setTransport = function(transport){
|
||
debug('setting transport %s', transport.name);
|
||
var self = this;
|
||
|
||
if (this.transport) {
|
||
debug('clearing existing transport %s', this.transport.name);
|
||
this.transport.removeAllListeners();
|
||
}
|
||
|
||
// set up transport
|
||
this.transport = transport;
|
||
|
||
// set up transport listeners
|
||
transport
|
||
.on('drain', function(){
|
||
self.onDrain();
|
||
})
|
||
.on('packet', function(packet){
|
||
self.onPacket(packet);
|
||
})
|
||
.on('error', function(e){
|
||
self.onError(e);
|
||
})
|
||
.on('close', function(){
|
||
self.onClose('transport close');
|
||
});
|
||
};
|
||
|
||
/**
|
||
* Probes a transport.
|
||
*
|
||
* @param {String} transport name
|
||
* @api private
|
||
*/
|
||
|
||
Socket.prototype.probe = function (name) {
|
||
debug('probing transport "%s"', name);
|
||
var transport = this.createTransport(name, { probe: 1 })
|
||
, failed = false
|
||
, self = this;
|
||
|
||
Socket.priorWebsocketSuccess = false;
|
||
|
||
function onTransportOpen(){
|
||
if (self.onlyBinaryUpgrades) {
|
||
var upgradeLosesBinary = !this.supportsBinary && self.transport.supportsBinary;
|
||
failed = failed || upgradeLosesBinary;
|
||
}
|
||
if (failed) return;
|
||
|
||
debug('probe transport "%s" opened', name);
|
||
transport.send([{ type: 'ping', data: 'probe' }]);
|
||
transport.once('packet', function (msg) {
|
||
if (failed) return;
|
||
if ('pong' == msg.type && 'probe' == msg.data) {
|
||
debug('probe transport "%s" pong', name);
|
||
self.upgrading = true;
|
||
self.emit('upgrading', transport);
|
||
if (!transport) return;
|
||
Socket.priorWebsocketSuccess = 'websocket' == transport.name;
|
||
|
||
debug('pausing current transport "%s"', self.transport.name);
|
||
self.transport.pause(function () {
|
||
if (failed) return;
|
||
if ('closed' == self.readyState) return;
|
||
debug('changing transport and sending upgrade packet');
|
||
|
||
cleanup();
|
||
|
||
self.setTransport(transport);
|
||
transport.send([{ type: 'upgrade' }]);
|
||
self.emit('upgrade', transport);
|
||
transport = null;
|
||
self.upgrading = false;
|
||
self.flush();
|
||
});
|
||
} else {
|
||
debug('probe transport "%s" failed', name);
|
||
var err = new Error('probe error');
|
||
err.transport = transport.name;
|
||
self.emit('upgradeError', err);
|
||
}
|
||
});
|
||
}
|
||
|
||
function freezeTransport() {
|
||
if (failed) return;
|
||
|
||
// Any callback called by transport should be ignored since now
|
||
failed = true;
|
||
|
||
cleanup();
|
||
|
||
transport.close();
|
||
transport = null;
|
||
}
|
||
|
||
//Handle any error that happens while probing
|
||
function onerror(err) {
|
||
var error = new Error('probe error: ' + err);
|
||
error.transport = transport.name;
|
||
|
||
freezeTransport();
|
||
|
||
debug('probe transport "%s" failed because of error: %s', name, err);
|
||
|
||
self.emit('upgradeError', error);
|
||
}
|
||
|
||
function onTransportClose(){
|
||
onerror("transport closed");
|
||
}
|
||
|
||
//When the socket is closed while we're probing
|
||
function onclose(){
|
||
onerror("socket closed");
|
||
}
|
||
|
||
//When the socket is upgraded while we're probing
|
||
function onupgrade(to){
|
||
if (transport && to.name != transport.name) {
|
||
debug('"%s" works - aborting "%s"', to.name, transport.name);
|
||
freezeTransport();
|
||
}
|
||
}
|
||
|
||
//Remove all listeners on the transport and on self
|
||
function cleanup(){
|
||
transport.removeListener('open', onTransportOpen);
|
||
transport.removeListener('error', onerror);
|
||
transport.removeListener('close', onTransportClose);
|
||
self.removeListener('close', onclose);
|
||
self.removeListener('upgrading', onupgrade);
|
||
}
|
||
|
||
transport.once('open', onTransportOpen);
|
||
transport.once('error', onerror);
|
||
transport.once('close', onTransportClose);
|
||
|
||
this.once('close', onclose);
|
||
this.once('upgrading', onupgrade);
|
||
|
||
transport.open();
|
||
|
||
};
|
||
|
||
/**
|
||
* Called when connection is deemed open.
|
||
*
|
||
* @api public
|
||
*/
|
||
|
||
Socket.prototype.onOpen = function () {
|
||
debug('socket open');
|
||
this.readyState = 'open';
|
||
Socket.priorWebsocketSuccess = 'websocket' == this.transport.name;
|
||
this.emit('open');
|
||
this.flush();
|
||
|
||
// we check for `readyState` in case an `open`
|
||
// listener already closed the socket
|
||
if ('open' == this.readyState && this.upgrade && this.transport.pause) {
|
||
debug('starting upgrade probes');
|
||
for (var i = 0, l = this.upgrades.length; i < l; i++) {
|
||
this.probe(this.upgrades[i]);
|
||
}
|
||
}
|
||
};
|
||
|
||
/**
|
||
* Handles a packet.
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
Socket.prototype.onPacket = function (packet) {
|
||
if ('opening' == this.readyState || 'open' == this.readyState) {
|
||
debug('socket receive: type "%s", data "%s"', packet.type, packet.data);
|
||
|
||
this.emit('packet', packet);
|
||
|
||
// Socket is live - any packet counts
|
||
this.emit('heartbeat');
|
||
|
||
switch (packet.type) {
|
||
case 'open':
|
||
this.onHandshake(parsejson(packet.data));
|
||
break;
|
||
|
||
case 'pong':
|
||
this.setPing();
|
||
this.emit('pong');
|
||
break;
|
||
|
||
case 'error':
|
||
var err = new Error('server error');
|
||
err.code = packet.data;
|
||
this.onError(err);
|
||
break;
|
||
|
||
case 'message':
|
||
this.emit('data', packet.data);
|
||
this.emit('message', packet.data);
|
||
break;
|
||
}
|
||
} else {
|
||
debug('packet received with socket readyState "%s"', this.readyState);
|
||
}
|
||
};
|
||
|
||
/**
|
||
* Called upon handshake completion.
|
||
*
|
||
* @param {Object} handshake obj
|
||
* @api private
|
||
*/
|
||
|
||
Socket.prototype.onHandshake = function (data) {
|
||
this.emit('handshake', data);
|
||
this.id = data.sid;
|
||
this.transport.query.sid = data.sid;
|
||
this.upgrades = this.filterUpgrades(data.upgrades);
|
||
this.pingInterval = data.pingInterval;
|
||
this.pingTimeout = data.pingTimeout;
|
||
this.onOpen();
|
||
// In case open handler closes socket
|
||
if ('closed' == this.readyState) return;
|
||
this.setPing();
|
||
|
||
// Prolong liveness of socket on heartbeat
|
||
this.removeListener('heartbeat', this.onHeartbeat);
|
||
this.on('heartbeat', this.onHeartbeat);
|
||
};
|
||
|
||
/**
|
||
* Resets ping timeout.
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
Socket.prototype.onHeartbeat = function (timeout) {
|
||
clearTimeout(this.pingTimeoutTimer);
|
||
var self = this;
|
||
self.pingTimeoutTimer = setTimeout(function () {
|
||
if ('closed' == self.readyState) return;
|
||
self.onClose('ping timeout');
|
||
}, timeout || (self.pingInterval + self.pingTimeout));
|
||
};
|
||
|
||
/**
|
||
* Pings server every `this.pingInterval` and expects response
|
||
* within `this.pingTimeout` or closes connection.
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
Socket.prototype.setPing = function () {
|
||
var self = this;
|
||
clearTimeout(self.pingIntervalTimer);
|
||
self.pingIntervalTimer = setTimeout(function () {
|
||
debug('writing ping packet - expecting pong within %sms', self.pingTimeout);
|
||
self.ping();
|
||
self.onHeartbeat(self.pingTimeout);
|
||
}, self.pingInterval);
|
||
};
|
||
|
||
/**
|
||
* Sends a ping packet.
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
Socket.prototype.ping = function () {
|
||
var self = this;
|
||
this.sendPacket('ping', function(){
|
||
self.emit('ping');
|
||
});
|
||
};
|
||
|
||
/**
|
||
* Called on `drain` event
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
Socket.prototype.onDrain = function() {
|
||
this.writeBuffer.splice(0, this.prevBufferLen);
|
||
|
||
// setting prevBufferLen = 0 is very important
|
||
// for example, when upgrading, upgrade packet is sent over,
|
||
// and a nonzero prevBufferLen could cause problems on `drain`
|
||
this.prevBufferLen = 0;
|
||
|
||
if (0 === this.writeBuffer.length) {
|
||
this.emit('drain');
|
||
} else {
|
||
this.flush();
|
||
}
|
||
};
|
||
|
||
/**
|
||
* Flush write buffers.
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
Socket.prototype.flush = function () {
|
||
if ('closed' != this.readyState && this.transport.writable &&
|
||
!this.upgrading && this.writeBuffer.length) {
|
||
debug('flushing %d packets in socket', this.writeBuffer.length);
|
||
this.transport.send(this.writeBuffer);
|
||
// keep track of current length of writeBuffer
|
||
// splice writeBuffer and callbackBuffer on `drain`
|
||
this.prevBufferLen = this.writeBuffer.length;
|
||
this.emit('flush');
|
||
}
|
||
};
|
||
|
||
/**
|
||
* Sends a message.
|
||
*
|
||
* @param {String} message.
|
||
* @param {Function} callback function.
|
||
* @param {Object} options.
|
||
* @return {Socket} for chaining.
|
||
* @api public
|
||
*/
|
||
|
||
Socket.prototype.write =
|
||
Socket.prototype.send = function (msg, options, fn) {
|
||
this.sendPacket('message', msg, options, fn);
|
||
return this;
|
||
};
|
||
|
||
/**
|
||
* Sends a packet.
|
||
*
|
||
* @param {String} packet type.
|
||
* @param {String} data.
|
||
* @param {Object} options.
|
||
* @param {Function} callback function.
|
||
* @api private
|
||
*/
|
||
|
||
Socket.prototype.sendPacket = function (type, data, options, fn) {
|
||
if('function' == typeof data) {
|
||
fn = data;
|
||
data = undefined;
|
||
}
|
||
|
||
if ('function' == typeof options) {
|
||
fn = options;
|
||
options = null;
|
||
}
|
||
|
||
if ('closing' == this.readyState || 'closed' == this.readyState) {
|
||
return;
|
||
}
|
||
|
||
options = options || {};
|
||
options.compress = false !== options.compress;
|
||
|
||
var packet = {
|
||
type: type,
|
||
data: data,
|
||
options: options
|
||
};
|
||
this.emit('packetCreate', packet);
|
||
this.writeBuffer.push(packet);
|
||
if (fn) this.once('flush', fn);
|
||
this.flush();
|
||
};
|
||
|
||
/**
|
||
* Closes the connection.
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
Socket.prototype.close = function () {
|
||
if ('opening' == this.readyState || 'open' == this.readyState) {
|
||
this.readyState = 'closing';
|
||
|
||
var self = this;
|
||
|
||
if (this.writeBuffer.length) {
|
||
this.once('drain', function() {
|
||
if (this.upgrading) {
|
||
waitForUpgrade();
|
||
} else {
|
||
close();
|
||
}
|
||
});
|
||
} else if (this.upgrading) {
|
||
waitForUpgrade();
|
||
} else {
|
||
close();
|
||
}
|
||
}
|
||
|
||
function close() {
|
||
self.onClose('forced close');
|
||
debug('socket closing - telling transport to close');
|
||
self.transport.close();
|
||
}
|
||
|
||
function cleanupAndClose() {
|
||
self.removeListener('upgrade', cleanupAndClose);
|
||
self.removeListener('upgradeError', cleanupAndClose);
|
||
close();
|
||
}
|
||
|
||
function waitForUpgrade() {
|
||
// wait for upgrade to finish since we can't send packets while pausing a transport
|
||
self.once('upgrade', cleanupAndClose);
|
||
self.once('upgradeError', cleanupAndClose);
|
||
}
|
||
|
||
return this;
|
||
};
|
||
|
||
/**
|
||
* Called upon transport error
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
Socket.prototype.onError = function (err) {
|
||
debug('socket error %j', err);
|
||
Socket.priorWebsocketSuccess = false;
|
||
this.emit('error', err);
|
||
this.onClose('transport error', err);
|
||
};
|
||
|
||
/**
|
||
* Called upon transport close.
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
Socket.prototype.onClose = function (reason, desc) {
|
||
if ('opening' == this.readyState || 'open' == this.readyState || 'closing' == this.readyState) {
|
||
debug('socket close with reason: "%s"', reason);
|
||
var self = this;
|
||
|
||
// clear timers
|
||
clearTimeout(this.pingIntervalTimer);
|
||
clearTimeout(this.pingTimeoutTimer);
|
||
|
||
// stop event from firing again for transport
|
||
this.transport.removeAllListeners('close');
|
||
|
||
// ensure transport won't stay open
|
||
this.transport.close();
|
||
|
||
// ignore further transport communication
|
||
this.transport.removeAllListeners();
|
||
|
||
// set ready state
|
||
this.readyState = 'closed';
|
||
|
||
// clear session id
|
||
this.id = null;
|
||
|
||
// emit close event
|
||
this.emit('close', reason, desc);
|
||
|
||
// clean buffers after, so users can still
|
||
// grab the buffers on `close` event
|
||
self.writeBuffer = [];
|
||
self.prevBufferLen = 0;
|
||
}
|
||
};
|
||
|
||
/**
|
||
* Filters upgrades, returning only those matching client transports.
|
||
*
|
||
* @param {Array} server upgrades
|
||
* @api private
|
||
*
|
||
*/
|
||
|
||
Socket.prototype.filterUpgrades = function (upgrades) {
|
||
var filteredUpgrades = [];
|
||
for (var i = 0, j = upgrades.length; i<j; i++) {
|
||
if (~index(this.transports, upgrades[i])) filteredUpgrades.push(upgrades[i]);
|
||
}
|
||
return filteredUpgrades;
|
||
};
|
||
|
||
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
|
||
|
||
/***/ },
|
||
/* 126 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
/* WEBPACK VAR INJECTION */(function(global) {
|
||
/**
|
||
* Module requirements.
|
||
*/
|
||
|
||
var Polling = __webpack_require__(58);
|
||
var inherit = __webpack_require__(12);
|
||
|
||
/**
|
||
* Module exports.
|
||
*/
|
||
|
||
module.exports = JSONPPolling;
|
||
|
||
/**
|
||
* Cached regular expressions.
|
||
*/
|
||
|
||
var rNewline = /\n/g;
|
||
var rEscapedNewline = /\\n/g;
|
||
|
||
/**
|
||
* Global JSONP callbacks.
|
||
*/
|
||
|
||
var callbacks;
|
||
|
||
/**
|
||
* Callbacks count.
|
||
*/
|
||
|
||
var index = 0;
|
||
|
||
/**
|
||
* Noop.
|
||
*/
|
||
|
||
function empty () { }
|
||
|
||
/**
|
||
* JSONP Polling constructor.
|
||
*
|
||
* @param {Object} opts.
|
||
* @api public
|
||
*/
|
||
|
||
function JSONPPolling (opts) {
|
||
Polling.call(this, opts);
|
||
|
||
this.query = this.query || {};
|
||
|
||
// define global callbacks array if not present
|
||
// we do this here (lazily) to avoid unneeded global pollution
|
||
if (!callbacks) {
|
||
// we need to consider multiple engines in the same page
|
||
if (!global.___eio) global.___eio = [];
|
||
callbacks = global.___eio;
|
||
}
|
||
|
||
// callback identifier
|
||
this.index = callbacks.length;
|
||
|
||
// add callback to jsonp global
|
||
var self = this;
|
||
callbacks.push(function (msg) {
|
||
self.onData(msg);
|
||
});
|
||
|
||
// append to query string
|
||
this.query.j = this.index;
|
||
|
||
// prevent spurious errors from being emitted when the window is unloaded
|
||
if (global.document && global.addEventListener) {
|
||
global.addEventListener('beforeunload', function () {
|
||
if (self.script) self.script.onerror = empty;
|
||
}, false);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Inherits from Polling.
|
||
*/
|
||
|
||
inherit(JSONPPolling, Polling);
|
||
|
||
/*
|
||
* JSONP only supports binary as base64 encoded strings
|
||
*/
|
||
|
||
JSONPPolling.prototype.supportsBinary = false;
|
||
|
||
/**
|
||
* Closes the socket.
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
JSONPPolling.prototype.doClose = function () {
|
||
if (this.script) {
|
||
this.script.parentNode.removeChild(this.script);
|
||
this.script = null;
|
||
}
|
||
|
||
if (this.form) {
|
||
this.form.parentNode.removeChild(this.form);
|
||
this.form = null;
|
||
this.iframe = null;
|
||
}
|
||
|
||
Polling.prototype.doClose.call(this);
|
||
};
|
||
|
||
/**
|
||
* Starts a poll cycle.
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
JSONPPolling.prototype.doPoll = function () {
|
||
var self = this;
|
||
var script = document.createElement('script');
|
||
|
||
if (this.script) {
|
||
this.script.parentNode.removeChild(this.script);
|
||
this.script = null;
|
||
}
|
||
|
||
script.async = true;
|
||
script.src = this.uri();
|
||
script.onerror = function(e){
|
||
self.onError('jsonp poll error',e);
|
||
};
|
||
|
||
var insertAt = document.getElementsByTagName('script')[0];
|
||
if (insertAt) {
|
||
insertAt.parentNode.insertBefore(script, insertAt);
|
||
}
|
||
else {
|
||
(document.head || document.body).appendChild(script);
|
||
}
|
||
this.script = script;
|
||
|
||
var isUAgecko = 'undefined' != typeof navigator && /gecko/i.test(navigator.userAgent);
|
||
|
||
if (isUAgecko) {
|
||
setTimeout(function () {
|
||
var iframe = document.createElement('iframe');
|
||
document.body.appendChild(iframe);
|
||
document.body.removeChild(iframe);
|
||
}, 100);
|
||
}
|
||
};
|
||
|
||
/**
|
||
* Writes with a hidden iframe.
|
||
*
|
||
* @param {String} data to send
|
||
* @param {Function} called upon flush.
|
||
* @api private
|
||
*/
|
||
|
||
JSONPPolling.prototype.doWrite = function (data, fn) {
|
||
var self = this;
|
||
|
||
if (!this.form) {
|
||
var form = document.createElement('form');
|
||
var area = document.createElement('textarea');
|
||
var id = this.iframeId = 'eio_iframe_' + this.index;
|
||
var iframe;
|
||
|
||
form.className = 'socketio';
|
||
form.style.position = 'absolute';
|
||
form.style.top = '-1000px';
|
||
form.style.left = '-1000px';
|
||
form.target = id;
|
||
form.method = 'POST';
|
||
form.setAttribute('accept-charset', 'utf-8');
|
||
area.name = 'd';
|
||
form.appendChild(area);
|
||
document.body.appendChild(form);
|
||
|
||
this.form = form;
|
||
this.area = area;
|
||
}
|
||
|
||
this.form.action = this.uri();
|
||
|
||
function complete () {
|
||
initIframe();
|
||
fn();
|
||
}
|
||
|
||
function initIframe () {
|
||
if (self.iframe) {
|
||
try {
|
||
self.form.removeChild(self.iframe);
|
||
} catch (e) {
|
||
self.onError('jsonp polling iframe removal error', e);
|
||
}
|
||
}
|
||
|
||
try {
|
||
// ie6 dynamic iframes with target="" support (thanks Chris Lambacher)
|
||
var html = '<iframe src="javascript:0" name="'+ self.iframeId +'">';
|
||
iframe = document.createElement(html);
|
||
} catch (e) {
|
||
iframe = document.createElement('iframe');
|
||
iframe.name = self.iframeId;
|
||
iframe.src = 'javascript:0';
|
||
}
|
||
|
||
iframe.id = self.iframeId;
|
||
|
||
self.form.appendChild(iframe);
|
||
self.iframe = iframe;
|
||
}
|
||
|
||
initIframe();
|
||
|
||
// escape \n to prevent it from being converted into \r\n by some UAs
|
||
// double escaping is required for escaped new lines because unescaping of new lines can be done safely on server-side
|
||
data = data.replace(rEscapedNewline, '\\\n');
|
||
this.area.value = data.replace(rNewline, '\\n');
|
||
|
||
try {
|
||
this.form.submit();
|
||
} catch(e) {}
|
||
|
||
if (this.iframe.attachEvent) {
|
||
this.iframe.onreadystatechange = function(){
|
||
if (self.iframe.readyState == 'complete') {
|
||
complete();
|
||
}
|
||
};
|
||
} else {
|
||
this.iframe.onload = complete;
|
||
}
|
||
};
|
||
|
||
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
|
||
|
||
/***/ },
|
||
/* 127 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
/* WEBPACK VAR INJECTION */(function(global) {/**
|
||
* Module requirements.
|
||
*/
|
||
|
||
var XMLHttpRequest = __webpack_require__(29);
|
||
var Polling = __webpack_require__(58);
|
||
var Emitter = __webpack_require__(30);
|
||
var inherit = __webpack_require__(12);
|
||
var debug = __webpack_require__(4)('engine.io-client:polling-xhr');
|
||
|
||
/**
|
||
* Module exports.
|
||
*/
|
||
|
||
module.exports = XHR;
|
||
module.exports.Request = Request;
|
||
|
||
/**
|
||
* Empty function
|
||
*/
|
||
|
||
function empty(){}
|
||
|
||
/**
|
||
* XHR Polling constructor.
|
||
*
|
||
* @param {Object} opts
|
||
* @api public
|
||
*/
|
||
|
||
function XHR(opts){
|
||
Polling.call(this, opts);
|
||
|
||
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;
|
||
}
|
||
|
||
this.xd = opts.hostname != global.location.hostname ||
|
||
port != opts.port;
|
||
this.xs = opts.secure != isSSL;
|
||
} else {
|
||
this.extraHeaders = opts.extraHeaders;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Inherits from Polling.
|
||
*/
|
||
|
||
inherit(XHR, Polling);
|
||
|
||
/**
|
||
* XHR supports binary
|
||
*/
|
||
|
||
XHR.prototype.supportsBinary = true;
|
||
|
||
/**
|
||
* Creates a request.
|
||
*
|
||
* @param {String} method
|
||
* @api private
|
||
*/
|
||
|
||
XHR.prototype.request = function(opts){
|
||
opts = opts || {};
|
||
opts.uri = this.uri();
|
||
opts.xd = this.xd;
|
||
opts.xs = this.xs;
|
||
opts.agent = this.agent || false;
|
||
opts.supportsBinary = this.supportsBinary;
|
||
opts.enablesXDR = this.enablesXDR;
|
||
|
||
// SSL options for Node.js client
|
||
opts.pfx = this.pfx;
|
||
opts.key = this.key;
|
||
opts.passphrase = this.passphrase;
|
||
opts.cert = this.cert;
|
||
opts.ca = this.ca;
|
||
opts.ciphers = this.ciphers;
|
||
opts.rejectUnauthorized = this.rejectUnauthorized;
|
||
|
||
// other options for Node.js client
|
||
opts.extraHeaders = this.extraHeaders;
|
||
|
||
return new Request(opts);
|
||
};
|
||
|
||
/**
|
||
* Sends data.
|
||
*
|
||
* @param {String} data to send.
|
||
* @param {Function} called upon flush.
|
||
* @api private
|
||
*/
|
||
|
||
XHR.prototype.doWrite = function(data, fn){
|
||
var isBinary = typeof data !== 'string' && data !== undefined;
|
||
var req = this.request({ method: 'POST', data: data, isBinary: isBinary });
|
||
var self = this;
|
||
req.on('success', fn);
|
||
req.on('error', function(err){
|
||
self.onError('xhr post error', err);
|
||
});
|
||
this.sendXhr = req;
|
||
};
|
||
|
||
/**
|
||
* Starts a poll cycle.
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
XHR.prototype.doPoll = function(){
|
||
debug('xhr poll');
|
||
var req = this.request();
|
||
var self = this;
|
||
req.on('data', function(data){
|
||
self.onData(data);
|
||
});
|
||
req.on('error', function(err){
|
||
self.onError('xhr poll error', err);
|
||
});
|
||
this.pollXhr = req;
|
||
};
|
||
|
||
/**
|
||
* Request constructor
|
||
*
|
||
* @param {Object} options
|
||
* @api public
|
||
*/
|
||
|
||
function Request(opts){
|
||
this.method = opts.method || 'GET';
|
||
this.uri = opts.uri;
|
||
this.xd = !!opts.xd;
|
||
this.xs = !!opts.xs;
|
||
this.async = false !== opts.async;
|
||
this.data = undefined != opts.data ? opts.data : null;
|
||
this.agent = opts.agent;
|
||
this.isBinary = opts.isBinary;
|
||
this.supportsBinary = opts.supportsBinary;
|
||
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;
|
||
|
||
this.create();
|
||
}
|
||
|
||
/**
|
||
* Mix in `Emitter`.
|
||
*/
|
||
|
||
Emitter(Request.prototype);
|
||
|
||
/**
|
||
* Creates the XHR object and sends the request.
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
Request.prototype.create = function(){
|
||
var opts = { agent: this.agent, xdomain: this.xd, xscheme: this.xs, enablesXDR: this.enablesXDR };
|
||
|
||
// SSL options for Node.js client
|
||
opts.pfx = this.pfx;
|
||
opts.key = this.key;
|
||
opts.passphrase = this.passphrase;
|
||
opts.cert = this.cert;
|
||
opts.ca = this.ca;
|
||
opts.ciphers = this.ciphers;
|
||
opts.rejectUnauthorized = this.rejectUnauthorized;
|
||
|
||
var xhr = this.xhr = new XMLHttpRequest(opts);
|
||
var self = this;
|
||
|
||
try {
|
||
debug('xhr open %s: %s', this.method, this.uri);
|
||
xhr.open(this.method, this.uri, this.async);
|
||
try {
|
||
if (this.extraHeaders) {
|
||
xhr.setDisableHeaderCheck(true);
|
||
for (var i in this.extraHeaders) {
|
||
if (this.extraHeaders.hasOwnProperty(i)) {
|
||
xhr.setRequestHeader(i, this.extraHeaders[i]);
|
||
}
|
||
}
|
||
}
|
||
} catch (e) {}
|
||
if (this.supportsBinary) {
|
||
// This has to be done after open because Firefox is stupid
|
||
// http://stackoverflow.com/questions/13216903/get-binary-data-with-xmlhttprequest-in-a-firefox-extension
|
||
xhr.responseType = 'arraybuffer';
|
||
}
|
||
|
||
if ('POST' == this.method) {
|
||
try {
|
||
if (this.isBinary) {
|
||
xhr.setRequestHeader('Content-type', 'application/octet-stream');
|
||
} else {
|
||
xhr.setRequestHeader('Content-type', 'text/plain;charset=UTF-8');
|
||
}
|
||
} catch (e) {}
|
||
}
|
||
|
||
// ie6 check
|
||
if ('withCredentials' in xhr) {
|
||
xhr.withCredentials = true;
|
||
}
|
||
|
||
if (this.hasXDR()) {
|
||
xhr.onload = function(){
|
||
self.onLoad();
|
||
};
|
||
xhr.onerror = function(){
|
||
self.onError(xhr.responseText);
|
||
};
|
||
} else {
|
||
xhr.onreadystatechange = function(){
|
||
if (4 != xhr.readyState) return;
|
||
if (200 == xhr.status || 1223 == xhr.status) {
|
||
self.onLoad();
|
||
} else {
|
||
// make sure the `error` event handler that's user-set
|
||
// does not throw in the same tick and gets caught here
|
||
setTimeout(function(){
|
||
self.onError(xhr.status);
|
||
}, 0);
|
||
}
|
||
};
|
||
}
|
||
|
||
debug('xhr data %s', this.data);
|
||
xhr.send(this.data);
|
||
} catch (e) {
|
||
// Need to defer since .create() is called directly fhrom the constructor
|
||
// and thus the 'error' event can only be only bound *after* this exception
|
||
// occurs. Therefore, also, we cannot throw here at all.
|
||
setTimeout(function() {
|
||
self.onError(e);
|
||
}, 0);
|
||
return;
|
||
}
|
||
|
||
if (global.document) {
|
||
this.index = Request.requestsCount++;
|
||
Request.requests[this.index] = this;
|
||
}
|
||
};
|
||
|
||
/**
|
||
* Called upon successful response.
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
Request.prototype.onSuccess = function(){
|
||
this.emit('success');
|
||
this.cleanup();
|
||
};
|
||
|
||
/**
|
||
* Called if we have data.
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
Request.prototype.onData = function(data){
|
||
this.emit('data', data);
|
||
this.onSuccess();
|
||
};
|
||
|
||
/**
|
||
* Called upon error.
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
Request.prototype.onError = function(err){
|
||
this.emit('error', err);
|
||
this.cleanup(true);
|
||
};
|
||
|
||
/**
|
||
* Cleans up house.
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
Request.prototype.cleanup = function(fromError){
|
||
if ('undefined' == typeof this.xhr || null === this.xhr) {
|
||
return;
|
||
}
|
||
// xmlhttprequest
|
||
if (this.hasXDR()) {
|
||
this.xhr.onload = this.xhr.onerror = empty;
|
||
} else {
|
||
this.xhr.onreadystatechange = empty;
|
||
}
|
||
|
||
if (fromError) {
|
||
try {
|
||
this.xhr.abort();
|
||
} catch(e) {}
|
||
}
|
||
|
||
if (global.document) {
|
||
delete Request.requests[this.index];
|
||
}
|
||
|
||
this.xhr = null;
|
||
};
|
||
|
||
/**
|
||
* Called upon load.
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
Request.prototype.onLoad = function(){
|
||
var data;
|
||
try {
|
||
var contentType;
|
||
try {
|
||
contentType = this.xhr.getResponseHeader('Content-Type').split(';')[0];
|
||
} catch (e) {}
|
||
if (contentType === 'application/octet-stream') {
|
||
data = this.xhr.response;
|
||
} else {
|
||
if (!this.supportsBinary) {
|
||
data = this.xhr.responseText;
|
||
} else {
|
||
try {
|
||
data = String.fromCharCode.apply(null, new Uint8Array(this.xhr.response));
|
||
} catch (e) {
|
||
var ui8Arr = new Uint8Array(this.xhr.response);
|
||
var dataArray = [];
|
||
for (var idx = 0, length = ui8Arr.length; idx < length; idx++) {
|
||
dataArray.push(ui8Arr[idx]);
|
||
}
|
||
|
||
data = String.fromCharCode.apply(null, dataArray);
|
||
}
|
||
}
|
||
}
|
||
} catch (e) {
|
||
this.onError(e);
|
||
}
|
||
if (null != data) {
|
||
this.onData(data);
|
||
}
|
||
};
|
||
|
||
/**
|
||
* Check if it has XDomainRequest.
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
Request.prototype.hasXDR = function(){
|
||
return 'undefined' !== typeof global.XDomainRequest && !this.xs && this.enablesXDR;
|
||
};
|
||
|
||
/**
|
||
* Aborts the request.
|
||
*
|
||
* @api public
|
||
*/
|
||
|
||
Request.prototype.abort = function(){
|
||
this.cleanup();
|
||
};
|
||
|
||
/**
|
||
* Aborts pending requests when unloading the window. This is needed to prevent
|
||
* memory leaks (e.g. when using IE) and to ensure that no spurious error is
|
||
* emitted.
|
||
*/
|
||
|
||
if (global.document) {
|
||
Request.requestsCount = 0;
|
||
Request.requests = {};
|
||
if (global.attachEvent) {
|
||
global.attachEvent('onunload', unloadHandler);
|
||
} else if (global.addEventListener) {
|
||
global.addEventListener('beforeunload', unloadHandler, false);
|
||
}
|
||
}
|
||
|
||
function unloadHandler() {
|
||
for (var i in Request.requests) {
|
||
if (Request.requests.hasOwnProperty(i)) {
|
||
Request.requests[i].abort();
|
||
}
|
||
}
|
||
}
|
||
|
||
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
|
||
|
||
/***/ },
|
||
/* 128 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
/* WEBPACK VAR INJECTION */(function(global) {/**
|
||
* Module dependencies.
|
||
*/
|
||
|
||
var Transport = __webpack_require__(28);
|
||
var parser = __webpack_require__(8);
|
||
var parseqs = __webpack_require__(33);
|
||
var inherit = __webpack_require__(12);
|
||
var yeast = __webpack_require__(69);
|
||
var debug = __webpack_require__(4)('engine.io-client:websocket');
|
||
var BrowserWebSocket = global.WebSocket || global.MozWebSocket;
|
||
|
||
/**
|
||
* Get either the `WebSocket` or `MozWebSocket` globals
|
||
* in the browser or try to resolve WebSocket-compatible
|
||
* interface exposed by `ws` for Node-like environment.
|
||
*/
|
||
|
||
var WebSocket = BrowserWebSocket;
|
||
if (!WebSocket && typeof window === 'undefined') {
|
||
try {
|
||
WebSocket = __webpack_require__(159);
|
||
} catch (e) { }
|
||
}
|
||
|
||
/**
|
||
* Module exports.
|
||
*/
|
||
|
||
module.exports = WS;
|
||
|
||
/**
|
||
* WebSocket transport constructor.
|
||
*
|
||
* @api {Object} connection options
|
||
* @api public
|
||
*/
|
||
|
||
function WS(opts){
|
||
var forceBase64 = (opts && opts.forceBase64);
|
||
if (forceBase64) {
|
||
this.supportsBinary = false;
|
||
}
|
||
this.perMessageDeflate = opts.perMessageDeflate;
|
||
Transport.call(this, opts);
|
||
}
|
||
|
||
/**
|
||
* Inherits from Transport.
|
||
*/
|
||
|
||
inherit(WS, Transport);
|
||
|
||
/**
|
||
* Transport name.
|
||
*
|
||
* @api public
|
||
*/
|
||
|
||
WS.prototype.name = 'websocket';
|
||
|
||
/*
|
||
* WebSockets support binary
|
||
*/
|
||
|
||
WS.prototype.supportsBinary = true;
|
||
|
||
/**
|
||
* Opens socket.
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
WS.prototype.doOpen = function(){
|
||
if (!this.check()) {
|
||
// let probe timeout
|
||
return;
|
||
}
|
||
|
||
var self = this;
|
||
var uri = this.uri();
|
||
var protocols = void(0);
|
||
var opts = {
|
||
agent: this.agent,
|
||
perMessageDeflate: this.perMessageDeflate
|
||
};
|
||
|
||
// SSL options for Node.js client
|
||
opts.pfx = this.pfx;
|
||
opts.key = this.key;
|
||
opts.passphrase = this.passphrase;
|
||
opts.cert = this.cert;
|
||
opts.ca = this.ca;
|
||
opts.ciphers = this.ciphers;
|
||
opts.rejectUnauthorized = this.rejectUnauthorized;
|
||
if (this.extraHeaders) {
|
||
opts.headers = this.extraHeaders;
|
||
}
|
||
|
||
this.ws = BrowserWebSocket ? new WebSocket(uri) : new WebSocket(uri, protocols, opts);
|
||
|
||
if (this.ws.binaryType === undefined) {
|
||
this.supportsBinary = false;
|
||
}
|
||
|
||
if (this.ws.supports && this.ws.supports.binary) {
|
||
this.supportsBinary = true;
|
||
this.ws.binaryType = 'buffer';
|
||
} else {
|
||
this.ws.binaryType = 'arraybuffer';
|
||
}
|
||
|
||
this.addEventListeners();
|
||
};
|
||
|
||
/**
|
||
* Adds event listeners to the socket
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
WS.prototype.addEventListeners = function(){
|
||
var self = this;
|
||
|
||
this.ws.onopen = function(){
|
||
self.onOpen();
|
||
};
|
||
this.ws.onclose = function(){
|
||
self.onClose();
|
||
};
|
||
this.ws.onmessage = function(ev){
|
||
self.onData(ev.data);
|
||
};
|
||
this.ws.onerror = function(e){
|
||
self.onError('websocket error', e);
|
||
};
|
||
};
|
||
|
||
/**
|
||
* Override `onData` to use a timer on iOS.
|
||
* See: https://gist.github.com/mloughran/2052006
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
if ('undefined' != typeof navigator
|
||
&& /iPad|iPhone|iPod/i.test(navigator.userAgent)) {
|
||
WS.prototype.onData = function(data){
|
||
var self = this;
|
||
setTimeout(function(){
|
||
Transport.prototype.onData.call(self, data);
|
||
}, 0);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Writes data to socket.
|
||
*
|
||
* @param {Array} array of packets.
|
||
* @api private
|
||
*/
|
||
|
||
WS.prototype.write = function(packets){
|
||
var self = this;
|
||
this.writable = false;
|
||
|
||
// encodePacket efficient as it uses WS framing
|
||
// no need for encodePayload
|
||
var total = packets.length;
|
||
for (var i = 0, l = total; i < l; i++) {
|
||
(function(packet) {
|
||
parser.encodePacket(packet, self.supportsBinary, function(data) {
|
||
if (!BrowserWebSocket) {
|
||
// always create a new object (GH-437)
|
||
var opts = {};
|
||
if (packet.options) {
|
||
opts.compress = packet.options.compress;
|
||
}
|
||
|
||
if (self.perMessageDeflate) {
|
||
var len = 'string' == typeof data ? global.Buffer.byteLength(data) : data.length;
|
||
if (len < self.perMessageDeflate.threshold) {
|
||
opts.compress = false;
|
||
}
|
||
}
|
||
}
|
||
|
||
//Sometimes the websocket has already been closed but the browser didn't
|
||
//have a chance of informing us about it yet, in that case send will
|
||
//throw an error
|
||
try {
|
||
if (BrowserWebSocket) {
|
||
// TypeError is thrown when passing the second argument on Safari
|
||
self.ws.send(data);
|
||
} else {
|
||
self.ws.send(data, opts);
|
||
}
|
||
} catch (e){
|
||
debug('websocket closed before onclose event');
|
||
}
|
||
|
||
--total || done();
|
||
});
|
||
})(packets[i]);
|
||
}
|
||
|
||
function done(){
|
||
self.emit('flush');
|
||
|
||
// fake drain
|
||
// defer to next tick to allow Socket to clear writeBuffer
|
||
setTimeout(function(){
|
||
self.writable = true;
|
||
self.emit('drain');
|
||
}, 0);
|
||
}
|
||
};
|
||
|
||
/**
|
||
* Called upon close
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
WS.prototype.onClose = function(){
|
||
Transport.prototype.onClose.call(this);
|
||
};
|
||
|
||
/**
|
||
* Closes socket.
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
WS.prototype.doClose = function(){
|
||
if (typeof this.ws !== 'undefined') {
|
||
this.ws.close();
|
||
}
|
||
};
|
||
|
||
/**
|
||
* Generates uri for connection.
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
WS.prototype.uri = function(){
|
||
var query = this.query || {};
|
||
var schema = this.secure ? 'wss' : 'ws';
|
||
var port = '';
|
||
|
||
// avoid port if default for schema
|
||
if (this.port && (('wss' == schema && this.port != 443)
|
||
|| ('ws' == schema && this.port != 80))) {
|
||
port = ':' + this.port;
|
||
}
|
||
|
||
// append timestamp to URI
|
||
if (this.timestampRequests) {
|
||
query[this.timestampParam] = yeast();
|
||
}
|
||
|
||
// communicate binary support capabilities
|
||
if (!this.supportsBinary) {
|
||
query.b64 = 1;
|
||
}
|
||
|
||
query = parseqs.encode(query);
|
||
|
||
// 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;
|
||
};
|
||
|
||
/**
|
||
* Feature detection for WebSocket.
|
||
*
|
||
* @return {Boolean} whether this transport is available.
|
||
* @api public
|
||
*/
|
||
|
||
WS.prototype.check = function(){
|
||
return !!WebSocket && !('__initialize' in WebSocket && this.name === WS.prototype.name);
|
||
};
|
||
|
||
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
|
||
|
||
/***/ },
|
||
/* 129 */
|
||
/***/ function(module, exports) {
|
||
|
||
|
||
/**
|
||
* Gets the keys for an object.
|
||
*
|
||
* @return {Array} keys
|
||
* @api private
|
||
*/
|
||
|
||
module.exports = Object.keys || function keys (obj){
|
||
var arr = [];
|
||
var has = Object.prototype.hasOwnProperty;
|
||
|
||
for (var i in obj) {
|
||
if (has.call(obj, i)) {
|
||
arr.push(i);
|
||
}
|
||
}
|
||
return arr;
|
||
};
|
||
|
||
|
||
/***/ },
|
||
/* 130 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
/* WEBPACK VAR INJECTION */(function(global) {
|
||
/*
|
||
* Module requirements.
|
||
*/
|
||
|
||
var isArray = __webpack_require__(131);
|
||
|
||
/**
|
||
* Module exports.
|
||
*/
|
||
|
||
module.exports = hasBinary;
|
||
|
||
/**
|
||
* Checks for binary data.
|
||
*
|
||
* Right now only Buffer and ArrayBuffer are supported..
|
||
*
|
||
* @param {Object} anything
|
||
* @api public
|
||
*/
|
||
|
||
function hasBinary(data) {
|
||
|
||
function _hasBinary(obj) {
|
||
if (!obj) return false;
|
||
|
||
if ( (global.Buffer && global.Buffer.isBuffer(obj)) ||
|
||
(global.ArrayBuffer && obj instanceof ArrayBuffer) ||
|
||
(global.Blob && obj instanceof Blob) ||
|
||
(global.File && obj instanceof File)
|
||
) {
|
||
return true;
|
||
}
|
||
|
||
if (isArray(obj)) {
|
||
for (var i = 0; i < obj.length; i++) {
|
||
if (_hasBinary(obj[i])) {
|
||
return true;
|
||
}
|
||
}
|
||
} else if (obj && 'object' == typeof obj) {
|
||
if (obj.toJSON) {
|
||
obj = obj.toJSON();
|
||
}
|
||
|
||
for (var key in obj) {
|
||
if (Object.prototype.hasOwnProperty.call(obj, key) && _hasBinary(obj[key])) {
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
return _hasBinary(data);
|
||
}
|
||
|
||
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
|
||
|
||
/***/ },
|
||
/* 131 */
|
||
/***/ function(module, exports) {
|
||
|
||
module.exports = Array.isArray || function (arr) {
|
||
return Object.prototype.toString.call(arr) == '[object Array]';
|
||
};
|
||
|
||
|
||
/***/ },
|
||
/* 132 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
/* WEBPACK VAR INJECTION */(function(global) {
|
||
/*
|
||
* Module requirements.
|
||
*/
|
||
|
||
var isArray = __webpack_require__(133);
|
||
|
||
/**
|
||
* Module exports.
|
||
*/
|
||
|
||
module.exports = hasBinary;
|
||
|
||
/**
|
||
* Checks for binary data.
|
||
*
|
||
* Right now only Buffer and ArrayBuffer are supported..
|
||
*
|
||
* @param {Object} anything
|
||
* @api public
|
||
*/
|
||
|
||
function hasBinary(data) {
|
||
|
||
function _hasBinary(obj) {
|
||
if (!obj) return false;
|
||
|
||
if ( (global.Buffer && global.Buffer.isBuffer && global.Buffer.isBuffer(obj)) ||
|
||
(global.ArrayBuffer && obj instanceof ArrayBuffer) ||
|
||
(global.Blob && obj instanceof Blob) ||
|
||
(global.File && obj instanceof File)
|
||
) {
|
||
return true;
|
||
}
|
||
|
||
if (isArray(obj)) {
|
||
for (var i = 0; i < obj.length; i++) {
|
||
if (_hasBinary(obj[i])) {
|
||
return true;
|
||
}
|
||
}
|
||
} else if (obj && 'object' == typeof obj) {
|
||
// see: https://github.com/Automattic/has-binary/pull/4
|
||
if (obj.toJSON && 'function' == typeof obj.toJSON) {
|
||
obj = obj.toJSON();
|
||
}
|
||
|
||
for (var key in obj) {
|
||
if (Object.prototype.hasOwnProperty.call(obj, key) && _hasBinary(obj[key])) {
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
return _hasBinary(data);
|
||
}
|
||
|
||
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
|
||
|
||
/***/ },
|
||
/* 133 */
|
||
/***/ function(module, exports) {
|
||
|
||
module.exports = Array.isArray || function (arr) {
|
||
return Object.prototype.toString.call(arr) == '[object Array]';
|
||
};
|
||
|
||
|
||
/***/ },
|
||
/* 134 */
|
||
/***/ function(module, exports) {
|
||
|
||
|
||
/**
|
||
* Module exports.
|
||
*
|
||
* Logic borrowed from Modernizr:
|
||
*
|
||
* - https://github.com/Modernizr/Modernizr/blob/master/feature-detects/cors.js
|
||
*/
|
||
|
||
try {
|
||
module.exports = typeof XMLHttpRequest !== 'undefined' &&
|
||
'withCredentials' in new XMLHttpRequest();
|
||
} catch (err) {
|
||
// if XMLHttp support is disabled in IE then it will throw
|
||
// when trying to create
|
||
module.exports = false;
|
||
}
|
||
|
||
|
||
/***/ },
|
||
/* 135 */
|
||
/***/ function(module, exports) {
|
||
|
||
exports.read = function (buffer, offset, isLE, mLen, nBytes) {
|
||
var e, m
|
||
var eLen = nBytes * 8 - mLen - 1
|
||
var eMax = (1 << eLen) - 1
|
||
var eBias = eMax >> 1
|
||
var nBits = -7
|
||
var i = isLE ? (nBytes - 1) : 0
|
||
var d = isLE ? -1 : 1
|
||
var s = buffer[offset + i]
|
||
|
||
i += d
|
||
|
||
e = s & ((1 << (-nBits)) - 1)
|
||
s >>= (-nBits)
|
||
nBits += eLen
|
||
for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}
|
||
|
||
m = e & ((1 << (-nBits)) - 1)
|
||
e >>= (-nBits)
|
||
nBits += mLen
|
||
for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}
|
||
|
||
if (e === 0) {
|
||
e = 1 - eBias
|
||
} else if (e === eMax) {
|
||
return m ? NaN : ((s ? -1 : 1) * Infinity)
|
||
} else {
|
||
m = m + Math.pow(2, mLen)
|
||
e = e - eBias
|
||
}
|
||
return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
|
||
}
|
||
|
||
exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
|
||
var e, m, c
|
||
var eLen = nBytes * 8 - mLen - 1
|
||
var eMax = (1 << eLen) - 1
|
||
var eBias = eMax >> 1
|
||
var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
|
||
var i = isLE ? 0 : (nBytes - 1)
|
||
var d = isLE ? 1 : -1
|
||
var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0
|
||
|
||
value = Math.abs(value)
|
||
|
||
if (isNaN(value) || value === Infinity) {
|
||
m = isNaN(value) ? 1 : 0
|
||
e = eMax
|
||
} else {
|
||
e = Math.floor(Math.log(value) / Math.LN2)
|
||
if (value * (c = Math.pow(2, -e)) < 1) {
|
||
e--
|
||
c *= 2
|
||
}
|
||
if (e + eBias >= 1) {
|
||
value += rt / c
|
||
} else {
|
||
value += rt * Math.pow(2, 1 - eBias)
|
||
}
|
||
if (value * c >= 2) {
|
||
e++
|
||
c /= 2
|
||
}
|
||
|
||
if (e + eBias >= eMax) {
|
||
m = 0
|
||
e = eMax
|
||
} else if (e + eBias >= 1) {
|
||
m = (value * c - 1) * Math.pow(2, mLen)
|
||
e = e + eBias
|
||
} else {
|
||
m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
|
||
e = 0
|
||
}
|
||
}
|
||
|
||
for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
|
||
|
||
e = (e << mLen) | m
|
||
eLen += mLen
|
||
for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
|
||
|
||
buffer[offset + i - d] |= s * 128
|
||
}
|
||
|
||
|
||
/***/ },
|
||
/* 136 */
|
||
/***/ function(module, exports) {
|
||
|
||
if (typeof Object.create === 'function') {
|
||
// implementation from standard node.js 'util' module
|
||
module.exports = function inherits(ctor, superCtor) {
|
||
ctor.super_ = superCtor
|
||
ctor.prototype = Object.create(superCtor.prototype, {
|
||
constructor: {
|
||
value: ctor,
|
||
enumerable: false,
|
||
writable: true,
|
||
configurable: true
|
||
}
|
||
});
|
||
};
|
||
} else {
|
||
// old school shim for old browsers
|
||
module.exports = function inherits(ctor, superCtor) {
|
||
ctor.super_ = superCtor
|
||
var TempCtor = function () {}
|
||
TempCtor.prototype = superCtor.prototype
|
||
ctor.prototype = new TempCtor()
|
||
ctor.prototype.constructor = ctor
|
||
}
|
||
}
|
||
|
||
|
||
/***/ },
|
||
/* 137 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
'use strict';
|
||
|
||
const Buffer = __webpack_require__(19).Buffer
|
||
|
||
class Entry {
|
||
constructor(payload, next) {
|
||
this.payload = payload || null;
|
||
this.hash = null;
|
||
this.next = next ? (next instanceof Array ? next : [next]) : [];
|
||
|
||
// Convert instances of Entry to its hash
|
||
this.next = this.next.map((f) => {
|
||
if(f instanceof Entry)
|
||
return f.hash;
|
||
return f;
|
||
})
|
||
}
|
||
|
||
get asJson() {
|
||
let res = { payload: this.payload }
|
||
let next = this.next.map((f) => {
|
||
if(f instanceof Entry)
|
||
return f.hash
|
||
return f;
|
||
});
|
||
Object.assign(res, { next: next });
|
||
return res;
|
||
}
|
||
|
||
hasChild(a) {
|
||
for(let i = 0; i < this.next.length; i++) {
|
||
if(this.next[i] === a.hash)
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
static create(ipfs, data, next) {
|
||
if(!ipfs) throw new Error("Entry requires ipfs instance")
|
||
const entry = new Entry(data, next);
|
||
return Entry.getIpfsHash(ipfs, entry)
|
||
.then((hash) => {
|
||
entry.hash = hash;
|
||
return entry;
|
||
});
|
||
}
|
||
|
||
static from(ipfs, data, nexts) {
|
||
if(!ipfs) throw new Error("Entry requires ipfs instance")
|
||
if(data instanceof Entry) return Promise.resolve(data);
|
||
const entry = new Entry(data, nexts);
|
||
return Entry.getIpfsHash(ipfs, entry)
|
||
.then((hash) => {
|
||
entry.hash = hash;
|
||
return entry;
|
||
});
|
||
}
|
||
|
||
static fromIpfsHash(ipfs, hash) {
|
||
if(!ipfs) throw new Error("Entry requires ipfs instance")
|
||
if(!hash) throw new Error("Invalid hash: " + hash)
|
||
const get = (hash) => {
|
||
return new Promise((resolve, reject) => {
|
||
ipfs.object.get(hash, { enc: 'base58' })
|
||
.then((obj) => {
|
||
if(obj.toJSON().Size === 0)
|
||
resolve(get(hash));
|
||
else
|
||
resolve(obj);
|
||
})
|
||
});
|
||
};
|
||
return get(hash).then((obj) => {
|
||
const f = JSON.parse(obj.toJSON().Data)
|
||
return Entry.create(ipfs, f.payload, f.next);
|
||
});
|
||
}
|
||
|
||
static getIpfsHash(ipfs, entry) {
|
||
if(!ipfs) throw new Error("Entry requires ipfs instance")
|
||
return ipfs.object.put(new Buffer(JSON.stringify(entry.asJson)))
|
||
.then((res) => res.toJSON().Hash);
|
||
}
|
||
|
||
static equals(a, b) {
|
||
return a.hash === b.hash;
|
||
}
|
||
}
|
||
|
||
module.exports = Entry;
|
||
|
||
|
||
/***/ },
|
||
/* 138 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
'use strict';
|
||
|
||
const _ = __webpack_require__(141);
|
||
const Lazy = __webpack_require__(31);
|
||
const Promise = __webpack_require__(82);
|
||
const Buffer = __webpack_require__(19).Buffer
|
||
const Entry = __webpack_require__(137);
|
||
|
||
const MaxBatchSize = 10; // How many items to keep per local batch
|
||
const MaxHistory = 256; // How many items to fetch on join
|
||
|
||
class Log {
|
||
constructor(ipfs, id, name, opts) {
|
||
this.id = id;
|
||
this.name = name;
|
||
this._ipfs = ipfs;
|
||
this._items = opts && opts.items ? opts.items : [];
|
||
|
||
this.options = { maxHistory: MaxHistory };
|
||
Object.assign(this.options, opts);
|
||
delete this.options.items;
|
||
|
||
this._currentBatch = [];
|
||
this._heads = [];
|
||
}
|
||
|
||
get items() {
|
||
return this._items.concat(this._currentBatch);
|
||
}
|
||
|
||
get snapshot() {
|
||
return {
|
||
id: this.id,
|
||
items: this._currentBatch.map((f) => f.hash)
|
||
}
|
||
}
|
||
|
||
add(data) {
|
||
if(this._currentBatch.length >= MaxBatchSize)
|
||
this._commit();
|
||
|
||
return Entry.from(this._ipfs, data, this._heads)
|
||
.then((entry) => {
|
||
this._heads = [entry.hash];
|
||
this._currentBatch.push(entry);
|
||
return entry;
|
||
});
|
||
}
|
||
|
||
join(other) {
|
||
if(!other.items) throw new Error("The log to join must be an instance of Log")
|
||
// let st = new Date().getTime();
|
||
const diff = _.differenceWith(other.items, this.items, Entry.equals);
|
||
const final = _.unionWith(this._currentBatch, diff, Entry.equals);
|
||
this._items = this._items.concat(final);
|
||
this._currentBatch = [];
|
||
|
||
const nexts = Lazy(diff)
|
||
.map((f) => f.next)
|
||
.flatten()
|
||
.take(this.options.maxHistory)
|
||
.toArray();
|
||
|
||
// Fetch history
|
||
return Promise.map(nexts, (f) => {
|
||
let all = this.items.map((a) => a.hash);
|
||
return this._fetchRecursive(this._ipfs, f, all, this.options.maxHistory - nexts.length, 0)
|
||
.then((history) => {
|
||
history.forEach((b) => this._insert(b));
|
||
return history;
|
||
});
|
||
}, { concurrency: 1 }).then((res) => {
|
||
this._heads = Log.findHeads(this);
|
||
// let et = new Date().getTime();
|
||
// console.log("Log.join took " + (et - st) + "ms");
|
||
return _.flatten(res).concat(diff)
|
||
})
|
||
}
|
||
|
||
clear() {
|
||
this._items = [];
|
||
this._currentBatch = [];
|
||
}
|
||
|
||
_insert(entry) {
|
||
let indices = Lazy(entry.next).map((next) => Lazy(this._items).map((f) => f.hash).indexOf(next)) // Find the item's parent's indices
|
||
const index = indices.toArray().length > 0 ? Math.max(indices.max() + 1, 0) : 0; // find the largest index (latest parent)
|
||
this._items.splice(index, 0, entry);
|
||
return entry;
|
||
}
|
||
|
||
_commit() {
|
||
this._items = this._items.concat(this._currentBatch);
|
||
this._currentBatch = [];
|
||
}
|
||
|
||
_fetchRecursive(ipfs, hash, all, amount, depth) {
|
||
const isReferenced = (list, item) => Lazy(list).reverse().find((f) => f === item) !== undefined;
|
||
let result = [];
|
||
|
||
// If the given hash is in the given log (all) or if we're at maximum depth, return
|
||
if(isReferenced(all, hash) || depth >= amount)
|
||
return Promise.resolve(result);
|
||
|
||
// Create the entry and add it to the result
|
||
return Entry.fromIpfsHash(ipfs, hash)
|
||
.then((entry) => {
|
||
result.push(entry);
|
||
all.push(hash);
|
||
depth ++;
|
||
|
||
return Promise.map(entry.next, (f) => this._fetchRecursive(ipfs, f, all, amount, depth), { concurrency: 1 })
|
||
.then((res) => _.flatten(res.concat(result)))
|
||
});
|
||
}
|
||
|
||
static getIpfsHash(ipfs, log) {
|
||
if(!ipfs) throw new Error("Ipfs instance not defined")
|
||
const data = new Buffer(JSON.stringify(log.snapshot));
|
||
return ipfs.object.put(data)
|
||
.then((res) => res.toJSON().Hash);
|
||
}
|
||
|
||
static fromIpfsHash(ipfs, hash, options) {
|
||
if(!ipfs) throw new Error("Ipfs instance not defined")
|
||
if(!hash) throw new Error("Invalid hash: " + hash)
|
||
if(!options) options = {};
|
||
return ipfs.object.get(hash, { enc: 'base58' })
|
||
.then((res) => Log.fromJson(ipfs, JSON.parse(res.toJSON().Data), options));
|
||
}
|
||
|
||
static fromJson(ipfs, json, options) {
|
||
if(!json.items) throw new Error("Not a Log instance")
|
||
if(!options) options = {};
|
||
return Promise.all(json.items.map((f) => Entry.fromIpfsHash(ipfs, f)))
|
||
.then((items) => {
|
||
Object.assign(options, { items: items });
|
||
return new Log(ipfs, json.id, '', options);
|
||
});
|
||
}
|
||
|
||
static findHeads(log) {
|
||
return Lazy(log.items)
|
||
.reverse()
|
||
.filter((f) => !Log.isReferencedInChain(log, f))
|
||
.map((f) => f.hash)
|
||
.toArray();
|
||
}
|
||
|
||
static isReferencedInChain(log, item) {
|
||
return Lazy(log.items).reverse().find((e) => e.hasChild(item)) !== undefined;
|
||
}
|
||
|
||
static get batchSize() {
|
||
return MaxBatchSize
|
||
}
|
||
}
|
||
|
||
module.exports = Log;
|
||
|
||
|
||
/***/ },
|
||
/* 139 */
|
||
/***/ function(module, exports) {
|
||
|
||
var toString = {}.toString;
|
||
|
||
module.exports = Array.isArray || function (arr) {
|
||
return toString.call(arr) == '[object Array]';
|
||
};
|
||
|
||
|
||
/***/ },
|
||
/* 140 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
/* WEBPACK VAR INJECTION */(function(module, global) {var __WEBPACK_AMD_DEFINE_RESULT__;/*! JSON v3.3.2 | http://bestiejs.github.io/json3 | Copyright 2012-2014, Kit Cambridge | http://kit.mit-license.org */
|
||
;(function () {
|
||
// Detect the `define` function exposed by asynchronous module loaders. The
|
||
// strict `define` check is necessary for compatibility with `r.js`.
|
||
var isLoader = "function" === "function" && __webpack_require__(158);
|
||
|
||
// A set of types used to distinguish objects from primitives.
|
||
var objectTypes = {
|
||
"function": true,
|
||
"object": true
|
||
};
|
||
|
||
// Detect the `exports` object exposed by CommonJS implementations.
|
||
var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
|
||
|
||
// Use the `global` object exposed by Node (including Browserify via
|
||
// `insert-module-globals`), Narwhal, and Ringo as the default context,
|
||
// and the `window` object in browsers. Rhino exports a `global` function
|
||
// instead.
|
||
var root = objectTypes[typeof window] && window || this,
|
||
freeGlobal = freeExports && objectTypes[typeof module] && module && !module.nodeType && typeof global == "object" && global;
|
||
|
||
if (freeGlobal && (freeGlobal["global"] === freeGlobal || freeGlobal["window"] === freeGlobal || freeGlobal["self"] === freeGlobal)) {
|
||
root = freeGlobal;
|
||
}
|
||
|
||
// Public: Initializes JSON 3 using the given `context` object, attaching the
|
||
// `stringify` and `parse` functions to the specified `exports` object.
|
||
function runInContext(context, exports) {
|
||
context || (context = root["Object"]());
|
||
exports || (exports = root["Object"]());
|
||
|
||
// Native constructor aliases.
|
||
var Number = context["Number"] || root["Number"],
|
||
String = context["String"] || root["String"],
|
||
Object = context["Object"] || root["Object"],
|
||
Date = context["Date"] || root["Date"],
|
||
SyntaxError = context["SyntaxError"] || root["SyntaxError"],
|
||
TypeError = context["TypeError"] || root["TypeError"],
|
||
Math = context["Math"] || root["Math"],
|
||
nativeJSON = context["JSON"] || root["JSON"];
|
||
|
||
// Delegate to the native `stringify` and `parse` implementations.
|
||
if (typeof nativeJSON == "object" && nativeJSON) {
|
||
exports.stringify = nativeJSON.stringify;
|
||
exports.parse = nativeJSON.parse;
|
||
}
|
||
|
||
// Convenience aliases.
|
||
var objectProto = Object.prototype,
|
||
getClass = objectProto.toString,
|
||
isProperty, forEach, undef;
|
||
|
||
// Test the `Date#getUTC*` methods. Based on work by @Yaffle.
|
||
var isExtended = new Date(-3509827334573292);
|
||
try {
|
||
// The `getUTCFullYear`, `Month`, and `Date` methods return nonsensical
|
||
// results for certain dates in Opera >= 10.53.
|
||
isExtended = isExtended.getUTCFullYear() == -109252 && isExtended.getUTCMonth() === 0 && isExtended.getUTCDate() === 1 &&
|
||
// Safari < 2.0.2 stores the internal millisecond time value correctly,
|
||
// but clips the values returned by the date methods to the range of
|
||
// signed 32-bit integers ([-2 ** 31, 2 ** 31 - 1]).
|
||
isExtended.getUTCHours() == 10 && isExtended.getUTCMinutes() == 37 && isExtended.getUTCSeconds() == 6 && isExtended.getUTCMilliseconds() == 708;
|
||
} catch (exception) {}
|
||
|
||
// Internal: Determines whether the native `JSON.stringify` and `parse`
|
||
// implementations are spec-compliant. Based on work by Ken Snyder.
|
||
function has(name) {
|
||
if (has[name] !== undef) {
|
||
// Return cached feature test result.
|
||
return has[name];
|
||
}
|
||
var isSupported;
|
||
if (name == "bug-string-char-index") {
|
||
// IE <= 7 doesn't support accessing string characters using square
|
||
// bracket notation. IE 8 only supports this for primitives.
|
||
isSupported = "a"[0] != "a";
|
||
} else if (name == "json") {
|
||
// Indicates whether both `JSON.stringify` and `JSON.parse` are
|
||
// supported.
|
||
isSupported = has("json-stringify") && has("json-parse");
|
||
} else {
|
||
var value, serialized = '{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}';
|
||
// Test `JSON.stringify`.
|
||
if (name == "json-stringify") {
|
||
var stringify = exports.stringify, stringifySupported = typeof stringify == "function" && isExtended;
|
||
if (stringifySupported) {
|
||
// A test function object with a custom `toJSON` method.
|
||
(value = function () {
|
||
return 1;
|
||
}).toJSON = value;
|
||
try {
|
||
stringifySupported =
|
||
// Firefox 3.1b1 and b2 serialize string, number, and boolean
|
||
// primitives as object literals.
|
||
stringify(0) === "0" &&
|
||
// FF 3.1b1, b2, and JSON 2 serialize wrapped primitives as object
|
||
// literals.
|
||
stringify(new Number()) === "0" &&
|
||
stringify(new String()) == '""' &&
|
||
// FF 3.1b1, 2 throw an error if the value is `null`, `undefined`, or
|
||
// does not define a canonical JSON representation (this applies to
|
||
// objects with `toJSON` properties as well, *unless* they are nested
|
||
// within an object or array).
|
||
stringify(getClass) === undef &&
|
||
// IE 8 serializes `undefined` as `"undefined"`. Safari <= 5.1.7 and
|
||
// FF 3.1b3 pass this test.
|
||
stringify(undef) === undef &&
|
||
// Safari <= 5.1.7 and FF 3.1b3 throw `Error`s and `TypeError`s,
|
||
// respectively, if the value is omitted entirely.
|
||
stringify() === undef &&
|
||
// FF 3.1b1, 2 throw an error if the given value is not a number,
|
||
// string, array, object, Boolean, or `null` literal. This applies to
|
||
// objects with custom `toJSON` methods as well, unless they are nested
|
||
// inside object or array literals. YUI 3.0.0b1 ignores custom `toJSON`
|
||
// methods entirely.
|
||
stringify(value) === "1" &&
|
||
stringify([value]) == "[1]" &&
|
||
// Prototype <= 1.6.1 serializes `[undefined]` as `"[]"` instead of
|
||
// `"[null]"`.
|
||
stringify([undef]) == "[null]" &&
|
||
// YUI 3.0.0b1 fails to serialize `null` literals.
|
||
stringify(null) == "null" &&
|
||
// FF 3.1b1, 2 halts serialization if an array contains a function:
|
||
// `[1, true, getClass, 1]` serializes as "[1,true,],". FF 3.1b3
|
||
// elides non-JSON values from objects and arrays, unless they
|
||
// define custom `toJSON` methods.
|
||
stringify([undef, getClass, null]) == "[null,null,null]" &&
|
||
// Simple serialization test. FF 3.1b1 uses Unicode escape sequences
|
||
// where character escape codes are expected (e.g., `\b` => `\u0008`).
|
||
stringify({ "a": [value, true, false, null, "\x00\b\n\f\r\t"] }) == serialized &&
|
||
// FF 3.1b1 and b2 ignore the `filter` and `width` arguments.
|
||
stringify(null, value) === "1" &&
|
||
stringify([1, 2], null, 1) == "[\n 1,\n 2\n]" &&
|
||
// JSON 2, Prototype <= 1.7, and older WebKit builds incorrectly
|
||
// serialize extended years.
|
||
stringify(new Date(-8.64e15)) == '"-271821-04-20T00:00:00.000Z"' &&
|
||
// The milliseconds are optional in ES 5, but required in 5.1.
|
||
stringify(new Date(8.64e15)) == '"+275760-09-13T00:00:00.000Z"' &&
|
||
// Firefox <= 11.0 incorrectly serializes years prior to 0 as negative
|
||
// four-digit years instead of six-digit years. Credits: @Yaffle.
|
||
stringify(new Date(-621987552e5)) == '"-000001-01-01T00:00:00.000Z"' &&
|
||
// Safari <= 5.1.5 and Opera >= 10.53 incorrectly serialize millisecond
|
||
// values less than 1000. Credits: @Yaffle.
|
||
stringify(new Date(-1)) == '"1969-12-31T23:59:59.999Z"';
|
||
} catch (exception) {
|
||
stringifySupported = false;
|
||
}
|
||
}
|
||
isSupported = stringifySupported;
|
||
}
|
||
// Test `JSON.parse`.
|
||
if (name == "json-parse") {
|
||
var parse = exports.parse;
|
||
if (typeof parse == "function") {
|
||
try {
|
||
// FF 3.1b1, b2 will throw an exception if a bare literal is provided.
|
||
// Conforming implementations should also coerce the initial argument to
|
||
// a string prior to parsing.
|
||
if (parse("0") === 0 && !parse(false)) {
|
||
// Simple parsing test.
|
||
value = parse(serialized);
|
||
var parseSupported = value["a"].length == 5 && value["a"][0] === 1;
|
||
if (parseSupported) {
|
||
try {
|
||
// Safari <= 5.1.2 and FF 3.1b1 allow unescaped tabs in strings.
|
||
parseSupported = !parse('"\t"');
|
||
} catch (exception) {}
|
||
if (parseSupported) {
|
||
try {
|
||
// FF 4.0 and 4.0.1 allow leading `+` signs and leading
|
||
// decimal points. FF 4.0, 4.0.1, and IE 9-10 also allow
|
||
// certain octal literals.
|
||
parseSupported = parse("01") !== 1;
|
||
} catch (exception) {}
|
||
}
|
||
if (parseSupported) {
|
||
try {
|
||
// FF 4.0, 4.0.1, and Rhino 1.7R3-R4 allow trailing decimal
|
||
// points. These environments, along with FF 3.1b1 and 2,
|
||
// also allow trailing commas in JSON objects and arrays.
|
||
parseSupported = parse("1.") !== 1;
|
||
} catch (exception) {}
|
||
}
|
||
}
|
||
}
|
||
} catch (exception) {
|
||
parseSupported = false;
|
||
}
|
||
}
|
||
isSupported = parseSupported;
|
||
}
|
||
}
|
||
return has[name] = !!isSupported;
|
||
}
|
||
|
||
if (!has("json")) {
|
||
// Common `[[Class]]` name aliases.
|
||
var functionClass = "[object Function]",
|
||
dateClass = "[object Date]",
|
||
numberClass = "[object Number]",
|
||
stringClass = "[object String]",
|
||
arrayClass = "[object Array]",
|
||
booleanClass = "[object Boolean]";
|
||
|
||
// Detect incomplete support for accessing string characters by index.
|
||
var charIndexBuggy = has("bug-string-char-index");
|
||
|
||
// Define additional utility methods if the `Date` methods are buggy.
|
||
if (!isExtended) {
|
||
var floor = Math.floor;
|
||
// A mapping between the months of the year and the number of days between
|
||
// January 1st and the first of the respective month.
|
||
var Months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
|
||
// Internal: Calculates the number of days between the Unix epoch and the
|
||
// first day of the given month.
|
||
var getDay = function (year, month) {
|
||
return Months[month] + 365 * (year - 1970) + floor((year - 1969 + (month = +(month > 1))) / 4) - floor((year - 1901 + month) / 100) + floor((year - 1601 + month) / 400);
|
||
};
|
||
}
|
||
|
||
// Internal: Determines if a property is a direct property of the given
|
||
// object. Delegates to the native `Object#hasOwnProperty` method.
|
||
if (!(isProperty = objectProto.hasOwnProperty)) {
|
||
isProperty = function (property) {
|
||
var members = {}, constructor;
|
||
if ((members.__proto__ = null, members.__proto__ = {
|
||
// The *proto* property cannot be set multiple times in recent
|
||
// versions of Firefox and SeaMonkey.
|
||
"toString": 1
|
||
}, members).toString != getClass) {
|
||
// Safari <= 2.0.3 doesn't implement `Object#hasOwnProperty`, but
|
||
// supports the mutable *proto* property.
|
||
isProperty = function (property) {
|
||
// Capture and break the object's prototype chain (see section 8.6.2
|
||
// of the ES 5.1 spec). The parenthesized expression prevents an
|
||
// unsafe transformation by the Closure Compiler.
|
||
var original = this.__proto__, result = property in (this.__proto__ = null, this);
|
||
// Restore the original prototype chain.
|
||
this.__proto__ = original;
|
||
return result;
|
||
};
|
||
} else {
|
||
// Capture a reference to the top-level `Object` constructor.
|
||
constructor = members.constructor;
|
||
// Use the `constructor` property to simulate `Object#hasOwnProperty` in
|
||
// other environments.
|
||
isProperty = function (property) {
|
||
var parent = (this.constructor || constructor).prototype;
|
||
return property in this && !(property in parent && this[property] === parent[property]);
|
||
};
|
||
}
|
||
members = null;
|
||
return isProperty.call(this, property);
|
||
};
|
||
}
|
||
|
||
// Internal: Normalizes the `for...in` iteration algorithm across
|
||
// environments. Each enumerated key is yielded to a `callback` function.
|
||
forEach = function (object, callback) {
|
||
var size = 0, Properties, members, property;
|
||
|
||
// Tests for bugs in the current environment's `for...in` algorithm. The
|
||
// `valueOf` property inherits the non-enumerable flag from
|
||
// `Object.prototype` in older versions of IE, Netscape, and Mozilla.
|
||
(Properties = function () {
|
||
this.valueOf = 0;
|
||
}).prototype.valueOf = 0;
|
||
|
||
// Iterate over a new instance of the `Properties` class.
|
||
members = new Properties();
|
||
for (property in members) {
|
||
// Ignore all properties inherited from `Object.prototype`.
|
||
if (isProperty.call(members, property)) {
|
||
size++;
|
||
}
|
||
}
|
||
Properties = members = null;
|
||
|
||
// Normalize the iteration algorithm.
|
||
if (!size) {
|
||
// A list of non-enumerable properties inherited from `Object.prototype`.
|
||
members = ["valueOf", "toString", "toLocaleString", "propertyIsEnumerable", "isPrototypeOf", "hasOwnProperty", "constructor"];
|
||
// IE <= 8, Mozilla 1.0, and Netscape 6.2 ignore shadowed non-enumerable
|
||
// properties.
|
||
forEach = function (object, callback) {
|
||
var isFunction = getClass.call(object) == functionClass, property, length;
|
||
var hasProperty = !isFunction && typeof object.constructor != "function" && objectTypes[typeof object.hasOwnProperty] && object.hasOwnProperty || isProperty;
|
||
for (property in object) {
|
||
// Gecko <= 1.0 enumerates the `prototype` property of functions under
|
||
// certain conditions; IE does not.
|
||
if (!(isFunction && property == "prototype") && hasProperty.call(object, property)) {
|
||
callback(property);
|
||
}
|
||
}
|
||
// Manually invoke the callback for each non-enumerable property.
|
||
for (length = members.length; property = members[--length]; hasProperty.call(object, property) && callback(property));
|
||
};
|
||
} else if (size == 2) {
|
||
// Safari <= 2.0.4 enumerates shadowed properties twice.
|
||
forEach = function (object, callback) {
|
||
// Create a set of iterated properties.
|
||
var members = {}, isFunction = getClass.call(object) == functionClass, property;
|
||
for (property in object) {
|
||
// Store each property name to prevent double enumeration. The
|
||
// `prototype` property of functions is not enumerated due to cross-
|
||
// environment inconsistencies.
|
||
if (!(isFunction && property == "prototype") && !isProperty.call(members, property) && (members[property] = 1) && isProperty.call(object, property)) {
|
||
callback(property);
|
||
}
|
||
}
|
||
};
|
||
} else {
|
||
// No bugs detected; use the standard `for...in` algorithm.
|
||
forEach = function (object, callback) {
|
||
var isFunction = getClass.call(object) == functionClass, property, isConstructor;
|
||
for (property in object) {
|
||
if (!(isFunction && property == "prototype") && isProperty.call(object, property) && !(isConstructor = property === "constructor")) {
|
||
callback(property);
|
||
}
|
||
}
|
||
// Manually invoke the callback for the `constructor` property due to
|
||
// cross-environment inconsistencies.
|
||
if (isConstructor || isProperty.call(object, (property = "constructor"))) {
|
||
callback(property);
|
||
}
|
||
};
|
||
}
|
||
return forEach(object, callback);
|
||
};
|
||
|
||
// Public: Serializes a JavaScript `value` as a JSON string. The optional
|
||
// `filter` argument may specify either a function that alters how object and
|
||
// array members are serialized, or an array of strings and numbers that
|
||
// indicates which properties should be serialized. The optional `width`
|
||
// argument may be either a string or number that specifies the indentation
|
||
// level of the output.
|
||
if (!has("json-stringify")) {
|
||
// Internal: A map of control characters and their escaped equivalents.
|
||
var Escapes = {
|
||
92: "\\\\",
|
||
34: '\\"',
|
||
8: "\\b",
|
||
12: "\\f",
|
||
10: "\\n",
|
||
13: "\\r",
|
||
9: "\\t"
|
||
};
|
||
|
||
// Internal: Converts `value` into a zero-padded string such that its
|
||
// length is at least equal to `width`. The `width` must be <= 6.
|
||
var leadingZeroes = "000000";
|
||
var toPaddedString = function (width, value) {
|
||
// The `|| 0` expression is necessary to work around a bug in
|
||
// Opera <= 7.54u2 where `0 == -0`, but `String(-0) !== "0"`.
|
||
return (leadingZeroes + (value || 0)).slice(-width);
|
||
};
|
||
|
||
// Internal: Double-quotes a string `value`, replacing all ASCII control
|
||
// characters (characters with code unit values between 0 and 31) with
|
||
// their escaped equivalents. This is an implementation of the
|
||
// `Quote(value)` operation defined in ES 5.1 section 15.12.3.
|
||
var unicodePrefix = "\\u00";
|
||
var quote = function (value) {
|
||
var result = '"', index = 0, length = value.length, useCharIndex = !charIndexBuggy || length > 10;
|
||
var symbols = useCharIndex && (charIndexBuggy ? value.split("") : value);
|
||
for (; index < length; index++) {
|
||
var charCode = value.charCodeAt(index);
|
||
// If the character is a control character, append its Unicode or
|
||
// shorthand escape sequence; otherwise, append the character as-is.
|
||
switch (charCode) {
|
||
case 8: case 9: case 10: case 12: case 13: case 34: case 92:
|
||
result += Escapes[charCode];
|
||
break;
|
||
default:
|
||
if (charCode < 32) {
|
||
result += unicodePrefix + toPaddedString(2, charCode.toString(16));
|
||
break;
|
||
}
|
||
result += useCharIndex ? symbols[index] : value.charAt(index);
|
||
}
|
||
}
|
||
return result + '"';
|
||
};
|
||
|
||
// Internal: Recursively serializes an object. Implements the
|
||
// `Str(key, holder)`, `JO(value)`, and `JA(value)` operations.
|
||
var serialize = function (property, object, callback, properties, whitespace, indentation, stack) {
|
||
var value, className, year, month, date, time, hours, minutes, seconds, milliseconds, results, element, index, length, prefix, result;
|
||
try {
|
||
// Necessary for host object support.
|
||
value = object[property];
|
||
} catch (exception) {}
|
||
if (typeof value == "object" && value) {
|
||
className = getClass.call(value);
|
||
if (className == dateClass && !isProperty.call(value, "toJSON")) {
|
||
if (value > -1 / 0 && value < 1 / 0) {
|
||
// Dates are serialized according to the `Date#toJSON` method
|
||
// specified in ES 5.1 section 15.9.5.44. See section 15.9.1.15
|
||
// for the ISO 8601 date time string format.
|
||
if (getDay) {
|
||
// Manually compute the year, month, date, hours, minutes,
|
||
// seconds, and milliseconds if the `getUTC*` methods are
|
||
// buggy. Adapted from @Yaffle's `date-shim` project.
|
||
date = floor(value / 864e5);
|
||
for (year = floor(date / 365.2425) + 1970 - 1; getDay(year + 1, 0) <= date; year++);
|
||
for (month = floor((date - getDay(year, 0)) / 30.42); getDay(year, month + 1) <= date; month++);
|
||
date = 1 + date - getDay(year, month);
|
||
// The `time` value specifies the time within the day (see ES
|
||
// 5.1 section 15.9.1.2). The formula `(A % B + B) % B` is used
|
||
// to compute `A modulo B`, as the `%` operator does not
|
||
// correspond to the `modulo` operation for negative numbers.
|
||
time = (value % 864e5 + 864e5) % 864e5;
|
||
// The hours, minutes, seconds, and milliseconds are obtained by
|
||
// decomposing the time within the day. See section 15.9.1.10.
|
||
hours = floor(time / 36e5) % 24;
|
||
minutes = floor(time / 6e4) % 60;
|
||
seconds = floor(time / 1e3) % 60;
|
||
milliseconds = time % 1e3;
|
||
} else {
|
||
year = value.getUTCFullYear();
|
||
month = value.getUTCMonth();
|
||
date = value.getUTCDate();
|
||
hours = value.getUTCHours();
|
||
minutes = value.getUTCMinutes();
|
||
seconds = value.getUTCSeconds();
|
||
milliseconds = value.getUTCMilliseconds();
|
||
}
|
||
// Serialize extended years correctly.
|
||
value = (year <= 0 || year >= 1e4 ? (year < 0 ? "-" : "+") + toPaddedString(6, year < 0 ? -year : year) : toPaddedString(4, year)) +
|
||
"-" + toPaddedString(2, month + 1) + "-" + toPaddedString(2, date) +
|
||
// Months, dates, hours, minutes, and seconds should have two
|
||
// digits; milliseconds should have three.
|
||
"T" + toPaddedString(2, hours) + ":" + toPaddedString(2, minutes) + ":" + toPaddedString(2, seconds) +
|
||
// Milliseconds are optional in ES 5.0, but required in 5.1.
|
||
"." + toPaddedString(3, milliseconds) + "Z";
|
||
} else {
|
||
value = null;
|
||
}
|
||
} else if (typeof value.toJSON == "function" && ((className != numberClass && className != stringClass && className != arrayClass) || isProperty.call(value, "toJSON"))) {
|
||
// Prototype <= 1.6.1 adds non-standard `toJSON` methods to the
|
||
// `Number`, `String`, `Date`, and `Array` prototypes. JSON 3
|
||
// ignores all `toJSON` methods on these objects unless they are
|
||
// defined directly on an instance.
|
||
value = value.toJSON(property);
|
||
}
|
||
}
|
||
if (callback) {
|
||
// If a replacement function was provided, call it to obtain the value
|
||
// for serialization.
|
||
value = callback.call(object, property, value);
|
||
}
|
||
if (value === null) {
|
||
return "null";
|
||
}
|
||
className = getClass.call(value);
|
||
if (className == booleanClass) {
|
||
// Booleans are represented literally.
|
||
return "" + value;
|
||
} else if (className == numberClass) {
|
||
// JSON numbers must be finite. `Infinity` and `NaN` are serialized as
|
||
// `"null"`.
|
||
return value > -1 / 0 && value < 1 / 0 ? "" + value : "null";
|
||
} else if (className == stringClass) {
|
||
// Strings are double-quoted and escaped.
|
||
return quote("" + value);
|
||
}
|
||
// Recursively serialize objects and arrays.
|
||
if (typeof value == "object") {
|
||
// Check for cyclic structures. This is a linear search; performance
|
||
// is inversely proportional to the number of unique nested objects.
|
||
for (length = stack.length; length--;) {
|
||
if (stack[length] === value) {
|
||
// Cyclic structures cannot be serialized by `JSON.stringify`.
|
||
throw TypeError();
|
||
}
|
||
}
|
||
// Add the object to the stack of traversed objects.
|
||
stack.push(value);
|
||
results = [];
|
||
// Save the current indentation level and indent one additional level.
|
||
prefix = indentation;
|
||
indentation += whitespace;
|
||
if (className == arrayClass) {
|
||
// Recursively serialize array elements.
|
||
for (index = 0, length = value.length; index < length; index++) {
|
||
element = serialize(index, value, callback, properties, whitespace, indentation, stack);
|
||
results.push(element === undef ? "null" : element);
|
||
}
|
||
result = results.length ? (whitespace ? "[\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "]" : ("[" + results.join(",") + "]")) : "[]";
|
||
} else {
|
||
// Recursively serialize object members. Members are selected from
|
||
// either a user-specified list of property names, or the object
|
||
// itself.
|
||
forEach(properties || value, function (property) {
|
||
var element = serialize(property, value, callback, properties, whitespace, indentation, stack);
|
||
if (element !== undef) {
|
||
// According to ES 5.1 section 15.12.3: "If `gap` {whitespace}
|
||
// is not the empty string, let `member` {quote(property) + ":"}
|
||
// be the concatenation of `member` and the `space` character."
|
||
// The "`space` character" refers to the literal space
|
||
// character, not the `space` {width} argument provided to
|
||
// `JSON.stringify`.
|
||
results.push(quote(property) + ":" + (whitespace ? " " : "") + element);
|
||
}
|
||
});
|
||
result = results.length ? (whitespace ? "{\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "}" : ("{" + results.join(",") + "}")) : "{}";
|
||
}
|
||
// Remove the object from the traversed object stack.
|
||
stack.pop();
|
||
return result;
|
||
}
|
||
};
|
||
|
||
// Public: `JSON.stringify`. See ES 5.1 section 15.12.3.
|
||
exports.stringify = function (source, filter, width) {
|
||
var whitespace, callback, properties, className;
|
||
if (objectTypes[typeof filter] && filter) {
|
||
if ((className = getClass.call(filter)) == functionClass) {
|
||
callback = filter;
|
||
} else if (className == arrayClass) {
|
||
// Convert the property names array into a makeshift set.
|
||
properties = {};
|
||
for (var index = 0, length = filter.length, value; index < length; value = filter[index++], ((className = getClass.call(value)), className == stringClass || className == numberClass) && (properties[value] = 1));
|
||
}
|
||
}
|
||
if (width) {
|
||
if ((className = getClass.call(width)) == numberClass) {
|
||
// Convert the `width` to an integer and create a string containing
|
||
// `width` number of space characters.
|
||
if ((width -= width % 1) > 0) {
|
||
for (whitespace = "", width > 10 && (width = 10); whitespace.length < width; whitespace += " ");
|
||
}
|
||
} else if (className == stringClass) {
|
||
whitespace = width.length <= 10 ? width : width.slice(0, 10);
|
||
}
|
||
}
|
||
// Opera <= 7.54u2 discards the values associated with empty string keys
|
||
// (`""`) only if they are used directly within an object member list
|
||
// (e.g., `!("" in { "": 1})`).
|
||
return serialize("", (value = {}, value[""] = source, value), callback, properties, whitespace, "", []);
|
||
};
|
||
}
|
||
|
||
// Public: Parses a JSON source string.
|
||
if (!has("json-parse")) {
|
||
var fromCharCode = String.fromCharCode;
|
||
|
||
// Internal: A map of escaped control characters and their unescaped
|
||
// equivalents.
|
||
var Unescapes = {
|
||
92: "\\",
|
||
34: '"',
|
||
47: "/",
|
||
98: "\b",
|
||
116: "\t",
|
||
110: "\n",
|
||
102: "\f",
|
||
114: "\r"
|
||
};
|
||
|
||
// Internal: Stores the parser state.
|
||
var Index, Source;
|
||
|
||
// Internal: Resets the parser state and throws a `SyntaxError`.
|
||
var abort = function () {
|
||
Index = Source = null;
|
||
throw SyntaxError();
|
||
};
|
||
|
||
// Internal: Returns the next token, or `"$"` if the parser has reached
|
||
// the end of the source string. A token may be a string, number, `null`
|
||
// literal, or Boolean literal.
|
||
var lex = function () {
|
||
var source = Source, length = source.length, value, begin, position, isSigned, charCode;
|
||
while (Index < length) {
|
||
charCode = source.charCodeAt(Index);
|
||
switch (charCode) {
|
||
case 9: case 10: case 13: case 32:
|
||
// Skip whitespace tokens, including tabs, carriage returns, line
|
||
// feeds, and space characters.
|
||
Index++;
|
||
break;
|
||
case 123: case 125: case 91: case 93: case 58: case 44:
|
||
// Parse a punctuator token (`{`, `}`, `[`, `]`, `:`, or `,`) at
|
||
// the current position.
|
||
value = charIndexBuggy ? source.charAt(Index) : source[Index];
|
||
Index++;
|
||
return value;
|
||
case 34:
|
||
// `"` delimits a JSON string; advance to the next character and
|
||
// begin parsing the string. String tokens are prefixed with the
|
||
// sentinel `@` character to distinguish them from punctuators and
|
||
// end-of-string tokens.
|
||
for (value = "@", Index++; Index < length;) {
|
||
charCode = source.charCodeAt(Index);
|
||
if (charCode < 32) {
|
||
// Unescaped ASCII control characters (those with a code unit
|
||
// less than the space character) are not permitted.
|
||
abort();
|
||
} else if (charCode == 92) {
|
||
// A reverse solidus (`\`) marks the beginning of an escaped
|
||
// control character (including `"`, `\`, and `/`) or Unicode
|
||
// escape sequence.
|
||
charCode = source.charCodeAt(++Index);
|
||
switch (charCode) {
|
||
case 92: case 34: case 47: case 98: case 116: case 110: case 102: case 114:
|
||
// Revive escaped control characters.
|
||
value += Unescapes[charCode];
|
||
Index++;
|
||
break;
|
||
case 117:
|
||
// `\u` marks the beginning of a Unicode escape sequence.
|
||
// Advance to the first character and validate the
|
||
// four-digit code point.
|
||
begin = ++Index;
|
||
for (position = Index + 4; Index < position; Index++) {
|
||
charCode = source.charCodeAt(Index);
|
||
// A valid sequence comprises four hexdigits (case-
|
||
// insensitive) that form a single hexadecimal value.
|
||
if (!(charCode >= 48 && charCode <= 57 || charCode >= 97 && charCode <= 102 || charCode >= 65 && charCode <= 70)) {
|
||
// Invalid Unicode escape sequence.
|
||
abort();
|
||
}
|
||
}
|
||
// Revive the escaped character.
|
||
value += fromCharCode("0x" + source.slice(begin, Index));
|
||
break;
|
||
default:
|
||
// Invalid escape sequence.
|
||
abort();
|
||
}
|
||
} else {
|
||
if (charCode == 34) {
|
||
// An unescaped double-quote character marks the end of the
|
||
// string.
|
||
break;
|
||
}
|
||
charCode = source.charCodeAt(Index);
|
||
begin = Index;
|
||
// Optimize for the common case where a string is valid.
|
||
while (charCode >= 32 && charCode != 92 && charCode != 34) {
|
||
charCode = source.charCodeAt(++Index);
|
||
}
|
||
// Append the string as-is.
|
||
value += source.slice(begin, Index);
|
||
}
|
||
}
|
||
if (source.charCodeAt(Index) == 34) {
|
||
// Advance to the next character and return the revived string.
|
||
Index++;
|
||
return value;
|
||
}
|
||
// Unterminated string.
|
||
abort();
|
||
default:
|
||
// Parse numbers and literals.
|
||
begin = Index;
|
||
// Advance past the negative sign, if one is specified.
|
||
if (charCode == 45) {
|
||
isSigned = true;
|
||
charCode = source.charCodeAt(++Index);
|
||
}
|
||
// Parse an integer or floating-point value.
|
||
if (charCode >= 48 && charCode <= 57) {
|
||
// Leading zeroes are interpreted as octal literals.
|
||
if (charCode == 48 && ((charCode = source.charCodeAt(Index + 1)), charCode >= 48 && charCode <= 57)) {
|
||
// Illegal octal literal.
|
||
abort();
|
||
}
|
||
isSigned = false;
|
||
// Parse the integer component.
|
||
for (; Index < length && ((charCode = source.charCodeAt(Index)), charCode >= 48 && charCode <= 57); Index++);
|
||
// Floats cannot contain a leading decimal point; however, this
|
||
// case is already accounted for by the parser.
|
||
if (source.charCodeAt(Index) == 46) {
|
||
position = ++Index;
|
||
// Parse the decimal component.
|
||
for (; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++);
|
||
if (position == Index) {
|
||
// Illegal trailing decimal.
|
||
abort();
|
||
}
|
||
Index = position;
|
||
}
|
||
// Parse exponents. The `e` denoting the exponent is
|
||
// case-insensitive.
|
||
charCode = source.charCodeAt(Index);
|
||
if (charCode == 101 || charCode == 69) {
|
||
charCode = source.charCodeAt(++Index);
|
||
// Skip past the sign following the exponent, if one is
|
||
// specified.
|
||
if (charCode == 43 || charCode == 45) {
|
||
Index++;
|
||
}
|
||
// Parse the exponential component.
|
||
for (position = Index; position < length && ((charCode = source.charCodeAt(position)), charCode >= 48 && charCode <= 57); position++);
|
||
if (position == Index) {
|
||
// Illegal empty exponent.
|
||
abort();
|
||
}
|
||
Index = position;
|
||
}
|
||
// Coerce the parsed value to a JavaScript number.
|
||
return +source.slice(begin, Index);
|
||
}
|
||
// A negative sign may only precede numbers.
|
||
if (isSigned) {
|
||
abort();
|
||
}
|
||
// `true`, `false`, and `null` literals.
|
||
if (source.slice(Index, Index + 4) == "true") {
|
||
Index += 4;
|
||
return true;
|
||
} else if (source.slice(Index, Index + 5) == "false") {
|
||
Index += 5;
|
||
return false;
|
||
} else if (source.slice(Index, Index + 4) == "null") {
|
||
Index += 4;
|
||
return null;
|
||
}
|
||
// Unrecognized token.
|
||
abort();
|
||
}
|
||
}
|
||
// Return the sentinel `$` character if the parser has reached the end
|
||
// of the source string.
|
||
return "$";
|
||
};
|
||
|
||
// Internal: Parses a JSON `value` token.
|
||
var get = function (value) {
|
||
var results, hasMembers;
|
||
if (value == "$") {
|
||
// Unexpected end of input.
|
||
abort();
|
||
}
|
||
if (typeof value == "string") {
|
||
if ((charIndexBuggy ? value.charAt(0) : value[0]) == "@") {
|
||
// Remove the sentinel `@` character.
|
||
return value.slice(1);
|
||
}
|
||
// Parse object and array literals.
|
||
if (value == "[") {
|
||
// Parses a JSON array, returning a new JavaScript array.
|
||
results = [];
|
||
for (;; hasMembers || (hasMembers = true)) {
|
||
value = lex();
|
||
// A closing square bracket marks the end of the array literal.
|
||
if (value == "]") {
|
||
break;
|
||
}
|
||
// If the array literal contains elements, the current token
|
||
// should be a comma separating the previous element from the
|
||
// next.
|
||
if (hasMembers) {
|
||
if (value == ",") {
|
||
value = lex();
|
||
if (value == "]") {
|
||
// Unexpected trailing `,` in array literal.
|
||
abort();
|
||
}
|
||
} else {
|
||
// A `,` must separate each array element.
|
||
abort();
|
||
}
|
||
}
|
||
// Elisions and leading commas are not permitted.
|
||
if (value == ",") {
|
||
abort();
|
||
}
|
||
results.push(get(value));
|
||
}
|
||
return results;
|
||
} else if (value == "{") {
|
||
// Parses a JSON object, returning a new JavaScript object.
|
||
results = {};
|
||
for (;; hasMembers || (hasMembers = true)) {
|
||
value = lex();
|
||
// A closing curly brace marks the end of the object literal.
|
||
if (value == "}") {
|
||
break;
|
||
}
|
||
// If the object literal contains members, the current token
|
||
// should be a comma separator.
|
||
if (hasMembers) {
|
||
if (value == ",") {
|
||
value = lex();
|
||
if (value == "}") {
|
||
// Unexpected trailing `,` in object literal.
|
||
abort();
|
||
}
|
||
} else {
|
||
// A `,` must separate each object member.
|
||
abort();
|
||
}
|
||
}
|
||
// Leading commas are not permitted, object property names must be
|
||
// double-quoted strings, and a `:` must separate each property
|
||
// name and value.
|
||
if (value == "," || typeof value != "string" || (charIndexBuggy ? value.charAt(0) : value[0]) != "@" || lex() != ":") {
|
||
abort();
|
||
}
|
||
results[value.slice(1)] = get(lex());
|
||
}
|
||
return results;
|
||
}
|
||
// Unexpected token encountered.
|
||
abort();
|
||
}
|
||
return value;
|
||
};
|
||
|
||
// Internal: Updates a traversed object member.
|
||
var update = function (source, property, callback) {
|
||
var element = walk(source, property, callback);
|
||
if (element === undef) {
|
||
delete source[property];
|
||
} else {
|
||
source[property] = element;
|
||
}
|
||
};
|
||
|
||
// Internal: Recursively traverses a parsed JSON object, invoking the
|
||
// `callback` function for each value. This is an implementation of the
|
||
// `Walk(holder, name)` operation defined in ES 5.1 section 15.12.2.
|
||
var walk = function (source, property, callback) {
|
||
var value = source[property], length;
|
||
if (typeof value == "object" && value) {
|
||
// `forEach` can't be used to traverse an array in Opera <= 8.54
|
||
// because its `Object#hasOwnProperty` implementation returns `false`
|
||
// for array indices (e.g., `![1, 2, 3].hasOwnProperty("0")`).
|
||
if (getClass.call(value) == arrayClass) {
|
||
for (length = value.length; length--;) {
|
||
update(value, length, callback);
|
||
}
|
||
} else {
|
||
forEach(value, function (property) {
|
||
update(value, property, callback);
|
||
});
|
||
}
|
||
}
|
||
return callback.call(source, property, value);
|
||
};
|
||
|
||
// Public: `JSON.parse`. See ES 5.1 section 15.12.2.
|
||
exports.parse = function (source, callback) {
|
||
var result, value;
|
||
Index = 0;
|
||
Source = "" + source;
|
||
result = get(lex());
|
||
// If a JSON string contains multiple tokens, it is invalid.
|
||
if (lex() != "$") {
|
||
abort();
|
||
}
|
||
// Reset the parser state.
|
||
Index = Source = null;
|
||
return callback && getClass.call(callback) == functionClass ? walk((value = {}, value[""] = result, value), "", callback) : result;
|
||
};
|
||
}
|
||
}
|
||
|
||
exports["runInContext"] = runInContext;
|
||
return exports;
|
||
}
|
||
|
||
if (freeExports && !isLoader) {
|
||
// Export for CommonJS environments.
|
||
runInContext(root, freeExports);
|
||
} else {
|
||
// Export for web browsers and JavaScript engines.
|
||
var nativeJSON = root.JSON,
|
||
previousJSON = root["JSON3"],
|
||
isRestored = false;
|
||
|
||
var JSON3 = runInContext(root, (root["JSON3"] = {
|
||
// Public: Restores the original value of the global `JSON` object and
|
||
// returns a reference to the `JSON3` object.
|
||
"noConflict": function () {
|
||
if (!isRestored) {
|
||
isRestored = true;
|
||
root.JSON = nativeJSON;
|
||
root["JSON3"] = previousJSON;
|
||
nativeJSON = previousJSON = null;
|
||
}
|
||
return JSON3;
|
||
}
|
||
}));
|
||
|
||
root.JSON = {
|
||
"parse": JSON3.parse,
|
||
"stringify": JSON3.stringify
|
||
};
|
||
}
|
||
|
||
// Export for asynchronous module loaders.
|
||
if (isLoader) {
|
||
!(__WEBPACK_AMD_DEFINE_RESULT__ = function () {
|
||
return JSON3;
|
||
}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
||
}
|
||
}).call(this);
|
||
|
||
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(35)(module), __webpack_require__(0)))
|
||
|
||
/***/ },
|
||
/* 141 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
/* WEBPACK VAR INJECTION */(function(global, module) {var __WEBPACK_AMD_DEFINE_RESULT__;/**
|
||
* @license
|
||
* lodash <https://lodash.com/>
|
||
* Copyright jQuery Foundation and other contributors <https://jquery.org/>
|
||
* Released under MIT license <https://lodash.com/license>
|
||
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
|
||
* 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.14.1';
|
||
|
||
/** 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 function 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;
|
||
|
||
/** Used to associate wrap methods with their bit flags. */
|
||
var wrapFlags = [
|
||
['ary', ARY_FLAG],
|
||
['bind', BIND_FLAG],
|
||
['bindKey', BIND_KEY_FLAG],
|
||
['curry', CURRY_FLAG],
|
||
['curryRight', CURRY_RIGHT_FLAG],
|
||
['flip', FLIP_FLAG],
|
||
['partial', PARTIAL_FLAG],
|
||
['partialRight', PARTIAL_RIGHT_FLAG],
|
||
['rearg', REARG_FLAG]
|
||
];
|
||
|
||
/** `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*$/,
|
||
reLeadingDot = /^\./,
|
||
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 wrap detail comments. */
|
||
var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,
|
||
reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/,
|
||
reSplitDetails = /,? & /;
|
||
|
||
/** 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 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 `global` from Node.js. */
|
||
var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
|
||
|
||
/** Detect free variable `self`. */
|
||
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
|
||
|
||
/** Used as a reference to the global object. */
|
||
var root = freeGlobal || freeSelf || Function('return this')();
|
||
|
||
/** Detect free variable `exports`. */
|
||
var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;
|
||
|
||
/** Detect free variable `module`. */
|
||
var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;
|
||
|
||
/** Detect the popular CommonJS extension `module.exports`. */
|
||
var moduleExports = freeModule && freeModule.exports === freeExports;
|
||
|
||
/** Detect free variable `process` from Node.js. */
|
||
var freeProcess = moduleExports && freeGlobal.process;
|
||
|
||
/** Used to access faster Node.js helpers. */
|
||
var nodeUtil = (function() {
|
||
try {
|
||
return freeProcess && freeProcess.binding('util');
|
||
} catch (e) {}
|
||
}());
|
||
|
||
/* Node.js helper references. */
|
||
var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer,
|
||
nodeIsDate = nodeUtil && nodeUtil.isDate,
|
||
nodeIsMap = nodeUtil && nodeUtil.isMap,
|
||
nodeIsRegExp = nodeUtil && nodeUtil.isRegExp,
|
||
nodeIsSet = nodeUtil && nodeUtil.isSet,
|
||
nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
|
||
|
||
/*--------------------------------------------------------------------------*/
|
||
|
||
/**
|
||
* 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's not chainable 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) {
|
||
// Don't return `set.add` because it's not chainable in IE 11.
|
||
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) {
|
||
switch (args.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 ? array.length : 0;
|
||
|
||
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 ? array.length : 0;
|
||
|
||
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 ? array.length : 0;
|
||
|
||
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 ? array.length : 0;
|
||
|
||
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 ? array.length : 0,
|
||
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) {
|
||
var length = array ? array.length : 0;
|
||
return !!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 ? array.length : 0;
|
||
|
||
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 ? array.length : 0,
|
||
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 ? array.length : 0;
|
||
|
||
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 ? array.length : 0;
|
||
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 ? array.length : 0;
|
||
|
||
while (++index < length) {
|
||
if (predicate(array[index], index, array)) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of methods like `_.findKey` and `_.findLastKey`,
|
||
* 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`.
|
||
* @returns {*} Returns the found element or its key, else `undefined`.
|
||
*/
|
||
function baseFindKey(collection, predicate, eachFunc) {
|
||
var result;
|
||
eachFunc(collection, function(value, key, collection) {
|
||
if (predicate(value, key, collection)) {
|
||
result = key;
|
||
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 {number} fromIndex The index to search from.
|
||
* @param {boolean} [fromRight] Specify iterating from right to left.
|
||
* @returns {number} Returns the index of the matched value, else `-1`.
|
||
*/
|
||
function baseFindIndex(array, predicate, fromIndex, fromRight) {
|
||
var length = array.length,
|
||
index = fromIndex + (fromRight ? 1 : -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 baseFindIndex(array, baseIsNaN, 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 `_.isNaN` without support for number objects.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
|
||
*/
|
||
function baseIsNaN(value) {
|
||
return value !== value;
|
||
}
|
||
|
||
/**
|
||
* 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 `_.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];
|
||
};
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.propertyOf` without support for deep paths.
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to query.
|
||
* @returns {Function} Returns the new accessor function.
|
||
*/
|
||
function basePropertyOf(object) {
|
||
return function(key) {
|
||
return object == null ? undefined : object[key];
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 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 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;
|
||
}
|
||
|
||
/**
|
||
* 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.
|
||
*/
|
||
var deburrLetter = basePropertyOf(deburredLetters);
|
||
|
||
/**
|
||
* Used by `_.escape` to convert characters to HTML entities.
|
||
*
|
||
* @private
|
||
* @param {string} chr The matched character to escape.
|
||
* @returns {string} Returns the escaped character.
|
||
*/
|
||
var escapeHtmlChar = basePropertyOf(htmlEscapes);
|
||
|
||
/**
|
||
* 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 value at `key` of `object`.
|
||
*
|
||
* @private
|
||
* @param {Object} [object] The object to query.
|
||
* @param {string} key The key of the property to get.
|
||
* @returns {*} Returns the property value.
|
||
*/
|
||
function getValue(object, key) {
|
||
return object == null ? undefined : object[key];
|
||
}
|
||
|
||
/**
|
||
* 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;
|
||
}
|
||
|
||
/**
|
||
* Creates a function that invokes `func` with its first argument transformed.
|
||
*
|
||
* @private
|
||
* @param {Function} func The function to wrap.
|
||
* @param {Function} transform The argument transform.
|
||
* @returns {Function} Returns the new function.
|
||
*/
|
||
function overArg(func, transform) {
|
||
return function(arg) {
|
||
return func(transform(arg));
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 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.
|
||
*/
|
||
var unescapeHtmlChar = basePropertyOf(htmlUnescapes);
|
||
|
||
/*--------------------------------------------------------------------------*/
|
||
|
||
/**
|
||
* 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 stub `Date#getTime` use in `_.now`.
|
||
* var stubbed = _.runInContext({
|
||
* 'Date': function() {
|
||
* return { 'getTime': stubGetTime };
|
||
* }
|
||
* });
|
||
*
|
||
* // 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 Array = context.Array,
|
||
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 detect overreaching core-js shims. */
|
||
var coreJsData = context['__core-js_shared__'];
|
||
|
||
/** Used to detect methods masquerading as native. */
|
||
var maskSrcKey = (function() {
|
||
var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
|
||
return uid ? ('Symbol(src)_1.' + uid) : '';
|
||
}());
|
||
|
||
/** 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,
|
||
enumerate = Reflect ? Reflect.enumerate : undefined,
|
||
iteratorSymbol = Symbol ? Symbol.iterator : undefined,
|
||
objectCreate = context.Object.create,
|
||
propertyIsEnumerable = objectProto.propertyIsEnumerable,
|
||
splice = arrayProto.splice,
|
||
spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined;
|
||
|
||
/** Built-in method references that are mockable. */
|
||
var clearTimeout = function(id) { return context.clearTimeout.call(root, id); },
|
||
setTimeout = function(func, wait) { return context.setTimeout.call(root, func, wait); };
|
||
|
||
/* Built-in method references for those with the same name as other `lodash` methods. */
|
||
var nativeCeil = Math.ceil,
|
||
nativeFloor = Math.floor,
|
||
nativeGetPrototype = Object.getPrototypeOf,
|
||
nativeGetSymbols = Object.getOwnPropertySymbols,
|
||
nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined,
|
||
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(context.Object, 'create');
|
||
|
||
/* Used to set `toString` methods. */
|
||
var defineProperty = (function() {
|
||
var func = getNative(context.Object, 'defineProperty'),
|
||
name = getNative.name;
|
||
|
||
return (name && name.length > 2) ? func : undefined;
|
||
}());
|
||
|
||
/** 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`, `conformsTo`, `deburr`,
|
||
* `defaultTo`, `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`, `stubArray`, `stubFalse`,
|
||
* `stubObject`, `stubString`, `stubTrue`, `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) {
|
||
var pairs = cache.__data__;
|
||
if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
|
||
pairs.push([key, value]);
|
||
return this;
|
||
}
|
||
cache = this.__data__ = new MapCache(pairs);
|
||
}
|
||
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.
|
||
*
|
||
* @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);
|
||
}
|
||
arrayEach(props || value, function(subValue, key) {
|
||
if (props) {
|
||
key = subValue;
|
||
subValue = value[key];
|
||
}
|
||
// Recursively populate clone (susceptible to call stack limits).
|
||
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);
|
||
return function(object) {
|
||
return baseConformsTo(object, source, props);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.conformsTo` which accepts `props` to check.
|
||
*
|
||
* @private
|
||
* @param {Object} object The object to inspect.
|
||
* @param {Object} source The object of property predicates to conform to.
|
||
* @returns {boolean} Returns `true` if `object` conforms, else `false`.
|
||
*/
|
||
function baseConformsTo(object, source, props) {
|
||
var length = props.length;
|
||
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 `args`
|
||
* to provide to `func`.
|
||
*
|
||
* @private
|
||
* @param {Function} func The function to delay.
|
||
* @param {number} wait The number of milliseconds to delay invocation.
|
||
* @param {Array} 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 `getTag`.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to query.
|
||
* @returns {string} Returns the `toStringTag`.
|
||
*/
|
||
function baseGetTag(value) {
|
||
return objectToString.call(value);
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.gt` which doesn't coerce arguments.
|
||
*
|
||
* @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 object != null &&
|
||
(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 object != null && key in Object(object);
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.inRange` which doesn't coerce arguments.
|
||
*
|
||
* @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 `_.isArrayBuffer` without Node.js optimizations.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.
|
||
*/
|
||
function baseIsArrayBuffer(value) {
|
||
return isObjectLike(value) && objectToString.call(value) == arrayBufferTag;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.isDate` without Node.js optimizations.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is a date object, else `false`.
|
||
*/
|
||
function baseIsDate(value) {
|
||
return isObjectLike(value) && objectToString.call(value) == dateTag;
|
||
}
|
||
|
||
/**
|
||
* 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 `_.isMap` without Node.js optimizations.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is a map, else `false`.
|
||
*/
|
||
function baseIsMap(value) {
|
||
return isObjectLike(value) && getTag(value) == mapTag;
|
||
}
|
||
|
||
/**
|
||
* 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 `_.isNative` without bad shim checks.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is a native function,
|
||
* else `false`.
|
||
*/
|
||
function baseIsNative(value) {
|
||
if (!isObject(value) || isMasked(value)) {
|
||
return false;
|
||
}
|
||
var pattern = (isFunction(value) || isHostObject(value)) ? reIsNative : reIsHostCtor;
|
||
return pattern.test(toSource(value));
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.isRegExp` without Node.js optimizations.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
|
||
*/
|
||
function baseIsRegExp(value) {
|
||
return isObject(value) && objectToString.call(value) == regexpTag;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.isSet` without Node.js optimizations.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is a set, else `false`.
|
||
*/
|
||
function baseIsSet(value) {
|
||
return isObjectLike(value) && getTag(value) == setTag;
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.isTypedArray` without Node.js optimizations.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
|
||
*/
|
||
function baseIsTypedArray(value) {
|
||
return isObjectLike(value) &&
|
||
isLength(value.length) && !!typedArrayTags[objectToString.call(value)];
|
||
}
|
||
|
||
/**
|
||
* 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.
|
||
*/
|
||
var baseKeys = overArg(nativeKeys, 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.
|
||
*
|
||
* @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;
|
||
}
|
||
}
|
||
if (isCommon) {
|
||
// Recursively merge objects and arrays (susceptible to call stack limits).
|
||
stack.set(srcValue, newValue);
|
||
mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
|
||
stack['delete'](srcValue);
|
||
}
|
||
assignMergeValue(object, key, newValue);
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.nth` which doesn't coerce arguments.
|
||
*
|
||
* @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 basePickBy(object, props, function(value, key) {
|
||
return key in object;
|
||
});
|
||
}
|
||
|
||
/**
|
||
* The base implementation of `_.pickBy` without support for iteratee shorthands.
|
||
*
|
||
* @private
|
||
* @param {Object} object The source object.
|
||
* @param {string[]} props The property identifiers to pick from.
|
||
* @param {Function} predicate The function invoked per property.
|
||
* @returns {Object} Returns the new object.
|
||
*/
|
||
function basePickBy(object, props, predicate) {
|
||
var index = -1,
|
||
length = props.length,
|
||
result = {};
|
||
|
||
while (++index < length) {
|
||
var key = props[index],
|
||
value = object[key];
|
||
|
||
if (predicate(value, key)) {
|
||
result[key] = value;
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* 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 (array === values) {
|
||
values = copyArray(values);
|
||
}
|
||
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.
|
||
*
|
||
* @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 `_.rest` which doesn't validate or coerce arguments.
|
||
*
|
||
* @private
|
||
* @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.
|
||
*/
|
||
function baseRest(func, start) {
|
||
start = nativeMax(start === undefined ? (func.length - 1) : 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];
|
||
}
|
||
index = -1;
|
||
var otherArgs = Array(start + 1);
|
||
while (++index < start) {
|
||
otherArgs[index] = args[index];
|
||
}
|
||
otherArgs[start] = array;
|
||
return apply(func, this, otherArgs);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 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)
|
||
: undefined;
|
||
|
||
assignValue(object, key, newValue === undefined ? source[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, 2), 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 baseRest(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 flags. See `createWrap` for more details.
|
||
* @param {*} [thisArg] The `this` binding of `func`.
|
||
* @returns {Function} Returns the new wrapped function.
|
||
*/
|
||
function createBind(func, bitmask, thisArg) {
|
||
var isBind = bitmask & BIND_FLAG,
|
||
Ctor = createCtor(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 createCtor(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 flags. See `createWrap` for more details.
|
||
* @param {number} arity The arity of `func`.
|
||
* @returns {Function} Returns the new wrapped function.
|
||
*/
|
||
function createCurry(func, bitmask, arity) {
|
||
var Ctor = createCtor(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 createRecurry(
|
||
func, bitmask, createHybrid, 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 `_.find` or `_.findLast` function.
|
||
*
|
||
* @private
|
||
* @param {Function} findIndexFunc The function to find the collection index.
|
||
* @returns {Function} Returns the new find function.
|
||
*/
|
||
function createFind(findIndexFunc) {
|
||
return function(collection, predicate, fromIndex) {
|
||
var iterable = Object(collection);
|
||
if (!isArrayLike(collection)) {
|
||
var iteratee = getIteratee(predicate, 3);
|
||
collection = keys(collection);
|
||
predicate = function(key) { return iteratee(iterable[key], key, iterable); };
|
||
}
|
||
var index = findIndexFunc(collection, predicate, fromIndex);
|
||
return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined;
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 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 baseRest(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 flags. See `createWrap` 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 createHybrid(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 : createCtor(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 createRecurry(
|
||
func, bitmask, createHybrid, 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 || createCtor(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.
|
||
* @param {number} [defaultValue] The value used for `undefined` arguments.
|
||
* @returns {Function} Returns the new mathematical operation function.
|
||
*/
|
||
function createMathOperation(operator, defaultValue) {
|
||
return function(value, other) {
|
||
var result;
|
||
if (value === undefined && other === undefined) {
|
||
return defaultValue;
|
||
}
|
||
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 baseRest(function(iteratees) {
|
||
iteratees = (iteratees.length == 1 && isArray(iteratees[0]))
|
||
? arrayMap(iteratees[0], baseUnary(getIteratee()))
|
||
: arrayMap(baseFlatten(iteratees, 1), baseUnary(getIteratee()));
|
||
|
||
return baseRest(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 flags. See `createWrap` 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 createPartial(func, bitmask, thisArg, partials) {
|
||
var isBind = bitmask & BIND_FLAG,
|
||
Ctor = createCtor(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 = toFinite(start);
|
||
if (end === undefined) {
|
||
end = start;
|
||
start = 0;
|
||
} else {
|
||
end = toFinite(end);
|
||
}
|
||
step = step === undefined ? (start < end ? 1 : -1) : toFinite(step);
|
||
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 flags. See `createWrap` 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 createRecurry(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 setWrapToString(result, func, bitmask);
|
||
}
|
||
|
||
/**
|
||
* 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 = nativeMin(toInteger(precision), 292);
|
||
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 object 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 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 createWrap(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 = createBind(func, bitmask, thisArg);
|
||
} else if (bitmask == CURRY_FLAG || bitmask == CURRY_RIGHT_FLAG) {
|
||
result = createCurry(func, bitmask, arity);
|
||
} else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !holders.length) {
|
||
result = createPartial(func, bitmask, thisArg, partials);
|
||
} else {
|
||
result = createHybrid.apply(undefined, newData);
|
||
}
|
||
var setter = data ? baseSetData : setData;
|
||
return setWrapToString(setter(result, newData), func, bitmask);
|
||
}
|
||
|
||
/**
|
||
* 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 && stack.get(other)) {
|
||
return stacked == other;
|
||
}
|
||
var index = -1,
|
||
result = true,
|
||
seen = (bitmask & UNORDERED_COMPARE_FLAG) ? new SetCache : undefined;
|
||
|
||
stack.set(array, other);
|
||
stack.set(other, array);
|
||
|
||
// 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);
|
||
stack['delete'](other);
|
||
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:
|
||
case numberTag:
|
||
// Coerce booleans to `1` or `0` and dates to milliseconds.
|
||
// Invalid dates are coerced to `NaN`.
|
||
return eq(+object, +other);
|
||
|
||
case errorTag:
|
||
return object.name == other.name && object.message == other.message;
|
||
|
||
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;
|
||
|
||
// Recursively compare objects (susceptible to call stack limits).
|
||
stack.set(object, other);
|
||
var result = equalArrays(convert(object), convert(other), equalFunc, customizer, bitmask, stack);
|
||
stack['delete'](object);
|
||
return result;
|
||
|
||
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 && stack.get(other)) {
|
||
return stacked == other;
|
||
}
|
||
var result = true;
|
||
stack.set(object, other);
|
||
stack.set(other, object);
|
||
|
||
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);
|
||
stack['delete'](other);
|
||
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 = keys(object),
|
||
length = result.length;
|
||
|
||
while (length--) {
|
||
var key = result[length],
|
||
value = object[key];
|
||
|
||
result[length] = [key, value, isStrictComparable(value)];
|
||
}
|
||
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 = getValue(object, key);
|
||
return baseIsNative(value) ? value : undefined;
|
||
}
|
||
|
||
/**
|
||
* Gets the `[[Prototype]]` of `value`.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to query.
|
||
* @returns {null|Object} Returns the `[[Prototype]]`.
|
||
*/
|
||
var getPrototype = overArg(nativeGetPrototype, Object);
|
||
|
||
/**
|
||
* 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.
|
||
*/
|
||
var getSymbols = nativeGetSymbols ? overArg(nativeGetSymbols, Object) : stubArray;
|
||
|
||
/**
|
||
* 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 = !nativeGetSymbols ? stubArray : 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`.
|
||
*/
|
||
var getTag = baseGetTag;
|
||
|
||
// 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 };
|
||
}
|
||
|
||
/**
|
||
* Extracts wrapper details from the `source` body comment.
|
||
*
|
||
* @private
|
||
* @param {string} source The source to inspect.
|
||
* @returns {Array} Returns the wrapper details.
|
||
*/
|
||
function getWrapDetails(source) {
|
||
var match = source.match(reWrapDetails);
|
||
return match ? match[1].split(reSplitDetails) : [];
|
||
}
|
||
|
||
/**
|
||
* 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;
|
||
}
|
||
|
||
/**
|
||
* Inserts wrapper `details` in a comment at the top of the `source` body.
|
||
*
|
||
* @private
|
||
* @param {string} source The source to modify.
|
||
* @returns {Array} details The details to insert.
|
||
* @returns {string} Returns the modified source.
|
||
*/
|
||
function insertWrapDetails(source, details) {
|
||
var length = details.length,
|
||
lastIndex = length - 1;
|
||
|
||
details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex];
|
||
details = details.join(length > 2 ? ', ' : ' ');
|
||
return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n');
|
||
}
|
||
|
||
/**
|
||
* 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) ||
|
||
!!(spreadableSymbol && value && value[spreadableSymbol]);
|
||
}
|
||
|
||
/**
|
||
* 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 `func` has its source masked.
|
||
*
|
||
* @private
|
||
* @param {Function} func The function to check.
|
||
* @returns {boolean} Returns `true` if `func` is masked, else `false`.
|
||
*/
|
||
function isMasked(func) {
|
||
return !!maskSrcKey && (maskSrcKey in func);
|
||
}
|
||
|
||
/**
|
||
* Checks if `func` is capable of being masked.
|
||
*
|
||
* @private
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `func` is maskable, else `false`.
|
||
*/
|
||
var isMaskable = coreJsData ? isFunction : stubFalse;
|
||
|
||
/**
|
||
* 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)) {
|
||
// Recursively merge objects and arrays (susceptible to call stack limits).
|
||
stack.set(srcValue, objValue);
|
||
baseMerge(objValue, srcValue, undefined, mergeDefaults, stack);
|
||
stack['delete'](srcValue);
|
||
}
|
||
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);
|
||
};
|
||
}());
|
||
|
||
/**
|
||
* Sets the `toString` method of `wrapper` to mimic the source of `reference`
|
||
* with wrapper details in a comment at the top of the source body.
|
||
*
|
||
* @private
|
||
* @param {Function} wrapper The function to modify.
|
||
* @param {Function} reference The reference function.
|
||
* @param {number} bitmask The bitmask flags. See `createWrap` for more details.
|
||
* @returns {Function} Returns `wrapper`.
|
||
*/
|
||
var setWrapToString = !defineProperty ? identity : function(wrapper, reference, bitmask) {
|
||
var source = (reference + '');
|
||
return defineProperty(wrapper, 'toString', {
|
||
'configurable': true,
|
||
'enumerable': false,
|
||
'value': constant(insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask)))
|
||
});
|
||
};
|
||
|
||
/**
|
||
* 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) {
|
||
string = toString(string);
|
||
|
||
var result = [];
|
||
if (reLeadingDot.test(string)) {
|
||
result.push('');
|
||
}
|
||
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 '';
|
||
}
|
||
|
||
/**
|
||
* Updates wrapper `details` based on `bitmask` flags.
|
||
*
|
||
* @private
|
||
* @returns {Array} details The details to modify.
|
||
* @param {number} bitmask The bitmask flags. See `createWrap` for more details.
|
||
* @returns {Array} Returns `details`.
|
||
*/
|
||
function updateWrapDetails(details, bitmask) {
|
||
arrayEach(wrapFlags, function(pair) {
|
||
var value = '_.' + pair[0];
|
||
if ((bitmask & pair[1]) && !arrayIncludes(details, value)) {
|
||
details.push(value);
|
||
}
|
||
});
|
||
return details.sort();
|
||
}
|
||
|
||
/**
|
||
* 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 `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.
|
||
*
|
||
* **Note:** Unlike `_.pullAll`, this method returns a new 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([2, 1], [2, 3]);
|
||
* // => [1]
|
||
*/
|
||
var difference = baseRest(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).
|
||
*
|
||
* **Note:** Unlike `_.pullAllBy`, this method returns a new array.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category Array
|
||
* @param {Array} array The array to inspect.
|
||
* @param {...Array} [values] The values to exclude.
|
||
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
|
||
* @returns {Array} Returns the new array of filtered values.
|
||
* @example
|
||
*
|
||
* _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor);
|
||
* // => [1.2]
|
||
*
|
||
* // The `_.property` iteratee shorthand.
|
||
* _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');
|
||
* // => [{ 'x': 2 }]
|
||
*/
|
||
var differenceBy = baseRest(function(array, values) {
|
||
var iteratee = last(values);
|
||
if (isArrayLikeObject(iteratee)) {
|
||
iteratee = undefined;
|
||
}
|
||
return isArrayLikeObject(array)
|
||
? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee, 2))
|
||
: [];
|
||
});
|
||
|
||
/**
|
||
* 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).
|
||
*
|
||
* **Note:** Unlike `_.pullAllWith`, this method returns a new array.
|
||
*
|
||
* @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 = baseRest(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 {Function} [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 {Function} [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 {Function} [predicate=_.identity]
|
||
* The function invoked per iteration.
|
||
* @param {number} [fromIndex=0] The index to search from.
|
||
* @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, fromIndex) {
|
||
var length = array ? array.length : 0;
|
||
if (!length) {
|
||
return -1;
|
||
}
|
||
var index = fromIndex == null ? 0 : toInteger(fromIndex);
|
||
if (index < 0) {
|
||
index = nativeMax(length + index, 0);
|
||
}
|
||
return baseFindIndex(array, getIteratee(predicate, 3), index);
|
||
}
|
||
|
||
/**
|
||
* 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 {Function} [predicate=_.identity]
|
||
* The function invoked per iteration.
|
||
* @param {number} [fromIndex=array.length-1] The index to search from.
|
||
* @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, fromIndex) {
|
||
var length = array ? array.length : 0;
|
||
if (!length) {
|
||
return -1;
|
||
}
|
||
var index = length - 1;
|
||
if (fromIndex !== undefined) {
|
||
index = toInteger(fromIndex);
|
||
index = fromIndex < 0
|
||
? nativeMax(length + index, 0)
|
||
: nativeMin(index, length - 1);
|
||
}
|
||
return baseFindIndex(array, getIteratee(predicate, 3), index, true);
|
||
}
|
||
|
||
/**
|
||
* 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([['a', 1], ['b', 2]]);
|
||
* // => { 'a': 1, 'b': 2 }
|
||
*/
|
||
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;
|
||
}
|
||
var index = fromIndex == null ? 0 : toInteger(fromIndex);
|
||
if (index < 0) {
|
||
index = nativeMax(length + index, 0);
|
||
}
|
||
return baseIndexOf(array, value, index);
|
||
}
|
||
|
||
/**
|
||
* 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], [2, 3]);
|
||
* // => [2]
|
||
*/
|
||
var intersection = baseRest(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 {Function} [iteratee=_.identity] The iteratee invoked per element.
|
||
* @returns {Array} Returns the new array of intersecting values.
|
||
* @example
|
||
*
|
||
* _.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor);
|
||
* // => [2.1]
|
||
*
|
||
* // The `_.property` iteratee shorthand.
|
||
* _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
|
||
* // => [{ 'x': 1 }]
|
||
*/
|
||
var intersectionBy = baseRest(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, 2))
|
||
: [];
|
||
});
|
||
|
||
/**
|
||
* 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 = baseRest(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 baseFindIndex(array, baseIsNaN, index - 1, true);
|
||
}
|
||
while (index--) {
|
||
if (array[index] === value) {
|
||
return index;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
/**
|
||
* Gets the element at index `n` 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 = ['a', 'b', 'c', 'a', 'b', 'c'];
|
||
*
|
||
* _.pull(array, 'a', 'c');
|
||
* console.log(array);
|
||
* // => ['b', 'b']
|
||
*/
|
||
var pull = baseRest(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 = ['a', 'b', 'c', 'a', 'b', 'c'];
|
||
*
|
||
* _.pullAll(array, ['a', 'c']);
|
||
* console.log(array);
|
||
* // => ['b', 'b']
|
||
*/
|
||
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 {Function} [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, 2))
|
||
: 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 = ['a', 'b', 'c', 'd'];
|
||
* var pulled = _.pullAt(array, [1, 3]);
|
||
*
|
||
* console.log(array);
|
||
* // => ['a', 'c']
|
||
*
|
||
* console.log(pulled);
|
||
* // => ['b', 'd']
|
||
*/
|
||
var pullAt = baseRest(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 {Function} [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
|
||
*/
|
||
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 {Function} [iteratee=_.identity]
|
||
* The iteratee invoked per element.
|
||
* @returns {number} Returns the index at which `value` should be inserted
|
||
* into `array`.
|
||
* @example
|
||
*
|
||
* var objects = [{ 'x': 4 }, { 'x': 5 }];
|
||
*
|
||
* _.sortedIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
|
||
* // => 0
|
||
*
|
||
* // The `_.property` iteratee shorthand.
|
||
* _.sortedIndexBy(objects, { 'x': 4 }, 'x');
|
||
* // => 0
|
||
*/
|
||
function sortedIndexBy(array, value, iteratee) {
|
||
return baseSortedIndexBy(array, value, getIteratee(iteratee, 2));
|
||
}
|
||
|
||
/**
|
||
* 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([4, 5, 5, 5, 6], 5);
|
||
* // => 1
|
||
*/
|
||
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, 5, 5, 6], 5);
|
||
* // => 4
|
||
*/
|
||
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 {Function} [iteratee=_.identity]
|
||
* The iteratee invoked per element.
|
||
* @returns {number} Returns the index at which `value` should be inserted
|
||
* into `array`.
|
||
* @example
|
||
*
|
||
* var objects = [{ 'x': 4 }, { 'x': 5 }];
|
||
*
|
||
* _.sortedLastIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
|
||
* // => 1
|
||
*
|
||
* // The `_.property` iteratee shorthand.
|
||
* _.sortedLastIndexBy(objects, { 'x': 4 }, 'x');
|
||
* // => 1
|
||
*/
|
||
function sortedLastIndexBy(array, value, iteratee) {
|
||
return baseSortedIndexBy(array, value, getIteratee(iteratee, 2), 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([4, 5, 5, 5, 6], 5);
|
||
* // => 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, 2))
|
||
: [];
|
||
}
|
||
|
||
/**
|
||
* 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 {Function} [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 {Function} [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, 2]);
|
||
* // => [2, 1]
|
||
*/
|
||
var union = baseRest(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. Result values are chosen from the first
|
||
* array in which the value occurs. The iteratee is invoked with one argument:
|
||
* (value).
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category Array
|
||
* @param {...Array} [arrays] The arrays to inspect.
|
||
* @param {Function} [iteratee=_.identity]
|
||
* The iteratee invoked per element.
|
||
* @returns {Array} Returns the new array of combined values.
|
||
* @example
|
||
*
|
||
* _.unionBy([2.1], [1.2, 2.3], Math.floor);
|
||
* // => [2.1, 1.2]
|
||
*
|
||
* // The `_.property` iteratee shorthand.
|
||
* _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
|
||
* // => [{ 'x': 1 }, { 'x': 2 }]
|
||
*/
|
||
var unionBy = baseRest(function(arrays) {
|
||
var iteratee = last(arrays);
|
||
if (isArrayLikeObject(iteratee)) {
|
||
iteratee = undefined;
|
||
}
|
||
return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee, 2));
|
||
});
|
||
|
||
/**
|
||
* This method is like `_.union` except that it accepts `comparator` which
|
||
* is invoked to compare elements of `arrays`. Result values are chosen from
|
||
* the first array in which the value occurs. 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 = baseRest(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 {Function} [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, 2))
|
||
: [];
|
||
}
|
||
|
||
/**
|
||
* 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(['a', 'b'], [1, 2], [true, false]);
|
||
* // => [['a', 1, true], ['b', 2, false]]
|
||
*
|
||
* _.unzip(zipped);
|
||
* // => [['a', 'b'], [1, 2], [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.
|
||
*
|
||
* **Note:** Unlike `_.pull`, this method returns a new array.
|
||
*
|
||
* @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([2, 1, 2, 3], 1, 2);
|
||
* // => [3]
|
||
*/
|
||
var without = baseRest(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], [2, 3]);
|
||
* // => [1, 3]
|
||
*/
|
||
var xor = baseRest(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 {Function} [iteratee=_.identity]
|
||
* The iteratee invoked per element.
|
||
* @returns {Array} Returns the new array of filtered values.
|
||
* @example
|
||
*
|
||
* _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor);
|
||
* // => [1.2, 3.4]
|
||
*
|
||
* // The `_.property` iteratee shorthand.
|
||
* _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
|
||
* // => [{ 'x': 2 }]
|
||
*/
|
||
var xorBy = baseRest(function(arrays) {
|
||
var iteratee = last(arrays);
|
||
if (isArrayLikeObject(iteratee)) {
|
||
iteratee = undefined;
|
||
}
|
||
return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee, 2));
|
||
});
|
||
|
||
/**
|
||
* 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 = baseRest(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(['a', 'b'], [1, 2], [true, false]);
|
||
* // => [['a', 1, true], ['b', 2, false]]
|
||
*/
|
||
var zip = baseRest(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 = baseRest(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]
|
||
*/
|
||
var wrapperAt = baseRest(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 {Function} [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 }
|
||
*
|
||
* // The `_.property` iteratee shorthand.
|
||
* _.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 {Function} [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).
|
||
*
|
||
* **Note:** Unlike `_.remove`, this method returns a new array.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 0.1.0
|
||
* @category Collection
|
||
* @param {Array|Object} collection The collection to iterate over.
|
||
* @param {Function} [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 {Function} [predicate=_.identity]
|
||
* The function invoked per iteration.
|
||
* @param {number} [fromIndex=0] The index to search from.
|
||
* @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'
|
||
*/
|
||
var find = createFind(findIndex);
|
||
|
||
/**
|
||
* 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 {Function} [predicate=_.identity]
|
||
* The function invoked per iteration.
|
||
* @param {number} [fromIndex=collection.length-1] The index to search from.
|
||
* @returns {*} Returns the matched element, else `undefined`.
|
||
* @example
|
||
*
|
||
* _.findLast([1, 2, 3, 4], function(n) {
|
||
* return n % 2 == 1;
|
||
* });
|
||
* // => 3
|
||
*/
|
||
var findLast = createFind(findLastIndex);
|
||
|
||
/**
|
||
* 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 {Function} [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 {Function} [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 {Function} [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 {Function} [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({ 'a': 1, 'b': 2 }, 1);
|
||
* // => true
|
||
*
|
||
* _.includes('abcd', 'bc');
|
||
* // => 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 `path` 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 = baseRest(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 {Function} [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 {Function} [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 {Function} [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 {Function} [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;
|
||
return func(collection, negate(getIteratee(predicate, 3)));
|
||
}
|
||
|
||
/**
|
||
* 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 {Function} [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 {...(Function|Function[])} [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 = baseRest(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]];
|
||
}
|
||
return baseOrderBy(collection, baseFlatten(iteratees, 1), []);
|
||
});
|
||
|
||
/*------------------------------------------------------------------------*/
|
||
|
||
/**
|
||
* 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
|
||
* @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 invocation.
|
||
*/
|
||
function now() {
|
||
return 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 createWrap(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
|
||
*
|
||
* function greet(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 = baseRest(function(func, thisArg, partials) {
|
||
var bitmask = BIND_FLAG;
|
||
if (partials.length) {
|
||
var holders = replaceHolders(partials, getHolder(bind));
|
||
bitmask |= PARTIAL_FLAG;
|
||
}
|
||
return createWrap(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 = baseRest(function(object, key, partials) {
|
||
var bitmask = BIND_FLAG | BIND_KEY_FLAG;
|
||
if (partials.length) {
|
||
var holders = replaceHolders(partials, getHolder(bindKey));
|
||
bitmask |= PARTIAL_FLAG;
|
||
}
|
||
return createWrap(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 = createWrap(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 = createWrap(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 `options` 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.
|
||
*
|
||
* If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
|
||
* until to the next tick, similar to `setTimeout` with a timeout of `0`.
|
||
*
|
||
* 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,
|
||
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 === undefined || (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) {
|
||
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);
|
||
}
|
||
lastInvokeTime = 0;
|
||
lastArgs = lastCallTime = 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.
|
||
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 = baseRest(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 = baseRest(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 createWrap(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() {
|
||
var args = arguments;
|
||
switch (args.length) {
|
||
case 0: return !predicate.call(this);
|
||
case 1: return !predicate.call(this, args[0]);
|
||
case 2: return !predicate.call(this, args[0], args[1]);
|
||
case 3: return !predicate.call(this, args[0], args[1], args[2]);
|
||
}
|
||
return !predicate.apply(this, args);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 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();
|
||
* // => `createApplication` is invoked once
|
||
*/
|
||
function once(func) {
|
||
return before(2, func);
|
||
}
|
||
|
||
/**
|
||
* Creates a function that invokes `func` with its arguments transformed.
|
||
*
|
||
* @static
|
||
* @since 4.0.0
|
||
* @memberOf _
|
||
* @category Function
|
||
* @param {Function} func The function to wrap.
|
||
* @param {...(Function|Function[])} [transforms=[_.identity]]
|
||
* The argument transforms.
|
||
* @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 = baseRest(function(func, transforms) {
|
||
transforms = (transforms.length == 1 && isArray(transforms[0]))
|
||
? arrayMap(transforms[0], baseUnary(getIteratee()))
|
||
: arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee()));
|
||
|
||
var funcsLength = transforms.length;
|
||
return baseRest(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
|
||
*
|
||
* function greet(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 = baseRest(function(func, partials) {
|
||
var holders = replaceHolders(partials, getHolder(partial));
|
||
return createWrap(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
|
||
*
|
||
* function greet(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 = baseRest(function(func, partials) {
|
||
var holders = replaceHolders(partials, getHolder(partialRight));
|
||
return createWrap(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 = baseRest(function(func, indexes) {
|
||
return createWrap(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 = start === undefined ? start : toInteger(start);
|
||
return baseRest(func, start);
|
||
}
|
||
|
||
/**
|
||
* 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 baseRest(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 `options` 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.
|
||
*
|
||
* If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
|
||
* until to the next tick, similar to `setTimeout` with a timeout of `0`.
|
||
*
|
||
* 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 `wrapper` as its first
|
||
* argument. Any additional arguments provided to the function are appended
|
||
* to those provided to the `wrapper`. 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 '<p>' + func(text) + '</p>';
|
||
* });
|
||
*
|
||
* p('fred, barney, & pebbles');
|
||
* // => '<p>fred, barney, & pebbles</p>'
|
||
*/
|
||
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);
|
||
}
|
||
|
||
/**
|
||
* Checks if `object` conforms to `source` by invoking the predicate
|
||
* properties of `source` with the corresponding property values of `object`.
|
||
*
|
||
* **Note:** This method is equivalent to `_.conforms` when `source` is
|
||
* partially applied.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.14.0
|
||
* @category Lang
|
||
* @param {Object} object The object to inspect.
|
||
* @param {Object} source The object of property predicates to conform to.
|
||
* @returns {boolean} Returns `true` if `object` conforms, else `false`.
|
||
* @example
|
||
*
|
||
* var object = { 'a': 1, 'b': 2 };
|
||
*
|
||
* _.conformsTo(object, { 'b': function(n) { return n > 1; } });
|
||
* // => true
|
||
*
|
||
* _.conformsTo(object, { 'b': function(n) { return n > 2; } });
|
||
* // => false
|
||
*/
|
||
function conformsTo(object, source) {
|
||
return source == null || baseConformsTo(object, source, keys(source));
|
||
}
|
||
|
||
/**
|
||
* 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 = { 'a': 1 };
|
||
* var other = { 'a': 1 };
|
||
*
|
||
* _.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 an `arguments` object,
|
||
* 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
|
||
* @category Lang
|
||
* @param {*} value The value to check.
|
||
* @returns {boolean} Returns `true` if `value` is an array, 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 an array buffer, else `false`.
|
||
* @example
|
||
*
|
||
* _.isArrayBuffer(new ArrayBuffer(2));
|
||
* // => true
|
||
*
|
||
* _.isArrayBuffer(new Array(2));
|
||
* // => false
|
||
*/
|
||
var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer;
|
||
|
||
/**
|
||
* 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 a boolean, 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 = nativeIsBuffer || stubFalse;
|
||
|
||
/**
|
||
* 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 a date object, else `false`.
|
||
* @example
|
||
*
|
||
* _.isDate(new Date);
|
||
* // => true
|
||
*
|
||
* _.isDate('Mon April 23 2012');
|
||
* // => false
|
||
*/
|
||
var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;
|
||
|
||
/**
|
||
* 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('<body>');
|
||
* // => 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 = { 'a': 1 };
|
||
* var other = { 'a': 1 };
|
||
*
|
||
* _.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 a function, 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 a map, else `false`.
|
||
* @example
|
||
*
|
||
* _.isMap(new Map);
|
||
* // => true
|
||
*
|
||
* _.isMap(new WeakMap);
|
||
* // => false
|
||
*/
|
||
var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;
|
||
|
||
/**
|
||
* Performs a partial deep comparison between `object` and `source` to
|
||
* determine if `object` contains equivalent property values.
|
||
*
|
||
* **Note:** This method supports comparing the same values as `_.isEqual`
|
||
* and is equivalent to `_.matches` when `source` is partially applied.
|
||
*
|
||
* @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 = { 'a': 1, 'b': 2 };
|
||
*
|
||
* _.isMatch(object, { 'b': 2 });
|
||
* // => true
|
||
*
|
||
* _.isMatch(object, { 'b': 1 });
|
||
* // => 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 pristine native function.
|
||
*
|
||
* **Note:** This method can't reliably detect native functions in the presence
|
||
* of the core-js package because core-js circumvents this kind of detection.
|
||
* Despite multiple requests, the core-js maintainer has made it clear: any
|
||
* attempt to fix the detection will be obstructed. As a result, we're left
|
||
* with little choice but to throw an error. Unfortunately, this also affects
|
||
* packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill),
|
||
* which rely on core-js.
|
||
*
|
||
* @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 (isMaskable(value)) {
|
||
throw new Error('This method is not supported with core-js. Try https://github.com/es-shims.');
|
||
}
|
||
return baseIsNative(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 a number, 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 a regexp, else `false`.
|
||
* @example
|
||
*
|
||
* _.isRegExp(/abc/);
|
||
* // => true
|
||
*
|
||
* _.isRegExp('/abc/');
|
||
* // => false
|
||
*/
|
||
var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp;
|
||
|
||
/**
|
||
* 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 a set, else `false`.
|
||
* @example
|
||
*
|
||
* _.isSet(new Set);
|
||
* // => true
|
||
*
|
||
* _.isSet(new WeakSet);
|
||
* // => false
|
||
*/
|
||
var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;
|
||
|
||
/**
|
||
* 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 a string, 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 a symbol, 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 a typed array, else `false`.
|
||
* @example
|
||
*
|
||
* _.isTypedArray(new Uint8Array);
|
||
* // => true
|
||
*
|
||
* _.isTypedArray([]);
|
||
* // => false
|
||
*/
|
||
var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
|
||
|
||
/**
|
||
* 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 a weak map, 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 a weak set, 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 method 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.a = 1;
|
||
* }
|
||
*
|
||
* function Bar() {
|
||
* this.c = 3;
|
||
* }
|
||
*
|
||
* Foo.prototype.b = 2;
|
||
* Bar.prototype.d = 4;
|
||
*
|
||
* _.assign({ 'a': 0 }, new Foo, new Bar);
|
||
* // => { 'a': 1, 'c': 3 }
|
||
*/
|
||
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.a = 1;
|
||
* }
|
||
*
|
||
* function Bar() {
|
||
* this.c = 3;
|
||
* }
|
||
*
|
||
* Foo.prototype.b = 2;
|
||
* Bar.prototype.d = 4;
|
||
*
|
||
* _.assignIn({ 'a': 0 }, new Foo, new Bar);
|
||
* // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 }
|
||
*/
|
||
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]
|
||
*/
|
||
var at = baseRest(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({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
|
||
* // => { 'a': 1, 'b': 2 }
|
||
*/
|
||
var defaults = baseRest(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({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } });
|
||
* // => { 'a': { 'b': 2, 'c': 3 } }
|
||
*/
|
||
var defaultsDeep = baseRest(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 {Function} [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 baseFindKey(object, getIteratee(predicate, 3), baseForOwn);
|
||
}
|
||
|
||
/**
|
||
* 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 {Function} [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 baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight);
|
||
}
|
||
|
||
/**
|
||
* 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 returned 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 {Function} [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 = baseRest(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 {Function} [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 {Function} [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 object = {
|
||
* 'a': [{ 'b': 2 }, { 'd': 4 }]
|
||
* };
|
||
*
|
||
* var other = {
|
||
* 'a': [{ 'c': 3 }, { 'e': 5 }]
|
||
* };
|
||
*
|
||
* _.merge(object, other);
|
||
* // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
|
||
*/
|
||
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 = { 'a': [1], 'b': [2] };
|
||
* var other = { 'a': [3], 'b': [4] };
|
||
*
|
||
* _.mergeWith(object, other, customizer);
|
||
* // => { 'a': [1, 3], 'b': [2, 4] }
|
||
*/
|
||
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 = baseRest(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 {Function} [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) {
|
||
return pickBy(object, negate(getIteratee(predicate)));
|
||
}
|
||
|
||
/**
|
||
* 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 = baseRest(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 {Function} [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, getAllKeysIn(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. If `accumulator` is not
|
||
* provided, a new object with the same `[[Prototype]]` will be used. 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 {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 = toFinite(start);
|
||
if (end === undefined) {
|
||
end = start;
|
||
start = 0;
|
||
} else {
|
||
end = toFinite(end);
|
||
}
|
||
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 = toFinite(lower);
|
||
if (upper === undefined) {
|
||
upper = lower;
|
||
lower = 0;
|
||
} else {
|
||
upper = toFinite(upper);
|
||
}
|
||
}
|
||
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 up to.
|
||
* @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);
|
||
|
||
var end = position;
|
||
position -= target.length;
|
||
return position >= 0 && string.slice(position, end) == target;
|
||
}
|
||
|
||
/**
|
||
* 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 <BOM> 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);
|
||
target = baseToString(target);
|
||
return string.slice(position, position + target.length) == target;
|
||
}
|
||
|
||
/**
|
||
* 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('<b><%- value %></b>');
|
||
* compiled({ 'value': '<script>' });
|
||
* // => '<b><script></b>'
|
||
*
|
||
* // Use the "evaluate" delimiter to execute JavaScript and generate HTML.
|
||
* var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');
|
||
* compiled({ 'users': ['fred', 'barney'] });
|
||
* // => '<li>fred</li><li>barney</li>'
|
||
*
|
||
* // Use the internal `print` function in "evaluate" delimiters.
|
||
* var compiled = _.template('<% print("hello " + user); %>!');
|
||
* compiled({ 'user': 'barney' });
|
||
* // => 'hello barney!'
|
||
*
|
||
* // Use the ES delimiter as an alternative to the default "interpolate" delimiter.
|
||
* var compiled = _.template('hello ${ user }!');
|
||
* compiled({ 'user': 'pebbles' });
|
||
* // => 'hello pebbles!'
|
||
*
|
||
* // Use backslashes to treat delimiters as plain text.
|
||
* var compiled = _.template('<%= "\\<%- value %\\>" %>');
|
||
* compiled({ 'value': 'ignored' });
|
||
* // => '<%- value %>'
|
||
*
|
||
* // Use the `imports` option to import `jQuery` as `jq`.
|
||
* var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>';
|
||
* var compiled = _.template(text, { 'imports': { 'jq': jQuery } });
|
||
* compiled({ 'users': ['fred', 'barney'] });
|
||
* // => '<li>fred</li><li>barney</li>'
|
||
*
|
||
* // Use the `sourceURL` option to specify a custom sourceURL for the template.
|
||
* var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' });
|
||
* compiled(data);
|
||
* // => Find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector.
|
||
*
|
||
* // Use the `variable` option to ensure a with-statement isn't used in the compiled template.
|
||
* var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' });
|
||
* compiled.source;
|
||
* // => function(data) {
|
||
* // var __t, __p = '';
|
||
* // __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!';
|
||
* // return __p;
|
||
* // }
|
||
*
|
||
* // Use custom template delimiters.
|
||
* _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
|
||
* var compiled = _.template('hello {{ user }}!');
|
||
* compiled({ 'user': 'mustache' });
|
||
* // => 'hello mustache!'
|
||
*
|
||
* // Use the `source` property to inline compiled templates for meaningful
|
||
* // line numbers in error messages and stack traces.
|
||
* fs.writeFileSync(path.join(process.cwd(), 'jst.js'), '\
|
||
* var JST = {\
|
||
* "main": ' + _.template(mainText).source + '\
|
||
* };\
|
||
* ');
|
||
*/
|
||
function template(string, options, guard) {
|
||
// Based on John Resig's `tmpl` implementation
|
||
// (http://ejohn.org/blog/javascript-micro-templating/)
|
||
// and Laura Doktorova's doT.js (https://github.com/olado/doT).
|
||
var settings = lodash.templateSettings;
|
||
|
||
if (guard && isIterateeCall(string, options, guard)) {
|
||
options = undefined;
|
||
}
|
||
string = toString(string);
|
||
options = assignInWith({}, options, settings, assignInDefaults);
|
||
|
||
var imports = assignInWith({}, options.imports, settings.imports, assignInDefaults),
|
||
importsKeys = keys(imports),
|
||
importsValues = baseValues(imports, importsKeys);
|
||
|
||
var isEscaping,
|
||
isEvaluating,
|
||
index = 0,
|
||
interpolate = options.interpolate || reNoMatch,
|
||
source = "__p += '";
|
||
|
||
// Compile the regexp to match each delimiter.
|
||
var reDelimiters = RegExp(
|
||
(options.escape || reNoMatch).source + '|' +
|
||
interpolate.source + '|' +
|
||
(interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
|
||
(options.evaluate || reNoMatch).source + '|$'
|
||
, 'g');
|
||
|
||
// Use a sourceURL for easier debugging.
|
||
var sourceURL = '//# sourceURL=' +
|
||
('sourceURL' in options
|
||
? options.sourceURL
|
||
: ('lodash.templateSources[' + (++templateCounter) + ']')
|
||
) + '\n';
|
||
|
||
string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
|
||
interpolateValue || (interpolateValue = esTemplateValue);
|
||
|
||
// Escape characters that can't be included in string literals.
|
||
source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);
|
||
|
||
// Replace delimiters with snippets.
|
||
if (escapeValue) {
|
||
isEscaping = true;
|
||
source += "' +\n__e(" + escapeValue + ") +\n'";
|
||
}
|
||
if (evaluateValue) {
|
||
isEvaluating = true;
|
||
source += "';\n" + evaluateValue + ";\n__p += '";
|
||
}
|
||
if (interpolateValue) {
|
||
source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
|
||
}
|
||
index = offset + match.length;
|
||
|
||
// The JS engine embedded in Adobe products needs `match` returned in
|
||
// order to produce the correct `offset` value.
|
||
return match;
|
||
});
|
||
|
||
source += "';\n";
|
||
|
||
// If `variable` is not specified wrap a with-statement around the generated
|
||
// code to add the data object to the top of the scope chain.
|
||
var variable = options.variable;
|
||
if (!variable) {
|
||
source = 'with (obj) {\n' + source + '\n}\n';
|
||
}
|
||
// Cleanup code by stripping empty strings.
|
||
source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
|
||
.replace(reEmptyStringMiddle, '$1')
|
||
.replace(reEmptyStringTrailing, '$1;');
|
||
|
||
// Frame code as the function body.
|
||
source = 'function(' + (variable || 'obj') + ') {\n' +
|
||
(variable
|
||
? ''
|
||
: 'obj || (obj = {});\n'
|
||
) +
|
||
"var __t, __p = ''" +
|
||
(isEscaping
|
||
? ', __e = _.escape'
|
||
: ''
|
||
) +
|
||
(isEvaluating
|
||
? ', __j = Array.prototype.join;\n' +
|
||
"function print() { __p += __j.call(arguments, '') }\n"
|
||
: ';\n'
|
||
) +
|
||
source +
|
||
'return __p\n}';
|
||
|
||
var result = attempt(function() {
|
||
return Function(importsKeys, sourceURL + 'return ' + source)
|
||
.apply(undefined, importsValues);
|
||
});
|
||
|
||
// Provide the compiled function's source by its `toString` method or
|
||
// the `source` property as a convenience for inlining compiled templates.
|
||
result.source = source;
|
||
if (isError(result)) {
|
||
throw result;
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Converts `string`, as a whole, to lower case just like
|
||
* [String#toLowerCase](https://mdn.io/toLowerCase).
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category String
|
||
* @param {string} [string=''] The string to convert.
|
||
* @returns {string} Returns the lower cased string.
|
||
* @example
|
||
*
|
||
* _.toLower('--Foo-Bar--');
|
||
* // => '--foo-bar--'
|
||
*
|
||
* _.toLower('fooBar');
|
||
* // => 'foobar'
|
||
*
|
||
* _.toLower('__FOO_BAR__');
|
||
* // => '__foo_bar__'
|
||
*/
|
||
function toLower(value) {
|
||
return toString(value).toLowerCase();
|
||
}
|
||
|
||
/**
|
||
* Converts `string`, as a whole, to upper case just like
|
||
* [String#toUpperCase](https://mdn.io/toUpperCase).
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category String
|
||
* @param {string} [string=''] The string to convert.
|
||
* @returns {string} Returns the upper cased string.
|
||
* @example
|
||
*
|
||
* _.toUpper('--foo-bar--');
|
||
* // => '--FOO-BAR--'
|
||
*
|
||
* _.toUpper('fooBar');
|
||
* // => 'FOOBAR'
|
||
*
|
||
* _.toUpper('__foo_bar__');
|
||
* // => '__FOO_BAR__'
|
||
*/
|
||
function toUpper(value) {
|
||
return toString(value).toUpperCase();
|
||
}
|
||
|
||
/**
|
||
* Removes leading and trailing whitespace or specified characters from `string`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 3.0.0
|
||
* @category String
|
||
* @param {string} [string=''] The string to trim.
|
||
* @param {string} [chars=whitespace] The characters to trim.
|
||
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
|
||
* @returns {string} Returns the trimmed string.
|
||
* @example
|
||
*
|
||
* _.trim(' abc ');
|
||
* // => 'abc'
|
||
*
|
||
* _.trim('-_-abc-_-', '_-');
|
||
* // => 'abc'
|
||
*
|
||
* _.map([' foo ', ' bar '], _.trim);
|
||
* // => ['foo', 'bar']
|
||
*/
|
||
function trim(string, chars, guard) {
|
||
string = toString(string);
|
||
if (string && (guard || chars === undefined)) {
|
||
return string.replace(reTrim, '');
|
||
}
|
||
if (!string || !(chars = baseToString(chars))) {
|
||
return string;
|
||
}
|
||
var strSymbols = stringToArray(string),
|
||
chrSymbols = stringToArray(chars),
|
||
start = charsStartIndex(strSymbols, chrSymbols),
|
||
end = charsEndIndex(strSymbols, chrSymbols) + 1;
|
||
|
||
return castSlice(strSymbols, start, end).join('');
|
||
}
|
||
|
||
/**
|
||
* Removes trailing whitespace or specified characters from `string`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category String
|
||
* @param {string} [string=''] The string to trim.
|
||
* @param {string} [chars=whitespace] The characters to trim.
|
||
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
|
||
* @returns {string} Returns the trimmed string.
|
||
* @example
|
||
*
|
||
* _.trimEnd(' abc ');
|
||
* // => ' abc'
|
||
*
|
||
* _.trimEnd('-_-abc-_-', '_-');
|
||
* // => '-_-abc'
|
||
*/
|
||
function trimEnd(string, chars, guard) {
|
||
string = toString(string);
|
||
if (string && (guard || chars === undefined)) {
|
||
return string.replace(reTrimEnd, '');
|
||
}
|
||
if (!string || !(chars = baseToString(chars))) {
|
||
return string;
|
||
}
|
||
var strSymbols = stringToArray(string),
|
||
end = charsEndIndex(strSymbols, stringToArray(chars)) + 1;
|
||
|
||
return castSlice(strSymbols, 0, end).join('');
|
||
}
|
||
|
||
/**
|
||
* Removes leading whitespace or specified characters from `string`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category String
|
||
* @param {string} [string=''] The string to trim.
|
||
* @param {string} [chars=whitespace] The characters to trim.
|
||
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
|
||
* @returns {string} Returns the trimmed string.
|
||
* @example
|
||
*
|
||
* _.trimStart(' abc ');
|
||
* // => 'abc '
|
||
*
|
||
* _.trimStart('-_-abc-_-', '_-');
|
||
* // => 'abc-_-'
|
||
*/
|
||
function trimStart(string, chars, guard) {
|
||
string = toString(string);
|
||
if (string && (guard || chars === undefined)) {
|
||
return string.replace(reTrimStart, '');
|
||
}
|
||
if (!string || !(chars = baseToString(chars))) {
|
||
return string;
|
||
}
|
||
var strSymbols = stringToArray(string),
|
||
start = charsStartIndex(strSymbols, stringToArray(chars));
|
||
|
||
return castSlice(strSymbols, start).join('');
|
||
}
|
||
|
||
/**
|
||
* Truncates `string` if it's longer than the given maximum string length.
|
||
* The last characters of the truncated string are replaced with the omission
|
||
* string which defaults to "...".
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category String
|
||
* @param {string} [string=''] The string to truncate.
|
||
* @param {Object} [options={}] The options object.
|
||
* @param {number} [options.length=30] The maximum string length.
|
||
* @param {string} [options.omission='...'] The string to indicate text is omitted.
|
||
* @param {RegExp|string} [options.separator] The separator pattern to truncate to.
|
||
* @returns {string} Returns the truncated string.
|
||
* @example
|
||
*
|
||
* _.truncate('hi-diddly-ho there, neighborino');
|
||
* // => 'hi-diddly-ho there, neighbo...'
|
||
*
|
||
* _.truncate('hi-diddly-ho there, neighborino', {
|
||
* 'length': 24,
|
||
* 'separator': ' '
|
||
* });
|
||
* // => 'hi-diddly-ho there,...'
|
||
*
|
||
* _.truncate('hi-diddly-ho there, neighborino', {
|
||
* 'length': 24,
|
||
* 'separator': /,? +/
|
||
* });
|
||
* // => 'hi-diddly-ho there...'
|
||
*
|
||
* _.truncate('hi-diddly-ho there, neighborino', {
|
||
* 'omission': ' [...]'
|
||
* });
|
||
* // => 'hi-diddly-ho there, neig [...]'
|
||
*/
|
||
function truncate(string, options) {
|
||
var length = DEFAULT_TRUNC_LENGTH,
|
||
omission = DEFAULT_TRUNC_OMISSION;
|
||
|
||
if (isObject(options)) {
|
||
var separator = 'separator' in options ? options.separator : separator;
|
||
length = 'length' in options ? toInteger(options.length) : length;
|
||
omission = 'omission' in options ? baseToString(options.omission) : omission;
|
||
}
|
||
string = toString(string);
|
||
|
||
var strLength = string.length;
|
||
if (reHasComplexSymbol.test(string)) {
|
||
var strSymbols = stringToArray(string);
|
||
strLength = strSymbols.length;
|
||
}
|
||
if (length >= strLength) {
|
||
return string;
|
||
}
|
||
var end = length - stringSize(omission);
|
||
if (end < 1) {
|
||
return omission;
|
||
}
|
||
var result = strSymbols
|
||
? castSlice(strSymbols, 0, end).join('')
|
||
: string.slice(0, end);
|
||
|
||
if (separator === undefined) {
|
||
return result + omission;
|
||
}
|
||
if (strSymbols) {
|
||
end += (result.length - end);
|
||
}
|
||
if (isRegExp(separator)) {
|
||
if (string.slice(end).search(separator)) {
|
||
var match,
|
||
substring = result;
|
||
|
||
if (!separator.global) {
|
||
separator = RegExp(separator.source, toString(reFlags.exec(separator)) + 'g');
|
||
}
|
||
separator.lastIndex = 0;
|
||
while ((match = separator.exec(substring))) {
|
||
var newEnd = match.index;
|
||
}
|
||
result = result.slice(0, newEnd === undefined ? end : newEnd);
|
||
}
|
||
} else if (string.indexOf(baseToString(separator), end) != end) {
|
||
var index = result.lastIndexOf(separator);
|
||
if (index > -1) {
|
||
result = result.slice(0, index);
|
||
}
|
||
}
|
||
return result + omission;
|
||
}
|
||
|
||
/**
|
||
* The inverse of `_.escape`; this method converts the HTML entities
|
||
* `&`, `<`, `>`, `"`, `'`, and ``` in `string` to
|
||
* their corresponding characters.
|
||
*
|
||
* **Note:** No other HTML entities are unescaped. To unescape additional
|
||
* HTML entities use a third-party library like [_he_](https://mths.be/he).
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 0.6.0
|
||
* @category String
|
||
* @param {string} [string=''] The string to unescape.
|
||
* @returns {string} Returns the unescaped string.
|
||
* @example
|
||
*
|
||
* _.unescape('fred, barney, & pebbles');
|
||
* // => 'fred, barney, & pebbles'
|
||
*/
|
||
function unescape(string) {
|
||
string = toString(string);
|
||
return (string && reHasEscapedHtml.test(string))
|
||
? string.replace(reEscapedHtml, unescapeHtmlChar)
|
||
: string;
|
||
}
|
||
|
||
/**
|
||
* Converts `string`, as space separated words, to upper case.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category String
|
||
* @param {string} [string=''] The string to convert.
|
||
* @returns {string} Returns the upper cased string.
|
||
* @example
|
||
*
|
||
* _.upperCase('--foo-bar');
|
||
* // => 'FOO BAR'
|
||
*
|
||
* _.upperCase('fooBar');
|
||
* // => 'FOO BAR'
|
||
*
|
||
* _.upperCase('__foo_bar__');
|
||
* // => 'FOO BAR'
|
||
*/
|
||
var upperCase = createCompounder(function(result, word, index) {
|
||
return result + (index ? ' ' : '') + word.toUpperCase();
|
||
});
|
||
|
||
/**
|
||
* Converts the first character of `string` to upper case.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category String
|
||
* @param {string} [string=''] The string to convert.
|
||
* @returns {string} Returns the converted string.
|
||
* @example
|
||
*
|
||
* _.upperFirst('fred');
|
||
* // => 'Fred'
|
||
*
|
||
* _.upperFirst('FRED');
|
||
* // => 'FRED'
|
||
*/
|
||
var upperFirst = createCaseFirst('toUpperCase');
|
||
|
||
/**
|
||
* Splits `string` into an array of its words.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 3.0.0
|
||
* @category String
|
||
* @param {string} [string=''] The string to inspect.
|
||
* @param {RegExp|string} [pattern] The pattern to match words.
|
||
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
|
||
* @returns {Array} Returns the words of `string`.
|
||
* @example
|
||
*
|
||
* _.words('fred, barney, & pebbles');
|
||
* // => ['fred', 'barney', 'pebbles']
|
||
*
|
||
* _.words('fred, barney, & pebbles', /[^, ]+/g);
|
||
* // => ['fred', 'barney', '&', 'pebbles']
|
||
*/
|
||
function words(string, pattern, guard) {
|
||
string = toString(string);
|
||
pattern = guard ? undefined : pattern;
|
||
|
||
if (pattern === undefined) {
|
||
pattern = reHasComplexWord.test(string) ? reComplexWord : reBasicWord;
|
||
}
|
||
return string.match(pattern) || [];
|
||
}
|
||
|
||
/*------------------------------------------------------------------------*/
|
||
|
||
/**
|
||
* Attempts to invoke `func`, returning either the result or the caught error
|
||
* object. Any additional arguments are provided to `func` when it's invoked.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 3.0.0
|
||
* @category Util
|
||
* @param {Function} func The function to attempt.
|
||
* @param {...*} [args] The arguments to invoke `func` with.
|
||
* @returns {*} Returns the `func` result or error object.
|
||
* @example
|
||
*
|
||
* // Avoid throwing errors for invalid selectors.
|
||
* var elements = _.attempt(function(selector) {
|
||
* return document.querySelectorAll(selector);
|
||
* }, '>_>');
|
||
*
|
||
* if (_.isError(elements)) {
|
||
* elements = [];
|
||
* }
|
||
*/
|
||
var attempt = baseRest(function(func, args) {
|
||
try {
|
||
return apply(func, undefined, args);
|
||
} catch (e) {
|
||
return isError(e) ? e : new Error(e);
|
||
}
|
||
});
|
||
|
||
/**
|
||
* Binds methods of an object to the object itself, overwriting the existing
|
||
* method.
|
||
*
|
||
* **Note:** This method doesn't set the "length" property of bound functions.
|
||
*
|
||
* @static
|
||
* @since 0.1.0
|
||
* @memberOf _
|
||
* @category Util
|
||
* @param {Object} object The object to bind and assign the bound methods to.
|
||
* @param {...(string|string[])} methodNames The object method names to bind.
|
||
* @returns {Object} Returns `object`.
|
||
* @example
|
||
*
|
||
* var view = {
|
||
* 'label': 'docs',
|
||
* 'click': function() {
|
||
* console.log('clicked ' + this.label);
|
||
* }
|
||
* };
|
||
*
|
||
* _.bindAll(view, ['click']);
|
||
* jQuery(element).on('click', view.click);
|
||
* // => Logs 'clicked docs' when clicked.
|
||
*/
|
||
var bindAll = baseRest(function(object, methodNames) {
|
||
arrayEach(baseFlatten(methodNames, 1), function(key) {
|
||
key = toKey(key);
|
||
object[key] = bind(object[key], object);
|
||
});
|
||
return object;
|
||
});
|
||
|
||
/**
|
||
* Creates a function that iterates over `pairs` and invokes the corresponding
|
||
* function of the first predicate to return truthy. The predicate-function
|
||
* pairs are invoked with the `this` binding and arguments of the created
|
||
* function.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category Util
|
||
* @param {Array} pairs The predicate-function pairs.
|
||
* @returns {Function} Returns the new composite function.
|
||
* @example
|
||
*
|
||
* var func = _.cond([
|
||
* [_.matches({ 'a': 1 }), _.constant('matches A')],
|
||
* [_.conforms({ 'b': _.isNumber }), _.constant('matches B')],
|
||
* [_.stubTrue, _.constant('no match')]
|
||
* ]);
|
||
*
|
||
* func({ 'a': 1, 'b': 2 });
|
||
* // => 'matches A'
|
||
*
|
||
* func({ 'a': 0, 'b': 1 });
|
||
* // => 'matches B'
|
||
*
|
||
* func({ 'a': '1', 'b': '2' });
|
||
* // => 'no match'
|
||
*/
|
||
function cond(pairs) {
|
||
var length = pairs ? pairs.length : 0,
|
||
toIteratee = getIteratee();
|
||
|
||
pairs = !length ? [] : arrayMap(pairs, function(pair) {
|
||
if (typeof pair[1] != 'function') {
|
||
throw new TypeError(FUNC_ERROR_TEXT);
|
||
}
|
||
return [toIteratee(pair[0]), pair[1]];
|
||
});
|
||
|
||
return baseRest(function(args) {
|
||
var index = -1;
|
||
while (++index < length) {
|
||
var pair = pairs[index];
|
||
if (apply(pair[0], this, args)) {
|
||
return apply(pair[1], this, args);
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Creates a function that invokes the predicate properties of `source` with
|
||
* the corresponding property values of a given object, returning `true` if
|
||
* all predicates return truthy, else `false`.
|
||
*
|
||
* **Note:** The created function is equivalent to `_.conformsTo` with
|
||
* `source` partially applied.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category Util
|
||
* @param {Object} source The object of property predicates to conform to.
|
||
* @returns {Function} Returns the new spec function.
|
||
* @example
|
||
*
|
||
* var objects = [
|
||
* { 'a': 2, 'b': 1 },
|
||
* { 'a': 1, 'b': 2 }
|
||
* ];
|
||
*
|
||
* _.filter(objects, _.conforms({ 'b': function(n) { return n > 1; } }));
|
||
* // => [{ 'a': 1, 'b': 2 }]
|
||
*/
|
||
function conforms(source) {
|
||
return baseConforms(baseClone(source, true));
|
||
}
|
||
|
||
/**
|
||
* Creates a function that returns `value`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 2.4.0
|
||
* @category Util
|
||
* @param {*} value The value to return from the new function.
|
||
* @returns {Function} Returns the new constant function.
|
||
* @example
|
||
*
|
||
* var objects = _.times(2, _.constant({ 'a': 1 }));
|
||
*
|
||
* console.log(objects);
|
||
* // => [{ 'a': 1 }, { 'a': 1 }]
|
||
*
|
||
* console.log(objects[0] === objects[1]);
|
||
* // => true
|
||
*/
|
||
function constant(value) {
|
||
return function() {
|
||
return value;
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Checks `value` to determine whether a default value should be returned in
|
||
* its place. The `defaultValue` is returned if `value` is `NaN`, `null`,
|
||
* or `undefined`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.14.0
|
||
* @category Util
|
||
* @param {*} value The value to check.
|
||
* @param {*} defaultValue The default value.
|
||
* @returns {*} Returns the resolved value.
|
||
* @example
|
||
*
|
||
* _.defaultTo(1, 10);
|
||
* // => 1
|
||
*
|
||
* _.defaultTo(undefined, 10);
|
||
* // => 10
|
||
*/
|
||
function defaultTo(value, defaultValue) {
|
||
return (value == null || value !== value) ? defaultValue : value;
|
||
}
|
||
|
||
/**
|
||
* Creates a function that returns the result of invoking the given functions
|
||
* with the `this` binding of the created function, where each successive
|
||
* invocation is supplied the return value of the previous.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 3.0.0
|
||
* @category Util
|
||
* @param {...(Function|Function[])} [funcs] The functions to invoke.
|
||
* @returns {Function} Returns the new composite function.
|
||
* @see _.flowRight
|
||
* @example
|
||
*
|
||
* function square(n) {
|
||
* return n * n;
|
||
* }
|
||
*
|
||
* var addSquare = _.flow([_.add, square]);
|
||
* addSquare(1, 2);
|
||
* // => 9
|
||
*/
|
||
var flow = createFlow();
|
||
|
||
/**
|
||
* This method is like `_.flow` except that it creates a function that
|
||
* invokes the given functions from right to left.
|
||
*
|
||
* @static
|
||
* @since 3.0.0
|
||
* @memberOf _
|
||
* @category Util
|
||
* @param {...(Function|Function[])} [funcs] The functions to invoke.
|
||
* @returns {Function} Returns the new composite function.
|
||
* @see _.flow
|
||
* @example
|
||
*
|
||
* function square(n) {
|
||
* return n * n;
|
||
* }
|
||
*
|
||
* var addSquare = _.flowRight([square, _.add]);
|
||
* addSquare(1, 2);
|
||
* // => 9
|
||
*/
|
||
var flowRight = createFlow(true);
|
||
|
||
/**
|
||
* This method returns the first argument it receives.
|
||
*
|
||
* @static
|
||
* @since 0.1.0
|
||
* @memberOf _
|
||
* @category Util
|
||
* @param {*} value Any value.
|
||
* @returns {*} Returns `value`.
|
||
* @example
|
||
*
|
||
* var object = { 'a': 1 };
|
||
*
|
||
* console.log(_.identity(object) === object);
|
||
* // => true
|
||
*/
|
||
function identity(value) {
|
||
return value;
|
||
}
|
||
|
||
/**
|
||
* Creates a function that invokes `func` with the arguments of the created
|
||
* function. If `func` is a property name, the created function returns the
|
||
* property value for a given element. If `func` is an array or object, the
|
||
* created function returns `true` for elements that contain the equivalent
|
||
* source properties, otherwise it returns `false`.
|
||
*
|
||
* @static
|
||
* @since 4.0.0
|
||
* @memberOf _
|
||
* @category Util
|
||
* @param {*} [func=_.identity] The value to convert to a callback.
|
||
* @returns {Function} Returns the callback.
|
||
* @example
|
||
*
|
||
* var users = [
|
||
* { 'user': 'barney', 'age': 36, 'active': true },
|
||
* { 'user': 'fred', 'age': 40, 'active': false }
|
||
* ];
|
||
*
|
||
* // The `_.matches` iteratee shorthand.
|
||
* _.filter(users, _.iteratee({ 'user': 'barney', 'active': true }));
|
||
* // => [{ 'user': 'barney', 'age': 36, 'active': true }]
|
||
*
|
||
* // The `_.matchesProperty` iteratee shorthand.
|
||
* _.filter(users, _.iteratee(['user', 'fred']));
|
||
* // => [{ 'user': 'fred', 'age': 40 }]
|
||
*
|
||
* // The `_.property` iteratee shorthand.
|
||
* _.map(users, _.iteratee('user'));
|
||
* // => ['barney', 'fred']
|
||
*
|
||
* // Create custom iteratee shorthands.
|
||
* _.iteratee = _.wrap(_.iteratee, function(iteratee, func) {
|
||
* return !_.isRegExp(func) ? iteratee(func) : function(string) {
|
||
* return func.test(string);
|
||
* };
|
||
* });
|
||
*
|
||
* _.filter(['abc', 'def'], /ef/);
|
||
* // => ['def']
|
||
*/
|
||
function iteratee(func) {
|
||
return baseIteratee(typeof func == 'function' ? func : baseClone(func, true));
|
||
}
|
||
|
||
/**
|
||
* Creates a function that performs a partial deep comparison between a given
|
||
* object and `source`, returning `true` if the given object has equivalent
|
||
* property values, else `false`.
|
||
*
|
||
* **Note:** The created function supports comparing the same values as
|
||
* `_.isEqual` is equivalent to `_.isMatch` with `source` partially applied.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 3.0.0
|
||
* @category Util
|
||
* @param {Object} source The object of property values to match.
|
||
* @returns {Function} Returns the new spec function.
|
||
* @example
|
||
*
|
||
* var objects = [
|
||
* { 'a': 1, 'b': 2, 'c': 3 },
|
||
* { 'a': 4, 'b': 5, 'c': 6 }
|
||
* ];
|
||
*
|
||
* _.filter(objects, _.matches({ 'a': 4, 'c': 6 }));
|
||
* // => [{ 'a': 4, 'b': 5, 'c': 6 }]
|
||
*/
|
||
function matches(source) {
|
||
return baseMatches(baseClone(source, true));
|
||
}
|
||
|
||
/**
|
||
* Creates a function that performs a partial deep comparison between the
|
||
* value at `path` of a given object to `srcValue`, returning `true` if the
|
||
* object value is equivalent, else `false`.
|
||
*
|
||
* **Note:** This method supports comparing the same values as `_.isEqual`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 3.2.0
|
||
* @category Util
|
||
* @param {Array|string} path The path of the property to get.
|
||
* @param {*} srcValue The value to match.
|
||
* @returns {Function} Returns the new spec function.
|
||
* @example
|
||
*
|
||
* var objects = [
|
||
* { 'a': 1, 'b': 2, 'c': 3 },
|
||
* { 'a': 4, 'b': 5, 'c': 6 }
|
||
* ];
|
||
*
|
||
* _.find(objects, _.matchesProperty('a', 4));
|
||
* // => { 'a': 4, 'b': 5, 'c': 6 }
|
||
*/
|
||
function matchesProperty(path, srcValue) {
|
||
return baseMatchesProperty(path, baseClone(srcValue, true));
|
||
}
|
||
|
||
/**
|
||
* Creates a function that invokes the method at `path` of a given object.
|
||
* Any additional arguments are provided to the invoked method.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 3.7.0
|
||
* @category Util
|
||
* @param {Array|string} path The path of the method to invoke.
|
||
* @param {...*} [args] The arguments to invoke the method with.
|
||
* @returns {Function} Returns the new invoker function.
|
||
* @example
|
||
*
|
||
* var objects = [
|
||
* { 'a': { 'b': _.constant(2) } },
|
||
* { 'a': { 'b': _.constant(1) } }
|
||
* ];
|
||
*
|
||
* _.map(objects, _.method('a.b'));
|
||
* // => [2, 1]
|
||
*
|
||
* _.map(objects, _.method(['a', 'b']));
|
||
* // => [2, 1]
|
||
*/
|
||
var method = baseRest(function(path, args) {
|
||
return function(object) {
|
||
return baseInvoke(object, path, args);
|
||
};
|
||
});
|
||
|
||
/**
|
||
* The opposite of `_.method`; this method creates a function that invokes
|
||
* the method at a given path of `object`. Any additional arguments are
|
||
* provided to the invoked method.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 3.7.0
|
||
* @category Util
|
||
* @param {Object} object The object to query.
|
||
* @param {...*} [args] The arguments to invoke the method with.
|
||
* @returns {Function} Returns the new invoker function.
|
||
* @example
|
||
*
|
||
* var array = _.times(3, _.constant),
|
||
* object = { 'a': array, 'b': array, 'c': array };
|
||
*
|
||
* _.map(['a[2]', 'c[0]'], _.methodOf(object));
|
||
* // => [2, 0]
|
||
*
|
||
* _.map([['a', '2'], ['c', '0']], _.methodOf(object));
|
||
* // => [2, 0]
|
||
*/
|
||
var methodOf = baseRest(function(object, args) {
|
||
return function(path) {
|
||
return baseInvoke(object, path, args);
|
||
};
|
||
});
|
||
|
||
/**
|
||
* Adds all own enumerable string keyed function properties of a source
|
||
* object to the destination object. If `object` is a function, then methods
|
||
* are added to its prototype as well.
|
||
*
|
||
* **Note:** Use `_.runInContext` to create a pristine `lodash` function to
|
||
* avoid conflicts caused by modifying the original.
|
||
*
|
||
* @static
|
||
* @since 0.1.0
|
||
* @memberOf _
|
||
* @category Util
|
||
* @param {Function|Object} [object=lodash] The destination object.
|
||
* @param {Object} source The object of functions to add.
|
||
* @param {Object} [options={}] The options object.
|
||
* @param {boolean} [options.chain=true] Specify whether mixins are chainable.
|
||
* @returns {Function|Object} Returns `object`.
|
||
* @example
|
||
*
|
||
* function vowels(string) {
|
||
* return _.filter(string, function(v) {
|
||
* return /[aeiou]/i.test(v);
|
||
* });
|
||
* }
|
||
*
|
||
* _.mixin({ 'vowels': vowels });
|
||
* _.vowels('fred');
|
||
* // => ['e']
|
||
*
|
||
* _('fred').vowels().value();
|
||
* // => ['e']
|
||
*
|
||
* _.mixin({ 'vowels': vowels }, { 'chain': false });
|
||
* _('fred').vowels();
|
||
* // => ['e']
|
||
*/
|
||
function mixin(object, source, options) {
|
||
var props = keys(source),
|
||
methodNames = baseFunctions(source, props);
|
||
|
||
if (options == null &&
|
||
!(isObject(source) && (methodNames.length || !props.length))) {
|
||
options = source;
|
||
source = object;
|
||
object = this;
|
||
methodNames = baseFunctions(source, keys(source));
|
||
}
|
||
var chain = !(isObject(options) && 'chain' in options) || !!options.chain,
|
||
isFunc = isFunction(object);
|
||
|
||
arrayEach(methodNames, function(methodName) {
|
||
var func = source[methodName];
|
||
object[methodName] = func;
|
||
if (isFunc) {
|
||
object.prototype[methodName] = function() {
|
||
var chainAll = this.__chain__;
|
||
if (chain || chainAll) {
|
||
var result = object(this.__wrapped__),
|
||
actions = result.__actions__ = copyArray(this.__actions__);
|
||
|
||
actions.push({ 'func': func, 'args': arguments, 'thisArg': object });
|
||
result.__chain__ = chainAll;
|
||
return result;
|
||
}
|
||
return func.apply(object, arrayPush([this.value()], arguments));
|
||
};
|
||
}
|
||
});
|
||
|
||
return object;
|
||
}
|
||
|
||
/**
|
||
* Reverts the `_` variable to its previous value and returns a reference to
|
||
* the `lodash` function.
|
||
*
|
||
* @static
|
||
* @since 0.1.0
|
||
* @memberOf _
|
||
* @category Util
|
||
* @returns {Function} Returns the `lodash` function.
|
||
* @example
|
||
*
|
||
* var lodash = _.noConflict();
|
||
*/
|
||
function noConflict() {
|
||
if (root._ === this) {
|
||
root._ = oldDash;
|
||
}
|
||
return this;
|
||
}
|
||
|
||
/**
|
||
* This method returns `undefined`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 2.3.0
|
||
* @category Util
|
||
* @example
|
||
*
|
||
* _.times(2, _.noop);
|
||
* // => [undefined, undefined]
|
||
*/
|
||
function noop() {
|
||
// No operation performed.
|
||
}
|
||
|
||
/**
|
||
* Creates a function that gets the argument at index `n`. If `n` is negative,
|
||
* the nth argument from the end is returned.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category Util
|
||
* @param {number} [n=0] The index of the argument to return.
|
||
* @returns {Function} Returns the new pass-thru function.
|
||
* @example
|
||
*
|
||
* var func = _.nthArg(1);
|
||
* func('a', 'b', 'c', 'd');
|
||
* // => 'b'
|
||
*
|
||
* var func = _.nthArg(-2);
|
||
* func('a', 'b', 'c', 'd');
|
||
* // => 'c'
|
||
*/
|
||
function nthArg(n) {
|
||
n = toInteger(n);
|
||
return baseRest(function(args) {
|
||
return baseNth(args, n);
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Creates a function that invokes `iteratees` with the arguments it receives
|
||
* and returns their results.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category Util
|
||
* @param {...(Function|Function[])} [iteratees=[_.identity]]
|
||
* The iteratees to invoke.
|
||
* @returns {Function} Returns the new function.
|
||
* @example
|
||
*
|
||
* var func = _.over([Math.max, Math.min]);
|
||
*
|
||
* func(1, 2, 3, 4);
|
||
* // => [4, 1]
|
||
*/
|
||
var over = createOver(arrayMap);
|
||
|
||
/**
|
||
* Creates a function that checks if **all** of the `predicates` return
|
||
* truthy when invoked with the arguments it receives.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category Util
|
||
* @param {...(Function|Function[])} [predicates=[_.identity]]
|
||
* The predicates to check.
|
||
* @returns {Function} Returns the new function.
|
||
* @example
|
||
*
|
||
* var func = _.overEvery([Boolean, isFinite]);
|
||
*
|
||
* func('1');
|
||
* // => true
|
||
*
|
||
* func(null);
|
||
* // => false
|
||
*
|
||
* func(NaN);
|
||
* // => false
|
||
*/
|
||
var overEvery = createOver(arrayEvery);
|
||
|
||
/**
|
||
* Creates a function that checks if **any** of the `predicates` return
|
||
* truthy when invoked with the arguments it receives.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category Util
|
||
* @param {...(Function|Function[])} [predicates=[_.identity]]
|
||
* The predicates to check.
|
||
* @returns {Function} Returns the new function.
|
||
* @example
|
||
*
|
||
* var func = _.overSome([Boolean, isFinite]);
|
||
*
|
||
* func('1');
|
||
* // => true
|
||
*
|
||
* func(null);
|
||
* // => true
|
||
*
|
||
* func(NaN);
|
||
* // => false
|
||
*/
|
||
var overSome = createOver(arraySome);
|
||
|
||
/**
|
||
* Creates a function that returns the value at `path` of a given object.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 2.4.0
|
||
* @category Util
|
||
* @param {Array|string} path The path of the property to get.
|
||
* @returns {Function} Returns the new accessor function.
|
||
* @example
|
||
*
|
||
* var objects = [
|
||
* { 'a': { 'b': 2 } },
|
||
* { 'a': { 'b': 1 } }
|
||
* ];
|
||
*
|
||
* _.map(objects, _.property('a.b'));
|
||
* // => [2, 1]
|
||
*
|
||
* _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');
|
||
* // => [1, 2]
|
||
*/
|
||
function property(path) {
|
||
return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
|
||
}
|
||
|
||
/**
|
||
* The opposite of `_.property`; this method creates a function that returns
|
||
* the value at a given path of `object`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 3.0.0
|
||
* @category Util
|
||
* @param {Object} object The object to query.
|
||
* @returns {Function} Returns the new accessor function.
|
||
* @example
|
||
*
|
||
* var array = [0, 1, 2],
|
||
* object = { 'a': array, 'b': array, 'c': array };
|
||
*
|
||
* _.map(['a[2]', 'c[0]'], _.propertyOf(object));
|
||
* // => [2, 0]
|
||
*
|
||
* _.map([['a', '2'], ['c', '0']], _.propertyOf(object));
|
||
* // => [2, 0]
|
||
*/
|
||
function propertyOf(object) {
|
||
return function(path) {
|
||
return object == null ? undefined : baseGet(object, path);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Creates an array of numbers (positive and/or negative) progressing from
|
||
* `start` up to, but not including, `end`. A step of `-1` is used if a negative
|
||
* `start` is specified without an `end` or `step`. If `end` is not specified,
|
||
* it's set to `start` with `start` then set to `0`.
|
||
*
|
||
* **Note:** JavaScript follows the IEEE-754 standard for resolving
|
||
* floating-point values which can produce unexpected results.
|
||
*
|
||
* @static
|
||
* @since 0.1.0
|
||
* @memberOf _
|
||
* @category Util
|
||
* @param {number} [start=0] The start of the range.
|
||
* @param {number} end The end of the range.
|
||
* @param {number} [step=1] The value to increment or decrement by.
|
||
* @returns {Array} Returns the range of numbers.
|
||
* @see _.inRange, _.rangeRight
|
||
* @example
|
||
*
|
||
* _.range(4);
|
||
* // => [0, 1, 2, 3]
|
||
*
|
||
* _.range(-4);
|
||
* // => [0, -1, -2, -3]
|
||
*
|
||
* _.range(1, 5);
|
||
* // => [1, 2, 3, 4]
|
||
*
|
||
* _.range(0, 20, 5);
|
||
* // => [0, 5, 10, 15]
|
||
*
|
||
* _.range(0, -4, -1);
|
||
* // => [0, -1, -2, -3]
|
||
*
|
||
* _.range(1, 4, 0);
|
||
* // => [1, 1, 1]
|
||
*
|
||
* _.range(0);
|
||
* // => []
|
||
*/
|
||
var range = createRange();
|
||
|
||
/**
|
||
* This method is like `_.range` except that it populates values in
|
||
* descending order.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category Util
|
||
* @param {number} [start=0] The start of the range.
|
||
* @param {number} end The end of the range.
|
||
* @param {number} [step=1] The value to increment or decrement by.
|
||
* @returns {Array} Returns the range of numbers.
|
||
* @see _.inRange, _.range
|
||
* @example
|
||
*
|
||
* _.rangeRight(4);
|
||
* // => [3, 2, 1, 0]
|
||
*
|
||
* _.rangeRight(-4);
|
||
* // => [-3, -2, -1, 0]
|
||
*
|
||
* _.rangeRight(1, 5);
|
||
* // => [4, 3, 2, 1]
|
||
*
|
||
* _.rangeRight(0, 20, 5);
|
||
* // => [15, 10, 5, 0]
|
||
*
|
||
* _.rangeRight(0, -4, -1);
|
||
* // => [-3, -2, -1, 0]
|
||
*
|
||
* _.rangeRight(1, 4, 0);
|
||
* // => [1, 1, 1]
|
||
*
|
||
* _.rangeRight(0);
|
||
* // => []
|
||
*/
|
||
var rangeRight = createRange(true);
|
||
|
||
/**
|
||
* This method returns a new empty array.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.13.0
|
||
* @category Util
|
||
* @returns {Array} Returns the new empty array.
|
||
* @example
|
||
*
|
||
* var arrays = _.times(2, _.stubArray);
|
||
*
|
||
* console.log(arrays);
|
||
* // => [[], []]
|
||
*
|
||
* console.log(arrays[0] === arrays[1]);
|
||
* // => false
|
||
*/
|
||
function stubArray() {
|
||
return [];
|
||
}
|
||
|
||
/**
|
||
* This method returns `false`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.13.0
|
||
* @category Util
|
||
* @returns {boolean} Returns `false`.
|
||
* @example
|
||
*
|
||
* _.times(2, _.stubFalse);
|
||
* // => [false, false]
|
||
*/
|
||
function stubFalse() {
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* This method returns a new empty object.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.13.0
|
||
* @category Util
|
||
* @returns {Object} Returns the new empty object.
|
||
* @example
|
||
*
|
||
* var objects = _.times(2, _.stubObject);
|
||
*
|
||
* console.log(objects);
|
||
* // => [{}, {}]
|
||
*
|
||
* console.log(objects[0] === objects[1]);
|
||
* // => false
|
||
*/
|
||
function stubObject() {
|
||
return {};
|
||
}
|
||
|
||
/**
|
||
* This method returns an empty string.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.13.0
|
||
* @category Util
|
||
* @returns {string} Returns the empty string.
|
||
* @example
|
||
*
|
||
* _.times(2, _.stubString);
|
||
* // => ['', '']
|
||
*/
|
||
function stubString() {
|
||
return '';
|
||
}
|
||
|
||
/**
|
||
* This method returns `true`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.13.0
|
||
* @category Util
|
||
* @returns {boolean} Returns `true`.
|
||
* @example
|
||
*
|
||
* _.times(2, _.stubTrue);
|
||
* // => [true, true]
|
||
*/
|
||
function stubTrue() {
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* Invokes the iteratee `n` times, returning an array of the results of
|
||
* each invocation. The iteratee is invoked with one argument; (index).
|
||
*
|
||
* @static
|
||
* @since 0.1.0
|
||
* @memberOf _
|
||
* @category Util
|
||
* @param {number} n The number of times to invoke `iteratee`.
|
||
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
|
||
* @returns {Array} Returns the array of results.
|
||
* @example
|
||
*
|
||
* _.times(3, String);
|
||
* // => ['0', '1', '2']
|
||
*
|
||
* _.times(4, _.constant(0));
|
||
* // => [0, 0, 0, 0]
|
||
*/
|
||
function times(n, iteratee) {
|
||
n = toInteger(n);
|
||
if (n < 1 || n > MAX_SAFE_INTEGER) {
|
||
return [];
|
||
}
|
||
var index = MAX_ARRAY_LENGTH,
|
||
length = nativeMin(n, MAX_ARRAY_LENGTH);
|
||
|
||
iteratee = getIteratee(iteratee);
|
||
n -= MAX_ARRAY_LENGTH;
|
||
|
||
var result = baseTimes(length, iteratee);
|
||
while (++index < n) {
|
||
iteratee(index);
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Converts `value` to a property path array.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category Util
|
||
* @param {*} value The value to convert.
|
||
* @returns {Array} Returns the new property path array.
|
||
* @example
|
||
*
|
||
* _.toPath('a.b.c');
|
||
* // => ['a', 'b', 'c']
|
||
*
|
||
* _.toPath('a[0].b.c');
|
||
* // => ['a', '0', 'b', 'c']
|
||
*/
|
||
function toPath(value) {
|
||
if (isArray(value)) {
|
||
return arrayMap(value, toKey);
|
||
}
|
||
return isSymbol(value) ? [value] : copyArray(stringToPath(value));
|
||
}
|
||
|
||
/**
|
||
* Generates a unique ID. If `prefix` is given, the ID is appended to it.
|
||
*
|
||
* @static
|
||
* @since 0.1.0
|
||
* @memberOf _
|
||
* @category Util
|
||
* @param {string} [prefix=''] The value to prefix the ID with.
|
||
* @returns {string} Returns the unique ID.
|
||
* @example
|
||
*
|
||
* _.uniqueId('contact_');
|
||
* // => 'contact_104'
|
||
*
|
||
* _.uniqueId();
|
||
* // => '105'
|
||
*/
|
||
function uniqueId(prefix) {
|
||
var id = ++idCounter;
|
||
return toString(prefix) + id;
|
||
}
|
||
|
||
/*------------------------------------------------------------------------*/
|
||
|
||
/**
|
||
* Adds two numbers.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 3.4.0
|
||
* @category Math
|
||
* @param {number} augend The first number in an addition.
|
||
* @param {number} addend The second number in an addition.
|
||
* @returns {number} Returns the total.
|
||
* @example
|
||
*
|
||
* _.add(6, 4);
|
||
* // => 10
|
||
*/
|
||
var add = createMathOperation(function(augend, addend) {
|
||
return augend + addend;
|
||
}, 0);
|
||
|
||
/**
|
||
* Computes `number` rounded up to `precision`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 3.10.0
|
||
* @category Math
|
||
* @param {number} number The number to round up.
|
||
* @param {number} [precision=0] The precision to round up to.
|
||
* @returns {number} Returns the rounded up number.
|
||
* @example
|
||
*
|
||
* _.ceil(4.006);
|
||
* // => 5
|
||
*
|
||
* _.ceil(6.004, 2);
|
||
* // => 6.01
|
||
*
|
||
* _.ceil(6040, -2);
|
||
* // => 6100
|
||
*/
|
||
var ceil = createRound('ceil');
|
||
|
||
/**
|
||
* Divide two numbers.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.7.0
|
||
* @category Math
|
||
* @param {number} dividend The first number in a division.
|
||
* @param {number} divisor The second number in a division.
|
||
* @returns {number} Returns the quotient.
|
||
* @example
|
||
*
|
||
* _.divide(6, 4);
|
||
* // => 1.5
|
||
*/
|
||
var divide = createMathOperation(function(dividend, divisor) {
|
||
return dividend / divisor;
|
||
}, 1);
|
||
|
||
/**
|
||
* Computes `number` rounded down to `precision`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 3.10.0
|
||
* @category Math
|
||
* @param {number} number The number to round down.
|
||
* @param {number} [precision=0] The precision to round down to.
|
||
* @returns {number} Returns the rounded down number.
|
||
* @example
|
||
*
|
||
* _.floor(4.006);
|
||
* // => 4
|
||
*
|
||
* _.floor(0.046, 2);
|
||
* // => 0.04
|
||
*
|
||
* _.floor(4060, -2);
|
||
* // => 4000
|
||
*/
|
||
var floor = createRound('floor');
|
||
|
||
/**
|
||
* Computes the maximum value of `array`. If `array` is empty or falsey,
|
||
* `undefined` is returned.
|
||
*
|
||
* @static
|
||
* @since 0.1.0
|
||
* @memberOf _
|
||
* @category Math
|
||
* @param {Array} array The array to iterate over.
|
||
* @returns {*} Returns the maximum value.
|
||
* @example
|
||
*
|
||
* _.max([4, 2, 8, 6]);
|
||
* // => 8
|
||
*
|
||
* _.max([]);
|
||
* // => undefined
|
||
*/
|
||
function max(array) {
|
||
return (array && array.length)
|
||
? baseExtremum(array, identity, baseGt)
|
||
: undefined;
|
||
}
|
||
|
||
/**
|
||
* This method is like `_.max` except that it accepts `iteratee` which is
|
||
* invoked for each element in `array` to generate the criterion by which
|
||
* the value is ranked. The iteratee is invoked with one argument: (value).
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category Math
|
||
* @param {Array} array The array to iterate over.
|
||
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
|
||
* @returns {*} Returns the maximum value.
|
||
* @example
|
||
*
|
||
* var objects = [{ 'n': 1 }, { 'n': 2 }];
|
||
*
|
||
* _.maxBy(objects, function(o) { return o.n; });
|
||
* // => { 'n': 2 }
|
||
*
|
||
* // The `_.property` iteratee shorthand.
|
||
* _.maxBy(objects, 'n');
|
||
* // => { 'n': 2 }
|
||
*/
|
||
function maxBy(array, iteratee) {
|
||
return (array && array.length)
|
||
? baseExtremum(array, getIteratee(iteratee, 2), baseGt)
|
||
: undefined;
|
||
}
|
||
|
||
/**
|
||
* Computes the mean of the values in `array`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category Math
|
||
* @param {Array} array The array to iterate over.
|
||
* @returns {number} Returns the mean.
|
||
* @example
|
||
*
|
||
* _.mean([4, 2, 8, 6]);
|
||
* // => 5
|
||
*/
|
||
function mean(array) {
|
||
return baseMean(array, identity);
|
||
}
|
||
|
||
/**
|
||
* This method is like `_.mean` except that it accepts `iteratee` which is
|
||
* invoked for each element in `array` to generate the value to be averaged.
|
||
* The iteratee is invoked with one argument: (value).
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.7.0
|
||
* @category Math
|
||
* @param {Array} array The array to iterate over.
|
||
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
|
||
* @returns {number} Returns the mean.
|
||
* @example
|
||
*
|
||
* var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
|
||
*
|
||
* _.meanBy(objects, function(o) { return o.n; });
|
||
* // => 5
|
||
*
|
||
* // The `_.property` iteratee shorthand.
|
||
* _.meanBy(objects, 'n');
|
||
* // => 5
|
||
*/
|
||
function meanBy(array, iteratee) {
|
||
return baseMean(array, getIteratee(iteratee, 2));
|
||
}
|
||
|
||
/**
|
||
* Computes the minimum value of `array`. If `array` is empty or falsey,
|
||
* `undefined` is returned.
|
||
*
|
||
* @static
|
||
* @since 0.1.0
|
||
* @memberOf _
|
||
* @category Math
|
||
* @param {Array} array The array to iterate over.
|
||
* @returns {*} Returns the minimum value.
|
||
* @example
|
||
*
|
||
* _.min([4, 2, 8, 6]);
|
||
* // => 2
|
||
*
|
||
* _.min([]);
|
||
* // => undefined
|
||
*/
|
||
function min(array) {
|
||
return (array && array.length)
|
||
? baseExtremum(array, identity, baseLt)
|
||
: undefined;
|
||
}
|
||
|
||
/**
|
||
* This method is like `_.min` except that it accepts `iteratee` which is
|
||
* invoked for each element in `array` to generate the criterion by which
|
||
* the value is ranked. The iteratee is invoked with one argument: (value).
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category Math
|
||
* @param {Array} array The array to iterate over.
|
||
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
|
||
* @returns {*} Returns the minimum value.
|
||
* @example
|
||
*
|
||
* var objects = [{ 'n': 1 }, { 'n': 2 }];
|
||
*
|
||
* _.minBy(objects, function(o) { return o.n; });
|
||
* // => { 'n': 1 }
|
||
*
|
||
* // The `_.property` iteratee shorthand.
|
||
* _.minBy(objects, 'n');
|
||
* // => { 'n': 1 }
|
||
*/
|
||
function minBy(array, iteratee) {
|
||
return (array && array.length)
|
||
? baseExtremum(array, getIteratee(iteratee, 2), baseLt)
|
||
: undefined;
|
||
}
|
||
|
||
/**
|
||
* Multiply two numbers.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.7.0
|
||
* @category Math
|
||
* @param {number} multiplier The first number in a multiplication.
|
||
* @param {number} multiplicand The second number in a multiplication.
|
||
* @returns {number} Returns the product.
|
||
* @example
|
||
*
|
||
* _.multiply(6, 4);
|
||
* // => 24
|
||
*/
|
||
var multiply = createMathOperation(function(multiplier, multiplicand) {
|
||
return multiplier * multiplicand;
|
||
}, 1);
|
||
|
||
/**
|
||
* Computes `number` rounded to `precision`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 3.10.0
|
||
* @category Math
|
||
* @param {number} number The number to round.
|
||
* @param {number} [precision=0] The precision to round to.
|
||
* @returns {number} Returns the rounded number.
|
||
* @example
|
||
*
|
||
* _.round(4.006);
|
||
* // => 4
|
||
*
|
||
* _.round(4.006, 2);
|
||
* // => 4.01
|
||
*
|
||
* _.round(4060, -2);
|
||
* // => 4100
|
||
*/
|
||
var round = createRound('round');
|
||
|
||
/**
|
||
* Subtract two numbers.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category Math
|
||
* @param {number} minuend The first number in a subtraction.
|
||
* @param {number} subtrahend The second number in a subtraction.
|
||
* @returns {number} Returns the difference.
|
||
* @example
|
||
*
|
||
* _.subtract(6, 4);
|
||
* // => 2
|
||
*/
|
||
var subtract = createMathOperation(function(minuend, subtrahend) {
|
||
return minuend - subtrahend;
|
||
}, 0);
|
||
|
||
/**
|
||
* Computes the sum of the values in `array`.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 3.4.0
|
||
* @category Math
|
||
* @param {Array} array The array to iterate over.
|
||
* @returns {number} Returns the sum.
|
||
* @example
|
||
*
|
||
* _.sum([4, 2, 8, 6]);
|
||
* // => 20
|
||
*/
|
||
function sum(array) {
|
||
return (array && array.length)
|
||
? baseSum(array, identity)
|
||
: 0;
|
||
}
|
||
|
||
/**
|
||
* This method is like `_.sum` except that it accepts `iteratee` which is
|
||
* invoked for each element in `array` to generate the value to be summed.
|
||
* The iteratee is invoked with one argument: (value).
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @since 4.0.0
|
||
* @category Math
|
||
* @param {Array} array The array to iterate over.
|
||
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
|
||
* @returns {number} Returns the sum.
|
||
* @example
|
||
*
|
||
* var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
|
||
*
|
||
* _.sumBy(objects, function(o) { return o.n; });
|
||
* // => 20
|
||
*
|
||
* // The `_.property` iteratee shorthand.
|
||
* _.sumBy(objects, 'n');
|
||
* // => 20
|
||
*/
|
||
function sumBy(array, iteratee) {
|
||
return (array && array.length)
|
||
? baseSum(array, getIteratee(iteratee, 2))
|
||
: 0;
|
||
}
|
||
|
||
/*------------------------------------------------------------------------*/
|
||
|
||
// Add methods that return wrapped values in chain sequences.
|
||
lodash.after = after;
|
||
lodash.ary = ary;
|
||
lodash.assign = assign;
|
||
lodash.assignIn = assignIn;
|
||
lodash.assignInWith = assignInWith;
|
||
lodash.assignWith = assignWith;
|
||
lodash.at = at;
|
||
lodash.before = before;
|
||
lodash.bind = bind;
|
||
lodash.bindAll = bindAll;
|
||
lodash.bindKey = bindKey;
|
||
lodash.castArray = castArray;
|
||
lodash.chain = chain;
|
||
lodash.chunk = chunk;
|
||
lodash.compact = compact;
|
||
lodash.concat = concat;
|
||
lodash.cond = cond;
|
||
lodash.conforms = conforms;
|
||
lodash.constant = constant;
|
||
lodash.countBy = countBy;
|
||
lodash.create = create;
|
||
lodash.curry = curry;
|
||
lodash.curryRight = curryRight;
|
||
lodash.debounce = debounce;
|
||
lodash.defaults = defaults;
|
||
lodash.defaultsDeep = defaultsDeep;
|
||
lodash.defer = defer;
|
||
lodash.delay = delay;
|
||
lodash.difference = difference;
|
||
lodash.differenceBy = differenceBy;
|
||
lodash.differenceWith = differenceWith;
|
||
lodash.drop = drop;
|
||
lodash.dropRight = dropRight;
|
||
lodash.dropRightWhile = dropRightWhile;
|
||
lodash.dropWhile = dropWhile;
|
||
lodash.fill = fill;
|
||
lodash.filter = filter;
|
||
lodash.flatMap = flatMap;
|
||
lodash.flatMapDeep = flatMapDeep;
|
||
lodash.flatMapDepth = flatMapDepth;
|
||
lodash.flatten = flatten;
|
||
lodash.flattenDeep = flattenDeep;
|
||
lodash.flattenDepth = flattenDepth;
|
||
lodash.flip = flip;
|
||
lodash.flow = flow;
|
||
lodash.flowRight = flowRight;
|
||
lodash.fromPairs = fromPairs;
|
||
lodash.functions = functions;
|
||
lodash.functionsIn = functionsIn;
|
||
lodash.groupBy = groupBy;
|
||
lodash.initial = initial;
|
||
lodash.intersection = intersection;
|
||
lodash.intersectionBy = intersectionBy;
|
||
lodash.intersectionWith = intersectionWith;
|
||
lodash.invert = invert;
|
||
lodash.invertBy = invertBy;
|
||
lodash.invokeMap = invokeMap;
|
||
lodash.iteratee = iteratee;
|
||
lodash.keyBy = keyBy;
|
||
lodash.keys = keys;
|
||
lodash.keysIn = keysIn;
|
||
lodash.map = map;
|
||
lodash.mapKeys = mapKeys;
|
||
lodash.mapValues = mapValues;
|
||
lodash.matches = matches;
|
||
lodash.matchesProperty = matchesProperty;
|
||
lodash.memoize = memoize;
|
||
lodash.merge = merge;
|
||
lodash.mergeWith = mergeWith;
|
||
lodash.method = method;
|
||
lodash.methodOf = methodOf;
|
||
lodash.mixin = mixin;
|
||
lodash.negate = negate;
|
||
lodash.nthArg = nthArg;
|
||
lodash.omit = omit;
|
||
lodash.omitBy = omitBy;
|
||
lodash.once = once;
|
||
lodash.orderBy = orderBy;
|
||
lodash.over = over;
|
||
lodash.overArgs = overArgs;
|
||
lodash.overEvery = overEvery;
|
||
lodash.overSome = overSome;
|
||
lodash.partial = partial;
|
||
lodash.partialRight = partialRight;
|
||
lodash.partition = partition;
|
||
lodash.pick = pick;
|
||
lodash.pickBy = pickBy;
|
||
lodash.property = property;
|
||
lodash.propertyOf = propertyOf;
|
||
lodash.pull = pull;
|
||
lodash.pullAll = pullAll;
|
||
lodash.pullAllBy = pullAllBy;
|
||
lodash.pullAllWith = pullAllWith;
|
||
lodash.pullAt = pullAt;
|
||
lodash.range = range;
|
||
lodash.rangeRight = rangeRight;
|
||
lodash.rearg = rearg;
|
||
lodash.reject = reject;
|
||
lodash.remove = remove;
|
||
lodash.rest = rest;
|
||
lodash.reverse = reverse;
|
||
lodash.sampleSize = sampleSize;
|
||
lodash.set = set;
|
||
lodash.setWith = setWith;
|
||
lodash.shuffle = shuffle;
|
||
lodash.slice = slice;
|
||
lodash.sortBy = sortBy;
|
||
lodash.sortedUniq = sortedUniq;
|
||
lodash.sortedUniqBy = sortedUniqBy;
|
||
lodash.split = split;
|
||
lodash.spread = spread;
|
||
lodash.tail = tail;
|
||
lodash.take = take;
|
||
lodash.takeRight = takeRight;
|
||
lodash.takeRightWhile = takeRightWhile;
|
||
lodash.takeWhile = takeWhile;
|
||
lodash.tap = tap;
|
||
lodash.throttle = throttle;
|
||
lodash.thru = thru;
|
||
lodash.toArray = toArray;
|
||
lodash.toPairs = toPairs;
|
||
lodash.toPairsIn = toPairsIn;
|
||
lodash.toPath = toPath;
|
||
lodash.toPlainObject = toPlainObject;
|
||
lodash.transform = transform;
|
||
lodash.unary = unary;
|
||
lodash.union = union;
|
||
lodash.unionBy = unionBy;
|
||
lodash.unionWith = unionWith;
|
||
lodash.uniq = uniq;
|
||
lodash.uniqBy = uniqBy;
|
||
lodash.uniqWith = uniqWith;
|
||
lodash.unset = unset;
|
||
lodash.unzip = unzip;
|
||
lodash.unzipWith = unzipWith;
|
||
lodash.update = update;
|
||
lodash.updateWith = updateWith;
|
||
lodash.values = values;
|
||
lodash.valuesIn = valuesIn;
|
||
lodash.without = without;
|
||
lodash.words = words;
|
||
lodash.wrap = wrap;
|
||
lodash.xor = xor;
|
||
lodash.xorBy = xorBy;
|
||
lodash.xorWith = xorWith;
|
||
lodash.zip = zip;
|
||
lodash.zipObject = zipObject;
|
||
lodash.zipObjectDeep = zipObjectDeep;
|
||
lodash.zipWith = zipWith;
|
||
|
||
// Add aliases.
|
||
lodash.entries = toPairs;
|
||
lodash.entriesIn = toPairsIn;
|
||
lodash.extend = assignIn;
|
||
lodash.extendWith = assignInWith;
|
||
|
||
// Add methods to `lodash.prototype`.
|
||
mixin(lodash, lodash);
|
||
|
||
/*------------------------------------------------------------------------*/
|
||
|
||
// Add methods that return unwrapped values in chain sequences.
|
||
lodash.add = add;
|
||
lodash.attempt = attempt;
|
||
lodash.camelCase = camelCase;
|
||
lodash.capitalize = capitalize;
|
||
lodash.ceil = ceil;
|
||
lodash.clamp = clamp;
|
||
lodash.clone = clone;
|
||
lodash.cloneDeep = cloneDeep;
|
||
lodash.cloneDeepWith = cloneDeepWith;
|
||
lodash.cloneWith = cloneWith;
|
||
lodash.conformsTo = conformsTo;
|
||
lodash.deburr = deburr;
|
||
lodash.defaultTo = defaultTo;
|
||
lodash.divide = divide;
|
||
lodash.endsWith = endsWith;
|
||
lodash.eq = eq;
|
||
lodash.escape = escape;
|
||
lodash.escapeRegExp = escapeRegExp;
|
||
lodash.every = every;
|
||
lodash.find = find;
|
||
lodash.findIndex = findIndex;
|
||
lodash.findKey = findKey;
|
||
lodash.findLast = findLast;
|
||
lodash.findLastIndex = findLastIndex;
|
||
lodash.findLastKey = findLastKey;
|
||
lodash.floor = floor;
|
||
lodash.forEach = forEach;
|
||
lodash.forEachRight = forEachRight;
|
||
lodash.forIn = forIn;
|
||
lodash.forInRight = forInRight;
|
||
lodash.forOwn = forOwn;
|
||
lodash.forOwnRight = forOwnRight;
|
||
lodash.get = get;
|
||
lodash.gt = gt;
|
||
lodash.gte = gte;
|
||
lodash.has = has;
|
||
lodash.hasIn = hasIn;
|
||
lodash.head = head;
|
||
lodash.identity = identity;
|
||
lodash.includes = includes;
|
||
lodash.indexOf = indexOf;
|
||
lodash.inRange = inRange;
|
||
lodash.invoke = invoke;
|
||
lodash.isArguments = isArguments;
|
||
lodash.isArray = isArray;
|
||
lodash.isArrayBuffer = isArrayBuffer;
|
||
lodash.isArrayLike = isArrayLike;
|
||
lodash.isArrayLikeObject = isArrayLikeObject;
|
||
lodash.isBoolean = isBoolean;
|
||
lodash.isBuffer = isBuffer;
|
||
lodash.isDate = isDate;
|
||
lodash.isElement = isElement;
|
||
lodash.isEmpty = isEmpty;
|
||
lodash.isEqual = isEqual;
|
||
lodash.isEqualWith = isEqualWith;
|
||
lodash.isError = isError;
|
||
lodash.isFinite = isFinite;
|
||
lodash.isFunction = isFunction;
|
||
lodash.isInteger = isInteger;
|
||
lodash.isLength = isLength;
|
||
lodash.isMap = isMap;
|
||
lodash.isMatch = isMatch;
|
||
lodash.isMatchWith = isMatchWith;
|
||
lodash.isNaN = isNaN;
|
||
lodash.isNative = isNative;
|
||
lodash.isNil = isNil;
|
||
lodash.isNull = isNull;
|
||
lodash.isNumber = isNumber;
|
||
lodash.isObject = isObject;
|
||
lodash.isObjectLike = isObjectLike;
|
||
lodash.isPlainObject = isPlainObject;
|
||
lodash.isRegExp = isRegExp;
|
||
lodash.isSafeInteger = isSafeInteger;
|
||
lodash.isSet = isSet;
|
||
lodash.isString = isString;
|
||
lodash.isSymbol = isSymbol;
|
||
lodash.isTypedArray = isTypedArray;
|
||
lodash.isUndefined = isUndefined;
|
||
lodash.isWeakMap = isWeakMap;
|
||
lodash.isWeakSet = isWeakSet;
|
||
lodash.join = join;
|
||
lodash.kebabCase = kebabCase;
|
||
lodash.last = last;
|
||
lodash.lastIndexOf = lastIndexOf;
|
||
lodash.lowerCase = lowerCase;
|
||
lodash.lowerFirst = lowerFirst;
|
||
lodash.lt = lt;
|
||
lodash.lte = lte;
|
||
lodash.max = max;
|
||
lodash.maxBy = maxBy;
|
||
lodash.mean = mean;
|
||
lodash.meanBy = meanBy;
|
||
lodash.min = min;
|
||
lodash.minBy = minBy;
|
||
lodash.stubArray = stubArray;
|
||
lodash.stubFalse = stubFalse;
|
||
lodash.stubObject = stubObject;
|
||
lodash.stubString = stubString;
|
||
lodash.stubTrue = stubTrue;
|
||
lodash.multiply = multiply;
|
||
lodash.nth = nth;
|
||
lodash.noConflict = noConflict;
|
||
lodash.noop = noop;
|
||
lodash.now = now;
|
||
lodash.pad = pad;
|
||
lodash.padEnd = padEnd;
|
||
lodash.padStart = padStart;
|
||
lodash.parseInt = parseInt;
|
||
lodash.random = random;
|
||
lodash.reduce = reduce;
|
||
lodash.reduceRight = reduceRight;
|
||
lodash.repeat = repeat;
|
||
lodash.replace = replace;
|
||
lodash.result = result;
|
||
lodash.round = round;
|
||
lodash.runInContext = runInContext;
|
||
lodash.sample = sample;
|
||
lodash.size = size;
|
||
lodash.snakeCase = snakeCase;
|
||
lodash.some = some;
|
||
lodash.sortedIndex = sortedIndex;
|
||
lodash.sortedIndexBy = sortedIndexBy;
|
||
lodash.sortedIndexOf = sortedIndexOf;
|
||
lodash.sortedLastIndex = sortedLastIndex;
|
||
lodash.sortedLastIndexBy = sortedLastIndexBy;
|
||
lodash.sortedLastIndexOf = sortedLastIndexOf;
|
||
lodash.startCase = startCase;
|
||
lodash.startsWith = startsWith;
|
||
lodash.subtract = subtract;
|
||
lodash.sum = sum;
|
||
lodash.sumBy = sumBy;
|
||
lodash.template = template;
|
||
lodash.times = times;
|
||
lodash.toFinite = toFinite;
|
||
lodash.toInteger = toInteger;
|
||
lodash.toLength = toLength;
|
||
lodash.toLower = toLower;
|
||
lodash.toNumber = toNumber;
|
||
lodash.toSafeInteger = toSafeInteger;
|
||
lodash.toString = toString;
|
||
lodash.toUpper = toUpper;
|
||
lodash.trim = trim;
|
||
lodash.trimEnd = trimEnd;
|
||
lodash.trimStart = trimStart;
|
||
lodash.truncate = truncate;
|
||
lodash.unescape = unescape;
|
||
lodash.uniqueId = uniqueId;
|
||
lodash.upperCase = upperCase;
|
||
lodash.upperFirst = upperFirst;
|
||
|
||
// Add aliases.
|
||
lodash.each = forEach;
|
||
lodash.eachRight = forEachRight;
|
||
lodash.first = head;
|
||
|
||
mixin(lodash, (function() {
|
||
var source = {};
|
||
baseForOwn(lodash, function(func, methodName) {
|
||
if (!hasOwnProperty.call(lodash.prototype, methodName)) {
|
||
source[methodName] = func;
|
||
}
|
||
});
|
||
return source;
|
||
}()), { 'chain': false });
|
||
|
||
/*------------------------------------------------------------------------*/
|
||
|
||
/**
|
||
* The semantic version number.
|
||
*
|
||
* @static
|
||
* @memberOf _
|
||
* @type {string}
|
||
*/
|
||
lodash.VERSION = VERSION;
|
||
|
||
// Assign default placeholders.
|
||
arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function(methodName) {
|
||
lodash[methodName].placeholder = lodash;
|
||
});
|
||
|
||
// Add `LazyWrapper` methods for `_.drop` and `_.take` variants.
|
||
arrayEach(['drop', 'take'], function(methodName, index) {
|
||
LazyWrapper.prototype[methodName] = function(n) {
|
||
var filtered = this.__filtered__;
|
||
if (filtered && !index) {
|
||
return new LazyWrapper(this);
|
||
}
|
||
n = n === undefined ? 1 : nativeMax(toInteger(n), 0);
|
||
|
||
var result = this.clone();
|
||
if (filtered) {
|
||
result.__takeCount__ = nativeMin(n, result.__takeCount__);
|
||
} else {
|
||
result.__views__.push({
|
||
'size': nativeMin(n, MAX_ARRAY_LENGTH),
|
||
'type': methodName + (result.__dir__ < 0 ? 'Right' : '')
|
||
});
|
||
}
|
||
return result;
|
||
};
|
||
|
||
LazyWrapper.prototype[methodName + 'Right'] = function(n) {
|
||
return this.reverse()[methodName](n).reverse();
|
||
};
|
||
});
|
||
|
||
// Add `LazyWrapper` methods that accept an `iteratee` value.
|
||
arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) {
|
||
var type = index + 1,
|
||
isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG;
|
||
|
||
LazyWrapper.prototype[methodName] = function(iteratee) {
|
||
var result = this.clone();
|
||
result.__iteratees__.push({
|
||
'iteratee': getIteratee(iteratee, 3),
|
||
'type': type
|
||
});
|
||
result.__filtered__ = result.__filtered__ || isFilter;
|
||
return result;
|
||
};
|
||
});
|
||
|
||
// Add `LazyWrapper` methods for `_.head` and `_.last`.
|
||
arrayEach(['head', 'last'], function(methodName, index) {
|
||
var takeName = 'take' + (index ? 'Right' : '');
|
||
|
||
LazyWrapper.prototype[methodName] = function() {
|
||
return this[takeName](1).value()[0];
|
||
};
|
||
});
|
||
|
||
// Add `LazyWrapper` methods for `_.initial` and `_.tail`.
|
||
arrayEach(['initial', 'tail'], function(methodName, index) {
|
||
var dropName = 'drop' + (index ? '' : 'Right');
|
||
|
||
LazyWrapper.prototype[methodName] = function() {
|
||
return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1);
|
||
};
|
||
});
|
||
|
||
LazyWrapper.prototype.compact = function() {
|
||
return this.filter(identity);
|
||
};
|
||
|
||
LazyWrapper.prototype.find = function(predicate) {
|
||
return this.filter(predicate).head();
|
||
};
|
||
|
||
LazyWrapper.prototype.findLast = function(predicate) {
|
||
return this.reverse().find(predicate);
|
||
};
|
||
|
||
LazyWrapper.prototype.invokeMap = baseRest(function(path, args) {
|
||
if (typeof path == 'function') {
|
||
return new LazyWrapper(this);
|
||
}
|
||
return this.map(function(value) {
|
||
return baseInvoke(value, path, args);
|
||
});
|
||
});
|
||
|
||
LazyWrapper.prototype.reject = function(predicate) {
|
||
return this.filter(negate(getIteratee(predicate)));
|
||
};
|
||
|
||
LazyWrapper.prototype.slice = function(start, end) {
|
||
start = toInteger(start);
|
||
|
||
var result = this;
|
||
if (result.__filtered__ && (start > 0 || end < 0)) {
|
||
return new LazyWrapper(result);
|
||
}
|
||
if (start < 0) {
|
||
result = result.takeRight(-start);
|
||
} else if (start) {
|
||
result = result.drop(start);
|
||
}
|
||
if (end !== undefined) {
|
||
end = toInteger(end);
|
||
result = end < 0 ? result.dropRight(-end) : result.take(end - start);
|
||
}
|
||
return result;
|
||
};
|
||
|
||
LazyWrapper.prototype.takeRightWhile = function(predicate) {
|
||
return this.reverse().takeWhile(predicate).reverse();
|
||
};
|
||
|
||
LazyWrapper.prototype.toArray = function() {
|
||
return this.take(MAX_ARRAY_LENGTH);
|
||
};
|
||
|
||
// Add `LazyWrapper` methods to `lodash.prototype`.
|
||
baseForOwn(LazyWrapper.prototype, function(func, methodName) {
|
||
var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName),
|
||
isTaker = /^(?:head|last)$/.test(methodName),
|
||
lodashFunc = lodash[isTaker ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName],
|
||
retUnwrapped = isTaker || /^find/.test(methodName);
|
||
|
||
if (!lodashFunc) {
|
||
return;
|
||
}
|
||
lodash.prototype[methodName] = function() {
|
||
var value = this.__wrapped__,
|
||
args = isTaker ? [1] : arguments,
|
||
isLazy = value instanceof LazyWrapper,
|
||
iteratee = args[0],
|
||
useLazy = isLazy || isArray(value);
|
||
|
||
var interceptor = function(value) {
|
||
var result = lodashFunc.apply(lodash, arrayPush([value], args));
|
||
return (isTaker && chainAll) ? result[0] : result;
|
||
};
|
||
|
||
if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) {
|
||
// Avoid lazy use if the iteratee has a "length" value other than `1`.
|
||
isLazy = useLazy = false;
|
||
}
|
||
var chainAll = this.__chain__,
|
||
isHybrid = !!this.__actions__.length,
|
||
isUnwrapped = retUnwrapped && !chainAll,
|
||
onlyLazy = isLazy && !isHybrid;
|
||
|
||
if (!retUnwrapped && useLazy) {
|
||
value = onlyLazy ? value : new LazyWrapper(this);
|
||
var result = func.apply(value, args);
|
||
result.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined });
|
||
return new LodashWrapper(result, chainAll);
|
||
}
|
||
if (isUnwrapped && onlyLazy) {
|
||
return func.apply(this, args);
|
||
}
|
||
result = this.thru(interceptor);
|
||
return isUnwrapped ? (isTaker ? result.value()[0] : result.value()) : result;
|
||
};
|
||
});
|
||
|
||
// Add `Array` methods to `lodash.prototype`.
|
||
arrayEach(['pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
|
||
var func = arrayProto[methodName],
|
||
chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',
|
||
retUnwrapped = /^(?:pop|shift)$/.test(methodName);
|
||
|
||
lodash.prototype[methodName] = function() {
|
||
var args = arguments;
|
||
if (retUnwrapped && !this.__chain__) {
|
||
var value = this.value();
|
||
return func.apply(isArray(value) ? value : [], args);
|
||
}
|
||
return this[chainName](function(value) {
|
||
return func.apply(isArray(value) ? value : [], args);
|
||
});
|
||
};
|
||
});
|
||
|
||
// Map minified method names to their real names.
|
||
baseForOwn(LazyWrapper.prototype, function(func, methodName) {
|
||
var lodashFunc = lodash[methodName];
|
||
if (lodashFunc) {
|
||
var key = (lodashFunc.name + ''),
|
||
names = realNames[key] || (realNames[key] = []);
|
||
|
||
names.push({ 'name': methodName, 'func': lodashFunc });
|
||
}
|
||
});
|
||
|
||
realNames[createHybrid(undefined, BIND_KEY_FLAG).name] = [{
|
||
'name': 'wrapper',
|
||
'func': undefined
|
||
}];
|
||
|
||
// Add methods to `LazyWrapper`.
|
||
LazyWrapper.prototype.clone = lazyClone;
|
||
LazyWrapper.prototype.reverse = lazyReverse;
|
||
LazyWrapper.prototype.value = lazyValue;
|
||
|
||
// Add chain sequence methods to the `lodash` wrapper.
|
||
lodash.prototype.at = wrapperAt;
|
||
lodash.prototype.chain = wrapperChain;
|
||
lodash.prototype.commit = wrapperCommit;
|
||
lodash.prototype.next = wrapperNext;
|
||
lodash.prototype.plant = wrapperPlant;
|
||
lodash.prototype.reverse = wrapperReverse;
|
||
lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue;
|
||
|
||
// Add lazy aliases.
|
||
lodash.prototype.first = lodash.prototype.head;
|
||
|
||
if (iteratorSymbol) {
|
||
lodash.prototype[iteratorSymbol] = wrapperToIterator;
|
||
}
|
||
return lodash;
|
||
}
|
||
|
||
/*--------------------------------------------------------------------------*/
|
||
|
||
// Export lodash.
|
||
var _ = runInContext();
|
||
|
||
// Some AMD build optimizers, like r.js, check for condition patterns like:
|
||
if (true) {
|
||
// Expose Lodash on the global object to prevent errors when Lodash is
|
||
// loaded by a script tag in the presence of an AMD loader.
|
||
// See http://requirejs.org/docs/errors.html#mismatch for more details.
|
||
// Use `_.noConflict` to remove Lodash from the global object.
|
||
root._ = _;
|
||
|
||
// Define as an anonymous module so, through path mapping, it can be
|
||
// referenced as the "underscore" module.
|
||
!(__WEBPACK_AMD_DEFINE_RESULT__ = function() {
|
||
return _;
|
||
}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
||
}
|
||
// Check for `exports` after `define` in case a build optimizer adds it.
|
||
else if (freeModule) {
|
||
// Export for Node.js.
|
||
(freeModule.exports = _)._ = _;
|
||
// Export for CommonJS support.
|
||
freeExports._ = _;
|
||
}
|
||
else {
|
||
// Export to the global object.
|
||
root._ = _;
|
||
}
|
||
}.call(this));
|
||
|
||
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0), __webpack_require__(35)(module)))
|
||
|
||
/***/ },
|
||
/* 142 */
|
||
/***/ function(module, exports) {
|
||
|
||
/**
|
||
* Helpers.
|
||
*/
|
||
|
||
var s = 1000;
|
||
var m = s * 60;
|
||
var h = m * 60;
|
||
var d = h * 24;
|
||
var y = d * 365.25;
|
||
|
||
/**
|
||
* Parse or format the given `val`.
|
||
*
|
||
* Options:
|
||
*
|
||
* - `long` verbose formatting [false]
|
||
*
|
||
* @param {String|Number} val
|
||
* @param {Object} options
|
||
* @return {String|Number}
|
||
* @api public
|
||
*/
|
||
|
||
module.exports = function(val, options){
|
||
options = options || {};
|
||
if ('string' == typeof val) return parse(val);
|
||
return options.long
|
||
? long(val)
|
||
: short(val);
|
||
};
|
||
|
||
/**
|
||
* Parse the given `str` and return milliseconds.
|
||
*
|
||
* @param {String} str
|
||
* @return {Number}
|
||
* @api private
|
||
*/
|
||
|
||
function parse(str) {
|
||
str = '' + str;
|
||
if (str.length > 10000) return;
|
||
var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(str);
|
||
if (!match) return;
|
||
var n = parseFloat(match[1]);
|
||
var type = (match[2] || 'ms').toLowerCase();
|
||
switch (type) {
|
||
case 'years':
|
||
case 'year':
|
||
case 'yrs':
|
||
case 'yr':
|
||
case 'y':
|
||
return n * y;
|
||
case 'days':
|
||
case 'day':
|
||
case 'd':
|
||
return n * d;
|
||
case 'hours':
|
||
case 'hour':
|
||
case 'hrs':
|
||
case 'hr':
|
||
case 'h':
|
||
return n * h;
|
||
case 'minutes':
|
||
case 'minute':
|
||
case 'mins':
|
||
case 'min':
|
||
case 'm':
|
||
return n * m;
|
||
case 'seconds':
|
||
case 'second':
|
||
case 'secs':
|
||
case 'sec':
|
||
case 's':
|
||
return n * s;
|
||
case 'milliseconds':
|
||
case 'millisecond':
|
||
case 'msecs':
|
||
case 'msec':
|
||
case 'ms':
|
||
return n;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Short format for `ms`.
|
||
*
|
||
* @param {Number} ms
|
||
* @return {String}
|
||
* @api private
|
||
*/
|
||
|
||
function short(ms) {
|
||
if (ms >= d) return Math.round(ms / d) + 'd';
|
||
if (ms >= h) return Math.round(ms / h) + 'h';
|
||
if (ms >= m) return Math.round(ms / m) + 'm';
|
||
if (ms >= s) return Math.round(ms / s) + 's';
|
||
return ms + 'ms';
|
||
}
|
||
|
||
/**
|
||
* Long format for `ms`.
|
||
*
|
||
* @param {Number} ms
|
||
* @return {String}
|
||
* @api private
|
||
*/
|
||
|
||
function long(ms) {
|
||
return plural(ms, d, 'day')
|
||
|| plural(ms, h, 'hour')
|
||
|| plural(ms, m, 'minute')
|
||
|| plural(ms, s, 'second')
|
||
|| ms + ' ms';
|
||
}
|
||
|
||
/**
|
||
* Pluralization helper.
|
||
*/
|
||
|
||
function plural(ms, n, name) {
|
||
if (ms < n) return;
|
||
if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name;
|
||
return Math.ceil(ms / n) + ' ' + name + 's';
|
||
}
|
||
|
||
|
||
/***/ },
|
||
/* 143 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
'use strict';
|
||
|
||
const Counter = __webpack_require__(120);
|
||
|
||
class CounterIndex {
|
||
constructor(id) {
|
||
this._counter = new Counter(id);
|
||
}
|
||
|
||
get() {
|
||
return this._counter;
|
||
}
|
||
|
||
updateIndex(oplog, added) {
|
||
if(this._counter) {
|
||
added.filter((f) => f && f.payload.op === 'COUNTER')
|
||
.map((f) => Counter.from(f.payload.value))
|
||
.forEach((f) => this._counter.merge(f))
|
||
}
|
||
}
|
||
}
|
||
|
||
module.exports = CounterIndex;
|
||
|
||
|
||
/***/ },
|
||
/* 144 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
'use strict';
|
||
|
||
const EventIndex = __webpack_require__(61);
|
||
|
||
class FeedIndex extends EventIndex {
|
||
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
|
||
} else if(item.payload.op === 'DEL') {
|
||
delete this._index[item.payload.value];
|
||
}
|
||
}
|
||
return handled;
|
||
}, []);
|
||
}
|
||
}
|
||
|
||
module.exports = FeedIndex;
|
||
|
||
|
||
/***/ },
|
||
/* 145 */
|
||
/***/ function(module, exports) {
|
||
|
||
"use strict";
|
||
'use strict';
|
||
|
||
class KeyValueIndex {
|
||
constructor() {
|
||
this._index = {};
|
||
}
|
||
|
||
get(key) {
|
||
return this._index[key];
|
||
}
|
||
|
||
updateIndex(oplog, added) {
|
||
added.reverse().reduce((handled, item) => {
|
||
if(handled.indexOf(item.payload.key) === -1) {
|
||
handled.push(item.payload.key);
|
||
if(item.payload.op === 'PUT') {
|
||
this._index[item.payload.key] = item.payload.value
|
||
} else if(item.payload.op === 'DEL') {
|
||
delete this._index[item.payload.key];
|
||
}
|
||
}
|
||
return handled;
|
||
}, []);
|
||
}
|
||
}
|
||
|
||
module.exports = KeyValueIndex;
|
||
|
||
|
||
/***/ },
|
||
/* 146 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
'use strict';
|
||
|
||
const fs = __webpack_require__(60);
|
||
const path = __webpack_require__(63);
|
||
|
||
// const defaultFilepath = path.resolve('./orbit-db-cache.json');
|
||
// let filePath = defaultFilepath;
|
||
let filePath;
|
||
let cache = {};
|
||
|
||
class Cache {
|
||
static set(key, value) {
|
||
return new Promise((resolve, reject) => {
|
||
cache[key] = value;
|
||
if(filePath) {
|
||
fs.writeFile(filePath, JSON.stringify(cache, null, 2) + "\n", resolve);
|
||
} else {
|
||
resolve();
|
||
}
|
||
})
|
||
}
|
||
|
||
static get(key) {
|
||
return cache[key];
|
||
}
|
||
|
||
static loadCache(cacheFile) {
|
||
cache = {};
|
||
return new Promise((resolve, reject) => {
|
||
if(cacheFile) {
|
||
filePath = cacheFile;
|
||
fs.exists(cacheFile, (res) => {
|
||
if(res) {
|
||
cache = JSON.parse(fs.readFileSync(cacheFile));
|
||
resolve();
|
||
} else {
|
||
resolve();
|
||
}
|
||
});
|
||
} else {
|
||
resolve();
|
||
}
|
||
});
|
||
}
|
||
|
||
static reset() {
|
||
cache = {};
|
||
}
|
||
}
|
||
|
||
module.exports = Cache;
|
||
|
||
|
||
/***/ },
|
||
/* 147 */
|
||
/***/ function(module, exports) {
|
||
|
||
"use strict";
|
||
'use strict';
|
||
|
||
class Index {
|
||
constructor(id) {
|
||
this.id = id;
|
||
this._index = [];
|
||
}
|
||
|
||
get() {
|
||
return this._index;
|
||
}
|
||
|
||
updateIndex(oplog, entries) {
|
||
this._index = oplog.ops;
|
||
}
|
||
}
|
||
|
||
module.exports = Index;
|
||
|
||
|
||
/***/ },
|
||
/* 148 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
/* WEBPACK VAR INJECTION */(function(global) {/**
|
||
* JSON parse.
|
||
*
|
||
* @see Based on jQuery#parseJSON (MIT) and JSON2
|
||
* @api private
|
||
*/
|
||
|
||
var rvalidchars = /^[\],:{}\s]*$/;
|
||
var rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
|
||
var rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
|
||
var rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g;
|
||
var rtrimLeft = /^\s+/;
|
||
var rtrimRight = /\s+$/;
|
||
|
||
module.exports = function parsejson(data) {
|
||
if ('string' != typeof data || !data) {
|
||
return null;
|
||
}
|
||
|
||
data = data.replace(rtrimLeft, '').replace(rtrimRight, '');
|
||
|
||
// Attempt to parse using the native JSON parser first
|
||
if (global.JSON && JSON.parse) {
|
||
return JSON.parse(data);
|
||
}
|
||
|
||
if (rvalidchars.test(data.replace(rvalidescape, '@')
|
||
.replace(rvalidtokens, ']')
|
||
.replace(rvalidbraces, ''))) {
|
||
return (new Function('return ' + data))();
|
||
}
|
||
};
|
||
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
|
||
|
||
/***/ },
|
||
/* 149 */
|
||
/***/ function(module, exports) {
|
||
|
||
// shim for using process in browser
|
||
|
||
var process = module.exports = {};
|
||
|
||
// cached from whatever global is present so that test runners that stub it
|
||
// don't break things. But we need to wrap it in a try catch in case it is
|
||
// wrapped in strict mode code which doesn't define any globals. It's inside a
|
||
// function because try/catches deoptimize in certain engines.
|
||
|
||
var cachedSetTimeout;
|
||
var cachedClearTimeout;
|
||
|
||
(function () {
|
||
try {
|
||
cachedSetTimeout = setTimeout;
|
||
} catch (e) {
|
||
cachedSetTimeout = function () {
|
||
throw new Error('setTimeout is not defined');
|
||
}
|
||
}
|
||
try {
|
||
cachedClearTimeout = clearTimeout;
|
||
} catch (e) {
|
||
cachedClearTimeout = function () {
|
||
throw new Error('clearTimeout is not defined');
|
||
}
|
||
}
|
||
} ())
|
||
var queue = [];
|
||
var draining = false;
|
||
var currentQueue;
|
||
var queueIndex = -1;
|
||
|
||
function cleanUpNextTick() {
|
||
if (!draining || !currentQueue) {
|
||
return;
|
||
}
|
||
draining = false;
|
||
if (currentQueue.length) {
|
||
queue = currentQueue.concat(queue);
|
||
} else {
|
||
queueIndex = -1;
|
||
}
|
||
if (queue.length) {
|
||
drainQueue();
|
||
}
|
||
}
|
||
|
||
function drainQueue() {
|
||
if (draining) {
|
||
return;
|
||
}
|
||
var timeout = cachedSetTimeout.call(null, cleanUpNextTick);
|
||
draining = true;
|
||
|
||
var len = queue.length;
|
||
while(len) {
|
||
currentQueue = queue;
|
||
queue = [];
|
||
while (++queueIndex < len) {
|
||
if (currentQueue) {
|
||
currentQueue[queueIndex].run();
|
||
}
|
||
}
|
||
queueIndex = -1;
|
||
len = queue.length;
|
||
}
|
||
currentQueue = null;
|
||
draining = false;
|
||
cachedClearTimeout.call(null, timeout);
|
||
}
|
||
|
||
process.nextTick = function (fun) {
|
||
var args = new Array(arguments.length - 1);
|
||
if (arguments.length > 1) {
|
||
for (var i = 1; i < arguments.length; i++) {
|
||
args[i - 1] = arguments[i];
|
||
}
|
||
}
|
||
queue.push(new Item(fun, args));
|
||
if (queue.length === 1 && !draining) {
|
||
cachedSetTimeout.call(null, drainQueue, 0);
|
||
}
|
||
};
|
||
|
||
// v8 likes predictible objects
|
||
function Item(fun, array) {
|
||
this.fun = fun;
|
||
this.array = array;
|
||
}
|
||
Item.prototype.run = function () {
|
||
this.fun.apply(null, this.array);
|
||
};
|
||
process.title = 'browser';
|
||
process.browser = true;
|
||
process.env = {};
|
||
process.argv = [];
|
||
process.version = ''; // empty string to avoid regexp issues
|
||
process.versions = {};
|
||
|
||
function noop() {}
|
||
|
||
process.on = noop;
|
||
process.addListener = noop;
|
||
process.once = noop;
|
||
process.off = noop;
|
||
process.removeListener = noop;
|
||
process.removeAllListeners = noop;
|
||
process.emit = noop;
|
||
|
||
process.binding = function (name) {
|
||
throw new Error('process.binding is not supported');
|
||
};
|
||
|
||
process.cwd = function () { return '/' };
|
||
process.chdir = function (dir) {
|
||
throw new Error('process.chdir is not supported');
|
||
};
|
||
process.umask = function() { return 0; };
|
||
|
||
|
||
/***/ },
|
||
/* 150 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
|
||
/**
|
||
* Module dependencies.
|
||
*/
|
||
|
||
var url = __webpack_require__(151);
|
||
var parser = __webpack_require__(34);
|
||
var Manager = __webpack_require__(64);
|
||
var debug = __webpack_require__(4)('socket.io-client');
|
||
|
||
/**
|
||
* Module exports.
|
||
*/
|
||
|
||
module.exports = exports = lookup;
|
||
|
||
/**
|
||
* Managers cache.
|
||
*/
|
||
|
||
var cache = exports.managers = {};
|
||
|
||
/**
|
||
* Looks up an existing `Manager` for multiplexing.
|
||
* If the user summons:
|
||
*
|
||
* `io('http://localhost/a');`
|
||
* `io('http://localhost/b');`
|
||
*
|
||
* We reuse the existing instance based on same scheme/port/host,
|
||
* and we initialize sockets for each namespace.
|
||
*
|
||
* @api public
|
||
*/
|
||
|
||
function lookup(uri, opts) {
|
||
if (typeof uri == 'object') {
|
||
opts = uri;
|
||
uri = undefined;
|
||
}
|
||
|
||
opts = opts || {};
|
||
|
||
var parsed = url(uri);
|
||
var source = parsed.source;
|
||
var id = parsed.id;
|
||
var path = parsed.path;
|
||
var sameNamespace = cache[id] && path in cache[id].nsps;
|
||
var newConnection = opts.forceNew || opts['force new connection'] ||
|
||
false === opts.multiplex || sameNamespace;
|
||
|
||
var io;
|
||
|
||
if (newConnection) {
|
||
debug('ignoring socket cache for %s', source);
|
||
io = Manager(source, opts);
|
||
} else {
|
||
if (!cache[id]) {
|
||
debug('new io instance for %s', source);
|
||
cache[id] = Manager(source, opts);
|
||
}
|
||
io = cache[id];
|
||
}
|
||
|
||
return io.socket(parsed.path);
|
||
}
|
||
|
||
/**
|
||
* Protocol version.
|
||
*
|
||
* @api public
|
||
*/
|
||
|
||
exports.protocol = parser.protocol;
|
||
|
||
/**
|
||
* `connect`.
|
||
*
|
||
* @param {String} uri
|
||
* @api public
|
||
*/
|
||
|
||
exports.connect = lookup;
|
||
|
||
/**
|
||
* Expose constructors for standalone build.
|
||
*
|
||
* @api public
|
||
*/
|
||
|
||
exports.Manager = __webpack_require__(64);
|
||
exports.Socket = __webpack_require__(66);
|
||
|
||
|
||
/***/ },
|
||
/* 151 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
/* WEBPACK VAR INJECTION */(function(global) {
|
||
/**
|
||
* Module dependencies.
|
||
*/
|
||
|
||
var parseuri = __webpack_require__(62);
|
||
var debug = __webpack_require__(4)('socket.io-client:url');
|
||
|
||
/**
|
||
* Module exports.
|
||
*/
|
||
|
||
module.exports = url;
|
||
|
||
/**
|
||
* URL parser.
|
||
*
|
||
* @param {String} url
|
||
* @param {Object} An object meant to mimic window.location.
|
||
* Defaults to window.location.
|
||
* @api public
|
||
*/
|
||
|
||
function url(uri, loc){
|
||
var obj = uri;
|
||
|
||
// default to window.location
|
||
var loc = loc || global.location;
|
||
if (null == uri) uri = loc.protocol + '//' + loc.host;
|
||
|
||
// relative path support
|
||
if ('string' == typeof uri) {
|
||
if ('/' == uri.charAt(0)) {
|
||
if ('/' == uri.charAt(1)) {
|
||
uri = loc.protocol + uri;
|
||
} else {
|
||
uri = loc.host + uri;
|
||
}
|
||
}
|
||
|
||
if (!/^(https?|wss?):\/\//.test(uri)) {
|
||
debug('protocol-less url %s', uri);
|
||
if ('undefined' != typeof loc) {
|
||
uri = loc.protocol + '//' + uri;
|
||
} else {
|
||
uri = 'https://' + uri;
|
||
}
|
||
}
|
||
|
||
// parse
|
||
debug('parse %s', uri);
|
||
obj = parseuri(uri);
|
||
}
|
||
|
||
// make sure we treat `localhost:80` and `localhost` equally
|
||
if (!obj.port) {
|
||
if (/^(http|ws)$/.test(obj.protocol)) {
|
||
obj.port = '80';
|
||
}
|
||
else if (/^(http|ws)s$/.test(obj.protocol)) {
|
||
obj.port = '443';
|
||
}
|
||
}
|
||
|
||
obj.path = obj.path || '/';
|
||
|
||
var ipv6 = obj.host.indexOf(':') !== -1;
|
||
var host = ipv6 ? '[' + obj.host + ']' : obj.host;
|
||
|
||
// define unique id
|
||
obj.id = obj.protocol + '://' + host + ':' + obj.port;
|
||
// define href
|
||
obj.href = obj.protocol + '://' + host + (loc && loc.port == obj.port ? '' : (':' + obj.port));
|
||
|
||
return obj;
|
||
}
|
||
|
||
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
|
||
|
||
/***/ },
|
||
/* 152 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
/* WEBPACK VAR INJECTION */(function(global) {/*global Blob,File*/
|
||
|
||
/**
|
||
* Module requirements
|
||
*/
|
||
|
||
var isArray = __webpack_require__(68);
|
||
var isBuf = __webpack_require__(67);
|
||
|
||
/**
|
||
* Replaces every Buffer | ArrayBuffer in packet with a numbered placeholder.
|
||
* Anything with blobs or files should be fed through removeBlobs before coming
|
||
* here.
|
||
*
|
||
* @param {Object} packet - socket.io event packet
|
||
* @return {Object} with deconstructed packet and list of buffers
|
||
* @api public
|
||
*/
|
||
|
||
exports.deconstructPacket = function(packet){
|
||
var buffers = [];
|
||
var packetData = packet.data;
|
||
|
||
function _deconstructPacket(data) {
|
||
if (!data) return data;
|
||
|
||
if (isBuf(data)) {
|
||
var placeholder = { _placeholder: true, num: buffers.length };
|
||
buffers.push(data);
|
||
return placeholder;
|
||
} else if (isArray(data)) {
|
||
var newData = new Array(data.length);
|
||
for (var i = 0; i < data.length; i++) {
|
||
newData[i] = _deconstructPacket(data[i]);
|
||
}
|
||
return newData;
|
||
} else if ('object' == typeof data && !(data instanceof Date)) {
|
||
var newData = {};
|
||
for (var key in data) {
|
||
newData[key] = _deconstructPacket(data[key]);
|
||
}
|
||
return newData;
|
||
}
|
||
return data;
|
||
}
|
||
|
||
var pack = packet;
|
||
pack.data = _deconstructPacket(packetData);
|
||
pack.attachments = buffers.length; // number of binary 'attachments'
|
||
return {packet: pack, buffers: buffers};
|
||
};
|
||
|
||
/**
|
||
* Reconstructs a binary packet from its placeholder packet and buffers
|
||
*
|
||
* @param {Object} packet - event packet with placeholders
|
||
* @param {Array} buffers - binary buffers to put in placeholder positions
|
||
* @return {Object} reconstructed packet
|
||
* @api public
|
||
*/
|
||
|
||
exports.reconstructPacket = function(packet, buffers) {
|
||
var curPlaceHolder = 0;
|
||
|
||
function _reconstructPacket(data) {
|
||
if (data && data._placeholder) {
|
||
var buf = buffers[data.num]; // appropriate buffer (should be natural order anyway)
|
||
return buf;
|
||
} else if (isArray(data)) {
|
||
for (var i = 0; i < data.length; i++) {
|
||
data[i] = _reconstructPacket(data[i]);
|
||
}
|
||
return data;
|
||
} else if (data && 'object' == typeof data) {
|
||
for (var key in data) {
|
||
data[key] = _reconstructPacket(data[key]);
|
||
}
|
||
return data;
|
||
}
|
||
return data;
|
||
}
|
||
|
||
packet.data = _reconstructPacket(packet.data);
|
||
packet.attachments = undefined; // no longer useful
|
||
return packet;
|
||
};
|
||
|
||
/**
|
||
* Asynchronously removes Blobs or Files from data via
|
||
* FileReader's readAsArrayBuffer method. Used before encoding
|
||
* data as msgpack. Calls callback with the blobless data.
|
||
*
|
||
* @param {Object} data
|
||
* @param {Function} callback
|
||
* @api private
|
||
*/
|
||
|
||
exports.removeBlobs = function(data, callback) {
|
||
function _removeBlobs(obj, curKey, containingObject) {
|
||
if (!obj) return obj;
|
||
|
||
// convert any blob
|
||
if ((global.Blob && obj instanceof Blob) ||
|
||
(global.File && obj instanceof File)) {
|
||
pendingBlobs++;
|
||
|
||
// async filereader
|
||
var fileReader = new FileReader();
|
||
fileReader.onload = function() { // this.result == arraybuffer
|
||
if (containingObject) {
|
||
containingObject[curKey] = this.result;
|
||
}
|
||
else {
|
||
bloblessData = this.result;
|
||
}
|
||
|
||
// if nothing pending its callback time
|
||
if(! --pendingBlobs) {
|
||
callback(bloblessData);
|
||
}
|
||
};
|
||
|
||
fileReader.readAsArrayBuffer(obj); // blob -> arraybuffer
|
||
} else if (isArray(obj)) { // handle array
|
||
for (var i = 0; i < obj.length; i++) {
|
||
_removeBlobs(obj[i], i, obj);
|
||
}
|
||
} else if (obj && 'object' == typeof obj && !isBuf(obj)) { // and object
|
||
for (var key in obj) {
|
||
_removeBlobs(obj[key], key, obj);
|
||
}
|
||
}
|
||
}
|
||
|
||
var pendingBlobs = 0;
|
||
var bloblessData = data;
|
||
_removeBlobs(bloblessData);
|
||
if (!pendingBlobs) {
|
||
callback(bloblessData);
|
||
}
|
||
};
|
||
|
||
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))
|
||
|
||
/***/ },
|
||
/* 153 */
|
||
/***/ 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;
|
||
};
|
||
|
||
|
||
/***/ },
|
||
/* 154 */
|
||
/***/ function(module, exports) {
|
||
|
||
module.exports = toArray
|
||
|
||
function toArray(list, index) {
|
||
var array = []
|
||
|
||
index = index || 0
|
||
|
||
for (var i = index || 0; i < list.length; i++) {
|
||
array[i - index] = list[i]
|
||
}
|
||
|
||
return array
|
||
}
|
||
|
||
|
||
/***/ },
|
||
/* 155 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
/* WEBPACK VAR INJECTION */(function(module, global) {var __WEBPACK_AMD_DEFINE_RESULT__;/*! https://mths.be/utf8js v2.0.0 by @mathias */
|
||
;(function(root) {
|
||
|
||
// Detect free variables `exports`
|
||
var freeExports = typeof exports == 'object' && exports;
|
||
|
||
// Detect free variable `module`
|
||
var freeModule = typeof module == 'object' && module &&
|
||
module.exports == freeExports && module;
|
||
|
||
// Detect free variable `global`, from Node.js or Browserified code,
|
||
// and use it as `root`
|
||
var freeGlobal = typeof global == 'object' && global;
|
||
if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
|
||
root = freeGlobal;
|
||
}
|
||
|
||
/*--------------------------------------------------------------------------*/
|
||
|
||
var stringFromCharCode = String.fromCharCode;
|
||
|
||
// Taken from https://mths.be/punycode
|
||
function ucs2decode(string) {
|
||
var output = [];
|
||
var counter = 0;
|
||
var length = string.length;
|
||
var value;
|
||
var extra;
|
||
while (counter < length) {
|
||
value = string.charCodeAt(counter++);
|
||
if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
|
||
// high surrogate, and there is a next character
|
||
extra = string.charCodeAt(counter++);
|
||
if ((extra & 0xFC00) == 0xDC00) { // low surrogate
|
||
output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
|
||
} else {
|
||
// unmatched surrogate; only append this code unit, in case the next
|
||
// code unit is the high surrogate of a surrogate pair
|
||
output.push(value);
|
||
counter--;
|
||
}
|
||
} else {
|
||
output.push(value);
|
||
}
|
||
}
|
||
return output;
|
||
}
|
||
|
||
// Taken from https://mths.be/punycode
|
||
function ucs2encode(array) {
|
||
var length = array.length;
|
||
var index = -1;
|
||
var value;
|
||
var output = '';
|
||
while (++index < length) {
|
||
value = array[index];
|
||
if (value > 0xFFFF) {
|
||
value -= 0x10000;
|
||
output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
|
||
value = 0xDC00 | value & 0x3FF;
|
||
}
|
||
output += stringFromCharCode(value);
|
||
}
|
||
return output;
|
||
}
|
||
|
||
function checkScalarValue(codePoint) {
|
||
if (codePoint >= 0xD800 && codePoint <= 0xDFFF) {
|
||
throw Error(
|
||
'Lone surrogate U+' + codePoint.toString(16).toUpperCase() +
|
||
' is not a scalar value'
|
||
);
|
||
}
|
||
}
|
||
/*--------------------------------------------------------------------------*/
|
||
|
||
function createByte(codePoint, shift) {
|
||
return stringFromCharCode(((codePoint >> shift) & 0x3F) | 0x80);
|
||
}
|
||
|
||
function encodeCodePoint(codePoint) {
|
||
if ((codePoint & 0xFFFFFF80) == 0) { // 1-byte sequence
|
||
return stringFromCharCode(codePoint);
|
||
}
|
||
var symbol = '';
|
||
if ((codePoint & 0xFFFFF800) == 0) { // 2-byte sequence
|
||
symbol = stringFromCharCode(((codePoint >> 6) & 0x1F) | 0xC0);
|
||
}
|
||
else if ((codePoint & 0xFFFF0000) == 0) { // 3-byte sequence
|
||
checkScalarValue(codePoint);
|
||
symbol = stringFromCharCode(((codePoint >> 12) & 0x0F) | 0xE0);
|
||
symbol += createByte(codePoint, 6);
|
||
}
|
||
else if ((codePoint & 0xFFE00000) == 0) { // 4-byte sequence
|
||
symbol = stringFromCharCode(((codePoint >> 18) & 0x07) | 0xF0);
|
||
symbol += createByte(codePoint, 12);
|
||
symbol += createByte(codePoint, 6);
|
||
}
|
||
symbol += stringFromCharCode((codePoint & 0x3F) | 0x80);
|
||
return symbol;
|
||
}
|
||
|
||
function utf8encode(string) {
|
||
var codePoints = ucs2decode(string);
|
||
var length = codePoints.length;
|
||
var index = -1;
|
||
var codePoint;
|
||
var byteString = '';
|
||
while (++index < length) {
|
||
codePoint = codePoints[index];
|
||
byteString += encodeCodePoint(codePoint);
|
||
}
|
||
return byteString;
|
||
}
|
||
|
||
/*--------------------------------------------------------------------------*/
|
||
|
||
function readContinuationByte() {
|
||
if (byteIndex >= byteCount) {
|
||
throw Error('Invalid byte index');
|
||
}
|
||
|
||
var continuationByte = byteArray[byteIndex] & 0xFF;
|
||
byteIndex++;
|
||
|
||
if ((continuationByte & 0xC0) == 0x80) {
|
||
return continuationByte & 0x3F;
|
||
}
|
||
|
||
// If we end up here, it’s not a continuation byte
|
||
throw Error('Invalid continuation byte');
|
||
}
|
||
|
||
function decodeSymbol() {
|
||
var byte1;
|
||
var byte2;
|
||
var byte3;
|
||
var byte4;
|
||
var codePoint;
|
||
|
||
if (byteIndex > byteCount) {
|
||
throw Error('Invalid byte index');
|
||
}
|
||
|
||
if (byteIndex == byteCount) {
|
||
return false;
|
||
}
|
||
|
||
// Read first byte
|
||
byte1 = byteArray[byteIndex] & 0xFF;
|
||
byteIndex++;
|
||
|
||
// 1-byte sequence (no continuation bytes)
|
||
if ((byte1 & 0x80) == 0) {
|
||
return byte1;
|
||
}
|
||
|
||
// 2-byte sequence
|
||
if ((byte1 & 0xE0) == 0xC0) {
|
||
var byte2 = readContinuationByte();
|
||
codePoint = ((byte1 & 0x1F) << 6) | byte2;
|
||
if (codePoint >= 0x80) {
|
||
return codePoint;
|
||
} else {
|
||
throw Error('Invalid continuation byte');
|
||
}
|
||
}
|
||
|
||
// 3-byte sequence (may include unpaired surrogates)
|
||
if ((byte1 & 0xF0) == 0xE0) {
|
||
byte2 = readContinuationByte();
|
||
byte3 = readContinuationByte();
|
||
codePoint = ((byte1 & 0x0F) << 12) | (byte2 << 6) | byte3;
|
||
if (codePoint >= 0x0800) {
|
||
checkScalarValue(codePoint);
|
||
return codePoint;
|
||
} else {
|
||
throw Error('Invalid continuation byte');
|
||
}
|
||
}
|
||
|
||
// 4-byte sequence
|
||
if ((byte1 & 0xF8) == 0xF0) {
|
||
byte2 = readContinuationByte();
|
||
byte3 = readContinuationByte();
|
||
byte4 = readContinuationByte();
|
||
codePoint = ((byte1 & 0x0F) << 0x12) | (byte2 << 0x0C) |
|
||
(byte3 << 0x06) | byte4;
|
||
if (codePoint >= 0x010000 && codePoint <= 0x10FFFF) {
|
||
return codePoint;
|
||
}
|
||
}
|
||
|
||
throw Error('Invalid UTF-8 detected');
|
||
}
|
||
|
||
var byteArray;
|
||
var byteCount;
|
||
var byteIndex;
|
||
function utf8decode(byteString) {
|
||
byteArray = ucs2decode(byteString);
|
||
byteCount = byteArray.length;
|
||
byteIndex = 0;
|
||
var codePoints = [];
|
||
var tmp;
|
||
while ((tmp = decodeSymbol()) !== false) {
|
||
codePoints.push(tmp);
|
||
}
|
||
return ucs2encode(codePoints);
|
||
}
|
||
|
||
/*--------------------------------------------------------------------------*/
|
||
|
||
var utf8 = {
|
||
'version': '2.0.0',
|
||
'encode': utf8encode,
|
||
'decode': utf8decode
|
||
};
|
||
|
||
// Some AMD build optimizers, like r.js, check for specific condition patterns
|
||
// like the following:
|
||
if (
|
||
true
|
||
) {
|
||
!(__WEBPACK_AMD_DEFINE_RESULT__ = function() {
|
||
return utf8;
|
||
}.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
||
} else if (freeExports && !freeExports.nodeType) {
|
||
if (freeModule) { // in Node.js or RingoJS v0.8.0+
|
||
freeModule.exports = utf8;
|
||
} else { // in Narwhal or RingoJS v0.7.0-
|
||
var object = {};
|
||
var hasOwnProperty = object.hasOwnProperty;
|
||
for (var key in utf8) {
|
||
hasOwnProperty.call(utf8, key) && (freeExports[key] = utf8[key]);
|
||
}
|
||
}
|
||
} else { // in Rhino or a web browser
|
||
root.utf8 = utf8;
|
||
}
|
||
|
||
}(this));
|
||
|
||
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(35)(module), __webpack_require__(0)))
|
||
|
||
/***/ },
|
||
/* 156 */
|
||
/***/ function(module, exports) {
|
||
|
||
module.exports = function isBuffer(arg) {
|
||
return arg && typeof arg === 'object'
|
||
&& typeof arg.copy === 'function'
|
||
&& typeof arg.fill === 'function'
|
||
&& typeof arg.readUInt8 === 'function';
|
||
}
|
||
|
||
/***/ },
|
||
/* 157 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
/* WEBPACK VAR INJECTION */(function(global, 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.
|
||
|
||
var formatRegExp = /%[sdj%]/g;
|
||
exports.format = function(f) {
|
||
if (!isString(f)) {
|
||
var objects = [];
|
||
for (var i = 0; i < arguments.length; i++) {
|
||
objects.push(inspect(arguments[i]));
|
||
}
|
||
return objects.join(' ');
|
||
}
|
||
|
||
var i = 1;
|
||
var args = arguments;
|
||
var len = args.length;
|
||
var str = String(f).replace(formatRegExp, function(x) {
|
||
if (x === '%%') return '%';
|
||
if (i >= len) return x;
|
||
switch (x) {
|
||
case '%s': return String(args[i++]);
|
||
case '%d': return Number(args[i++]);
|
||
case '%j':
|
||
try {
|
||
return JSON.stringify(args[i++]);
|
||
} catch (_) {
|
||
return '[Circular]';
|
||
}
|
||
default:
|
||
return x;
|
||
}
|
||
});
|
||
for (var x = args[i]; i < len; x = args[++i]) {
|
||
if (isNull(x) || !isObject(x)) {
|
||
str += ' ' + x;
|
||
} else {
|
||
str += ' ' + inspect(x);
|
||
}
|
||
}
|
||
return str;
|
||
};
|
||
|
||
|
||
// Mark that a method should not be used.
|
||
// Returns a modified function which warns once by default.
|
||
// If --no-deprecation is set, then it is a no-op.
|
||
exports.deprecate = function(fn, msg) {
|
||
// Allow for deprecating things in the process of starting up.
|
||
if (isUndefined(global.process)) {
|
||
return function() {
|
||
return exports.deprecate(fn, msg).apply(this, arguments);
|
||
};
|
||
}
|
||
|
||
if (process.noDeprecation === true) {
|
||
return fn;
|
||
}
|
||
|
||
var warned = false;
|
||
function deprecated() {
|
||
if (!warned) {
|
||
if (process.throwDeprecation) {
|
||
throw new Error(msg);
|
||
} else if (process.traceDeprecation) {
|
||
console.trace(msg);
|
||
} else {
|
||
console.error(msg);
|
||
}
|
||
warned = true;
|
||
}
|
||
return fn.apply(this, arguments);
|
||
}
|
||
|
||
return deprecated;
|
||
};
|
||
|
||
|
||
var debugs = {};
|
||
var debugEnviron;
|
||
exports.debuglog = function(set) {
|
||
if (isUndefined(debugEnviron))
|
||
debugEnviron = process.env.NODE_DEBUG || '';
|
||
set = set.toUpperCase();
|
||
if (!debugs[set]) {
|
||
if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
|
||
var pid = process.pid;
|
||
debugs[set] = function() {
|
||
var msg = exports.format.apply(exports, arguments);
|
||
console.error('%s %d: %s', set, pid, msg);
|
||
};
|
||
} else {
|
||
debugs[set] = function() {};
|
||
}
|
||
}
|
||
return debugs[set];
|
||
};
|
||
|
||
|
||
/**
|
||
* Echos the value of a value. Trys to print the value out
|
||
* in the best way possible given the different types.
|
||
*
|
||
* @param {Object} obj The object to print out.
|
||
* @param {Object} opts Optional options object that alters the output.
|
||
*/
|
||
/* legacy: obj, showHidden, depth, colors*/
|
||
function inspect(obj, opts) {
|
||
// default options
|
||
var ctx = {
|
||
seen: [],
|
||
stylize: stylizeNoColor
|
||
};
|
||
// legacy...
|
||
if (arguments.length >= 3) ctx.depth = arguments[2];
|
||
if (arguments.length >= 4) ctx.colors = arguments[3];
|
||
if (isBoolean(opts)) {
|
||
// legacy...
|
||
ctx.showHidden = opts;
|
||
} else if (opts) {
|
||
// got an "options" object
|
||
exports._extend(ctx, opts);
|
||
}
|
||
// set default options
|
||
if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
|
||
if (isUndefined(ctx.depth)) ctx.depth = 2;
|
||
if (isUndefined(ctx.colors)) ctx.colors = false;
|
||
if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
|
||
if (ctx.colors) ctx.stylize = stylizeWithColor;
|
||
return formatValue(ctx, obj, ctx.depth);
|
||
}
|
||
exports.inspect = inspect;
|
||
|
||
|
||
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
|
||
inspect.colors = {
|
||
'bold' : [1, 22],
|
||
'italic' : [3, 23],
|
||
'underline' : [4, 24],
|
||
'inverse' : [7, 27],
|
||
'white' : [37, 39],
|
||
'grey' : [90, 39],
|
||
'black' : [30, 39],
|
||
'blue' : [34, 39],
|
||
'cyan' : [36, 39],
|
||
'green' : [32, 39],
|
||
'magenta' : [35, 39],
|
||
'red' : [31, 39],
|
||
'yellow' : [33, 39]
|
||
};
|
||
|
||
// Don't use 'blue' not visible on cmd.exe
|
||
inspect.styles = {
|
||
'special': 'cyan',
|
||
'number': 'yellow',
|
||
'boolean': 'yellow',
|
||
'undefined': 'grey',
|
||
'null': 'bold',
|
||
'string': 'green',
|
||
'date': 'magenta',
|
||
// "name": intentionally not styling
|
||
'regexp': 'red'
|
||
};
|
||
|
||
|
||
function stylizeWithColor(str, styleType) {
|
||
var style = inspect.styles[styleType];
|
||
|
||
if (style) {
|
||
return '\u001b[' + inspect.colors[style][0] + 'm' + str +
|
||
'\u001b[' + inspect.colors[style][1] + 'm';
|
||
} else {
|
||
return str;
|
||
}
|
||
}
|
||
|
||
|
||
function stylizeNoColor(str, styleType) {
|
||
return str;
|
||
}
|
||
|
||
|
||
function arrayToHash(array) {
|
||
var hash = {};
|
||
|
||
array.forEach(function(val, idx) {
|
||
hash[val] = true;
|
||
});
|
||
|
||
return hash;
|
||
}
|
||
|
||
|
||
function formatValue(ctx, value, recurseTimes) {
|
||
// Provide a hook for user-specified inspect functions.
|
||
// Check that value is an object with an inspect function on it
|
||
if (ctx.customInspect &&
|
||
value &&
|
||
isFunction(value.inspect) &&
|
||
// Filter out the util module, it's inspect function is special
|
||
value.inspect !== exports.inspect &&
|
||
// Also filter out any prototype objects using the circular check.
|
||
!(value.constructor && value.constructor.prototype === value)) {
|
||
var ret = value.inspect(recurseTimes, ctx);
|
||
if (!isString(ret)) {
|
||
ret = formatValue(ctx, ret, recurseTimes);
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
// Primitive types cannot have properties
|
||
var primitive = formatPrimitive(ctx, value);
|
||
if (primitive) {
|
||
return primitive;
|
||
}
|
||
|
||
// Look up the keys of the object.
|
||
var keys = Object.keys(value);
|
||
var visibleKeys = arrayToHash(keys);
|
||
|
||
if (ctx.showHidden) {
|
||
keys = Object.getOwnPropertyNames(value);
|
||
}
|
||
|
||
// IE doesn't make error fields non-enumerable
|
||
// http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
|
||
if (isError(value)
|
||
&& (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
|
||
return formatError(value);
|
||
}
|
||
|
||
// Some type of object without properties can be shortcutted.
|
||
if (keys.length === 0) {
|
||
if (isFunction(value)) {
|
||
var name = value.name ? ': ' + value.name : '';
|
||
return ctx.stylize('[Function' + name + ']', 'special');
|
||
}
|
||
if (isRegExp(value)) {
|
||
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
|
||
}
|
||
if (isDate(value)) {
|
||
return ctx.stylize(Date.prototype.toString.call(value), 'date');
|
||
}
|
||
if (isError(value)) {
|
||
return formatError(value);
|
||
}
|
||
}
|
||
|
||
var base = '', array = false, braces = ['{', '}'];
|
||
|
||
// Make Array say that they are Array
|
||
if (isArray(value)) {
|
||
array = true;
|
||
braces = ['[', ']'];
|
||
}
|
||
|
||
// Make functions say that they are functions
|
||
if (isFunction(value)) {
|
||
var n = value.name ? ': ' + value.name : '';
|
||
base = ' [Function' + n + ']';
|
||
}
|
||
|
||
// Make RegExps say that they are RegExps
|
||
if (isRegExp(value)) {
|
||
base = ' ' + RegExp.prototype.toString.call(value);
|
||
}
|
||
|
||
// Make dates with properties first say the date
|
||
if (isDate(value)) {
|
||
base = ' ' + Date.prototype.toUTCString.call(value);
|
||
}
|
||
|
||
// Make error with message first say the error
|
||
if (isError(value)) {
|
||
base = ' ' + formatError(value);
|
||
}
|
||
|
||
if (keys.length === 0 && (!array || value.length == 0)) {
|
||
return braces[0] + base + braces[1];
|
||
}
|
||
|
||
if (recurseTimes < 0) {
|
||
if (isRegExp(value)) {
|
||
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
|
||
} else {
|
||
return ctx.stylize('[Object]', 'special');
|
||
}
|
||
}
|
||
|
||
ctx.seen.push(value);
|
||
|
||
var output;
|
||
if (array) {
|
||
output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
|
||
} else {
|
||
output = keys.map(function(key) {
|
||
return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
|
||
});
|
||
}
|
||
|
||
ctx.seen.pop();
|
||
|
||
return reduceToSingleString(output, base, braces);
|
||
}
|
||
|
||
|
||
function formatPrimitive(ctx, value) {
|
||
if (isUndefined(value))
|
||
return ctx.stylize('undefined', 'undefined');
|
||
if (isString(value)) {
|
||
var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
|
||
.replace(/'/g, "\\'")
|
||
.replace(/\\"/g, '"') + '\'';
|
||
return ctx.stylize(simple, 'string');
|
||
}
|
||
if (isNumber(value))
|
||
return ctx.stylize('' + value, 'number');
|
||
if (isBoolean(value))
|
||
return ctx.stylize('' + value, 'boolean');
|
||
// For some reason typeof null is "object", so special case here.
|
||
if (isNull(value))
|
||
return ctx.stylize('null', 'null');
|
||
}
|
||
|
||
|
||
function formatError(value) {
|
||
return '[' + Error.prototype.toString.call(value) + ']';
|
||
}
|
||
|
||
|
||
function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
|
||
var output = [];
|
||
for (var i = 0, l = value.length; i < l; ++i) {
|
||
if (hasOwnProperty(value, String(i))) {
|
||
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
|
||
String(i), true));
|
||
} else {
|
||
output.push('');
|
||
}
|
||
}
|
||
keys.forEach(function(key) {
|
||
if (!key.match(/^\d+$/)) {
|
||
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
|
||
key, true));
|
||
}
|
||
});
|
||
return output;
|
||
}
|
||
|
||
|
||
function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
|
||
var name, str, desc;
|
||
desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
|
||
if (desc.get) {
|
||
if (desc.set) {
|
||
str = ctx.stylize('[Getter/Setter]', 'special');
|
||
} else {
|
||
str = ctx.stylize('[Getter]', 'special');
|
||
}
|
||
} else {
|
||
if (desc.set) {
|
||
str = ctx.stylize('[Setter]', 'special');
|
||
}
|
||
}
|
||
if (!hasOwnProperty(visibleKeys, key)) {
|
||
name = '[' + key + ']';
|
||
}
|
||
if (!str) {
|
||
if (ctx.seen.indexOf(desc.value) < 0) {
|
||
if (isNull(recurseTimes)) {
|
||
str = formatValue(ctx, desc.value, null);
|
||
} else {
|
||
str = formatValue(ctx, desc.value, recurseTimes - 1);
|
||
}
|
||
if (str.indexOf('\n') > -1) {
|
||
if (array) {
|
||
str = str.split('\n').map(function(line) {
|
||
return ' ' + line;
|
||
}).join('\n').substr(2);
|
||
} else {
|
||
str = '\n' + str.split('\n').map(function(line) {
|
||
return ' ' + line;
|
||
}).join('\n');
|
||
}
|
||
}
|
||
} else {
|
||
str = ctx.stylize('[Circular]', 'special');
|
||
}
|
||
}
|
||
if (isUndefined(name)) {
|
||
if (array && key.match(/^\d+$/)) {
|
||
return str;
|
||
}
|
||
name = JSON.stringify('' + key);
|
||
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
|
||
name = name.substr(1, name.length - 2);
|
||
name = ctx.stylize(name, 'name');
|
||
} else {
|
||
name = name.replace(/'/g, "\\'")
|
||
.replace(/\\"/g, '"')
|
||
.replace(/(^"|"$)/g, "'");
|
||
name = ctx.stylize(name, 'string');
|
||
}
|
||
}
|
||
|
||
return name + ': ' + str;
|
||
}
|
||
|
||
|
||
function reduceToSingleString(output, base, braces) {
|
||
var numLinesEst = 0;
|
||
var length = output.reduce(function(prev, cur) {
|
||
numLinesEst++;
|
||
if (cur.indexOf('\n') >= 0) numLinesEst++;
|
||
return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
|
||
}, 0);
|
||
|
||
if (length > 60) {
|
||
return braces[0] +
|
||
(base === '' ? '' : base + '\n ') +
|
||
' ' +
|
||
output.join(',\n ') +
|
||
' ' +
|
||
braces[1];
|
||
}
|
||
|
||
return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
|
||
}
|
||
|
||
|
||
// NOTE: These type checking functions intentionally don't use `instanceof`
|
||
// because it is fragile and can be easily faked with `Object.create()`.
|
||
function isArray(ar) {
|
||
return Array.isArray(ar);
|
||
}
|
||
exports.isArray = isArray;
|
||
|
||
function isBoolean(arg) {
|
||
return typeof arg === 'boolean';
|
||
}
|
||
exports.isBoolean = isBoolean;
|
||
|
||
function isNull(arg) {
|
||
return arg === null;
|
||
}
|
||
exports.isNull = isNull;
|
||
|
||
function isNullOrUndefined(arg) {
|
||
return arg == null;
|
||
}
|
||
exports.isNullOrUndefined = isNullOrUndefined;
|
||
|
||
function isNumber(arg) {
|
||
return typeof arg === 'number';
|
||
}
|
||
exports.isNumber = isNumber;
|
||
|
||
function isString(arg) {
|
||
return typeof arg === 'string';
|
||
}
|
||
exports.isString = isString;
|
||
|
||
function isSymbol(arg) {
|
||
return typeof arg === 'symbol';
|
||
}
|
||
exports.isSymbol = isSymbol;
|
||
|
||
function isUndefined(arg) {
|
||
return arg === void 0;
|
||
}
|
||
exports.isUndefined = isUndefined;
|
||
|
||
function isRegExp(re) {
|
||
return isObject(re) && objectToString(re) === '[object RegExp]';
|
||
}
|
||
exports.isRegExp = isRegExp;
|
||
|
||
function isObject(arg) {
|
||
return typeof arg === 'object' && arg !== null;
|
||
}
|
||
exports.isObject = isObject;
|
||
|
||
function isDate(d) {
|
||
return isObject(d) && objectToString(d) === '[object Date]';
|
||
}
|
||
exports.isDate = isDate;
|
||
|
||
function isError(e) {
|
||
return isObject(e) &&
|
||
(objectToString(e) === '[object Error]' || e instanceof Error);
|
||
}
|
||
exports.isError = isError;
|
||
|
||
function isFunction(arg) {
|
||
return typeof arg === 'function';
|
||
}
|
||
exports.isFunction = isFunction;
|
||
|
||
function isPrimitive(arg) {
|
||
return arg === null ||
|
||
typeof arg === 'boolean' ||
|
||
typeof arg === 'number' ||
|
||
typeof arg === 'string' ||
|
||
typeof arg === 'symbol' || // ES6 symbol
|
||
typeof arg === 'undefined';
|
||
}
|
||
exports.isPrimitive = isPrimitive;
|
||
|
||
exports.isBuffer = __webpack_require__(156);
|
||
|
||
function objectToString(o) {
|
||
return Object.prototype.toString.call(o);
|
||
}
|
||
|
||
|
||
function pad(n) {
|
||
return n < 10 ? '0' + n.toString(10) : n.toString(10);
|
||
}
|
||
|
||
|
||
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
|
||
'Oct', 'Nov', 'Dec'];
|
||
|
||
// 26 Feb 16:19:34
|
||
function timestamp() {
|
||
var d = new Date();
|
||
var time = [pad(d.getHours()),
|
||
pad(d.getMinutes()),
|
||
pad(d.getSeconds())].join(':');
|
||
return [d.getDate(), months[d.getMonth()], time].join(' ');
|
||
}
|
||
|
||
|
||
// log is just a thin wrapper to console.log that prepends a timestamp
|
||
exports.log = function() {
|
||
console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
|
||
};
|
||
|
||
|
||
/**
|
||
* Inherit the prototype methods from one constructor into another.
|
||
*
|
||
* The Function.prototype.inherits from lang.js rewritten as a standalone
|
||
* function (not on Function.prototype). NOTE: If this file is to be loaded
|
||
* during bootstrapping this function needs to be rewritten using some native
|
||
* functions as prototype setup using normal JavaScript does not work as
|
||
* expected during bootstrapping (see mirror.js in r114903).
|
||
*
|
||
* @param {function} ctor Constructor function which needs to inherit the
|
||
* prototype.
|
||
* @param {function} superCtor Constructor function to inherit prototype from.
|
||
*/
|
||
exports.inherits = __webpack_require__(136);
|
||
|
||
exports._extend = function(origin, add) {
|
||
// Don't do anything if add isn't an object
|
||
if (!add || !isObject(add)) return origin;
|
||
|
||
var keys = Object.keys(add);
|
||
var i = keys.length;
|
||
while (i--) {
|
||
origin[keys[i]] = add[keys[i]];
|
||
}
|
||
return origin;
|
||
};
|
||
|
||
function hasOwnProperty(obj, prop) {
|
||
return Object.prototype.hasOwnProperty.call(obj, prop);
|
||
}
|
||
|
||
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0), __webpack_require__(18)))
|
||
|
||
/***/ },
|
||
/* 158 */
|
||
/***/ function(module, exports) {
|
||
|
||
/* WEBPACK VAR INJECTION */(function(__webpack_amd_options__) {module.exports = __webpack_amd_options__;
|
||
|
||
/* WEBPACK VAR INJECTION */}.call(exports, {}))
|
||
|
||
/***/ },
|
||
/* 159 */
|
||
/***/ function(module, exports) {
|
||
|
||
/* (ignored) */
|
||
|
||
/***/ },
|
||
/* 160 */
|
||
/***/ function(module, exports, __webpack_require__) {
|
||
|
||
"use strict";
|
||
'use strict';
|
||
|
||
var _stringify = __webpack_require__(36);
|
||
|
||
var _stringify2 = _interopRequireDefault(_stringify);
|
||
|
||
var _promise = __webpack_require__(37);
|
||
|
||
var _promise2 = _interopRequireDefault(_promise);
|
||
|
||
var _keys = __webpack_require__(71);
|
||
|
||
var _keys2 = _interopRequireDefault(_keys);
|
||
|
||
var _classCallCheck2 = __webpack_require__(38);
|
||
|
||
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
|
||
|
||
var _createClass2 = __webpack_require__(39);
|
||
|
||
var _createClass3 = _interopRequireDefault(_createClass2);
|
||
|
||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||
|
||
var EventEmitter = __webpack_require__(40).EventEmitter;
|
||
var Logger = __webpack_require__(41);
|
||
var logger = Logger.create("orbit-db", { color: Logger.Colors.Magenta });
|
||
var EventStore = __webpack_require__(42);
|
||
var FeedStore = __webpack_require__(73);
|
||
var KeyValueStore = __webpack_require__(74);
|
||
var CounterStore = __webpack_require__(72);
|
||
var PubSub = __webpack_require__(70);
|
||
|
||
var OrbitDB = function () {
|
||
function OrbitDB(ipfs) {
|
||
(0, _classCallCheck3.default)(this, OrbitDB);
|
||
|
||
this._ipfs = ipfs;
|
||
this._pubsub = null;
|
||
this.user = null;
|
||
this.network = null;
|
||
this.events = new EventEmitter();
|
||
this.stores = {};
|
||
}
|
||
|
||
/* Databases */
|
||
|
||
|
||
(0, _createClass3.default)(OrbitDB, [{
|
||
key: 'feed',
|
||
value: function feed(dbname, options) {
|
||
return this._createStore(FeedStore, dbname, options);
|
||
}
|
||
}, {
|
||
key: 'eventlog',
|
||
value: function eventlog(dbname, options) {
|
||
return this._createStore(EventStore, dbname, options);
|
||
}
|
||
}, {
|
||
key: 'kvstore',
|
||
value: function kvstore(dbname, options) {
|
||
return this._createStore(KeyValueStore, dbname, options);
|
||
}
|
||
}, {
|
||
key: 'counter',
|
||
value: function counter(dbname, options) {
|
||
return this._createStore(CounterStore, dbname, options);
|
||
}
|
||
}, {
|
||
key: 'disconnect',
|
||
value: function disconnect() {
|
||
var _this = this;
|
||
|
||
if (this._pubsub) this._pubsub.disconnect();
|
||
this.events.removeAllListeners('load');
|
||
this.events.removeAllListeners('ready');
|
||
this.events.removeAllListeners('sync');
|
||
this.events.removeAllListeners('synced');
|
||
this.events.removeAllListeners('data');
|
||
this.events.removeAllListeners('close');
|
||
(0, _keys2.default)(this.stores).map(function (e) {
|
||
return _this.stores[e];
|
||
}).forEach(function (store) {
|
||
store.events.removeAllListeners('load');
|
||
store.events.removeAllListeners('ready');
|
||
store.events.removeAllListeners('sync');
|
||
store.events.removeAllListeners('updated');
|
||
store.events.removeAllListeners('data');
|
||
store.events.removeAllListeners('close');
|
||
});
|
||
this.stores = {};
|
||
this.user = null;
|
||
this.network = null;
|
||
}
|
||
}, {
|
||
key: '_createStore',
|
||
value: function _createStore(Store, dbname, options) {
|
||
if (!options) options = {};
|
||
var replicate = options.subscribe !== undefined ? options.subscribe : true;
|
||
var store = new Store(this._ipfs, this.user.username, dbname, options);
|
||
this.stores[dbname] = store;
|
||
return this._subscribe(store, dbname, replicate);
|
||
}
|
||
}, {
|
||
key: '_subscribe',
|
||
value: function _subscribe(store, dbname, subscribe, callback) {
|
||
if (subscribe === undefined) subscribe = true;
|
||
|
||
store.events.on('load', this._onLoad.bind(this));
|
||
store.events.on('ready', this._onReady.bind(this));
|
||
store.events.on('sync', this._onSync.bind(this));
|
||
store.events.on('updated', this._onSynced.bind(this));
|
||
store.events.on('data', this._onWrite.bind(this));
|
||
store.events.on('close', this._onClose.bind(this));
|
||
|
||
if (subscribe && this._pubsub) this._pubsub.subscribe(dbname, '', this._onMessage.bind(this), store.options.maxHistory > 0);
|
||
|
||
return store.use(this.user.username);
|
||
}
|
||
}, {
|
||
key: '_onMessage',
|
||
value: function _onMessage(dbname, hash) {
|
||
// console.log(".MESSAGE", dbname, hash, this.user.username);
|
||
var store = this.stores[dbname];
|
||
this.events.emit('message', dbname, hash);
|
||
// console.log("sync", store !== null, this.user.username)
|
||
store.sync(hash).catch(function (e) {
|
||
return logger.error(e.stack);
|
||
});
|
||
}
|
||
}, {
|
||
key: '_onWrite',
|
||
value: function _onWrite(dbname, hash) {
|
||
// console.log(".WRITE", dbname, hash, this.user.username);
|
||
if (!hash) throw new Error("Hash can't be null!");
|
||
if (this._pubsub) this._pubsub.publish(dbname, hash);
|
||
this.events.emit('data', dbname, hash);
|
||
}
|
||
}, {
|
||
key: '_onSync',
|
||
value: function _onSync(dbname) {
|
||
// console.log(".SYNC", dbname);
|
||
this.events.emit('sync', dbname);
|
||
}
|
||
}, {
|
||
key: '_onSynced',
|
||
value: function _onSynced(dbname, items) {
|
||
// console.log(".SYNCED", dbname, items.length);
|
||
this.events.emit('synced', dbname, items);
|
||
}
|
||
}, {
|
||
key: '_onLoad',
|
||
value: function _onLoad(dbname) {
|
||
// console.log(".LOAD", dbname);
|
||
this.events.emit('load', dbname);
|
||
}
|
||
}, {
|
||
key: '_onReady',
|
||
value: function _onReady(dbname) {
|
||
// console.log(".READY", dbname);
|
||
this.events.emit('ready', this.stores[dbname]);
|
||
}
|
||
}, {
|
||
key: '_onClose',
|
||
value: function _onClose(dbname) {
|
||
if (this._pubsub) this._pubsub.unsubscribe(dbname);
|
||
delete this.stores[dbname];
|
||
this.events.emit('closed', dbname);
|
||
}
|
||
}, {
|
||
key: '_connect',
|
||
value: function _connect(hash, username, password, allowOffline) {
|
||
var _this2 = this;
|
||
|
||
if (allowOffline === undefined) allowOffline = false;
|
||
|
||
var readNetworkInfo = function readNetworkInfo(hash) {
|
||
return new _promise2.default(function (resolve, reject) {
|
||
resolve((0, _stringify2.default)({
|
||
name: 'Orbit DEV Network',
|
||
publishers: [hash]
|
||
}));
|
||
});
|
||
};
|
||
|
||
var host = void 0,
|
||
port = void 0,
|
||
name = void 0;
|
||
return readNetworkInfo(hash).then(function (object) {
|
||
_this2.network = JSON.parse(object);
|
||
name = _this2.network.name;
|
||
host = _this2.network.publishers[0].split(":")[0];
|
||
port = _this2.network.publishers[0].split(":")[1];
|
||
}).then(function () {
|
||
_this2._pubsub = new PubSub();
|
||
logger.debug('Connecting to network ' + hash + ' (' + host + ':' + port + ')');
|
||
return _this2._pubsub.connect(host, port, username, password);
|
||
}).then(function () {
|
||
logger.debug('Connected to network ' + hash + ' (' + host + ':' + port + ')');
|
||
_this2.user = { username: username, id: username }; // TODO: user id from ipfs hash
|
||
return;
|
||
}).catch(function (e) {
|
||
logger.warn('Couldn\'t connect to ' + hash + ' network: ' + e.message);
|
||
if (!allowOffline) {
|
||
logger.debug('\'allowOffline\' set to false, terminating');
|
||
if (_this2._pubsub) _this2._pubsub.disconnect();
|
||
throw e;
|
||
}
|
||
_this2.user = { username: username, id: username }; // TODO: user id from ipfs hash
|
||
return;
|
||
});
|
||
}
|
||
}]);
|
||
return OrbitDB;
|
||
}();
|
||
|
||
var OrbitClientFactory = function () {
|
||
function OrbitClientFactory() {
|
||
(0, _classCallCheck3.default)(this, OrbitClientFactory);
|
||
}
|
||
|
||
(0, _createClass3.default)(OrbitClientFactory, null, [{
|
||
key: 'connect',
|
||
value: function connect(network, username, password, ipfs, options) {
|
||
if (!options) options = { allowOffline: false };
|
||
|
||
if (!ipfs) {
|
||
logger.error("IPFS instance not provided");
|
||
throw new Error("IPFS instance not provided");
|
||
}
|
||
|
||
var client = new OrbitDB(ipfs);
|
||
return client._connect(network, username, password, options.allowOffline).then(function () {
|
||
return client;
|
||
});
|
||
}
|
||
}]);
|
||
return OrbitClientFactory;
|
||
}();
|
||
|
||
module.exports = OrbitClientFactory;
|
||
|
||
/***/ }
|
||
/******/ ]); |