34011 lines
1.0 MiB
34011 lines
1.0 MiB
exports.id = 305;
|
|
exports.ids = [305];
|
|
exports.modules = {
|
|
|
|
/***/ 42869:
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
const json = __webpack_require__(29387);
|
|
const strings = __webpack_require__(13043);
|
|
const regex = __webpack_require__(13732);
|
|
const yaml = __webpack_require__(76050);
|
|
|
|
module.exports = {
|
|
...json,
|
|
...strings,
|
|
...regex,
|
|
...yaml,
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 29387:
|
|
/***/ ((module) => {
|
|
|
|
function isValidJSON(str) {
|
|
if (typeof str !== "string") {
|
|
return;
|
|
}
|
|
try {
|
|
JSON.parse(str);
|
|
return true;
|
|
} catch (err) {
|
|
if (err instanceof SyntaxError) {
|
|
return false;
|
|
}
|
|
throw err;
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
"json.is_valid": isValidJSON,
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 13732:
|
|
/***/ ((module) => {
|
|
|
|
const regexSplit = (pattern, s) => s.split(RegExp(pattern));
|
|
|
|
module.exports = { "regex.split": regexSplit };
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 13043:
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
const vsprintf = __webpack_require__(8975).vsprintf;
|
|
|
|
const sprintf = (s, values) => vsprintf(s, values);
|
|
|
|
module.exports = { sprintf };
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 76050:
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
const yaml = __webpack_require__(6792);
|
|
|
|
// see: https://eemeli.org/yaml/v1/#errors
|
|
const errors = new Set([
|
|
"YAMLReferenceError",
|
|
"YAMLSemanticError",
|
|
"YAMLSyntaxError",
|
|
"YAMLWarning",
|
|
]);
|
|
|
|
function parse(str) {
|
|
if (typeof str !== "string") {
|
|
return { ok: false, result: undefined };
|
|
}
|
|
|
|
const YAML_SILENCE_WARNINGS_CACHED = global.YAML_SILENCE_WARNINGS;
|
|
try {
|
|
// see: https://eemeli.org/yaml/v1/#silencing-warnings
|
|
global.YAML_SILENCE_WARNINGS = true;
|
|
return { ok: true, result: yaml.parse(str) };
|
|
} catch (err) {
|
|
// Ignore parser errors.
|
|
if (err && errors.has(err.name)) {
|
|
return { ok: false, result: undefined };
|
|
}
|
|
throw err;
|
|
} finally {
|
|
global.YAML_SILENCE_WARNINGS = YAML_SILENCE_WARNINGS_CACHED;
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
// is_valid is expected to return nothing if input is invalid otherwise
|
|
// true/false for it being valid YAML.
|
|
"yaml.is_valid": (str) => typeof str === "string" ? parse(str).ok : undefined,
|
|
"yaml.marshal": (data) => yaml.stringify(data),
|
|
"yaml.unmarshal": (str) => parse(str).result,
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 39026:
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
// Copyright 2018 The OPA Authors. All rights reserved.
|
|
// Use of this source code is governed by an Apache2
|
|
// license that can be found in the LICENSE file.
|
|
const builtIns = __webpack_require__(42869);
|
|
const util = __webpack_require__(31669);
|
|
|
|
// NOTE: The util shim here exists for Node 10.x and can be removed
|
|
// when dropping support. Browsers and Node >= 11.x use the global.
|
|
const TextEncoder = typeof global.TextEncoder !== "undefined"
|
|
? global.TextEncoder
|
|
: util.TextEncoder;
|
|
const TextDecoder = typeof global.TextDecoder !== "undefined"
|
|
? global.TextDecoder
|
|
: util.TextDecoder;
|
|
|
|
/**
|
|
* @param {WebAssembly.Memory} mem
|
|
*/
|
|
function stringDecoder(mem) {
|
|
return function (addr) {
|
|
const i8 = new Int8Array(mem.buffer);
|
|
let s = "";
|
|
while (i8[addr] !== 0) {
|
|
s += String.fromCharCode(i8[addr++]);
|
|
}
|
|
return s;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Stringifies and loads an object into OPA's Memory
|
|
* @param {WebAssembly.Instance} wasmInstance
|
|
* @param {WebAssembly.Memory} memory
|
|
* @param {any | ArrayBuffer} value data as `object`, literal primitive or ArrayBuffer (last is assumed to be a well-formed stringified JSON)
|
|
* @returns {number}
|
|
*/
|
|
function _loadJSON(wasmInstance, memory, value) {
|
|
if (value === undefined) {
|
|
return 0;
|
|
}
|
|
|
|
let valueBuf;
|
|
if (value instanceof ArrayBuffer) {
|
|
valueBuf = new Uint8Array(value);
|
|
} else {
|
|
const valueAsText = JSON.stringify(value);
|
|
valueBuf = new TextEncoder().encode(valueAsText);
|
|
}
|
|
|
|
const valueBufLen = valueBuf.byteLength;
|
|
const rawAddr = wasmInstance.exports.opa_malloc(valueBufLen);
|
|
const memoryBuffer = new Uint8Array(memory.buffer);
|
|
memoryBuffer.set(valueBuf, rawAddr);
|
|
|
|
const parsedAddr = wasmInstance.exports.opa_json_parse(rawAddr, valueBufLen);
|
|
|
|
if (parsedAddr === 0) {
|
|
throw "failed to parse json value";
|
|
}
|
|
return parsedAddr;
|
|
}
|
|
|
|
/**
|
|
* Dumps and parses a JSON object from OPA's Memory
|
|
* @param {WebAssembly.Instance} wasmInstance
|
|
* @param {WebAssembly.Memory} memory
|
|
* @param {number} addr
|
|
* @returns {object}
|
|
*/
|
|
function _dumpJSON(wasmInstance, memory, addr) {
|
|
const rawAddr = wasmInstance.exports.opa_json_dump(addr);
|
|
return _dumpJSONRaw(memory, rawAddr);
|
|
}
|
|
|
|
/**
|
|
* Parses a JSON object from wasm instance's memory
|
|
* @param {WebAssembly.Memory} memory
|
|
* @param {number} addr
|
|
* @returns {object}
|
|
*/
|
|
function _dumpJSONRaw(memory, addr) {
|
|
const buf = new Uint8Array(memory.buffer);
|
|
|
|
let idx = addr;
|
|
|
|
while (buf[idx] !== 0) {
|
|
idx++;
|
|
}
|
|
|
|
const utf8View = new Uint8Array(memory.buffer, addr, idx - addr);
|
|
const jsonAsText = new TextDecoder().decode(utf8View);
|
|
|
|
return JSON.parse(jsonAsText);
|
|
}
|
|
|
|
const builtinFuncs = builtIns;
|
|
|
|
/**
|
|
* _builtinCall dispatches the built-in function. The built-in function
|
|
* arguments are loaded from Wasm and back in using JSON serialization.
|
|
* @param {WebAssembly.Instance} wasmInstance
|
|
* @param {WebAssembly.Memory} memory
|
|
* @param {{ [builtinId: number]: string }} builtins
|
|
* @param {string} builtin_id
|
|
*/
|
|
function _builtinCall(wasmInstance, memory, builtins, builtinId) {
|
|
const builtInName = builtins[builtinId];
|
|
const impl = builtinFuncs[builtInName];
|
|
|
|
if (impl === undefined) {
|
|
throw {
|
|
message: "not implemented: built-in function " +
|
|
builtinId +
|
|
": " +
|
|
builtins[builtinId],
|
|
};
|
|
}
|
|
|
|
const argArray = Array.prototype.slice.apply(arguments);
|
|
const args = [];
|
|
|
|
for (let i = 4; i < argArray.length; i++) {
|
|
const jsArg = _dumpJSON(wasmInstance, memory, argArray[i]);
|
|
args.push(jsArg);
|
|
}
|
|
|
|
const result = impl(...args);
|
|
|
|
return _loadJSON(wasmInstance, memory, result);
|
|
}
|
|
|
|
/**
|
|
* _loadPolicy can take in either an ArrayBuffer or WebAssembly.Module
|
|
* as its first argument, and a WebAssembly.Memory for the second parameter.
|
|
* It will return a Promise, depending on the input type the promise
|
|
* resolves to both a compiled WebAssembly.Module and its first WebAssembly.Instance
|
|
* or to the WebAssemblyInstance.
|
|
* @param {BufferSource | WebAssembly.Module} policyWasm
|
|
* @param {WebAssembly.Memory} memory
|
|
* @returns {Promise<{ policy: WebAssembly.WebAssemblyInstantiatedSource | WebAssembly.Instance, minorVersion: number }>}
|
|
*/
|
|
async function _loadPolicy(policyWasm, memory) {
|
|
const addr2string = stringDecoder(memory);
|
|
|
|
const env = {};
|
|
|
|
const wasm = await WebAssembly.instantiate(policyWasm, {
|
|
env: {
|
|
memory,
|
|
opa_abort: function (addr) {
|
|
throw addr2string(addr);
|
|
},
|
|
opa_println: function (addr) {
|
|
console.log(addr2string(addr));
|
|
},
|
|
opa_builtin0: function (builtinId, _ctx) {
|
|
return _builtinCall(env.instance, memory, env.builtins, builtinId);
|
|
},
|
|
opa_builtin1: function (builtinId, _ctx, arg1) {
|
|
return _builtinCall(
|
|
env.instance,
|
|
memory,
|
|
env.builtins,
|
|
builtinId,
|
|
arg1,
|
|
);
|
|
},
|
|
opa_builtin2: function (builtinId, _ctx, arg1, arg2) {
|
|
return _builtinCall(
|
|
env.instance,
|
|
memory,
|
|
env.builtins,
|
|
builtinId,
|
|
arg1,
|
|
arg2,
|
|
);
|
|
},
|
|
opa_builtin3: function (builtinId, _ctx, arg1, arg2, arg3) {
|
|
return _builtinCall(
|
|
env.instance,
|
|
memory,
|
|
env.builtins,
|
|
builtinId,
|
|
arg1,
|
|
arg2,
|
|
arg3,
|
|
);
|
|
},
|
|
opa_builtin4: function (builtinId, _ctx, arg1, arg2, arg3, arg4) {
|
|
return _builtinCall(
|
|
env.instance,
|
|
memory,
|
|
env.builtins,
|
|
builtinId,
|
|
arg1,
|
|
arg2,
|
|
arg3,
|
|
arg4,
|
|
);
|
|
},
|
|
},
|
|
});
|
|
|
|
// Note: On Node 10.x this value is a number on Node 12.x and up it is
|
|
// an object with numberic `value` property.
|
|
const abiVersionGlobal = wasm.instance.exports.opa_wasm_abi_version;
|
|
if (abiVersionGlobal !== undefined) {
|
|
const abiVersion = typeof abiVersionGlobal === "number"
|
|
? abiVersionGlobal
|
|
: abiVersionGlobal.value;
|
|
if (abiVersion !== 1) {
|
|
throw `unsupported ABI version ${abiVersion}`;
|
|
}
|
|
} else {
|
|
console.error("opa_wasm_abi_version undefined"); // logs to stderr
|
|
}
|
|
|
|
const abiMinorVersionGlobal =
|
|
wasm.instance.exports.opa_wasm_abi_minor_version;
|
|
let abiMinorVersion;
|
|
if (abiMinorVersionGlobal !== undefined) {
|
|
abiMinorVersion = typeof abiMinorVersionGlobal === "number"
|
|
? abiMinorVersionGlobal
|
|
: abiMinorVersionGlobal.value;
|
|
} else {
|
|
console.error("opa_wasm_abi_minor_version undefined");
|
|
}
|
|
|
|
env.instance = wasm.instance ? wasm.instance : wasm;
|
|
|
|
const builtins = _dumpJSON(
|
|
env.instance,
|
|
memory,
|
|
env.instance.exports.builtins(),
|
|
);
|
|
|
|
/** @type {typeof builtIns} */
|
|
env.builtins = {};
|
|
|
|
for (const key of Object.keys(builtins)) {
|
|
env.builtins[builtins[key]] = key;
|
|
}
|
|
|
|
return { policy: wasm, minorVersion: abiMinorVersion };
|
|
}
|
|
|
|
/**
|
|
* LoadedPolicy is a wrapper around a WebAssembly.Instance and WebAssembly.Memory
|
|
* for a compiled Rego policy. There are helpers to run the wasm instance and
|
|
* handle the output from the policy wasm.
|
|
*/
|
|
class LoadedPolicy {
|
|
/**
|
|
* Loads and initializes a compiled Rego policy.
|
|
* @param {WebAssembly.WebAssemblyInstantiatedSource} policy
|
|
* @param {WebAssembly.Memory} memory
|
|
*/
|
|
constructor(policy, memory, minorVersion) {
|
|
this.minorVersion = minorVersion;
|
|
this.mem = memory;
|
|
|
|
// Depending on how the wasm was instantiated "policy" might be a
|
|
// WebAssembly Instance or be a wrapper around the Module and
|
|
// Instance. We only care about the Instance.
|
|
this.wasmInstance = policy.instance ? policy.instance : policy;
|
|
|
|
this.dataAddr = _loadJSON(this.wasmInstance, this.mem, {});
|
|
this.baseHeapPtr = this.wasmInstance.exports.opa_heap_ptr_get();
|
|
this.dataHeapPtr = this.baseHeapPtr;
|
|
this.entrypoints = _dumpJSON(
|
|
this.wasmInstance,
|
|
this.mem,
|
|
this.wasmInstance.exports.entrypoints(),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Evaluates the loaded policy with the given input and
|
|
* return the result set. This should be re-used for multiple evaluations
|
|
* of the same policy with different inputs.
|
|
*
|
|
* To call a non-default entrypoint in your WASM specify it as the second
|
|
* param. A list of entrypoints can be accessed with the `this.entrypoints`
|
|
* property.
|
|
* @param {any | ArrayBuffer} input input to be evaluated in form of `object`, literal primitive or ArrayBuffer (last is assumed to be a well-formed stringified JSON)
|
|
* @param {number | string} entrypoint ID or name of the entrypoint to call (optional)
|
|
*/
|
|
evaluate(input, entrypoint = 0) {
|
|
// determine entrypoint ID
|
|
if (typeof entrypoint === "number") {
|
|
// used as-is
|
|
} else if (typeof entrypoint === "string") {
|
|
if (Object.prototype.hasOwnProperty.call(this.entrypoints, entrypoint)) {
|
|
entrypoint = this.entrypoints[entrypoint];
|
|
} else {
|
|
throw `entrypoint ${entrypoint} is not valid in this instance`;
|
|
}
|
|
} else {
|
|
throw `entrypoint value is an invalid type, must be either string or number`;
|
|
}
|
|
|
|
// ABI 1.2 fastpath
|
|
if (this.minorVersion >= 2) {
|
|
// write input into memory, adjust heap pointer
|
|
let inputBuf = null;
|
|
let inputLen = 0;
|
|
let inputAddr = 0;
|
|
if (input) {
|
|
if (input instanceof ArrayBuffer) {
|
|
inputBuf = new Uint8Array(input);
|
|
} else {
|
|
const inputAsText = JSON.stringify(input);
|
|
inputBuf = new TextEncoder().encode(inputAsText);
|
|
}
|
|
|
|
inputAddr = this.dataHeapPtr;
|
|
inputLen = inputBuf.byteLength;
|
|
const delta = inputAddr + inputLen - this.mem.buffer.byteLength;
|
|
if (delta > 0) {
|
|
const pages = roundup(delta);
|
|
this.mem.grow(pages);
|
|
}
|
|
const buf = new Uint8Array(this.mem.buffer);
|
|
buf.set(inputBuf, this.dataHeapPtr);
|
|
this.dataHeapPtr = inputAddr + inputLen;
|
|
}
|
|
|
|
const ret = this.wasmInstance.exports.opa_eval(
|
|
0,
|
|
entrypoint,
|
|
this.dataAddr,
|
|
inputAddr,
|
|
inputLen,
|
|
this.dataHeapPtr,
|
|
0,
|
|
);
|
|
return _dumpJSONRaw(this.mem, ret);
|
|
}
|
|
|
|
// Reset the heap pointer before each evaluation
|
|
this.wasmInstance.exports.opa_heap_ptr_set(this.dataHeapPtr);
|
|
|
|
// Load the input data
|
|
const inputAddr = _loadJSON(this.wasmInstance, this.mem, input);
|
|
|
|
// Setup the evaluation context
|
|
const ctxAddr = this.wasmInstance.exports.opa_eval_ctx_new();
|
|
this.wasmInstance.exports.opa_eval_ctx_set_input(ctxAddr, inputAddr);
|
|
this.wasmInstance.exports.opa_eval_ctx_set_data(ctxAddr, this.dataAddr);
|
|
this.wasmInstance.exports.opa_eval_ctx_set_entrypoint(ctxAddr, entrypoint);
|
|
|
|
// Actually evaluate the policy
|
|
this.wasmInstance.exports.eval(ctxAddr);
|
|
|
|
// Retrieve the result
|
|
const resultAddr = this.wasmInstance.exports.opa_eval_ctx_get_result(
|
|
ctxAddr,
|
|
);
|
|
return _dumpJSON(this.wasmInstance, this.mem, resultAddr);
|
|
}
|
|
|
|
/**
|
|
* evalBool will evaluate the policy and return a boolean answer
|
|
* depending on the return code from the policy evaluation.
|
|
* @deprecated Use `evaluate` instead.
|
|
* @param {object} input
|
|
*/
|
|
evalBool(input) {
|
|
const rs = this.evaluate(input);
|
|
return rs && rs.length === 1 && rs[0] === true;
|
|
}
|
|
|
|
/**
|
|
* Loads data for use in subsequent evaluations.
|
|
* @param {object | ArrayBuffer} data data in form of `object` or ArrayBuffer (last is assumed to be a well-formed stringified JSON)
|
|
*/
|
|
setData(data) {
|
|
this.wasmInstance.exports.opa_heap_ptr_set(this.baseHeapPtr);
|
|
this.dataAddr = _loadJSON(this.wasmInstance, this.mem, data);
|
|
this.dataHeapPtr = this.wasmInstance.exports.opa_heap_ptr_get();
|
|
}
|
|
}
|
|
|
|
function roundup(bytes) {
|
|
const pageSize = 64 * 1024;
|
|
return Math.ceil(bytes / pageSize);
|
|
}
|
|
|
|
module.exports = {
|
|
/**
|
|
* Takes in either an ArrayBuffer or WebAssembly.Module
|
|
* and will return a LoadedPolicy object which can be used to evaluate
|
|
* the policy.
|
|
*
|
|
* To set custom memory size specify number of memory pages
|
|
* as second param.
|
|
* Defaults to 5 pages (320KB).
|
|
* @param {BufferSource | WebAssembly.Module} regoWasm
|
|
* @param {number | WebAssembly.MemoryDescriptor} memoryDescriptor For backwards-compatibility, a 'number' argument is taken to be the initial memory size.
|
|
*/
|
|
async loadPolicy(regoWasm, memoryDescriptor = {}) {
|
|
// back-compat, second arg used to be a number: 'memorySize', with default of 5
|
|
if (typeof memoryDescriptor === "number") {
|
|
memoryDescriptor = { initial: memoryDescriptor };
|
|
}
|
|
memoryDescriptor.initial = memoryDescriptor.initial || 5;
|
|
|
|
const memory = new WebAssembly.Memory(memoryDescriptor);
|
|
const { policy, minorVersion } = await _loadPolicy(regoWasm, memory);
|
|
return new LoadedPolicy(policy, memory, minorVersion);
|
|
},
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 98611:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
var types_1 = __webpack_require__(60442);
|
|
Object.defineProperty(exports, "CloudConfigFileTypes", ({ enumerable: true, get: function () { return types_1.CloudConfigFileTypes; } }));
|
|
var issue_to_line_1 = __webpack_require__(76932);
|
|
Object.defineProperty(exports, "issuesToLineNumbers", ({ enumerable: true, get: function () { return issue_to_line_1.issuesToLineNumbers; } }));
|
|
Object.defineProperty(exports, "getTrees", ({ enumerable: true, get: function () { return issue_to_line_1.getTrees; } }));
|
|
Object.defineProperty(exports, "getLineNumber", ({ enumerable: true, get: function () { return issue_to_line_1.getLineNumber; } }));
|
|
var yaml_parser_1 = __webpack_require__(54232);
|
|
Object.defineProperty(exports, "parseFileContent", ({ enumerable: true, get: function () { return yaml_parser_1.parseFileContent; } }));
|
|
var path_1 = __webpack_require__(89639);
|
|
Object.defineProperty(exports, "parsePath", ({ enumerable: true, get: function () { return path_1.parsePath; } }));
|
|
//# sourceMappingURL=index.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 76932:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.getLineNumber = exports.getTrees = exports.issuesToLineNumbers = void 0;
|
|
var types = __webpack_require__(60442);
|
|
var utils_1 = __webpack_require__(95680);
|
|
function issuesToLineNumbers(fileContent, fileType, path) {
|
|
var trees = getTrees(fileType, fileContent);
|
|
return getLineNumber(path, fileType, trees);
|
|
}
|
|
exports.issuesToLineNumbers = issuesToLineNumbers;
|
|
function getTrees(fileType, fileContent) {
|
|
assertFileType(fileType);
|
|
var trees = utils_1.buildTreeForTypeMap[fileType](fileContent);
|
|
if (Object.keys(trees).length === 0) {
|
|
throw new Error('failed to create trees');
|
|
}
|
|
return trees;
|
|
}
|
|
exports.getTrees = getTrees;
|
|
function getLineNumber(path, fileType, trees) {
|
|
assertFileType(fileType);
|
|
var pathDetails = utils_1.getPathDetails(path.slice(), fileType);
|
|
var treeNodes = trees[pathDetails.docId].nodes;
|
|
return utils_1.findLineNumberOfGivenPath(treeNodes, pathDetails);
|
|
}
|
|
exports.getLineNumber = getLineNumber;
|
|
function assertFileType(fileType) {
|
|
if (!Object.values(types.CloudConfigFileTypes).includes(fileType)) {
|
|
throw new Error('Unknown format');
|
|
}
|
|
}
|
|
//# sourceMappingURL=index.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 83686:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
var esprima_1 = __webpack_require__(31072);
|
|
var JsonIterator = /** @class */ (function () {
|
|
function JsonIterator(fileContent) {
|
|
this.tokens = [];
|
|
this.i = -1;
|
|
this.currentToken = {
|
|
type: '',
|
|
value: '',
|
|
loc: undefined,
|
|
};
|
|
this.done = false;
|
|
this.previousProps = [];
|
|
this.lastProp = undefined;
|
|
this.tokens = esprima_1.tokenize(fileContent, {
|
|
comment: true,
|
|
loc: true,
|
|
});
|
|
if (!this.tokens.length) {
|
|
throw new SyntaxError('unexpected end of JSON input');
|
|
}
|
|
}
|
|
JsonIterator.prototype[Symbol.iterator] = function () {
|
|
return this;
|
|
};
|
|
JsonIterator.prototype.isCurrentType = function (type) {
|
|
if (!this.currentToken) {
|
|
throw new SyntaxError('unexpected end of JSON input');
|
|
}
|
|
return ((this.currentToken.type === 'Punctuator'
|
|
? this.currentToken.value
|
|
: this.currentToken.type) === type);
|
|
};
|
|
JsonIterator.prototype.isCurrentValue = function (value) {
|
|
if (!this.currentToken) {
|
|
throw new SyntaxError('unexpected end of JSON input');
|
|
}
|
|
return (this.currentToken.type === 'Punctuator' &&
|
|
this.currentToken.value === value);
|
|
};
|
|
JsonIterator.prototype.expectType = function (type) {
|
|
if (this.isCurrentType(type)) {
|
|
return;
|
|
}
|
|
var error = new SyntaxError("Unexpected type " + this.currentToken.type);
|
|
Object.assign(error, this.currentToken.loc.start);
|
|
throw error;
|
|
};
|
|
JsonIterator.prototype.expectValue = function (value) {
|
|
if (this.isCurrentValue(value)) {
|
|
return;
|
|
}
|
|
var error = new SyntaxError("Unexpected value " + this.currentToken.value);
|
|
Object.assign(error, this.currentToken.loc.start);
|
|
throw error;
|
|
};
|
|
JsonIterator.prototype.skipComments = function () {
|
|
while (this.currentToken &&
|
|
(this.isCurrentType('LineComment') || this.isCurrentType('BlockComment'))) {
|
|
this.next();
|
|
}
|
|
};
|
|
JsonIterator.prototype.next = function () {
|
|
if (this.done) {
|
|
throw new SyntaxError('Unexpected EOF');
|
|
}
|
|
var newToken = this.tokens[++this.i];
|
|
this.currentToken = newToken;
|
|
if (!this.currentToken) {
|
|
this.done = true;
|
|
}
|
|
};
|
|
JsonIterator.prototype.current = function () {
|
|
return this.currentToken;
|
|
};
|
|
JsonIterator.prototype.getCurrentLocation = function () {
|
|
return {
|
|
line: this.currentToken ? this.currentToken.loc.start.line : 0,
|
|
columnStart: this.currentToken ? this.currentToken.loc.start.column : 0,
|
|
columnEnd: this.currentToken ? this.currentToken.loc.end.column : 0,
|
|
};
|
|
};
|
|
//--------------- Prop Handling
|
|
JsonIterator.prototype.setLastProp = function (prop) {
|
|
this.lastProp = prop;
|
|
};
|
|
JsonIterator.prototype.pushLastProp = function () {
|
|
this.previousProps.push(this.lastProp);
|
|
this.lastProp = undefined;
|
|
};
|
|
JsonIterator.prototype.restoreProp = function () {
|
|
this.lastProp = this.previousProps.pop();
|
|
};
|
|
JsonIterator.prototype.getLastProp = function () {
|
|
return this.lastProp !== undefined ? this.lastProp.toString() : '';
|
|
};
|
|
return JsonIterator;
|
|
}());
|
|
exports.default = JsonIterator;
|
|
//# sourceMappingURL=iterator.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 25552:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.buildJsonTreeMap = void 0;
|
|
var tslib_1 = __webpack_require__(70655);
|
|
var iterator_1 = __webpack_require__(83686);
|
|
var COLON = ':';
|
|
var BRACKET_OPEN = '[';
|
|
var BRACKET_CLOSE = ']';
|
|
var CURLY_BRACKET_OPEN = '{';
|
|
var CURLY_BRACKET_CLOSE = '}';
|
|
var COMMA = ',';
|
|
var MINUS = '-';
|
|
var possibleValueTypes = ['String', 'Boolean', 'Null', 'Numeric'];
|
|
function buildJsonTreeMap(jsonContent) {
|
|
var iter = new iterator_1.default(jsonContent);
|
|
iter.next();
|
|
iter.skipComments();
|
|
var singleWalk = walk(iter);
|
|
var tree = {
|
|
nodes: singleWalk[0].values,
|
|
};
|
|
// JSON are always single doc
|
|
return {
|
|
0: tree,
|
|
};
|
|
}
|
|
exports.buildJsonTreeMap = buildJsonTreeMap;
|
|
function skipCommentsAndParseObjectOrArray(iter, shouldParseObject) {
|
|
iter.pushLastProp();
|
|
iter.skipComments();
|
|
var nodes = [];
|
|
if (shouldParseObject) {
|
|
nodes = parseObject(iter);
|
|
}
|
|
else {
|
|
nodes = parseArray(iter);
|
|
}
|
|
// bypass }
|
|
iter.next();
|
|
iter.restoreProp();
|
|
return nodes;
|
|
}
|
|
function parseObject(iter) {
|
|
var nodes = [];
|
|
var firstLoop = true;
|
|
var name;
|
|
while (!iter.isCurrentValue(CURLY_BRACKET_CLOSE)) {
|
|
if (!firstLoop) {
|
|
// key-value pair delimiter
|
|
iter.expectValue(COMMA);
|
|
iter.next();
|
|
iter.skipComments();
|
|
// If there is a trailing comma, we might reach the end
|
|
// ```
|
|
// {
|
|
// "a": 1,
|
|
// }
|
|
// ```
|
|
if (iter.isCurrentValue(CURLY_BRACKET_CLOSE)) {
|
|
break;
|
|
}
|
|
}
|
|
firstLoop = false;
|
|
iter.expectType('String');
|
|
name = JSON.parse(iter.current().value);
|
|
iter.setLastProp(name);
|
|
iter.next();
|
|
iter.expectValue(COLON);
|
|
iter.next();
|
|
nodes.push.apply(nodes, walk(iter));
|
|
}
|
|
return nodes;
|
|
}
|
|
function parseArray(iter) {
|
|
var nodes = [];
|
|
var firstLoop = true;
|
|
var i = 0;
|
|
while (!iter.isCurrentValue(BRACKET_CLOSE)) {
|
|
if (!firstLoop) {
|
|
iter.expectValue(COMMA);
|
|
iter.next();
|
|
iter.skipComments();
|
|
if (iter.isCurrentValue(BRACKET_CLOSE)) {
|
|
break;
|
|
}
|
|
}
|
|
firstLoop = false;
|
|
iter.setLastProp(i);
|
|
nodes.push.apply(nodes, walk(iter));
|
|
iter.skipComments();
|
|
i++;
|
|
}
|
|
return nodes;
|
|
}
|
|
function handleNativeCase(iter) {
|
|
if (!possibleValueTypes.includes(iter.current().type)) {
|
|
throw new Error('failed to find type ' + iter.current().type);
|
|
}
|
|
// turn "apiVersion" -> apiVersion
|
|
// turn 'apiVersion' -> apiVersion
|
|
var currentValue = iter.current().value;
|
|
if ((currentValue.startsWith('"') && currentValue.endsWith('"')) ||
|
|
(currentValue.startsWith("'") && currentValue.endsWith("'"))) {
|
|
currentValue = currentValue.substring(1, currentValue.length - 1);
|
|
}
|
|
var nativeNode = {
|
|
key: iter.getLastProp(),
|
|
lineLocation: iter.getCurrentLocation(),
|
|
values: currentValue,
|
|
};
|
|
iter.next();
|
|
return [nativeNode];
|
|
}
|
|
function walk(iter) {
|
|
var currentNode = {
|
|
key: iter.getLastProp(),
|
|
lineLocation: iter.getCurrentLocation(),
|
|
values: [],
|
|
};
|
|
switch (iter.current().value) {
|
|
case CURLY_BRACKET_OPEN:
|
|
iter.next();
|
|
return [
|
|
tslib_1.__assign(tslib_1.__assign({}, currentNode), { values: skipCommentsAndParseObjectOrArray(iter, true) }),
|
|
];
|
|
case BRACKET_OPEN:
|
|
iter.next();
|
|
return skipCommentsAndParseObjectOrArray(iter, false).map(function (value, i) {
|
|
return {
|
|
key: iter.getLastProp() + "[" + i + "]",
|
|
lineLocation: value.lineLocation,
|
|
values: value.values,
|
|
};
|
|
});
|
|
case MINUS:
|
|
iter.next();
|
|
break;
|
|
}
|
|
return handleNativeCase(iter);
|
|
}
|
|
//# sourceMappingURL=parser.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 89179:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.buildTfTreeMap = void 0;
|
|
var types_1 = __webpack_require__(978);
|
|
var utils_1 = __webpack_require__(41904);
|
|
function buildTfTreeMap(tfContent) {
|
|
var multiLineComment = false;
|
|
var multiLinePhrase = { phrase: null };
|
|
var nodes = [];
|
|
var currNode = null;
|
|
var stateQueue = [];
|
|
var duringTypeParsing = false;
|
|
var tfFileLines = tfContent.split('\n');
|
|
for (var i = 0; i < tfFileLines.length; i++) {
|
|
var line = { content: tfFileLines[i].trim(), number: i };
|
|
var lineState = utils_1.getLineState(line, multiLineComment, multiLinePhrase);
|
|
multiLineComment = lineState.multiCommentLine;
|
|
if (lineState.ignoredLine) {
|
|
continue;
|
|
}
|
|
if (multiLinePhrase.phrase) {
|
|
//Multi-line phrase ended - line is not ignored any more
|
|
multiLinePhrase.phrase = null;
|
|
continue;
|
|
}
|
|
var topType = void 0;
|
|
if (stateQueue.length > 0) {
|
|
topType = stateQueue[stateQueue.length - 1].type;
|
|
}
|
|
var lineType = utils_1.getLineType(line, topType);
|
|
// In case of array value where is multiline and not completed yet
|
|
// or
|
|
// Object inside array
|
|
// -> can skip this line
|
|
if (topType === types_1.TFLineTypes.ARRAY_START &&
|
|
![
|
|
types_1.TFLineTypes.ARRAY_END,
|
|
types_1.TFLineTypes.OBJECT_START,
|
|
types_1.TFLineTypes.OBJECT_START_AND_END,
|
|
].includes(lineType)) {
|
|
continue;
|
|
}
|
|
switch (lineType) {
|
|
case types_1.TFLineTypes.IGNORE:
|
|
continue;
|
|
case types_1.TFLineTypes.TYPE_START:
|
|
currNode = getTypeDetailsFromLine(line, nodes, stateQueue);
|
|
duringTypeParsing = true;
|
|
continue;
|
|
case types_1.TFLineTypes.TYPE_START_AND_END:
|
|
currNode = getTypeDetailsFromLine(line, nodes, stateQueue);
|
|
stateQueue = [];
|
|
duringTypeParsing = false;
|
|
continue;
|
|
case types_1.TFLineTypes.TYPE_END:
|
|
if (topType !== types_1.TFLineTypes.SUB_TYPE) {
|
|
throw new SyntaxError('Invalid TF Input - End of type object without sub type');
|
|
}
|
|
stateQueue = [];
|
|
duringTypeParsing = false;
|
|
continue;
|
|
case types_1.TFLineTypes.OBJECT_START:
|
|
currNode = getComplexObjectNode(line, stateQueue, utils_1.Charts.openBracketsObject, lineType);
|
|
continue;
|
|
case types_1.TFLineTypes.OBJECT_START_AND_END:
|
|
getComplexObjectNode(line, stateQueue, utils_1.Charts.openBracketsObject, lineType);
|
|
stateQueue.pop();
|
|
continue;
|
|
case types_1.TFLineTypes.OBJECT_END: {
|
|
currNode = handleComplexObjectEnd(currNode, stateQueue, types_1.TFLineTypes.OBJECT_START);
|
|
continue;
|
|
}
|
|
case types_1.TFLineTypes.FUNCTION_START:
|
|
currNode = getComplexObjectNode(line, stateQueue, utils_1.Charts.openFunction, lineType);
|
|
continue;
|
|
case types_1.TFLineTypes.FUNCTION_START_AND_END:
|
|
getComplexObjectNode(line, stateQueue, utils_1.Charts.openFunction, lineType);
|
|
stateQueue.pop();
|
|
continue;
|
|
case types_1.TFLineTypes.FUNCTION_END:
|
|
currNode = handleComplexObjectEnd(currNode, stateQueue, types_1.TFLineTypes.FUNCTION_START);
|
|
continue;
|
|
case types_1.TFLineTypes.STRING:
|
|
case types_1.TFLineTypes.MULTILINE_STRING:
|
|
case types_1.TFLineTypes.ARRAY_START_AND_END: {
|
|
if (!currNode) {
|
|
throw new SyntaxError('Unexpected TF input - Simple object without parent node');
|
|
}
|
|
var simpleNode = getSimpleNode(line);
|
|
currNode.values.push(simpleNode);
|
|
if (lineType === types_1.TFLineTypes.MULTILINE_STRING) {
|
|
multiLinePhrase = utils_1.getMultiLinePhrase(line);
|
|
}
|
|
continue;
|
|
}
|
|
case types_1.TFLineTypes.ARRAY_START: {
|
|
if (!currNode) {
|
|
throw new SyntaxError('Unexpected TF input - Simple object without parent node');
|
|
}
|
|
var simpleNode = getSimpleNode(line);
|
|
if (simpleNode.values === utils_1.Charts.openBracketsArray) {
|
|
simpleNode.values = [];
|
|
}
|
|
currNode.values.push(simpleNode);
|
|
stateQueue.push({
|
|
structure: simpleNode,
|
|
type: lineType,
|
|
});
|
|
continue;
|
|
}
|
|
case types_1.TFLineTypes.ARRAY_END: {
|
|
stateQueue.pop();
|
|
continue;
|
|
}
|
|
default:
|
|
throw new SyntaxError("Invalid TF input - Unhandled line type " + types_1.TFLineTypes[lineType]);
|
|
}
|
|
}
|
|
if (duringTypeParsing || stateQueue.length !== 0) {
|
|
throw new SyntaxError('Invalid TF input - Broken file');
|
|
}
|
|
if (nodes.length === 0) {
|
|
throw new SyntaxError('Invalid TF input - No nodes were parsed');
|
|
}
|
|
// TF are always single doc
|
|
return {
|
|
0: { nodes: nodes },
|
|
};
|
|
}
|
|
exports.buildTfTreeMap = buildTfTreeMap;
|
|
function getTypeDetailsFromLine(currentLine, nodes, stateQueue) {
|
|
var lineContent = currentLine.content.split(utils_1.Charts.space);
|
|
var resourceType = lineContent[1].replace(/"/g, '');
|
|
var objectType = lineContent[0];
|
|
if (resourceType === utils_1.Charts.openBracketsObject) {
|
|
if (types_1.TerraformValidConfigurationTypes.includes(objectType)) {
|
|
//Support Terraform configurations settings object
|
|
resourceType = '';
|
|
}
|
|
else {
|
|
throw new SyntaxError('Invalid TF input - Type object without sub type');
|
|
}
|
|
}
|
|
var headNode = getTypeNode(objectType, currentLine, nodes);
|
|
if (lineContent[2] &&
|
|
lineContent[2] !== null &&
|
|
lineContent[2] !== utils_1.Charts.openBracketsObject) {
|
|
var resourceName = lineContent[2].replace(/"/g, '');
|
|
resourceType = resourceType + "[" + resourceName + "]";
|
|
}
|
|
var subHeadNode = getSubTypeNode(headNode, resourceType, currentLine);
|
|
stateQueue.push({ structure: headNode, type: types_1.TFLineTypes.TYPE_START });
|
|
stateQueue.push({ structure: subHeadNode, type: types_1.TFLineTypes.SUB_TYPE });
|
|
return subHeadNode;
|
|
}
|
|
function getTypeNode(objectType, line, nodes) {
|
|
var headNode = nodes.find(function (node) { return node.key === objectType; });
|
|
if (!headNode) {
|
|
headNode = utils_1.getNode(objectType, line, []);
|
|
nodes.push(headNode);
|
|
}
|
|
return headNode;
|
|
}
|
|
function getSubTypeNode(headNode, resourceType, line) {
|
|
var headerSubTypes = headNode.values;
|
|
var subHeadNode = headerSubTypes.find(function (node) { return node.key === resourceType; });
|
|
if (!subHeadNode) {
|
|
subHeadNode = utils_1.getNode(resourceType, line);
|
|
headNode.values.push(subHeadNode);
|
|
}
|
|
return subHeadNode;
|
|
}
|
|
function getComplexObjectNode(line, stateQueue, splitByChart, lineType) {
|
|
var key = line.content
|
|
.split(splitByChart)[0]
|
|
.split(utils_1.Charts.equal)[0]
|
|
.trim();
|
|
var objectNode = utils_1.getNode(key, line);
|
|
stateQueue.push({ structure: objectNode, type: lineType });
|
|
return objectNode;
|
|
}
|
|
function getSimpleNode(line) {
|
|
var _a = line.content.split(utils_1.Charts.equal), key = _a[0], value = _a[1];
|
|
return utils_1.getNode(key.trim(), line, value.trim().replace(/"/g, ''));
|
|
}
|
|
function handleComplexObjectEnd(currNode, stateQueue, startLineType) {
|
|
var topState = stateQueue[stateQueue.length - 1];
|
|
if (topState.type !== startLineType || stateQueue.length === 0) {
|
|
throw new SyntaxError('Invalid TF Input - Object end without start');
|
|
}
|
|
if (!currNode) {
|
|
throw new SyntaxError('Invalid TF input - Object without parent');
|
|
}
|
|
stateQueue.pop();
|
|
topState = stateQueue[stateQueue.length - 1];
|
|
var topNode = topState.structure;
|
|
topNode.values.push(currNode);
|
|
return topNode;
|
|
}
|
|
//# sourceMappingURL=parser.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 978:
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.TerraformValidConfigurationTypes = exports.TFLineTypes = void 0;
|
|
var TFLineTypes;
|
|
(function (TFLineTypes) {
|
|
TFLineTypes[TFLineTypes["TYPE_START"] = 1] = "TYPE_START";
|
|
TFLineTypes[TFLineTypes["TYPE_END"] = 2] = "TYPE_END";
|
|
TFLineTypes[TFLineTypes["TYPE_START_AND_END"] = 3] = "TYPE_START_AND_END";
|
|
TFLineTypes[TFLineTypes["SUB_TYPE"] = 4] = "SUB_TYPE";
|
|
TFLineTypes[TFLineTypes["STRING"] = 5] = "STRING";
|
|
TFLineTypes[TFLineTypes["MULTILINE_STRING"] = 6] = "MULTILINE_STRING";
|
|
TFLineTypes[TFLineTypes["ARRAY_START_AND_END"] = 7] = "ARRAY_START_AND_END";
|
|
TFLineTypes[TFLineTypes["ARRAY_START"] = 8] = "ARRAY_START";
|
|
TFLineTypes[TFLineTypes["ARRAY_END"] = 9] = "ARRAY_END";
|
|
TFLineTypes[TFLineTypes["OBJECT_START_AND_END"] = 10] = "OBJECT_START_AND_END";
|
|
TFLineTypes[TFLineTypes["OBJECT_START"] = 11] = "OBJECT_START";
|
|
TFLineTypes[TFLineTypes["OBJECT_END"] = 12] = "OBJECT_END";
|
|
TFLineTypes[TFLineTypes["FUNCTION_START_AND_END"] = 13] = "FUNCTION_START_AND_END";
|
|
TFLineTypes[TFLineTypes["FUNCTION_START"] = 14] = "FUNCTION_START";
|
|
TFLineTypes[TFLineTypes["FUNCTION_END"] = 15] = "FUNCTION_END";
|
|
TFLineTypes[TFLineTypes["IGNORE"] = 99] = "IGNORE";
|
|
})(TFLineTypes = exports.TFLineTypes || (exports.TFLineTypes = {}));
|
|
exports.TerraformValidConfigurationTypes = ['terraform', 'locals'];
|
|
//# sourceMappingURL=types.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 41904:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.getNode = exports.getLineType = exports.getMultiLinePhrase = exports.getLineState = exports.Charts = void 0;
|
|
var types_1 = __webpack_require__(978);
|
|
exports.Charts = {
|
|
space: ' ',
|
|
equal: '=',
|
|
commentHash: '#',
|
|
commentDash: '//',
|
|
multilineCommentStart: '/*',
|
|
multilineCommentEnd: '*/',
|
|
multilinePhrase: '<<',
|
|
openBracketsObject: '{',
|
|
closeBracketsObject: '}',
|
|
openBracketsArray: '[',
|
|
closeBracketsArray: ']',
|
|
openFunction: '(',
|
|
closeFunction: ')',
|
|
};
|
|
function getLineState(line, isMultiLineComment, multiLinePhrase) {
|
|
var multiCommentLine = isMultiLineComment;
|
|
var ignoredLine = false;
|
|
if (line.content.startsWith(exports.Charts.multilineCommentStart)) {
|
|
ignoredLine = true;
|
|
multiCommentLine = true;
|
|
}
|
|
if (line.content.includes(exports.Charts.multilineCommentEnd)) {
|
|
// Multiline comment ended - this is still a commented line
|
|
ignoredLine = true;
|
|
multiCommentLine = false;
|
|
}
|
|
if (line.content.startsWith(exports.Charts.commentHash) ||
|
|
line.content.startsWith(exports.Charts.commentDash) ||
|
|
line.content.length === 0 //Empty Line
|
|
) {
|
|
ignoredLine = true;
|
|
}
|
|
// Inside a multiline comment
|
|
if (isMultiLineComment && !ignoredLine) {
|
|
ignoredLine = true;
|
|
}
|
|
// Inside a multiline phrase
|
|
if (multiLinePhrase.phrase &&
|
|
!line.content.includes(multiLinePhrase.phrase)) {
|
|
ignoredLine = true;
|
|
}
|
|
return {
|
|
ignoredLine: ignoredLine,
|
|
multiCommentLine: multiCommentLine,
|
|
};
|
|
}
|
|
exports.getLineState = getLineState;
|
|
function getMultiLinePhrase(line) {
|
|
var phrase = line.content
|
|
.split(exports.Charts.multilinePhrase)[1]
|
|
.trim()
|
|
.split(exports.Charts.space)[0];
|
|
return { phrase: phrase };
|
|
}
|
|
exports.getMultiLinePhrase = getMultiLinePhrase;
|
|
function getLineType(line, currentObjectType) {
|
|
if (!currentObjectType) {
|
|
if (line.content.includes(exports.Charts.openBracketsObject)) {
|
|
if (line.content.includes(exports.Charts.closeBracketsObject)) {
|
|
return types_1.TFLineTypes.TYPE_START_AND_END;
|
|
}
|
|
return types_1.TFLineTypes.TYPE_START;
|
|
}
|
|
throw new SyntaxError('Invalid TF input - TF Object without parent Type');
|
|
}
|
|
if (line.content.includes(exports.Charts.openBracketsArray)) {
|
|
if (line.content.includes(exports.Charts.closeBracketsArray)) {
|
|
return types_1.TFLineTypes.ARRAY_START_AND_END;
|
|
}
|
|
return types_1.TFLineTypes.ARRAY_START;
|
|
}
|
|
if (line.content.includes(exports.Charts.closeBracketsArray)) {
|
|
return types_1.TFLineTypes.ARRAY_END;
|
|
}
|
|
if (line.content.includes(exports.Charts.multilinePhrase)) {
|
|
return types_1.TFLineTypes.MULTILINE_STRING;
|
|
}
|
|
if (line.content.includes(exports.Charts.openFunction)) {
|
|
if (line.content.includes(exports.Charts.closeFunction)) {
|
|
return types_1.TFLineTypes.FUNCTION_START_AND_END;
|
|
}
|
|
return types_1.TFLineTypes.FUNCTION_START;
|
|
}
|
|
if (line.content.includes(exports.Charts.openBracketsObject)) {
|
|
if (line.content.includes(exports.Charts.closeBracketsObject)) {
|
|
if (line.content.includes(exports.Charts.equal)) {
|
|
return types_1.TFLineTypes.STRING;
|
|
}
|
|
return types_1.TFLineTypes.OBJECT_START_AND_END;
|
|
}
|
|
return types_1.TFLineTypes.OBJECT_START;
|
|
}
|
|
if (line.content.includes(exports.Charts.closeFunction)) {
|
|
if (currentObjectType != types_1.TFLineTypes.FUNCTION_START) {
|
|
throw new SyntaxError('Invalid TF input - Close function sign without open function');
|
|
}
|
|
return types_1.TFLineTypes.FUNCTION_END;
|
|
}
|
|
if (currentObjectType === types_1.TFLineTypes.FUNCTION_START) {
|
|
if (line.content.split(exports.Charts.space).length === 1) {
|
|
return types_1.TFLineTypes.IGNORE;
|
|
}
|
|
return types_1.TFLineTypes.STRING;
|
|
}
|
|
if (line.content.includes(exports.Charts.equal)) {
|
|
return types_1.TFLineTypes.STRING;
|
|
}
|
|
if (line.content.includes(exports.Charts.closeBracketsObject)) {
|
|
if (currentObjectType === types_1.TFLineTypes.SUB_TYPE) {
|
|
return types_1.TFLineTypes.TYPE_END;
|
|
}
|
|
return types_1.TFLineTypes.OBJECT_END;
|
|
}
|
|
if (line.content.startsWith(exports.Charts.multilinePhrase)) {
|
|
return types_1.TFLineTypes.MULTILINE_STRING;
|
|
}
|
|
if (currentObjectType === types_1.TFLineTypes.ARRAY_START) {
|
|
// Handling case of multi-line array object where the content is not yet finished.
|
|
// Those lines will be skipped as part of
|
|
// https://github.com/snyk/cloud-config-parser/blob/b5f5bdd8dd60cb3ad9c110bb6c640f08db0e108b/lib/issue-to-line/tf/parser.ts#L44
|
|
return types_1.TFLineTypes.STRING;
|
|
}
|
|
throw new SyntaxError("Invalid TF input - Unknown line type - " + line.content);
|
|
}
|
|
exports.getLineType = getLineType;
|
|
function getNode(key, line, values) {
|
|
var node = {
|
|
key: key,
|
|
lineLocation: {
|
|
line: line.number + 1,
|
|
columnStart: 0,
|
|
columnEnd: line.content.length,
|
|
},
|
|
values: values ? values : [],
|
|
};
|
|
return node;
|
|
}
|
|
exports.getNode = getNode;
|
|
//# sourceMappingURL=utils.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 95680:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
var _a;
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.getLineLocationForYamlElement = exports.findLineNumberOfGivenPath = exports.removeInputPathPrefix = exports.getPathDetails = exports.buildTreeForTypeMap = void 0;
|
|
var types_1 = __webpack_require__(60442);
|
|
var parser_1 = __webpack_require__(59559);
|
|
var parser_2 = __webpack_require__(25552);
|
|
var parser_3 = __webpack_require__(89179);
|
|
exports.buildTreeForTypeMap = (_a = {},
|
|
_a[types_1.CloudConfigFileTypes.YAML] = parser_1.buildYamlTreeMap,
|
|
_a[types_1.CloudConfigFileTypes.JSON] = parser_2.buildJsonTreeMap,
|
|
_a[types_1.CloudConfigFileTypes.TF] = parser_3.buildTfTreeMap,
|
|
_a);
|
|
function getPathDetails(path, fileType) {
|
|
if (fileType === types_1.CloudConfigFileTypes.YAML) {
|
|
return parser_1.getPathDetailsForYamlFile(path);
|
|
}
|
|
return {
|
|
docId: 0,
|
|
path: removeInputPathPrefix(path),
|
|
};
|
|
}
|
|
exports.getPathDetails = getPathDetails;
|
|
function removeInputPathPrefix(path) {
|
|
if (path[0] === 'input') {
|
|
return path.splice(1);
|
|
}
|
|
return path;
|
|
}
|
|
exports.removeInputPathPrefix = removeInputPathPrefix;
|
|
function findLineNumberOfGivenPath(nodes, pathDetails) {
|
|
var filteredNodes = nodes.filter(function (node) { return node.key === pathDetails.path[0]; });
|
|
if (filteredNodes.length === 0) {
|
|
// If the path does not exist, we will return '-1'
|
|
return -1;
|
|
}
|
|
if (pathDetails.path.length === 1) {
|
|
return filteredNodes[0].lineLocation.line;
|
|
}
|
|
return getLineNumberForSingleNode(filteredNodes[0], pathDetails.path.splice(1));
|
|
}
|
|
exports.findLineNumberOfGivenPath = findLineNumberOfGivenPath;
|
|
function getLineNumberForSingleNode(baseNode, remainingPath) {
|
|
var node = baseNode;
|
|
while (remainingPath.length) {
|
|
if (typeof node.values === 'string') {
|
|
return node.lineLocation.line;
|
|
}
|
|
var nodeForPath = getNodeForPath(node.values, remainingPath[0]);
|
|
if (!nodeForPath) {
|
|
//Not exists
|
|
return node.lineLocation.line;
|
|
}
|
|
node = nodeForPath;
|
|
remainingPath = remainingPath.splice(1);
|
|
}
|
|
return node.lineLocation.line;
|
|
}
|
|
function getNodeForPath(nodeValues, path) {
|
|
if (!path.includes('[')) {
|
|
return nodeValues.find(function (currNode) {
|
|
return currNode.key.startsWith(path + "[") || currNode.key === path;
|
|
});
|
|
}
|
|
var _a = path.replace(']', '').split('['), nodeName = _a[0], subNodeName = _a[1];
|
|
var subNodeId = parseInt(subNodeName);
|
|
if (!isNaN(subNodeId) && Number.isInteger(subNodeId)) {
|
|
return nodeValues.find(function (currNode) { return currNode.key === path; });
|
|
}
|
|
return nodeValues.find(function (currNode) {
|
|
var values = currNode.values;
|
|
if (typeof values !== 'string') {
|
|
return (currNode.key === path ||
|
|
(currNode.key.startsWith(nodeName) &&
|
|
values.filter(function (value) {
|
|
return value.key === 'name' && value.values === subNodeName;
|
|
}).length > 0));
|
|
}
|
|
return false;
|
|
});
|
|
}
|
|
function getLineLocationForYamlElement(nodeElement) {
|
|
return {
|
|
line: nodeElement.startMark.line + 1,
|
|
columnStart: nodeElement.startMark.pointer,
|
|
columnEnd: nodeElement.endMark.pointer,
|
|
};
|
|
}
|
|
exports.getLineLocationForYamlElement = getLineLocationForYamlElement;
|
|
//# sourceMappingURL=utils.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 59559:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.getPathDetailsForYamlFile = exports.buildYamlTreeMap = void 0;
|
|
var yamlJs = __webpack_require__(35740);
|
|
var utils_1 = __webpack_require__(95680);
|
|
var NULL_TAG = 'tag:yaml.org,2002:null';
|
|
var STR_TAG = 'tag:yaml.org,2002:str';
|
|
var INT_TAG = 'tag:yaml.org,2002:int';
|
|
var FLOAT_TAG = 'tag:yaml.org,2002:float';
|
|
var BOOL_TAG = 'tag:yaml.org,2002:bool';
|
|
var MAP_TAG = 'tag:yaml.org,2002:map';
|
|
var SEQ_TAG = 'tag:yaml.org,2002:seq';
|
|
var TIMESTAMP_TAG = 'tag:yaml.org,2002:timestamp';
|
|
var KEY_NODE_INDEX = 0;
|
|
var VAL_NODE_INDEX = 1;
|
|
var COMMENT_CHAR = '#';
|
|
var MULTI_DOC_SEPARATOR = '---';
|
|
function buildYamlTreeMap(yamlContent) {
|
|
var yamlTrees = {};
|
|
var docsArray = [];
|
|
try {
|
|
docsArray = yamlJs.compose_all(yamlContent);
|
|
}
|
|
catch (error) {
|
|
throw new Error('failed to compose_all for given yaml');
|
|
}
|
|
// Edge case that yamlJs does not handle -
|
|
// The first lines, before the first doc separator (---) are comments
|
|
// The yamlJs will ignore this lines and will have 1 less document than expected.
|
|
// This will only happen for the first document which document object will not be added for
|
|
if (yamlContent.startsWith(COMMENT_CHAR) &&
|
|
yamlContent.split(MULTI_DOC_SEPARATOR).length === docsArray.length + 1) {
|
|
/* eslint-disable @typescript-eslint/camelcase */
|
|
// Disable camelcase - object structure from yamlJs
|
|
var commentObject = {
|
|
start_mark: { line: 0, column: 0, pointer: 0, buffer: yamlContent },
|
|
end_mark: { line: 0, column: 0, pointer: 0, buffer: yamlContent },
|
|
style: undefined,
|
|
tag: NULL_TAG,
|
|
unique_id: 'node_0',
|
|
value: '',
|
|
};
|
|
/* eslint-enable @typescript-eslint/camelcase */
|
|
docsArray.unshift(commentObject);
|
|
}
|
|
for (var i = 0; i < docsArray.length; i++) {
|
|
var yamlDoc = convertComposeElementToType(docsArray[i]);
|
|
// Handle case of empty document - the tag will be null
|
|
// No need to build tree for this document
|
|
if (yamlDoc.tag !== NULL_TAG) {
|
|
yamlTrees[i] = buildTree(yamlDoc);
|
|
}
|
|
}
|
|
return yamlTrees;
|
|
}
|
|
exports.buildYamlTreeMap = buildYamlTreeMap;
|
|
function buildTree(yamlDoc) {
|
|
var _a;
|
|
var tree = { nodes: [] };
|
|
if (yamlDoc.tag !== MAP_TAG) {
|
|
throw new Error('Invalid tree - cannot build from map');
|
|
}
|
|
for (var _i = 0, _b = yamlDoc.value; _i < _b.length; _i++) {
|
|
var yamlElementValues = _b[_i];
|
|
var values = [
|
|
convertComposeElementToType(yamlElementValues[KEY_NODE_INDEX]),
|
|
convertComposeElementToType(yamlElementValues[VAL_NODE_INDEX]),
|
|
];
|
|
(_a = tree.nodes).push.apply(_a, buildTreeBranch(values, []));
|
|
}
|
|
return tree;
|
|
}
|
|
function buildTreeBranch(yamlElements, path) {
|
|
//We are checking on the valNode - which is the second element in the yamlElements array ([1])
|
|
switch (yamlElements[VAL_NODE_INDEX].tag) {
|
|
case NULL_TAG:
|
|
case STR_TAG:
|
|
case INT_TAG:
|
|
case FLOAT_TAG:
|
|
case BOOL_TAG:
|
|
case TIMESTAMP_TAG:
|
|
return buildPrimitiveLeaf(yamlElements);
|
|
case MAP_TAG:
|
|
return buildMapBranch(yamlElements, path);
|
|
case SEQ_TAG:
|
|
return buildSeqBranch(yamlElements, path);
|
|
default:
|
|
return [];
|
|
}
|
|
}
|
|
function buildPrimitiveLeaf(yamlElements) {
|
|
var keyNode = yamlElements[0], valNode = yamlElements[1];
|
|
var key = keyNode.value;
|
|
var values = valNode.value;
|
|
var lineLocation = utils_1.getLineLocationForYamlElement(keyNode);
|
|
return [
|
|
{
|
|
key: key,
|
|
lineLocation: lineLocation,
|
|
values: values,
|
|
},
|
|
];
|
|
}
|
|
function buildMapBranch(yamlElements, path) {
|
|
var keyNode = yamlElements[KEY_NODE_INDEX];
|
|
var fullPath = path.concat([keyNode.value]);
|
|
return [
|
|
getFileStructureNodesForYamlElement(yamlElements, keyNode.value, fullPath),
|
|
];
|
|
}
|
|
function buildSeqBranch(yamlElements, path) {
|
|
var keyNode = yamlElements[0], valNode = yamlElements[1];
|
|
var seqNodes = [];
|
|
for (var i = 0; i < valNode.value.length; i++) {
|
|
var nodeElement = convertComposeElementToType(valNode.value[i]);
|
|
var key = keyNode.value + "[" + i + "]";
|
|
var fullPath = path.concat(key);
|
|
if (typeof nodeElement.value === 'string') {
|
|
var lineLocation = utils_1.getLineLocationForYamlElement(nodeElement);
|
|
var node = {
|
|
key: key,
|
|
lineLocation: lineLocation,
|
|
values: nodeElement.value,
|
|
};
|
|
seqNodes.push(node);
|
|
}
|
|
else {
|
|
seqNodes.push(getFileStructureNodesForYamlElement([nodeElement, nodeElement], key, fullPath));
|
|
}
|
|
}
|
|
return seqNodes;
|
|
}
|
|
function convertComposeElementToType(yamlElement) {
|
|
return {
|
|
id: yamlElement.id,
|
|
tag: yamlElement.tag,
|
|
startMark: {
|
|
line: yamlElement.start_mark.line,
|
|
column: yamlElement.start_mark.column,
|
|
Buffer: yamlElement.start_mark.buffer,
|
|
pointer: yamlElement.start_mark.pointer,
|
|
},
|
|
endMark: {
|
|
line: yamlElement.end_mark.line,
|
|
column: yamlElement.end_mark.column,
|
|
Buffer: yamlElement.end_mark.buffer,
|
|
pointer: yamlElement.end_mark.pointer,
|
|
},
|
|
value: yamlElement.value,
|
|
};
|
|
}
|
|
function getFileStructureNodesForYamlElement(yamlElements, key, fullPath) {
|
|
var keyNode = yamlElements[0], valNode = yamlElements[1];
|
|
var nodes = [];
|
|
var lineLocation = utils_1.getLineLocationForYamlElement(keyNode);
|
|
for (var _i = 0, _a = valNode.value; _i < _a.length; _i++) {
|
|
var yamlElementValues = _a[_i];
|
|
var values = [
|
|
convertComposeElementToType(yamlElementValues[KEY_NODE_INDEX]),
|
|
convertComposeElementToType(yamlElementValues[VAL_NODE_INDEX]),
|
|
];
|
|
nodes.push.apply(nodes, buildTreeBranch(values, fullPath));
|
|
}
|
|
return {
|
|
key: key,
|
|
lineLocation: lineLocation,
|
|
values: nodes,
|
|
};
|
|
}
|
|
function getPathDetailsForYamlFile(path) {
|
|
var firstPath = path[0];
|
|
if (firstPath.includes('[DocId:')) {
|
|
var docId = firstPath.replace('[DocId: ', '').replace(']', '');
|
|
var pathWithoutDocId = path.splice(1);
|
|
return {
|
|
docId: parseInt(docId),
|
|
path: utils_1.removeInputPathPrefix(pathWithoutDocId),
|
|
};
|
|
}
|
|
return {
|
|
docId: 0,
|
|
path: utils_1.removeInputPathPrefix(path),
|
|
};
|
|
}
|
|
exports.getPathDetailsForYamlFile = getPathDetailsForYamlFile;
|
|
//# sourceMappingURL=parser.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 89639:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.parsePath = void 0;
|
|
var peggy = __webpack_require__(4193);
|
|
var grammar = "\n// Documentation, specifically for parsing delimited lists.\n// https://peggyjs.org/documentation#parsing-lists\n\n// A path is a dot delimeted list of identifiers.\npath = head:segment tail:(\".\" @segment)* { return [head, ...tail]; }\n\n// Segments consist of an identifier and an optional index.\n// e.g. hello or hello[world]\nsegment = $(identifier index?)\n\n// An identifier is a string of consecutive characters not consisting of dots, quotes or brackets. \nidentifier = [^'\"\\[\\]\\.]+\n\n// An index consists of square brackets containing a quoted or unquoted value.\n// e.g. hello['world'] or hello[world]\nindex = \"[\" $( unquoted_index / single_quoted_index / double_quoted_index) \"]\"\n\nunquoted_index = [^'\"\\]\\[]+\nsingle_quoted_index = \"'\" [^']+ \"'\"\ndouble_quoted_index = '\"' [^\"]+ '\"'\n";
|
|
exports.parsePath = createPathParser();
|
|
function createPathParser() {
|
|
var parser = peggy.generate(grammar);
|
|
return function (expr) {
|
|
try {
|
|
return parser.parse(expr);
|
|
}
|
|
catch (e) {
|
|
return expr.split('.');
|
|
}
|
|
};
|
|
}
|
|
//# sourceMappingURL=path.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 60442:
|
|
/***/ ((__unused_webpack_module, exports) => {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.CloudConfigFileTypes = void 0;
|
|
var CloudConfigFileTypes;
|
|
(function (CloudConfigFileTypes) {
|
|
CloudConfigFileTypes[CloudConfigFileTypes["YAML"] = 1] = "YAML";
|
|
CloudConfigFileTypes[CloudConfigFileTypes["JSON"] = 2] = "JSON";
|
|
CloudConfigFileTypes[CloudConfigFileTypes["TF"] = 3] = "TF";
|
|
})(CloudConfigFileTypes = exports.CloudConfigFileTypes || (exports.CloudConfigFileTypes = {}));
|
|
//# sourceMappingURL=types.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 54232:
|
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
exports.parseFileContent = void 0;
|
|
var YAML = __webpack_require__(6792);
|
|
function parseFileContent(fileContent) {
|
|
// the YAML library can parse both YAML and JSON content, as well as content with singe/multiple YAMLs
|
|
// by using this library we don't have to disambiguate between these different contents ourselves
|
|
return YAML.parseAllDocuments(fileContent).map(function (doc) {
|
|
if (shouldThrowErrorFor(doc)) {
|
|
throw doc.errors[0];
|
|
}
|
|
if (showThrowWarningFor(doc)) {
|
|
throw doc.warnings[0];
|
|
}
|
|
return doc.toJSON();
|
|
});
|
|
}
|
|
exports.parseFileContent = parseFileContent;
|
|
function shouldThrowErrorFor(doc) {
|
|
var errorsToSkip = [
|
|
'Insufficient indentation in flow collection',
|
|
'Map keys must be unique',
|
|
];
|
|
return (doc.errors.length !== 0 &&
|
|
!errorsToSkip.some(function (e) { return doc.errors[0].message.includes(e); }));
|
|
}
|
|
function showThrowWarningFor(doc) {
|
|
var warningsToInclude = [
|
|
'Keys with collection values will be stringified as YAML due to JS Object restrictions. Use mapAsMap: true to avoid this.',
|
|
];
|
|
return (doc.warnings.length !== 0 &&
|
|
warningsToInclude.some(function (e) { return doc.warnings[0].message.includes(e); }));
|
|
}
|
|
//# sourceMappingURL=index.js.map
|
|
|
|
/***/ }),
|
|
|
|
/***/ 75316:
|
|
/***/ ((module, exports, __webpack_require__) => {
|
|
|
|
/* module decorator */ module = __webpack_require__.nmd(module);
|
|
/**
|
|
* lodash (Custom Build) <https://lodash.com/>
|
|
* Build: `lodash modularize exports="npm" -o ./`
|
|
* 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
|
|
*/
|
|
|
|
/** 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 to compose bitmasks for comparison styles. */
|
|
var UNORDERED_COMPARE_FLAG = 1,
|
|
PARTIAL_COMPARE_FLAG = 2;
|
|
|
|
/** Used as references for various `Number` constants. */
|
|
var INFINITY = 1 / 0,
|
|
MAX_SAFE_INTEGER = 9007199254740991;
|
|
|
|
/** `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]';
|
|
|
|
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 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/7.0/#sec-patterns).
|
|
*/
|
|
var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
|
|
|
|
/** Used to match backslashes in property paths. */
|
|
var reEscapeChar = /\\(\\)?/g;
|
|
|
|
/** Used to detect host constructors (Safari). */
|
|
var reIsHostCtor = /^\[object .+?Constructor\]$/;
|
|
|
|
/** Used to detect unsigned integer values. */
|
|
var reIsUint = /^(?:0|[1-9]\d*)$/;
|
|
|
|
/** 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;
|
|
|
|
/** 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 = true && exports && !exports.nodeType && exports;
|
|
|
|
/** Detect free variable `module`. */
|
|
var freeModule = freeExports && "object" == '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 nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
|
|
/**
|
|
* 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 `_.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 `_.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 `_.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 `_.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);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 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 `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 unary function that invokes `func` with its 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));
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
|
|
/** Used for built-in method references. */
|
|
var arrayProto = Array.prototype,
|
|
funcProto = Function.prototype,
|
|
objectProto = Object.prototype;
|
|
|
|
/** Used to detect overreaching core-js shims. */
|
|
var coreJsData = root['__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 = funcProto.toString;
|
|
|
|
/** Used to check objects for own properties. */
|
|
var hasOwnProperty = objectProto.hasOwnProperty;
|
|
|
|
/**
|
|
* Used to resolve the
|
|
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
|
|
* of values.
|
|
*/
|
|
var objectToString = objectProto.toString;
|
|
|
|
/** 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 Symbol = root.Symbol,
|
|
Uint8Array = root.Uint8Array,
|
|
propertyIsEnumerable = objectProto.propertyIsEnumerable,
|
|
splice = arrayProto.splice;
|
|
|
|
/* Built-in method references for those with the same name as other `lodash` methods. */
|
|
var nativeKeys = overArg(Object.keys, Object);
|
|
|
|
/* Built-in method references that are verified to be native. */
|
|
var DataView = getNative(root, 'DataView'),
|
|
Map = getNative(root, 'Map'),
|
|
Promise = getNative(root, 'Promise'),
|
|
Set = getNative(root, 'Set'),
|
|
WeakMap = getNative(root, 'WeakMap'),
|
|
nativeCreate = getNative(Object, 'create');
|
|
|
|
/** 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 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;
|
|
|
|
/**
|
|
* Creates an array of the enumerable property names of the array-like `value`.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to query.
|
|
* @param {boolean} inherited Specify returning inherited property names.
|
|
* @returns {Array} Returns the array of property names.
|
|
*/
|
|
function arrayLikeKeys(value, inherited) {
|
|
// Safari 8.1 makes `arguments.callee` enumerable in strict mode.
|
|
// Safari 9 makes `arguments.length` enumerable in strict mode.
|
|
var result = (isArray(value) || isArguments(value))
|
|
? baseTimes(value.length, String)
|
|
: [];
|
|
|
|
var length = result.length,
|
|
skipIndexes = !!length;
|
|
|
|
for (var key in value) {
|
|
if ((inherited || hasOwnProperty.call(value, key)) &&
|
|
!(skipIndexes && (key == 'length' || isIndex(key, length)))) {
|
|
result.push(key);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Gets the index at which the `key` is found in `array` of key-value pairs.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to inspect.
|
|
* @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;
|
|
}
|
|
|
|
/**
|
|
* 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 `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();
|
|
|
|
/**
|
|
* 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 `_.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 `getTag`.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to query.
|
|
* @returns {string} Returns the `toStringTag`.
|
|
*/
|
|
function baseGetTag(value) {
|
|
return objectToString.call(value);
|
|
}
|
|
|
|
/**
|
|
* 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 `_.isEqual` which supports partial comparisons
|
|
* and tracks traversed objects.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to compare.
|
|
* @param {*} other The other value to compare.
|
|
* @param {Function} [customizer] The function to customize comparisons.
|
|
* @param {boolean} [bitmask] The bitmask of comparison flags.
|
|
* The bitmask may be composed of the following flags:
|
|
* 1 - Unordered comparison
|
|
* 2 - Partial comparison
|
|
* @param {Object} [stack] Tracks traversed `value` and `other` objects.
|
|
* @returns {boolean} Returns `true` if the values are equivalent, else `false`.
|
|
*/
|
|
function baseIsEqual(value, other, customizer, bitmask, stack) {
|
|
if (value === other) {
|
|
return true;
|
|
}
|
|
if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) {
|
|
return value !== value && other !== other;
|
|
}
|
|
return baseIsEqualDeep(value, other, baseIsEqual, customizer, bitmask, stack);
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `baseIsEqual` for arrays and objects which performs
|
|
* deep comparisons and tracks traversed objects enabling objects with circular
|
|
* references to be compared.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to compare.
|
|
* @param {Object} other The other object to compare.
|
|
* @param {Function} equalFunc The function to determine equivalents of values.
|
|
* @param {Function} [customizer] The function to customize comparisons.
|
|
* @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual`
|
|
* for more details.
|
|
* @param {Object} [stack] Tracks traversed `object` and `other` objects.
|
|
* @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
|
|
*/
|
|
function baseIsEqualDeep(object, other, equalFunc, customizer, bitmask, stack) {
|
|
var objIsArr = isArray(object),
|
|
othIsArr = isArray(other),
|
|
objTag = arrayTag,
|
|
othTag = arrayTag;
|
|
|
|
if (!objIsArr) {
|
|
objTag = getTag(object);
|
|
objTag = objTag == argsTag ? objectTag : objTag;
|
|
}
|
|
if (!othIsArr) {
|
|
othTag = getTag(other);
|
|
othTag = othTag == argsTag ? objectTag : othTag;
|
|
}
|
|
var objIsObj = objTag == objectTag && !isHostObject(object),
|
|
othIsObj = othTag == objectTag && !isHostObject(other),
|
|
isSameTag = objTag == othTag;
|
|
|
|
if (isSameTag && !objIsObj) {
|
|
stack || (stack = new Stack);
|
|
return (objIsArr || isTypedArray(object))
|
|
? equalArrays(object, other, equalFunc, customizer, bitmask, stack)
|
|
: equalByTag(object, other, objTag, equalFunc, customizer, bitmask, stack);
|
|
}
|
|
if (!(bitmask & PARTIAL_COMPARE_FLAG)) {
|
|
var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
|
|
othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
|
|
|
|
if (objIsWrapped || othIsWrapped) {
|
|
var objUnwrapped = objIsWrapped ? object.value() : object,
|
|
othUnwrapped = othIsWrapped ? other.value() : other;
|
|
|
|
stack || (stack = new Stack);
|
|
return equalFunc(objUnwrapped, othUnwrapped, customizer, bitmask, stack);
|
|
}
|
|
}
|
|
if (!isSameTag) {
|
|
return false;
|
|
}
|
|
stack || (stack = new Stack);
|
|
return equalObjects(object, other, equalFunc, customizer, bitmask, stack);
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.isMatch` without support for iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to inspect.
|
|
* @param {Object} source The object of property values to match.
|
|
* @param {Array} matchData The property names, values, and compare flags to match.
|
|
* @param {Function} [customizer] The function to customize comparisons.
|
|
* @returns {boolean} Returns `true` if `object` is a match, else `false`.
|
|
*/
|
|
function baseIsMatch(object, source, matchData, customizer) {
|
|
var index = matchData.length,
|
|
length = index,
|
|
noCustomizer = !customizer;
|
|
|
|
if (object == null) {
|
|
return !length;
|
|
}
|
|
object = Object(object);
|
|
while (index--) {
|
|
var data = matchData[index];
|
|
if ((noCustomizer && data[2])
|
|
? data[1] !== object[data[0]]
|
|
: !(data[0] in object)
|
|
) {
|
|
return false;
|
|
}
|
|
}
|
|
while (++index < length) {
|
|
data = matchData[index];
|
|
var key = data[0],
|
|
objValue = object[key],
|
|
srcValue = data[1];
|
|
|
|
if (noCustomizer && data[2]) {
|
|
if (objValue === undefined && !(key in object)) {
|
|
return false;
|
|
}
|
|
} else {
|
|
var stack = new Stack;
|
|
if (customizer) {
|
|
var result = customizer(objValue, srcValue, key, object, source, stack);
|
|
}
|
|
if (!(result === undefined
|
|
? baseIsEqual(srcValue, objValue, customizer, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG, stack)
|
|
: result
|
|
)) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.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 `_.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 treat sparse arrays as dense.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to query.
|
|
* @returns {Array} Returns the array of property names.
|
|
*/
|
|
function baseKeys(object) {
|
|
if (!isPrototype(object)) {
|
|
return nativeKeys(object);
|
|
}
|
|
var result = [];
|
|
for (var key in Object(object)) {
|
|
if (hasOwnProperty.call(object, key) && key != 'constructor') {
|
|
result.push(key);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* 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 `_.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(baseIteratee));
|
|
|
|
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);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 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 `_.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;
|
|
}
|
|
|
|
/**
|
|
* 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);
|
|
}
|
|
|
|
/**
|
|
* 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 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;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 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/7.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 : hasOwnProperty.call(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;
|
|
}
|
|
|
|
/**
|
|
* 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 `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 < 14, 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;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 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) || isArguments(object));
|
|
}
|
|
|
|
/**
|
|
* 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 `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 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 `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)));
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 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 '';
|
|
}
|
|
|
|
/**
|
|
* 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 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/7.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;
|
|
|
|
/**
|
|
* Performs a
|
|
* [`SameValueZero`](http://ecma-international.org/ecma-262/7.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 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 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 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(value.length) && !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 `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-9 which returns 'object' for typed array and other constructors.
|
|
var tag = isObject(value) ? objectToString.call(value) : '';
|
|
return tag == funcTag || tag == genTag;
|
|
}
|
|
|
|
/**
|
|
* Checks if `value` is a valid array-like length.
|
|
*
|
|
* **Note:** This method is loosely based on
|
|
* [`ToLength`](http://ecma-international.org/ecma-262/7.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/7.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 `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;
|
|
|
|
/**
|
|
* 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);
|
|
}
|
|
|
|
/**
|
|
* 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 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 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/7.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) {
|
|
return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
|
|
}
|
|
|
|
/**
|
|
* 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 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);
|
|
}
|
|
|
|
module.exports = orderBy;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 96486:
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/* module decorator */ module = __webpack_require__.nmd(module);
|
|
var __WEBPACK_AMD_DEFINE_RESULT__;/**
|
|
* @license
|
|
* Lodash <https://lodash.com/>
|
|
* Copyright OpenJS Foundation and other contributors <https://openjsf.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.17.21';
|
|
|
|
/** Used as the size to enable large array optimizations. */
|
|
var LARGE_ARRAY_SIZE = 200;
|
|
|
|
/** Error message constants. */
|
|
var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.',
|
|
FUNC_ERROR_TEXT = 'Expected a function',
|
|
INVALID_TEMPL_VAR_ERROR_TEXT = 'Invalid `variable` option passed into `_.template`';
|
|
|
|
/** Used to stand-in for `undefined` hash values. */
|
|
var HASH_UNDEFINED = '__lodash_hash_undefined__';
|
|
|
|
/** Used as the maximum memoize cache size. */
|
|
var MAX_MEMOIZE_SIZE = 500;
|
|
|
|
/** Used as the internal argument placeholder. */
|
|
var PLACEHOLDER = '__lodash_placeholder__';
|
|
|
|
/** Used to compose bitmasks for cloning. */
|
|
var CLONE_DEEP_FLAG = 1,
|
|
CLONE_FLAT_FLAG = 2,
|
|
CLONE_SYMBOLS_FLAG = 4;
|
|
|
|
/** Used to compose bitmasks for value comparisons. */
|
|
var COMPARE_PARTIAL_FLAG = 1,
|
|
COMPARE_UNORDERED_FLAG = 2;
|
|
|
|
/** Used to compose bitmasks for function metadata. */
|
|
var WRAP_BIND_FLAG = 1,
|
|
WRAP_BIND_KEY_FLAG = 2,
|
|
WRAP_CURRY_BOUND_FLAG = 4,
|
|
WRAP_CURRY_FLAG = 8,
|
|
WRAP_CURRY_RIGHT_FLAG = 16,
|
|
WRAP_PARTIAL_FLAG = 32,
|
|
WRAP_PARTIAL_RIGHT_FLAG = 64,
|
|
WRAP_ARY_FLAG = 128,
|
|
WRAP_REARG_FLAG = 256,
|
|
WRAP_FLIP_FLAG = 512;
|
|
|
|
/** 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 = 800,
|
|
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', WRAP_ARY_FLAG],
|
|
['bind', WRAP_BIND_FLAG],
|
|
['bindKey', WRAP_BIND_KEY_FLAG],
|
|
['curry', WRAP_CURRY_FLAG],
|
|
['curryRight', WRAP_CURRY_RIGHT_FLAG],
|
|
['flip', WRAP_FLIP_FLAG],
|
|
['partial', WRAP_PARTIAL_FLAG],
|
|
['partialRight', WRAP_PARTIAL_RIGHT_FLAG],
|
|
['rearg', WRAP_REARG_FLAG]
|
|
];
|
|
|
|
/** `Object#toString` result references. */
|
|
var argsTag = '[object Arguments]',
|
|
arrayTag = '[object Array]',
|
|
asyncTag = '[object AsyncFunction]',
|
|
boolTag = '[object Boolean]',
|
|
dateTag = '[object Date]',
|
|
domExcTag = '[object DOMException]',
|
|
errorTag = '[object Error]',
|
|
funcTag = '[object Function]',
|
|
genTag = '[object GeneratorFunction]',
|
|
mapTag = '[object Map]',
|
|
numberTag = '[object Number]',
|
|
nullTag = '[object Null]',
|
|
objectTag = '[object Object]',
|
|
promiseTag = '[object Promise]',
|
|
proxyTag = '[object Proxy]',
|
|
regexpTag = '[object RegExp]',
|
|
setTag = '[object Set]',
|
|
stringTag = '[object String]',
|
|
symbolTag = '[object Symbol]',
|
|
undefinedTag = '[object Undefined]',
|
|
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);/g,
|
|
reUnescapedHtml = /[&<>"']/g,
|
|
reHasEscapedHtml = RegExp(reEscapedHtml.source),
|
|
reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
|
|
|
|
/** Used to match template delimiters. */
|
|
var reEscape = /<%-([\s\S]+?)%>/g,
|
|
reEvaluate = /<%([\s\S]+?)%>/g,
|
|
reInterpolate = /<%=([\s\S]+?)%>/g;
|
|
|
|
/** Used to match property names within property paths. */
|
|
var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
|
|
reIsPlainProp = /^\w*$/,
|
|
rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
|
|
|
|
/**
|
|
* Used to match `RegExp`
|
|
* [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
|
|
*/
|
|
var reRegExpChar = /[\\^$.*+?()[\]{}|]/g,
|
|
reHasRegExpChar = RegExp(reRegExpChar.source);
|
|
|
|
/** Used to match leading whitespace. */
|
|
var reTrimStart = /^\s+/;
|
|
|
|
/** Used to match a single whitespace character. */
|
|
var reWhitespace = /\s/;
|
|
|
|
/** Used to match wrap detail comments. */
|
|
var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,
|
|
reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/,
|
|
reSplitDetails = /,? & /;
|
|
|
|
/** Used to match words composed of alphanumeric characters. */
|
|
var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
|
|
|
|
/**
|
|
* Used to validate the `validate` option in `_.template` variable.
|
|
*
|
|
* Forbids characters which could potentially change the meaning of the function argument definition:
|
|
* - "()," (modification of function parameters)
|
|
* - "=" (default value)
|
|
* - "[]{}" (destructuring of function parameters)
|
|
* - "/" (beginning of a comment)
|
|
* - whitespace
|
|
*/
|
|
var reForbiddenIdentifierChars = /[()=,{}\[\]\/\s]/;
|
|
|
|
/** Used to match backslashes in property paths. */
|
|
var reEscapeChar = /\\(\\)?/g;
|
|
|
|
/**
|
|
* Used to match
|
|
* [ES template delimiters](http://ecma-international.org/ecma-262/7.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 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 Unicode letters (excluding mathematical operators). */
|
|
var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/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',
|
|
reComboHalfMarksRange = '\\ufe20-\\ufe2f',
|
|
rsComboSymbolsRange = '\\u20d0-\\u20ff',
|
|
rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,
|
|
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 = '[' + rsComboRange + ']',
|
|
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 rsMiscLower = '(?:' + rsLower + '|' + rsMisc + ')',
|
|
rsMiscUpper = '(?:' + rsUpper + '|' + rsMisc + ')',
|
|
rsOptContrLower = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?',
|
|
rsOptContrUpper = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?',
|
|
reOptMod = rsModifier + '?',
|
|
rsOptVar = '[' + rsVarRange + ']?',
|
|
rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',
|
|
rsOrdLower = '\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])',
|
|
rsOrdUpper = '\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])',
|
|
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 reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');
|
|
|
|
/** Used to match complex or compound words. */
|
|
var reUnicodeWord = RegExp([
|
|
rsUpper + '?' + rsLower + '+' + rsOptContrLower + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')',
|
|
rsMiscUpper + '+' + rsOptContrUpper + '(?=' + [rsBreak, rsUpper + rsMiscLower, '$'].join('|') + ')',
|
|
rsUpper + '?' + rsMiscLower + '+' + rsOptContrLower,
|
|
rsUpper + '+' + rsOptContrUpper,
|
|
rsOrdUpper,
|
|
rsOrdLower,
|
|
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 reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']');
|
|
|
|
/** Used to detect strings that need a more robust regexp to match words. */
|
|
var reHasUnicodeWord = /[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', '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 Unicode letters to basic Latin letters. */
|
|
var deburredLetters = {
|
|
// Latin-1 Supplement block.
|
|
'\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',
|
|
// Latin Extended-A block.
|
|
'\u0100': 'A', '\u0102': 'A', '\u0104': 'A',
|
|
'\u0101': 'a', '\u0103': 'a', '\u0105': 'a',
|
|
'\u0106': 'C', '\u0108': 'C', '\u010a': 'C', '\u010c': 'C',
|
|
'\u0107': 'c', '\u0109': 'c', '\u010b': 'c', '\u010d': 'c',
|
|
'\u010e': 'D', '\u0110': 'D', '\u010f': 'd', '\u0111': 'd',
|
|
'\u0112': 'E', '\u0114': 'E', '\u0116': 'E', '\u0118': 'E', '\u011a': 'E',
|
|
'\u0113': 'e', '\u0115': 'e', '\u0117': 'e', '\u0119': 'e', '\u011b': 'e',
|
|
'\u011c': 'G', '\u011e': 'G', '\u0120': 'G', '\u0122': 'G',
|
|
'\u011d': 'g', '\u011f': 'g', '\u0121': 'g', '\u0123': 'g',
|
|
'\u0124': 'H', '\u0126': 'H', '\u0125': 'h', '\u0127': 'h',
|
|
'\u0128': 'I', '\u012a': 'I', '\u012c': 'I', '\u012e': 'I', '\u0130': 'I',
|
|
'\u0129': 'i', '\u012b': 'i', '\u012d': 'i', '\u012f': 'i', '\u0131': 'i',
|
|
'\u0134': 'J', '\u0135': 'j',
|
|
'\u0136': 'K', '\u0137': 'k', '\u0138': 'k',
|
|
'\u0139': 'L', '\u013b': 'L', '\u013d': 'L', '\u013f': 'L', '\u0141': 'L',
|
|
'\u013a': 'l', '\u013c': 'l', '\u013e': 'l', '\u0140': 'l', '\u0142': 'l',
|
|
'\u0143': 'N', '\u0145': 'N', '\u0147': 'N', '\u014a': 'N',
|
|
'\u0144': 'n', '\u0146': 'n', '\u0148': 'n', '\u014b': 'n',
|
|
'\u014c': 'O', '\u014e': 'O', '\u0150': 'O',
|
|
'\u014d': 'o', '\u014f': 'o', '\u0151': 'o',
|
|
'\u0154': 'R', '\u0156': 'R', '\u0158': 'R',
|
|
'\u0155': 'r', '\u0157': 'r', '\u0159': 'r',
|
|
'\u015a': 'S', '\u015c': 'S', '\u015e': 'S', '\u0160': 'S',
|
|
'\u015b': 's', '\u015d': 's', '\u015f': 's', '\u0161': 's',
|
|
'\u0162': 'T', '\u0164': 'T', '\u0166': 'T',
|
|
'\u0163': 't', '\u0165': 't', '\u0167': 't',
|
|
'\u0168': 'U', '\u016a': 'U', '\u016c': 'U', '\u016e': 'U', '\u0170': 'U', '\u0172': 'U',
|
|
'\u0169': 'u', '\u016b': 'u', '\u016d': 'u', '\u016f': 'u', '\u0171': 'u', '\u0173': 'u',
|
|
'\u0174': 'W', '\u0175': 'w',
|
|
'\u0176': 'Y', '\u0177': 'y', '\u0178': 'Y',
|
|
'\u0179': 'Z', '\u017b': 'Z', '\u017d': 'Z',
|
|
'\u017a': 'z', '\u017c': 'z', '\u017e': 'z',
|
|
'\u0132': 'IJ', '\u0133': 'ij',
|
|
'\u0152': 'Oe', '\u0153': 'oe',
|
|
'\u0149': "'n", '\u017f': 's'
|
|
};
|
|
|
|
/** 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 = true && exports && !exports.nodeType && exports;
|
|
|
|
/** Detect free variable `module`. */
|
|
var freeModule = freeExports && "object" == '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 {
|
|
// Use `util.types` for Node.js 10+.
|
|
var types = freeModule && freeModule.require && freeModule.require('util').types;
|
|
|
|
if (types) {
|
|
return types;
|
|
}
|
|
|
|
// Legacy `process.binding('util')` for Node.js < 10.
|
|
return freeProcess && freeProcess.binding && 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;
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* 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 == null ? 0 : array.length;
|
|
|
|
while (++index < length) {
|
|
var value = array[index];
|
|
setter(accumulator, value, iteratee(value), array);
|
|
}
|
|
return accumulator;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.forEach` for arrays without support for
|
|
* iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Array} [array] The array to iterate over.
|
|
* @param {Function} iteratee The function invoked per iteration.
|
|
* @returns {Array} Returns `array`.
|
|
*/
|
|
function arrayEach(array, iteratee) {
|
|
var index = -1,
|
|
length = array == null ? 0 : array.length;
|
|
|
|
while (++index < length) {
|
|
if (iteratee(array[index], index, array) === false) {
|
|
break;
|
|
}
|
|
}
|
|
return array;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.forEachRight` for arrays without support for
|
|
* iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Array} [array] The array to iterate over.
|
|
* @param {Function} iteratee The function invoked per iteration.
|
|
* @returns {Array} Returns `array`.
|
|
*/
|
|
function arrayEachRight(array, iteratee) {
|
|
var length = array == null ? 0 : array.length;
|
|
|
|
while (length--) {
|
|
if (iteratee(array[length], length, array) === false) {
|
|
break;
|
|
}
|
|
}
|
|
return array;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.every` for arrays without support for
|
|
* iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Array} [array] The array to iterate over.
|
|
* @param {Function} predicate The function invoked per iteration.
|
|
* @returns {boolean} Returns `true` if all elements pass the predicate check,
|
|
* else `false`.
|
|
*/
|
|
function arrayEvery(array, predicate) {
|
|
var index = -1,
|
|
length = array == null ? 0 : array.length;
|
|
|
|
while (++index < length) {
|
|
if (!predicate(array[index], index, array)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.filter` for arrays without support for
|
|
* iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Array} [array] The array to iterate over.
|
|
* @param {Function} predicate The function invoked per iteration.
|
|
* @returns {Array} Returns the new filtered array.
|
|
*/
|
|
function arrayFilter(array, predicate) {
|
|
var index = -1,
|
|
length = array == null ? 0 : array.length,
|
|
resIndex = 0,
|
|
result = [];
|
|
|
|
while (++index < length) {
|
|
var value = array[index];
|
|
if (predicate(value, index, array)) {
|
|
result[resIndex++] = value;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.includes` for arrays without support for
|
|
* specifying an index to search from.
|
|
*
|
|
* @private
|
|
* @param {Array} [array] The array to inspect.
|
|
* @param {*} target The value to search for.
|
|
* @returns {boolean} Returns `true` if `target` is found, else `false`.
|
|
*/
|
|
function arrayIncludes(array, value) {
|
|
var length = array == null ? 0 : array.length;
|
|
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 inspect.
|
|
* @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 == null ? 0 : array.length;
|
|
|
|
while (++index < length) {
|
|
if (comparator(value, array[index])) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.map` for arrays without support for iteratee
|
|
* shorthands.
|
|
*
|
|
* @private
|
|
* @param {Array} [array] The array to iterate over.
|
|
* @param {Function} iteratee The function invoked per iteration.
|
|
* @returns {Array} Returns the new mapped array.
|
|
*/
|
|
function arrayMap(array, iteratee) {
|
|
var index = -1,
|
|
length = array == null ? 0 : array.length,
|
|
result = Array(length);
|
|
|
|
while (++index < length) {
|
|
result[index] = iteratee(array[index], index, array);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Appends the elements of `values` to `array`.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to modify.
|
|
* @param {Array} values The values to append.
|
|
* @returns {Array} Returns `array`.
|
|
*/
|
|
function arrayPush(array, values) {
|
|
var index = -1,
|
|
length = values.length,
|
|
offset = array.length;
|
|
|
|
while (++index < length) {
|
|
array[offset + index] = values[index];
|
|
}
|
|
return array;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.reduce` for arrays without support for
|
|
* iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Array} [array] The array to iterate over.
|
|
* @param {Function} iteratee The function invoked per iteration.
|
|
* @param {*} [accumulator] The initial value.
|
|
* @param {boolean} [initAccum] Specify using the first element of `array` as
|
|
* the initial value.
|
|
* @returns {*} Returns the accumulated value.
|
|
*/
|
|
function arrayReduce(array, iteratee, accumulator, initAccum) {
|
|
var index = -1,
|
|
length = array == null ? 0 : array.length;
|
|
|
|
if (initAccum && length) {
|
|
accumulator = array[++index];
|
|
}
|
|
while (++index < length) {
|
|
accumulator = iteratee(accumulator, array[index], index, array);
|
|
}
|
|
return accumulator;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.reduceRight` for arrays without support for
|
|
* iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Array} [array] The array to iterate over.
|
|
* @param {Function} iteratee The function invoked per iteration.
|
|
* @param {*} [accumulator] The initial value.
|
|
* @param {boolean} [initAccum] Specify using the last element of `array` as
|
|
* the initial value.
|
|
* @returns {*} Returns the accumulated value.
|
|
*/
|
|
function arrayReduceRight(array, iteratee, accumulator, initAccum) {
|
|
var length = array == null ? 0 : array.length;
|
|
if (initAccum && length) {
|
|
accumulator = array[--length];
|
|
}
|
|
while (length--) {
|
|
accumulator = iteratee(accumulator, array[length], length, array);
|
|
}
|
|
return accumulator;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.some` for arrays without support for iteratee
|
|
* shorthands.
|
|
*
|
|
* @private
|
|
* @param {Array} [array] The array to iterate over.
|
|
* @param {Function} predicate The function invoked per iteration.
|
|
* @returns {boolean} Returns `true` if any element passes the predicate check,
|
|
* else `false`.
|
|
*/
|
|
function arraySome(array, predicate) {
|
|
var index = -1,
|
|
length = array == null ? 0 : array.length;
|
|
|
|
while (++index < length) {
|
|
if (predicate(array[index], index, array)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Gets the size of an ASCII `string`.
|
|
*
|
|
* @private
|
|
* @param {string} string The string inspect.
|
|
* @returns {number} Returns the string size.
|
|
*/
|
|
var asciiSize = baseProperty('length');
|
|
|
|
/**
|
|
* Converts an ASCII `string` to an array.
|
|
*
|
|
* @private
|
|
* @param {string} string The string to convert.
|
|
* @returns {Array} Returns the converted array.
|
|
*/
|
|
function asciiToArray(string) {
|
|
return string.split('');
|
|
}
|
|
|
|
/**
|
|
* Splits an ASCII `string` into an array of its words.
|
|
*
|
|
* @private
|
|
* @param {string} The string to inspect.
|
|
* @returns {Array} Returns the words of `string`.
|
|
*/
|
|
function asciiWords(string) {
|
|
return string.match(reAsciiWord) || [];
|
|
}
|
|
|
|
/**
|
|
* 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 inspect.
|
|
* @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 inspect.
|
|
* @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 inspect.
|
|
* @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) {
|
|
return value === value
|
|
? strictIndexOf(array, value, fromIndex)
|
|
: baseFindIndex(array, baseIsNaN, fromIndex);
|
|
}
|
|
|
|
/**
|
|
* This function is like `baseIndexOf` except that it accepts a comparator.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to inspect.
|
|
* @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 == null ? 0 : array.length;
|
|
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 `_.trim`.
|
|
*
|
|
* @private
|
|
* @param {string} string The string to trim.
|
|
* @returns {string} Returns the trimmed string.
|
|
*/
|
|
function baseTrim(string) {
|
|
return string
|
|
? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '')
|
|
: string;
|
|
}
|
|
|
|
/**
|
|
* 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 Supplement and Latin Extended-A
|
|
* 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 `string` contains Unicode symbols.
|
|
*
|
|
* @private
|
|
* @param {string} string The string to inspect.
|
|
* @returns {boolean} Returns `true` if a symbol is found, else `false`.
|
|
*/
|
|
function hasUnicode(string) {
|
|
return reHasUnicode.test(string);
|
|
}
|
|
|
|
/**
|
|
* Checks if `string` contains a word composed of Unicode symbols.
|
|
*
|
|
* @private
|
|
* @param {string} string The string to inspect.
|
|
* @returns {boolean} Returns `true` if a word is found, else `false`.
|
|
*/
|
|
function hasUnicodeWord(string) {
|
|
return reHasUnicodeWord.test(string);
|
|
}
|
|
|
|
/**
|
|
* 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 unary function that invokes `func` with its 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;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.indexOf` which performs strict equality
|
|
* comparisons of values, i.e. `===`.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to inspect.
|
|
* @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 strictIndexOf(array, value, fromIndex) {
|
|
var index = fromIndex - 1,
|
|
length = array.length;
|
|
|
|
while (++index < length) {
|
|
if (array[index] === value) {
|
|
return index;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.lastIndexOf` which performs strict equality
|
|
* comparisons of values, i.e. `===`.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to inspect.
|
|
* @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 strictLastIndexOf(array, value, fromIndex) {
|
|
var index = fromIndex + 1;
|
|
while (index--) {
|
|
if (array[index] === value) {
|
|
return index;
|
|
}
|
|
}
|
|
return index;
|
|
}
|
|
|
|
/**
|
|
* Gets the number of symbols in `string`.
|
|
*
|
|
* @private
|
|
* @param {string} string The string to inspect.
|
|
* @returns {number} Returns the string size.
|
|
*/
|
|
function stringSize(string) {
|
|
return hasUnicode(string)
|
|
? unicodeSize(string)
|
|
: asciiSize(string);
|
|
}
|
|
|
|
/**
|
|
* Converts `string` to an array.
|
|
*
|
|
* @private
|
|
* @param {string} string The string to convert.
|
|
* @returns {Array} Returns the converted array.
|
|
*/
|
|
function stringToArray(string) {
|
|
return hasUnicode(string)
|
|
? unicodeToArray(string)
|
|
: asciiToArray(string);
|
|
}
|
|
|
|
/**
|
|
* Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace
|
|
* character of `string`.
|
|
*
|
|
* @private
|
|
* @param {string} string The string to inspect.
|
|
* @returns {number} Returns the index of the last non-whitespace character.
|
|
*/
|
|
function trimmedEndIndex(string) {
|
|
var index = string.length;
|
|
|
|
while (index-- && reWhitespace.test(string.charAt(index))) {}
|
|
return index;
|
|
}
|
|
|
|
/**
|
|
* 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);
|
|
|
|
/**
|
|
* Gets the size of a Unicode `string`.
|
|
*
|
|
* @private
|
|
* @param {string} string The string inspect.
|
|
* @returns {number} Returns the string size.
|
|
*/
|
|
function unicodeSize(string) {
|
|
var result = reUnicode.lastIndex = 0;
|
|
while (reUnicode.test(string)) {
|
|
++result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts a Unicode `string` to an array.
|
|
*
|
|
* @private
|
|
* @param {string} string The string to convert.
|
|
* @returns {Array} Returns the converted array.
|
|
*/
|
|
function unicodeToArray(string) {
|
|
return string.match(reUnicode) || [];
|
|
}
|
|
|
|
/**
|
|
* Splits a Unicode `string` into an array of its words.
|
|
*
|
|
* @private
|
|
* @param {string} The string to inspect.
|
|
* @returns {Array} Returns the words of `string`.
|
|
*/
|
|
function unicodeWords(string) {
|
|
return string.match(reUnicodeWord) || [];
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* 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
|
|
*
|
|
* // Create a suped-up `defer` in Node.js.
|
|
* var defer = _.runInContext({ 'setTimeout': setImmediate }).defer;
|
|
*/
|
|
var runInContext = (function runInContext(context) {
|
|
context = context == null ? root : _.defaults(root.Object(), context, _.pick(root, contextProps));
|
|
|
|
/** Built-in constructor references. */
|
|
var Array = context.Array,
|
|
Date = context.Date,
|
|
Error = context.Error,
|
|
Function = context.Function,
|
|
Math = context.Math,
|
|
Object = context.Object,
|
|
RegExp = context.RegExp,
|
|
String = context.String,
|
|
TypeError = context.TypeError;
|
|
|
|
/** Used for built-in method references. */
|
|
var arrayProto = Array.prototype,
|
|
funcProto = Function.prototype,
|
|
objectProto = Object.prototype;
|
|
|
|
/** Used to detect overreaching core-js shims. */
|
|
var coreJsData = context['__core-js_shared__'];
|
|
|
|
/** Used to resolve the decompiled source of functions. */
|
|
var funcToString = funcProto.toString;
|
|
|
|
/** Used to check objects for own properties. */
|
|
var hasOwnProperty = objectProto.hasOwnProperty;
|
|
|
|
/** Used to generate unique IDs. */
|
|
var idCounter = 0;
|
|
|
|
/** 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
|
|
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
|
|
* of values.
|
|
*/
|
|
var nativeObjectToString = objectProto.toString;
|
|
|
|
/** Used to infer the `Object` constructor. */
|
|
var objectCtorString = funcToString.call(Object);
|
|
|
|
/** 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,
|
|
Symbol = context.Symbol,
|
|
Uint8Array = context.Uint8Array,
|
|
allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined,
|
|
getPrototype = overArg(Object.getPrototypeOf, Object),
|
|
objectCreate = Object.create,
|
|
propertyIsEnumerable = objectProto.propertyIsEnumerable,
|
|
splice = arrayProto.splice,
|
|
spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined,
|
|
symIterator = Symbol ? Symbol.iterator : undefined,
|
|
symToStringTag = Symbol ? Symbol.toStringTag : undefined;
|
|
|
|
var defineProperty = (function() {
|
|
try {
|
|
var func = getNative(Object, 'defineProperty');
|
|
func({}, '', {});
|
|
return func;
|
|
} catch (e) {}
|
|
}());
|
|
|
|
/** Mocked built-ins. */
|
|
var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout,
|
|
ctxNow = Date && Date.now !== root.Date.now && Date.now,
|
|
ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout;
|
|
|
|
/* Built-in method references for those with the same name as other `lodash` methods. */
|
|
var nativeCeil = Math.ceil,
|
|
nativeFloor = Math.floor,
|
|
nativeGetSymbols = Object.getOwnPropertySymbols,
|
|
nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined,
|
|
nativeIsFinite = context.isFinite,
|
|
nativeJoin = arrayProto.join,
|
|
nativeKeys = overArg(Object.keys, Object),
|
|
nativeMax = Math.max,
|
|
nativeMin = Math.min,
|
|
nativeNow = Date.now,
|
|
nativeParseInt = context.parseInt,
|
|
nativeRandom = Math.random,
|
|
nativeReverse = arrayProto.reverse;
|
|
|
|
/* Built-in method references that are verified to be native. */
|
|
var DataView = getNative(context, 'DataView'),
|
|
Map = getNative(context, 'Map'),
|
|
Promise = getNative(context, 'Promise'),
|
|
Set = getNative(context, 'Set'),
|
|
WeakMap = getNative(context, 'WeakMap'),
|
|
nativeCreate = getNative(Object, 'create');
|
|
|
|
/** Used to store function metadata. */
|
|
var metaMap = WeakMap && new WeakMap;
|
|
|
|
/** 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 and 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 base implementation of `_.create` without support for assigning
|
|
* properties to the created object.
|
|
*
|
|
* @private
|
|
* @param {Object} proto The object to inherit from.
|
|
* @returns {Object} Returns the new object.
|
|
*/
|
|
var baseCreate = (function() {
|
|
function object() {}
|
|
return function(proto) {
|
|
if (!isObject(proto)) {
|
|
return {};
|
|
}
|
|
if (objectCreate) {
|
|
return objectCreate(proto);
|
|
}
|
|
object.prototype = proto;
|
|
var result = new object;
|
|
object.prototype = undefined;
|
|
return result;
|
|
};
|
|
}());
|
|
|
|
/**
|
|
* 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) as well as ES2015 template strings. 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 || (!isRight && 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 == null ? 0 : entries.length;
|
|
|
|
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) : {};
|
|
this.size = 0;
|
|
}
|
|
|
|
/**
|
|
* 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) {
|
|
var result = this.has(key) && delete this.__data__[key];
|
|
this.size -= result ? 1 : 0;
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* 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__;
|
|
this.size += this.has(key) ? 0 : 1;
|
|
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 == null ? 0 : entries.length;
|
|
|
|
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__ = [];
|
|
this.size = 0;
|
|
}
|
|
|
|
/**
|
|
* 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);
|
|
}
|
|
--this.size;
|
|
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) {
|
|
++this.size;
|
|
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 == null ? 0 : entries.length;
|
|
|
|
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.size = 0;
|
|
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) {
|
|
var result = getMapData(this, key)['delete'](key);
|
|
this.size -= result ? 1 : 0;
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* 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) {
|
|
var data = getMapData(this, key),
|
|
size = data.size;
|
|
|
|
data.set(key, value);
|
|
this.size += data.size == size ? 0 : 1;
|
|
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 == null ? 0 : values.length;
|
|
|
|
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) {
|
|
var data = this.__data__ = new ListCache(entries);
|
|
this.size = data.size;
|
|
}
|
|
|
|
/**
|
|
* Removes all key-value entries from the stack.
|
|
*
|
|
* @private
|
|
* @name clear
|
|
* @memberOf Stack
|
|
*/
|
|
function stackClear() {
|
|
this.__data__ = new ListCache;
|
|
this.size = 0;
|
|
}
|
|
|
|
/**
|
|
* 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) {
|
|
var data = this.__data__,
|
|
result = data['delete'](key);
|
|
|
|
this.size = data.size;
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* 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 data = this.__data__;
|
|
if (data instanceof ListCache) {
|
|
var pairs = data.__data__;
|
|
if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
|
|
pairs.push([key, value]);
|
|
this.size = ++data.size;
|
|
return this;
|
|
}
|
|
data = this.__data__ = new MapCache(pairs);
|
|
}
|
|
data.set(key, value);
|
|
this.size = data.size;
|
|
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;
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Creates an array of the enumerable property names of the array-like `value`.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to query.
|
|
* @param {boolean} inherited Specify returning inherited property names.
|
|
* @returns {Array} Returns the array of property names.
|
|
*/
|
|
function arrayLikeKeys(value, inherited) {
|
|
var isArr = isArray(value),
|
|
isArg = !isArr && isArguments(value),
|
|
isBuff = !isArr && !isArg && isBuffer(value),
|
|
isType = !isArr && !isArg && !isBuff && isTypedArray(value),
|
|
skipIndexes = isArr || isArg || isBuff || isType,
|
|
result = skipIndexes ? baseTimes(value.length, String) : [],
|
|
length = result.length;
|
|
|
|
for (var key in value) {
|
|
if ((inherited || hasOwnProperty.call(value, key)) &&
|
|
!(skipIndexes && (
|
|
// Safari 9 has enumerable `arguments.length` in strict mode.
|
|
key == 'length' ||
|
|
// Node.js 0.10 has enumerable non-index properties on buffers.
|
|
(isBuff && (key == 'offset' || key == 'parent')) ||
|
|
// PhantomJS 2 has enumerable non-index properties on typed arrays.
|
|
(isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||
|
|
// Skip index properties.
|
|
isIndex(key, length)
|
|
))) {
|
|
result.push(key);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.sample` for arrays.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to sample.
|
|
* @returns {*} Returns the random element.
|
|
*/
|
|
function arraySample(array) {
|
|
var length = array.length;
|
|
return length ? array[baseRandom(0, length - 1)] : undefined;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.sampleSize` for arrays.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to sample.
|
|
* @param {number} n The number of elements to sample.
|
|
* @returns {Array} Returns the random elements.
|
|
*/
|
|
function arraySampleSize(array, n) {
|
|
return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length));
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.shuffle` for arrays.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to shuffle.
|
|
* @returns {Array} Returns the new shuffled array.
|
|
*/
|
|
function arrayShuffle(array) {
|
|
return shuffleSelf(copyArray(array));
|
|
}
|
|
|
|
/**
|
|
* 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)) ||
|
|
(value === undefined && !(key in object))) {
|
|
baseAssignValue(object, key, value);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Assigns `value` to `key` of `object` if the existing value is not equivalent
|
|
* using [`SameValueZero`](http://ecma-international.org/ecma-262/7.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))) {
|
|
baseAssignValue(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 inspect.
|
|
* @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 `_.assignIn` 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 baseAssignIn(object, source) {
|
|
return object && copyObject(source, keysIn(source), object);
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `assignValue` and `assignMergeValue` without
|
|
* value checks.
|
|
*
|
|
* @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 baseAssignValue(object, key, value) {
|
|
if (key == '__proto__' && defineProperty) {
|
|
defineProperty(object, key, {
|
|
'configurable': true,
|
|
'enumerable': true,
|
|
'value': value,
|
|
'writable': true
|
|
});
|
|
} else {
|
|
object[key] = value;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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 to pick.
|
|
* @returns {Array} Returns the picked elements.
|
|
*/
|
|
function baseAt(object, paths) {
|
|
var index = -1,
|
|
length = paths.length,
|
|
result = Array(length),
|
|
skip = object == null;
|
|
|
|
while (++index < length) {
|
|
result[index] = skip ? 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} bitmask The bitmask flags.
|
|
* 1 - Deep clone
|
|
* 2 - Flatten inherited properties
|
|
* 4 - Clone 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, bitmask, customizer, key, object, stack) {
|
|
var result,
|
|
isDeep = bitmask & CLONE_DEEP_FLAG,
|
|
isFlat = bitmask & CLONE_FLAT_FLAG,
|
|
isFull = bitmask & CLONE_SYMBOLS_FLAG;
|
|
|
|
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)) {
|
|
result = (isFlat || isFunc) ? {} : initCloneObject(value);
|
|
if (!isDeep) {
|
|
return isFlat
|
|
? copySymbolsIn(value, baseAssignIn(result, value))
|
|
: copySymbols(value, baseAssign(result, value));
|
|
}
|
|
} else {
|
|
if (!cloneableTags[tag]) {
|
|
return object ? value : {};
|
|
}
|
|
result = initCloneByTag(value, tag, 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 (isSet(value)) {
|
|
value.forEach(function(subValue) {
|
|
result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack));
|
|
});
|
|
} else if (isMap(value)) {
|
|
value.forEach(function(subValue, key) {
|
|
result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack));
|
|
});
|
|
}
|
|
|
|
var keysFunc = isFull
|
|
? (isFlat ? getAllKeysIn : getAllKeys)
|
|
: (isFlat ? keysIn : keys);
|
|
|
|
var props = isArr ? undefined : keysFunc(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, bitmask, 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;
|
|
}
|
|
object = Object(object);
|
|
while (length--) {
|
|
var key = props[length],
|
|
predicate = source[key],
|
|
value = object[key];
|
|
|
|
if ((value === undefined && !(key in object)) || !predicate(value)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* 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|Object} Returns the timer id or timeout object.
|
|
*/
|
|
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 == null ? value : iteratee(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 = castPath(path, object);
|
|
|
|
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` without fallbacks for buggy environments.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to query.
|
|
* @returns {string} Returns the `toStringTag`.
|
|
*/
|
|
function baseGetTag(value) {
|
|
if (value == null) {
|
|
return value === undefined ? undefinedTag : nullTag;
|
|
}
|
|
return (symToStringTag && symToStringTag in Object(value))
|
|
? getRawTag(value)
|
|
: objectToString(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) {
|
|
return object != null && hasOwnProperty.call(object, key);
|
|
}
|
|
|
|
/**
|
|
* 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) {
|
|
path = castPath(path, object);
|
|
object = parent(object, path);
|
|
var func = object == null ? object : object[toKey(last(path))];
|
|
return func == null ? undefined : apply(func, object, args);
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.isArguments`.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to check.
|
|
* @returns {boolean} Returns `true` if `value` is an `arguments` object,
|
|
*/
|
|
function baseIsArguments(value) {
|
|
return isObjectLike(value) && baseGetTag(value) == argsTag;
|
|
}
|
|
|
|
/**
|
|
* 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) && baseGetTag(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) && baseGetTag(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 {boolean} bitmask The bitmask flags.
|
|
* 1 - Unordered comparison
|
|
* 2 - Partial comparison
|
|
* @param {Function} [customizer] The function to customize comparisons.
|
|
* @param {Object} [stack] Tracks traversed `value` and `other` objects.
|
|
* @returns {boolean} Returns `true` if the values are equivalent, else `false`.
|
|
*/
|
|
function baseIsEqual(value, other, bitmask, customizer, stack) {
|
|
if (value === other) {
|
|
return true;
|
|
}
|
|
if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {
|
|
return value !== value && other !== other;
|
|
}
|
|
return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, 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 {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
|
|
* @param {Function} customizer The function to customize comparisons.
|
|
* @param {Function} equalFunc The function to determine equivalents of values.
|
|
* @param {Object} [stack] Tracks traversed `object` and `other` objects.
|
|
* @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
|
|
*/
|
|
function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
|
|
var objIsArr = isArray(object),
|
|
othIsArr = isArray(other),
|
|
objTag = objIsArr ? arrayTag : getTag(object),
|
|
othTag = othIsArr ? arrayTag : getTag(other);
|
|
|
|
objTag = objTag == argsTag ? objectTag : objTag;
|
|
othTag = othTag == argsTag ? objectTag : othTag;
|
|
|
|
var objIsObj = objTag == objectTag,
|
|
othIsObj = othTag == objectTag,
|
|
isSameTag = objTag == othTag;
|
|
|
|
if (isSameTag && isBuffer(object)) {
|
|
if (!isBuffer(other)) {
|
|
return false;
|
|
}
|
|
objIsArr = true;
|
|
objIsObj = false;
|
|
}
|
|
if (isSameTag && !objIsObj) {
|
|
stack || (stack = new Stack);
|
|
return (objIsArr || isTypedArray(object))
|
|
? equalArrays(object, other, bitmask, customizer, equalFunc, stack)
|
|
: equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
|
|
}
|
|
if (!(bitmask & COMPARE_PARTIAL_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, bitmask, customizer, stack);
|
|
}
|
|
}
|
|
if (!isSameTag) {
|
|
return false;
|
|
}
|
|
stack || (stack = new Stack);
|
|
return equalObjects(object, other, bitmask, customizer, equalFunc, 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, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, 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) ? 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 isObjectLike(value) && baseGetTag(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[baseGetTag(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 treat sparse arrays as dense.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to query.
|
|
* @returns {Array} Returns the array of property names.
|
|
*/
|
|
function baseKeys(object) {
|
|
if (!isPrototype(object)) {
|
|
return nativeKeys(object);
|
|
}
|
|
var result = [];
|
|
for (var key in Object(object)) {
|
|
if (hasOwnProperty.call(object, key) && key != 'constructor') {
|
|
result.push(key);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to query.
|
|
* @returns {Array} Returns the array of property names.
|
|
*/
|
|
function baseKeysIn(object) {
|
|
if (!isObject(object)) {
|
|
return nativeKeysIn(object);
|
|
}
|
|
var isProto = isPrototype(object),
|
|
result = [];
|
|
|
|
for (var key in object) {
|
|
if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
|
|
result.push(key);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* 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, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_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;
|
|
}
|
|
baseFor(source, function(srcValue, key) {
|
|
stack || (stack = new Stack);
|
|
if (isObject(srcValue)) {
|
|
baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
|
|
}
|
|
else {
|
|
var newValue = customizer
|
|
? customizer(safeGet(object, key), srcValue, (key + ''), object, source, stack)
|
|
: undefined;
|
|
|
|
if (newValue === undefined) {
|
|
newValue = srcValue;
|
|
}
|
|
assignMergeValue(object, key, newValue);
|
|
}
|
|
}, keysIn);
|
|
}
|
|
|
|
/**
|
|
* 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 = safeGet(object, key),
|
|
srcValue = safeGet(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) {
|
|
var isArr = isArray(srcValue),
|
|
isBuff = !isArr && isBuffer(srcValue),
|
|
isTyped = !isArr && !isBuff && isTypedArray(srcValue);
|
|
|
|
newValue = srcValue;
|
|
if (isArr || isBuff || isTyped) {
|
|
if (isArray(objValue)) {
|
|
newValue = objValue;
|
|
}
|
|
else if (isArrayLikeObject(objValue)) {
|
|
newValue = copyArray(objValue);
|
|
}
|
|
else if (isBuff) {
|
|
isCommon = false;
|
|
newValue = cloneBuffer(srcValue, true);
|
|
}
|
|
else if (isTyped) {
|
|
isCommon = false;
|
|
newValue = cloneTypedArray(srcValue, true);
|
|
}
|
|
else {
|
|
newValue = [];
|
|
}
|
|
}
|
|
else if (isPlainObject(srcValue) || isArguments(srcValue)) {
|
|
newValue = objValue;
|
|
if (isArguments(objValue)) {
|
|
newValue = toPlainObject(objValue);
|
|
}
|
|
else if (!isObject(objValue) || isFunction(objValue)) {
|
|
newValue = initCloneObject(srcValue);
|
|
}
|
|
}
|
|
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) {
|
|
if (iteratees.length) {
|
|
iteratees = arrayMap(iteratees, function(iteratee) {
|
|
if (isArray(iteratee)) {
|
|
return function(value) {
|
|
return baseGet(value, iteratee.length === 1 ? iteratee[0] : iteratee);
|
|
}
|
|
}
|
|
return iteratee;
|
|
});
|
|
} else {
|
|
iteratees = [identity];
|
|
}
|
|
|
|
var index = -1;
|
|
iteratees = arrayMap(iteratees, 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[]} paths The property paths to pick.
|
|
* @returns {Object} Returns the new object.
|
|
*/
|
|
function basePick(object, paths) {
|
|
return basePickBy(object, paths, function(value, path) {
|
|
return hasIn(object, path);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.pickBy` without support for iteratee shorthands.
|
|
*
|
|
* @private
|
|
* @param {Object} object The source object.
|
|
* @param {string[]} paths The property paths to pick.
|
|
* @param {Function} predicate The function invoked per property.
|
|
* @returns {Object} Returns the new object.
|
|
*/
|
|
function basePickBy(object, paths, predicate) {
|
|
var index = -1,
|
|
length = paths.length,
|
|
result = {};
|
|
|
|
while (++index < length) {
|
|
var path = paths[index],
|
|
value = baseGet(object, path);
|
|
|
|
if (predicate(value, path)) {
|
|
baseSet(result, castPath(path, object), 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 {
|
|
baseUnset(array, 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) {
|
|
return setToString(overRest(func, start, identity), func + '');
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.sample`.
|
|
*
|
|
* @private
|
|
* @param {Array|Object} collection The collection to sample.
|
|
* @returns {*} Returns the random element.
|
|
*/
|
|
function baseSample(collection) {
|
|
return arraySample(values(collection));
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.sampleSize` without param guards.
|
|
*
|
|
* @private
|
|
* @param {Array|Object} collection The collection to sample.
|
|
* @param {number} n The number of elements to sample.
|
|
* @returns {Array} Returns the random elements.
|
|
*/
|
|
function baseSampleSize(collection, n) {
|
|
var array = values(collection);
|
|
return shuffleSelf(array, baseClamp(n, 0, array.length));
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.set`.
|
|
*
|
|
* @private
|
|
* @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 path creation.
|
|
* @returns {Object} Returns `object`.
|
|
*/
|
|
function baseSet(object, path, value, customizer) {
|
|
if (!isObject(object)) {
|
|
return object;
|
|
}
|
|
path = castPath(path, object);
|
|
|
|
var index = -1,
|
|
length = path.length,
|
|
lastIndex = length - 1,
|
|
nested = object;
|
|
|
|
while (nested != null && ++index < length) {
|
|
var key = toKey(path[index]),
|
|
newValue = value;
|
|
|
|
if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
|
|
return object;
|
|
}
|
|
|
|
if (index != lastIndex) {
|
|
var objValue = nested[key];
|
|
newValue = customizer ? customizer(objValue, key, nested) : undefined;
|
|
if (newValue === undefined) {
|
|
newValue = isObject(objValue)
|
|
? objValue
|
|
: (isIndex(path[index + 1]) ? [] : {});
|
|
}
|
|
}
|
|
assignValue(nested, key, newValue);
|
|
nested = nested[key];
|
|
}
|
|
return object;
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `setData` without support for hot loop shorting.
|
|
*
|
|
* @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 `setToString` without support for hot loop shorting.
|
|
*
|
|
* @private
|
|
* @param {Function} func The function to modify.
|
|
* @param {Function} string The `toString` result.
|
|
* @returns {Function} Returns `func`.
|
|
*/
|
|
var baseSetToString = !defineProperty ? identity : function(func, string) {
|
|
return defineProperty(func, 'toString', {
|
|
'configurable': true,
|
|
'enumerable': false,
|
|
'value': constant(string),
|
|
'writable': true
|
|
});
|
|
};
|
|
|
|
/**
|
|
* The base implementation of `_.shuffle`.
|
|
*
|
|
* @private
|
|
* @param {Array|Object} collection The collection to shuffle.
|
|
* @returns {Array} Returns the new shuffled array.
|
|
*/
|
|
function baseShuffle(collection) {
|
|
return shuffleSelf(values(collection));
|
|
}
|
|
|
|
/**
|
|
* 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 == null ? low : array.length;
|
|
|
|
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) {
|
|
var low = 0,
|
|
high = array == null ? 0 : array.length;
|
|
if (high === 0) {
|
|
return 0;
|
|
}
|
|
|
|
value = iteratee(value);
|
|
var 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 (isArray(value)) {
|
|
// Recursively convert values (susceptible to call stack limits).
|
|
return arrayMap(value, baseToString) + '';
|
|
}
|
|
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 property path to unset.
|
|
* @returns {boolean} Returns `true` if the property is deleted, else `false`.
|
|
*/
|
|
function baseUnset(object, path) {
|
|
path = castPath(path, object);
|
|
object = parent(object, path);
|
|
return object == null || delete object[toKey(last(path))];
|
|
}
|
|
|
|
/**
|
|
* The base implementation of `_.update`.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to modify.
|
|
* @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 length = arrays.length;
|
|
if (length < 2) {
|
|
return length ? baseUniq(arrays[0]) : [];
|
|
}
|
|
var index = -1,
|
|
result = Array(length);
|
|
|
|
while (++index < length) {
|
|
var array = arrays[index],
|
|
othIndex = -1;
|
|
|
|
while (++othIndex < length) {
|
|
if (othIndex != index) {
|
|
result[index] = baseDifference(result[index] || array, arrays[othIndex], iteratee, comparator);
|
|
}
|
|
}
|
|
}
|
|
return baseUniq(baseFlatten(result, 1), 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.
|
|
* @param {Object} [object] The object to query keys on.
|
|
* @returns {Array} Returns the cast property path array.
|
|
*/
|
|
function castPath(value, object) {
|
|
if (isArray(value)) {
|
|
return value;
|
|
}
|
|
return isKey(value, object) ? [value] : stringToPath(toString(value));
|
|
}
|
|
|
|
/**
|
|
* A `baseRest` alias which can be replaced with `identity` by module
|
|
* replacement plugins.
|
|
*
|
|
* @private
|
|
* @type {Function}
|
|
* @param {Function} func The function to apply a rest parameter to.
|
|
* @returns {Function} Returns the new function.
|
|
*/
|
|
var castRest = baseRest;
|
|
|
|
/**
|
|
* 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);
|
|
}
|
|
|
|
/**
|
|
* A simple wrapper around the global [`clearTimeout`](https://mdn.io/clearTimeout).
|
|
*
|
|
* @private
|
|
* @param {number|Object} id The timer id or timeout object of the timer to clear.
|
|
*/
|
|
var clearTimeout = ctxClearTimeout || function(id) {
|
|
return root.clearTimeout(id);
|
|
};
|
|
|
|
/**
|
|
* 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 length = buffer.length,
|
|
result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(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 `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 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) {
|
|
var isNew = !object;
|
|
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;
|
|
|
|
if (newValue === undefined) {
|
|
newValue = source[key];
|
|
}
|
|
if (isNew) {
|
|
baseAssignValue(object, key, newValue);
|
|
} else {
|
|
assignValue(object, key, newValue);
|
|
}
|
|
}
|
|
return object;
|
|
}
|
|
|
|
/**
|
|
* Copies own symbols 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);
|
|
}
|
|
|
|
/**
|
|
* Copies own and inherited symbols 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 copySymbolsIn(source, object) {
|
|
return copyObject(source, getSymbolsIn(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 & WRAP_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 = hasUnicode(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/7.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 flatRest(function(funcs) {
|
|
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] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_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)) {
|
|
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 & WRAP_ARY_FLAG,
|
|
isBind = bitmask & WRAP_BIND_FLAG,
|
|
isBindKey = bitmask & WRAP_BIND_KEY_FLAG,
|
|
isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG),
|
|
isFlip = bitmask & WRAP_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 flatRest(function(iteratees) {
|
|
iteratees = arrayMap(iteratees, 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 hasUnicode(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 & WRAP_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 & WRAP_CURRY_FLAG,
|
|
newHolders = isCurry ? holders : undefined,
|
|
newHoldersRight = isCurry ? undefined : holders,
|
|
newPartials = isCurry ? partials : undefined,
|
|
newPartialsRight = isCurry ? undefined : partials;
|
|
|
|
bitmask |= (isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG);
|
|
bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG);
|
|
|
|
if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) {
|
|
bitmask &= ~(WRAP_BIND_FLAG | WRAP_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 = precision == null ? 0 : nativeMin(toInteger(precision), 292);
|
|
if (precision && nativeIsFinite(number)) {
|
|
// 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.
|
|
* 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 & WRAP_BIND_KEY_FLAG;
|
|
if (!isBindKey && typeof func != 'function') {
|
|
throw new TypeError(FUNC_ERROR_TEXT);
|
|
}
|
|
var length = partials ? partials.length : 0;
|
|
if (!length) {
|
|
bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_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 & WRAP_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] === undefined
|
|
? (isBindKey ? 0 : func.length)
|
|
: nativeMax(newData[9] - length, 0);
|
|
|
|
if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) {
|
|
bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG);
|
|
}
|
|
if (!bitmask || bitmask == WRAP_BIND_FLAG) {
|
|
var result = createBind(func, bitmask, thisArg);
|
|
} else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) {
|
|
result = createCurry(func, bitmask, arity);
|
|
} else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_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);
|
|
}
|
|
|
|
/**
|
|
* Used by `_.defaults` to customize its `_.assignIn` use to assign properties
|
|
* of source objects to the destination object for all destination properties
|
|
* that resolve to `undefined`.
|
|
*
|
|
* @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 customDefaultsAssignIn(objValue, srcValue, key, object) {
|
|
if (objValue === undefined ||
|
|
(eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) {
|
|
return srcValue;
|
|
}
|
|
return objValue;
|
|
}
|
|
|
|
/**
|
|
* Used by `_.defaultsDeep` to customize its `_.merge` use to merge source
|
|
* objects into destination objects that are passed thru.
|
|
*
|
|
* @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 customDefaultsMerge(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, customDefaultsMerge, stack);
|
|
stack['delete'](srcValue);
|
|
}
|
|
return objValue;
|
|
}
|
|
|
|
/**
|
|
* Used by `_.omit` to customize its `_.cloneDeep` use to only clone plain
|
|
* objects.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to inspect.
|
|
* @param {string} key The key of the property to inspect.
|
|
* @returns {*} Returns the uncloned value or `undefined` to defer cloning to `_.cloneDeep`.
|
|
*/
|
|
function customOmitClone(value) {
|
|
return isPlainObject(value) ? undefined : value;
|
|
}
|
|
|
|
/**
|
|
* 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 {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
|
|
* @param {Function} customizer The function to customize comparisons.
|
|
* @param {Function} equalFunc The function to determine equivalents of values.
|
|
* @param {Object} stack Tracks traversed `array` and `other` objects.
|
|
* @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
|
|
*/
|
|
function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
|
|
var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
|
|
arrLength = array.length,
|
|
othLength = other.length;
|
|
|
|
if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
|
|
return false;
|
|
}
|
|
// Check that cyclic values are equal.
|
|
var arrStacked = stack.get(array);
|
|
var othStacked = stack.get(other);
|
|
if (arrStacked && othStacked) {
|
|
return arrStacked == other && othStacked == array;
|
|
}
|
|
var index = -1,
|
|
result = true,
|
|
seen = (bitmask & COMPARE_UNORDERED_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 (!cacheHas(seen, othIndex) &&
|
|
(arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
|
|
return seen.push(othIndex);
|
|
}
|
|
})) {
|
|
result = false;
|
|
break;
|
|
}
|
|
} else if (!(
|
|
arrValue === othValue ||
|
|
equalFunc(arrValue, othValue, bitmask, customizer, 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 {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
|
|
* @param {Function} customizer The function to customize comparisons.
|
|
* @param {Function} equalFunc The function to determine equivalents of values.
|
|
* @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, bitmask, customizer, equalFunc, 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/7.0/#sec-regexp.prototype.tostring
|
|
// for more details.
|
|
return object == (other + '');
|
|
|
|
case mapTag:
|
|
var convert = mapToArray;
|
|
|
|
case setTag:
|
|
var isPartial = bitmask & COMPARE_PARTIAL_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 |= COMPARE_UNORDERED_FLAG;
|
|
|
|
// Recursively compare objects (susceptible to call stack limits).
|
|
stack.set(object, other);
|
|
var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, 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 {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
|
|
* @param {Function} customizer The function to customize comparisons.
|
|
* @param {Function} equalFunc The function to determine equivalents of values.
|
|
* @param {Object} stack Tracks traversed `object` and `other` objects.
|
|
* @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
|
|
*/
|
|
function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
|
|
var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
|
|
objProps = getAllKeys(object),
|
|
objLength = objProps.length,
|
|
othProps = getAllKeys(other),
|
|
othLength = othProps.length;
|
|
|
|
if (objLength != othLength && !isPartial) {
|
|
return false;
|
|
}
|
|
var index = objLength;
|
|
while (index--) {
|
|
var key = objProps[index];
|
|
if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
|
|
return false;
|
|
}
|
|
}
|
|
// Check that cyclic values are equal.
|
|
var objStacked = stack.get(object);
|
|
var othStacked = stack.get(other);
|
|
if (objStacked && othStacked) {
|
|
return objStacked == other && othStacked == object;
|
|
}
|
|
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, bitmask, customizer, 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;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `baseRest` which flattens the rest array.
|
|
*
|
|
* @private
|
|
* @param {Function} func The function to apply a rest parameter to.
|
|
* @returns {Function} Returns the new function.
|
|
*/
|
|
function flatRest(func) {
|
|
return setToString(overRest(func, undefined, flatten), func + '');
|
|
}
|
|
|
|
/**
|
|
* 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 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;
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to query.
|
|
* @returns {string} Returns the raw `toStringTag`.
|
|
*/
|
|
function getRawTag(value) {
|
|
var isOwn = hasOwnProperty.call(value, symToStringTag),
|
|
tag = value[symToStringTag];
|
|
|
|
try {
|
|
value[symToStringTag] = undefined;
|
|
var unmasked = true;
|
|
} catch (e) {}
|
|
|
|
var result = nativeObjectToString.call(value);
|
|
if (unmasked) {
|
|
if (isOwn) {
|
|
value[symToStringTag] = tag;
|
|
} else {
|
|
delete value[symToStringTag];
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Creates an array of the own enumerable symbols of `object`.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to query.
|
|
* @returns {Array} Returns the array of symbols.
|
|
*/
|
|
var getSymbols = !nativeGetSymbols ? stubArray : function(object) {
|
|
if (object == null) {
|
|
return [];
|
|
}
|
|
object = Object(object);
|
|
return arrayFilter(nativeGetSymbols(object), function(symbol) {
|
|
return propertyIsEnumerable.call(object, symbol);
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Creates an array of the own and inherited enumerable symbols 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 and promises in Node.js < 6.
|
|
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 = baseGetTag(value),
|
|
Ctor = result == objectTag ? value.constructor : undefined,
|
|
ctorString = Ctor ? toSource(Ctor) : '';
|
|
|
|
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 = castPath(path, object);
|
|
|
|
var index = -1,
|
|
length = path.length,
|
|
result = false;
|
|
|
|
while (++index < length) {
|
|
var key = toKey(path[index]);
|
|
if (!(result = object != null && hasFunc(object, key))) {
|
|
break;
|
|
}
|
|
object = object[key];
|
|
}
|
|
if (result || ++index != length) {
|
|
return result;
|
|
}
|
|
length = object == null ? 0 : object.length;
|
|
return !!length && isLength(length) && isIndex(key, length) &&
|
|
(isArray(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 = new 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`, `Map`, `Number`, `RegExp`, `Set`, or `String`.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to clone.
|
|
* @param {string} tag The `toStringTag` of the object to clone.
|
|
* @param {boolean} [isDeep] Specify a deep clone.
|
|
* @returns {Object} Returns the initialized clone.
|
|
*/
|
|
function initCloneByTag(object, tag, 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 new Ctor;
|
|
|
|
case numberTag:
|
|
case stringTag:
|
|
return new Ctor(object);
|
|
|
|
case regexpTag:
|
|
return cloneRegExp(object);
|
|
|
|
case setTag:
|
|
return new Ctor;
|
|
|
|
case symbolTag:
|
|
return cloneSymbol(object);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
if (!length) {
|
|
return source;
|
|
}
|
|
var 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) {
|
|
var type = typeof value;
|
|
length = length == null ? MAX_SAFE_INTEGER : length;
|
|
|
|
return !!length &&
|
|
(type == 'number' ||
|
|
(type != 'symbol' && 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)));
|
|
};
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.memoize` which clears the memoized function's
|
|
* cache when it exceeds `MAX_MEMOIZE_SIZE`.
|
|
*
|
|
* @private
|
|
* @param {Function} func The function to have its output memoized.
|
|
* @returns {Function} Returns the new memoized function.
|
|
*/
|
|
function memoizeCapped(func) {
|
|
var result = memoize(func, function(key) {
|
|
if (cache.size === MAX_MEMOIZE_SIZE) {
|
|
cache.clear();
|
|
}
|
|
return key;
|
|
});
|
|
|
|
var cache = result.cache;
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* 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 < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG);
|
|
|
|
var isCombo =
|
|
((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_CURRY_FLAG)) ||
|
|
((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_REARG_FLAG) && (data[7].length <= source[8])) ||
|
|
((srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == WRAP_CURRY_FLAG));
|
|
|
|
// Exit early if metadata can't be merged.
|
|
if (!(isCommon || isCombo)) {
|
|
return data;
|
|
}
|
|
// Use source `thisArg` if available.
|
|
if (srcBitmask & WRAP_BIND_FLAG) {
|
|
data[2] = source[2];
|
|
// Set when currying a bound function.
|
|
newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_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 & WRAP_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;
|
|
}
|
|
|
|
/**
|
|
* This function is like
|
|
* [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
|
|
* except that it includes inherited enumerable properties.
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to query.
|
|
* @returns {Array} Returns the array of property names.
|
|
*/
|
|
function nativeKeysIn(object) {
|
|
var result = [];
|
|
if (object != null) {
|
|
for (var key in Object(object)) {
|
|
result.push(key);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts `value` to a string using `Object.prototype.toString`.
|
|
*
|
|
* @private
|
|
* @param {*} value The value to convert.
|
|
* @returns {string} Returns the converted string.
|
|
*/
|
|
function objectToString(value) {
|
|
return nativeObjectToString.call(value);
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `baseRest` which transforms the rest array.
|
|
*
|
|
* @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.
|
|
* @param {Function} transform The rest array transform.
|
|
* @returns {Function} Returns the new function.
|
|
*/
|
|
function overRest(func, start, transform) {
|
|
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] = transform(array);
|
|
return apply(func, this, otherArgs);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 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 < 2 ? 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;
|
|
}
|
|
|
|
/**
|
|
* Gets the value at `key`, unless `key` is "__proto__" or "constructor".
|
|
*
|
|
* @private
|
|
* @param {Object} object The object to query.
|
|
* @param {string} key The key of the property to get.
|
|
* @returns {*} Returns the property value.
|
|
*/
|
|
function safeGet(object, key) {
|
|
if (key === 'constructor' && typeof object[key] === 'function') {
|
|
return;
|
|
}
|
|
|
|
if (key == '__proto__') {
|
|
return;
|
|
}
|
|
|
|
return object[key];
|
|
}
|
|
|
|
/**
|
|
* 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 = shortOut(baseSetData);
|
|
|
|
/**
|
|
* A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout).
|
|
*
|
|
* @private
|
|
* @param {Function} func The function to delay.
|
|
* @param {number} wait The number of milliseconds to delay invocation.
|
|
* @returns {number|Object} Returns the timer id or timeout object.
|
|
*/
|
|
var setTimeout = ctxSetTimeout || function(func, wait) {
|
|
return root.setTimeout(func, wait);
|
|
};
|
|
|
|
/**
|
|
* Sets the `toString` method of `func` to return `string`.
|
|
*
|
|
* @private
|
|
* @param {Function} func The function to modify.
|
|
* @param {Function} string The `toString` result.
|
|
* @returns {Function} Returns `func`.
|
|
*/
|
|
var setToString = shortOut(baseSetToString);
|
|
|
|
/**
|
|
* 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`.
|
|
*/
|
|
function setWrapToString(wrapper, reference, bitmask) {
|
|
var source = (reference + '');
|
|
return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask)));
|
|
}
|
|
|
|
/**
|
|
* Creates a function that'll short out and invoke `identity` instead
|
|
* of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`
|
|
* milliseconds.
|
|
*
|
|
* @private
|
|
* @param {Function} func The function to restrict.
|
|
* @returns {Function} Returns the new shortable function.
|
|
*/
|
|
function shortOut(func) {
|
|
var count = 0,
|
|
lastCalled = 0;
|
|
|
|
return function() {
|
|
var stamp = nativeNow(),
|
|
remaining = HOT_SPAN - (stamp - lastCalled);
|
|
|
|
lastCalled = stamp;
|
|
if (remaining > 0) {
|
|
if (++count >= HOT_COUNT) {
|
|
return arguments[0];
|
|
}
|
|
} else {
|
|
count = 0;
|
|
}
|
|
return func.apply(undefined, arguments);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* A specialized version of `_.shuffle` which mutates and sets the size of `array`.
|
|
*
|
|
* @private
|
|
* @param {Array} array The array to shuffle.
|
|
* @param {number} [size=array.length] The size of `array`.
|
|
* @returns {Array} Returns `array`.
|
|
*/
|
|
function shuffleSelf(array, size) {
|
|
var index = -1,
|
|
length = array.length,
|
|
lastIndex = length - 1;
|
|
|
|
size = size === undefined ? length : size;
|
|
while (++index < size) {
|
|
var rand = baseRandom(index, lastIndex),
|
|
value = array[rand];
|
|
|
|
array[rand] = array[index];
|
|
array[index] = value;
|
|
}
|
|
array.length = size;
|
|
return array;
|
|
}
|
|
|
|
/**
|
|
* Converts `string` to a property path array.
|
|
*
|
|
* @private
|
|
* @param {string} string The string to convert.
|
|
* @returns {Array} Returns the property path array.
|
|
*/
|
|
var stringToPath = memoizeCapped(function(string) {
|
|
var result = [];
|
|
if (string.charCodeAt(0) === 46 /* . */) {
|
|
result.push('');
|
|
}
|
|
string.replace(rePropName, function(match, number, quote, subString) {
|
|
result.push(quote ? subString.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 convert.
|
|
* @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 == null ? 0 : array.length;
|
|
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 == null ? 0 : array.length,
|
|
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;
|
|
if (!length) {
|
|
return [];
|
|
}
|
|
var args = Array(length - 1),
|
|
array = arguments[0],
|
|
index = length;
|
|
|
|
while (index--) {
|
|
args[index - 1] = arguments[index];
|
|
}
|
|
return 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/7.0/#sec-samevaluezero)
|
|
* for equality comparisons. The order and references of result values are
|
|
* determined by 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. The order and references of result values are
|
|
* determined by 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`. The order and
|
|
* references of result values are determined by 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 == null ? 0 : array.length;
|
|
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 == null ? 0 : array.length;
|
|
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 == null ? 0 : array.length;
|
|
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 inspect.
|
|
* @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 == null ? 0 : array.length;
|
|
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 inspect.
|
|
* @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 == null ? 0 : array.length;
|
|
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 == null ? 0 : array.length;
|
|
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 == null ? 0 : array.length;
|
|
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 == null ? 0 : array.length;
|
|
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 == null ? 0 : pairs.length,
|
|
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/7.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 inspect.
|
|
* @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 == null ? 0 : array.length;
|
|
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) {
|
|
var length = array == null ? 0 : array.length;
|
|
return length ? baseSlice(array, 0, -1) : [];
|
|
}
|
|
|
|
/**
|
|
* Creates an array of unique values that are included in all given arrays
|
|
* using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
|
|
* for equality comparisons. The order and references of result values are
|
|
* determined by 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. The order and references of result values are
|
|
* determined by 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`. The order and references
|
|
* of result values are determined by 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);
|
|
|
|
comparator = typeof comparator == 'function' ? comparator : undefined;
|
|
if (comparator) {
|
|
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 == null ? '' : 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 == null ? 0 : array.length;
|
|
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 inspect.
|
|
* @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 == null ? 0 : array.length;
|
|
if (!length) {
|
|
return -1;
|
|
}
|
|
var index = length;
|
|
if (fromIndex !== undefined) {
|
|
index = toInteger(fromIndex);
|
|
index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);
|
|
}
|
|
return value === value
|
|
? strictLastIndexOf(array, value, index)
|
|
: baseFindIndex(array, baseIsNaN, index, true);
|
|
}
|
|
|
|
/**
|
|
* 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/7.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 = flatRest(function(array, indexes) {
|
|
var length = array == null ? 0 : array.length,
|
|
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 == null ? array : nativeReverse.call(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 == null ? 0 : array.length;
|
|
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 inspect.
|
|
* @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 == null ? 0 : array.length;
|
|
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 inspect.
|
|
* @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 == null ? 0 : array.length;
|
|
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) {
|
|
var length = array == null ? 0 : array.length;
|
|
return length ? baseSlice(array, 1, length) : [];
|
|
}
|
|
|
|
/**
|
|
* 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 == null ? 0 : array.length;
|
|
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/7.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);
|
|
comparator = typeof comparator == 'function' ? 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/7.0/#sec-samevaluezero)
|
|
* for equality comparisons, in which only the first occurrence of each element
|
|
* is kept. The order of result values is determined by the order they occur
|
|
* in the array.
|
|
*
|
|
* @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 order of result values is determined by the
|
|
* order they occur in the array. The iteratee is invoked with one argument:
|
|
* (value).
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 4.0.0
|
|
* @category Array
|
|
* @param {Array} array The array to inspect.
|
|
* @param {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 order of result values is
|
|
* determined by the order they occur in the 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) {
|
|
comparator = typeof comparator == 'function' ? comparator : undefined;
|
|
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/7.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 order of result values is determined
|
|
* by the order they occur in the arrays. 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 order of result values is
|
|
* determined by the order they occur in the 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);
|
|
comparator = typeof comparator == 'function' ? 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 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 = flatRest(function(paths) {
|
|
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) {
|
|
if (hasOwnProperty.call(result, key)) {
|
|
++result[key];
|
|
} else {
|
|
baseAssignValue(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).
|
|
*
|
|
* **Note:** This method returns `true` for
|
|
* [empty collections](https://en.wikipedia.org/wiki/Empty_set) because
|
|
* [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of
|
|
* elements of empty collections.
|
|
*
|
|
* @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']
|
|
*
|
|
* // Combining several predicates using `_.overEvery` or `_.overSome`.
|
|
* _.filter(users, _.overSome([{ 'age': 36 }, ['age', 40]]));
|
|
* // => objects for ['fred', '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 inspect.
|
|
* @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 inspect.
|
|
* @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
|
|
*
|
|
* _.forEach([1, 2], 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 {
|
|
baseAssignValue(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/7.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 inspect.
|
|
* @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',
|
|
result = isArrayLike(collection) ? Array(collection.length) : [];
|
|
|
|
baseEach(collection, function(value) {
|
|
result[++index] = isFunc ? apply(path, 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) {
|
|
baseAssignValue(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 func = isArray(collection) ? arraySample : baseSample;
|
|
return func(collection);
|
|
}
|
|
|
|
/**
|
|
* 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) {
|
|
if ((guard ? isIterateeCall(collection, n, guard) : n === undefined)) {
|
|
n = 1;
|
|
} else {
|
|
n = toInteger(n);
|
|
}
|
|
var func = isArray(collection) ? arraySampleSize : baseSampleSize;
|
|
return func(collection, n);
|
|
}
|
|
|
|
/**
|
|
* 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) {
|
|
var func = isArray(collection) ? arrayShuffle : baseShuffle;
|
|
return func(collection);
|
|
}
|
|
|
|
/**
|
|
* 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|string} 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)) {
|
|
return isString(collection) ? stringSize(collection) : collection.length;
|
|
}
|
|
var tag = getTag(collection);
|
|
if (tag == mapTag || tag == setTag) {
|
|
return collection.size;
|
|
}
|
|
return baseKeys(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': 30 },
|
|
* { 'user': 'barney', 'age': 34 }
|
|
* ];
|
|
*
|
|
* _.sortBy(users, [function(o) { return o.user; }]);
|
|
* // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 30]]
|
|
*
|
|
* _.sortBy(users, ['user', 'age']);
|
|
* // => objects for [['barney', 34], ['barney', 36], ['fred', 30], ['fred', 48]]
|
|
*/
|
|
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.
|
|
*/
|
|
var now = ctxNow || function() {
|
|
return root.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, WRAP_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 = WRAP_BIND_FLAG;
|
|
if (partials.length) {
|
|
var holders = replaceHolders(partials, getHolder(bind));
|
|
bitmask |= WRAP_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 = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG;
|
|
if (partials.length) {
|
|
var holders = replaceHolders(partials, getHolder(bindKey));
|
|
bitmask |= WRAP_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, WRAP_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, WRAP_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,
|
|
timeWaiting = wait - timeSinceLastCall;
|
|
|
|
return maxing
|
|
? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke)
|
|
: timeWaiting;
|
|
}
|
|
|
|
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.
|
|
clearTimeout(timerId);
|
|
timerId = setTimeout(timerExpired, wait);
|
|
return invokeFunc(lastCallTime);
|
|
}
|
|
}
|
|
if (timerId === undefined) {
|
|
timerId = setTimeout(timerExpired, wait);
|
|
}
|
|
return result;
|
|
}
|
|
debounced.cancel = cancel;
|
|
debounced.flush = flush;
|
|
return debounced;
|
|
}
|
|
|
|
/**
|
|
* Defers invoking the `func` until the current call stack has cleared. Any
|
|
* additional arguments are provided to `func` when it's invoked.
|
|
*
|
|
* @static
|
|
* @memberOf _
|
|
* @since 0.1.0
|
|
* @category Function
|
|
* @param {Function} func The function to defer.
|
|
* @param {...*} [args] The arguments to invoke `func` with.
|
|
* @returns {number} Returns the timer id.
|
|
* @example
|
|
*
|
|
* _.defer(function(text) {
|
|
* console.log(text);
|
|
* }, 'deferred');
|
|
* // => Logs 'deferred' after one millisecond.
|
|
*/
|
|
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, WRAP_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/7.0/#sec-properties-of-the-map-prototype-object)
|
|
* method interface of `clear`, `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 != null && 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) || cache;
|
|
return result;
|
|
};
|
|
memoized.cache = new (memoize.Cache || MapCache);
|
|
return memoized;
|
|
}
|
|
|
|
// Expose `MapCache`.
|
|
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 = castRest(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, WRAP_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, WRAP_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 = flatRest(function(func, indexes) {
|
|
return createWrap(func, WRAP_REARG_FLAG, undefined, undefined, undefined, indexes);
|
|
});
|
|
|
|
/**
|
|
* 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/7.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 == null ? 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) {
|
|
return partial(castFunction(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, CLONE_SYMBOLS_FLAG);
|
|
}
|
|
|
|
/**
|
|
* 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) {
|
|
customizer = typeof customizer == 'function' ? customizer : undefined;
|
|
return baseClone(value, CLONE_SYMBOLS_FLAG, 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, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG);
|
|
}
|
|
|
|
/**
|
|
* 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) {
|
|
customizer = typeof customizer == 'function' ? customizer : undefined;
|
|
return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, 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/7.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
|
|
*/
|
|
var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {
|
|
return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&
|
|
!propertyIsEnumerable.call(value, 'callee');
|
|
};
|
|
|
|
/**
|
|
* 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(value.length) && !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) && baseGetTag(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 isObjectLike(value) && value.nodeType === 1 && !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 (value == null) {
|
|
return true;
|
|
}
|
|
if (isArrayLike(value) &&
|
|
(isArray(value) || typeof value == 'string' || typeof value.splice == 'function' ||
|
|
isBuffer(value) || isTypedArray(value) || isArguments(value))) {
|
|
return !value.length;
|
|
}
|
|
var tag = getTag(value);
|
|
if (tag == mapTag || tag == setTag) {
|
|
return !value.size;
|
|
}
|
|
if (isPrototype(value)) {
|
|
return !baseKeys(value).length;
|
|
}
|
|
for (var key in value) {
|
|
if (hasOwnProperty.call(value, key)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* 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 compared by strict equality, i.e. `===`.
|
|
*
|
|
* @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, undefined, 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;
|
|
}
|
|
var tag = baseGetTag(value);
|
|
return tag == errorTag || tag == domExcTag ||
|
|
(typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value));
|
|
}
|
|
|
|
/**
|
|
* 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) {
|
|
if (!isObject(value)) {
|
|
return false;
|
|
}
|
|
// The use of `Object#toString` avoids issues with the `typeof` operator
|
|
// in Safari 9 which returns 'object' for typed arrays and other constructors.
|
|
var tag = baseGetTag(value);
|
|
return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
|
|
}
|
|
|
|
/**
|
|
* 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 method is loosely based on
|
|
* [`ToLength`](http://ecma-international.org/ecma-262/7.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/7.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 != null && (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 != null && 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 is equivalent to `_.matches` when `source` is
|
|
* partially applied.
|
|
*
|
|
* Partial comparisons will match empty array and empty object `source`
|
|
* values against any array or object value, respectively. See `_.isEqual`
|
|
* for a list of supported value comparisons.
|
|
*
|
|
* @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(CORE_ERROR_TEXT);
|
|
}
|
|
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) && baseGetTag(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) || baseGetTag(value) != objectTag) {
|
|
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) && baseGetTag(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) && baseGetTag(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) && baseGetTag(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 (symIterator && value[symIterator]) {
|
|
return iteratorToArray(value[symIterator]());
|
|
}
|
|
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/7.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/7.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 = typeof value.valueOf == 'function' ? value.valueOf() : value;
|
|
value = isObject(other) ? (other + '') : other;
|
|
}
|
|
if (typeof value != 'string') {
|
|
return value === 0 ? value : +value;
|
|
}
|
|
value = baseTrim(value);
|
|
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 value
|
|
? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER)
|
|
: (value === 0 ? value : 0);
|
|
}
|
|
|
|
/**
|
|
* 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 convert.
|
|
* @returns {string} Returns the converted 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 (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) {
|
|
copyObject(source, keysIn(source), object);
|
|
});
|
|
|
|
/**
|
|
* 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 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 = flatRest(baseAt);
|
|
|
|
/**
|
|
* 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 == null ? result : baseAssign(result, properties);
|
|
}
|
|
|
|
/**
|
|
* 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(object, sources) {
|
|
object = Object(object);
|
|
|
|
var index = -1;
|
|
var length = sources.length;
|
|
var guard = length > 2 ? sources[2] : undefined;
|
|
|
|
if (guard && isIterateeCall(sources[0], sources[1], guard)) {
|
|
length = 1;
|
|
}
|
|
|
|
while (++index < length) {
|
|
var source = sources[index];
|
|
var props = keysIn(source);
|
|
var propsIndex = -1;
|
|
var propsLength = props.length;
|
|
|
|
while (++propsIndex < propsLength) {
|
|
var key = props[propsIndex];
|
|
var value = object[key];
|
|
|
|
if (value === undefined ||
|
|
(eq(value, objectProto[key]) && !hasOwnProperty.call(object, key))) {
|
|
object[key] = source[key];
|
|
}
|
|
}
|
|
}
|
|
|
|
return object;
|
|
});
|
|
|
|
/**
|
|
* 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, customDefaultsMerge);
|
|
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 inspect.
|
|
* @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 inspect.
|
|
* @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) {
|
|
if (value != null &&
|
|
typeof value.toString != 'function') {
|
|
value = nativeObjectToString.call(value);
|
|
}
|
|
|
|
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 (value != null &&
|
|
typeof value.toString != 'function') {
|
|
value = nativeObjectToString.call(value);
|
|
}
|
|
|
|
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/7.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) {
|
|
return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
|
|
}
|
|
|
|
/**
|
|
* 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) {
|
|
return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
|
|
}
|
|
|
|
/**
|
|
* 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) {
|
|
baseAssignValue(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) {
|
|
baseAssignValue(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 six 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 property paths of `object` that are not omitted.
|
|
*
|
|
* **Note:** This method is considerably slower than `_.pick`.
|
|
*
|
|
* @static
|
|
* @since 0.1.0
|
|
* @memberOf _
|
|
* @category Object
|
|
* @param {Object} object The source object.
|
|
* @param {...(string|string[])} [paths] The property paths 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 = flatRest(function(object, paths) {
|
|
var result = {};
|
|
if (object == null) {
|
|
return result;
|
|
}
|
|
var isDeep = false;
|
|
paths = arrayMap(paths, function(path) {
|
|
path = castPath(path, object);
|
|
isDeep || (isDeep = path.length > 1);
|
|
return path;
|
|
});
|
|
copyObject(object, getAllKeysIn(object), result);
|
|
if (isDeep) {
|
|
result = baseClone(result, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone);
|
|
}
|
|
var length = paths.length;
|
|
while (length--) {
|
|
baseUnset(result, paths[length]);
|
|
}
|
|
return result;
|
|
});
|
|
|
|
/**
|
|
* 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[])} [paths] The property paths 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 = flatRest(function(object, paths) {
|
|
return object == null ? {} : basePick(object, paths);
|
|
});
|
|
|
|
/**
|
|
* 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) {
|
|
if (object == null) {
|
|
return {};
|
|
}
|
|
var props = arrayMap(getAllKeysIn(object), function(prop) {
|
|
return [prop];
|
|
});
|
|
predicate = getIteratee(predicate);
|
|
return basePickBy(object, props, function(value, path) {
|
|
return predicate(value, path[0]);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 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 = castPath(path, object);
|
|
|
|
var index = -1,
|
|
length = path.length;
|
|
|
|
// Ensure the loop is entered when path is empty.
|
|
if (!length) {
|
|
length = 1;
|
|
object = undefined;
|
|
}
|
|
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),
|
|
isArrLike = isArr || isBuffer(object) || isTypedArray(object);
|
|
|
|
iteratee = getIteratee(iteratee, 4);
|
|
if (accumulator == null) {
|
|
var Ctor = object && object.constructor;
|
|
if (isArrLike) {
|
|
accumulator = isArr ? new Ctor : [];
|
|
}
|
|
else if (isObject(object)) {
|
|
accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {};
|
|
}
|
|
else {
|
|
accumulator = {};
|
|
}
|
|
}
|
|
(isArrLike ? 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 == null ? [] : 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 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)
|
|
* and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A)
|
|
* letters 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(reLatin, 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 inspect.
|
|
* @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.
|
|
*
|
|
* 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) {
|
|
if (guard || radix == null) {
|
|
radix = 0;
|
|
} else if (radix) {
|
|
radix = +radix;
|
|
}
|
|
return nativeParseInt(toString(string).replace(reTrimStart, ''), radix || 0);
|
|
}
|
|
|
|
/**
|
|
* 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 : string.replace(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 && hasUnicode(string)) {
|
|
return castSlice(stringToArray(string), 0, limit);
|
|
}
|
|
}
|
|
return string.split(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 inspect.
|
|
* @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 = position == null
|
|
? 0
|
|
: 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 template literal delimiter as an "interpolate" delimiter.
|
|
* // Disable support by replacing the "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, customDefaultsAssignIn);
|
|
|
|
var imports = assignInWith({}, options.imports, settings.imports, customDefaultsAssignIn),
|
|
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.
|
|
// The sourceURL gets injected into the source that's eval-ed, so be careful
|
|
// to normalize all kinds of whitespace, so e.g. newlines (and unicode versions of it) can't sneak in
|
|
// and escape the comment, thus injecting code that gets evaled.
|
|
var sourceURL = '//# sourceURL=' +
|
|
(hasOwnProperty.call(options, 'sourceURL')
|
|
? (options.sourceURL + '').replace(/\s/g, ' ')
|
|
: ('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 = hasOwnProperty.call(options, 'variable') && options.variable;
|
|
if (!variable) {
|
|
source = 'with (obj) {\n' + source + '\n}\n';
|
|
}
|
|
// Throw an error if a forbidden character was found in `variable`, to prevent
|
|
// potential command injection attacks.
|
|
else if (reForbiddenIdentifierChars.test(variable)) {
|
|
throw new Error(INVALID_TEMPL_VAR_ERROR_TEXT);
|
|
}
|
|
|
|
// 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 baseTrim(string);
|
|
}
|
|
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.slice(0, trimmedEndIndex(string) + 1);
|
|
}
|
|
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 (hasUnicode(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) {
|
|
return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string);
|
|
}
|
|
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 = flatRest(function(object, methodNames) {
|
|
arrayEach(methodNames, function(key) {
|
|
key = toKey(key);
|
|
baseAssignValue(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 == null ? 0 : pairs.length,
|
|
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, CLONE_DEEP_FLAG));
|
|
}
|
|
|
|
/**
|
|
* 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, CLONE_DEEP_FLAG));
|
|
}
|
|
|
|
/**
|
|
* 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 is equivalent to `_.isMatch` with `source`
|
|
* partially applied.
|
|
*
|
|
* Partial comparisons will match empty array and empty object `source`
|
|
* values against any array or object value, respectively. See `_.isEqual`
|
|
* for a list of supported value comparisons.
|
|
*
|
|
* **Note:** Multiple values can be checked by combining several matchers
|
|
* using `_.overSome`
|
|
*
|
|
* @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 }]
|
|
*
|
|
* // Checking for several possible values
|
|
* _.filter(objects, _.overSome([_.matches({ 'a': 1 }), _.matches({ 'a': 4 })]));
|
|
* // => [{ 'a': 1, 'b': 2, 'c': 3 }, { 'a': 4, 'b': 5, 'c': 6 }]
|
|
*/
|
|
function matches(source) {
|
|
return baseMatches(baseClone(source, CLONE_DEEP_FLAG));
|
|
}
|
|
|
|
/**
|
|
* 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:** Partial comparisons will match empty array and empty object
|
|
* `srcValue` values against any array or object value, respectively. See
|
|
* `_.isEqual` for a list of supported value comparisons.
|
|
*
|
|
* **Note:** Multiple values can be checked by combining several matchers
|
|
* using `_.overSome`
|
|
*
|
|
* @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 }
|
|
*
|
|
* // Checking for several possible values
|
|
* _.filter(objects, _.overSome([_.matchesProperty('a', 1), _.matchesProperty('a', 4)]));
|
|
* // => [{ 'a': 1, 'b': 2, 'c': 3 }, { 'a': 4, 'b': 5, 'c': 6 }]
|
|
*/
|
|
function matchesProperty(path, srcValue) {
|
|
return baseMatchesProperty(path, baseClone(srcValue, CLONE_DEEP_FLAG));
|
|
}
|
|
|
|
/**
|
|
* 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.
|
|
*
|
|
* Following shorthands are possible for providing predicates.
|
|
* Pass an `Object` and it will be used as an parameter for `_.matches` to create the predicate.
|
|
* Pass an `Array` of parameters for `_.matchesProperty` and the predicate will be created using them.
|
|
*
|
|
* @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.
|
|
*
|
|
* Following shorthands are possible for providing predicates.
|
|
* Pass an `Object` and it will be used as an parameter for `_.matches` to create the predicate.
|
|
* Pass an `Array` of parameters for `_.matchesProperty` and the predicate will be created using them.
|
|
*
|
|
* @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 matchesFunc = _.overSome([{ 'a': 1 }, { 'a': 2 }])
|
|
* var matchesPropertyFunc = _.overSome([['a', 1], ['a', 2]])
|
|
*/
|
|
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(toString(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) {
|
|
n = n === undefined ? 1 : nativeMax(toInteger(n), 0);
|
|
|
|
var result = (this.__filtered__ && !index)
|
|
? new LazyWrapper(this)
|
|
: this.clone();
|
|
|
|
if (result.__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 + '';
|
|
if (!hasOwnProperty.call(realNames, key)) {
|
|
realNames[key] = [];
|
|
}
|
|
realNames[key].push({ 'name': methodName, 'func': lodashFunc });
|
|
}
|
|
});
|
|
|
|
realNames[createHybrid(undefined, WRAP_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 (symIterator) {
|
|
lodash.prototype[symIterator] = 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 {}
|
|
}.call(this));
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 19861:
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
const visitor = __webpack_require__(68202);
|
|
|
|
// AST utilities.
|
|
const asts = {
|
|
findRule(ast, name) {
|
|
for (let i = 0; i < ast.rules.length; i++) {
|
|
if (ast.rules[i].name === name) {
|
|
return ast.rules[i];
|
|
}
|
|
}
|
|
|
|
return undefined;
|
|
},
|
|
|
|
indexOfRule(ast, name) {
|
|
for (let i = 0; i < ast.rules.length; i++) {
|
|
if (ast.rules[i].name === name) {
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
},
|
|
|
|
alwaysConsumesOnSuccess(ast, node) {
|
|
function consumesTrue() { return true; }
|
|
function consumesFalse() { return false; }
|
|
|
|
const consumes = visitor.build({
|
|
choice(node) {
|
|
return node.alternatives.every(consumes);
|
|
},
|
|
|
|
sequence(node) {
|
|
return node.elements.some(consumes);
|
|
},
|
|
|
|
simple_and: consumesFalse,
|
|
simple_not: consumesFalse,
|
|
optional: consumesFalse,
|
|
zero_or_more: consumesFalse,
|
|
semantic_and: consumesFalse,
|
|
semantic_not: consumesFalse,
|
|
|
|
rule_ref(node) {
|
|
return consumes(asts.findRule(ast, node.name));
|
|
},
|
|
|
|
literal(node) {
|
|
return node.value !== "";
|
|
},
|
|
|
|
class: consumesTrue,
|
|
any: consumesTrue
|
|
});
|
|
|
|
return consumes(node);
|
|
}
|
|
};
|
|
|
|
module.exports = asts;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 79203:
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
const generateBytecode = __webpack_require__(12886);
|
|
const generateJS = __webpack_require__(15843);
|
|
const inferenceMatchResult = __webpack_require__(35412);
|
|
const removeProxyRules = __webpack_require__(32929);
|
|
const reportDuplicateLabels = __webpack_require__(96734);
|
|
const reportDuplicateRules = __webpack_require__(1117);
|
|
const reportInfiniteRecursion = __webpack_require__(10730);
|
|
const reportInfiniteRepetition = __webpack_require__(79505);
|
|
const reportUndefinedRules = __webpack_require__(41442);
|
|
const reportIncorrectPlucking = __webpack_require__(66237);
|
|
const visitor = __webpack_require__(68202);
|
|
|
|
function processOptions(options, defaults) {
|
|
const processedOptions = {};
|
|
|
|
Object.keys(options).forEach(name => {
|
|
processedOptions[name] = options[name];
|
|
});
|
|
|
|
Object.keys(defaults).forEach(name => {
|
|
if (!Object.prototype.hasOwnProperty.call(processedOptions, name)) {
|
|
processedOptions[name] = defaults[name];
|
|
}
|
|
});
|
|
|
|
return processedOptions;
|
|
}
|
|
|
|
const compiler = {
|
|
// AST node visitor builder. Useful mainly for plugins which manipulate the
|
|
// AST.
|
|
visitor,
|
|
|
|
// Compiler passes.
|
|
//
|
|
// Each pass is a function that is passed the AST. It can perform checks on it
|
|
// or modify it as needed. If the pass encounters a semantic error, it throws
|
|
// |peg.GrammarError|.
|
|
passes: {
|
|
check: [
|
|
reportUndefinedRules,
|
|
reportDuplicateRules,
|
|
reportDuplicateLabels,
|
|
reportInfiniteRecursion,
|
|
reportInfiniteRepetition,
|
|
reportIncorrectPlucking
|
|
],
|
|
transform: [
|
|
removeProxyRules,
|
|
inferenceMatchResult,
|
|
],
|
|
generate: [
|
|
generateBytecode,
|
|
generateJS
|
|
]
|
|
},
|
|
|
|
// Generates a parser from a specified grammar AST. Throws |peg.GrammarError|
|
|
// if the AST contains a semantic error. Note that not all errors are detected
|
|
// during the generation and some may protrude to the generated parser and
|
|
// cause its malfunction.
|
|
compile(ast, passes, options) {
|
|
options = options !== undefined ? options : {};
|
|
|
|
options = processOptions(options, {
|
|
allowedStartRules: [ast.rules[0].name],
|
|
cache: false,
|
|
dependencies: {},
|
|
exportVar: null,
|
|
format: "bare",
|
|
output: "parser",
|
|
trace: false
|
|
});
|
|
|
|
Object.keys(passes).forEach(stage => {
|
|
passes[stage].forEach(p => { p(ast, options); });
|
|
});
|
|
|
|
switch (options.output) {
|
|
case "parser":
|
|
return eval(ast.code);
|
|
|
|
case "source":
|
|
return ast.code;
|
|
|
|
default:
|
|
throw new Error("Invalid output format: " + options.output + ".");
|
|
}
|
|
}
|
|
};
|
|
|
|
module.exports = compiler;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 86164:
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
// Bytecode instruction opcodes.
|
|
const opcodes = {
|
|
// Stack Manipulation
|
|
|
|
/** @deprecated Unused */
|
|
PUSH: 0, // PUSH c
|
|
PUSH_EMPTY_STRING: 35, // PUSH_EMPTY_STRING
|
|
PUSH_UNDEFINED: 1, // PUSH_UNDEFINED
|
|
PUSH_NULL: 2, // PUSH_NULL
|
|
PUSH_FAILED: 3, // PUSH_FAILED
|
|
PUSH_EMPTY_ARRAY: 4, // PUSH_EMPTY_ARRAY
|
|
PUSH_CURR_POS: 5, // PUSH_CURR_POS
|
|
POP: 6, // POP
|
|
POP_CURR_POS: 7, // POP_CURR_POS
|
|
POP_N: 8, // POP_N n
|
|
NIP: 9, // NIP
|
|
APPEND: 10, // APPEND
|
|
WRAP: 11, // WRAP n
|
|
TEXT: 12, // TEXT
|
|
PLUCK: 36, // PLUCK n, k, p1, ..., pK
|
|
|
|
// Conditions and Loops
|
|
|
|
IF: 13, // IF t, f
|
|
IF_ERROR: 14, // IF_ERROR t, f
|
|
IF_NOT_ERROR: 15, // IF_NOT_ERROR t, f
|
|
WHILE_NOT_ERROR: 16, // WHILE_NOT_ERROR b
|
|
|
|
// Matching
|
|
|
|
MATCH_ANY: 17, // MATCH_ANY a, f, ...
|
|
MATCH_STRING: 18, // MATCH_STRING s, a, f, ...
|
|
MATCH_STRING_IC: 19, // MATCH_STRING_IC s, a, f, ...
|
|
MATCH_CHAR_CLASS: 20, // MATCH_CHAR_CLASS c, a, f, ...
|
|
/** @deprecated Replaced with `MATCH_CHAR_CLASS` */
|
|
MATCH_REGEXP: 20, // MATCH_REGEXP r, a, f, ...
|
|
ACCEPT_N: 21, // ACCEPT_N n
|
|
ACCEPT_STRING: 22, // ACCEPT_STRING s
|
|
FAIL: 23, // FAIL e
|
|
|
|
// Calls
|
|
|
|
LOAD_SAVED_POS: 24, // LOAD_SAVED_POS p
|
|
UPDATE_SAVED_POS: 25, // UPDATE_SAVED_POS
|
|
CALL: 26, // CALL f, n, pc, p1, p2, ..., pN
|
|
|
|
// Rules
|
|
|
|
RULE: 27, // RULE r
|
|
|
|
// Failure Reporting
|
|
|
|
SILENT_FAILS_ON: 28, // SILENT_FAILS_ON
|
|
SILENT_FAILS_OFF: 29 // SILENT_FAILS_OFF
|
|
|
|
// Because the tests have hard-coded opcode numbers, don't renumber
|
|
// existing opcodes. New opcodes that have been put in the correct
|
|
// sections above are repeated here in order to ensure we don't
|
|
// reuse them.
|
|
//
|
|
// 30-34 reserved for @mingun
|
|
// PUSH_EMPTY_STRING: 35
|
|
// PLUCK: 36
|
|
};
|
|
|
|
module.exports = opcodes;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 12886:
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
const asts = __webpack_require__(19861);
|
|
const op = __webpack_require__(86164);
|
|
const visitor = __webpack_require__(68202);
|
|
const { ALWAYS_MATCH, SOMETIMES_MATCH, NEVER_MATCH } = __webpack_require__(35412);
|
|
|
|
// Generates bytecode.
|
|
//
|
|
// Instructions
|
|
// ============
|
|
//
|
|
// Stack Manipulation
|
|
// ------------------
|
|
//
|
|
// [35] PUSH_EMPTY_STRING
|
|
//
|
|
// stack.push("");
|
|
//
|
|
// [1] PUSH_UNDEFINED
|
|
//
|
|
// stack.push(undefined);
|
|
//
|
|
// [2] PUSH_NULL
|
|
//
|
|
// stack.push(null);
|
|
//
|
|
// [3] PUSH_FAILED
|
|
//
|
|
// stack.push(FAILED);
|
|
//
|
|
// [4] PUSH_EMPTY_ARRAY
|
|
//
|
|
// stack.push([]);
|
|
//
|
|
// [5] PUSH_CURR_POS
|
|
//
|
|
// stack.push(currPos);
|
|
//
|
|
// [6] POP
|
|
//
|
|
// stack.pop();
|
|
//
|
|
// [7] POP_CURR_POS
|
|
//
|
|
// currPos = stack.pop();
|
|
//
|
|
// [8] POP_N n
|
|
//
|
|
// stack.pop(n);
|
|
//
|
|
// [9] NIP
|
|
//
|
|
// value = stack.pop();
|
|
// stack.pop();
|
|
// stack.push(value);
|
|
//
|
|
// [10] APPEND
|
|
//
|
|
// value = stack.pop();
|
|
// array = stack.pop();
|
|
// array.push(value);
|
|
// stack.push(array);
|
|
//
|
|
// [11] WRAP n
|
|
//
|
|
// stack.push(stack.pop(n));
|
|
//
|
|
// [12] TEXT
|
|
//
|
|
// stack.push(input.substring(stack.pop(), currPos));
|
|
//
|
|
// [36] PLUCK n, k, p1, ..., pK
|
|
//
|
|
// value = [stack[p1], ..., stack[pK]]; // when k != 1
|
|
// -or-
|
|
// value = stack[p1]; // when k == 1
|
|
//
|
|
// stack.pop(n);
|
|
// stack.push(value);
|
|
//
|
|
// Conditions and Loops
|
|
// --------------------
|
|
//
|
|
// [13] IF t, f
|
|
//
|
|
// if (stack.top()) {
|
|
// interpret(ip + 3, ip + 3 + t);
|
|
// } else {
|
|
// interpret(ip + 3 + t, ip + 3 + t + f);
|
|
// }
|
|
//
|
|
// [14] IF_ERROR t, f
|
|
//
|
|
// if (stack.top() === FAILED) {
|
|
// interpret(ip + 3, ip + 3 + t);
|
|
// } else {
|
|
// interpret(ip + 3 + t, ip + 3 + t + f);
|
|
// }
|
|
//
|
|
// [15] IF_NOT_ERROR t, f
|
|
//
|
|
// if (stack.top() !== FAILED) {
|
|
// interpret(ip + 3, ip + 3 + t);
|
|
// } else {
|
|
// interpret(ip + 3 + t, ip + 3 + t + f);
|
|
// }
|
|
//
|
|
// [16] WHILE_NOT_ERROR b
|
|
//
|
|
// while(stack.top() !== FAILED) {
|
|
// interpret(ip + 2, ip + 2 + b);
|
|
// }
|
|
//
|
|
// Matching
|
|
// --------
|
|
//
|
|
// [17] MATCH_ANY a, f, ...
|
|
//
|
|
// if (input.length > currPos) {
|
|
// interpret(ip + 3, ip + 3 + a);
|
|
// } else {
|
|
// interpret(ip + 3 + a, ip + 3 + a + f);
|
|
// }
|
|
//
|
|
// [18] MATCH_STRING s, a, f, ...
|
|
//
|
|
// if (input.substr(currPos, literals[s].length) === literals[s]) {
|
|
// interpret(ip + 4, ip + 4 + a);
|
|
// } else {
|
|
// interpret(ip + 4 + a, ip + 4 + a + f);
|
|
// }
|
|
//
|
|
// [19] MATCH_STRING_IC s, a, f, ...
|
|
//
|
|
// if (input.substr(currPos, literals[s].length).toLowerCase() === literals[s]) {
|
|
// interpret(ip + 4, ip + 4 + a);
|
|
// } else {
|
|
// interpret(ip + 4 + a, ip + 4 + a + f);
|
|
// }
|
|
//
|
|
// [20] MATCH_CHAR_CLASS c, a, f, ...
|
|
//
|
|
// if (classes[c].test(input.charAt(currPos))) {
|
|
// interpret(ip + 4, ip + 4 + a);
|
|
// } else {
|
|
// interpret(ip + 4 + a, ip + 4 + a + f);
|
|
// }
|
|
//
|
|
// [21] ACCEPT_N n
|
|
//
|
|
// stack.push(input.substring(currPos, n));
|
|
// currPos += n;
|
|
//
|
|
// [22] ACCEPT_STRING s
|
|
//
|
|
// stack.push(literals[s]);
|
|
// currPos += literals[s].length;
|
|
//
|
|
// [23] FAIL e
|
|
//
|
|
// stack.push(FAILED);
|
|
// fail(expectations[e]);
|
|
//
|
|
// Calls
|
|
// -----
|
|
//
|
|
// [24] LOAD_SAVED_POS p
|
|
//
|
|
// savedPos = stack[p];
|
|
//
|
|
// [25] UPDATE_SAVED_POS
|
|
//
|
|
// savedPos = currPos;
|
|
//
|
|
// [26] CALL f, n, pc, p1, p2, ..., pN
|
|
//
|
|
// value = functions[f](stack[p1], ..., stack[pN]);
|
|
// stack.pop(n);
|
|
// stack.push(value);
|
|
//
|
|
// Rules
|
|
// -----
|
|
//
|
|
// [27] RULE r
|
|
//
|
|
// stack.push(parseRule(r));
|
|
//
|
|
// Failure Reporting
|
|
// -----------------
|
|
//
|
|
// [28] SILENT_FAILS_ON
|
|
//
|
|
// silentFails++;
|
|
//
|
|
// [29] SILENT_FAILS_OFF
|
|
//
|
|
// silentFails--;
|
|
//
|
|
// This pass can use the results of other previous passes, each of which can
|
|
// change the AST (and, as consequence, the bytecode).
|
|
//
|
|
// In particular, if the pass |inferenceMatchResult| has been run before this pass,
|
|
// then each AST node will contain a |match| property, which represents a possible
|
|
// match result of the node:
|
|
// - `<0` - node is never matched, for example, `!('a'*)` (negation of the always
|
|
// matched node). Generator can put |FAILED| to the stack immediately
|
|
// - `=0` - sometimes node matched, sometimes not. This is the same behavior
|
|
// when |match| is missed
|
|
// - `>0` - node is always matched, for example, `'a'*` (because result is an
|
|
// empty array, or an array with some elements). The generator does not
|
|
// need to add a check for |FAILED|, because it is impossible
|
|
//
|
|
// To handle the situation, when the |inferenceMatchResult| has not run (that
|
|
// happens, for example, in tests), the |match| value extracted using the
|
|
// `|0` trick, which performing cast of any value to an integer with value `0`
|
|
// that is equivalent of an unknown match result and signals the generator that
|
|
// runtime check for the |FAILED| is required. Trick is explained on the
|
|
// Wikipedia page (https://en.wikipedia.org/wiki/Asm.js#Code_generation)
|
|
function generateBytecode(ast) {
|
|
const literals = [];
|
|
const classes = [];
|
|
const expectations = [];
|
|
const functions = [];
|
|
|
|
function addLiteralConst(value) {
|
|
const index = literals.indexOf(value);
|
|
|
|
return index === -1 ? literals.push(value) - 1 : index;
|
|
}
|
|
|
|
function addClassConst(node) {
|
|
const cls = {
|
|
value: node.parts,
|
|
inverted: node.inverted,
|
|
ignoreCase: node.ignoreCase
|
|
};
|
|
const pattern = JSON.stringify(cls);
|
|
const index = classes.findIndex(c => JSON.stringify(c) === pattern);
|
|
|
|
return index === -1 ? classes.push(cls) - 1 : index;
|
|
}
|
|
|
|
function addExpectedConst(expected) {
|
|
const pattern = JSON.stringify(expected);
|
|
const index = expectations.findIndex(e => JSON.stringify(e) === pattern);
|
|
|
|
return index === -1 ? expectations.push(expected) - 1 : index;
|
|
}
|
|
|
|
function addFunctionConst(predicate, params, code) {
|
|
const func = { predicate, params, body: code };
|
|
const pattern = JSON.stringify(func);
|
|
const index = functions.findIndex(f => JSON.stringify(f) === pattern);
|
|
|
|
return index === -1 ? functions.push(func) - 1 : index;
|
|
}
|
|
|
|
function cloneEnv(env) {
|
|
const clone = {};
|
|
|
|
Object.keys(env).forEach(name => {
|
|
clone[name] = env[name];
|
|
});
|
|
|
|
return clone;
|
|
}
|
|
|
|
function buildSequence(first, ...args) {
|
|
return first.concat(...args);
|
|
}
|
|
|
|
function buildCondition(match, condCode, thenCode, elseCode) {
|
|
if (match === ALWAYS_MATCH) { return thenCode; }
|
|
if (match === NEVER_MATCH) { return elseCode; }
|
|
|
|
return condCode.concat(
|
|
[thenCode.length, elseCode.length],
|
|
thenCode,
|
|
elseCode
|
|
);
|
|
}
|
|
|
|
function buildLoop(condCode, bodyCode) {
|
|
return condCode.concat([bodyCode.length], bodyCode);
|
|
}
|
|
|
|
function buildCall(functionIndex, delta, env, sp) {
|
|
const params = Object.keys(env).map(name => sp - env[name]);
|
|
|
|
return [op.CALL, functionIndex, delta, params.length].concat(params);
|
|
}
|
|
|
|
function buildSimplePredicate(expression, negative, context) {
|
|
const match = expression.match | 0;
|
|
|
|
return buildSequence(
|
|
[op.PUSH_CURR_POS],
|
|
[op.SILENT_FAILS_ON],
|
|
generate(expression, {
|
|
sp: context.sp + 1,
|
|
env: cloneEnv(context.env),
|
|
action: null
|
|
}),
|
|
[op.SILENT_FAILS_OFF],
|
|
buildCondition(
|
|
negative ? -match : match,
|
|
[negative ? op.IF_ERROR : op.IF_NOT_ERROR],
|
|
buildSequence(
|
|
[op.POP],
|
|
[negative ? op.POP : op.POP_CURR_POS],
|
|
[op.PUSH_UNDEFINED]
|
|
),
|
|
buildSequence(
|
|
[op.POP],
|
|
[negative ? op.POP_CURR_POS : op.POP],
|
|
[op.PUSH_FAILED]
|
|
)
|
|
)
|
|
);
|
|
}
|
|
|
|
function buildSemanticPredicate(node, negative, context) {
|
|
const functionIndex = addFunctionConst(
|
|
true, Object.keys(context.env), node.code
|
|
);
|
|
|
|
return buildSequence(
|
|
[op.UPDATE_SAVED_POS],
|
|
buildCall(functionIndex, 0, context.env, context.sp),
|
|
buildCondition(
|
|
node.match | 0,
|
|
[op.IF],
|
|
buildSequence(
|
|
[op.POP],
|
|
negative ? [op.PUSH_FAILED] : [op.PUSH_UNDEFINED]
|
|
),
|
|
buildSequence(
|
|
[op.POP],
|
|
negative ? [op.PUSH_UNDEFINED] : [op.PUSH_FAILED]
|
|
)
|
|
)
|
|
);
|
|
}
|
|
|
|
function buildAppendLoop(expressionCode) {
|
|
return buildLoop(
|
|
[op.WHILE_NOT_ERROR],
|
|
buildSequence([op.APPEND], expressionCode)
|
|
);
|
|
}
|
|
|
|
const generate = visitor.build({
|
|
grammar(node) {
|
|
node.rules.forEach(generate);
|
|
|
|
node.literals = literals;
|
|
node.classes = classes;
|
|
node.expectations = expectations;
|
|
node.functions = functions;
|
|
},
|
|
|
|
rule(node) {
|
|
node.bytecode = generate(node.expression, {
|
|
sp: -1, // stack pointer
|
|
env: { }, // mapping of label names to stack positions
|
|
pluck: [], // fields that have been picked
|
|
action: null // action nodes pass themselves to children here
|
|
});
|
|
},
|
|
|
|
named(node, context) {
|
|
const match = node.match | 0;
|
|
// Expectation not required if node always fail
|
|
const nameIndex = match === NEVER_MATCH ? null : addExpectedConst(
|
|
{ type: "rule", value: node.name }
|
|
);
|
|
|
|
// The code generated below is slightly suboptimal because |FAIL| pushes
|
|
// to the stack, so we need to stick a |POP| in front of it. We lack a
|
|
// dedicated instruction that would just report the failure and not touch
|
|
// the stack.
|
|
return buildSequence(
|
|
[op.SILENT_FAILS_ON],
|
|
generate(node.expression, context),
|
|
[op.SILENT_FAILS_OFF],
|
|
buildCondition(match, [op.IF_ERROR], [op.FAIL, nameIndex], [])
|
|
);
|
|
},
|
|
|
|
choice(node, context) {
|
|
function buildAlternativesCode(alternatives, context) {
|
|
const match = alternatives[0].match | 0;
|
|
const first = generate(alternatives[0], {
|
|
sp: context.sp,
|
|
env: cloneEnv(context.env),
|
|
action: null
|
|
});
|
|
// If an alternative always match, no need to generate code for the next
|
|
// alternatives. Because their will never tried to match, any side-effects
|
|
// from next alternatives is impossible so we can skip their generation
|
|
if (match === ALWAYS_MATCH) {
|
|
return first;
|
|
}
|
|
|
|
// Even if an alternative never match it can have side-effects from
|
|
// a semantic predicates or an actions, so we can not skip generation
|
|
// of the first alternative.
|
|
// We can do that when analysis for possible side-effects will be introduced
|
|
return buildSequence(
|
|
first,
|
|
alternatives.length > 1
|
|
? buildCondition(
|
|
SOMETIMES_MATCH,
|
|
[op.IF_ERROR],
|
|
buildSequence(
|
|
[op.POP],
|
|
buildAlternativesCode(alternatives.slice(1), context)
|
|
),
|
|
[]
|
|
)
|
|
: []
|
|
);
|
|
}
|
|
|
|
return buildAlternativesCode(node.alternatives, context);
|
|
},
|
|
|
|
action(node, context) {
|
|
const env = cloneEnv(context.env);
|
|
const emitCall = node.expression.type !== "sequence"
|
|
|| node.expression.elements.length === 0;
|
|
const expressionCode = generate(node.expression, {
|
|
sp: context.sp + (emitCall ? 1 : 0),
|
|
env,
|
|
action: node
|
|
});
|
|
const match = node.expression.match | 0;
|
|
// Function only required if expression can match
|
|
const functionIndex = emitCall && match !== NEVER_MATCH
|
|
? addFunctionConst(false, Object.keys(env), node.code)
|
|
: null;
|
|
|
|
return emitCall
|
|
? buildSequence(
|
|
[op.PUSH_CURR_POS],
|
|
expressionCode,
|
|
buildCondition(
|
|
match,
|
|
[op.IF_NOT_ERROR],
|
|
buildSequence(
|
|
[op.LOAD_SAVED_POS, 1],
|
|
buildCall(functionIndex, 1, env, context.sp + 2)
|
|
),
|
|
[]
|
|
),
|
|
[op.NIP]
|
|
)
|
|
: expressionCode;
|
|
},
|
|
|
|
sequence(node, context) {
|
|
function buildElementsCode(elements, context) {
|
|
if (elements.length > 0) {
|
|
const processedCount = node.elements.length - elements.length + 1;
|
|
|
|
return buildSequence(
|
|
generate(elements[0], {
|
|
sp: context.sp,
|
|
env: context.env,
|
|
pluck: context.pluck,
|
|
action: null
|
|
}),
|
|
buildCondition(
|
|
elements[0].match | 0,
|
|
[op.IF_NOT_ERROR],
|
|
buildElementsCode(elements.slice(1), {
|
|
sp: context.sp + 1,
|
|
env: context.env,
|
|
pluck: context.pluck,
|
|
action: context.action
|
|
}),
|
|
buildSequence(
|
|
processedCount > 1 ? [op.POP_N, processedCount] : [op.POP],
|
|
[op.POP_CURR_POS],
|
|
[op.PUSH_FAILED]
|
|
)
|
|
)
|
|
);
|
|
} else {
|
|
if (context.pluck.length > 0) {
|
|
return buildSequence(
|
|
[ op.PLUCK, node.elements.length + 1, context.pluck.length ],
|
|
context.pluck.map(eSP => context.sp - eSP)
|
|
);
|
|
}
|
|
|
|
if (context.action) {
|
|
const functionIndex = addFunctionConst(
|
|
false,
|
|
Object.keys(context.env),
|
|
context.action.code
|
|
);
|
|
|
|
return buildSequence(
|
|
[op.LOAD_SAVED_POS, node.elements.length],
|
|
buildCall(
|
|
functionIndex,
|
|
node.elements.length + 1,
|
|
context.env,
|
|
context.sp
|
|
)
|
|
);
|
|
} else {
|
|
return buildSequence([op.WRAP, node.elements.length], [op.NIP]);
|
|
}
|
|
}
|
|
}
|
|
|
|
return buildSequence(
|
|
[op.PUSH_CURR_POS],
|
|
buildElementsCode(node.elements, {
|
|
sp: context.sp + 1,
|
|
env: context.env,
|
|
pluck: [],
|
|
action: context.action
|
|
})
|
|
);
|
|
},
|
|
|
|
labeled(node, context) {
|
|
let env = context.env;
|
|
const label = node.label;
|
|
const sp = context.sp + 1;
|
|
|
|
if (label) {
|
|
env = cloneEnv(context.env);
|
|
context.env[node.label] = sp;
|
|
}
|
|
|
|
if (node.pick) {
|
|
context.pluck.push(sp);
|
|
}
|
|
|
|
return generate(node.expression, {
|
|
sp: context.sp,
|
|
env,
|
|
action: null
|
|
});
|
|
},
|
|
|
|
text(node, context) {
|
|
return buildSequence(
|
|
[op.PUSH_CURR_POS],
|
|
generate(node.expression, {
|
|
sp: context.sp + 1,
|
|
env: cloneEnv(context.env),
|
|
action: null
|
|
}),
|
|
buildCondition(
|
|
node.match | 0,
|
|
[op.IF_NOT_ERROR],
|
|
buildSequence([op.POP], [op.TEXT]),
|
|
[op.NIP]
|
|
)
|
|
);
|
|
},
|
|
|
|
simple_and(node, context) {
|
|
return buildSimplePredicate(node.expression, false, context);
|
|
},
|
|
|
|
simple_not(node, context) {
|
|
return buildSimplePredicate(node.expression, true, context);
|
|
},
|
|
|
|
optional(node, context) {
|
|
return buildSequence(
|
|
generate(node.expression, {
|
|
sp: context.sp,
|
|
env: cloneEnv(context.env),
|
|
action: null
|
|
}),
|
|
buildCondition(
|
|
// Check expression match, not the node match
|
|
// If expression always match, no need to replace FAILED to NULL,
|
|
// because FAILED will never appeared
|
|
-(node.expression.match | 0),
|
|
[op.IF_ERROR],
|
|
buildSequence([op.POP], [op.PUSH_NULL]),
|
|
[]
|
|
)
|
|
);
|
|
},
|
|
|
|
zero_or_more(node, context) {
|
|
const expressionCode = generate(node.expression, {
|
|
sp: context.sp + 1,
|
|
env: cloneEnv(context.env),
|
|
action: null
|
|
});
|
|
|
|
return buildSequence(
|
|
[op.PUSH_EMPTY_ARRAY],
|
|
expressionCode,
|
|
buildAppendLoop(expressionCode),
|
|
[op.POP]
|
|
);
|
|
},
|
|
|
|
one_or_more(node, context) {
|
|
const expressionCode = generate(node.expression, {
|
|
sp: context.sp + 1,
|
|
env: cloneEnv(context.env),
|
|
action: null
|
|
});
|
|
|
|
return buildSequence(
|
|
[op.PUSH_EMPTY_ARRAY],
|
|
expressionCode,
|
|
buildCondition(
|
|
// Condition depends on the expression match, not the node match
|
|
node.expression.match | 0,
|
|
[op.IF_NOT_ERROR],
|
|
buildSequence(buildAppendLoop(expressionCode), [op.POP]),
|
|
buildSequence([op.POP], [op.POP], [op.PUSH_FAILED])
|
|
)
|
|
);
|
|
},
|
|
|
|
group(node, context) {
|
|
return generate(node.expression, {
|
|
sp: context.sp,
|
|
env: cloneEnv(context.env),
|
|
action: null
|
|
});
|
|
},
|
|
|
|
semantic_and(node, context) {
|
|
return buildSemanticPredicate(node, false, context);
|
|
},
|
|
|
|
semantic_not(node, context) {
|
|
return buildSemanticPredicate(node, true, context);
|
|
},
|
|
|
|
rule_ref(node) {
|
|
return [op.RULE, asts.indexOfRule(ast, node.name)];
|
|
},
|
|
|
|
literal(node) {
|
|
if (node.value.length > 0) {
|
|
const match = node.match | 0;
|
|
// String only required if condition is generated or string is
|
|
// case-sensitive and node always match
|
|
const needConst = match === SOMETIMES_MATCH
|
|
|| (match === ALWAYS_MATCH && !node.ignoreCase);
|
|
const stringIndex = needConst ? addLiteralConst(
|
|
node.ignoreCase ? node.value.toLowerCase() : node.value
|
|
) : null;
|
|
// Expectation not required if node always match
|
|
const expectedIndex = match !== ALWAYS_MATCH ? addExpectedConst({
|
|
type: "literal",
|
|
value: node.value,
|
|
ignoreCase: node.ignoreCase
|
|
}) : null;
|
|
|
|
// For case-sensitive strings the value must match the beginning of the
|
|
// remaining input exactly. As a result, we can use |ACCEPT_STRING| and
|
|
// save one |substr| call that would be needed if we used |ACCEPT_N|.
|
|
return buildCondition(
|
|
match,
|
|
node.ignoreCase
|
|
? [op.MATCH_STRING_IC, stringIndex]
|
|
: [op.MATCH_STRING, stringIndex],
|
|
node.ignoreCase
|
|
? [op.ACCEPT_N, node.value.length]
|
|
: [op.ACCEPT_STRING, stringIndex],
|
|
[op.FAIL, expectedIndex]
|
|
);
|
|
}
|
|
|
|
return [op.PUSH_EMPTY_STRING];
|
|
},
|
|
|
|
class(node) {
|
|
const match = node.match | 0;
|
|
// Character class constant only required if condition is generated
|
|
const classIndex = match === SOMETIMES_MATCH ? addClassConst(node) : null;
|
|
// Expectation not required if node always match
|
|
const expectedIndex = match !== ALWAYS_MATCH ? addExpectedConst({
|
|
type: "class",
|
|
value: node.parts,
|
|
inverted: node.inverted,
|
|
ignoreCase: node.ignoreCase
|
|
}) : null;
|
|
|
|
return buildCondition(
|
|
match,
|
|
[op.MATCH_CHAR_CLASS, classIndex],
|
|
[op.ACCEPT_N, 1],
|
|
[op.FAIL, expectedIndex]
|
|
);
|
|
},
|
|
|
|
any(node) {
|
|
const match = node.match | 0;
|
|
// Expectation not required if node always match
|
|
const expectedIndex = match !== ALWAYS_MATCH ? addExpectedConst({
|
|
type: "any"
|
|
}) : null;
|
|
|
|
return buildCondition(
|
|
match,
|
|
[op.MATCH_ANY],
|
|
[op.ACCEPT_N, 1],
|
|
[op.FAIL, expectedIndex]
|
|
);
|
|
}
|
|
});
|
|
|
|
generate(ast);
|
|
}
|
|
|
|
module.exports = generateBytecode;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 15843:
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
const asts = __webpack_require__(19861);
|
|
const op = __webpack_require__(86164);
|
|
const Stack = __webpack_require__(78013);
|
|
const VERSION = __webpack_require__(80244);
|
|
|
|
function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); }
|
|
|
|
function stringEscape(s) {
|
|
// ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a string
|
|
// literal except for the closing quote character, backslash, carriage
|
|
// return, line separator, paragraph separator, and line feed. Any character
|
|
// may appear in the form of an escape sequence.
|
|
//
|
|
// For portability, we also escape all control and non-ASCII characters.
|
|
return s
|
|
.replace(/\\/g, "\\\\") // backslash
|
|
.replace(/"/g, "\\\"") // closing double quote
|
|
.replace(/\0/g, "\\0") // null
|
|
.replace(/\x08/g, "\\b") // backspace
|
|
.replace(/\t/g, "\\t") // horizontal tab
|
|
.replace(/\n/g, "\\n") // line feed
|
|
.replace(/\v/g, "\\v") // vertical tab
|
|
.replace(/\f/g, "\\f") // form feed
|
|
.replace(/\r/g, "\\r") // carriage return
|
|
.replace(/[\x00-\x0F]/g, ch => "\\x0" + hex(ch))
|
|
.replace(/[\x10-\x1F\x7F-\xFF]/g, ch => "\\x" + hex(ch))
|
|
.replace(/[\u0100-\u0FFF]/g, ch => "\\u0" + hex(ch))
|
|
.replace(/[\u1000-\uFFFF]/g, ch => "\\u" + hex(ch));
|
|
}
|
|
|
|
function regexpClassEscape(s) {
|
|
// Based on ECMA-262, 5th ed., 7.8.5 & 15.10.1.
|
|
//
|
|
// For portability, we also escape all control and non-ASCII characters.
|
|
return s
|
|
.replace(/\\/g, "\\\\") // backslash
|
|
.replace(/\//g, "\\/") // closing slash
|
|
.replace(/]/g, "\\]") // closing bracket
|
|
.replace(/\^/g, "\\^") // caret
|
|
.replace(/-/g, "\\-") // dash
|
|
.replace(/\0/g, "\\0") // null
|
|
.replace(/\x08/g, "\\b") // backspace
|
|
.replace(/\t/g, "\\t") // horizontal tab
|
|
.replace(/\n/g, "\\n") // line feed
|
|
.replace(/\v/g, "\\v") // vertical tab
|
|
.replace(/\f/g, "\\f") // form feed
|
|
.replace(/\r/g, "\\r") // carriage return
|
|
.replace(/[\x00-\x0F]/g, ch => "\\x0" + hex(ch))
|
|
.replace(/[\x10-\x1F\x7F-\xFF]/g, ch => "\\x" + hex(ch))
|
|
.replace(/[\u0100-\u0FFF]/g, ch => "\\u0" + hex(ch))
|
|
.replace(/[\u1000-\uFFFF]/g, ch => "\\u" + hex(ch));
|
|
}
|
|
|
|
// Generates parser JavaScript code.
|
|
function generateJS(ast, options) {
|
|
// These only indent non-empty lines to avoid trailing whitespace.
|
|
function indent2(code) { return code.replace(/^(.+)$/gm, " $1"); }
|
|
|
|
function l(i) { return "peg$c" + i; } // |literals[i]| of the abstract machine
|
|
function r(i) { return "peg$r" + i; } // |classes[i]| of the abstract machine
|
|
function e(i) { return "peg$e" + i; } // |expectations[i]| of the abstract machine
|
|
function f(i) { return "peg$f" + i; } // |actions[i]| of the abstract machine
|
|
|
|
function generateTables() {
|
|
function buildLiteral(literal) {
|
|
return "\"" + stringEscape(literal) + "\"";
|
|
}
|
|
|
|
function buildRegexp(cls) {
|
|
return "/^["
|
|
+ (cls.inverted ? "^" : "")
|
|
+ cls.value.map(part =>
|
|
Array.isArray(part)
|
|
? regexpClassEscape(part[0])
|
|
+ "-"
|
|
+ regexpClassEscape(part[1])
|
|
: regexpClassEscape(part)
|
|
).join("")
|
|
+ "]/" + (cls.ignoreCase ? "i" : "");
|
|
}
|
|
|
|
function buildExpectation(e) {
|
|
switch (e.type) {
|
|
case "rule": {
|
|
return "peg$otherExpectation(\"" + stringEscape(e.value) + "\")";
|
|
}
|
|
case "literal": {
|
|
return "peg$literalExpectation(\""
|
|
+ stringEscape(e.value)
|
|
+ "\", "
|
|
+ e.ignoreCase
|
|
+ ")";
|
|
}
|
|
case "class": {
|
|
const parts = e.value.map(part =>
|
|
Array.isArray(part)
|
|
? "[\"" + stringEscape(part[0]) + "\", \"" + stringEscape(part[1]) + "\"]"
|
|
: "\"" + stringEscape(part) + "\""
|
|
).join(", ");
|
|
|
|
return "peg$classExpectation(["
|
|
+ parts + "], "
|
|
+ e.inverted + ", "
|
|
+ e.ignoreCase
|
|
+ ")";
|
|
}
|
|
case "any": return "peg$anyExpectation()";
|
|
default: throw new Error("Unknown expectation type (" + JSON.stringify(e) + ")");
|
|
}
|
|
}
|
|
|
|
function buildFunc(a) {
|
|
return "function(" + a.params.join(", ") + ") {"
|
|
+ a.body
|
|
+ "}";
|
|
}
|
|
|
|
return ast.literals.map(
|
|
(c, i) => "var " + l(i) + " = " + buildLiteral(c) + ";"
|
|
).concat("", ast.classes.map(
|
|
(c, i) => "var " + r(i) + " = " + buildRegexp(c) + ";"
|
|
)).concat("", ast.expectations.map(
|
|
(c, i) => "var " + e(i) + " = " + buildExpectation(c) + ";"
|
|
)).concat("", ast.functions.map(
|
|
(c, i) => "var " + f(i) + " = " + buildFunc(c) + ";"
|
|
)).join("\n");
|
|
}
|
|
|
|
function generateRuleHeader(ruleNameCode, ruleIndexCode) {
|
|
const parts = [];
|
|
|
|
parts.push("");
|
|
|
|
if (options.trace) {
|
|
parts.push([
|
|
"peg$tracer.trace({",
|
|
" type: \"rule.enter\",",
|
|
" rule: " + ruleNameCode + ",",
|
|
" location: peg$computeLocation(startPos, startPos)",
|
|
"});",
|
|
""
|
|
].join("\n"));
|
|
}
|
|
|
|
if (options.cache) {
|
|
parts.push([
|
|
"var key = peg$currPos * " + ast.rules.length + " + " + ruleIndexCode + ";",
|
|
"var cached = peg$resultsCache[key];",
|
|
"",
|
|
"if (cached) {",
|
|
" peg$currPos = cached.nextPos;",
|
|
""
|
|
].join("\n"));
|
|
|
|
if (options.trace) {
|
|
parts.push([
|
|
"if (cached.result !== peg$FAILED) {",
|
|
" peg$tracer.trace({",
|
|
" type: \"rule.match\",",
|
|
" rule: " + ruleNameCode + ",",
|
|
" result: cached.result,",
|
|
" location: peg$computeLocation(startPos, peg$currPos)",
|
|
" });",
|
|
"} else {",
|
|
" peg$tracer.trace({",
|
|
" type: \"rule.fail\",",
|
|
" rule: " + ruleNameCode + ",",
|
|
" location: peg$computeLocation(startPos, startPos)",
|
|
" });",
|
|
"}",
|
|
""
|
|
].join("\n"));
|
|
}
|
|
|
|
parts.push([
|
|
" return cached.result;",
|
|
"}",
|
|
""
|
|
].join("\n"));
|
|
}
|
|
|
|
return parts.join("\n");
|
|
}
|
|
|
|
function generateRuleFooter(ruleNameCode, resultCode) {
|
|
const parts = [];
|
|
|
|
if (options.cache) {
|
|
parts.push([
|
|
"",
|
|
"peg$resultsCache[key] = { nextPos: peg$currPos, result: " + resultCode + " };"
|
|
].join("\n"));
|
|
}
|
|
|
|
if (options.trace) {
|
|
parts.push([
|
|
"",
|
|
"if (" + resultCode + " !== peg$FAILED) {",
|
|
" peg$tracer.trace({",
|
|
" type: \"rule.match\",",
|
|
" rule: " + ruleNameCode + ",",
|
|
" result: " + resultCode + ",",
|
|
" location: peg$computeLocation(startPos, peg$currPos)",
|
|
" });",
|
|
"} else {",
|
|
" peg$tracer.trace({",
|
|
" type: \"rule.fail\",",
|
|
" rule: " + ruleNameCode + ",",
|
|
" location: peg$computeLocation(startPos, startPos)",
|
|
" });",
|
|
"}"
|
|
].join("\n"));
|
|
}
|
|
|
|
parts.push([
|
|
"",
|
|
"return " + resultCode + ";"
|
|
].join("\n"));
|
|
|
|
return parts.join("\n");
|
|
}
|
|
|
|
function generateRuleFunction(rule) {
|
|
const parts = [];
|
|
const stack = new Stack(rule.name, "s", "var");
|
|
|
|
function compile(bc) {
|
|
let ip = 0;
|
|
const end = bc.length;
|
|
const parts = [];
|
|
let value;
|
|
|
|
function compileCondition(cond, argCount) {
|
|
const baseLength = argCount + 3;
|
|
const thenLength = bc[ip + baseLength - 2];
|
|
const elseLength = bc[ip + baseLength - 1];
|
|
let thenCode, elseCode;
|
|
|
|
stack.checkedIf(ip,
|
|
() => {
|
|
ip += baseLength;
|
|
thenCode = compile(bc.slice(ip, ip + thenLength));
|
|
ip += thenLength;
|
|
},
|
|
elseLength > 0 ? () => {
|
|
elseCode = compile(bc.slice(ip, ip + elseLength));
|
|
ip += elseLength;
|
|
} : null
|
|
);
|
|
|
|
parts.push("if (" + cond + ") {");
|
|
parts.push(indent2(thenCode));
|
|
if (elseLength > 0) {
|
|
parts.push("} else {");
|
|
parts.push(indent2(elseCode));
|
|
}
|
|
parts.push("}");
|
|
}
|
|
|
|
function compileLoop(cond) {
|
|
const baseLength = 2;
|
|
const bodyLength = bc[ip + baseLength - 1];
|
|
let bodyCode;
|
|
|
|
stack.checkedLoop(ip, () => {
|
|
ip += baseLength;
|
|
bodyCode = compile(bc.slice(ip, ip + bodyLength));
|
|
ip += bodyLength;
|
|
});
|
|
|
|
parts.push("while (" + cond + ") {");
|
|
parts.push(indent2(bodyCode));
|
|
parts.push("}");
|
|
}
|
|
|
|
function compileCall() {
|
|
const baseLength = 4;
|
|
const paramsLength = bc[ip + baseLength - 1];
|
|
|
|
const value = f(bc[ip + 1]) + "("
|
|
+ bc.slice(ip + baseLength, ip + baseLength + paramsLength).map(
|
|
p => stack.index(p)
|
|
).join(", ")
|
|
+ ")";
|
|
stack.pop(bc[ip + 2]);
|
|
parts.push(stack.push(value));
|
|
ip += baseLength + paramsLength;
|
|
}
|
|
|
|
while (ip < end) {
|
|
switch (bc[ip]) {
|
|
case op.PUSH_EMPTY_STRING: // PUSH_EMPTY_STRING
|
|
parts.push(stack.push("''"));
|
|
ip++;
|
|
break;
|
|
|
|
case op.PUSH_CURR_POS: // PUSH_CURR_POS
|
|
parts.push(stack.push("peg$currPos"));
|
|
ip++;
|
|
break;
|
|
|
|
case op.PUSH_UNDEFINED: // PUSH_UNDEFINED
|
|
parts.push(stack.push("undefined"));
|
|
ip++;
|
|
break;
|
|
|
|
case op.PUSH_NULL: // PUSH_NULL
|
|
parts.push(stack.push("null"));
|
|
ip++;
|
|
break;
|
|
|
|
case op.PUSH_FAILED: // PUSH_FAILED
|
|
parts.push(stack.push("peg$FAILED"));
|
|
ip++;
|
|
break;
|
|
|
|
case op.PUSH_EMPTY_ARRAY: // PUSH_EMPTY_ARRAY
|
|
parts.push(stack.push("[]"));
|
|
ip++;
|
|
break;
|
|
|
|
case op.POP: // POP
|
|
stack.pop();
|
|
ip++;
|
|
break;
|
|
|
|
case op.POP_CURR_POS: // POP_CURR_POS
|
|
parts.push("peg$currPos = " + stack.pop() + ";");
|
|
ip++;
|
|
break;
|
|
|
|
case op.POP_N: // POP_N n
|
|
stack.pop(bc[ip + 1]);
|
|
ip += 2;
|
|
break;
|
|
|
|
case op.NIP: // NIP
|
|
value = stack.pop();
|
|
stack.pop();
|
|
parts.push(stack.push(value));
|
|
ip++;
|
|
break;
|
|
|
|
case op.APPEND: // APPEND
|
|
value = stack.pop();
|
|
parts.push(stack.top() + ".push(" + value + ");");
|
|
ip++;
|
|
break;
|
|
|
|
case op.WRAP: // WRAP n
|
|
parts.push(
|
|
// @ts-expect-error pop() returns array if argument is specified
|
|
stack.push("[" + stack.pop(bc[ip + 1]).join(", ") + "]")
|
|
);
|
|
ip += 2;
|
|
break;
|
|
|
|
case op.TEXT: // TEXT
|
|
parts.push(
|
|
stack.push("input.substring(" + stack.pop() + ", peg$currPos)")
|
|
);
|
|
ip++;
|
|
break;
|
|
|
|
case op.PLUCK: { // PLUCK n, k, p1, ..., pK
|
|
const baseLength = 3;
|
|
const paramsLength = bc[ip + baseLength - 1];
|
|
const n = baseLength + paramsLength;
|
|
value = bc.slice(ip + baseLength, ip + n);
|
|
value = paramsLength === 1
|
|
? stack.index(value[0])
|
|
: `[ ${
|
|
value.map(p => stack.index(p)).join(", ")
|
|
} ]`;
|
|
stack.pop(bc[ip + 1]);
|
|
parts.push(stack.push(value));
|
|
ip += n;
|
|
break;
|
|
}
|
|
|
|
case op.IF: // IF t, f
|
|
compileCondition(stack.top(), 0);
|
|
break;
|
|
|
|
case op.IF_ERROR: // IF_ERROR t, f
|
|
compileCondition(stack.top() + " === peg$FAILED", 0);
|
|
break;
|
|
|
|
case op.IF_NOT_ERROR: // IF_NOT_ERROR t, f
|
|
compileCondition(stack.top() + " !== peg$FAILED", 0);
|
|
break;
|
|
|
|
case op.WHILE_NOT_ERROR: // WHILE_NOT_ERROR b
|
|
compileLoop(stack.top() + " !== peg$FAILED");
|
|
break;
|
|
|
|
case op.MATCH_ANY: // MATCH_ANY a, f, ...
|
|
compileCondition("input.length > peg$currPos", 0);
|
|
break;
|
|
|
|
case op.MATCH_STRING: // MATCH_STRING s, a, f, ...
|
|
compileCondition(
|
|
ast.literals[bc[ip + 1]].length > 1
|
|
? "input.substr(peg$currPos, "
|
|
+ ast.literals[bc[ip + 1]].length
|
|
+ ") === "
|
|
+ l(bc[ip + 1])
|
|
: "input.charCodeAt(peg$currPos) === "
|
|
+ ast.literals[bc[ip + 1]].charCodeAt(0),
|
|
1
|
|
);
|
|
break;
|
|
|
|
case op.MATCH_STRING_IC: // MATCH_STRING_IC s, a, f, ...
|
|
compileCondition(
|
|
"input.substr(peg$currPos, "
|
|
+ ast.literals[bc[ip + 1]].length
|
|
+ ").toLowerCase() === "
|
|
+ l(bc[ip + 1]),
|
|
1
|
|
);
|
|
break;
|
|
|
|
case op.MATCH_CHAR_CLASS: // MATCH_CHAR_CLASS c, a, f, ...
|
|
compileCondition(
|
|
r(bc[ip + 1]) + ".test(input.charAt(peg$currPos))",
|
|
1
|
|
);
|
|
break;
|
|
|
|
case op.ACCEPT_N: // ACCEPT_N n
|
|
parts.push(stack.push(
|
|
bc[ip + 1] > 1
|
|
? "input.substr(peg$currPos, " + bc[ip + 1] + ")"
|
|
: "input.charAt(peg$currPos)"
|
|
));
|
|
parts.push(
|
|
bc[ip + 1] > 1
|
|
? "peg$currPos += " + bc[ip + 1] + ";"
|
|
: "peg$currPos++;"
|
|
);
|
|
ip += 2;
|
|
break;
|
|
|
|
case op.ACCEPT_STRING: // ACCEPT_STRING s
|
|
parts.push(stack.push(l(bc[ip + 1])));
|
|
parts.push(
|
|
ast.literals[bc[ip + 1]].length > 1
|
|
? "peg$currPos += " + ast.literals[bc[ip + 1]].length + ";"
|
|
: "peg$currPos++;"
|
|
);
|
|
ip += 2;
|
|
break;
|
|
|
|
case op.FAIL: // FAIL e
|
|
parts.push(stack.push("peg$FAILED"));
|
|
parts.push("if (peg$silentFails === 0) { peg$fail(" + e(bc[ip + 1]) + "); }");
|
|
ip += 2;
|
|
break;
|
|
|
|
case op.LOAD_SAVED_POS: // LOAD_SAVED_POS p
|
|
parts.push("peg$savedPos = " + stack.index(bc[ip + 1]) + ";");
|
|
ip += 2;
|
|
break;
|
|
|
|
case op.UPDATE_SAVED_POS: // UPDATE_SAVED_POS
|
|
parts.push("peg$savedPos = peg$currPos;");
|
|
ip++;
|
|
break;
|
|
|
|
case op.CALL: // CALL f, n, pc, p1, p2, ..., pN
|
|
compileCall();
|
|
break;
|
|
|
|
case op.RULE: // RULE r
|
|
parts.push(stack.push("peg$parse" + ast.rules[bc[ip + 1]].name + "()"));
|
|
ip += 2;
|
|
break;
|
|
|
|
case op.SILENT_FAILS_ON: // SILENT_FAILS_ON
|
|
parts.push("peg$silentFails++;");
|
|
ip++;
|
|
break;
|
|
|
|
case op.SILENT_FAILS_OFF: // SILENT_FAILS_OFF
|
|
parts.push("peg$silentFails--;");
|
|
ip++;
|
|
break;
|
|
|
|
default:
|
|
throw new Error("Invalid opcode: " + bc[ip] + ".");
|
|
}
|
|
}
|
|
|
|
return parts.join("\n");
|
|
}
|
|
|
|
const code = compile(rule.bytecode);
|
|
|
|
parts.push("function peg$parse" + rule.name + "() {");
|
|
|
|
if (options.trace) {
|
|
parts.push(" var startPos = peg$currPos;");
|
|
}
|
|
|
|
parts.push(indent2(stack.defines()));
|
|
|
|
parts.push(indent2(generateRuleHeader(
|
|
"\"" + stringEscape(rule.name) + "\"",
|
|
asts.indexOfRule(ast, rule.name)
|
|
)));
|
|
parts.push(indent2(code));
|
|
parts.push(indent2(generateRuleFooter(
|
|
"\"" + stringEscape(rule.name) + "\"",
|
|
stack.result()
|
|
)));
|
|
|
|
parts.push("}");
|
|
|
|
return parts.join("\n");
|
|
}
|
|
|
|
function generateToplevel() {
|
|
const parts = [];
|
|
|
|
if (ast.topLevelInitializer) {
|
|
parts.push(ast.topLevelInitializer.code);
|
|
parts.push("");
|
|
}
|
|
|
|
parts.push([
|
|
"function peg$subclass(child, parent) {",
|
|
" function C() { this.constructor = child; }",
|
|
" C.prototype = parent.prototype;",
|
|
" child.prototype = new C();",
|
|
"}",
|
|
"",
|
|
"function peg$SyntaxError(message, expected, found, location) {",
|
|
" var self = Error.call(this, message);",
|
|
" if (Object.setPrototypeOf) {",
|
|
" Object.setPrototypeOf(self, peg$SyntaxError.prototype);",
|
|
" }",
|
|
" self.expected = expected;",
|
|
" self.found = found;",
|
|
" self.location = location;",
|
|
" self.name = \"SyntaxError\";",
|
|
" return self;",
|
|
"}",
|
|
"",
|
|
"peg$subclass(peg$SyntaxError, Error);",
|
|
"",
|
|
"function peg$padEnd(str, targetLength, padString) {",
|
|
" padString = padString || \" \";",
|
|
" if (str.length > targetLength) { return str; }",
|
|
" targetLength -= str.length;",
|
|
" padString += padString.repeat(targetLength);",
|
|
" return str + padString.slice(0, targetLength);",
|
|
"}",
|
|
"",
|
|
"peg$SyntaxError.prototype.format = function(sources) {",
|
|
" var str = \"Error: \" + this.message;",
|
|
" if (this.location) {",
|
|
" var src = null;",
|
|
" var k;",
|
|
" for (k = 0; k < sources.length; k++) {",
|
|
" if (sources[k].source === this.location.source) {",
|
|
" src = sources[k].text.split(/\\r\\n|\\n|\\r/g);",
|
|
" break;",
|
|
" }",
|
|
" }",
|
|
" var s = this.location.start;",
|
|
" var loc = this.location.source + \":\" + s.line + \":\" + s.column;",
|
|
" if (src) {",
|
|
" var e = this.location.end;",
|
|
" var filler = peg$padEnd(\"\", s.line.toString().length);",
|
|
" var line = src[s.line - 1];",
|
|
" var last = s.line === e.line ? e.column : line.length + 1;",
|
|
" str += \"\\n --> \" + loc + \"\\n\"",
|
|
" + filler + \" |\\n\"",
|
|
" + s.line + \" | \" + line + \"\\n\"",
|
|
" + filler + \" | \" + peg$padEnd(\"\", s.column - 1)",
|
|
" + peg$padEnd(\"\", last - s.column, \"^\");",
|
|
" } else {",
|
|
" str += \"\\n at \" + loc;",
|
|
" }",
|
|
" }",
|
|
" return str;",
|
|
"};",
|
|
"",
|
|
"peg$SyntaxError.buildMessage = function(expected, found) {",
|
|
" var DESCRIBE_EXPECTATION_FNS = {",
|
|
" literal: function(expectation) {",
|
|
" return \"\\\"\" + literalEscape(expectation.text) + \"\\\"\";",
|
|
" },",
|
|
"",
|
|
" class: function(expectation) {",
|
|
" var escapedParts = expectation.parts.map(function(part) {",
|
|
" return Array.isArray(part)",
|
|
" ? classEscape(part[0]) + \"-\" + classEscape(part[1])",
|
|
" : classEscape(part);",
|
|
" });",
|
|
"",
|
|
" return \"[\" + (expectation.inverted ? \"^\" : \"\") + escapedParts + \"]\";",
|
|
" },",
|
|
"",
|
|
" any: function() {",
|
|
" return \"any character\";",
|
|
" },",
|
|
"",
|
|
" end: function() {",
|
|
" return \"end of input\";",
|
|
" },",
|
|
"",
|
|
" other: function(expectation) {",
|
|
" return expectation.description;",
|
|
" }",
|
|
" };",
|
|
"",
|
|
" function hex(ch) {",
|
|
" return ch.charCodeAt(0).toString(16).toUpperCase();",
|
|
" }",
|
|
"",
|
|
" function literalEscape(s) {",
|
|
" return s",
|
|
" .replace(/\\\\/g, \"\\\\\\\\\")", // backslash
|
|
" .replace(/\"/g, \"\\\\\\\"\")", // closing double quote
|
|
" .replace(/\\0/g, \"\\\\0\")", // null
|
|
" .replace(/\\t/g, \"\\\\t\")", // horizontal tab
|
|
" .replace(/\\n/g, \"\\\\n\")", // line feed
|
|
" .replace(/\\r/g, \"\\\\r\")", // carriage return
|
|
" .replace(/[\\x00-\\x0F]/g, function(ch) { return \"\\\\x0\" + hex(ch); })",
|
|
" .replace(/[\\x10-\\x1F\\x7F-\\x9F]/g, function(ch) { return \"\\\\x\" + hex(ch); });",
|
|
" }",
|
|
"",
|
|
" function classEscape(s) {",
|
|
" return s",
|
|
" .replace(/\\\\/g, \"\\\\\\\\\")", // backslash
|
|
" .replace(/\\]/g, \"\\\\]\")", // closing bracket
|
|
" .replace(/\\^/g, \"\\\\^\")", // caret
|
|
" .replace(/-/g, \"\\\\-\")", // dash
|
|
" .replace(/\\0/g, \"\\\\0\")", // null
|
|
" .replace(/\\t/g, \"\\\\t\")", // horizontal tab
|
|
" .replace(/\\n/g, \"\\\\n\")", // line feed
|
|
" .replace(/\\r/g, \"\\\\r\")", // carriage return
|
|
" .replace(/[\\x00-\\x0F]/g, function(ch) { return \"\\\\x0\" + hex(ch); })",
|
|
" .replace(/[\\x10-\\x1F\\x7F-\\x9F]/g, function(ch) { return \"\\\\x\" + hex(ch); });",
|
|
" }",
|
|
"",
|
|
" function describeExpectation(expectation) {",
|
|
" return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation);",
|
|
" }",
|
|
"",
|
|
" function describeExpected(expected) {",
|
|
" var descriptions = expected.map(describeExpectation);",
|
|
" var i, j;",
|
|
"",
|
|
" descriptions.sort();",
|
|
"",
|
|
" if (descriptions.length > 0) {",
|
|
" for (i = 1, j = 1; i < descriptions.length; i++) {",
|
|
" if (descriptions[i - 1] !== descriptions[i]) {",
|
|
" descriptions[j] = descriptions[i];",
|
|
" j++;",
|
|
" }",
|
|
" }",
|
|
" descriptions.length = j;",
|
|
" }",
|
|
"",
|
|
" switch (descriptions.length) {",
|
|
" case 1:",
|
|
" return descriptions[0];",
|
|
"",
|
|
" case 2:",
|
|
" return descriptions[0] + \" or \" + descriptions[1];",
|
|
"",
|
|
" default:",
|
|
" return descriptions.slice(0, -1).join(\", \")",
|
|
" + \", or \"",
|
|
" + descriptions[descriptions.length - 1];",
|
|
" }",
|
|
" }",
|
|
"",
|
|
" function describeFound(found) {",
|
|
" return found ? \"\\\"\" + literalEscape(found) + \"\\\"\" : \"end of input\";",
|
|
" }",
|
|
"",
|
|
" return \"Expected \" + describeExpected(expected) + \" but \" + describeFound(found) + \" found.\";",
|
|
"};",
|
|
""
|
|
].join("\n"));
|
|
|
|
if (options.trace) {
|
|
parts.push([
|
|
"function peg$DefaultTracer() {",
|
|
" this.indentLevel = 0;",
|
|
"}",
|
|
"",
|
|
"peg$DefaultTracer.prototype.trace = function(event) {",
|
|
" var that = this;",
|
|
"",
|
|
" function log(event) {",
|
|
" function repeat(string, n) {",
|
|
" var result = \"\", i;",
|
|
"",
|
|
" for (i = 0; i < n; i++) {",
|
|
" result += string;",
|
|
" }",
|
|
"",
|
|
" return result;",
|
|
" }",
|
|
"",
|
|
" function pad(string, length) {",
|
|
" return string + repeat(\" \", length - string.length);",
|
|
" }",
|
|
"",
|
|
" if (typeof console === \"object\") {", // IE 8-10
|
|
" console.log(",
|
|
" event.location.start.line + \":\" + event.location.start.column + \"-\"",
|
|
" + event.location.end.line + \":\" + event.location.end.column + \" \"",
|
|
" + pad(event.type, 10) + \" \"",
|
|
" + repeat(\" \", that.indentLevel) + event.rule",
|
|
" );",
|
|
" }",
|
|
" }",
|
|
"",
|
|
" switch (event.type) {",
|
|
" case \"rule.enter\":",
|
|
" log(event);",
|
|
" this.indentLevel++;",
|
|
" break;",
|
|
"",
|
|
" case \"rule.match\":",
|
|
" this.indentLevel--;",
|
|
" log(event);",
|
|
" break;",
|
|
"",
|
|
" case \"rule.fail\":",
|
|
" this.indentLevel--;",
|
|
" log(event);",
|
|
" break;",
|
|
"",
|
|
" default:",
|
|
" throw new Error(\"Invalid event type: \" + event.type + \".\");",
|
|
" }",
|
|
"};",
|
|
""
|
|
].join("\n"));
|
|
}
|
|
|
|
const startRuleFunctions = "{ "
|
|
+ options.allowedStartRules.map(
|
|
r => r + ": peg$parse" + r
|
|
).join(", ")
|
|
+ " }";
|
|
const startRuleFunction = "peg$parse" + options.allowedStartRules[0];
|
|
|
|
parts.push([
|
|
"function peg$parse(input, options) {",
|
|
" options = options !== undefined ? options : {};",
|
|
"",
|
|
" var peg$FAILED = {};",
|
|
" var peg$source = options.grammarSource;",
|
|
"",
|
|
" var peg$startRuleFunctions = " + startRuleFunctions + ";",
|
|
" var peg$startRuleFunction = " + startRuleFunction + ";",
|
|
"",
|
|
indent2(generateTables()),
|
|
"",
|
|
" var peg$currPos = 0;",
|
|
" var peg$savedPos = 0;",
|
|
" var peg$posDetailsCache = [{ line: 1, column: 1 }];",
|
|
" var peg$maxFailPos = 0;",
|
|
" var peg$maxFailExpected = [];",
|
|
" var peg$silentFails = 0;", // 0 = report failures, > 0 = silence failures
|
|
""
|
|
].join("\n"));
|
|
|
|
if (options.cache) {
|
|
parts.push([
|
|
" var peg$resultsCache = {};",
|
|
""
|
|
].join("\n"));
|
|
}
|
|
|
|
if (options.trace) {
|
|
parts.push([
|
|
" var peg$tracer = \"tracer\" in options ? options.tracer : new peg$DefaultTracer();",
|
|
""
|
|
].join("\n"));
|
|
}
|
|
|
|
parts.push([
|
|
" var peg$result;",
|
|
"",
|
|
" if (\"startRule\" in options) {",
|
|
" if (!(options.startRule in peg$startRuleFunctions)) {",
|
|
" throw new Error(\"Can't start parsing from rule \\\"\" + options.startRule + \"\\\".\");",
|
|
" }",
|
|
"",
|
|
" peg$startRuleFunction = peg$startRuleFunctions[options.startRule];",
|
|
" }",
|
|
"",
|
|
" function text() {",
|
|
" return input.substring(peg$savedPos, peg$currPos);",
|
|
" }",
|
|
"",
|
|
" function offset() {",
|
|
" return peg$savedPos;",
|
|
" }",
|
|
"",
|
|
" function range() {",
|
|
" return {",
|
|
" source: peg$source,",
|
|
" start: peg$savedPos,",
|
|
" end: peg$currPos",
|
|
" };",
|
|
" }",
|
|
"",
|
|
" function location() {",
|
|
" return peg$computeLocation(peg$savedPos, peg$currPos);",
|
|
" }",
|
|
"",
|
|
" function expected(description, location) {",
|
|
" location = location !== undefined",
|
|
" ? location",
|
|
" : peg$computeLocation(peg$savedPos, peg$currPos);",
|
|
"",
|
|
" throw peg$buildStructuredError(",
|
|
" [peg$otherExpectation(description)],",
|
|
" input.substring(peg$savedPos, peg$currPos),",
|
|
" location",
|
|
" );",
|
|
" }",
|
|
"",
|
|
" function error(message, location) {",
|
|
" location = location !== undefined",
|
|
" ? location",
|
|
" : peg$computeLocation(peg$savedPos, peg$currPos);",
|
|
"",
|
|
" throw peg$buildSimpleError(message, location);",
|
|
" }",
|
|
"",
|
|
" function peg$literalExpectation(text, ignoreCase) {",
|
|
" return { type: \"literal\", text: text, ignoreCase: ignoreCase };",
|
|
" }",
|
|
"",
|
|
" function peg$classExpectation(parts, inverted, ignoreCase) {",
|
|
" return { type: \"class\", parts: parts, inverted: inverted, ignoreCase: ignoreCase };",
|
|
" }",
|
|
"",
|
|
" function peg$anyExpectation() {",
|
|
" return { type: \"any\" };",
|
|
" }",
|
|
"",
|
|
" function peg$endExpectation() {",
|
|
" return { type: \"end\" };",
|
|
" }",
|
|
"",
|
|
" function peg$otherExpectation(description) {",
|
|
" return { type: \"other\", description: description };",
|
|
" }",
|
|
"",
|
|
" function peg$computePosDetails(pos) {",
|
|
" var details = peg$posDetailsCache[pos];",
|
|
" var p;",
|
|
"",
|
|
" if (details) {",
|
|
" return details;",
|
|
" } else {",
|
|
" p = pos - 1;",
|
|
" while (!peg$posDetailsCache[p]) {",
|
|
" p--;",
|
|
" }",
|
|
"",
|
|
" details = peg$posDetailsCache[p];",
|
|
" details = {",
|
|
" line: details.line,",
|
|
" column: details.column",
|
|
" };",
|
|
"",
|
|
" while (p < pos) {",
|
|
" if (input.charCodeAt(p) === 10) {",
|
|
" details.line++;",
|
|
" details.column = 1;",
|
|
" } else {",
|
|
" details.column++;",
|
|
" }",
|
|
"",
|
|
" p++;",
|
|
" }",
|
|
"",
|
|
" peg$posDetailsCache[pos] = details;",
|
|
"",
|
|
" return details;",
|
|
" }",
|
|
" }",
|
|
"",
|
|
" function peg$computeLocation(startPos, endPos) {",
|
|
" var startPosDetails = peg$computePosDetails(startPos);",
|
|
" var endPosDetails = peg$computePosDetails(endPos);",
|
|
"",
|
|
" return {",
|
|
" source: peg$source,",
|
|
" start: {",
|
|
" offset: startPos,",
|
|
" line: startPosDetails.line,",
|
|
" column: startPosDetails.column",
|
|
" },",
|
|
" end: {",
|
|
" offset: endPos,",
|
|
" line: endPosDetails.line,",
|
|
" column: endPosDetails.column",
|
|
" }",
|
|
" };",
|
|
" }",
|
|
"",
|
|
" function peg$fail(expected) {",
|
|
" if (peg$currPos < peg$maxFailPos) { return; }",
|
|
"",
|
|
" if (peg$currPos > peg$maxFailPos) {",
|
|
" peg$maxFailPos = peg$currPos;",
|
|
" peg$maxFailExpected = [];",
|
|
" }",
|
|
"",
|
|
" peg$maxFailExpected.push(expected);",
|
|
" }",
|
|
"",
|
|
" function peg$buildSimpleError(message, location) {",
|
|
" return new peg$SyntaxError(message, null, null, location);",
|
|
" }",
|
|
"",
|
|
" function peg$buildStructuredError(expected, found, location) {",
|
|
" return new peg$SyntaxError(",
|
|
" peg$SyntaxError.buildMessage(expected, found),",
|
|
" expected,",
|
|
" found,",
|
|
" location",
|
|
" );",
|
|
" }",
|
|
""
|
|
].join("\n"));
|
|
|
|
ast.rules.forEach(rule => {
|
|
parts.push(indent2(generateRuleFunction(rule)));
|
|
parts.push("");
|
|
});
|
|
|
|
if (ast.initializer) {
|
|
parts.push(indent2(ast.initializer.code));
|
|
parts.push("");
|
|
}
|
|
|
|
parts.push([
|
|
" peg$result = peg$startRuleFunction();",
|
|
"",
|
|
" if (peg$result !== peg$FAILED && peg$currPos === input.length) {",
|
|
" return peg$result;",
|
|
" } else {",
|
|
" if (peg$result !== peg$FAILED && peg$currPos < input.length) {",
|
|
" peg$fail(peg$endExpectation());",
|
|
" }",
|
|
"",
|
|
" throw peg$buildStructuredError(",
|
|
" peg$maxFailExpected,",
|
|
" peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null,",
|
|
" peg$maxFailPos < input.length",
|
|
" ? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1)",
|
|
" : peg$computeLocation(peg$maxFailPos, peg$maxFailPos)",
|
|
" );",
|
|
" }",
|
|
"}"
|
|
].join("\n"));
|
|
|
|
return parts.join("\n");
|
|
}
|
|
|
|
function generateWrapper(toplevelCode) {
|
|
function generateGeneratedByComment() {
|
|
return [
|
|
`// Generated by Peggy ${VERSION}.`,
|
|
"//",
|
|
"// https://peggyjs.org/"
|
|
].join("\n");
|
|
}
|
|
|
|
function generateParserObject() {
|
|
return options.trace
|
|
? [
|
|
"{",
|
|
" SyntaxError: peg$SyntaxError,",
|
|
" DefaultTracer: peg$DefaultTracer,",
|
|
" parse: peg$parse",
|
|
"}"
|
|
].join("\n")
|
|
: [
|
|
"{",
|
|
" SyntaxError: peg$SyntaxError,",
|
|
" parse: peg$parse",
|
|
"}"
|
|
].join("\n");
|
|
}
|
|
|
|
function generateParserExports() {
|
|
return options.trace
|
|
? [
|
|
"{",
|
|
" peg$SyntaxError as SyntaxError,",
|
|
" peg$DefaultTracer as DefaultTracer,",
|
|
" peg$parse as parse",
|
|
"}"
|
|
].join("\n")
|
|
: [
|
|
"{",
|
|
" peg$SyntaxError as SyntaxError,",
|
|
" peg$parse as parse",
|
|
"}"
|
|
].join("\n");
|
|
}
|
|
|
|
const generators = {
|
|
bare() {
|
|
return [
|
|
generateGeneratedByComment(),
|
|
"(function() {",
|
|
" \"use strict\";",
|
|
"",
|
|
indent2(toplevelCode),
|
|
"",
|
|
indent2("return " + generateParserObject() + ";"),
|
|
"})()"
|
|
].join("\n");
|
|
},
|
|
|
|
commonjs() {
|
|
const parts = [];
|
|
const dependencyVars = Object.keys(options.dependencies);
|
|
|
|
parts.push([
|
|
generateGeneratedByComment(),
|
|
"",
|
|
"\"use strict\";",
|
|
""
|
|
].join("\n"));
|
|
|
|
if (dependencyVars.length > 0) {
|
|
dependencyVars.forEach(variable => {
|
|
parts.push("var " + variable
|
|
+ " = require(\""
|
|
+ stringEscape(options.dependencies[variable])
|
|
+ "\");"
|
|
);
|
|
});
|
|
parts.push("");
|
|
}
|
|
|
|
parts.push([
|
|
toplevelCode,
|
|
"",
|
|
"module.exports = " + generateParserObject() + ";",
|
|
""
|
|
].join("\n"));
|
|
|
|
return parts.join("\n");
|
|
},
|
|
|
|
es() {
|
|
const parts = [];
|
|
const dependencyVars = Object.keys(options.dependencies);
|
|
|
|
parts.push(
|
|
generateGeneratedByComment(),
|
|
""
|
|
);
|
|
|
|
if (dependencyVars.length > 0) {
|
|
dependencyVars.forEach(variable => {
|
|
parts.push("import " + variable
|
|
+ " from \""
|
|
+ stringEscape(options.dependencies[variable])
|
|
+ "\";"
|
|
);
|
|
});
|
|
parts.push("");
|
|
}
|
|
|
|
parts.push(
|
|
toplevelCode,
|
|
"",
|
|
"export " + generateParserExports() + ";",
|
|
""
|
|
);
|
|
|
|
return parts.join("\n");
|
|
},
|
|
|
|
amd() {
|
|
const dependencyVars = Object.keys(options.dependencies);
|
|
const dependencyIds = dependencyVars.map(v => options.dependencies[v]);
|
|
const dependencies = "["
|
|
+ dependencyIds.map(
|
|
id => "\"" + stringEscape(id) + "\""
|
|
).join(", ")
|
|
+ "]";
|
|
const params = dependencyVars.join(", ");
|
|
|
|
return [
|
|
generateGeneratedByComment(),
|
|
"define(" + dependencies + ", function(" + params + ") {",
|
|
" \"use strict\";",
|
|
"",
|
|
indent2(toplevelCode),
|
|
"",
|
|
indent2("return " + generateParserObject() + ";"),
|
|
"});",
|
|
""
|
|
].join("\n");
|
|
},
|
|
|
|
globals() {
|
|
return [
|
|
generateGeneratedByComment(),
|
|
"(function(root) {",
|
|
" \"use strict\";",
|
|
"",
|
|
indent2(toplevelCode),
|
|
"",
|
|
indent2("root." + options.exportVar + " = " + generateParserObject() + ";"),
|
|
"})(this);",
|
|
""
|
|
].join("\n");
|
|
},
|
|
|
|
umd() {
|
|
const parts = [];
|
|
const dependencyVars = Object.keys(options.dependencies);
|
|
const dependencyIds = dependencyVars.map(v => options.dependencies[v]);
|
|
const dependencies = "["
|
|
+ dependencyIds.map(
|
|
id => "\"" + stringEscape(id) + "\""
|
|
).join(", ")
|
|
+ "]";
|
|
const requires = dependencyIds.map(
|
|
id => "require(\"" + stringEscape(id) + "\")"
|
|
).join(", ");
|
|
const params = dependencyVars.join(", ");
|
|
|
|
parts.push([
|
|
generateGeneratedByComment(),
|
|
"(function(root, factory) {",
|
|
" if (typeof define === \"function\" && define.amd) {",
|
|
" define(" + dependencies + ", factory);",
|
|
" } else if (typeof module === \"object\" && module.exports) {",
|
|
" module.exports = factory(" + requires + ");"
|
|
].join("\n"));
|
|
|
|
if (options.exportVar !== null) {
|
|
parts.push([
|
|
" } else {",
|
|
" root." + options.exportVar + " = factory();"
|
|
].join("\n"));
|
|
}
|
|
|
|
parts.push([
|
|
" }",
|
|
"})(this, function(" + params + ") {",
|
|
" \"use strict\";",
|
|
"",
|
|
indent2(toplevelCode),
|
|
"",
|
|
indent2("return " + generateParserObject() + ";"),
|
|
"});",
|
|
""
|
|
].join("\n"));
|
|
|
|
return parts.join("\n");
|
|
}
|
|
};
|
|
|
|
return generators[options.format]();
|
|
}
|
|
|
|
ast.code = generateWrapper(generateToplevel());
|
|
}
|
|
|
|
module.exports = generateJS;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 35412:
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
const visitor = __webpack_require__(68202);
|
|
const asts = __webpack_require__(19861);
|
|
const GrammarError = __webpack_require__(94297);
|
|
|
|
const ALWAYS_MATCH = 1;
|
|
const SOMETIMES_MATCH = 0;
|
|
const NEVER_MATCH = -1;
|
|
|
|
// Inference match result of the each node. Can be:
|
|
// -1: negative result, matching of that node always fails
|
|
// 0: neutral result, may be fail, may be match
|
|
// 1: positive result, always match
|
|
function inferenceMatchResult(ast) {
|
|
function sometimesMatch(node) { return (node.match = SOMETIMES_MATCH); }
|
|
function alwaysMatch(node) {
|
|
inference(node.expression);
|
|
|
|
return (node.match = ALWAYS_MATCH);
|
|
}
|
|
|
|
function inferenceExpression(node) {
|
|
return (node.match = inference(node.expression));
|
|
}
|
|
function inferenceElements(elements, forChoice) {
|
|
const length = elements.length;
|
|
let always = 0;
|
|
let never = 0;
|
|
|
|
for (let i = 0; i < length; ++i) {
|
|
const result = inference(elements[i]);
|
|
|
|
if (result === ALWAYS_MATCH) { ++always; }
|
|
if (result === NEVER_MATCH) { ++never; }
|
|
}
|
|
|
|
if (always === length) {
|
|
return ALWAYS_MATCH;
|
|
}
|
|
if (forChoice) {
|
|
return never === length ? NEVER_MATCH : SOMETIMES_MATCH;
|
|
}
|
|
|
|
return never > 0 ? NEVER_MATCH : SOMETIMES_MATCH;
|
|
}
|
|
|
|
const inference = visitor.build({
|
|
rule(node) {
|
|
let oldResult;
|
|
let count = 0;
|
|
|
|
// If property not yet calculated, do that
|
|
if (typeof node.match === "undefined") {
|
|
node.match = SOMETIMES_MATCH;
|
|
do {
|
|
oldResult = node.match;
|
|
node.match = inference(node.expression);
|
|
// 6 == 3! -- permutations count for all transitions from one match
|
|
// state to another.
|
|
// After 6 iterations the cycle with guarantee begins
|
|
// For example, an input of `start = [] start` will generate the
|
|
// sequence: 0 -> -1 -> -1 (then stop)
|
|
//
|
|
// A more complex grammar theoretically would generate the
|
|
// sequence: 0 -> 1 -> 0 -> -1 -> 0 -> 1 -> ... (then cycle)
|
|
// but there are no examples of such grammars yet (possible, they
|
|
// do not exist at all)
|
|
|
|
// istanbul ignore next This is canary test, shouldn't trigger in real life
|
|
if (++count > 6) {
|
|
throw new GrammarError(
|
|
"Infinity cycle detected when trying to evaluate node match result",
|
|
node.location
|
|
);
|
|
}
|
|
} while (oldResult !== node.match);
|
|
}
|
|
|
|
return node.match;
|
|
},
|
|
named: inferenceExpression,
|
|
choice(node) {
|
|
return (node.match = inferenceElements(node.alternatives, true));
|
|
},
|
|
action: inferenceExpression,
|
|
sequence(node) {
|
|
return (node.match = inferenceElements(node.elements, false));
|
|
},
|
|
labeled: inferenceExpression,
|
|
text: inferenceExpression,
|
|
simple_and: inferenceExpression,
|
|
simple_not(node) {
|
|
return (node.match = -inference(node.expression));
|
|
},
|
|
optional: alwaysMatch,
|
|
zero_or_more: alwaysMatch,
|
|
one_or_more: inferenceExpression,
|
|
group: inferenceExpression,
|
|
semantic_and: sometimesMatch,
|
|
semantic_not: sometimesMatch,
|
|
rule_ref(node) {
|
|
const rule = asts.findRule(ast, node.name);
|
|
|
|
return (node.match = inference(rule));
|
|
},
|
|
literal(node) {
|
|
// Empty literal always match on any input
|
|
const match = node.value.length === 0 ? ALWAYS_MATCH : SOMETIMES_MATCH;
|
|
|
|
return (node.match = match);
|
|
},
|
|
class(node) {
|
|
// Empty character class never match on any input
|
|
const match = node.parts.length === 0 ? NEVER_MATCH : SOMETIMES_MATCH;
|
|
|
|
return (node.match = match);
|
|
},
|
|
// |any| not match on empty input
|
|
any: sometimesMatch
|
|
});
|
|
|
|
inference(ast);
|
|
}
|
|
|
|
inferenceMatchResult.ALWAYS_MATCH = ALWAYS_MATCH;
|
|
inferenceMatchResult.SOMETIMES_MATCH = SOMETIMES_MATCH;
|
|
inferenceMatchResult.NEVER_MATCH = NEVER_MATCH;
|
|
|
|
module.exports = inferenceMatchResult;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 32929:
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
const visitor = __webpack_require__(68202);
|
|
|
|
// Removes proxy rules -- that is, rules that only delegate to other rule.
|
|
function removeProxyRules(ast, options) {
|
|
function isProxyRule(node) {
|
|
return node.type === "rule" && node.expression.type === "rule_ref";
|
|
}
|
|
|
|
function replaceRuleRefs(ast, from, to) {
|
|
const replace = visitor.build({
|
|
rule_ref(node) {
|
|
if (node.name === from) {
|
|
node.name = to;
|
|
}
|
|
}
|
|
});
|
|
|
|
replace(ast);
|
|
}
|
|
|
|
const indices = [];
|
|
|
|
ast.rules.forEach((rule, i) => {
|
|
if (isProxyRule(rule)) {
|
|
replaceRuleRefs(ast, rule.name, rule.expression.name);
|
|
if (options.allowedStartRules.indexOf(rule.name) === -1) {
|
|
indices.push(i);
|
|
}
|
|
}
|
|
});
|
|
|
|
indices.reverse();
|
|
|
|
indices.forEach(i => { ast.rules.splice(i, 1); });
|
|
}
|
|
|
|
module.exports = removeProxyRules;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 96734:
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
const GrammarError = __webpack_require__(94297);
|
|
const visitor = __webpack_require__(68202);
|
|
|
|
// Checks that each label is defined only once within each scope.
|
|
function reportDuplicateLabels(ast) {
|
|
function cloneEnv(env) {
|
|
const clone = {};
|
|
|
|
Object.keys(env).forEach(name => {
|
|
clone[name] = env[name];
|
|
});
|
|
|
|
return clone;
|
|
}
|
|
|
|
function checkExpressionWithClonedEnv(node, env) {
|
|
check(node.expression, cloneEnv(env));
|
|
}
|
|
|
|
const check = visitor.build({
|
|
rule(node) {
|
|
check(node.expression, { });
|
|
},
|
|
|
|
choice(node, env) {
|
|
node.alternatives.forEach(alternative => {
|
|
check(alternative, cloneEnv(env));
|
|
});
|
|
},
|
|
|
|
action: checkExpressionWithClonedEnv,
|
|
|
|
labeled(node, env) {
|
|
const label = node.label;
|
|
if (label && Object.prototype.hasOwnProperty.call(env, label)) {
|
|
throw new GrammarError(
|
|
`Label "${node.label}" is already defined`,
|
|
node.labelLocation,
|
|
[{
|
|
message: "Original label location",
|
|
location: env[label]
|
|
}]
|
|
);
|
|
}
|
|
|
|
check(node.expression, env);
|
|
|
|
env[node.label] = node.labelLocation;
|
|
},
|
|
|
|
text: checkExpressionWithClonedEnv,
|
|
simple_and: checkExpressionWithClonedEnv,
|
|
simple_not: checkExpressionWithClonedEnv,
|
|
optional: checkExpressionWithClonedEnv,
|
|
zero_or_more: checkExpressionWithClonedEnv,
|
|
one_or_more: checkExpressionWithClonedEnv,
|
|
group: checkExpressionWithClonedEnv
|
|
});
|
|
|
|
check(ast);
|
|
}
|
|
|
|
module.exports = reportDuplicateLabels;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 1117:
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
const GrammarError = __webpack_require__(94297);
|
|
const visitor = __webpack_require__(68202);
|
|
|
|
// Checks that each rule is defined only once.
|
|
function reportDuplicateRules(ast) {
|
|
const rules = {};
|
|
|
|
const check = visitor.build({
|
|
rule(node) {
|
|
if (Object.prototype.hasOwnProperty.call(rules, node.name)) {
|
|
throw new GrammarError(
|
|
`Rule "${node.name}" is already defined`,
|
|
node.nameLocation,
|
|
[{
|
|
message: "Original rule location",
|
|
location: rules[node.name]
|
|
}]
|
|
);
|
|
}
|
|
|
|
rules[node.name] = node.nameLocation;
|
|
}
|
|
});
|
|
|
|
check(ast);
|
|
}
|
|
|
|
module.exports = reportDuplicateRules;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 66237:
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
const GrammarError = __webpack_require__(94297);
|
|
const visitor = __webpack_require__(68202);
|
|
|
|
//
|
|
// Compiler pass to ensure the following are enforced:
|
|
//
|
|
// - plucking can not be done with an action block
|
|
//
|
|
function reportIncorrectPlucking(ast) {
|
|
const check = visitor.build({
|
|
action(node) {
|
|
check(node.expression, node);
|
|
},
|
|
|
|
labeled(node, action) {
|
|
if (node.pick) {
|
|
if (action) {
|
|
throw new GrammarError(
|
|
"\"@\" cannot be used with an action block",
|
|
node.labelLocation,
|
|
[{
|
|
message: "Action block location",
|
|
location: action.codeLocation
|
|
}]
|
|
);
|
|
}
|
|
}
|
|
|
|
check(node.expression);
|
|
}
|
|
});
|
|
|
|
check(ast);
|
|
}
|
|
|
|
module.exports = reportIncorrectPlucking;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 10730:
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
const GrammarError = __webpack_require__(94297);
|
|
const asts = __webpack_require__(19861);
|
|
const visitor = __webpack_require__(68202);
|
|
|
|
// Reports left recursion in the grammar, which prevents infinite recursion in
|
|
// the generated parser.
|
|
//
|
|
// Both direct and indirect recursion is detected. The pass also correctly
|
|
// reports cases like this:
|
|
//
|
|
// start = "a"? start
|
|
//
|
|
// In general, if a rule reference can be reached without consuming any input,
|
|
// it can lead to left recursion.
|
|
function reportInfiniteRecursion(ast) {
|
|
// Array with rule names for error message
|
|
const visitedRules = [];
|
|
// Array with rule_refs for diagnostic
|
|
const backtraceRefs = [];
|
|
|
|
const check = visitor.build({
|
|
rule(node) {
|
|
visitedRules.push(node.name);
|
|
check(node.expression);
|
|
visitedRules.pop();
|
|
},
|
|
|
|
sequence(node) {
|
|
node.elements.every(element => {
|
|
check(element);
|
|
|
|
return !asts.alwaysConsumesOnSuccess(ast, element);
|
|
});
|
|
},
|
|
|
|
rule_ref(node) {
|
|
backtraceRefs.push(node);
|
|
|
|
const rule = asts.findRule(ast, node.name);
|
|
|
|
if (visitedRules.indexOf(node.name) !== -1) {
|
|
visitedRules.push(node.name);
|
|
|
|
throw new GrammarError(
|
|
"Possible infinite loop when parsing (left recursion: "
|
|
+ visitedRules.join(" -> ")
|
|
+ ")",
|
|
rule.nameLocation,
|
|
backtraceRefs.map((ref, i, a) => {
|
|
return {
|
|
message: i + 1 !== a.length
|
|
? `Step ${i + 1}: call of the rule "${ref.name}" without input consumption`
|
|
: `Step ${i + 1}: call itself without input consumption - left recursion`,
|
|
location: ref.location
|
|
};
|
|
})
|
|
);
|
|
}
|
|
|
|
check(rule);
|
|
backtraceRefs.pop();
|
|
}
|
|
});
|
|
|
|
check(ast);
|
|
}
|
|
|
|
module.exports = reportInfiniteRecursion;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 79505:
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
const GrammarError = __webpack_require__(94297);
|
|
const asts = __webpack_require__(19861);
|
|
const visitor = __webpack_require__(68202);
|
|
|
|
// Reports expressions that don't consume any input inside |*| or |+| in the
|
|
// grammar, which prevents infinite loops in the generated parser.
|
|
function reportInfiniteRepetition(ast) {
|
|
const check = visitor.build({
|
|
zero_or_more(node) {
|
|
if (!asts.alwaysConsumesOnSuccess(ast, node.expression)) {
|
|
throw new GrammarError(
|
|
"Possible infinite loop when parsing (repetition used with an expression that may not consume any input)",
|
|
node.location
|
|
);
|
|
}
|
|
},
|
|
|
|
one_or_more(node) {
|
|
if (!asts.alwaysConsumesOnSuccess(ast, node.expression)) {
|
|
throw new GrammarError(
|
|
"Possible infinite loop when parsing (repetition used with an expression that may not consume any input)",
|
|
node.location
|
|
);
|
|
}
|
|
}
|
|
});
|
|
|
|
check(ast);
|
|
}
|
|
|
|
module.exports = reportInfiniteRepetition;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 41442:
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
const GrammarError = __webpack_require__(94297);
|
|
const asts = __webpack_require__(19861);
|
|
const visitor = __webpack_require__(68202);
|
|
|
|
// Checks that all referenced rules exist.
|
|
function reportUndefinedRules(ast) {
|
|
const check = visitor.build({
|
|
rule_ref(node) {
|
|
if (!asts.findRule(ast, node.name)) {
|
|
throw new GrammarError(
|
|
`Rule "${node.name}" is not defined`,
|
|
node.location
|
|
);
|
|
}
|
|
}
|
|
});
|
|
|
|
check(ast);
|
|
}
|
|
|
|
module.exports = reportUndefinedRules;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 78013:
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
/** Utility class that helps generating code for C-like languages. */
|
|
class Stack {
|
|
/**
|
|
* Constructs the helper for tracking variable slots of the stack virtual machine
|
|
*
|
|
* @param {string} ruleName The name of rule that will be used in error messages
|
|
* @param {string} varName The prefix for generated names of variables
|
|
* @param {string} type The type of the variables. For JavaScript there are `var` or `let`
|
|
*/
|
|
constructor(ruleName, varName, type) {
|
|
/** Last used variable in the stack. */
|
|
this.sp = -1;
|
|
/** Maximum stack size. */
|
|
this.maxSp = -1;
|
|
this.varName = varName;
|
|
this.ruleName = ruleName;
|
|
this.type = type;
|
|
}
|
|
|
|
/**
|
|
* Returns name of the variable at the index `i`.
|
|
*
|
|
* @param {number} i Index for which name must be generated
|
|
* @return {string} Generated name
|
|
*
|
|
* @throws {RangeError} If `i < 0`, which means a stack underflow (there are more `pop`s than `push`es)
|
|
*/
|
|
name(i) {
|
|
if (i < 0) {
|
|
throw new RangeError(
|
|
`Rule '${this.ruleName}': The variable stack underflow: attempt to use a variable '${this.varName}<x>' at an index ${i}`
|
|
);
|
|
}
|
|
|
|
return this.varName + i;
|
|
}
|
|
|
|
/**
|
|
* Assigns `exprCode` to the new variable in the stack, returns generated code.
|
|
* As the result, the size of a stack increases on 1.
|
|
*
|
|
* @param {string} exprCode Any expression code that must be assigned to the new variable in the stack
|
|
* @return {string} Assignment code
|
|
*/
|
|
push(exprCode) {
|
|
const code = this.name(++this.sp) + " = " + exprCode + ";";
|
|
|
|
if (this.sp > this.maxSp) { this.maxSp = this.sp; }
|
|
|
|
return code;
|
|
}
|
|
|
|
/**
|
|
* Returns name or `n` names of the variable(s) from the top of the stack.
|
|
*
|
|
* @param {number} [n=1] Quantity of variables, which need to be removed from the stack
|
|
* @return {string|string[]} Generated name(s). If `n > 1` than array has length of `n`
|
|
*
|
|
* @throws {RangeError} If the stack underflow (there are more `pop`s than `push`es)
|
|
*/
|
|
pop(n) {
|
|
if (n !== undefined) {
|
|
this.sp -= n;
|
|
|
|
return Array.from({ length: n }, (v, i) => this.name(this.sp + 1 + i));
|
|
}
|
|
|
|
return this.name(this.sp--);
|
|
}
|
|
|
|
/**
|
|
* Returns name of the first free variable. The same as `index(0)`.
|
|
*
|
|
* @return {string} Generated name
|
|
*
|
|
* @throws {RangeError} If the stack is empty (there was no `push`'s yet)
|
|
*/
|
|
top() { return this.name(this.sp); }
|
|
|
|
/**
|
|
* Returns name of the variable at index `i`.
|
|
*
|
|
* @param {number} [i] Index of the variable from top of the stack
|
|
* @return {string} Generated name
|
|
*
|
|
* @throws {RangeError} If `i < 0` or more than the stack size
|
|
*/
|
|
index(i) {
|
|
if (i < 0) {
|
|
throw new RangeError(
|
|
`Rule '${this.ruleName}': The variable stack overflow: attempt to get a variable at a negative index ${i}`
|
|
);
|
|
}
|
|
|
|
return this.name(this.sp - i);
|
|
}
|
|
|
|
/**
|
|
* Returns variable name that contains result (bottom of the stack).
|
|
*
|
|
* @return {string} Generated name
|
|
*
|
|
* @throws {RangeError} If the stack is empty (there was no `push`es yet)
|
|
*/
|
|
result() {
|
|
if (this.maxSp < 0) {
|
|
throw new RangeError(
|
|
`Rule '${this.ruleName}': The variable stack is empty, can't get the result'`
|
|
);
|
|
}
|
|
|
|
return this.name(0);
|
|
}
|
|
|
|
/**
|
|
* Returns defines of all used variables.
|
|
*
|
|
* @return {string} Generated define variable expression with the type `this.type`.
|
|
* If the stack is empty, returns empty string
|
|
*/
|
|
defines() {
|
|
if (this.maxSp < 0) {
|
|
return "";
|
|
}
|
|
|
|
return this.type + " " + Array.from({ length: this.maxSp + 1 }, (v, i) => this.name(i)).join(", ") + ";";
|
|
}
|
|
|
|
/**
|
|
* Checks that code in the `generateIf` and `generateElse` move the stack pointer in the same way.
|
|
*
|
|
* @param {number} pos Opcode number for error messages
|
|
* @param {function()} generateIf First function that works with this stack
|
|
* @param {function()} [generateElse] Second function that works with this stack
|
|
* @return {undefined}
|
|
*
|
|
* @throws {Error} If `generateElse` is defined and the stack pointer moved differently in the
|
|
* `generateIf` and `generateElse`
|
|
*/
|
|
checkedIf(pos, generateIf, generateElse) {
|
|
const baseSp = this.sp;
|
|
|
|
generateIf();
|
|
|
|
if (generateElse) {
|
|
const thenSp = this.sp;
|
|
|
|
this.sp = baseSp;
|
|
generateElse();
|
|
|
|
if (thenSp !== this.sp) {
|
|
throw new Error(
|
|
"Rule '" + this.ruleName + "', position " + pos + ": "
|
|
+ "Branches of a condition can't move the stack pointer differently "
|
|
+ "(before: " + baseSp + ", after then: " + thenSp + ", after else: " + this.sp + ")."
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Checks that code in the `generateBody` do not move stack pointer.
|
|
*
|
|
* @param {number} pos Opcode number for error messages
|
|
* @param {function()} generateBody Function that works with this stack
|
|
* @return {undefined}
|
|
*
|
|
* @throws {Error} If `generateBody` move the stack pointer (if it contains unbalanced `push`es and `pop`s)
|
|
*/
|
|
checkedLoop(pos, generateBody) {
|
|
const baseSp = this.sp;
|
|
|
|
generateBody();
|
|
|
|
if (baseSp !== this.sp) {
|
|
throw new Error(
|
|
"Rule '" + this.ruleName + "', position " + pos + ": "
|
|
+ "Body of a loop can't move the stack pointer "
|
|
+ "(before: " + baseSp + ", after: " + this.sp + ")."
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = Stack;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 68202:
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
// Simple AST node visitor builder.
|
|
const visitor = {
|
|
build(functions) {
|
|
function visit(node, ...args) {
|
|
return functions[node.type](node, ...args);
|
|
}
|
|
|
|
function visitNop() {
|
|
// Do nothing.
|
|
}
|
|
|
|
function visitExpression(node, ...args) {
|
|
return visit(node.expression, ...args);
|
|
}
|
|
|
|
function visitChildren(property) {
|
|
return function(node, ...args) {
|
|
// We do not use .map() here, because if you need the result
|
|
// of applying visitor to children you probable also need to
|
|
// process it in some way, therefore you anyway have to override
|
|
// this method. If you do not needed that, we do not waste time
|
|
// and memory for creating the output array
|
|
node[property].forEach(child => visit(child, ...args));
|
|
};
|
|
}
|
|
|
|
const DEFAULT_FUNCTIONS = {
|
|
grammar(node, ...args) {
|
|
if (node.topLevelInitializer) {
|
|
visit(node.topLevelInitializer, ...args);
|
|
}
|
|
|
|
if (node.initializer) {
|
|
visit(node.initializer, ...args);
|
|
}
|
|
|
|
node.rules.forEach(rule => visit(rule, ...args));
|
|
},
|
|
|
|
top_level_initializer: visitNop,
|
|
initializer: visitNop,
|
|
rule: visitExpression,
|
|
named: visitExpression,
|
|
choice: visitChildren("alternatives"),
|
|
action: visitExpression,
|
|
sequence: visitChildren("elements"),
|
|
labeled: visitExpression,
|
|
text: visitExpression,
|
|
simple_and: visitExpression,
|
|
simple_not: visitExpression,
|
|
optional: visitExpression,
|
|
zero_or_more: visitExpression,
|
|
one_or_more: visitExpression,
|
|
group: visitExpression,
|
|
semantic_and: visitNop,
|
|
semantic_not: visitNop,
|
|
rule_ref: visitNop,
|
|
literal: visitNop,
|
|
class: visitNop,
|
|
any: visitNop
|
|
};
|
|
|
|
Object.keys(DEFAULT_FUNCTIONS).forEach(type => {
|
|
if (!Object.prototype.hasOwnProperty.call(functions, type)) {
|
|
functions[type] = DEFAULT_FUNCTIONS[type];
|
|
}
|
|
});
|
|
|
|
return visit;
|
|
}
|
|
};
|
|
|
|
module.exports = visitor;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 94297:
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
// See: https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
|
|
// This is roughly what typescript generates, it's not called after super(), where it's needed.
|
|
const setProtoOf = Object.setPrototypeOf
|
|
|| ({ __proto__: [] } instanceof Array
|
|
&& function(d, b) {
|
|
// eslint-disable-next-line no-proto
|
|
d.__proto__ = b;
|
|
})
|
|
|| function(d, b) {
|
|
for (const p in b) {
|
|
if (Object.prototype.hasOwnProperty.call(b, p)) {
|
|
d[p] = b[p];
|
|
}
|
|
}
|
|
};
|
|
|
|
// Thrown when the grammar contains an error.
|
|
class GrammarError extends Error {
|
|
constructor(message, location, diagnostics) {
|
|
super(message);
|
|
setProtoOf(this, GrammarError.prototype);
|
|
this.name = "GrammarError";
|
|
this.location = location;
|
|
if (diagnostics === undefined) {
|
|
diagnostics = [];
|
|
}
|
|
this.diagnostics = diagnostics;
|
|
}
|
|
|
|
toString() {
|
|
let str = super.toString();
|
|
if (this.location) {
|
|
str += "\n at ";
|
|
if ((this.location.source !== undefined)
|
|
&& (this.location.source !== null)) {
|
|
str += `${this.location.source}:`;
|
|
}
|
|
str += `${this.location.start.line}:${this.location.start.column}`;
|
|
}
|
|
for (const diag of this.diagnostics) {
|
|
str += "\n from ";
|
|
if ((diag.location.source !== undefined)
|
|
&& (diag.location.source !== null)) {
|
|
str += `${diag.location.source}:`;
|
|
}
|
|
str += `${diag.location.start.line}:${diag.location.start.column}: ${diag.message}`;
|
|
}
|
|
|
|
return str;
|
|
}
|
|
|
|
/**
|
|
* @typedef SourceText {source: any, text: string}
|
|
*/
|
|
/**
|
|
* Format the error with associated sources. The `location.source` should have
|
|
* a `toString()` representation in order the result to look nice. If source
|
|
* is `null` or `undefined`, it is skipped from the output
|
|
*
|
|
* Sample output:
|
|
* ```
|
|
* Error: Label "head" is already defined
|
|
* --> examples/arithmetics.pegjs:15:17
|
|
* |
|
|
* 15 | = head:Factor head:(_ ("*" / "/") _ Factor)* {
|
|
* | ^^^^
|
|
* note: Original label location
|
|
* --> examples/arithmetics.pegjs:15:5
|
|
* |
|
|
* 15 | = head:Factor head:(_ ("*" / "/") _ Factor)* {
|
|
* | ^^^^
|
|
* ```
|
|
*
|
|
* @param {SourceText[]} sources mapping from location source to source text
|
|
*
|
|
* @returns {string} the formatted error
|
|
*/
|
|
format(sources) {
|
|
const srcLines = sources.map(({ source, text }) => ({
|
|
source,
|
|
text: text.split(/\r\n|\n|\r/g)
|
|
}));
|
|
|
|
function entry(location, indent, message = "") {
|
|
let str = "";
|
|
const src = srcLines.find(({ source }) => source === location.source);
|
|
const s = location.start;
|
|
if (src) {
|
|
const e = location.end;
|
|
const line = src.text[s.line - 1];
|
|
const last = s.line === e.line ? e.column : line.length + 1;
|
|
if (message) {
|
|
str += `\nnote: ${message}`;
|
|
}
|
|
str += `
|
|
--> ${location.source}:${s.line}:${s.column}
|
|
${"".padEnd(indent)} |
|
|
${s.line.toString().padStart(indent)} | ${line}
|
|
${"".padEnd(indent)} | ${"".padEnd(s.column - 1)}${"".padEnd(last - s.column, "^")}`;
|
|
} else {
|
|
str += `\n at ${location.source}:${s.line}:${s.column}`;
|
|
if (message) {
|
|
str += `: ${message}`;
|
|
}
|
|
}
|
|
|
|
return str;
|
|
}
|
|
|
|
// Calculate maximum width of all lines
|
|
let maxLine;
|
|
if (this.location) {
|
|
maxLine = this.diagnostics.reduce(
|
|
(t, { location }) => Math.max(t, location.start.line),
|
|
this.location.start.line
|
|
);
|
|
} else {
|
|
maxLine = Math.max.apply(
|
|
null,
|
|
this.diagnostics.map(d => d.location.start.line)
|
|
);
|
|
}
|
|
maxLine = maxLine.toString().length;
|
|
|
|
let str = `Error: ${this.message}`;
|
|
if (this.location) {
|
|
str += entry(this.location, maxLine);
|
|
}
|
|
for (const diag of this.diagnostics) {
|
|
str += entry(diag.location, maxLine, diag.message);
|
|
}
|
|
|
|
return str;
|
|
}
|
|
}
|
|
|
|
module.exports = GrammarError;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 80170:
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
// Generated by Peggy 1.2.0.
|
|
//
|
|
// https://peggyjs.org/
|
|
|
|
|
|
|
|
|
|
const OPS_TO_PREFIXED_TYPES = {
|
|
"$": "text",
|
|
"&": "simple_and",
|
|
"!": "simple_not"
|
|
};
|
|
|
|
const OPS_TO_SUFFIXED_TYPES = {
|
|
"?": "optional",
|
|
"*": "zero_or_more",
|
|
"+": "one_or_more"
|
|
};
|
|
|
|
const OPS_TO_SEMANTIC_PREDICATE_TYPES = {
|
|
"&": "semantic_and",
|
|
"!": "semantic_not"
|
|
};
|
|
|
|
|
|
function peg$subclass(child, parent) {
|
|
function C() { this.constructor = child; }
|
|
C.prototype = parent.prototype;
|
|
child.prototype = new C();
|
|
}
|
|
|
|
function peg$SyntaxError(message, expected, found, location) {
|
|
var self = Error.call(this, message);
|
|
if (Object.setPrototypeOf) {
|
|
Object.setPrototypeOf(self, peg$SyntaxError.prototype);
|
|
}
|
|
self.expected = expected;
|
|
self.found = found;
|
|
self.location = location;
|
|
self.name = "SyntaxError";
|
|
return self;
|
|
}
|
|
|
|
peg$subclass(peg$SyntaxError, Error);
|
|
|
|
function peg$padEnd(str, targetLength, padString) {
|
|
padString = padString || " ";
|
|
if (str.length > targetLength) { return str; }
|
|
targetLength -= str.length;
|
|
padString += padString.repeat(targetLength);
|
|
return str + padString.slice(0, targetLength);
|
|
}
|
|
|
|
peg$SyntaxError.prototype.format = function(sources) {
|
|
var str = "Error: " + this.message;
|
|
if (this.location) {
|
|
var src = null;
|
|
var k;
|
|
for (k = 0; k < sources.length; k++) {
|
|
if (sources[k].source === this.location.source) {
|
|
src = sources[k].text.split(/\r\n|\n|\r/g);
|
|
break;
|
|
}
|
|
}
|
|
var s = this.location.start;
|
|
var loc = this.location.source + ":" + s.line + ":" + s.column;
|
|
if (src) {
|
|
var e = this.location.end;
|
|
var filler = peg$padEnd("", s.line.toString().length);
|
|
var line = src[s.line - 1];
|
|
var last = s.line === e.line ? e.column : line.length + 1;
|
|
str += "\n --> " + loc + "\n"
|
|
+ filler + " |\n"
|
|
+ s.line + " | " + line + "\n"
|
|
+ filler + " | " + peg$padEnd("", s.column - 1)
|
|
+ peg$padEnd("", last - s.column, "^");
|
|
} else {
|
|
str += "\n at " + loc;
|
|
}
|
|
}
|
|
return str;
|
|
};
|
|
|
|
peg$SyntaxError.buildMessage = function(expected, found) {
|
|
var DESCRIBE_EXPECTATION_FNS = {
|
|
literal: function(expectation) {
|
|
return "\"" + literalEscape(expectation.text) + "\"";
|
|
},
|
|
|
|
class: function(expectation) {
|
|
var escapedParts = expectation.parts.map(function(part) {
|
|
return Array.isArray(part)
|
|
? classEscape(part[0]) + "-" + classEscape(part[1])
|
|
: classEscape(part);
|
|
});
|
|
|
|
return "[" + (expectation.inverted ? "^" : "") + escapedParts + "]";
|
|
},
|
|
|
|
any: function() {
|
|
return "any character";
|
|
},
|
|
|
|
end: function() {
|
|
return "end of input";
|
|
},
|
|
|
|
other: function(expectation) {
|
|
return expectation.description;
|
|
}
|
|
};
|
|
|
|
function hex(ch) {
|
|
return ch.charCodeAt(0).toString(16).toUpperCase();
|
|
}
|
|
|
|
function literalEscape(s) {
|
|
return s
|
|
.replace(/\\/g, "\\\\")
|
|
.replace(/"/g, "\\\"")
|
|
.replace(/\0/g, "\\0")
|
|
.replace(/\t/g, "\\t")
|
|
.replace(/\n/g, "\\n")
|
|
.replace(/\r/g, "\\r")
|
|
.replace(/[\x00-\x0F]/g, function(ch) { return "\\x0" + hex(ch); })
|
|
.replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return "\\x" + hex(ch); });
|
|
}
|
|
|
|
function classEscape(s) {
|
|
return s
|
|
.replace(/\\/g, "\\\\")
|
|
.replace(/\]/g, "\\]")
|
|
.replace(/\^/g, "\\^")
|
|
.replace(/-/g, "\\-")
|
|
.replace(/\0/g, "\\0")
|
|
.replace(/\t/g, "\\t")
|
|
.replace(/\n/g, "\\n")
|
|
.replace(/\r/g, "\\r")
|
|
.replace(/[\x00-\x0F]/g, function(ch) { return "\\x0" + hex(ch); })
|
|
.replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return "\\x" + hex(ch); });
|
|
}
|
|
|
|
function describeExpectation(expectation) {
|
|
return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation);
|
|
}
|
|
|
|
function describeExpected(expected) {
|
|
var descriptions = expected.map(describeExpectation);
|
|
var i, j;
|
|
|
|
descriptions.sort();
|
|
|
|
if (descriptions.length > 0) {
|
|
for (i = 1, j = 1; i < descriptions.length; i++) {
|
|
if (descriptions[i - 1] !== descriptions[i]) {
|
|
descriptions[j] = descriptions[i];
|
|
j++;
|
|
}
|
|
}
|
|
descriptions.length = j;
|
|
}
|
|
|
|
switch (descriptions.length) {
|
|
case 1:
|
|
return descriptions[0];
|
|
|
|
case 2:
|
|
return descriptions[0] + " or " + descriptions[1];
|
|
|
|
default:
|
|
return descriptions.slice(0, -1).join(", ")
|
|
+ ", or "
|
|
+ descriptions[descriptions.length - 1];
|
|
}
|
|
}
|
|
|
|
function describeFound(found) {
|
|
return found ? "\"" + literalEscape(found) + "\"" : "end of input";
|
|
}
|
|
|
|
return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found.";
|
|
};
|
|
|
|
function peg$parse(input, options) {
|
|
options = options !== undefined ? options : {};
|
|
|
|
var peg$FAILED = {};
|
|
var peg$source = options.grammarSource;
|
|
|
|
var peg$startRuleFunctions = { Grammar: peg$parseGrammar };
|
|
var peg$startRuleFunction = peg$parseGrammar;
|
|
|
|
var peg$c0 = "{";
|
|
var peg$c1 = "}";
|
|
var peg$c2 = "=";
|
|
var peg$c3 = "/";
|
|
var peg$c4 = "@";
|
|
var peg$c5 = ":";
|
|
var peg$c6 = "$";
|
|
var peg$c7 = "&";
|
|
var peg$c8 = "!";
|
|
var peg$c9 = "?";
|
|
var peg$c10 = "*";
|
|
var peg$c11 = "+";
|
|
var peg$c12 = "(";
|
|
var peg$c13 = ")";
|
|
var peg$c14 = "\t";
|
|
var peg$c15 = "\v";
|
|
var peg$c16 = "\f";
|
|
var peg$c17 = " ";
|
|
var peg$c18 = "\xA0";
|
|
var peg$c19 = "\uFEFF";
|
|
var peg$c20 = "\n";
|
|
var peg$c21 = "\r\n";
|
|
var peg$c22 = "\r";
|
|
var peg$c23 = "\u2028";
|
|
var peg$c24 = "\u2029";
|
|
var peg$c25 = "/*";
|
|
var peg$c26 = "*/";
|
|
var peg$c27 = "//";
|
|
var peg$c28 = "_";
|
|
var peg$c29 = "\\";
|
|
var peg$c30 = "\u200C";
|
|
var peg$c31 = "\u200D";
|
|
var peg$c32 = "i";
|
|
var peg$c33 = "\"";
|
|
var peg$c34 = "'";
|
|
var peg$c35 = "[";
|
|
var peg$c36 = "^";
|
|
var peg$c37 = "]";
|
|
var peg$c38 = "-";
|
|
var peg$c39 = "0";
|
|
var peg$c40 = "b";
|
|
var peg$c41 = "f";
|
|
var peg$c42 = "n";
|
|
var peg$c43 = "r";
|
|
var peg$c44 = "t";
|
|
var peg$c45 = "v";
|
|
var peg$c46 = "x";
|
|
var peg$c47 = "u";
|
|
var peg$c48 = ".";
|
|
var peg$c49 = ";";
|
|
|
|
var peg$r0 = /^[\n\r\u2028\u2029]/;
|
|
var peg$r1 = /^[0-9]/;
|
|
var peg$r2 = /^[0-9a-f]/i;
|
|
var peg$r3 = /^[{}]/;
|
|
var peg$r4 = /^[a-z\xB5\xDF-\xF6\xF8-\xFF\u0101\u0103\u0105\u0107\u0109\u010B\u010D\u010F\u0111\u0113\u0115\u0117\u0119\u011B\u011D\u011F\u0121\u0123\u0125\u0127\u0129\u012B\u012D\u012F\u0131\u0133\u0135\u0137-\u0138\u013A\u013C\u013E\u0140\u0142\u0144\u0146\u0148-\u0149\u014B\u014D\u014F\u0151\u0153\u0155\u0157\u0159\u015B\u015D\u015F\u0161\u0163\u0165\u0167\u0169\u016B\u016D\u016F\u0171\u0173\u0175\u0177\u017A\u017C\u017E-\u0180\u0183\u0185\u0188\u018C-\u018D\u0192\u0195\u0199-\u019B\u019E\u01A1\u01A3\u01A5\u01A8\u01AA-\u01AB\u01AD\u01B0\u01B4\u01B6\u01B9-\u01BA\u01BD-\u01BF\u01C6\u01C9\u01CC\u01CE\u01D0\u01D2\u01D4\u01D6\u01D8\u01DA\u01DC-\u01DD\u01DF\u01E1\u01E3\u01E5\u01E7\u01E9\u01EB\u01ED\u01EF-\u01F0\u01F3\u01F5\u01F9\u01FB\u01FD\u01FF\u0201\u0203\u0205\u0207\u0209\u020B\u020D\u020F\u0211\u0213\u0215\u0217\u0219\u021B\u021D\u021F\u0221\u0223\u0225\u0227\u0229\u022B\u022D\u022F\u0231\u0233-\u0239\u023C\u023F-\u0240\u0242\u0247\u0249\u024B\u024D\u024F-\u0293\u0295-\u02AF\u0371\u0373\u0377\u037B-\u037D\u0390\u03AC-\u03CE\u03D0-\u03D1\u03D5-\u03D7\u03D9\u03DB\u03DD\u03DF\u03E1\u03E3\u03E5\u03E7\u03E9\u03EB\u03ED\u03EF-\u03F3\u03F5\u03F8\u03FB-\u03FC\u0430-\u045F\u0461\u0463\u0465\u0467\u0469\u046B\u046D\u046F\u0471\u0473\u0475\u0477\u0479\u047B\u047D\u047F\u0481\u048B\u048D\u048F\u0491\u0493\u0495\u0497\u0499\u049B\u049D\u049F\u04A1\u04A3\u04A5\u04A7\u04A9\u04AB\u04AD\u04AF\u04B1\u04B3\u04B5\u04B7\u04B9\u04BB\u04BD\u04BF\u04C2\u04C4\u04C6\u04C8\u04CA\u04CC\u04CE-\u04CF\u04D1\u04D3\u04D5\u04D7\u04D9\u04DB\u04DD\u04DF\u04E1\u04E3\u04E5\u04E7\u04E9\u04EB\u04ED\u04EF\u04F1\u04F3\u04F5\u04F7\u04F9\u04FB\u04FD\u04FF\u0501\u0503\u0505\u0507\u0509\u050B\u050D\u050F\u0511\u0513\u0515\u0517\u0519\u051B\u051D\u051F\u0521\u0523\u0525\u0527\u0529\u052B\u052D\u052F\u0561-\u0587\u13F8-\u13FD\u1D00-\u1D2B\u1D6B-\u1D77\u1D79-\u1D9A\u1E01\u1E03\u1E05\u1E07\u1E09\u1E0B\u1E0D\u1E0F\u1E11\u1E13\u1E15\u1E17\u1E19\u1E1B\u1E1D\u1E1F\u1E21\u1E23\u1E25\u1E27\u1E29\u1E2B\u1E2D\u1E2F\u1E31\u1E33\u1E35\u1E37\u1E39\u1E3B\u1E3D\u1E3F\u1E41\u1E43\u1E45\u1E47\u1E49\u1E4B\u1E4D\u1E4F\u1E51\u1E53\u1E55\u1E57\u1E59\u1E5B\u1E5D\u1E5F\u1E61\u1E63\u1E65\u1E67\u1E69\u1E6B\u1E6D\u1E6F\u1E71\u1E73\u1E75\u1E77\u1E79\u1E7B\u1E7D\u1E7F\u1E81\u1E83\u1E85\u1E87\u1E89\u1E8B\u1E8D\u1E8F\u1E91\u1E93\u1E95-\u1E9D\u1E9F\u1EA1\u1EA3\u1EA5\u1EA7\u1EA9\u1EAB\u1EAD\u1EAF\u1EB1\u1EB3\u1EB5\u1EB7\u1EB9\u1EBB\u1EBD\u1EBF\u1EC1\u1EC3\u1EC5\u1EC7\u1EC9\u1ECB\u1ECD\u1ECF\u1ED1\u1ED3\u1ED5\u1ED7\u1ED9\u1EDB\u1EDD\u1EDF\u1EE1\u1EE3\u1EE5\u1EE7\u1EE9\u1EEB\u1EED\u1EEF\u1EF1\u1EF3\u1EF5\u1EF7\u1EF9\u1EFB\u1EFD\u1EFF-\u1F07\u1F10-\u1F15\u1F20-\u1F27\u1F30-\u1F37\u1F40-\u1F45\u1F50-\u1F57\u1F60-\u1F67\u1F70-\u1F7D\u1F80-\u1F87\u1F90-\u1F97\u1FA0-\u1FA7\u1FB0-\u1FB4\u1FB6-\u1FB7\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FC7\u1FD0-\u1FD3\u1FD6-\u1FD7\u1FE0-\u1FE7\u1FF2-\u1FF4\u1FF6-\u1FF7\u210A\u210E-\u210F\u2113\u212F\u2134\u2139\u213C-\u213D\u2146-\u2149\u214E\u2184\u2C30-\u2C5E\u2C61\u2C65-\u2C66\u2C68\u2C6A\u2C6C\u2C71\u2C73-\u2C74\u2C76-\u2C7B\u2C81\u2C83\u2C85\u2C87\u2C89\u2C8B\u2C8D\u2C8F\u2C91\u2C93\u2C95\u2C97\u2C99\u2C9B\u2C9D\u2C9F\u2CA1\u2CA3\u2CA5\u2CA7\u2CA9\u2CAB\u2CAD\u2CAF\u2CB1\u2CB3\u2CB5\u2CB7\u2CB9\u2CBB\u2CBD\u2CBF\u2CC1\u2CC3\u2CC5\u2CC7\u2CC9\u2CCB\u2CCD\u2CCF\u2CD1\u2CD3\u2CD5\u2CD7\u2CD9\u2CDB\u2CDD\u2CDF\u2CE1\u2CE3-\u2CE4\u2CEC\u2CEE\u2CF3\u2D00-\u2D25\u2D27\u2D2D\uA641\uA643\uA645\uA647\uA649\uA64B\uA64D\uA64F\uA651\uA653\uA655\uA657\uA659\uA65B\uA65D\uA65F\uA661\uA663\uA665\uA667\uA669\uA66B\uA66D\uA681\uA683\uA685\uA687\uA689\uA68B\uA68D\uA68F\uA691\uA693\uA695\uA697\uA699\uA69B\uA723\uA725\uA727\uA729\uA72B\uA72D\uA72F-\uA731\uA733\uA735\uA737\uA739\uA73B\uA73D\uA73F\uA741\uA743\uA745\uA747\uA749\uA74B\uA74D\uA74F\uA751\uA753\uA755\uA757\uA759\uA75B\uA75D\uA75F\uA761\uA763\uA765\uA767\uA769\uA76B\uA76D\uA76F\uA771-\uA778\uA77A\uA77C\uA77F\uA781\uA783\uA785\uA787\uA78C\uA78E\uA791\uA793-\uA795\uA797\uA799\uA79B\uA79D\uA79F\uA7A1\uA7A3\uA7A5\uA7A7\uA7A9\uA7B5\uA7B7\uA7FA\uAB30-\uAB5A\uAB60-\uAB65\uAB70-\uABBF\uFB00-\uFB06\uFB13-\uFB17\uFF41-\uFF5A]/;
|
|
var peg$r5 = /^[\u02B0-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0374\u037A\u0559\u0640\u06E5-\u06E6\u07F4-\u07F5\u07FA\u081A\u0824\u0828\u0971\u0E46\u0EC6\u10FC\u17D7\u1843\u1AA7\u1C78-\u1C7D\u1D2C-\u1D6A\u1D78\u1D9B-\u1DBF\u2071\u207F\u2090-\u209C\u2C7C-\u2C7D\u2D6F\u2E2F\u3005\u3031-\u3035\u303B\u309D-\u309E\u30FC-\u30FE\uA015\uA4F8-\uA4FD\uA60C\uA67F\uA69C-\uA69D\uA717-\uA71F\uA770\uA788\uA7F8-\uA7F9\uA9CF\uA9E6\uAA70\uAADD\uAAF3-\uAAF4\uAB5C-\uAB5F\uFF70\uFF9E-\uFF9F]/;
|
|
var peg$r6 = /^[\xAA\xBA\u01BB\u01C0-\u01C3\u0294\u05D0-\u05EA\u05F0-\u05F2\u0620-\u063F\u0641-\u064A\u066E-\u066F\u0671-\u06D3\u06D5\u06EE-\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u0800-\u0815\u0840-\u0858\u08A0-\u08B4\u0904-\u0939\u093D\u0950\u0958-\u0961\u0972-\u0980\u0985-\u098C\u098F-\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC-\u09DD\u09DF-\u09E1\u09F0-\u09F1\u0A05-\u0A0A\u0A0F-\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32-\u0A33\u0A35-\u0A36\u0A38-\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2-\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0-\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F-\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32-\u0B33\u0B35-\u0B39\u0B3D\u0B5C-\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99-\u0B9A\u0B9C\u0B9E-\u0B9F\u0BA3-\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60-\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0-\u0CE1\u0CF1-\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32-\u0E33\u0E40-\u0E45\u0E81-\u0E82\u0E84\u0E87-\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA-\u0EAB\u0EAD-\u0EB0\u0EB2-\u0EB3\u0EBD\u0EC0-\u0EC4\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065-\u1066\u106E-\u1070\u1075-\u1081\u108E\u10D0-\u10FA\u10FD-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17DC\u1820-\u1842\u1844-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE-\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C77\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5-\u1CF6\u2135-\u2138\u2D30-\u2D67\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3006\u303C\u3041-\u3096\u309F\u30A1-\u30FA\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA014\uA016-\uA48C\uA4D0-\uA4F7\uA500-\uA60B\uA610-\uA61F\uA62A-\uA62B\uA66E\uA6A0-\uA6E5\uA78F\uA7F7\uA7FB-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9E0-\uA9E4\uA9E7-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA6F\uAA71-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5-\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADC\uAAE0-\uAAEA\uAAF2\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40-\uFB41\uFB43-\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF66-\uFF6F\uFF71-\uFF9D\uFFA0-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]/;
|
|
var peg$r7 = /^[\u01C5\u01C8\u01CB\u01F2\u1F88-\u1F8F\u1F98-\u1F9F\u1FA8-\u1FAF\u1FBC\u1FCC\u1FFC]/;
|
|
var peg$r8 = /^[A-Z\xC0-\xD6\xD8-\xDE\u0100\u0102\u0104\u0106\u0108\u010A\u010C\u010E\u0110\u0112\u0114\u0116\u0118\u011A\u011C\u011E\u0120\u0122\u0124\u0126\u0128\u012A\u012C\u012E\u0130\u0132\u0134\u0136\u0139\u013B\u013D\u013F\u0141\u0143\u0145\u0147\u014A\u014C\u014E\u0150\u0152\u0154\u0156\u0158\u015A\u015C\u015E\u0160\u0162\u0164\u0166\u0168\u016A\u016C\u016E\u0170\u0172\u0174\u0176\u0178-\u0179\u017B\u017D\u0181-\u0182\u0184\u0186-\u0187\u0189-\u018B\u018E-\u0191\u0193-\u0194\u0196-\u0198\u019C-\u019D\u019F-\u01A0\u01A2\u01A4\u01A6-\u01A7\u01A9\u01AC\u01AE-\u01AF\u01B1-\u01B3\u01B5\u01B7-\u01B8\u01BC\u01C4\u01C7\u01CA\u01CD\u01CF\u01D1\u01D3\u01D5\u01D7\u01D9\u01DB\u01DE\u01E0\u01E2\u01E4\u01E6\u01E8\u01EA\u01EC\u01EE\u01F1\u01F4\u01F6-\u01F8\u01FA\u01FC\u01FE\u0200\u0202\u0204\u0206\u0208\u020A\u020C\u020E\u0210\u0212\u0214\u0216\u0218\u021A\u021C\u021E\u0220\u0222\u0224\u0226\u0228\u022A\u022C\u022E\u0230\u0232\u023A-\u023B\u023D-\u023E\u0241\u0243-\u0246\u0248\u024A\u024C\u024E\u0370\u0372\u0376\u037F\u0386\u0388-\u038A\u038C\u038E-\u038F\u0391-\u03A1\u03A3-\u03AB\u03CF\u03D2-\u03D4\u03D8\u03DA\u03DC\u03DE\u03E0\u03E2\u03E4\u03E6\u03E8\u03EA\u03EC\u03EE\u03F4\u03F7\u03F9-\u03FA\u03FD-\u042F\u0460\u0462\u0464\u0466\u0468\u046A\u046C\u046E\u0470\u0472\u0474\u0476\u0478\u047A\u047C\u047E\u0480\u048A\u048C\u048E\u0490\u0492\u0494\u0496\u0498\u049A\u049C\u049E\u04A0\u04A2\u04A4\u04A6\u04A8\u04AA\u04AC\u04AE\u04B0\u04B2\u04B4\u04B6\u04B8\u04BA\u04BC\u04BE\u04C0-\u04C1\u04C3\u04C5\u04C7\u04C9\u04CB\u04CD\u04D0\u04D2\u04D4\u04D6\u04D8\u04DA\u04DC\u04DE\u04E0\u04E2\u04E4\u04E6\u04E8\u04EA\u04EC\u04EE\u04F0\u04F2\u04F4\u04F6\u04F8\u04FA\u04FC\u04FE\u0500\u0502\u0504\u0506\u0508\u050A\u050C\u050E\u0510\u0512\u0514\u0516\u0518\u051A\u051C\u051E\u0520\u0522\u0524\u0526\u0528\u052A\u052C\u052E\u0531-\u0556\u10A0-\u10C5\u10C7\u10CD\u13A0-\u13F5\u1E00\u1E02\u1E04\u1E06\u1E08\u1E0A\u1E0C\u1E0E\u1E10\u1E12\u1E14\u1E16\u1E18\u1E1A\u1E1C\u1E1E\u1E20\u1E22\u1E24\u1E26\u1E28\u1E2A\u1E2C\u1E2E\u1E30\u1E32\u1E34\u1E36\u1E38\u1E3A\u1E3C\u1E3E\u1E40\u1E42\u1E44\u1E46\u1E48\u1E4A\u1E4C\u1E4E\u1E50\u1E52\u1E54\u1E56\u1E58\u1E5A\u1E5C\u1E5E\u1E60\u1E62\u1E64\u1E66\u1E68\u1E6A\u1E6C\u1E6E\u1E70\u1E72\u1E74\u1E76\u1E78\u1E7A\u1E7C\u1E7E\u1E80\u1E82\u1E84\u1E86\u1E88\u1E8A\u1E8C\u1E8E\u1E90\u1E92\u1E94\u1E9E\u1EA0\u1EA2\u1EA4\u1EA6\u1EA8\u1EAA\u1EAC\u1EAE\u1EB0\u1EB2\u1EB4\u1EB6\u1EB8\u1EBA\u1EBC\u1EBE\u1EC0\u1EC2\u1EC4\u1EC6\u1EC8\u1ECA\u1ECC\u1ECE\u1ED0\u1ED2\u1ED4\u1ED6\u1ED8\u1EDA\u1EDC\u1EDE\u1EE0\u1EE2\u1EE4\u1EE6\u1EE8\u1EEA\u1EEC\u1EEE\u1EF0\u1EF2\u1EF4\u1EF6\u1EF8\u1EFA\u1EFC\u1EFE\u1F08-\u1F0F\u1F18-\u1F1D\u1F28-\u1F2F\u1F38-\u1F3F\u1F48-\u1F4D\u1F59\u1F5B\u1F5D\u1F5F\u1F68-\u1F6F\u1FB8-\u1FBB\u1FC8-\u1FCB\u1FD8-\u1FDB\u1FE8-\u1FEC\u1FF8-\u1FFB\u2102\u2107\u210B-\u210D\u2110-\u2112\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u2130-\u2133\u213E-\u213F\u2145\u2183\u2C00-\u2C2E\u2C60\u2C62-\u2C64\u2C67\u2C69\u2C6B\u2C6D-\u2C70\u2C72\u2C75\u2C7E-\u2C80\u2C82\u2C84\u2C86\u2C88\u2C8A\u2C8C\u2C8E\u2C90\u2C92\u2C94\u2C96\u2C98\u2C9A\u2C9C\u2C9E\u2CA0\u2CA2\u2CA4\u2CA6\u2CA8\u2CAA\u2CAC\u2CAE\u2CB0\u2CB2\u2CB4\u2CB6\u2CB8\u2CBA\u2CBC\u2CBE\u2CC0\u2CC2\u2CC4\u2CC6\u2CC8\u2CCA\u2CCC\u2CCE\u2CD0\u2CD2\u2CD4\u2CD6\u2CD8\u2CDA\u2CDC\u2CDE\u2CE0\u2CE2\u2CEB\u2CED\u2CF2\uA640\uA642\uA644\uA646\uA648\uA64A\uA64C\uA64E\uA650\uA652\uA654\uA656\uA658\uA65A\uA65C\uA65E\uA660\uA662\uA664\uA666\uA668\uA66A\uA66C\uA680\uA682\uA684\uA686\uA688\uA68A\uA68C\uA68E\uA690\uA692\uA694\uA696\uA698\uA69A\uA722\uA724\uA726\uA728\uA72A\uA72C\uA72E\uA732\uA734\uA736\uA738\uA73A\uA73C\uA73E\uA740\uA742\uA744\uA746\uA748\uA74A\uA74C\uA74E\uA750\uA752\uA754\uA756\uA758\uA75A\uA75C\uA75E\uA760\uA762\uA764\uA766\uA768\uA76A\uA76C\uA76E\uA779\uA77B\uA77D-\uA77E\uA780\uA782\uA784\uA786\uA78B\uA78D\uA790\uA792\uA796\uA798\uA79A\uA79C\uA79E\uA7A0\uA7A2\uA7A4\uA7A6\uA7A8\uA7AA-\uA7AD\uA7B0-\uA7B4\uA7B6\uFF21-\uFF3A]/;
|
|
var peg$r9 = /^[\u0903\u093B\u093E-\u0940\u0949-\u094C\u094E-\u094F\u0982-\u0983\u09BE-\u09C0\u09C7-\u09C8\u09CB-\u09CC\u09D7\u0A03\u0A3E-\u0A40\u0A83\u0ABE-\u0AC0\u0AC9\u0ACB-\u0ACC\u0B02-\u0B03\u0B3E\u0B40\u0B47-\u0B48\u0B4B-\u0B4C\u0B57\u0BBE-\u0BBF\u0BC1-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCC\u0BD7\u0C01-\u0C03\u0C41-\u0C44\u0C82-\u0C83\u0CBE\u0CC0-\u0CC4\u0CC7-\u0CC8\u0CCA-\u0CCB\u0CD5-\u0CD6\u0D02-\u0D03\u0D3E-\u0D40\u0D46-\u0D48\u0D4A-\u0D4C\u0D57\u0D82-\u0D83\u0DCF-\u0DD1\u0DD8-\u0DDF\u0DF2-\u0DF3\u0F3E-\u0F3F\u0F7F\u102B-\u102C\u1031\u1038\u103B-\u103C\u1056-\u1057\u1062-\u1064\u1067-\u106D\u1083-\u1084\u1087-\u108C\u108F\u109A-\u109C\u17B6\u17BE-\u17C5\u17C7-\u17C8\u1923-\u1926\u1929-\u192B\u1930-\u1931\u1933-\u1938\u1A19-\u1A1A\u1A55\u1A57\u1A61\u1A63-\u1A64\u1A6D-\u1A72\u1B04\u1B35\u1B3B\u1B3D-\u1B41\u1B43-\u1B44\u1B82\u1BA1\u1BA6-\u1BA7\u1BAA\u1BE7\u1BEA-\u1BEC\u1BEE\u1BF2-\u1BF3\u1C24-\u1C2B\u1C34-\u1C35\u1CE1\u1CF2-\u1CF3\u302E-\u302F\uA823-\uA824\uA827\uA880-\uA881\uA8B4-\uA8C3\uA952-\uA953\uA983\uA9B4-\uA9B5\uA9BA-\uA9BB\uA9BD-\uA9C0\uAA2F-\uAA30\uAA33-\uAA34\uAA4D\uAA7B\uAA7D\uAAEB\uAAEE-\uAAEF\uAAF5\uABE3-\uABE4\uABE6-\uABE7\uABE9-\uABEA\uABEC]/;
|
|
var peg$r10 = /^[\u0300-\u036F\u0483-\u0487\u0591-\u05BD\u05BF\u05C1-\u05C2\u05C4-\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7-\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08E3-\u0902\u093A\u093C\u0941-\u0948\u094D\u0951-\u0957\u0962-\u0963\u0981\u09BC\u09C1-\u09C4\u09CD\u09E2-\u09E3\u0A01-\u0A02\u0A3C\u0A41-\u0A42\u0A47-\u0A48\u0A4B-\u0A4D\u0A51\u0A70-\u0A71\u0A75\u0A81-\u0A82\u0ABC\u0AC1-\u0AC5\u0AC7-\u0AC8\u0ACD\u0AE2-\u0AE3\u0B01\u0B3C\u0B3F\u0B41-\u0B44\u0B4D\u0B56\u0B62-\u0B63\u0B82\u0BC0\u0BCD\u0C00\u0C3E-\u0C40\u0C46-\u0C48\u0C4A-\u0C4D\u0C55-\u0C56\u0C62-\u0C63\u0C81\u0CBC\u0CBF\u0CC6\u0CCC-\u0CCD\u0CE2-\u0CE3\u0D01\u0D41-\u0D44\u0D4D\u0D62-\u0D63\u0DCA\u0DD2-\u0DD4\u0DD6\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9\u0EBB-\u0EBC\u0EC8-\u0ECD\u0F18-\u0F19\u0F35\u0F37\u0F39\u0F71-\u0F7E\u0F80-\u0F84\u0F86-\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102D-\u1030\u1032-\u1037\u1039-\u103A\u103D-\u103E\u1058-\u1059\u105E-\u1060\u1071-\u1074\u1082\u1085-\u1086\u108D\u109D\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752-\u1753\u1772-\u1773\u17B4-\u17B5\u17B7-\u17BD\u17C6\u17C9-\u17D3\u17DD\u180B-\u180D\u18A9\u1920-\u1922\u1927-\u1928\u1932\u1939-\u193B\u1A17-\u1A18\u1A1B\u1A56\u1A58-\u1A5E\u1A60\u1A62\u1A65-\u1A6C\u1A73-\u1A7C\u1A7F\u1AB0-\u1ABD\u1B00-\u1B03\u1B34\u1B36-\u1B3A\u1B3C\u1B42\u1B6B-\u1B73\u1B80-\u1B81\u1BA2-\u1BA5\u1BA8-\u1BA9\u1BAB-\u1BAD\u1BE6\u1BE8-\u1BE9\u1BED\u1BEF-\u1BF1\u1C2C-\u1C33\u1C36-\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE0\u1CE2-\u1CE8\u1CED\u1CF4\u1CF8-\u1CF9\u1DC0-\u1DF5\u1DFC-\u1DFF\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302D\u3099-\u309A\uA66F\uA674-\uA67D\uA69E-\uA69F\uA6F0-\uA6F1\uA802\uA806\uA80B\uA825-\uA826\uA8C4\uA8E0-\uA8F1\uA926-\uA92D\uA947-\uA951\uA980-\uA982\uA9B3\uA9B6-\uA9B9\uA9BC\uA9E5\uAA29-\uAA2E\uAA31-\uAA32\uAA35-\uAA36\uAA43\uAA4C\uAA7C\uAAB0\uAAB2-\uAAB4\uAAB7-\uAAB8\uAABE-\uAABF\uAAC1\uAAEC-\uAAED\uAAF6\uABE5\uABE8\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE2F]/;
|
|
var peg$r11 = /^[0-9\u0660-\u0669\u06F0-\u06F9\u07C0-\u07C9\u0966-\u096F\u09E6-\u09EF\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0BE6-\u0BEF\u0C66-\u0C6F\u0CE6-\u0CEF\u0D66-\u0D6F\u0DE6-\u0DEF\u0E50-\u0E59\u0ED0-\u0ED9\u0F20-\u0F29\u1040-\u1049\u1090-\u1099\u17E0-\u17E9\u1810-\u1819\u1946-\u194F\u19D0-\u19D9\u1A80-\u1A89\u1A90-\u1A99\u1B50-\u1B59\u1BB0-\u1BB9\u1C40-\u1C49\u1C50-\u1C59\uA620-\uA629\uA8D0-\uA8D9\uA900-\uA909\uA9D0-\uA9D9\uA9F0-\uA9F9\uAA50-\uAA59\uABF0-\uABF9\uFF10-\uFF19]/;
|
|
var peg$r12 = /^[\u16EE-\u16F0\u2160-\u2182\u2185-\u2188\u3007\u3021-\u3029\u3038-\u303A\uA6E6-\uA6EF]/;
|
|
var peg$r13 = /^[_\u203F-\u2040\u2054\uFE33-\uFE34\uFE4D-\uFE4F\uFF3F]/;
|
|
var peg$r14 = /^[ \xA0\u1680\u2000-\u200A\u202F\u205F\u3000]/;
|
|
|
|
var peg$e0 = peg$literalExpectation("{", false);
|
|
var peg$e1 = peg$literalExpectation("}", false);
|
|
var peg$e2 = peg$literalExpectation("=", false);
|
|
var peg$e3 = peg$literalExpectation("/", false);
|
|
var peg$e4 = peg$literalExpectation("@", false);
|
|
var peg$e5 = peg$literalExpectation(":", false);
|
|
var peg$e6 = peg$literalExpectation("$", false);
|
|
var peg$e7 = peg$literalExpectation("&", false);
|
|
var peg$e8 = peg$literalExpectation("!", false);
|
|
var peg$e9 = peg$literalExpectation("?", false);
|
|
var peg$e10 = peg$literalExpectation("*", false);
|
|
var peg$e11 = peg$literalExpectation("+", false);
|
|
var peg$e12 = peg$literalExpectation("(", false);
|
|
var peg$e13 = peg$literalExpectation(")", false);
|
|
var peg$e14 = peg$anyExpectation();
|
|
var peg$e15 = peg$otherExpectation("whitespace");
|
|
var peg$e16 = peg$literalExpectation("\t", false);
|
|
var peg$e17 = peg$literalExpectation("\v", false);
|
|
var peg$e18 = peg$literalExpectation("\f", false);
|
|
var peg$e19 = peg$literalExpectation(" ", false);
|
|
var peg$e20 = peg$literalExpectation("\xA0", false);
|
|
var peg$e21 = peg$literalExpectation("\uFEFF", false);
|
|
var peg$e22 = peg$classExpectation(["\n", "\r", "\u2028", "\u2029"], false, false);
|
|
var peg$e23 = peg$otherExpectation("end of line");
|
|
var peg$e24 = peg$literalExpectation("\n", false);
|
|
var peg$e25 = peg$literalExpectation("\r\n", false);
|
|
var peg$e26 = peg$literalExpectation("\r", false);
|
|
var peg$e27 = peg$literalExpectation("\u2028", false);
|
|
var peg$e28 = peg$literalExpectation("\u2029", false);
|
|
var peg$e29 = peg$otherExpectation("comment");
|
|
var peg$e30 = peg$literalExpectation("/*", false);
|
|
var peg$e31 = peg$literalExpectation("*/", false);
|
|
var peg$e32 = peg$literalExpectation("//", false);
|
|
var peg$e33 = peg$otherExpectation("identifier");
|
|
var peg$e34 = peg$literalExpectation("_", false);
|
|
var peg$e35 = peg$literalExpectation("\\", false);
|
|
var peg$e36 = peg$literalExpectation("\u200C", false);
|
|
var peg$e37 = peg$literalExpectation("\u200D", false);
|
|
var peg$e38 = peg$otherExpectation("literal");
|
|
var peg$e39 = peg$literalExpectation("i", false);
|
|
var peg$e40 = peg$otherExpectation("string");
|
|
var peg$e41 = peg$literalExpectation("\"", false);
|
|
var peg$e42 = peg$literalExpectation("'", false);
|
|
var peg$e43 = peg$otherExpectation("character class");
|
|
var peg$e44 = peg$literalExpectation("[", false);
|
|
var peg$e45 = peg$literalExpectation("^", false);
|
|
var peg$e46 = peg$literalExpectation("]", false);
|
|
var peg$e47 = peg$literalExpectation("-", false);
|
|
var peg$e48 = peg$literalExpectation("0", false);
|
|
var peg$e49 = peg$literalExpectation("b", false);
|
|
var peg$e50 = peg$literalExpectation("f", false);
|
|
var peg$e51 = peg$literalExpectation("n", false);
|
|
var peg$e52 = peg$literalExpectation("r", false);
|
|
var peg$e53 = peg$literalExpectation("t", false);
|
|
var peg$e54 = peg$literalExpectation("v", false);
|
|
var peg$e55 = peg$literalExpectation("x", false);
|
|
var peg$e56 = peg$literalExpectation("u", false);
|
|
var peg$e57 = peg$classExpectation([["0", "9"]], false, false);
|
|
var peg$e58 = peg$classExpectation([["0", "9"], ["a", "f"]], false, true);
|
|
var peg$e59 = peg$literalExpectation(".", false);
|
|
var peg$e60 = peg$otherExpectation("code block");
|
|
var peg$e61 = peg$classExpectation(["{", "}"], false, false);
|
|
var peg$e62 = peg$classExpectation([["a", "z"], "\xB5", ["\xDF", "\xF6"], ["\xF8", "\xFF"], "\u0101", "\u0103", "\u0105", "\u0107", "\u0109", "\u010B", "\u010D", "\u010F", "\u0111", "\u0113", "\u0115", "\u0117", "\u0119", "\u011B", "\u011D", "\u011F", "\u0121", "\u0123", "\u0125", "\u0127", "\u0129", "\u012B", "\u012D", "\u012F", "\u0131", "\u0133", "\u0135", ["\u0137", "\u0138"], "\u013A", "\u013C", "\u013E", "\u0140", "\u0142", "\u0144", "\u0146", ["\u0148", "\u0149"], "\u014B", "\u014D", "\u014F", "\u0151", "\u0153", "\u0155", "\u0157", "\u0159", "\u015B", "\u015D", "\u015F", "\u0161", "\u0163", "\u0165", "\u0167", "\u0169", "\u016B", "\u016D", "\u016F", "\u0171", "\u0173", "\u0175", "\u0177", "\u017A", "\u017C", ["\u017E", "\u0180"], "\u0183", "\u0185", "\u0188", ["\u018C", "\u018D"], "\u0192", "\u0195", ["\u0199", "\u019B"], "\u019E", "\u01A1", "\u01A3", "\u01A5", "\u01A8", ["\u01AA", "\u01AB"], "\u01AD", "\u01B0", "\u01B4", "\u01B6", ["\u01B9", "\u01BA"], ["\u01BD", "\u01BF"], "\u01C6", "\u01C9", "\u01CC", "\u01CE", "\u01D0", "\u01D2", "\u01D4", "\u01D6", "\u01D8", "\u01DA", ["\u01DC", "\u01DD"], "\u01DF", "\u01E1", "\u01E3", "\u01E5", "\u01E7", "\u01E9", "\u01EB", "\u01ED", ["\u01EF", "\u01F0"], "\u01F3", "\u01F5", "\u01F9", "\u01FB", "\u01FD", "\u01FF", "\u0201", "\u0203", "\u0205", "\u0207", "\u0209", "\u020B", "\u020D", "\u020F", "\u0211", "\u0213", "\u0215", "\u0217", "\u0219", "\u021B", "\u021D", "\u021F", "\u0221", "\u0223", "\u0225", "\u0227", "\u0229", "\u022B", "\u022D", "\u022F", "\u0231", ["\u0233", "\u0239"], "\u023C", ["\u023F", "\u0240"], "\u0242", "\u0247", "\u0249", "\u024B", "\u024D", ["\u024F", "\u0293"], ["\u0295", "\u02AF"], "\u0371", "\u0373", "\u0377", ["\u037B", "\u037D"], "\u0390", ["\u03AC", "\u03CE"], ["\u03D0", "\u03D1"], ["\u03D5", "\u03D7"], "\u03D9", "\u03DB", "\u03DD", "\u03DF", "\u03E1", "\u03E3", "\u03E5", "\u03E7", "\u03E9", "\u03EB", "\u03ED", ["\u03EF", "\u03F3"], "\u03F5", "\u03F8", ["\u03FB", "\u03FC"], ["\u0430", "\u045F"], "\u0461", "\u0463", "\u0465", "\u0467", "\u0469", "\u046B", "\u046D", "\u046F", "\u0471", "\u0473", "\u0475", "\u0477", "\u0479", "\u047B", "\u047D", "\u047F", "\u0481", "\u048B", "\u048D", "\u048F", "\u0491", "\u0493", "\u0495", "\u0497", "\u0499", "\u049B", "\u049D", "\u049F", "\u04A1", "\u04A3", "\u04A5", "\u04A7", "\u04A9", "\u04AB", "\u04AD", "\u04AF", "\u04B1", "\u04B3", "\u04B5", "\u04B7", "\u04B9", "\u04BB", "\u04BD", "\u04BF", "\u04C2", "\u04C4", "\u04C6", "\u04C8", "\u04CA", "\u04CC", ["\u04CE", "\u04CF"], "\u04D1", "\u04D3", "\u04D5", "\u04D7", "\u04D9", "\u04DB", "\u04DD", "\u04DF", "\u04E1", "\u04E3", "\u04E5", "\u04E7", "\u04E9", "\u04EB", "\u04ED", "\u04EF", "\u04F1", "\u04F3", "\u04F5", "\u04F7", "\u04F9", "\u04FB", "\u04FD", "\u04FF", "\u0501", "\u0503", "\u0505", "\u0507", "\u0509", "\u050B", "\u050D", "\u050F", "\u0511", "\u0513", "\u0515", "\u0517", "\u0519", "\u051B", "\u051D", "\u051F", "\u0521", "\u0523", "\u0525", "\u0527", "\u0529", "\u052B", "\u052D", "\u052F", ["\u0561", "\u0587"], ["\u13F8", "\u13FD"], ["\u1D00", "\u1D2B"], ["\u1D6B", "\u1D77"], ["\u1D79", "\u1D9A"], "\u1E01", "\u1E03", "\u1E05", "\u1E07", "\u1E09", "\u1E0B", "\u1E0D", "\u1E0F", "\u1E11", "\u1E13", "\u1E15", "\u1E17", "\u1E19", "\u1E1B", "\u1E1D", "\u1E1F", "\u1E21", "\u1E23", "\u1E25", "\u1E27", "\u1E29", "\u1E2B", "\u1E2D", "\u1E2F", "\u1E31", "\u1E33", "\u1E35", "\u1E37", "\u1E39", "\u1E3B", "\u1E3D", "\u1E3F", "\u1E41", "\u1E43", "\u1E45", "\u1E47", "\u1E49", "\u1E4B", "\u1E4D", "\u1E4F", "\u1E51", "\u1E53", "\u1E55", "\u1E57", "\u1E59", "\u1E5B", "\u1E5D", "\u1E5F", "\u1E61", "\u1E63", "\u1E65", "\u1E67", "\u1E69", "\u1E6B", "\u1E6D", "\u1E6F", "\u1E71", "\u1E73", "\u1E75", "\u1E77", "\u1E79", "\u1E7B", "\u1E7D", "\u1E7F", "\u1E81", "\u1E83", "\u1E85", "\u1E87", "\u1E89", "\u1E8B", "\u1E8D", "\u1E8F", "\u1E91", "\u1E93", ["\u1E95", "\u1E9D"], "\u1E9F", "\u1EA1", "\u1EA3", "\u1EA5", "\u1EA7", "\u1EA9", "\u1EAB", "\u1EAD", "\u1EAF", "\u1EB1", "\u1EB3", "\u1EB5", "\u1EB7", "\u1EB9", "\u1EBB", "\u1EBD", "\u1EBF", "\u1EC1", "\u1EC3", "\u1EC5", "\u1EC7", "\u1EC9", "\u1ECB", "\u1ECD", "\u1ECF", "\u1ED1", "\u1ED3", "\u1ED5", "\u1ED7", "\u1ED9", "\u1EDB", "\u1EDD", "\u1EDF", "\u1EE1", "\u1EE3", "\u1EE5", "\u1EE7", "\u1EE9", "\u1EEB", "\u1EED", "\u1EEF", "\u1EF1", "\u1EF3", "\u1EF5", "\u1EF7", "\u1EF9", "\u1EFB", "\u1EFD", ["\u1EFF", "\u1F07"], ["\u1F10", "\u1F15"], ["\u1F20", "\u1F27"], ["\u1F30", "\u1F37"], ["\u1F40", "\u1F45"], ["\u1F50", "\u1F57"], ["\u1F60", "\u1F67"], ["\u1F70", "\u1F7D"], ["\u1F80", "\u1F87"], ["\u1F90", "\u1F97"], ["\u1FA0", "\u1FA7"], ["\u1FB0", "\u1FB4"], ["\u1FB6", "\u1FB7"], "\u1FBE", ["\u1FC2", "\u1FC4"], ["\u1FC6", "\u1FC7"], ["\u1FD0", "\u1FD3"], ["\u1FD6", "\u1FD7"], ["\u1FE0", "\u1FE7"], ["\u1FF2", "\u1FF4"], ["\u1FF6", "\u1FF7"], "\u210A", ["\u210E", "\u210F"], "\u2113", "\u212F", "\u2134", "\u2139", ["\u213C", "\u213D"], ["\u2146", "\u2149"], "\u214E", "\u2184", ["\u2C30", "\u2C5E"], "\u2C61", ["\u2C65", "\u2C66"], "\u2C68", "\u2C6A", "\u2C6C", "\u2C71", ["\u2C73", "\u2C74"], ["\u2C76", "\u2C7B"], "\u2C81", "\u2C83", "\u2C85", "\u2C87", "\u2C89", "\u2C8B", "\u2C8D", "\u2C8F", "\u2C91", "\u2C93", "\u2C95", "\u2C97", "\u2C99", "\u2C9B", "\u2C9D", "\u2C9F", "\u2CA1", "\u2CA3", "\u2CA5", "\u2CA7", "\u2CA9", "\u2CAB", "\u2CAD", "\u2CAF", "\u2CB1", "\u2CB3", "\u2CB5", "\u2CB7", "\u2CB9", "\u2CBB", "\u2CBD", "\u2CBF", "\u2CC1", "\u2CC3", "\u2CC5", "\u2CC7", "\u2CC9", "\u2CCB", "\u2CCD", "\u2CCF", "\u2CD1", "\u2CD3", "\u2CD5", "\u2CD7", "\u2CD9", "\u2CDB", "\u2CDD", "\u2CDF", "\u2CE1", ["\u2CE3", "\u2CE4"], "\u2CEC", "\u2CEE", "\u2CF3", ["\u2D00", "\u2D25"], "\u2D27", "\u2D2D", "\uA641", "\uA643", "\uA645", "\uA647", "\uA649", "\uA64B", "\uA64D", "\uA64F", "\uA651", "\uA653", "\uA655", "\uA657", "\uA659", "\uA65B", "\uA65D", "\uA65F", "\uA661", "\uA663", "\uA665", "\uA667", "\uA669", "\uA66B", "\uA66D", "\uA681", "\uA683", "\uA685", "\uA687", "\uA689", "\uA68B", "\uA68D", "\uA68F", "\uA691", "\uA693", "\uA695", "\uA697", "\uA699", "\uA69B", "\uA723", "\uA725", "\uA727", "\uA729", "\uA72B", "\uA72D", ["\uA72F", "\uA731"], "\uA733", "\uA735", "\uA737", "\uA739", "\uA73B", "\uA73D", "\uA73F", "\uA741", "\uA743", "\uA745", "\uA747", "\uA749", "\uA74B", "\uA74D", "\uA74F", "\uA751", "\uA753", "\uA755", "\uA757", "\uA759", "\uA75B", "\uA75D", "\uA75F", "\uA761", "\uA763", "\uA765", "\uA767", "\uA769", "\uA76B", "\uA76D", "\uA76F", ["\uA771", "\uA778"], "\uA77A", "\uA77C", "\uA77F", "\uA781", "\uA783", "\uA785", "\uA787", "\uA78C", "\uA78E", "\uA791", ["\uA793", "\uA795"], "\uA797", "\uA799", "\uA79B", "\uA79D", "\uA79F", "\uA7A1", "\uA7A3", "\uA7A5", "\uA7A7", "\uA7A9", "\uA7B5", "\uA7B7", "\uA7FA", ["\uAB30", "\uAB5A"], ["\uAB60", "\uAB65"], ["\uAB70", "\uABBF"], ["\uFB00", "\uFB06"], ["\uFB13", "\uFB17"], ["\uFF41", "\uFF5A"]], false, false);
|
|
var peg$e63 = peg$classExpectation([["\u02B0", "\u02C1"], ["\u02C6", "\u02D1"], ["\u02E0", "\u02E4"], "\u02EC", "\u02EE", "\u0374", "\u037A", "\u0559", "\u0640", ["\u06E5", "\u06E6"], ["\u07F4", "\u07F5"], "\u07FA", "\u081A", "\u0824", "\u0828", "\u0971", "\u0E46", "\u0EC6", "\u10FC", "\u17D7", "\u1843", "\u1AA7", ["\u1C78", "\u1C7D"], ["\u1D2C", "\u1D6A"], "\u1D78", ["\u1D9B", "\u1DBF"], "\u2071", "\u207F", ["\u2090", "\u209C"], ["\u2C7C", "\u2C7D"], "\u2D6F", "\u2E2F", "\u3005", ["\u3031", "\u3035"], "\u303B", ["\u309D", "\u309E"], ["\u30FC", "\u30FE"], "\uA015", ["\uA4F8", "\uA4FD"], "\uA60C", "\uA67F", ["\uA69C", "\uA69D"], ["\uA717", "\uA71F"], "\uA770", "\uA788", ["\uA7F8", "\uA7F9"], "\uA9CF", "\uA9E6", "\uAA70", "\uAADD", ["\uAAF3", "\uAAF4"], ["\uAB5C", "\uAB5F"], "\uFF70", ["\uFF9E", "\uFF9F"]], false, false);
|
|
var peg$e64 = peg$classExpectation(["\xAA", "\xBA", "\u01BB", ["\u01C0", "\u01C3"], "\u0294", ["\u05D0", "\u05EA"], ["\u05F0", "\u05F2"], ["\u0620", "\u063F"], ["\u0641", "\u064A"], ["\u066E", "\u066F"], ["\u0671", "\u06D3"], "\u06D5", ["\u06EE", "\u06EF"], ["\u06FA", "\u06FC"], "\u06FF", "\u0710", ["\u0712", "\u072F"], ["\u074D", "\u07A5"], "\u07B1", ["\u07CA", "\u07EA"], ["\u0800", "\u0815"], ["\u0840", "\u0858"], ["\u08A0", "\u08B4"], ["\u0904", "\u0939"], "\u093D", "\u0950", ["\u0958", "\u0961"], ["\u0972", "\u0980"], ["\u0985", "\u098C"], ["\u098F", "\u0990"], ["\u0993", "\u09A8"], ["\u09AA", "\u09B0"], "\u09B2", ["\u09B6", "\u09B9"], "\u09BD", "\u09CE", ["\u09DC", "\u09DD"], ["\u09DF", "\u09E1"], ["\u09F0", "\u09F1"], ["\u0A05", "\u0A0A"], ["\u0A0F", "\u0A10"], ["\u0A13", "\u0A28"], ["\u0A2A", "\u0A30"], ["\u0A32", "\u0A33"], ["\u0A35", "\u0A36"], ["\u0A38", "\u0A39"], ["\u0A59", "\u0A5C"], "\u0A5E", ["\u0A72", "\u0A74"], ["\u0A85", "\u0A8D"], ["\u0A8F", "\u0A91"], ["\u0A93", "\u0AA8"], ["\u0AAA", "\u0AB0"], ["\u0AB2", "\u0AB3"], ["\u0AB5", "\u0AB9"], "\u0ABD", "\u0AD0", ["\u0AE0", "\u0AE1"], "\u0AF9", ["\u0B05", "\u0B0C"], ["\u0B0F", "\u0B10"], ["\u0B13", "\u0B28"], ["\u0B2A", "\u0B30"], ["\u0B32", "\u0B33"], ["\u0B35", "\u0B39"], "\u0B3D", ["\u0B5C", "\u0B5D"], ["\u0B5F", "\u0B61"], "\u0B71", "\u0B83", ["\u0B85", "\u0B8A"], ["\u0B8E", "\u0B90"], ["\u0B92", "\u0B95"], ["\u0B99", "\u0B9A"], "\u0B9C", ["\u0B9E", "\u0B9F"], ["\u0BA3", "\u0BA4"], ["\u0BA8", "\u0BAA"], ["\u0BAE", "\u0BB9"], "\u0BD0", ["\u0C05", "\u0C0C"], ["\u0C0E", "\u0C10"], ["\u0C12", "\u0C28"], ["\u0C2A", "\u0C39"], "\u0C3D", ["\u0C58", "\u0C5A"], ["\u0C60", "\u0C61"], ["\u0C85", "\u0C8C"], ["\u0C8E", "\u0C90"], ["\u0C92", "\u0CA8"], ["\u0CAA", "\u0CB3"], ["\u0CB5", "\u0CB9"], "\u0CBD", "\u0CDE", ["\u0CE0", "\u0CE1"], ["\u0CF1", "\u0CF2"], ["\u0D05", "\u0D0C"], ["\u0D0E", "\u0D10"], ["\u0D12", "\u0D3A"], "\u0D3D", "\u0D4E", ["\u0D5F", "\u0D61"], ["\u0D7A", "\u0D7F"], ["\u0D85", "\u0D96"], ["\u0D9A", "\u0DB1"], ["\u0DB3", "\u0DBB"], "\u0DBD", ["\u0DC0", "\u0DC6"], ["\u0E01", "\u0E30"], ["\u0E32", "\u0E33"], ["\u0E40", "\u0E45"], ["\u0E81", "\u0E82"], "\u0E84", ["\u0E87", "\u0E88"], "\u0E8A", "\u0E8D", ["\u0E94", "\u0E97"], ["\u0E99", "\u0E9F"], ["\u0EA1", "\u0EA3"], "\u0EA5", "\u0EA7", ["\u0EAA", "\u0EAB"], ["\u0EAD", "\u0EB0"], ["\u0EB2", "\u0EB3"], "\u0EBD", ["\u0EC0", "\u0EC4"], ["\u0EDC", "\u0EDF"], "\u0F00", ["\u0F40", "\u0F47"], ["\u0F49", "\u0F6C"], ["\u0F88", "\u0F8C"], ["\u1000", "\u102A"], "\u103F", ["\u1050", "\u1055"], ["\u105A", "\u105D"], "\u1061", ["\u1065", "\u1066"], ["\u106E", "\u1070"], ["\u1075", "\u1081"], "\u108E", ["\u10D0", "\u10FA"], ["\u10FD", "\u1248"], ["\u124A", "\u124D"], ["\u1250", "\u1256"], "\u1258", ["\u125A", "\u125D"], ["\u1260", "\u1288"], ["\u128A", "\u128D"], ["\u1290", "\u12B0"], ["\u12B2", "\u12B5"], ["\u12B8", "\u12BE"], "\u12C0", ["\u12C2", "\u12C5"], ["\u12C8", "\u12D6"], ["\u12D8", "\u1310"], ["\u1312", "\u1315"], ["\u1318", "\u135A"], ["\u1380", "\u138F"], ["\u1401", "\u166C"], ["\u166F", "\u167F"], ["\u1681", "\u169A"], ["\u16A0", "\u16EA"], ["\u16F1", "\u16F8"], ["\u1700", "\u170C"], ["\u170E", "\u1711"], ["\u1720", "\u1731"], ["\u1740", "\u1751"], ["\u1760", "\u176C"], ["\u176E", "\u1770"], ["\u1780", "\u17B3"], "\u17DC", ["\u1820", "\u1842"], ["\u1844", "\u1877"], ["\u1880", "\u18A8"], "\u18AA", ["\u18B0", "\u18F5"], ["\u1900", "\u191E"], ["\u1950", "\u196D"], ["\u1970", "\u1974"], ["\u1980", "\u19AB"], ["\u19B0", "\u19C9"], ["\u1A00", "\u1A16"], ["\u1A20", "\u1A54"], ["\u1B05", "\u1B33"], ["\u1B45", "\u1B4B"], ["\u1B83", "\u1BA0"], ["\u1BAE", "\u1BAF"], ["\u1BBA", "\u1BE5"], ["\u1C00", "\u1C23"], ["\u1C4D", "\u1C4F"], ["\u1C5A", "\u1C77"], ["\u1CE9", "\u1CEC"], ["\u1CEE", "\u1CF1"], ["\u1CF5", "\u1CF6"], ["\u2135", "\u2138"], ["\u2D30", "\u2D67"], ["\u2D80", "\u2D96"], ["\u2DA0", "\u2DA6"], ["\u2DA8", "\u2DAE"], ["\u2DB0", "\u2DB6"], ["\u2DB8", "\u2DBE"], ["\u2DC0", "\u2DC6"], ["\u2DC8", "\u2DCE"], ["\u2DD0", "\u2DD6"], ["\u2DD8", "\u2DDE"], "\u3006", "\u303C", ["\u3041", "\u3096"], "\u309F", ["\u30A1", "\u30FA"], "\u30FF", ["\u3105", "\u312D"], ["\u3131", "\u318E"], ["\u31A0", "\u31BA"], ["\u31F0", "\u31FF"], ["\u3400", "\u4DB5"], ["\u4E00", "\u9FD5"], ["\uA000", "\uA014"], ["\uA016", "\uA48C"], ["\uA4D0", "\uA4F7"], ["\uA500", "\uA60B"], ["\uA610", "\uA61F"], ["\uA62A", "\uA62B"], "\uA66E", ["\uA6A0", "\uA6E5"], "\uA78F", "\uA7F7", ["\uA7FB", "\uA801"], ["\uA803", "\uA805"], ["\uA807", "\uA80A"], ["\uA80C", "\uA822"], ["\uA840", "\uA873"], ["\uA882", "\uA8B3"], ["\uA8F2", "\uA8F7"], "\uA8FB", "\uA8FD", ["\uA90A", "\uA925"], ["\uA930", "\uA946"], ["\uA960", "\uA97C"], ["\uA984", "\uA9B2"], ["\uA9E0", "\uA9E4"], ["\uA9E7", "\uA9EF"], ["\uA9FA", "\uA9FE"], ["\uAA00", "\uAA28"], ["\uAA40", "\uAA42"], ["\uAA44", "\uAA4B"], ["\uAA60", "\uAA6F"], ["\uAA71", "\uAA76"], "\uAA7A", ["\uAA7E", "\uAAAF"], "\uAAB1", ["\uAAB5", "\uAAB6"], ["\uAAB9", "\uAABD"], "\uAAC0", "\uAAC2", ["\uAADB", "\uAADC"], ["\uAAE0", "\uAAEA"], "\uAAF2", ["\uAB01", "\uAB06"], ["\uAB09", "\uAB0E"], ["\uAB11", "\uAB16"], ["\uAB20", "\uAB26"], ["\uAB28", "\uAB2E"], ["\uABC0", "\uABE2"], ["\uAC00", "\uD7A3"], ["\uD7B0", "\uD7C6"], ["\uD7CB", "\uD7FB"], ["\uF900", "\uFA6D"], ["\uFA70", "\uFAD9"], "\uFB1D", ["\uFB1F", "\uFB28"], ["\uFB2A", "\uFB36"], ["\uFB38", "\uFB3C"], "\uFB3E", ["\uFB40", "\uFB41"], ["\uFB43", "\uFB44"], ["\uFB46", "\uFBB1"], ["\uFBD3", "\uFD3D"], ["\uFD50", "\uFD8F"], ["\uFD92", "\uFDC7"], ["\uFDF0", "\uFDFB"], ["\uFE70", "\uFE74"], ["\uFE76", "\uFEFC"], ["\uFF66", "\uFF6F"], ["\uFF71", "\uFF9D"], ["\uFFA0", "\uFFBE"], ["\uFFC2", "\uFFC7"], ["\uFFCA", "\uFFCF"], ["\uFFD2", "\uFFD7"], ["\uFFDA", "\uFFDC"]], false, false);
|
|
var peg$e65 = peg$classExpectation(["\u01C5", "\u01C8", "\u01CB", "\u01F2", ["\u1F88", "\u1F8F"], ["\u1F98", "\u1F9F"], ["\u1FA8", "\u1FAF"], "\u1FBC", "\u1FCC", "\u1FFC"], false, false);
|
|
var peg$e66 = peg$classExpectation([["A", "Z"], ["\xC0", "\xD6"], ["\xD8", "\xDE"], "\u0100", "\u0102", "\u0104", "\u0106", "\u0108", "\u010A", "\u010C", "\u010E", "\u0110", "\u0112", "\u0114", "\u0116", "\u0118", "\u011A", "\u011C", "\u011E", "\u0120", "\u0122", "\u0124", "\u0126", "\u0128", "\u012A", "\u012C", "\u012E", "\u0130", "\u0132", "\u0134", "\u0136", "\u0139", "\u013B", "\u013D", "\u013F", "\u0141", "\u0143", "\u0145", "\u0147", "\u014A", "\u014C", "\u014E", "\u0150", "\u0152", "\u0154", "\u0156", "\u0158", "\u015A", "\u015C", "\u015E", "\u0160", "\u0162", "\u0164", "\u0166", "\u0168", "\u016A", "\u016C", "\u016E", "\u0170", "\u0172", "\u0174", "\u0176", ["\u0178", "\u0179"], "\u017B", "\u017D", ["\u0181", "\u0182"], "\u0184", ["\u0186", "\u0187"], ["\u0189", "\u018B"], ["\u018E", "\u0191"], ["\u0193", "\u0194"], ["\u0196", "\u0198"], ["\u019C", "\u019D"], ["\u019F", "\u01A0"], "\u01A2", "\u01A4", ["\u01A6", "\u01A7"], "\u01A9", "\u01AC", ["\u01AE", "\u01AF"], ["\u01B1", "\u01B3"], "\u01B5", ["\u01B7", "\u01B8"], "\u01BC", "\u01C4", "\u01C7", "\u01CA", "\u01CD", "\u01CF", "\u01D1", "\u01D3", "\u01D5", "\u01D7", "\u01D9", "\u01DB", "\u01DE", "\u01E0", "\u01E2", "\u01E4", "\u01E6", "\u01E8", "\u01EA", "\u01EC", "\u01EE", "\u01F1", "\u01F4", ["\u01F6", "\u01F8"], "\u01FA", "\u01FC", "\u01FE", "\u0200", "\u0202", "\u0204", "\u0206", "\u0208", "\u020A", "\u020C", "\u020E", "\u0210", "\u0212", "\u0214", "\u0216", "\u0218", "\u021A", "\u021C", "\u021E", "\u0220", "\u0222", "\u0224", "\u0226", "\u0228", "\u022A", "\u022C", "\u022E", "\u0230", "\u0232", ["\u023A", "\u023B"], ["\u023D", "\u023E"], "\u0241", ["\u0243", "\u0246"], "\u0248", "\u024A", "\u024C", "\u024E", "\u0370", "\u0372", "\u0376", "\u037F", "\u0386", ["\u0388", "\u038A"], "\u038C", ["\u038E", "\u038F"], ["\u0391", "\u03A1"], ["\u03A3", "\u03AB"], "\u03CF", ["\u03D2", "\u03D4"], "\u03D8", "\u03DA", "\u03DC", "\u03DE", "\u03E0", "\u03E2", "\u03E4", "\u03E6", "\u03E8", "\u03EA", "\u03EC", "\u03EE", "\u03F4", "\u03F7", ["\u03F9", "\u03FA"], ["\u03FD", "\u042F"], "\u0460", "\u0462", "\u0464", "\u0466", "\u0468", "\u046A", "\u046C", "\u046E", "\u0470", "\u0472", "\u0474", "\u0476", "\u0478", "\u047A", "\u047C", "\u047E", "\u0480", "\u048A", "\u048C", "\u048E", "\u0490", "\u0492", "\u0494", "\u0496", "\u0498", "\u049A", "\u049C", "\u049E", "\u04A0", "\u04A2", "\u04A4", "\u04A6", "\u04A8", "\u04AA", "\u04AC", "\u04AE", "\u04B0", "\u04B2", "\u04B4", "\u04B6", "\u04B8", "\u04BA", "\u04BC", "\u04BE", ["\u04C0", "\u04C1"], "\u04C3", "\u04C5", "\u04C7", "\u04C9", "\u04CB", "\u04CD", "\u04D0", "\u04D2", "\u04D4", "\u04D6", "\u04D8", "\u04DA", "\u04DC", "\u04DE", "\u04E0", "\u04E2", "\u04E4", "\u04E6", "\u04E8", "\u04EA", "\u04EC", "\u04EE", "\u04F0", "\u04F2", "\u04F4", "\u04F6", "\u04F8", "\u04FA", "\u04FC", "\u04FE", "\u0500", "\u0502", "\u0504", "\u0506", "\u0508", "\u050A", "\u050C", "\u050E", "\u0510", "\u0512", "\u0514", "\u0516", "\u0518", "\u051A", "\u051C", "\u051E", "\u0520", "\u0522", "\u0524", "\u0526", "\u0528", "\u052A", "\u052C", "\u052E", ["\u0531", "\u0556"], ["\u10A0", "\u10C5"], "\u10C7", "\u10CD", ["\u13A0", "\u13F5"], "\u1E00", "\u1E02", "\u1E04", "\u1E06", "\u1E08", "\u1E0A", "\u1E0C", "\u1E0E", "\u1E10", "\u1E12", "\u1E14", "\u1E16", "\u1E18", "\u1E1A", "\u1E1C", "\u1E1E", "\u1E20", "\u1E22", "\u1E24", "\u1E26", "\u1E28", "\u1E2A", "\u1E2C", "\u1E2E", "\u1E30", "\u1E32", "\u1E34", "\u1E36", "\u1E38", "\u1E3A", "\u1E3C", "\u1E3E", "\u1E40", "\u1E42", "\u1E44", "\u1E46", "\u1E48", "\u1E4A", "\u1E4C", "\u1E4E", "\u1E50", "\u1E52", "\u1E54", "\u1E56", "\u1E58", "\u1E5A", "\u1E5C", "\u1E5E", "\u1E60", "\u1E62", "\u1E64", "\u1E66", "\u1E68", "\u1E6A", "\u1E6C", "\u1E6E", "\u1E70", "\u1E72", "\u1E74", "\u1E76", "\u1E78", "\u1E7A", "\u1E7C", "\u1E7E", "\u1E80", "\u1E82", "\u1E84", "\u1E86", "\u1E88", "\u1E8A", "\u1E8C", "\u1E8E", "\u1E90", "\u1E92", "\u1E94", "\u1E9E", "\u1EA0", "\u1EA2", "\u1EA4", "\u1EA6", "\u1EA8", "\u1EAA", "\u1EAC", "\u1EAE", "\u1EB0", "\u1EB2", "\u1EB4", "\u1EB6", "\u1EB8", "\u1EBA", "\u1EBC", "\u1EBE", "\u1EC0", "\u1EC2", "\u1EC4", "\u1EC6", "\u1EC8", "\u1ECA", "\u1ECC", "\u1ECE", "\u1ED0", "\u1ED2", "\u1ED4", "\u1ED6", "\u1ED8", "\u1EDA", "\u1EDC", "\u1EDE", "\u1EE0", "\u1EE2", "\u1EE4", "\u1EE6", "\u1EE8", "\u1EEA", "\u1EEC", "\u1EEE", "\u1EF0", "\u1EF2", "\u1EF4", "\u1EF6", "\u1EF8", "\u1EFA", "\u1EFC", "\u1EFE", ["\u1F08", "\u1F0F"], ["\u1F18", "\u1F1D"], ["\u1F28", "\u1F2F"], ["\u1F38", "\u1F3F"], ["\u1F48", "\u1F4D"], "\u1F59", "\u1F5B", "\u1F5D", "\u1F5F", ["\u1F68", "\u1F6F"], ["\u1FB8", "\u1FBB"], ["\u1FC8", "\u1FCB"], ["\u1FD8", "\u1FDB"], ["\u1FE8", "\u1FEC"], ["\u1FF8", "\u1FFB"], "\u2102", "\u2107", ["\u210B", "\u210D"], ["\u2110", "\u2112"], "\u2115", ["\u2119", "\u211D"], "\u2124", "\u2126", "\u2128", ["\u212A", "\u212D"], ["\u2130", "\u2133"], ["\u213E", "\u213F"], "\u2145", "\u2183", ["\u2C00", "\u2C2E"], "\u2C60", ["\u2C62", "\u2C64"], "\u2C67", "\u2C69", "\u2C6B", ["\u2C6D", "\u2C70"], "\u2C72", "\u2C75", ["\u2C7E", "\u2C80"], "\u2C82", "\u2C84", "\u2C86", "\u2C88", "\u2C8A", "\u2C8C", "\u2C8E", "\u2C90", "\u2C92", "\u2C94", "\u2C96", "\u2C98", "\u2C9A", "\u2C9C", "\u2C9E", "\u2CA0", "\u2CA2", "\u2CA4", "\u2CA6", "\u2CA8", "\u2CAA", "\u2CAC", "\u2CAE", "\u2CB0", "\u2CB2", "\u2CB4", "\u2CB6", "\u2CB8", "\u2CBA", "\u2CBC", "\u2CBE", "\u2CC0", "\u2CC2", "\u2CC4", "\u2CC6", "\u2CC8", "\u2CCA", "\u2CCC", "\u2CCE", "\u2CD0", "\u2CD2", "\u2CD4", "\u2CD6", "\u2CD8", "\u2CDA", "\u2CDC", "\u2CDE", "\u2CE0", "\u2CE2", "\u2CEB", "\u2CED", "\u2CF2", "\uA640", "\uA642", "\uA644", "\uA646", "\uA648", "\uA64A", "\uA64C", "\uA64E", "\uA650", "\uA652", "\uA654", "\uA656", "\uA658", "\uA65A", "\uA65C", "\uA65E", "\uA660", "\uA662", "\uA664", "\uA666", "\uA668", "\uA66A", "\uA66C", "\uA680", "\uA682", "\uA684", "\uA686", "\uA688", "\uA68A", "\uA68C", "\uA68E", "\uA690", "\uA692", "\uA694", "\uA696", "\uA698", "\uA69A", "\uA722", "\uA724", "\uA726", "\uA728", "\uA72A", "\uA72C", "\uA72E", "\uA732", "\uA734", "\uA736", "\uA738", "\uA73A", "\uA73C", "\uA73E", "\uA740", "\uA742", "\uA744", "\uA746", "\uA748", "\uA74A", "\uA74C", "\uA74E", "\uA750", "\uA752", "\uA754", "\uA756", "\uA758", "\uA75A", "\uA75C", "\uA75E", "\uA760", "\uA762", "\uA764", "\uA766", "\uA768", "\uA76A", "\uA76C", "\uA76E", "\uA779", "\uA77B", ["\uA77D", "\uA77E"], "\uA780", "\uA782", "\uA784", "\uA786", "\uA78B", "\uA78D", "\uA790", "\uA792", "\uA796", "\uA798", "\uA79A", "\uA79C", "\uA79E", "\uA7A0", "\uA7A2", "\uA7A4", "\uA7A6", "\uA7A8", ["\uA7AA", "\uA7AD"], ["\uA7B0", "\uA7B4"], "\uA7B6", ["\uFF21", "\uFF3A"]], false, false);
|
|
var peg$e67 = peg$classExpectation(["\u0903", "\u093B", ["\u093E", "\u0940"], ["\u0949", "\u094C"], ["\u094E", "\u094F"], ["\u0982", "\u0983"], ["\u09BE", "\u09C0"], ["\u09C7", "\u09C8"], ["\u09CB", "\u09CC"], "\u09D7", "\u0A03", ["\u0A3E", "\u0A40"], "\u0A83", ["\u0ABE", "\u0AC0"], "\u0AC9", ["\u0ACB", "\u0ACC"], ["\u0B02", "\u0B03"], "\u0B3E", "\u0B40", ["\u0B47", "\u0B48"], ["\u0B4B", "\u0B4C"], "\u0B57", ["\u0BBE", "\u0BBF"], ["\u0BC1", "\u0BC2"], ["\u0BC6", "\u0BC8"], ["\u0BCA", "\u0BCC"], "\u0BD7", ["\u0C01", "\u0C03"], ["\u0C41", "\u0C44"], ["\u0C82", "\u0C83"], "\u0CBE", ["\u0CC0", "\u0CC4"], ["\u0CC7", "\u0CC8"], ["\u0CCA", "\u0CCB"], ["\u0CD5", "\u0CD6"], ["\u0D02", "\u0D03"], ["\u0D3E", "\u0D40"], ["\u0D46", "\u0D48"], ["\u0D4A", "\u0D4C"], "\u0D57", ["\u0D82", "\u0D83"], ["\u0DCF", "\u0DD1"], ["\u0DD8", "\u0DDF"], ["\u0DF2", "\u0DF3"], ["\u0F3E", "\u0F3F"], "\u0F7F", ["\u102B", "\u102C"], "\u1031", "\u1038", ["\u103B", "\u103C"], ["\u1056", "\u1057"], ["\u1062", "\u1064"], ["\u1067", "\u106D"], ["\u1083", "\u1084"], ["\u1087", "\u108C"], "\u108F", ["\u109A", "\u109C"], "\u17B6", ["\u17BE", "\u17C5"], ["\u17C7", "\u17C8"], ["\u1923", "\u1926"], ["\u1929", "\u192B"], ["\u1930", "\u1931"], ["\u1933", "\u1938"], ["\u1A19", "\u1A1A"], "\u1A55", "\u1A57", "\u1A61", ["\u1A63", "\u1A64"], ["\u1A6D", "\u1A72"], "\u1B04", "\u1B35", "\u1B3B", ["\u1B3D", "\u1B41"], ["\u1B43", "\u1B44"], "\u1B82", "\u1BA1", ["\u1BA6", "\u1BA7"], "\u1BAA", "\u1BE7", ["\u1BEA", "\u1BEC"], "\u1BEE", ["\u1BF2", "\u1BF3"], ["\u1C24", "\u1C2B"], ["\u1C34", "\u1C35"], "\u1CE1", ["\u1CF2", "\u1CF3"], ["\u302E", "\u302F"], ["\uA823", "\uA824"], "\uA827", ["\uA880", "\uA881"], ["\uA8B4", "\uA8C3"], ["\uA952", "\uA953"], "\uA983", ["\uA9B4", "\uA9B5"], ["\uA9BA", "\uA9BB"], ["\uA9BD", "\uA9C0"], ["\uAA2F", "\uAA30"], ["\uAA33", "\uAA34"], "\uAA4D", "\uAA7B", "\uAA7D", "\uAAEB", ["\uAAEE", "\uAAEF"], "\uAAF5", ["\uABE3", "\uABE4"], ["\uABE6", "\uABE7"], ["\uABE9", "\uABEA"], "\uABEC"], false, false);
|
|
var peg$e68 = peg$classExpectation([["\u0300", "\u036F"], ["\u0483", "\u0487"], ["\u0591", "\u05BD"], "\u05BF", ["\u05C1", "\u05C2"], ["\u05C4", "\u05C5"], "\u05C7", ["\u0610", "\u061A"], ["\u064B", "\u065F"], "\u0670", ["\u06D6", "\u06DC"], ["\u06DF", "\u06E4"], ["\u06E7", "\u06E8"], ["\u06EA", "\u06ED"], "\u0711", ["\u0730", "\u074A"], ["\u07A6", "\u07B0"], ["\u07EB", "\u07F3"], ["\u0816", "\u0819"], ["\u081B", "\u0823"], ["\u0825", "\u0827"], ["\u0829", "\u082D"], ["\u0859", "\u085B"], ["\u08E3", "\u0902"], "\u093A", "\u093C", ["\u0941", "\u0948"], "\u094D", ["\u0951", "\u0957"], ["\u0962", "\u0963"], "\u0981", "\u09BC", ["\u09C1", "\u09C4"], "\u09CD", ["\u09E2", "\u09E3"], ["\u0A01", "\u0A02"], "\u0A3C", ["\u0A41", "\u0A42"], ["\u0A47", "\u0A48"], ["\u0A4B", "\u0A4D"], "\u0A51", ["\u0A70", "\u0A71"], "\u0A75", ["\u0A81", "\u0A82"], "\u0ABC", ["\u0AC1", "\u0AC5"], ["\u0AC7", "\u0AC8"], "\u0ACD", ["\u0AE2", "\u0AE3"], "\u0B01", "\u0B3C", "\u0B3F", ["\u0B41", "\u0B44"], "\u0B4D", "\u0B56", ["\u0B62", "\u0B63"], "\u0B82", "\u0BC0", "\u0BCD", "\u0C00", ["\u0C3E", "\u0C40"], ["\u0C46", "\u0C48"], ["\u0C4A", "\u0C4D"], ["\u0C55", "\u0C56"], ["\u0C62", "\u0C63"], "\u0C81", "\u0CBC", "\u0CBF", "\u0CC6", ["\u0CCC", "\u0CCD"], ["\u0CE2", "\u0CE3"], "\u0D01", ["\u0D41", "\u0D44"], "\u0D4D", ["\u0D62", "\u0D63"], "\u0DCA", ["\u0DD2", "\u0DD4"], "\u0DD6", "\u0E31", ["\u0E34", "\u0E3A"], ["\u0E47", "\u0E4E"], "\u0EB1", ["\u0EB4", "\u0EB9"], ["\u0EBB", "\u0EBC"], ["\u0EC8", "\u0ECD"], ["\u0F18", "\u0F19"], "\u0F35", "\u0F37", "\u0F39", ["\u0F71", "\u0F7E"], ["\u0F80", "\u0F84"], ["\u0F86", "\u0F87"], ["\u0F8D", "\u0F97"], ["\u0F99", "\u0FBC"], "\u0FC6", ["\u102D", "\u1030"], ["\u1032", "\u1037"], ["\u1039", "\u103A"], ["\u103D", "\u103E"], ["\u1058", "\u1059"], ["\u105E", "\u1060"], ["\u1071", "\u1074"], "\u1082", ["\u1085", "\u1086"], "\u108D", "\u109D", ["\u135D", "\u135F"], ["\u1712", "\u1714"], ["\u1732", "\u1734"], ["\u1752", "\u1753"], ["\u1772", "\u1773"], ["\u17B4", "\u17B5"], ["\u17B7", "\u17BD"], "\u17C6", ["\u17C9", "\u17D3"], "\u17DD", ["\u180B", "\u180D"], "\u18A9", ["\u1920", "\u1922"], ["\u1927", "\u1928"], "\u1932", ["\u1939", "\u193B"], ["\u1A17", "\u1A18"], "\u1A1B", "\u1A56", ["\u1A58", "\u1A5E"], "\u1A60", "\u1A62", ["\u1A65", "\u1A6C"], ["\u1A73", "\u1A7C"], "\u1A7F", ["\u1AB0", "\u1ABD"], ["\u1B00", "\u1B03"], "\u1B34", ["\u1B36", "\u1B3A"], "\u1B3C", "\u1B42", ["\u1B6B", "\u1B73"], ["\u1B80", "\u1B81"], ["\u1BA2", "\u1BA5"], ["\u1BA8", "\u1BA9"], ["\u1BAB", "\u1BAD"], "\u1BE6", ["\u1BE8", "\u1BE9"], "\u1BED", ["\u1BEF", "\u1BF1"], ["\u1C2C", "\u1C33"], ["\u1C36", "\u1C37"], ["\u1CD0", "\u1CD2"], ["\u1CD4", "\u1CE0"], ["\u1CE2", "\u1CE8"], "\u1CED", "\u1CF4", ["\u1CF8", "\u1CF9"], ["\u1DC0", "\u1DF5"], ["\u1DFC", "\u1DFF"], ["\u20D0", "\u20DC"], "\u20E1", ["\u20E5", "\u20F0"], ["\u2CEF", "\u2CF1"], "\u2D7F", ["\u2DE0", "\u2DFF"], ["\u302A", "\u302D"], ["\u3099", "\u309A"], "\uA66F", ["\uA674", "\uA67D"], ["\uA69E", "\uA69F"], ["\uA6F0", "\uA6F1"], "\uA802", "\uA806", "\uA80B", ["\uA825", "\uA826"], "\uA8C4", ["\uA8E0", "\uA8F1"], ["\uA926", "\uA92D"], ["\uA947", "\uA951"], ["\uA980", "\uA982"], "\uA9B3", ["\uA9B6", "\uA9B9"], "\uA9BC", "\uA9E5", ["\uAA29", "\uAA2E"], ["\uAA31", "\uAA32"], ["\uAA35", "\uAA36"], "\uAA43", "\uAA4C", "\uAA7C", "\uAAB0", ["\uAAB2", "\uAAB4"], ["\uAAB7", "\uAAB8"], ["\uAABE", "\uAABF"], "\uAAC1", ["\uAAEC", "\uAAED"], "\uAAF6", "\uABE5", "\uABE8", "\uABED", "\uFB1E", ["\uFE00", "\uFE0F"], ["\uFE20", "\uFE2F"]], false, false);
|
|
var peg$e69 = peg$classExpectation([["0", "9"], ["\u0660", "\u0669"], ["\u06F0", "\u06F9"], ["\u07C0", "\u07C9"], ["\u0966", "\u096F"], ["\u09E6", "\u09EF"], ["\u0A66", "\u0A6F"], ["\u0AE6", "\u0AEF"], ["\u0B66", "\u0B6F"], ["\u0BE6", "\u0BEF"], ["\u0C66", "\u0C6F"], ["\u0CE6", "\u0CEF"], ["\u0D66", "\u0D6F"], ["\u0DE6", "\u0DEF"], ["\u0E50", "\u0E59"], ["\u0ED0", "\u0ED9"], ["\u0F20", "\u0F29"], ["\u1040", "\u1049"], ["\u1090", "\u1099"], ["\u17E0", "\u17E9"], ["\u1810", "\u1819"], ["\u1946", "\u194F"], ["\u19D0", "\u19D9"], ["\u1A80", "\u1A89"], ["\u1A90", "\u1A99"], ["\u1B50", "\u1B59"], ["\u1BB0", "\u1BB9"], ["\u1C40", "\u1C49"], ["\u1C50", "\u1C59"], ["\uA620", "\uA629"], ["\uA8D0", "\uA8D9"], ["\uA900", "\uA909"], ["\uA9D0", "\uA9D9"], ["\uA9F0", "\uA9F9"], ["\uAA50", "\uAA59"], ["\uABF0", "\uABF9"], ["\uFF10", "\uFF19"]], false, false);
|
|
var peg$e70 = peg$classExpectation([["\u16EE", "\u16F0"], ["\u2160", "\u2182"], ["\u2185", "\u2188"], "\u3007", ["\u3021", "\u3029"], ["\u3038", "\u303A"], ["\uA6E6", "\uA6EF"]], false, false);
|
|
var peg$e71 = peg$classExpectation(["_", ["\u203F", "\u2040"], "\u2054", ["\uFE33", "\uFE34"], ["\uFE4D", "\uFE4F"], "\uFF3F"], false, false);
|
|
var peg$e72 = peg$classExpectation([" ", "\xA0", "\u1680", ["\u2000", "\u200A"], "\u202F", "\u205F", "\u3000"], false, false);
|
|
var peg$e73 = peg$literalExpectation(";", false);
|
|
|
|
var peg$f0 = function(topLevelInitializer, initializer, rules) {
|
|
return {
|
|
type: "grammar",
|
|
topLevelInitializer,
|
|
initializer,
|
|
rules,
|
|
location: location()
|
|
};
|
|
};
|
|
var peg$f1 = function(code) {
|
|
return {
|
|
type: "top_level_initializer",
|
|
code: code[0],
|
|
codeLocation: code[1],
|
|
location: location()
|
|
};
|
|
};
|
|
var peg$f2 = function(code) {
|
|
return {
|
|
type: "initializer",
|
|
code: code[0],
|
|
codeLocation: code[1],
|
|
location: location()
|
|
};
|
|
};
|
|
var peg$f3 = function(name, displayName, expression) {
|
|
return {
|
|
type: "rule",
|
|
name: name[0],
|
|
nameLocation: name[1],
|
|
expression: displayName !== null
|
|
? {
|
|
type: "named",
|
|
name: displayName,
|
|
expression,
|
|
location: location()
|
|
}
|
|
: expression,
|
|
location: location()
|
|
};
|
|
};
|
|
var peg$f4 = function(head, tail) {
|
|
return tail.length > 0
|
|
? {
|
|
type: "choice",
|
|
alternatives: [head].concat(tail),
|
|
location: location()
|
|
}
|
|
: head;
|
|
};
|
|
var peg$f5 = function(expression, code) {
|
|
return code !== null
|
|
? {
|
|
type: "action",
|
|
expression,
|
|
code: code[0],
|
|
codeLocation: code[1],
|
|
location: location()
|
|
}
|
|
: expression;
|
|
};
|
|
var peg$f6 = function(head, tail) {
|
|
return ((tail.length > 0) || (head.type === "labeled" && head.pick))
|
|
? {
|
|
type: "sequence",
|
|
elements: [head].concat(tail),
|
|
location: location()
|
|
}
|
|
: head;
|
|
};
|
|
var peg$f7 = function(pluck, label, expression) {
|
|
if (expression.type.startsWith("semantic_")) {
|
|
error("\"@\" cannot be used on a semantic predicate", pluck);
|
|
}
|
|
return {
|
|
type: "labeled",
|
|
label: label !== null ? label[0] : null,
|
|
// Use location of "@" if label is unavailable
|
|
labelLocation: label !== null ? label[1] : pluck,
|
|
pick: true,
|
|
expression,
|
|
location: location()
|
|
};
|
|
};
|
|
var peg$f8 = function(label, expression) {
|
|
return {
|
|
type: "labeled",
|
|
label: label[0],
|
|
labelLocation: label[1],
|
|
expression,
|
|
location: location()
|
|
};
|
|
};
|
|
var peg$f9 = function() { return location(); };
|
|
var peg$f10 = function(label) {
|
|
if (reservedWords.indexOf(label[0]) >= 0) {
|
|
error(`Label can't be a reserved word "${label[0]}"`, label[1]);
|
|
}
|
|
|
|
return label;
|
|
};
|
|
var peg$f11 = function(operator, expression) {
|
|
return {
|
|
type: OPS_TO_PREFIXED_TYPES[operator],
|
|
expression,
|
|
location: location()
|
|
};
|
|
};
|
|
var peg$f12 = function(expression, operator) {
|
|
return {
|
|
type: OPS_TO_SUFFIXED_TYPES[operator],
|
|
expression,
|
|
location: location()
|
|
};
|
|
};
|
|
var peg$f13 = function(expression) {
|
|
// The purpose of the "group" AST node is just to isolate label scope. We
|
|
// don't need to put it around nodes that can't contain any labels or
|
|
// nodes that already isolate label scope themselves. This leaves us with
|
|
// "labeled" and "sequence".
|
|
return expression.type === "labeled" || expression.type === "sequence"
|
|
? { type: "group", expression, location: location() }
|
|
: expression;
|
|
};
|
|
var peg$f14 = function(name) {
|
|
return { type: "rule_ref", name: name[0], location: location() };
|
|
};
|
|
var peg$f15 = function(operator, code) {
|
|
return {
|
|
type: OPS_TO_SEMANTIC_PREDICATE_TYPES[operator],
|
|
code: code[0],
|
|
codeLocation: code[1],
|
|
location: location()
|
|
};
|
|
};
|
|
var peg$f16 = function(head, tail) {
|
|
return [head + tail.join(""), location()];
|
|
};
|
|
var peg$f17 = function(value, ignoreCase) {
|
|
return {
|
|
type: "literal",
|
|
value,
|
|
ignoreCase: ignoreCase !== null,
|
|
location: location()
|
|
};
|
|
};
|
|
var peg$f18 = function(chars) { return chars.join(""); };
|
|
var peg$f19 = function(inverted, parts, ignoreCase) {
|
|
return {
|
|
type: "class",
|
|
parts: parts.filter(part => part !== ""),
|
|
inverted: inverted !== null,
|
|
ignoreCase: ignoreCase !== null,
|
|
location: location()
|
|
};
|
|
};
|
|
var peg$f20 = function(begin, end) {
|
|
if (begin.charCodeAt(0) > end.charCodeAt(0)) {
|
|
error(
|
|
"Invalid character range: " + text() + "."
|
|
);
|
|
}
|
|
|
|
return [begin, end];
|
|
};
|
|
var peg$f21 = function() { return ""; };
|
|
var peg$f22 = function() { return "\0"; };
|
|
var peg$f23 = function() { return "\b"; };
|
|
var peg$f24 = function() { return "\f"; };
|
|
var peg$f25 = function() { return "\n"; };
|
|
var peg$f26 = function() { return "\r"; };
|
|
var peg$f27 = function() { return "\t"; };
|
|
var peg$f28 = function() { return "\v"; };
|
|
var peg$f29 = function(digits) {
|
|
return String.fromCharCode(parseInt(digits, 16));
|
|
};
|
|
var peg$f30 = function() { return { type: "any", location: location() }; };
|
|
var peg$f31 = function(code) { return [code, location()]; };
|
|
|
|
var peg$currPos = 0;
|
|
var peg$savedPos = 0;
|
|
var peg$posDetailsCache = [{ line: 1, column: 1 }];
|
|
var peg$maxFailPos = 0;
|
|
var peg$maxFailExpected = [];
|
|
var peg$silentFails = 0;
|
|
|
|
var peg$result;
|
|
|
|
if ("startRule" in options) {
|
|
if (!(options.startRule in peg$startRuleFunctions)) {
|
|
throw new Error("Can't start parsing from rule \"" + options.startRule + "\".");
|
|
}
|
|
|
|
peg$startRuleFunction = peg$startRuleFunctions[options.startRule];
|
|
}
|
|
|
|
function text() {
|
|
return input.substring(peg$savedPos, peg$currPos);
|
|
}
|
|
|
|
function offset() {
|
|
return peg$savedPos;
|
|
}
|
|
|
|
function range() {
|
|
return {
|
|
source: peg$source,
|
|
start: peg$savedPos,
|
|
end: peg$currPos
|
|
};
|
|
}
|
|
|
|
function location() {
|
|
return peg$computeLocation(peg$savedPos, peg$currPos);
|
|
}
|
|
|
|
function expected(description, location) {
|
|
location = location !== undefined
|
|
? location
|
|
: peg$computeLocation(peg$savedPos, peg$currPos);
|
|
|
|
throw peg$buildStructuredError(
|
|
[peg$otherExpectation(description)],
|
|
input.substring(peg$savedPos, peg$currPos),
|
|
location
|
|
);
|
|
}
|
|
|
|
function error(message, location) {
|
|
location = location !== undefined
|
|
? location
|
|
: peg$computeLocation(peg$savedPos, peg$currPos);
|
|
|
|
throw peg$buildSimpleError(message, location);
|
|
}
|
|
|
|
function peg$literalExpectation(text, ignoreCase) {
|
|
return { type: "literal", text: text, ignoreCase: ignoreCase };
|
|
}
|
|
|
|
function peg$classExpectation(parts, inverted, ignoreCase) {
|
|
return { type: "class", parts: parts, inverted: inverted, ignoreCase: ignoreCase };
|
|
}
|
|
|
|
function peg$anyExpectation() {
|
|
return { type: "any" };
|
|
}
|
|
|
|
function peg$endExpectation() {
|
|
return { type: "end" };
|
|
}
|
|
|
|
function peg$otherExpectation(description) {
|
|
return { type: "other", description: description };
|
|
}
|
|
|
|
function peg$computePosDetails(pos) {
|
|
var details = peg$posDetailsCache[pos];
|
|
var p;
|
|
|
|
if (details) {
|
|
return details;
|
|
} else {
|
|
p = pos - 1;
|
|
while (!peg$posDetailsCache[p]) {
|
|
p--;
|
|
}
|
|
|
|
details = peg$posDetailsCache[p];
|
|
details = {
|
|
line: details.line,
|
|
column: details.column
|
|
};
|
|
|
|
while (p < pos) {
|
|
if (input.charCodeAt(p) === 10) {
|
|
details.line++;
|
|
details.column = 1;
|
|
} else {
|
|
details.column++;
|
|
}
|
|
|
|
p++;
|
|
}
|
|
|
|
peg$posDetailsCache[pos] = details;
|
|
|
|
return details;
|
|
}
|
|
}
|
|
|
|
function peg$computeLocation(startPos, endPos) {
|
|
var startPosDetails = peg$computePosDetails(startPos);
|
|
var endPosDetails = peg$computePosDetails(endPos);
|
|
|
|
return {
|
|
source: peg$source,
|
|
start: {
|
|
offset: startPos,
|
|
line: startPosDetails.line,
|
|
column: startPosDetails.column
|
|
},
|
|
end: {
|
|
offset: endPos,
|
|
line: endPosDetails.line,
|
|
column: endPosDetails.column
|
|
}
|
|
};
|
|
}
|
|
|
|
function peg$fail(expected) {
|
|
if (peg$currPos < peg$maxFailPos) { return; }
|
|
|
|
if (peg$currPos > peg$maxFailPos) {
|
|
peg$maxFailPos = peg$currPos;
|
|
peg$maxFailExpected = [];
|
|
}
|
|
|
|
peg$maxFailExpected.push(expected);
|
|
}
|
|
|
|
function peg$buildSimpleError(message, location) {
|
|
return new peg$SyntaxError(message, null, null, location);
|
|
}
|
|
|
|
function peg$buildStructuredError(expected, found, location) {
|
|
return new peg$SyntaxError(
|
|
peg$SyntaxError.buildMessage(expected, found),
|
|
expected,
|
|
found,
|
|
location
|
|
);
|
|
}
|
|
|
|
function peg$parseGrammar() {
|
|
var s0, s1, s2, s3, s4, s5, s6, s7;
|
|
|
|
s0 = peg$currPos;
|
|
s1 = peg$parse__();
|
|
s2 = peg$currPos;
|
|
s3 = peg$parseTopLevelInitializer();
|
|
if (s3 !== peg$FAILED) {
|
|
s4 = peg$parse__();
|
|
s2 = s3;
|
|
} else {
|
|
peg$currPos = s2;
|
|
s2 = peg$FAILED;
|
|
}
|
|
if (s2 === peg$FAILED) {
|
|
s2 = null;
|
|
}
|
|
s3 = peg$currPos;
|
|
s4 = peg$parseInitializer();
|
|
if (s4 !== peg$FAILED) {
|
|
s5 = peg$parse__();
|
|
s3 = s4;
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
if (s3 === peg$FAILED) {
|
|
s3 = null;
|
|
}
|
|
s4 = [];
|
|
s5 = peg$currPos;
|
|
s6 = peg$parseRule();
|
|
if (s6 !== peg$FAILED) {
|
|
s7 = peg$parse__();
|
|
s5 = s6;
|
|
} else {
|
|
peg$currPos = s5;
|
|
s5 = peg$FAILED;
|
|
}
|
|
if (s5 !== peg$FAILED) {
|
|
while (s5 !== peg$FAILED) {
|
|
s4.push(s5);
|
|
s5 = peg$currPos;
|
|
s6 = peg$parseRule();
|
|
if (s6 !== peg$FAILED) {
|
|
s7 = peg$parse__();
|
|
s5 = s6;
|
|
} else {
|
|
peg$currPos = s5;
|
|
s5 = peg$FAILED;
|
|
}
|
|
}
|
|
} else {
|
|
s4 = peg$FAILED;
|
|
}
|
|
if (s4 !== peg$FAILED) {
|
|
peg$savedPos = s0;
|
|
s0 = peg$f0(s2, s3, s4);
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseTopLevelInitializer() {
|
|
var s0, s1, s2, s3, s4;
|
|
|
|
s0 = peg$currPos;
|
|
if (input.charCodeAt(peg$currPos) === 123) {
|
|
s1 = peg$c0;
|
|
peg$currPos++;
|
|
} else {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e0); }
|
|
}
|
|
if (s1 !== peg$FAILED) {
|
|
s2 = peg$parseCodeBlock();
|
|
if (s2 !== peg$FAILED) {
|
|
if (input.charCodeAt(peg$currPos) === 125) {
|
|
s3 = peg$c1;
|
|
peg$currPos++;
|
|
} else {
|
|
s3 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e1); }
|
|
}
|
|
if (s3 !== peg$FAILED) {
|
|
s4 = peg$parseEOS();
|
|
if (s4 !== peg$FAILED) {
|
|
peg$savedPos = s0;
|
|
s0 = peg$f1(s2);
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseInitializer() {
|
|
var s0, s1, s2;
|
|
|
|
s0 = peg$currPos;
|
|
s1 = peg$parseCodeBlock();
|
|
if (s1 !== peg$FAILED) {
|
|
s2 = peg$parseEOS();
|
|
if (s2 !== peg$FAILED) {
|
|
peg$savedPos = s0;
|
|
s0 = peg$f2(s1);
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseRule() {
|
|
var s0, s1, s2, s3, s4, s5, s6, s7;
|
|
|
|
s0 = peg$currPos;
|
|
s1 = peg$parseIdentifierName();
|
|
if (s1 !== peg$FAILED) {
|
|
s2 = peg$parse__();
|
|
s3 = peg$currPos;
|
|
s4 = peg$parseStringLiteral();
|
|
if (s4 !== peg$FAILED) {
|
|
s5 = peg$parse__();
|
|
s3 = s4;
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
if (s3 === peg$FAILED) {
|
|
s3 = null;
|
|
}
|
|
if (input.charCodeAt(peg$currPos) === 61) {
|
|
s4 = peg$c2;
|
|
peg$currPos++;
|
|
} else {
|
|
s4 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e2); }
|
|
}
|
|
if (s4 !== peg$FAILED) {
|
|
s5 = peg$parse__();
|
|
s6 = peg$parseChoiceExpression();
|
|
if (s6 !== peg$FAILED) {
|
|
s7 = peg$parseEOS();
|
|
if (s7 !== peg$FAILED) {
|
|
peg$savedPos = s0;
|
|
s0 = peg$f3(s1, s3, s6);
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseChoiceExpression() {
|
|
var s0, s1, s2, s3, s4, s5, s6, s7;
|
|
|
|
s0 = peg$currPos;
|
|
s1 = peg$parseActionExpression();
|
|
if (s1 !== peg$FAILED) {
|
|
s2 = [];
|
|
s3 = peg$currPos;
|
|
s4 = peg$parse__();
|
|
if (input.charCodeAt(peg$currPos) === 47) {
|
|
s5 = peg$c3;
|
|
peg$currPos++;
|
|
} else {
|
|
s5 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e3); }
|
|
}
|
|
if (s5 !== peg$FAILED) {
|
|
s6 = peg$parse__();
|
|
s7 = peg$parseActionExpression();
|
|
if (s7 !== peg$FAILED) {
|
|
s3 = s7;
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
while (s3 !== peg$FAILED) {
|
|
s2.push(s3);
|
|
s3 = peg$currPos;
|
|
s4 = peg$parse__();
|
|
if (input.charCodeAt(peg$currPos) === 47) {
|
|
s5 = peg$c3;
|
|
peg$currPos++;
|
|
} else {
|
|
s5 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e3); }
|
|
}
|
|
if (s5 !== peg$FAILED) {
|
|
s6 = peg$parse__();
|
|
s7 = peg$parseActionExpression();
|
|
if (s7 !== peg$FAILED) {
|
|
s3 = s7;
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
}
|
|
peg$savedPos = s0;
|
|
s0 = peg$f4(s1, s2);
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseActionExpression() {
|
|
var s0, s1, s2, s3, s4;
|
|
|
|
s0 = peg$currPos;
|
|
s1 = peg$parseSequenceExpression();
|
|
if (s1 !== peg$FAILED) {
|
|
s2 = peg$currPos;
|
|
s3 = peg$parse__();
|
|
s4 = peg$parseCodeBlock();
|
|
if (s4 !== peg$FAILED) {
|
|
s2 = s4;
|
|
} else {
|
|
peg$currPos = s2;
|
|
s2 = peg$FAILED;
|
|
}
|
|
if (s2 === peg$FAILED) {
|
|
s2 = null;
|
|
}
|
|
peg$savedPos = s0;
|
|
s0 = peg$f5(s1, s2);
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseSequenceExpression() {
|
|
var s0, s1, s2, s3, s4, s5;
|
|
|
|
s0 = peg$currPos;
|
|
s1 = peg$parseLabeledExpression();
|
|
if (s1 !== peg$FAILED) {
|
|
s2 = [];
|
|
s3 = peg$currPos;
|
|
s4 = peg$parse__();
|
|
s5 = peg$parseLabeledExpression();
|
|
if (s5 !== peg$FAILED) {
|
|
s3 = s5;
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
while (s3 !== peg$FAILED) {
|
|
s2.push(s3);
|
|
s3 = peg$currPos;
|
|
s4 = peg$parse__();
|
|
s5 = peg$parseLabeledExpression();
|
|
if (s5 !== peg$FAILED) {
|
|
s3 = s5;
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
}
|
|
peg$savedPos = s0;
|
|
s0 = peg$f6(s1, s2);
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseLabeledExpression() {
|
|
var s0, s1, s2, s3;
|
|
|
|
s0 = peg$currPos;
|
|
s1 = peg$parsePluck();
|
|
if (s1 !== peg$FAILED) {
|
|
s2 = peg$parseLabelColon();
|
|
if (s2 === peg$FAILED) {
|
|
s2 = null;
|
|
}
|
|
s3 = peg$parsePrefixedExpression();
|
|
if (s3 !== peg$FAILED) {
|
|
peg$savedPos = s0;
|
|
s0 = peg$f7(s1, s2, s3);
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$currPos;
|
|
s1 = peg$parseLabelColon();
|
|
if (s1 !== peg$FAILED) {
|
|
s2 = peg$parse__();
|
|
s3 = peg$parsePrefixedExpression();
|
|
if (s3 !== peg$FAILED) {
|
|
peg$savedPos = s0;
|
|
s0 = peg$f8(s1, s3);
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$parsePrefixedExpression();
|
|
}
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parsePluck() {
|
|
var s0, s1;
|
|
|
|
s0 = peg$currPos;
|
|
if (input.charCodeAt(peg$currPos) === 64) {
|
|
s1 = peg$c4;
|
|
peg$currPos++;
|
|
} else {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e4); }
|
|
}
|
|
if (s1 !== peg$FAILED) {
|
|
peg$savedPos = s0;
|
|
s1 = peg$f9();
|
|
}
|
|
s0 = s1;
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseLabelColon() {
|
|
var s0, s1, s2, s3;
|
|
|
|
s0 = peg$currPos;
|
|
s1 = peg$parseIdentifierName();
|
|
if (s1 !== peg$FAILED) {
|
|
s2 = peg$parse__();
|
|
if (input.charCodeAt(peg$currPos) === 58) {
|
|
s3 = peg$c5;
|
|
peg$currPos++;
|
|
} else {
|
|
s3 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e5); }
|
|
}
|
|
if (s3 !== peg$FAILED) {
|
|
peg$savedPos = s0;
|
|
s0 = peg$f10(s1);
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parsePrefixedExpression() {
|
|
var s0, s1, s2, s3;
|
|
|
|
s0 = peg$currPos;
|
|
s1 = peg$parsePrefixedOperator();
|
|
if (s1 !== peg$FAILED) {
|
|
s2 = peg$parse__();
|
|
s3 = peg$parseSuffixedExpression();
|
|
if (s3 !== peg$FAILED) {
|
|
peg$savedPos = s0;
|
|
s0 = peg$f11(s1, s3);
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$parseSuffixedExpression();
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parsePrefixedOperator() {
|
|
var s0;
|
|
|
|
if (input.charCodeAt(peg$currPos) === 36) {
|
|
s0 = peg$c6;
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e6); }
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
if (input.charCodeAt(peg$currPos) === 38) {
|
|
s0 = peg$c7;
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e7); }
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
if (input.charCodeAt(peg$currPos) === 33) {
|
|
s0 = peg$c8;
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e8); }
|
|
}
|
|
}
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseSuffixedExpression() {
|
|
var s0, s1, s2, s3;
|
|
|
|
s0 = peg$currPos;
|
|
s1 = peg$parsePrimaryExpression();
|
|
if (s1 !== peg$FAILED) {
|
|
s2 = peg$parse__();
|
|
s3 = peg$parseSuffixedOperator();
|
|
if (s3 !== peg$FAILED) {
|
|
peg$savedPos = s0;
|
|
s0 = peg$f12(s1, s3);
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$parsePrimaryExpression();
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseSuffixedOperator() {
|
|
var s0;
|
|
|
|
if (input.charCodeAt(peg$currPos) === 63) {
|
|
s0 = peg$c9;
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e9); }
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
if (input.charCodeAt(peg$currPos) === 42) {
|
|
s0 = peg$c10;
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e10); }
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
if (input.charCodeAt(peg$currPos) === 43) {
|
|
s0 = peg$c11;
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e11); }
|
|
}
|
|
}
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parsePrimaryExpression() {
|
|
var s0, s1, s2, s3, s4, s5;
|
|
|
|
s0 = peg$parseLiteralMatcher();
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$parseCharacterClassMatcher();
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$parseAnyMatcher();
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$parseRuleReferenceExpression();
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$parseSemanticPredicateExpression();
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$currPos;
|
|
if (input.charCodeAt(peg$currPos) === 40) {
|
|
s1 = peg$c12;
|
|
peg$currPos++;
|
|
} else {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e12); }
|
|
}
|
|
if (s1 !== peg$FAILED) {
|
|
s2 = peg$parse__();
|
|
s3 = peg$parseChoiceExpression();
|
|
if (s3 !== peg$FAILED) {
|
|
s4 = peg$parse__();
|
|
if (input.charCodeAt(peg$currPos) === 41) {
|
|
s5 = peg$c13;
|
|
peg$currPos++;
|
|
} else {
|
|
s5 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e13); }
|
|
}
|
|
if (s5 !== peg$FAILED) {
|
|
peg$savedPos = s0;
|
|
s0 = peg$f13(s3);
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseRuleReferenceExpression() {
|
|
var s0, s1, s2, s3, s4, s5, s6, s7;
|
|
|
|
s0 = peg$currPos;
|
|
s1 = peg$parseIdentifierName();
|
|
if (s1 !== peg$FAILED) {
|
|
s2 = peg$currPos;
|
|
peg$silentFails++;
|
|
s3 = peg$currPos;
|
|
s4 = peg$parse__();
|
|
s5 = peg$currPos;
|
|
s6 = peg$parseStringLiteral();
|
|
if (s6 !== peg$FAILED) {
|
|
s7 = peg$parse__();
|
|
s6 = [s6, s7];
|
|
s5 = s6;
|
|
} else {
|
|
peg$currPos = s5;
|
|
s5 = peg$FAILED;
|
|
}
|
|
if (s5 === peg$FAILED) {
|
|
s5 = null;
|
|
}
|
|
if (input.charCodeAt(peg$currPos) === 61) {
|
|
s6 = peg$c2;
|
|
peg$currPos++;
|
|
} else {
|
|
s6 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e2); }
|
|
}
|
|
if (s6 !== peg$FAILED) {
|
|
s4 = [s4, s5, s6];
|
|
s3 = s4;
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
peg$silentFails--;
|
|
if (s3 === peg$FAILED) {
|
|
s2 = undefined;
|
|
} else {
|
|
peg$currPos = s2;
|
|
s2 = peg$FAILED;
|
|
}
|
|
if (s2 !== peg$FAILED) {
|
|
peg$savedPos = s0;
|
|
s0 = peg$f14(s1);
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseSemanticPredicateExpression() {
|
|
var s0, s1, s2, s3;
|
|
|
|
s0 = peg$currPos;
|
|
s1 = peg$parseSemanticPredicateOperator();
|
|
if (s1 !== peg$FAILED) {
|
|
s2 = peg$parse__();
|
|
s3 = peg$parseCodeBlock();
|
|
if (s3 !== peg$FAILED) {
|
|
peg$savedPos = s0;
|
|
s0 = peg$f15(s1, s3);
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseSemanticPredicateOperator() {
|
|
var s0;
|
|
|
|
if (input.charCodeAt(peg$currPos) === 38) {
|
|
s0 = peg$c7;
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e7); }
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
if (input.charCodeAt(peg$currPos) === 33) {
|
|
s0 = peg$c8;
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e8); }
|
|
}
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseSourceCharacter() {
|
|
var s0;
|
|
|
|
if (input.length > peg$currPos) {
|
|
s0 = input.charAt(peg$currPos);
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e14); }
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseWhiteSpace() {
|
|
var s0, s1;
|
|
|
|
peg$silentFails++;
|
|
if (input.charCodeAt(peg$currPos) === 9) {
|
|
s0 = peg$c14;
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e16); }
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
if (input.charCodeAt(peg$currPos) === 11) {
|
|
s0 = peg$c15;
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e17); }
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
if (input.charCodeAt(peg$currPos) === 12) {
|
|
s0 = peg$c16;
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e18); }
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
if (input.charCodeAt(peg$currPos) === 32) {
|
|
s0 = peg$c17;
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e19); }
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
if (input.charCodeAt(peg$currPos) === 160) {
|
|
s0 = peg$c18;
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e20); }
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
if (input.charCodeAt(peg$currPos) === 65279) {
|
|
s0 = peg$c19;
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e21); }
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$parseZs();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
peg$silentFails--;
|
|
if (s0 === peg$FAILED) {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e15); }
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseLineTerminator() {
|
|
var s0;
|
|
|
|
if (peg$r0.test(input.charAt(peg$currPos))) {
|
|
s0 = input.charAt(peg$currPos);
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e22); }
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseLineTerminatorSequence() {
|
|
var s0, s1;
|
|
|
|
peg$silentFails++;
|
|
if (input.charCodeAt(peg$currPos) === 10) {
|
|
s0 = peg$c20;
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e24); }
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
if (input.substr(peg$currPos, 2) === peg$c21) {
|
|
s0 = peg$c21;
|
|
peg$currPos += 2;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e25); }
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
if (input.charCodeAt(peg$currPos) === 13) {
|
|
s0 = peg$c22;
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e26); }
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
if (input.charCodeAt(peg$currPos) === 8232) {
|
|
s0 = peg$c23;
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e27); }
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
if (input.charCodeAt(peg$currPos) === 8233) {
|
|
s0 = peg$c24;
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e28); }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
peg$silentFails--;
|
|
if (s0 === peg$FAILED) {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e23); }
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseComment() {
|
|
var s0, s1;
|
|
|
|
peg$silentFails++;
|
|
s0 = peg$parseMultiLineComment();
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$parseSingleLineComment();
|
|
}
|
|
peg$silentFails--;
|
|
if (s0 === peg$FAILED) {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e29); }
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseMultiLineComment() {
|
|
var s0, s1, s2, s3, s4, s5;
|
|
|
|
s0 = peg$currPos;
|
|
if (input.substr(peg$currPos, 2) === peg$c25) {
|
|
s1 = peg$c25;
|
|
peg$currPos += 2;
|
|
} else {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e30); }
|
|
}
|
|
if (s1 !== peg$FAILED) {
|
|
s2 = [];
|
|
s3 = peg$currPos;
|
|
s4 = peg$currPos;
|
|
peg$silentFails++;
|
|
if (input.substr(peg$currPos, 2) === peg$c26) {
|
|
s5 = peg$c26;
|
|
peg$currPos += 2;
|
|
} else {
|
|
s5 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e31); }
|
|
}
|
|
peg$silentFails--;
|
|
if (s5 === peg$FAILED) {
|
|
s4 = undefined;
|
|
} else {
|
|
peg$currPos = s4;
|
|
s4 = peg$FAILED;
|
|
}
|
|
if (s4 !== peg$FAILED) {
|
|
s5 = peg$parseSourceCharacter();
|
|
if (s5 !== peg$FAILED) {
|
|
s4 = [s4, s5];
|
|
s3 = s4;
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
while (s3 !== peg$FAILED) {
|
|
s2.push(s3);
|
|
s3 = peg$currPos;
|
|
s4 = peg$currPos;
|
|
peg$silentFails++;
|
|
if (input.substr(peg$currPos, 2) === peg$c26) {
|
|
s5 = peg$c26;
|
|
peg$currPos += 2;
|
|
} else {
|
|
s5 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e31); }
|
|
}
|
|
peg$silentFails--;
|
|
if (s5 === peg$FAILED) {
|
|
s4 = undefined;
|
|
} else {
|
|
peg$currPos = s4;
|
|
s4 = peg$FAILED;
|
|
}
|
|
if (s4 !== peg$FAILED) {
|
|
s5 = peg$parseSourceCharacter();
|
|
if (s5 !== peg$FAILED) {
|
|
s4 = [s4, s5];
|
|
s3 = s4;
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
}
|
|
if (input.substr(peg$currPos, 2) === peg$c26) {
|
|
s3 = peg$c26;
|
|
peg$currPos += 2;
|
|
} else {
|
|
s3 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e31); }
|
|
}
|
|
if (s3 !== peg$FAILED) {
|
|
s1 = [s1, s2, s3];
|
|
s0 = s1;
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseMultiLineCommentNoLineTerminator() {
|
|
var s0, s1, s2, s3, s4, s5;
|
|
|
|
s0 = peg$currPos;
|
|
if (input.substr(peg$currPos, 2) === peg$c25) {
|
|
s1 = peg$c25;
|
|
peg$currPos += 2;
|
|
} else {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e30); }
|
|
}
|
|
if (s1 !== peg$FAILED) {
|
|
s2 = [];
|
|
s3 = peg$currPos;
|
|
s4 = peg$currPos;
|
|
peg$silentFails++;
|
|
if (input.substr(peg$currPos, 2) === peg$c26) {
|
|
s5 = peg$c26;
|
|
peg$currPos += 2;
|
|
} else {
|
|
s5 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e31); }
|
|
}
|
|
if (s5 === peg$FAILED) {
|
|
s5 = peg$parseLineTerminator();
|
|
}
|
|
peg$silentFails--;
|
|
if (s5 === peg$FAILED) {
|
|
s4 = undefined;
|
|
} else {
|
|
peg$currPos = s4;
|
|
s4 = peg$FAILED;
|
|
}
|
|
if (s4 !== peg$FAILED) {
|
|
s5 = peg$parseSourceCharacter();
|
|
if (s5 !== peg$FAILED) {
|
|
s4 = [s4, s5];
|
|
s3 = s4;
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
while (s3 !== peg$FAILED) {
|
|
s2.push(s3);
|
|
s3 = peg$currPos;
|
|
s4 = peg$currPos;
|
|
peg$silentFails++;
|
|
if (input.substr(peg$currPos, 2) === peg$c26) {
|
|
s5 = peg$c26;
|
|
peg$currPos += 2;
|
|
} else {
|
|
s5 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e31); }
|
|
}
|
|
if (s5 === peg$FAILED) {
|
|
s5 = peg$parseLineTerminator();
|
|
}
|
|
peg$silentFails--;
|
|
if (s5 === peg$FAILED) {
|
|
s4 = undefined;
|
|
} else {
|
|
peg$currPos = s4;
|
|
s4 = peg$FAILED;
|
|
}
|
|
if (s4 !== peg$FAILED) {
|
|
s5 = peg$parseSourceCharacter();
|
|
if (s5 !== peg$FAILED) {
|
|
s4 = [s4, s5];
|
|
s3 = s4;
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
}
|
|
if (input.substr(peg$currPos, 2) === peg$c26) {
|
|
s3 = peg$c26;
|
|
peg$currPos += 2;
|
|
} else {
|
|
s3 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e31); }
|
|
}
|
|
if (s3 !== peg$FAILED) {
|
|
s1 = [s1, s2, s3];
|
|
s0 = s1;
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseSingleLineComment() {
|
|
var s0, s1, s2, s3, s4, s5;
|
|
|
|
s0 = peg$currPos;
|
|
if (input.substr(peg$currPos, 2) === peg$c27) {
|
|
s1 = peg$c27;
|
|
peg$currPos += 2;
|
|
} else {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e32); }
|
|
}
|
|
if (s1 !== peg$FAILED) {
|
|
s2 = [];
|
|
s3 = peg$currPos;
|
|
s4 = peg$currPos;
|
|
peg$silentFails++;
|
|
s5 = peg$parseLineTerminator();
|
|
peg$silentFails--;
|
|
if (s5 === peg$FAILED) {
|
|
s4 = undefined;
|
|
} else {
|
|
peg$currPos = s4;
|
|
s4 = peg$FAILED;
|
|
}
|
|
if (s4 !== peg$FAILED) {
|
|
s5 = peg$parseSourceCharacter();
|
|
if (s5 !== peg$FAILED) {
|
|
s4 = [s4, s5];
|
|
s3 = s4;
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
while (s3 !== peg$FAILED) {
|
|
s2.push(s3);
|
|
s3 = peg$currPos;
|
|
s4 = peg$currPos;
|
|
peg$silentFails++;
|
|
s5 = peg$parseLineTerminator();
|
|
peg$silentFails--;
|
|
if (s5 === peg$FAILED) {
|
|
s4 = undefined;
|
|
} else {
|
|
peg$currPos = s4;
|
|
s4 = peg$FAILED;
|
|
}
|
|
if (s4 !== peg$FAILED) {
|
|
s5 = peg$parseSourceCharacter();
|
|
if (s5 !== peg$FAILED) {
|
|
s4 = [s4, s5];
|
|
s3 = s4;
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
}
|
|
s1 = [s1, s2];
|
|
s0 = s1;
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseIdentifierName() {
|
|
var s0, s1, s2, s3;
|
|
|
|
peg$silentFails++;
|
|
s0 = peg$currPos;
|
|
s1 = peg$parseIdentifierStart();
|
|
if (s1 !== peg$FAILED) {
|
|
s2 = [];
|
|
s3 = peg$parseIdentifierPart();
|
|
while (s3 !== peg$FAILED) {
|
|
s2.push(s3);
|
|
s3 = peg$parseIdentifierPart();
|
|
}
|
|
peg$savedPos = s0;
|
|
s0 = peg$f16(s1, s2);
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
peg$silentFails--;
|
|
if (s0 === peg$FAILED) {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e33); }
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseIdentifierStart() {
|
|
var s0, s1, s2;
|
|
|
|
s0 = peg$parseUnicodeLetter();
|
|
if (s0 === peg$FAILED) {
|
|
if (input.charCodeAt(peg$currPos) === 36) {
|
|
s0 = peg$c6;
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e6); }
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
if (input.charCodeAt(peg$currPos) === 95) {
|
|
s0 = peg$c28;
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e34); }
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$currPos;
|
|
if (input.charCodeAt(peg$currPos) === 92) {
|
|
s1 = peg$c29;
|
|
peg$currPos++;
|
|
} else {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e35); }
|
|
}
|
|
if (s1 !== peg$FAILED) {
|
|
s2 = peg$parseUnicodeEscapeSequence();
|
|
if (s2 !== peg$FAILED) {
|
|
s0 = s2;
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseIdentifierPart() {
|
|
var s0;
|
|
|
|
s0 = peg$parseIdentifierStart();
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$parseUnicodeCombiningMark();
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$parseNd();
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$parsePc();
|
|
if (s0 === peg$FAILED) {
|
|
if (input.charCodeAt(peg$currPos) === 8204) {
|
|
s0 = peg$c30;
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e36); }
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
if (input.charCodeAt(peg$currPos) === 8205) {
|
|
s0 = peg$c31;
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e37); }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseUnicodeLetter() {
|
|
var s0;
|
|
|
|
s0 = peg$parseLu();
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$parseLl();
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$parseLt();
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$parseLm();
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$parseLo();
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$parseNl();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseUnicodeCombiningMark() {
|
|
var s0;
|
|
|
|
s0 = peg$parseMn();
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$parseMc();
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseLiteralMatcher() {
|
|
var s0, s1, s2;
|
|
|
|
peg$silentFails++;
|
|
s0 = peg$currPos;
|
|
s1 = peg$parseStringLiteral();
|
|
if (s1 !== peg$FAILED) {
|
|
if (input.charCodeAt(peg$currPos) === 105) {
|
|
s2 = peg$c32;
|
|
peg$currPos++;
|
|
} else {
|
|
s2 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e39); }
|
|
}
|
|
if (s2 === peg$FAILED) {
|
|
s2 = null;
|
|
}
|
|
peg$savedPos = s0;
|
|
s0 = peg$f17(s1, s2);
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
peg$silentFails--;
|
|
if (s0 === peg$FAILED) {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e38); }
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseStringLiteral() {
|
|
var s0, s1, s2, s3;
|
|
|
|
peg$silentFails++;
|
|
s0 = peg$currPos;
|
|
if (input.charCodeAt(peg$currPos) === 34) {
|
|
s1 = peg$c33;
|
|
peg$currPos++;
|
|
} else {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e41); }
|
|
}
|
|
if (s1 !== peg$FAILED) {
|
|
s2 = [];
|
|
s3 = peg$parseDoubleStringCharacter();
|
|
while (s3 !== peg$FAILED) {
|
|
s2.push(s3);
|
|
s3 = peg$parseDoubleStringCharacter();
|
|
}
|
|
if (input.charCodeAt(peg$currPos) === 34) {
|
|
s3 = peg$c33;
|
|
peg$currPos++;
|
|
} else {
|
|
s3 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e41); }
|
|
}
|
|
if (s3 !== peg$FAILED) {
|
|
peg$savedPos = s0;
|
|
s0 = peg$f18(s2);
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$currPos;
|
|
if (input.charCodeAt(peg$currPos) === 39) {
|
|
s1 = peg$c34;
|
|
peg$currPos++;
|
|
} else {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e42); }
|
|
}
|
|
if (s1 !== peg$FAILED) {
|
|
s2 = [];
|
|
s3 = peg$parseSingleStringCharacter();
|
|
while (s3 !== peg$FAILED) {
|
|
s2.push(s3);
|
|
s3 = peg$parseSingleStringCharacter();
|
|
}
|
|
if (input.charCodeAt(peg$currPos) === 39) {
|
|
s3 = peg$c34;
|
|
peg$currPos++;
|
|
} else {
|
|
s3 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e42); }
|
|
}
|
|
if (s3 !== peg$FAILED) {
|
|
peg$savedPos = s0;
|
|
s0 = peg$f18(s2);
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
}
|
|
peg$silentFails--;
|
|
if (s0 === peg$FAILED) {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e40); }
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseDoubleStringCharacter() {
|
|
var s0, s1, s2, s3;
|
|
|
|
s0 = peg$currPos;
|
|
s1 = peg$currPos;
|
|
s2 = peg$currPos;
|
|
peg$silentFails++;
|
|
if (input.charCodeAt(peg$currPos) === 34) {
|
|
s3 = peg$c33;
|
|
peg$currPos++;
|
|
} else {
|
|
s3 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e41); }
|
|
}
|
|
if (s3 === peg$FAILED) {
|
|
if (input.charCodeAt(peg$currPos) === 92) {
|
|
s3 = peg$c29;
|
|
peg$currPos++;
|
|
} else {
|
|
s3 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e35); }
|
|
}
|
|
if (s3 === peg$FAILED) {
|
|
s3 = peg$parseLineTerminator();
|
|
}
|
|
}
|
|
peg$silentFails--;
|
|
if (s3 === peg$FAILED) {
|
|
s2 = undefined;
|
|
} else {
|
|
peg$currPos = s2;
|
|
s2 = peg$FAILED;
|
|
}
|
|
if (s2 !== peg$FAILED) {
|
|
s3 = peg$parseSourceCharacter();
|
|
if (s3 !== peg$FAILED) {
|
|
s2 = [s2, s3];
|
|
s1 = s2;
|
|
} else {
|
|
peg$currPos = s1;
|
|
s1 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s1;
|
|
s1 = peg$FAILED;
|
|
}
|
|
if (s1 !== peg$FAILED) {
|
|
s0 = input.substring(s0, peg$currPos);
|
|
} else {
|
|
s0 = s1;
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$currPos;
|
|
if (input.charCodeAt(peg$currPos) === 92) {
|
|
s1 = peg$c29;
|
|
peg$currPos++;
|
|
} else {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e35); }
|
|
}
|
|
if (s1 !== peg$FAILED) {
|
|
s2 = peg$parseEscapeSequence();
|
|
if (s2 !== peg$FAILED) {
|
|
s0 = s2;
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$parseLineContinuation();
|
|
}
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseSingleStringCharacter() {
|
|
var s0, s1, s2, s3;
|
|
|
|
s0 = peg$currPos;
|
|
s1 = peg$currPos;
|
|
s2 = peg$currPos;
|
|
peg$silentFails++;
|
|
if (input.charCodeAt(peg$currPos) === 39) {
|
|
s3 = peg$c34;
|
|
peg$currPos++;
|
|
} else {
|
|
s3 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e42); }
|
|
}
|
|
if (s3 === peg$FAILED) {
|
|
if (input.charCodeAt(peg$currPos) === 92) {
|
|
s3 = peg$c29;
|
|
peg$currPos++;
|
|
} else {
|
|
s3 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e35); }
|
|
}
|
|
if (s3 === peg$FAILED) {
|
|
s3 = peg$parseLineTerminator();
|
|
}
|
|
}
|
|
peg$silentFails--;
|
|
if (s3 === peg$FAILED) {
|
|
s2 = undefined;
|
|
} else {
|
|
peg$currPos = s2;
|
|
s2 = peg$FAILED;
|
|
}
|
|
if (s2 !== peg$FAILED) {
|
|
s3 = peg$parseSourceCharacter();
|
|
if (s3 !== peg$FAILED) {
|
|
s2 = [s2, s3];
|
|
s1 = s2;
|
|
} else {
|
|
peg$currPos = s1;
|
|
s1 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s1;
|
|
s1 = peg$FAILED;
|
|
}
|
|
if (s1 !== peg$FAILED) {
|
|
s0 = input.substring(s0, peg$currPos);
|
|
} else {
|
|
s0 = s1;
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$currPos;
|
|
if (input.charCodeAt(peg$currPos) === 92) {
|
|
s1 = peg$c29;
|
|
peg$currPos++;
|
|
} else {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e35); }
|
|
}
|
|
if (s1 !== peg$FAILED) {
|
|
s2 = peg$parseEscapeSequence();
|
|
if (s2 !== peg$FAILED) {
|
|
s0 = s2;
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$parseLineContinuation();
|
|
}
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseCharacterClassMatcher() {
|
|
var s0, s1, s2, s3, s4, s5;
|
|
|
|
peg$silentFails++;
|
|
s0 = peg$currPos;
|
|
if (input.charCodeAt(peg$currPos) === 91) {
|
|
s1 = peg$c35;
|
|
peg$currPos++;
|
|
} else {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e44); }
|
|
}
|
|
if (s1 !== peg$FAILED) {
|
|
if (input.charCodeAt(peg$currPos) === 94) {
|
|
s2 = peg$c36;
|
|
peg$currPos++;
|
|
} else {
|
|
s2 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e45); }
|
|
}
|
|
if (s2 === peg$FAILED) {
|
|
s2 = null;
|
|
}
|
|
s3 = [];
|
|
s4 = peg$parseClassCharacterRange();
|
|
if (s4 === peg$FAILED) {
|
|
s4 = peg$parseClassCharacter();
|
|
}
|
|
while (s4 !== peg$FAILED) {
|
|
s3.push(s4);
|
|
s4 = peg$parseClassCharacterRange();
|
|
if (s4 === peg$FAILED) {
|
|
s4 = peg$parseClassCharacter();
|
|
}
|
|
}
|
|
if (input.charCodeAt(peg$currPos) === 93) {
|
|
s4 = peg$c37;
|
|
peg$currPos++;
|
|
} else {
|
|
s4 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e46); }
|
|
}
|
|
if (s4 !== peg$FAILED) {
|
|
if (input.charCodeAt(peg$currPos) === 105) {
|
|
s5 = peg$c32;
|
|
peg$currPos++;
|
|
} else {
|
|
s5 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e39); }
|
|
}
|
|
if (s5 === peg$FAILED) {
|
|
s5 = null;
|
|
}
|
|
peg$savedPos = s0;
|
|
s0 = peg$f19(s2, s3, s5);
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
peg$silentFails--;
|
|
if (s0 === peg$FAILED) {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e43); }
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseClassCharacterRange() {
|
|
var s0, s1, s2, s3;
|
|
|
|
s0 = peg$currPos;
|
|
s1 = peg$parseClassCharacter();
|
|
if (s1 !== peg$FAILED) {
|
|
if (input.charCodeAt(peg$currPos) === 45) {
|
|
s2 = peg$c38;
|
|
peg$currPos++;
|
|
} else {
|
|
s2 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e47); }
|
|
}
|
|
if (s2 !== peg$FAILED) {
|
|
s3 = peg$parseClassCharacter();
|
|
if (s3 !== peg$FAILED) {
|
|
peg$savedPos = s0;
|
|
s0 = peg$f20(s1, s3);
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseClassCharacter() {
|
|
var s0, s1, s2, s3;
|
|
|
|
s0 = peg$currPos;
|
|
s1 = peg$currPos;
|
|
s2 = peg$currPos;
|
|
peg$silentFails++;
|
|
if (input.charCodeAt(peg$currPos) === 93) {
|
|
s3 = peg$c37;
|
|
peg$currPos++;
|
|
} else {
|
|
s3 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e46); }
|
|
}
|
|
if (s3 === peg$FAILED) {
|
|
if (input.charCodeAt(peg$currPos) === 92) {
|
|
s3 = peg$c29;
|
|
peg$currPos++;
|
|
} else {
|
|
s3 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e35); }
|
|
}
|
|
if (s3 === peg$FAILED) {
|
|
s3 = peg$parseLineTerminator();
|
|
}
|
|
}
|
|
peg$silentFails--;
|
|
if (s3 === peg$FAILED) {
|
|
s2 = undefined;
|
|
} else {
|
|
peg$currPos = s2;
|
|
s2 = peg$FAILED;
|
|
}
|
|
if (s2 !== peg$FAILED) {
|
|
s3 = peg$parseSourceCharacter();
|
|
if (s3 !== peg$FAILED) {
|
|
s2 = [s2, s3];
|
|
s1 = s2;
|
|
} else {
|
|
peg$currPos = s1;
|
|
s1 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s1;
|
|
s1 = peg$FAILED;
|
|
}
|
|
if (s1 !== peg$FAILED) {
|
|
s0 = input.substring(s0, peg$currPos);
|
|
} else {
|
|
s0 = s1;
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$currPos;
|
|
if (input.charCodeAt(peg$currPos) === 92) {
|
|
s1 = peg$c29;
|
|
peg$currPos++;
|
|
} else {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e35); }
|
|
}
|
|
if (s1 !== peg$FAILED) {
|
|
s2 = peg$parseEscapeSequence();
|
|
if (s2 !== peg$FAILED) {
|
|
s0 = s2;
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$parseLineContinuation();
|
|
}
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseLineContinuation() {
|
|
var s0, s1, s2;
|
|
|
|
s0 = peg$currPos;
|
|
if (input.charCodeAt(peg$currPos) === 92) {
|
|
s1 = peg$c29;
|
|
peg$currPos++;
|
|
} else {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e35); }
|
|
}
|
|
if (s1 !== peg$FAILED) {
|
|
s2 = peg$parseLineTerminatorSequence();
|
|
if (s2 !== peg$FAILED) {
|
|
peg$savedPos = s0;
|
|
s0 = peg$f21();
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseEscapeSequence() {
|
|
var s0, s1, s2, s3;
|
|
|
|
s0 = peg$parseCharacterEscapeSequence();
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$currPos;
|
|
if (input.charCodeAt(peg$currPos) === 48) {
|
|
s1 = peg$c39;
|
|
peg$currPos++;
|
|
} else {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e48); }
|
|
}
|
|
if (s1 !== peg$FAILED) {
|
|
s2 = peg$currPos;
|
|
peg$silentFails++;
|
|
s3 = peg$parseDecimalDigit();
|
|
peg$silentFails--;
|
|
if (s3 === peg$FAILED) {
|
|
s2 = undefined;
|
|
} else {
|
|
peg$currPos = s2;
|
|
s2 = peg$FAILED;
|
|
}
|
|
if (s2 !== peg$FAILED) {
|
|
peg$savedPos = s0;
|
|
s0 = peg$f22();
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$parseHexEscapeSequence();
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$parseUnicodeEscapeSequence();
|
|
}
|
|
}
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseCharacterEscapeSequence() {
|
|
var s0;
|
|
|
|
s0 = peg$parseSingleEscapeCharacter();
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$parseNonEscapeCharacter();
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseSingleEscapeCharacter() {
|
|
var s0, s1;
|
|
|
|
if (input.charCodeAt(peg$currPos) === 39) {
|
|
s0 = peg$c34;
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e42); }
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
if (input.charCodeAt(peg$currPos) === 34) {
|
|
s0 = peg$c33;
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e41); }
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
if (input.charCodeAt(peg$currPos) === 92) {
|
|
s0 = peg$c29;
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e35); }
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$currPos;
|
|
if (input.charCodeAt(peg$currPos) === 98) {
|
|
s1 = peg$c40;
|
|
peg$currPos++;
|
|
} else {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e49); }
|
|
}
|
|
if (s1 !== peg$FAILED) {
|
|
peg$savedPos = s0;
|
|
s1 = peg$f23();
|
|
}
|
|
s0 = s1;
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$currPos;
|
|
if (input.charCodeAt(peg$currPos) === 102) {
|
|
s1 = peg$c41;
|
|
peg$currPos++;
|
|
} else {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e50); }
|
|
}
|
|
if (s1 !== peg$FAILED) {
|
|
peg$savedPos = s0;
|
|
s1 = peg$f24();
|
|
}
|
|
s0 = s1;
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$currPos;
|
|
if (input.charCodeAt(peg$currPos) === 110) {
|
|
s1 = peg$c42;
|
|
peg$currPos++;
|
|
} else {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e51); }
|
|
}
|
|
if (s1 !== peg$FAILED) {
|
|
peg$savedPos = s0;
|
|
s1 = peg$f25();
|
|
}
|
|
s0 = s1;
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$currPos;
|
|
if (input.charCodeAt(peg$currPos) === 114) {
|
|
s1 = peg$c43;
|
|
peg$currPos++;
|
|
} else {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e52); }
|
|
}
|
|
if (s1 !== peg$FAILED) {
|
|
peg$savedPos = s0;
|
|
s1 = peg$f26();
|
|
}
|
|
s0 = s1;
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$currPos;
|
|
if (input.charCodeAt(peg$currPos) === 116) {
|
|
s1 = peg$c44;
|
|
peg$currPos++;
|
|
} else {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e53); }
|
|
}
|
|
if (s1 !== peg$FAILED) {
|
|
peg$savedPos = s0;
|
|
s1 = peg$f27();
|
|
}
|
|
s0 = s1;
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$currPos;
|
|
if (input.charCodeAt(peg$currPos) === 118) {
|
|
s1 = peg$c45;
|
|
peg$currPos++;
|
|
} else {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e54); }
|
|
}
|
|
if (s1 !== peg$FAILED) {
|
|
peg$savedPos = s0;
|
|
s1 = peg$f28();
|
|
}
|
|
s0 = s1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseNonEscapeCharacter() {
|
|
var s0, s1, s2, s3;
|
|
|
|
s0 = peg$currPos;
|
|
s1 = peg$currPos;
|
|
s2 = peg$currPos;
|
|
peg$silentFails++;
|
|
s3 = peg$parseEscapeCharacter();
|
|
if (s3 === peg$FAILED) {
|
|
s3 = peg$parseLineTerminator();
|
|
}
|
|
peg$silentFails--;
|
|
if (s3 === peg$FAILED) {
|
|
s2 = undefined;
|
|
} else {
|
|
peg$currPos = s2;
|
|
s2 = peg$FAILED;
|
|
}
|
|
if (s2 !== peg$FAILED) {
|
|
s3 = peg$parseSourceCharacter();
|
|
if (s3 !== peg$FAILED) {
|
|
s2 = [s2, s3];
|
|
s1 = s2;
|
|
} else {
|
|
peg$currPos = s1;
|
|
s1 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s1;
|
|
s1 = peg$FAILED;
|
|
}
|
|
if (s1 !== peg$FAILED) {
|
|
s0 = input.substring(s0, peg$currPos);
|
|
} else {
|
|
s0 = s1;
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseEscapeCharacter() {
|
|
var s0;
|
|
|
|
s0 = peg$parseSingleEscapeCharacter();
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$parseDecimalDigit();
|
|
if (s0 === peg$FAILED) {
|
|
if (input.charCodeAt(peg$currPos) === 120) {
|
|
s0 = peg$c46;
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e55); }
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
if (input.charCodeAt(peg$currPos) === 117) {
|
|
s0 = peg$c47;
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e56); }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseHexEscapeSequence() {
|
|
var s0, s1, s2, s3, s4, s5;
|
|
|
|
s0 = peg$currPos;
|
|
if (input.charCodeAt(peg$currPos) === 120) {
|
|
s1 = peg$c46;
|
|
peg$currPos++;
|
|
} else {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e55); }
|
|
}
|
|
if (s1 !== peg$FAILED) {
|
|
s2 = peg$currPos;
|
|
s3 = peg$currPos;
|
|
s4 = peg$parseHexDigit();
|
|
if (s4 !== peg$FAILED) {
|
|
s5 = peg$parseHexDigit();
|
|
if (s5 !== peg$FAILED) {
|
|
s4 = [s4, s5];
|
|
s3 = s4;
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
if (s3 !== peg$FAILED) {
|
|
s2 = input.substring(s2, peg$currPos);
|
|
} else {
|
|
s2 = s3;
|
|
}
|
|
if (s2 !== peg$FAILED) {
|
|
peg$savedPos = s0;
|
|
s0 = peg$f29(s2);
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseUnicodeEscapeSequence() {
|
|
var s0, s1, s2, s3, s4, s5, s6, s7;
|
|
|
|
s0 = peg$currPos;
|
|
if (input.charCodeAt(peg$currPos) === 117) {
|
|
s1 = peg$c47;
|
|
peg$currPos++;
|
|
} else {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e56); }
|
|
}
|
|
if (s1 !== peg$FAILED) {
|
|
s2 = peg$currPos;
|
|
s3 = peg$currPos;
|
|
s4 = peg$parseHexDigit();
|
|
if (s4 !== peg$FAILED) {
|
|
s5 = peg$parseHexDigit();
|
|
if (s5 !== peg$FAILED) {
|
|
s6 = peg$parseHexDigit();
|
|
if (s6 !== peg$FAILED) {
|
|
s7 = peg$parseHexDigit();
|
|
if (s7 !== peg$FAILED) {
|
|
s4 = [s4, s5, s6, s7];
|
|
s3 = s4;
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
if (s3 !== peg$FAILED) {
|
|
s2 = input.substring(s2, peg$currPos);
|
|
} else {
|
|
s2 = s3;
|
|
}
|
|
if (s2 !== peg$FAILED) {
|
|
peg$savedPos = s0;
|
|
s0 = peg$f29(s2);
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseDecimalDigit() {
|
|
var s0;
|
|
|
|
if (peg$r1.test(input.charAt(peg$currPos))) {
|
|
s0 = input.charAt(peg$currPos);
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e57); }
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseHexDigit() {
|
|
var s0;
|
|
|
|
if (peg$r2.test(input.charAt(peg$currPos))) {
|
|
s0 = input.charAt(peg$currPos);
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e58); }
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseAnyMatcher() {
|
|
var s0, s1;
|
|
|
|
s0 = peg$currPos;
|
|
if (input.charCodeAt(peg$currPos) === 46) {
|
|
s1 = peg$c48;
|
|
peg$currPos++;
|
|
} else {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e59); }
|
|
}
|
|
if (s1 !== peg$FAILED) {
|
|
peg$savedPos = s0;
|
|
s1 = peg$f30();
|
|
}
|
|
s0 = s1;
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseCodeBlock() {
|
|
var s0, s1, s2, s3;
|
|
|
|
peg$silentFails++;
|
|
s0 = peg$currPos;
|
|
if (input.charCodeAt(peg$currPos) === 123) {
|
|
s1 = peg$c0;
|
|
peg$currPos++;
|
|
} else {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e0); }
|
|
}
|
|
if (s1 !== peg$FAILED) {
|
|
s2 = peg$parseBareCodeBlock();
|
|
if (input.charCodeAt(peg$currPos) === 125) {
|
|
s3 = peg$c1;
|
|
peg$currPos++;
|
|
} else {
|
|
s3 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e1); }
|
|
}
|
|
if (s3 !== peg$FAILED) {
|
|
s0 = s2;
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
peg$silentFails--;
|
|
if (s0 === peg$FAILED) {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e60); }
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseBareCodeBlock() {
|
|
var s0, s1;
|
|
|
|
s0 = peg$currPos;
|
|
s1 = peg$parseCode();
|
|
peg$savedPos = s0;
|
|
s1 = peg$f31(s1);
|
|
s0 = s1;
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseCode() {
|
|
var s0, s1, s2, s3, s4, s5;
|
|
|
|
s0 = peg$currPos;
|
|
s1 = [];
|
|
s2 = [];
|
|
s3 = peg$currPos;
|
|
s4 = peg$currPos;
|
|
peg$silentFails++;
|
|
if (peg$r3.test(input.charAt(peg$currPos))) {
|
|
s5 = input.charAt(peg$currPos);
|
|
peg$currPos++;
|
|
} else {
|
|
s5 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e61); }
|
|
}
|
|
peg$silentFails--;
|
|
if (s5 === peg$FAILED) {
|
|
s4 = undefined;
|
|
} else {
|
|
peg$currPos = s4;
|
|
s4 = peg$FAILED;
|
|
}
|
|
if (s4 !== peg$FAILED) {
|
|
s5 = peg$parseSourceCharacter();
|
|
if (s5 !== peg$FAILED) {
|
|
s4 = [s4, s5];
|
|
s3 = s4;
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
if (s3 !== peg$FAILED) {
|
|
while (s3 !== peg$FAILED) {
|
|
s2.push(s3);
|
|
s3 = peg$currPos;
|
|
s4 = peg$currPos;
|
|
peg$silentFails++;
|
|
if (peg$r3.test(input.charAt(peg$currPos))) {
|
|
s5 = input.charAt(peg$currPos);
|
|
peg$currPos++;
|
|
} else {
|
|
s5 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e61); }
|
|
}
|
|
peg$silentFails--;
|
|
if (s5 === peg$FAILED) {
|
|
s4 = undefined;
|
|
} else {
|
|
peg$currPos = s4;
|
|
s4 = peg$FAILED;
|
|
}
|
|
if (s4 !== peg$FAILED) {
|
|
s5 = peg$parseSourceCharacter();
|
|
if (s5 !== peg$FAILED) {
|
|
s4 = [s4, s5];
|
|
s3 = s4;
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
}
|
|
} else {
|
|
s2 = peg$FAILED;
|
|
}
|
|
if (s2 === peg$FAILED) {
|
|
s2 = peg$currPos;
|
|
if (input.charCodeAt(peg$currPos) === 123) {
|
|
s3 = peg$c0;
|
|
peg$currPos++;
|
|
} else {
|
|
s3 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e0); }
|
|
}
|
|
if (s3 !== peg$FAILED) {
|
|
s4 = peg$parseCode();
|
|
if (input.charCodeAt(peg$currPos) === 125) {
|
|
s5 = peg$c1;
|
|
peg$currPos++;
|
|
} else {
|
|
s5 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e1); }
|
|
}
|
|
if (s5 !== peg$FAILED) {
|
|
s3 = [s3, s4, s5];
|
|
s2 = s3;
|
|
} else {
|
|
peg$currPos = s2;
|
|
s2 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s2;
|
|
s2 = peg$FAILED;
|
|
}
|
|
}
|
|
while (s2 !== peg$FAILED) {
|
|
s1.push(s2);
|
|
s2 = [];
|
|
s3 = peg$currPos;
|
|
s4 = peg$currPos;
|
|
peg$silentFails++;
|
|
if (peg$r3.test(input.charAt(peg$currPos))) {
|
|
s5 = input.charAt(peg$currPos);
|
|
peg$currPos++;
|
|
} else {
|
|
s5 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e61); }
|
|
}
|
|
peg$silentFails--;
|
|
if (s5 === peg$FAILED) {
|
|
s4 = undefined;
|
|
} else {
|
|
peg$currPos = s4;
|
|
s4 = peg$FAILED;
|
|
}
|
|
if (s4 !== peg$FAILED) {
|
|
s5 = peg$parseSourceCharacter();
|
|
if (s5 !== peg$FAILED) {
|
|
s4 = [s4, s5];
|
|
s3 = s4;
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
if (s3 !== peg$FAILED) {
|
|
while (s3 !== peg$FAILED) {
|
|
s2.push(s3);
|
|
s3 = peg$currPos;
|
|
s4 = peg$currPos;
|
|
peg$silentFails++;
|
|
if (peg$r3.test(input.charAt(peg$currPos))) {
|
|
s5 = input.charAt(peg$currPos);
|
|
peg$currPos++;
|
|
} else {
|
|
s5 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e61); }
|
|
}
|
|
peg$silentFails--;
|
|
if (s5 === peg$FAILED) {
|
|
s4 = undefined;
|
|
} else {
|
|
peg$currPos = s4;
|
|
s4 = peg$FAILED;
|
|
}
|
|
if (s4 !== peg$FAILED) {
|
|
s5 = peg$parseSourceCharacter();
|
|
if (s5 !== peg$FAILED) {
|
|
s4 = [s4, s5];
|
|
s3 = s4;
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s3;
|
|
s3 = peg$FAILED;
|
|
}
|
|
}
|
|
} else {
|
|
s2 = peg$FAILED;
|
|
}
|
|
if (s2 === peg$FAILED) {
|
|
s2 = peg$currPos;
|
|
if (input.charCodeAt(peg$currPos) === 123) {
|
|
s3 = peg$c0;
|
|
peg$currPos++;
|
|
} else {
|
|
s3 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e0); }
|
|
}
|
|
if (s3 !== peg$FAILED) {
|
|
s4 = peg$parseCode();
|
|
if (input.charCodeAt(peg$currPos) === 125) {
|
|
s5 = peg$c1;
|
|
peg$currPos++;
|
|
} else {
|
|
s5 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e1); }
|
|
}
|
|
if (s5 !== peg$FAILED) {
|
|
s3 = [s3, s4, s5];
|
|
s2 = s3;
|
|
} else {
|
|
peg$currPos = s2;
|
|
s2 = peg$FAILED;
|
|
}
|
|
} else {
|
|
peg$currPos = s2;
|
|
s2 = peg$FAILED;
|
|
}
|
|
}
|
|
}
|
|
s0 = input.substring(s0, peg$currPos);
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseLl() {
|
|
var s0;
|
|
|
|
if (peg$r4.test(input.charAt(peg$currPos))) {
|
|
s0 = input.charAt(peg$currPos);
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e62); }
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseLm() {
|
|
var s0;
|
|
|
|
if (peg$r5.test(input.charAt(peg$currPos))) {
|
|
s0 = input.charAt(peg$currPos);
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e63); }
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseLo() {
|
|
var s0;
|
|
|
|
if (peg$r6.test(input.charAt(peg$currPos))) {
|
|
s0 = input.charAt(peg$currPos);
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e64); }
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseLt() {
|
|
var s0;
|
|
|
|
if (peg$r7.test(input.charAt(peg$currPos))) {
|
|
s0 = input.charAt(peg$currPos);
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e65); }
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseLu() {
|
|
var s0;
|
|
|
|
if (peg$r8.test(input.charAt(peg$currPos))) {
|
|
s0 = input.charAt(peg$currPos);
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e66); }
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseMc() {
|
|
var s0;
|
|
|
|
if (peg$r9.test(input.charAt(peg$currPos))) {
|
|
s0 = input.charAt(peg$currPos);
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e67); }
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseMn() {
|
|
var s0;
|
|
|
|
if (peg$r10.test(input.charAt(peg$currPos))) {
|
|
s0 = input.charAt(peg$currPos);
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e68); }
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseNd() {
|
|
var s0;
|
|
|
|
if (peg$r11.test(input.charAt(peg$currPos))) {
|
|
s0 = input.charAt(peg$currPos);
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e69); }
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseNl() {
|
|
var s0;
|
|
|
|
if (peg$r12.test(input.charAt(peg$currPos))) {
|
|
s0 = input.charAt(peg$currPos);
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e70); }
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parsePc() {
|
|
var s0;
|
|
|
|
if (peg$r13.test(input.charAt(peg$currPos))) {
|
|
s0 = input.charAt(peg$currPos);
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e71); }
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseZs() {
|
|
var s0;
|
|
|
|
if (peg$r14.test(input.charAt(peg$currPos))) {
|
|
s0 = input.charAt(peg$currPos);
|
|
peg$currPos++;
|
|
} else {
|
|
s0 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e72); }
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parse__() {
|
|
var s0, s1;
|
|
|
|
s0 = [];
|
|
s1 = peg$parseWhiteSpace();
|
|
if (s1 === peg$FAILED) {
|
|
s1 = peg$parseLineTerminatorSequence();
|
|
if (s1 === peg$FAILED) {
|
|
s1 = peg$parseComment();
|
|
}
|
|
}
|
|
while (s1 !== peg$FAILED) {
|
|
s0.push(s1);
|
|
s1 = peg$parseWhiteSpace();
|
|
if (s1 === peg$FAILED) {
|
|
s1 = peg$parseLineTerminatorSequence();
|
|
if (s1 === peg$FAILED) {
|
|
s1 = peg$parseComment();
|
|
}
|
|
}
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parse_() {
|
|
var s0, s1;
|
|
|
|
s0 = [];
|
|
s1 = peg$parseWhiteSpace();
|
|
if (s1 === peg$FAILED) {
|
|
s1 = peg$parseMultiLineCommentNoLineTerminator();
|
|
}
|
|
while (s1 !== peg$FAILED) {
|
|
s0.push(s1);
|
|
s1 = peg$parseWhiteSpace();
|
|
if (s1 === peg$FAILED) {
|
|
s1 = peg$parseMultiLineCommentNoLineTerminator();
|
|
}
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseEOS() {
|
|
var s0, s1, s2, s3;
|
|
|
|
s0 = peg$currPos;
|
|
s1 = peg$parse__();
|
|
if (input.charCodeAt(peg$currPos) === 59) {
|
|
s2 = peg$c49;
|
|
peg$currPos++;
|
|
} else {
|
|
s2 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e73); }
|
|
}
|
|
if (s2 !== peg$FAILED) {
|
|
s1 = [s1, s2];
|
|
s0 = s1;
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$currPos;
|
|
s1 = peg$parse_();
|
|
s2 = peg$parseSingleLineComment();
|
|
if (s2 === peg$FAILED) {
|
|
s2 = null;
|
|
}
|
|
s3 = peg$parseLineTerminatorSequence();
|
|
if (s3 !== peg$FAILED) {
|
|
s1 = [s1, s2, s3];
|
|
s0 = s1;
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
if (s0 === peg$FAILED) {
|
|
s0 = peg$currPos;
|
|
s1 = peg$parse__();
|
|
s2 = peg$parseEOF();
|
|
if (s2 !== peg$FAILED) {
|
|
s1 = [s1, s2];
|
|
s0 = s1;
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
}
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
function peg$parseEOF() {
|
|
var s0, s1;
|
|
|
|
s0 = peg$currPos;
|
|
peg$silentFails++;
|
|
if (input.length > peg$currPos) {
|
|
s1 = input.charAt(peg$currPos);
|
|
peg$currPos++;
|
|
} else {
|
|
s1 = peg$FAILED;
|
|
if (peg$silentFails === 0) { peg$fail(peg$e14); }
|
|
}
|
|
peg$silentFails--;
|
|
if (s1 === peg$FAILED) {
|
|
s0 = undefined;
|
|
} else {
|
|
peg$currPos = s0;
|
|
s0 = peg$FAILED;
|
|
}
|
|
|
|
return s0;
|
|
}
|
|
|
|
|
|
// Cannot use Set here because of native IE support.
|
|
const reservedWords = options.reservedWords || [];
|
|
|
|
|
|
peg$result = peg$startRuleFunction();
|
|
|
|
if (peg$result !== peg$FAILED && peg$currPos === input.length) {
|
|
return peg$result;
|
|
} else {
|
|
if (peg$result !== peg$FAILED && peg$currPos < input.length) {
|
|
peg$fail(peg$endExpectation());
|
|
}
|
|
|
|
throw peg$buildStructuredError(
|
|
peg$maxFailExpected,
|
|
peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null,
|
|
peg$maxFailPos < input.length
|
|
? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1)
|
|
: peg$computeLocation(peg$maxFailPos, peg$maxFailPos)
|
|
);
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
SyntaxError: peg$SyntaxError,
|
|
parse: peg$parse
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 4193:
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
"use strict";
|
|
|
|
|
|
const GrammarError = __webpack_require__(94297);
|
|
const compiler = __webpack_require__(79203);
|
|
const parser = __webpack_require__(80170);
|
|
const VERSION = __webpack_require__(80244);
|
|
|
|
const RESERVED_WORDS = [
|
|
// Reserved keywords as of ECMAScript 2015
|
|
"break",
|
|
"case",
|
|
"catch",
|
|
"class",
|
|
"const",
|
|
"continue",
|
|
"debugger",
|
|
"default",
|
|
"delete",
|
|
"do",
|
|
"else",
|
|
"export",
|
|
"extends",
|
|
"finally",
|
|
"for",
|
|
"function",
|
|
"if",
|
|
"import",
|
|
"in",
|
|
"instanceof",
|
|
"new",
|
|
"return",
|
|
"super",
|
|
"switch",
|
|
"this",
|
|
"throw",
|
|
"try",
|
|
"typeof",
|
|
"var",
|
|
"void",
|
|
"while",
|
|
"with",
|
|
// "yield", // encountered twice on the web page
|
|
|
|
// Special constants
|
|
"null",
|
|
"true",
|
|
"false",
|
|
|
|
// These are always reserved:
|
|
"enum",
|
|
|
|
// The following are only reserved when they are found in strict mode code
|
|
// Peggy generates code in strictly mode, so it applicable to it
|
|
"implements",
|
|
"interface",
|
|
"let",
|
|
"package",
|
|
"private",
|
|
"protected",
|
|
"public",
|
|
"static",
|
|
"yield",
|
|
|
|
// The following are only reserved when they are found in module code:
|
|
"await"
|
|
];
|
|
|
|
const peg = {
|
|
// Peggy version (filled in by /tools/release).
|
|
VERSION,
|
|
/**
|
|
* Default list of reserved words. Contains list of currently and future
|
|
* JavaScript (ECMAScript 2015) reserved words.
|
|
*
|
|
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#reserved_keywords_as_of_ecmascript_2015
|
|
*/
|
|
RESERVED_WORDS,
|
|
GrammarError,
|
|
parser,
|
|
compiler,
|
|
|
|
// Generates a parser from a specified grammar and returns it.
|
|
//
|
|
// The grammar must be a string in the format described by the meta-grammar in
|
|
// the parser.pegjs file.
|
|
//
|
|
// Throws |peg.parser.SyntaxError| if the grammar contains a syntax error or
|
|
// |peg.GrammarError| if it contains a semantic error. Note that not all
|
|
// errors are detected during the generation and some may protrude to the
|
|
// generated parser and cause its malfunction.
|
|
generate(grammar, options) {
|
|
options = options !== undefined ? options : {};
|
|
|
|
function copyPasses(passes) {
|
|
const converted = {};
|
|
Object.keys(passes).forEach(stage => {
|
|
converted[stage] = passes[stage].slice();
|
|
});
|
|
|
|
return converted;
|
|
}
|
|
|
|
const plugins = "plugins" in options ? options.plugins : [];
|
|
const config = {
|
|
parser: peg.parser,
|
|
passes: copyPasses(peg.compiler.passes),
|
|
reservedWords: peg.RESERVED_WORDS.slice(),
|
|
};
|
|
|
|
plugins.forEach(p => { p.use(config, options); });
|
|
|
|
return peg.compiler.compile(
|
|
config.parser.parse(grammar, {
|
|
grammarSource: options.grammarSource,
|
|
reservedWords: config.reservedWords,
|
|
}),
|
|
config.passes,
|
|
options
|
|
);
|
|
}
|
|
};
|
|
|
|
module.exports = peg;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 80244:
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
|
|
// This file is generated.
|
|
// Do not edit it! Your work will be overwritten.
|
|
//
|
|
// Instead, please look at ./tools/set_version.js
|
|
|
|
|
|
|
|
module.exports = "1.2.0";
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 6391:
|
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
|
|
(function() {
|
|
var MarkedYAMLError, events, nodes;
|
|
|
|
events = __webpack_require__(35063);
|
|
|
|
({MarkedYAMLError} = __webpack_require__(45372));
|
|
|
|
nodes = __webpack_require__(96914);
|
|
|
|
/*
|
|
Thrown for errors encountered during composing.
|
|
*/
|
|
this.ComposerError = class ComposerError extends MarkedYAMLError {};
|
|
|
|
/*
|
|
The composer class handles the construction of representation trees from events.
|
|
|
|
This uses the methods from {Parser} to process the event stream, and provides a similar stream-like
|
|
interface to representation trees via {Composer#check_node}, {Composer#get_node}, and
|
|
{Composer#get_single_node}.
|
|
*/
|
|
this.Composer = (function() {
|
|
var ctor;
|
|
|
|
class Composer {
|
|
constructor() {
|
|
return ctor.apply(this, arguments);
|
|
}
|
|
|
|
/*
|
|
Initialise a `Composer` instance.
|
|
*/
|
|
initialise() {
|
|
// @property {Object} A mapping from anchor names to nodes.
|
|
return this.anchors = {};
|
|
}
|
|
|
|
/*
|
|
Checks if a document can be composed from the event stream.
|
|
|
|
So long as the event stream hasn't ended (no [StreamEndEvent]), another document can be composed.
|
|
|
|
@return {Boolean} True if a document can be composed, false otherwise.
|
|
*/
|
|
check_node() {
|
|
if (this.check_event(events.StreamStartEvent)) {
|
|
// Drop the STREAM-START event.
|
|
this.get_event();
|
|
}
|
|
// Are there more documents available?
|
|
return !this.check_event(events.StreamEndEvent);
|
|
}
|
|
|
|
/*
|
|
Compose a document from the remaining event stream.
|
|
|
|
{Composer#check_node} must be called before calling this method.
|
|
|
|
@return {Node} The next document in the stream. Returns `undefined` if the event stream has ended.
|
|
*/
|
|
get_node() {
|
|
if (!this.check_event(events.StreamEndEvent)) {
|
|
return this.compose_document();
|
|
}
|
|
}
|
|
|
|
/*
|
|
Compose a single document from the entire event stream.
|
|
|
|
@throw {ComposerError} if there's more than one document is in the stream.
|
|
|
|
@return {Node} The single document in the stream.
|
|
*/
|
|
get_single_node() {
|
|
var document, event;
|
|
// Drop the STREAM-START event.
|
|
this.get_event();
|
|
// Compose a document if the stream is not empty.
|
|
document = null;
|
|
if (!this.check_event(events.StreamEndEvent)) {
|
|
document = this.compose_document();
|
|
}
|
|
// Ensure that the stream contains no more documents.
|
|
if (!this.check_event(events.StreamEndEvent)) {
|
|
event = this.get_event();
|
|
throw new exports.ComposerError('expected a single document in the stream', document.start_mark, 'but found another document', event.start_mark);
|
|
}
|
|
// Drop the STREAM-END event.
|
|
this.get_event();
|
|
return document;
|
|
}
|
|
|
|
/*
|
|
Compose a document node from the event stream.
|
|
|
|
A 'document' node is any single {Node} subclass. {DocumentStart} and {DocumentEnd} events delimit
|
|
the events used for composition.
|
|
|
|
@private
|
|
|
|
@return {Node} The document node.
|
|
*/
|
|
compose_document() {
|
|
var node;
|
|
// Drop the DOCUMENT-START event.
|
|
this.get_event();
|
|
// Compose the root node.
|
|
node = this.compose_node();
|
|
// Drop the DOCUMENT-END node.
|
|
this.get_event();
|
|
// Reset the anchors
|
|
this.anchors = {};
|
|
return node;
|
|
}
|
|
|
|
/*
|
|
Compose a node from the event stream.
|
|
|
|
Composes a {ScalarNode}, {SequenceNode}, or {MappingNode} from the event stream, depending on the
|
|
first event encountered ({ScalarEvent}, {SequenceStartEvent}, or {MappingStartEvent}
|
|
respectively).
|
|
|
|
@private
|
|
|
|
@param parent {Node} The parent of the new node.
|
|
@param index {Number} The index of the new node within the parent's children.
|
|
@throw {ComposerError} if an alias is encountered for an undefined anchor.
|
|
@throw {ComposerError} if a duplicate anchor is envountered.
|
|
@return {Node} The composed node.
|
|
*/
|
|
compose_node(parent, index) {
|
|
var anchor, event, node;
|
|
if (this.check_event(events.AliasEvent)) {
|
|
event = this.get_event();
|
|
anchor = event.anchor;
|
|
if (!(anchor in this.anchors)) {
|
|
throw new exports.ComposerError(null, null, `found undefined alias ${anchor}`, event.start_mark);
|
|
}
|
|
return this.anchors[anchor];
|
|
}
|
|
event = this.peek_event();
|
|
anchor = event.anchor;
|
|
if (anchor !== null && anchor in this.anchors) {
|
|
throw new exports.ComposerError(`found duplicate anchor ${anchor}; first occurence`, this.anchors[anchor].start_mark, 'second occurrence', event.start_mark);
|
|
}
|
|
this.descend_resolver(parent, index);
|
|
if (this.check_event(events.ScalarEvent)) {
|
|
node = this.compose_scalar_node(anchor);
|
|
} else if (this.check_event(events.SequenceStartEvent)) {
|
|
node = this.compose_sequence_node(anchor);
|
|
} else if (this.check_event(events.MappingStartEvent)) {
|
|
node = this.compose_mapping_node(anchor);
|
|
}
|
|
this.ascend_resolver();
|
|
return node;
|
|
}
|
|
|
|
/*
|
|
Compose a {ScalarNode} from the event stream.
|
|
|
|
@private
|
|
|
|
@param anchor {String} The anchor name for the node (if any).
|
|
@return {ScalarNode} The node composed from a {ScalarEvent}.
|
|
*/
|
|
compose_scalar_node(anchor) {
|
|
var event, node, tag;
|
|
event = this.get_event();
|
|
tag = event.tag;
|
|
if (tag === null || tag === '!') {
|
|
tag = this.resolve(nodes.ScalarNode, event.value, event.implicit);
|
|
}
|
|
node = new nodes.ScalarNode(tag, event.value, event.start_mark, event.end_mark, event.style);
|
|
if (anchor !== null) {
|
|
this.anchors[anchor] = node;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
/*
|
|
Compose a {SequenceNode} from the event stream.
|
|
|
|
The contents of the node are composed from events between a {SequenceStartEvent} and a
|
|
{SequenceEndEvent}.
|
|
|
|
@private
|
|
|
|
@param anchor {String} The anchor name for the node (if any).
|
|
@return {SequenceNode} The composed node.
|
|
*/
|
|
compose_sequence_node(anchor) {
|
|
var end_event, index, node, start_event, tag;
|
|
start_event = this.get_event();
|
|
tag = start_event.tag;
|
|
if (tag === null || tag === '!') {
|
|
tag = this.resolve(nodes.SequenceNode, null, start_event.implicit);
|
|
}
|
|
node = new nodes.SequenceNode(tag, [], start_event.start_mark, null, start_event.flow_style);
|
|
if (anchor !== null) {
|
|
this.anchors[anchor] = node;
|
|
}
|
|
index = 0;
|
|
while (!this.check_event(events.SequenceEndEvent)) {
|
|
node.value.push(this.compose_node(node, index));
|
|
index++;
|
|
}
|
|
end_event = this.get_event();
|
|
node.end_mark = end_event.end_mark;
|
|
return node;
|
|
}
|
|
|
|
/*
|
|
Compose a {MappingNode} from the event stream.
|
|
|
|
The contents of the node are composed from events between a {MappingStartEvent} and a
|
|
{MappingEndEvent}.
|
|
|
|
@private
|
|
|
|
@param anchor {String} The anchor name for the node (if any).
|
|
@return {MappingNode} The composed node.
|
|
*/
|
|
compose_mapping_node(anchor) {
|
|
var end_event, item_key, item_value, node, start_event, tag;
|
|
start_event = this.get_event();
|
|
tag = start_event.tag;
|
|
if (tag === null || tag === '!') {
|
|
tag = this.resolve(nodes.MappingNode, null, start_event.implicit);
|
|
}
|
|
node = new nodes.MappingNode(tag, [], start_event.start_mark, null, start_event.flow_style);
|
|
if (anchor !== null) {
|
|
this.anchors[anchor] = node;
|
|
}
|
|
while (!this.check_event(events.MappingEndEvent)) {
|
|
item_key = this.compose_node(node);
|
|
item_value = this.compose_node(node, item_key);
|
|
node.value.push([item_key, item_value]);
|
|
}
|
|
end_event = this.get_event();
|
|
node.end_mark = end_event.end_mark;
|
|
return node;
|
|
}
|
|
|
|
};
|
|
|
|
ctor = Composer.prototype.initialise;
|
|
|
|
return Composer;
|
|
|
|
}).call(this);
|
|
|
|
}).call(this);
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 51574:
|
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
|
|
(function() {
|
|
var MarkedYAMLError, nodes, util,
|
|
indexOf = [].indexOf;
|
|
|
|
({MarkedYAMLError} = __webpack_require__(45372));
|
|
|
|
nodes = __webpack_require__(96914);
|
|
|
|
util = __webpack_require__(23823);
|
|
|
|
/*
|
|
Thrown for errors encountered during construction.
|
|
*/
|
|
this.ConstructorError = class ConstructorError extends MarkedYAMLError {};
|
|
|
|
/*
|
|
The constructor class handles the construction of Javascript objects from representation trees
|
|
({Node}s).
|
|
|
|
This uses the methods from {Composer} to process the representation stream, and provides a similar
|
|
stream-like interface to Javascript objects via {BaseConstructor#check_node},
|
|
{BaseConstructor#get_node}, and {BaseConstructor#get_single_node}.
|
|
*/
|
|
this.BaseConstructor = (function() {
|
|
var ctor;
|
|
|
|
class BaseConstructor {
|
|
constructor() {
|
|
return ctor.apply(this, arguments);
|
|
}
|
|
|
|
/*
|
|
Add a constructor function for a specific tag.
|
|
|
|
The constructor will be used to turn {Node Nodes} with the given tag into a Javascript object.
|
|
|
|
@param tag {String} The tag for which the constructor should apply.
|
|
@param constructor {Function<Node,any>} A function that turns a {Node} with the given tag into a
|
|
Javascript object.
|
|
@return {Function<Node,Any>} Returns the supplied `constructor`.
|
|
*/
|
|
static add_constructor(tag, constructor) {
|
|
if (!this.prototype.hasOwnProperty('yaml_constructors')) {
|
|
this.prototype.yaml_constructors = util.extend({}, this.prototype.yaml_constructors);
|
|
}
|
|
return this.prototype.yaml_constructors[tag] = constructor;
|
|
}
|
|
|
|
/*
|
|
Add a constructor function for a tag prefix.
|
|
|
|
The constructor will be used to turn {Node Nodes} with the given tag prefix into a Javascript
|
|
object.
|
|
|
|
@param tag_prefix {String} The tag prefix for which the constructor should apply.
|
|
@param multi_constructor {Function<Node,any>} A function that turns a {Node} with the given tag
|
|
prefix into a Javascript object.
|
|
@return {Function<Node,Any>} Returns the supplied `multi_constructor`.
|
|
*/
|
|
static add_multi_constructor(tag_prefix, multi_constructor) {
|
|
if (!this.prototype.hasOwnProperty('yaml_multi_constructors')) {
|
|
this.prototype.yaml_multi_constructors = util.extend({}, this.prototype.yaml_multi_constructors);
|
|
}
|
|
return this.prototype.yaml_multi_constructors[tag_prefix] = multi_constructor;
|
|
}
|
|
|
|
/*
|
|
Initialise a new instance.
|
|
*/
|
|
initialise() {
|
|
// @param {Object} A map from {Node#unique_id} to the constructed Javascript object for the node.
|
|
this.constructed_objects = {};
|
|
// @param {Array<String>} An array of {Node#unique_id}s that are being constructed.
|
|
this.constructing_nodes = [];
|
|
// @param {Function<any>} An array of functions to be exectied after docmuent construction.
|
|
return this.deferred_constructors = [];
|
|
}
|
|
|
|
/*
|
|
Checks if a document can be constructed from the representation stream.
|
|
|
|
So long as the representation stream hasn't ended, another document can be constructed.
|
|
|
|
@return {Boolean} True if a document can be constructed, false otherwise.
|
|
*/
|
|
check_data() {
|
|
return this.check_node();
|
|
}
|
|
|
|
/*
|
|
Construct a document from the remaining representation stream.
|
|
|
|
{Constructor#check_data} must be called before calling this method.
|
|
|
|
@return {any} The next document in the stream. Returns `undefined` if the stream has ended.
|
|
*/
|
|
get_data() {
|
|
if (this.check_node()) {
|
|
return this.construct_document(this.get_node());
|
|
}
|
|
}
|
|
|
|
/*
|
|
Construct a single document from the entire representation stream.
|
|
|
|
@throw {ComposerError} if there's more than one document is in the stream.
|
|
|
|
@return {Node} The single document in the stream.
|
|
*/
|
|
get_single_data() {
|
|
var node;
|
|
node = this.get_single_node();
|
|
if (node != null) {
|
|
return this.construct_document(node);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/*
|
|
Construct a document node
|
|
|
|
@private
|
|
*/
|
|
construct_document(node) {
|
|
var data;
|
|
data = this.construct_object(node);
|
|
while (!util.is_empty(this.deferred_constructors)) {
|
|
this.deferred_constructors.pop()();
|
|
}
|
|
return data;
|
|
}
|
|
|
|
defer(f) {
|
|
return this.deferred_constructors.push(f);
|
|
}
|
|
|
|
construct_object(node) {
|
|
var constructor, object, ref, tag_prefix, tag_suffix;
|
|
if (node.unique_id in this.constructed_objects) {
|
|
return this.constructed_objects[node.unique_id];
|
|
}
|
|
if (ref = node.unique_id, indexOf.call(this.constructing_nodes, ref) >= 0) {
|
|
throw new exports.ConstructorError(null, null, 'found unconstructable recursive node', node.start_mark);
|
|
}
|
|
this.constructing_nodes.push(node.unique_id);
|
|
constructor = null;
|
|
tag_suffix = null;
|
|
if (node.tag in this.yaml_constructors) {
|
|
constructor = this.yaml_constructors[node.tag];
|
|
} else {
|
|
for (tag_prefix in this.yaml_multi_constructors) {
|
|
if (node.tag.indexOf(tag_prefix === 0)) {
|
|
tag_suffix = node.tag.slice(tag_prefix.length);
|
|
constructor = this.yaml_multi_constructors[tag_prefix];
|
|
break;
|
|
}
|
|
}
|
|
if (constructor == null) {
|
|
if (null in this.yaml_multi_constructors) {
|
|
tag_suffix = node.tag;
|
|
constructor = this.yaml_multi_constructors[null];
|
|
} else if (null in this.yaml_constructors) {
|
|
constructor = this.yaml_constructors[null];
|
|
} else if (node instanceof nodes.ScalarNode) {
|
|
constructor = this.construct_scalar;
|
|
} else if (node instanceof nodes.SequenceNode) {
|
|
constructor = this.construct_sequence;
|
|
} else if (node instanceof nodes.MappingNode) {
|
|
constructor = this.construct_mapping;
|
|
}
|
|
}
|
|
}
|
|
object = constructor.call(this, tag_suffix != null ? tag_suffix : node, node);
|
|
this.constructed_objects[node.unique_id] = object;
|
|
this.constructing_nodes.pop();
|
|
return object;
|
|
}
|
|
|
|
construct_scalar(node) {
|
|
if (!(node instanceof nodes.ScalarNode)) {
|
|
throw new exports.ConstructorError(null, null, `expected a scalar node but found ${node.id}`, node.start_mark);
|
|
}
|
|
return node.value;
|
|
}
|
|
|
|
construct_sequence(node) {
|
|
var child, i, len, ref, results;
|
|
if (!(node instanceof nodes.SequenceNode)) {
|
|
throw new exports.ConstructorError(null, null, `expected a sequence node but found ${node.id}`, node.start_mark);
|
|
}
|
|
ref = node.value;
|
|
results = [];
|
|
for (i = 0, len = ref.length; i < len; i++) {
|
|
child = ref[i];
|
|
results.push(this.construct_object(child));
|
|
}
|
|
return results;
|
|
}
|
|
|
|
construct_mapping(node) {
|
|
var i, key, key_node, len, mapping, ref, value, value_node;
|
|
if (!(node instanceof nodes.MappingNode)) {
|
|
throw new ConstructorError(null, null, `expected a mapping node but found ${node.id}`, node.start_mark);
|
|
}
|
|
mapping = {};
|
|
ref = node.value;
|
|
for (i = 0, len = ref.length; i < len; i++) {
|
|
[key_node, value_node] = ref[i];
|
|
key = this.construct_object(key_node);
|
|
if (typeof key === 'object') {
|
|
throw new exports.ConstructorError('while constructing a mapping', node.start_mark, 'found unhashable key', key_node.start_mark);
|
|
}
|
|
value = this.construct_object(value_node);
|
|
mapping[key] = value;
|
|
}
|
|
return mapping;
|
|
}
|
|
|
|
construct_pairs(node) {
|
|
var i, key, key_node, len, pairs, ref, value, value_node;
|
|
if (!(node instanceof nodes.MappingNode)) {
|
|
throw new exports.ConstructorError(null, null, `expected a mapping node but found ${node.id}`, node.start_mark);
|
|
}
|
|
pairs = [];
|
|
ref = node.value;
|
|
for (i = 0, len = ref.length; i < len; i++) {
|
|
[key_node, value_node] = ref[i];
|
|
key = this.construct_object(key_node);
|
|
value = this.construct_object(value_node);
|
|
pairs.push([key, value]);
|
|
}
|
|
return pairs;
|
|
}
|
|
|
|
};
|
|
|
|
/*
|
|
@property {Object} A map from a YAML tag to a constructor function for data with that tag.
|
|
@private
|
|
*/
|
|
BaseConstructor.prototype.yaml_constructors = {};
|
|
|
|
/*
|
|
@property {Object} A map from a YAML tag prefix to a constructor function for data with that tag
|
|
prefix.
|
|
@private
|
|
*/
|
|
BaseConstructor.prototype.yaml_multi_constructors = {};
|
|
|
|
ctor = BaseConstructor.prototype.initialise;
|
|
|
|
return BaseConstructor;
|
|
|
|
}).call(this);
|
|
|
|
this.Constructor = (function() {
|
|
var BOOL_VALUES, TIMESTAMP_PARTS, TIMESTAMP_REGEX;
|
|
|
|
class Constructor extends this.BaseConstructor {
|
|
construct_scalar(node) {
|
|
var i, key_node, len, ref, value_node;
|
|
if (node instanceof nodes.MappingNode) {
|
|
ref = node.value;
|
|
for (i = 0, len = ref.length; i < len; i++) {
|
|
[key_node, value_node] = ref[i];
|
|
if (key_node.tag === 'tag:yaml.org,2002:value') {
|
|
return this.construct_scalar(value_node);
|
|
}
|
|
}
|
|
}
|
|
return super.construct_scalar(node);
|
|
}
|
|
|
|
flatten_mapping(node) {
|
|
var i, index, j, key_node, len, len1, merge, ref, submerge, subnode, value, value_node;
|
|
merge = [];
|
|
index = 0;
|
|
while (index < node.value.length) {
|
|
[key_node, value_node] = node.value[index];
|
|
if (key_node.tag === 'tag:yaml.org,2002:merge') {
|
|
node.value.splice(index, 1);
|
|
//delete node.value[index]
|
|
if (value_node instanceof nodes.MappingNode) {
|
|
this.flatten_mapping(value_node);
|
|
merge = merge.concat(value_node.value);
|
|
} else if (value_node instanceof nodes.SequenceNode) {
|
|
submerge = [];
|
|
ref = value_node.value;
|
|
for (i = 0, len = ref.length; i < len; i++) {
|
|
subnode = ref[i];
|
|
if (!(subnode instanceof nodes.MappingNode)) {
|
|
throw new exports.ConstructorError('while constructing a mapping', node.start_mark, `expected a mapping for merging, but found ${subnode.id}`, subnode.start_mark);
|
|
}
|
|
this.flatten_mapping(subnode);
|
|
submerge.push(subnode.value);
|
|
}
|
|
submerge.reverse();
|
|
for (j = 0, len1 = submerge.length; j < len1; j++) {
|
|
value = submerge[j];
|
|
merge = merge.concat(value);
|
|
}
|
|
} else {
|
|
throw new exports.ConstructorError('while constructing a mapping', node.start_mark, `expected a mapping or list of mappings for merging but found ${value_node.id}`, value_node.start_mark);
|
|
}
|
|
} else if (key_node.tag === 'tag:yaml.org,2002:value') {
|
|
key_node.tag = 'tag:yaml.org,2002:str';
|
|
index++;
|
|
} else {
|
|
index++;
|
|
}
|
|
}
|
|
if (merge.length) {
|
|
return node.value = merge.concat(node.value);
|
|
}
|
|
}
|
|
|
|
construct_mapping(node) {
|
|
if (node instanceof nodes.MappingNode) {
|
|
this.flatten_mapping(node);
|
|
}
|
|
return super.construct_mapping(node);
|
|
}
|
|
|
|
construct_yaml_null(node) {
|
|
this.construct_scalar(node);
|
|
return null;
|
|
}
|
|
|
|
construct_yaml_bool(node) {
|
|
var value;
|
|
value = this.construct_scalar(node);
|
|
return BOOL_VALUES[value.toLowerCase()];
|
|
}
|
|
|
|
construct_yaml_int(node) {
|
|
var base, digit, digits, i, len, part, ref, sign, value;
|
|
value = this.construct_scalar(node);
|
|
value = value.replace(/_/g, '');
|
|
sign = value[0] === '-' ? -1 : 1;
|
|
if (ref = value[0], indexOf.call('+-', ref) >= 0) {
|
|
value = value.slice(1);
|
|
}
|
|
if (value === '0') {
|
|
return 0;
|
|
} else if (value.indexOf('0b') === 0) {
|
|
return sign * parseInt(value.slice(2), 2);
|
|
} else if (value.indexOf('0x') === 0) {
|
|
return sign * parseInt(value.slice(2), 16);
|
|
} else if (value.indexOf('0o') === 0) {
|
|
return sign * parseInt(value.slice(2), 8);
|
|
} else if (value[0] === '0') {
|
|
return sign * parseInt(value, 8);
|
|
} else if (indexOf.call(value, ':') >= 0) {
|
|
digits = (function() {
|
|
var i, len, ref1, results;
|
|
ref1 = value.split(/:/g);
|
|
results = [];
|
|
for (i = 0, len = ref1.length; i < len; i++) {
|
|
part = ref1[i];
|
|
results.push(parseInt(part));
|
|
}
|
|
return results;
|
|
})();
|
|
digits.reverse();
|
|
base = 1;
|
|
value = 0;
|
|
for (i = 0, len = digits.length; i < len; i++) {
|
|
digit = digits[i];
|
|
value += digit * base;
|
|
base *= 60;
|
|
}
|
|
return sign * value;
|
|
} else {
|
|
return sign * parseInt(value);
|
|
}
|
|
}
|
|
|
|
construct_yaml_float(node) {
|
|
var base, digit, digits, i, len, part, ref, sign, value;
|
|
value = this.construct_scalar(node);
|
|
value = value.replace(/_/g, '').toLowerCase();
|
|
sign = value[0] === '-' ? -1 : 1;
|
|
if (ref = value[0], indexOf.call('+-', ref) >= 0) {
|
|
value = value.slice(1);
|
|
}
|
|
if (value === '.inf') {
|
|
return sign * 2e308;
|
|
} else if (value === '.nan') {
|
|
return 0/0;
|
|
} else if (indexOf.call(value, ':') >= 0) {
|
|
digits = (function() {
|
|
var i, len, ref1, results;
|
|
ref1 = value.split(/:/g);
|
|
results = [];
|
|
for (i = 0, len = ref1.length; i < len; i++) {
|
|
part = ref1[i];
|
|
results.push(parseFloat(part));
|
|
}
|
|
return results;
|
|
})();
|
|
digits.reverse();
|
|
base = 1;
|
|
value = 0.0;
|
|
for (i = 0, len = digits.length; i < len; i++) {
|
|
digit = digits[i];
|
|
value += digit * base;
|
|
base *= 60;
|
|
}
|
|
return sign * value;
|
|
} else {
|
|
return sign * parseFloat(value);
|
|
}
|
|
}
|
|
|
|
construct_yaml_binary(node) {
|
|
var error, value;
|
|
value = this.construct_scalar(node);
|
|
try {
|
|
if (typeof window !== "undefined" && window !== null) {
|
|
return atob(value);
|
|
}
|
|
return new Buffer(value, 'base64').toString('ascii');
|
|
} catch (error1) {
|
|
error = error1;
|
|
throw new exports.ConstructorError(null, null, `failed to decode base64 data: ${error}`, node.start_mark);
|
|
}
|
|
}
|
|
|
|
construct_yaml_timestamp(node) {
|
|
var date, day, fraction, hour, index, key, match, millisecond, minute, month, second, tz_hour, tz_minute, tz_sign, value, values, year;
|
|
value = this.construct_scalar(node);
|
|
match = node.value.match(TIMESTAMP_REGEX);
|
|
values = {};
|
|
for (key in TIMESTAMP_PARTS) {
|
|
index = TIMESTAMP_PARTS[key];
|
|
values[key] = match[index];
|
|
}
|
|
year = parseInt(values.year);
|
|
month = parseInt(values.month) - 1;
|
|
day = parseInt(values.day);
|
|
if (!values.hour) {
|
|
return new Date(Date.UTC(year, month, day));
|
|
}
|
|
hour = parseInt(values.hour);
|
|
minute = parseInt(values.minute);
|
|
second = parseInt(values.second);
|
|
millisecond = 0;
|
|
if (values.fraction) {
|
|
fraction = values.fraction.slice(0, 6);
|
|
while (fraction.length < 6) {
|
|
fraction += '0';
|
|
}
|
|
fraction = parseInt(fraction);
|
|
millisecond = Math.round(fraction / 1000);
|
|
}
|
|
if (values.tz_sign) {
|
|
tz_sign = values.tz_sign === '-' ? 1 : -1;
|
|
if (tz_hour = parseInt(values.tz_hour)) {
|
|
hour += tz_sign * tz_hour;
|
|
}
|
|
if (tz_minute = parseInt(values.tz_minute)) {
|
|
minute += tz_sign * tz_minute;
|
|
}
|
|
}
|
|
date = new Date(Date.UTC(year, month, day, hour, minute, second, millisecond));
|
|
return date;
|
|
}
|
|
|
|
construct_yaml_pair_list(type, node) {
|
|
var list;
|
|
list = [];
|
|
if (!(node instanceof nodes.SequenceNode)) {
|
|
throw new exports.ConstructorError(`while constructing ${type}`, node.start_mark, `expected a sequence but found ${node.id}`, node.start_mark);
|
|
}
|
|
this.defer(() => {
|
|
var i, key, key_node, len, ref, results, subnode, value, value_node;
|
|
ref = node.value;
|
|
results = [];
|
|
for (i = 0, len = ref.length; i < len; i++) {
|
|
subnode = ref[i];
|
|
if (!(subnode instanceof nodes.MappingNode)) {
|
|
throw new exports.ConstructorError(`while constructing ${type}`, node.start_mark, `expected a mapping of length 1 but found ${subnode.id}`, subnode.start_mark);
|
|
}
|
|
if (subnode.value.length !== 1) {
|
|
throw new exports.ConstructorError(`while constructing ${type}`, node.start_mark, `expected a mapping of length 1 but found ${subnode.id}`, subnode.start_mark);
|
|
}
|
|
[key_node, value_node] = subnode.value[0];
|
|
key = this.construct_object(key_node);
|
|
value = this.construct_object(value_node);
|
|
results.push(list.push([key, value]));
|
|
}
|
|
return results;
|
|
});
|
|
return list;
|
|
}
|
|
|
|
construct_yaml_omap(node) {
|
|
return this.construct_yaml_pair_list('an ordered map', node);
|
|
}
|
|
|
|
construct_yaml_pairs(node) {
|
|
return this.construct_yaml_pair_list('pairs', node);
|
|
}
|
|
|
|
construct_yaml_set(node) {
|
|
var data;
|
|
data = [];
|
|
this.defer(() => {
|
|
var item, results;
|
|
results = [];
|
|
for (item in this.construct_mapping(node)) {
|
|
results.push(data.push(item));
|
|
}
|
|
return results;
|
|
});
|
|
return data;
|
|
}
|
|
|
|
construct_yaml_str(node) {
|
|
return this.construct_scalar(node);
|
|
}
|
|
|
|
construct_yaml_seq(node) {
|
|
var data;
|
|
data = [];
|
|
this.defer(() => {
|
|
var i, item, len, ref, results;
|
|
ref = this.construct_sequence(node);
|
|
results = [];
|
|
for (i = 0, len = ref.length; i < len; i++) {
|
|
item = ref[i];
|
|
results.push(data.push(item));
|
|
}
|
|
return results;
|
|
});
|
|
return data;
|
|
}
|
|
|
|
construct_yaml_map(node) {
|
|
var data;
|
|
data = {};
|
|
this.defer(() => {
|
|
var key, ref, results, value;
|
|
ref = this.construct_mapping(node);
|
|
results = [];
|
|
for (key in ref) {
|
|
value = ref[key];
|
|
results.push(data[key] = value);
|
|
}
|
|
return results;
|
|
});
|
|
return data;
|
|
}
|
|
|
|
construct_yaml_object(node, klass) {
|
|
var data;
|
|
data = new klass;
|
|
this.defer(() => {
|
|
var key, ref, results, value;
|
|
ref = this.construct_mapping(node, true);
|
|
results = [];
|
|
for (key in ref) {
|
|
value = ref[key];
|
|
results.push(data[key] = value);
|
|
}
|
|
return results;
|
|
});
|
|
return data;
|
|
}
|
|
|
|
construct_undefined(node) {
|
|
throw new exports.ConstructorError(null, null, `could not determine a constructor for the tag ${node.tag}`, node.start_mark);
|
|
}
|
|
|
|
};
|
|
|
|
BOOL_VALUES = {
|
|
on: true,
|
|
off: false,
|
|
true: true,
|
|
false: false,
|
|
yes: true,
|
|
no: false
|
|
};
|
|
|
|
TIMESTAMP_REGEX = /^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:(?:[Tt]|[\x20\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\.([0-9]*))?(?:[\x20\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?)?$/; // 1: year
|
|
// 2: month
|
|
// 3: day
|
|
// 4: hour
|
|
// 5: minute
|
|
// 6: second
|
|
// 7: fraction
|
|
// 9: tz_sign
|
|
// 10: tz_hour
|
|
// 11: tz_minute
|
|
// 8: tz
|
|
|
|
TIMESTAMP_PARTS = {
|
|
year: 1,
|
|
month: 2,
|
|
day: 3,
|
|
hour: 4,
|
|
minute: 5,
|
|
second: 6,
|
|
fraction: 7,
|
|
tz: 8,
|
|
tz_sign: 9,
|
|
tz_hour: 10,
|
|
tz_minute: 11
|
|
};
|
|
|
|
return Constructor;
|
|
|
|
}).call(this);
|
|
|
|
this.Constructor.add_constructor('tag:yaml.org,2002:null', this.Constructor.prototype.construct_yaml_null);
|
|
|
|
this.Constructor.add_constructor('tag:yaml.org,2002:bool', this.Constructor.prototype.construct_yaml_bool);
|
|
|
|
this.Constructor.add_constructor('tag:yaml.org,2002:int', this.Constructor.prototype.construct_yaml_int);
|
|
|
|
this.Constructor.add_constructor('tag:yaml.org,2002:float', this.Constructor.prototype.construct_yaml_float);
|
|
|
|
this.Constructor.add_constructor('tag:yaml.org,2002:binary', this.Constructor.prototype.construct_yaml_binary);
|
|
|
|
this.Constructor.add_constructor('tag:yaml.org,2002:timestamp', this.Constructor.prototype.construct_yaml_timestamp);
|
|
|
|
this.Constructor.add_constructor('tag:yaml.org,2002:omap', this.Constructor.prototype.construct_yaml_omap);
|
|
|
|
this.Constructor.add_constructor('tag:yaml.org,2002:pairs', this.Constructor.prototype.construct_yaml_pairs);
|
|
|
|
this.Constructor.add_constructor('tag:yaml.org,2002:set', this.Constructor.prototype.construct_yaml_set);
|
|
|
|
this.Constructor.add_constructor('tag:yaml.org,2002:str', this.Constructor.prototype.construct_yaml_str);
|
|
|
|
this.Constructor.add_constructor('tag:yaml.org,2002:seq', this.Constructor.prototype.construct_yaml_seq);
|
|
|
|
this.Constructor.add_constructor('tag:yaml.org,2002:map', this.Constructor.prototype.construct_yaml_map);
|
|
|
|
this.Constructor.add_constructor(null, this.Constructor.prototype.construct_undefined);
|
|
|
|
}).call(this);
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 28190:
|
|
/***/ (function(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) {
|
|
|
|
(function() {
|
|
var emitter, representer, resolver, serializer, util;
|
|
|
|
util = __webpack_require__(23823);
|
|
|
|
emitter = __webpack_require__(63320);
|
|
|
|
serializer = __webpack_require__(56472);
|
|
|
|
representer = __webpack_require__(13832);
|
|
|
|
resolver = __webpack_require__(3579);
|
|
|
|
this.make_dumper = function(Emitter = emitter.Emitter, Serializer = serializer.Serializer, Representer = representer.Representer, Resolver = resolver.Resolver) {
|
|
var Dumper, components;
|
|
components = [Emitter, Serializer, Representer, Resolver];
|
|
return Dumper = (function() {
|
|
var component;
|
|
|
|
class Dumper {
|
|
constructor(stream, options = {}) {
|
|
var i, len, ref;
|
|
components[0].prototype.initialise.call(this, stream, options);
|
|
ref = components.slice(1);
|
|
for (i = 0, len = ref.length; i < len; i++) {
|
|
component = ref[i];
|
|
component.prototype.initialise.call(this, options);
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
util.extend(Dumper.prototype, ...((function() {
|
|
var i, len, results;
|
|
results = [];
|
|
for (i = 0, len = components.length; i < len; i++) {
|
|
component = components[i];
|
|
results.push(component.prototype);
|
|
}
|
|
return results;
|
|
})()));
|
|
|
|
return Dumper;
|
|
|
|
}).call(this);
|
|
};
|
|
|
|
this.Dumper = this.make_dumper();
|
|
|
|
}).call(this);
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 63320:
|
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
|
|
(function() {
|
|
var ScalarAnalysis, YAMLError, events, util,
|
|
hasProp = {}.hasOwnProperty,
|
|
indexOf = [].indexOf;
|
|
|
|
events = __webpack_require__(35063);
|
|
|
|
util = __webpack_require__(23823);
|
|
|
|
({YAMLError} = __webpack_require__(45372));
|
|
|
|
this.EmitterError = class EmitterError extends YAMLError {};
|
|
|
|
/*
|
|
Emitter expects events obeying the following grammar:
|
|
|
|
stream ::= STREAM-START document* STREAM-END
|
|
document ::= DOCUMENT-START node DOCUMENT-END
|
|
node ::= SCALA | sequence | mapping
|
|
sequence ::= SEQUENCE-START node* SEQUENCE-END
|
|
mapping ::= MAPPING-START (node node)* MAPPING-END
|
|
*/
|
|
this.Emitter = (function() {
|
|
var C_WHITESPACE, DEFAULT_TAG_PREFIXES, ESCAPE_REPLACEMENTS, ctor;
|
|
|
|
class Emitter {
|
|
constructor() {
|
|
return ctor.apply(this, arguments);
|
|
}
|
|
|
|
initialise(stream, options) {
|
|
var ref;
|
|
this.stream = stream;
|
|
// Encoding can be overriden by STREAM-START
|
|
this.encoding = null;
|
|
// Emitter is a state machine with a stack of states to handle nested structures.
|
|
this.states = [];
|
|
this.state = this.expect_stream_start;
|
|
// Current event and the event queue
|
|
this.events = [];
|
|
this.event = null;
|
|
// The current indentation level and the stack of previous indents.
|
|
this.indents = [];
|
|
this.indent = null;
|
|
// Flow level.
|
|
this.flow_level = 0;
|
|
// Contexts.
|
|
this.root_context = false;
|
|
this.sequence_context = false;
|
|
this.mapping_context = false;
|
|
this.simple_key_context = false;
|
|
// Characteristics of the last emitted character:
|
|
// - current position.
|
|
// - is it a whitespace?
|
|
// - is it an indentation character (indentation space, '-', '?', or ':')?
|
|
this.line = 0;
|
|
this.column = 0;
|
|
this.whitespace = true;
|
|
this.indentation = true;
|
|
// Whether the document requires an explicit document indicator.
|
|
this.open_ended = false;
|
|
// Formatting details
|
|
({canonical: this.canonical, allow_unicode: this.allow_unicode} = options);
|
|
if (this.canonical == null) {
|
|
this.canonical = false;
|
|
}
|
|
if (this.allow_unicode == null) {
|
|
this.allow_unicode = true;
|
|
}
|
|
this.best_indent = 1 < options.indent && options.indent < 10 ? options.indent : 2;
|
|
this.best_width = options.width > this.indent * 2 ? options.width : 80;
|
|
this.best_line_break = (ref = options.line_break) === '\r' || ref === '\n' || ref === '\r\n' ? options.line_break : '\n';
|
|
// Tag prefixes.
|
|
this.tag_prefixes = null;
|
|
// Prepared anchor and tag
|
|
this.prepared_anchor = null;
|
|
this.prepared_tag = null;
|
|
// Scalar analysis and style.
|
|
this.analysis = null;
|
|
return this.style = null;
|
|
}
|
|
|
|
/*
|
|
Reset the state attributes (to clear self-references)
|
|
*/
|
|
dispose() {
|
|
this.states = [];
|
|
return this.state = null;
|
|
}
|
|
|
|
emit(event) {
|
|
var results;
|
|
this.events.push(event);
|
|
results = [];
|
|
while (!this.need_more_events()) {
|
|
this.event = this.events.shift();
|
|
this.state();
|
|
results.push(this.event = null);
|
|
}
|
|
return results;
|
|
}
|
|
|
|
/*
|
|
In some cases, we wait for a few next events before emitting.
|
|
*/
|
|
need_more_events() {
|
|
var event;
|
|
if (this.events.length === 0) {
|
|
return true;
|
|
}
|
|
event = this.events[0];
|
|
if (event instanceof events.DocumentStartEvent) {
|
|
return this.need_events(1);
|
|
} else if (event instanceof events.SequenceStartEvent) {
|
|
return this.need_events(2);
|
|
} else if (event instanceof events.MappingStartEvent) {
|
|
return this.need_events(3);
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
need_events(count) {
|
|
var event, i, len, level, ref;
|
|
level = 0;
|
|
ref = this.events.slice(1);
|
|
for (i = 0, len = ref.length; i < len; i++) {
|
|
event = ref[i];
|
|
if (event instanceof events.DocumentStartEvent || event instanceof events.CollectionStartEvent) {
|
|
level++;
|
|
} else if (event instanceof events.DocumentEndEvent || event instanceof events.CollectionEndEvent) {
|
|
level--;
|
|
} else if (event instanceof events.StreamEndEvent) {
|
|
level = -1;
|
|
}
|
|
if (level < 0) {
|
|
return false;
|
|
}
|
|
}
|
|
return this.events.length < count + 1;
|
|
}
|
|
|
|
increase_indent(options = {}) {
|
|
this.indents.push(this.indent);
|
|
if (this.indent == null) {
|
|
return this.indent = options.flow ? this.best_indent : 0;
|
|
} else if (!options.indentless) {
|
|
return this.indent += this.best_indent;
|
|
}
|
|
}
|
|
|
|
// Stream states
|
|
expect_stream_start() {
|
|
if (this.event instanceof events.StreamStartEvent) {
|
|
if (this.event.encoding && !('encoding' in this.stream)) {
|
|
this.encoding = this.event.encoding;
|
|
}
|
|
this.write_stream_start();
|
|
return this.state = this.expect_first_document_start;
|
|
} else {
|
|
return this.error('expected StreamStartEvent, but got', this.event);
|
|
}
|
|
}
|
|
|
|
expect_nothing() {
|
|
return this.error('expected nothing, but got', this.event);
|
|
}
|
|
|
|
// Document states
|
|
expect_first_document_start() {
|
|
return this.expect_document_start(true);
|
|
}
|
|
|
|
expect_document_start(first = false) {
|
|
var explicit, handle, i, k, len, prefix, ref;
|
|
if (this.event instanceof events.DocumentStartEvent) {
|
|
if ((this.event.version || this.event.tags) && this.open_ended) {
|
|
this.write_indicator('...', true);
|
|
this.write_indent();
|
|
}
|
|
if (this.event.version) {
|
|
this.write_version_directive(this.prepare_version(this.event.version));
|
|
}
|
|
this.tag_prefixes = util.clone(DEFAULT_TAG_PREFIXES);
|
|
if (this.event.tags) {
|
|
ref = ((function() {
|
|
var ref, results;
|
|
ref = this.event.tags;
|
|
results = [];
|
|
for (k in ref) {
|
|
if (!hasProp.call(ref, k)) continue;
|
|
results.push(k);
|
|
}
|
|
return results;
|
|
}).call(this)).sort();
|
|
for (i = 0, len = ref.length; i < len; i++) {
|
|
handle = ref[i];
|
|
prefix = this.event.tags[handle];
|
|
this.tag_prefixes[prefix] = handle;
|
|
this.write_tag_directive(this.prepare_tag_handle(handle), this.prepare_tag_prefix(prefix));
|
|
}
|
|
}
|
|
explicit = !first || this.event.explicit || this.canonical || this.event.version || this.event.tags || this.check_empty_document();
|
|
if (explicit) {
|
|
this.write_indent();
|
|
this.write_indicator('---', true);
|
|
if (this.canonical) {
|
|
this.write_indent();
|
|
}
|
|
}
|
|
return this.state = this.expect_document_root;
|
|
} else if (this.event instanceof events.StreamEndEvent) {
|
|
if (this.open_ended) {
|
|
this.write_indicator('...', true);
|
|
this.write_indent();
|
|
}
|
|
this.write_stream_end();
|
|
return this.state = this.expect_nothing;
|
|
} else {
|
|
return this.error('expected DocumentStartEvent, but got', this.event);
|
|
}
|
|
}
|
|
|
|
expect_document_end() {
|
|
if (this.event instanceof events.DocumentEndEvent) {
|
|
this.write_indent();
|
|
if (this.event.explicit) {
|
|
this.write_indicator('...', true);
|
|
this.write_indent();
|
|
}
|
|
this.flush_stream();
|
|
return this.state = this.expect_document_start;
|
|
} else {
|
|
return this.error('expected DocumentEndEvent, but got', this.event);
|
|
}
|
|
}
|
|
|
|
expect_document_root() {
|
|
this.states.push(this.expect_document_end);
|
|
return this.expect_node({
|
|
root: true
|
|
});
|
|
}
|
|
|
|
// Node states
|
|
expect_node(expect = {}) {
|
|
this.root_context = !!expect.root;
|
|
this.sequence_context = !!expect.sequence;
|
|
this.mapping_context = !!expect.mapping;
|
|
this.simple_key_context = !!expect.simple_key;
|
|
if (this.event instanceof events.AliasEvent) {
|
|
return this.expect_alias();
|
|
} else if (this.event instanceof events.ScalarEvent || this.event instanceof events.CollectionStartEvent) {
|
|
this.process_anchor('&');
|
|
this.process_tag();
|
|
if (this.event instanceof events.ScalarEvent) {
|
|
return this.expect_scalar();
|
|
} else if (this.event instanceof events.SequenceStartEvent) {
|
|
if (this.flow_level || this.canonical || this.event.flow_style || this.check_empty_sequence()) {
|
|
return this.expect_flow_sequence();
|
|
} else {
|
|
return this.expect_block_sequence();
|
|
}
|
|
} else if (this.event instanceof events.MappingStartEvent) {
|
|
if (this.flow_level || this.canonical || this.event.flow_style || this.check_empty_mapping()) {
|
|
return this.expect_flow_mapping();
|
|
} else {
|
|
return this.expect_block_mapping();
|
|
}
|
|
}
|
|
} else {
|
|
return this.error('expected NodeEvent, but got', this.event);
|
|
}
|
|
}
|
|
|
|
expect_alias() {
|
|
if (!this.event.anchor) {
|
|
this.error('anchor is not specified for alias');
|
|
}
|
|
this.process_anchor('*');
|
|
return this.state = this.states.pop();
|
|
}
|
|
|
|
expect_scalar() {
|
|
this.increase_indent({
|
|
flow: true
|
|
});
|
|
this.process_scalar();
|
|
this.indent = this.indents.pop();
|
|
return this.state = this.states.pop();
|
|
}
|
|
|
|
// Flow sequence states
|
|
expect_flow_sequence() {
|
|
this.write_indicator('[', true, {
|
|
whitespace: true
|
|
});
|
|
this.flow_level++;
|
|
this.increase_indent({
|
|
flow: true
|
|
});
|
|
return this.state = this.expect_first_flow_sequence_item;
|
|
}
|
|
|
|
expect_first_flow_sequence_item() {
|
|
if (this.event instanceof events.SequenceEndEvent) {
|
|
this.indent = this.indents.pop();
|
|
this.flow_level--;
|
|
this.write_indicator(']', false);
|
|
return this.state = this.states.pop();
|
|
} else {
|
|
if (this.canonical || this.column > this.best_width) {
|
|
this.write_indent();
|
|
}
|
|
this.states.push(this.expect_flow_sequence_item);
|
|
return this.expect_node({
|
|
sequence: true
|
|
});
|
|
}
|
|
}
|
|
|
|
expect_flow_sequence_item() {
|
|
if (this.event instanceof events.SequenceEndEvent) {
|
|
this.indent = this.indents.pop();
|
|
this.flow_level--;
|
|
if (this.canonical) {
|
|
this.write_indicator(',', false);
|
|
this.write_indent();
|
|
}
|
|
this.write_indicator(']', false);
|
|
return this.state = this.states.pop();
|
|
} else {
|
|
this.write_indicator(',', false);
|
|
if (this.canonical || this.column > this.best_width) {
|
|
this.write_indent();
|
|
}
|
|
this.states.push(this.expect_flow_sequence_item);
|
|
return this.expect_node({
|
|
sequence: true
|
|
});
|
|
}
|
|
}
|
|
|
|
// Flow mapping states
|
|
expect_flow_mapping() {
|
|
this.write_indicator('{', true, {
|
|
whitespace: true
|
|
});
|
|
this.flow_level++;
|
|
this.increase_indent({
|
|
flow: true
|
|
});
|
|
return this.state = this.expect_first_flow_mapping_key;
|
|
}
|
|
|
|
expect_first_flow_mapping_key() {
|
|
if (this.event instanceof events.MappingEndEvent) {
|
|
this.indent = this.indents.pop();
|
|
this.flow_level--;
|
|
this.write_indicator('}', false);
|
|
return this.state = this.states.pop();
|
|
} else {
|
|
if (this.canonical || this.column > this.best_width) {
|
|
this.write_indent();
|
|
}
|
|
if (!this.canonical && this.check_simple_key()) {
|
|
this.states.push(this.expect_flow_mapping_simple_value);
|
|
return this.expect_node({
|
|
mapping: true,
|
|
simple_key: true
|
|
});
|
|
} else {
|
|
this.write_indicator('?', true);
|
|
this.states.push(this.expect_flow_mapping_value);
|
|
return this.expect_node({
|
|
mapping: true
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
expect_flow_mapping_key() {
|
|
if (this.event instanceof events.MappingEndEvent) {
|
|
this.indent = this.indents.pop();
|
|
this.flow_level--;
|
|
if (this.canonical) {
|
|
this.write_indicator(',', false);
|
|
this.write_indent();
|
|
}
|
|
this.write_indicator('}', false);
|
|
return this.state = this.states.pop();
|
|
} else {
|
|
this.write_indicator(',', false);
|
|
if (this.canonical || this.column > this.best_width) {
|
|
this.write_indent();
|
|
}
|
|
if (!this.canonical && this.check_simple_key()) {
|
|
this.states.push(this.expect_flow_mapping_simple_value);
|
|
return this.expect_node({
|
|
mapping: true,
|
|
simple_key: true
|
|
});
|
|
} else {
|
|
this.write_indicator('?', true);
|
|
this.states.push(this.expect_flow_mapping_value);
|
|
return this.expect_node({
|
|
mapping: true
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
expect_flow_mapping_simple_value() {
|
|
this.write_indicator(':', false);
|
|
this.states.push(this.expect_flow_mapping_key);
|
|
return this.expect_node({
|
|
mapping: true
|
|
});
|
|
}
|
|
|
|
expect_flow_mapping_value() {
|
|
if (this.canonical || this.column > this.best_width) {
|
|
this.write_indent();
|
|
}
|
|
this.write_indicator(':', true);
|
|
this.states.push(this.expect_flow_mapping_key);
|
|
return this.expect_node({
|
|
mapping: true
|
|
});
|
|
}
|
|
|
|
// Block sequence states
|
|
expect_block_sequence() {
|
|
var indentless;
|
|
indentless = this.mapping_context && !this.indentation;
|
|
this.increase_indent({indentless});
|
|
return this.state = this.expect_first_block_sequence_item;
|
|
}
|
|
|
|
expect_first_block_sequence_item() {
|
|
return this.expect_block_sequence_item(true);
|
|
}
|
|
|
|
expect_block_sequence_item(first = false) {
|
|
if (!first && this.event instanceof events.SequenceEndEvent) {
|
|
this.indent = this.indents.pop();
|
|
return this.state = this.states.pop();
|
|
} else {
|
|
this.write_indent();
|
|
this.write_indicator('-', true, {
|
|
indentation: true
|
|
});
|
|
this.states.push(this.expect_block_sequence_item);
|
|
return this.expect_node({
|
|
sequence: true
|
|
});
|
|
}
|
|
}
|
|
|
|
// Block mapping states
|
|
expect_block_mapping() {
|
|
this.increase_indent();
|
|
return this.state = this.expect_first_block_mapping_key;
|
|
}
|
|
|
|
expect_first_block_mapping_key() {
|
|
return this.expect_block_mapping_key(true);
|
|
}
|
|
|
|
expect_block_mapping_key(first = false) {
|
|
if (!first && this.event instanceof events.MappingEndEvent) {
|
|
this.indent = this.indents.pop();
|
|
return this.state = this.states.pop();
|
|
} else {
|
|
this.write_indent();
|
|
if (this.check_simple_key()) {
|
|
this.states.push(this.expect_block_mapping_simple_value);
|
|
return this.expect_node({
|
|
mapping: true,
|
|
simple_key: true
|
|
});
|
|
} else {
|
|
this.write_indicator('?', true, {
|
|
indentation: true
|
|
});
|
|
this.states.push(this.expect_block_mapping_value);
|
|
return this.expect_node({
|
|
mapping: true
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
expect_block_mapping_simple_value() {
|
|
this.write_indicator(':', false);
|
|
this.states.push(this.expect_block_mapping_key);
|
|
return this.expect_node({
|
|
mapping: true
|
|
});
|
|
}
|
|
|
|
expect_block_mapping_value() {
|
|
this.write_indent();
|
|
this.write_indicator(':', true, {
|
|
indentation: true
|
|
});
|
|
this.states.push(this.expect_block_mapping_key);
|
|
return this.expect_node({
|
|
mapping: true
|
|
});
|
|
}
|
|
|
|
// Checkers
|
|
check_empty_document() {
|
|
var event;
|
|
if (!(this.event instanceof events.DocumentStartEvent) || this.events.length === 0) {
|
|
return false;
|
|
}
|
|
event = this.events[0];
|
|
return event instanceof events.ScalarEvent && (event.anchor == null) && (event.tag == null) && event.implicit && event.value === '';
|
|
}
|
|
|
|
check_empty_sequence() {
|
|
return this.event instanceof events.SequenceStartEvent && this.events[0] instanceof events.SequenceEndEvent;
|
|
}
|
|
|
|
check_empty_mapping() {
|
|
return this.event instanceof events.MappingStartEvent && this.events[0] instanceof events.MappingEndEvent;
|
|
}
|
|
|
|
check_simple_key() {
|
|
var length;
|
|
length = 0;
|
|
if (this.event instanceof events.NodeEvent && (this.event.anchor != null)) {
|
|
if (this.prepared_anchor == null) {
|
|
this.prepared_anchor = this.prepare_anchor(this.event.anchor);
|
|
}
|
|
length += this.prepared_anchor.length;
|
|
}
|
|
if ((this.event.tag != null) && (this.event instanceof events.ScalarEvent || this.event instanceof events.CollectionStartEvent)) {
|
|
if (this.prepared_tag == null) {
|
|
this.prepared_tag = this.prepare_tag(this.event.tag);
|
|
}
|
|
length += this.prepared_tag.length;
|
|
}
|
|
if (this.event instanceof events.ScalarEvent) {
|
|
if (this.analysis == null) {
|
|
this.analysis = this.analyze_scalar(this.event.value);
|
|
}
|
|
length += this.analysis.scalar.length;
|
|
}
|
|
return length < 128 && (this.event instanceof events.AliasEvent || (this.event instanceof events.ScalarEvent && !this.analysis.empty && !this.analysis.multiline) || this.check_empty_sequence() || this.check_empty_mapping());
|
|
}
|
|
|
|
// Anchor, Tag and Scalar processors
|
|
process_anchor(indicator) {
|
|
if (this.event.anchor == null) {
|
|
this.prepared_anchor = null;
|
|
return;
|
|
}
|
|
if (this.prepared_anchor == null) {
|
|
this.prepared_anchor = this.prepare_anchor(this.event.anchor);
|
|
}
|
|
if (this.prepared_anchor) {
|
|
this.write_indicator(`${indicator}${this.prepared_anchor}`, true);
|
|
}
|
|
return this.prepared_anchor = null;
|
|
}
|
|
|
|
process_tag() {
|
|
var tag;
|
|
tag = this.event.tag;
|
|
if (this.event instanceof events.ScalarEvent) {
|
|
if (this.style == null) {
|
|
this.style = this.choose_scalar_style();
|
|
}
|
|
if ((!this.canonical || (tag == null)) && ((this.style === '' && this.event.implicit[0]) || (this.style !== '' && this.event.implicit[1]))) {
|
|
this.prepared_tag = null;
|
|
return;
|
|
}
|
|
if (this.event.implicit[0] && (tag == null)) {
|
|
tag = '!';
|
|
this.prepared_tag = null;
|
|
}
|
|
} else if ((!this.canonical || (tag == null)) && this.event.implicit) {
|
|
this.prepared_tag = null;
|
|
return;
|
|
}
|
|
if (tag == null) {
|
|
this.error('tag is not specified');
|
|
}
|
|
if (this.prepared_tag == null) {
|
|
this.prepared_tag = this.prepare_tag(tag);
|
|
}
|
|
this.write_indicator(this.prepared_tag, true);
|
|
return this.prepared_tag = null;
|
|
}
|
|
|
|
process_scalar() {
|
|
var split;
|
|
if (this.analysis == null) {
|
|
this.analysis = this.analyze_scalar(this.event.value);
|
|
}
|
|
if (this.style == null) {
|
|
this.style = this.choose_scalar_style();
|
|
}
|
|
split = !this.simple_key_context;
|
|
switch (this.style) {
|
|
case '"':
|
|
this.write_double_quoted(this.analysis.scalar, split);
|
|
break;
|
|
case "'":
|
|
this.write_single_quoted(this.analysis.scalar, split);
|
|
break;
|
|
case '>':
|
|
this.write_folded(this.analysis.scalar);
|
|
break;
|
|
case '|':
|
|
this.write_literal(this.analysis.scalar);
|
|
break;
|
|
default:
|
|
this.write_plain(this.analysis.scalar, split);
|
|
}
|
|
this.analysis = null;
|
|
return this.style = null;
|
|
}
|
|
|
|
choose_scalar_style() {
|
|
var ref;
|
|
if (this.analysis == null) {
|
|
this.analysis = this.analyze_scalar(this.event.value);
|
|
}
|
|
if (this.event.style === '"' || this.canonical) {
|
|
return '"';
|
|
}
|
|
if (!this.event.style && this.event.implicit[0] && !(this.simple_key_context && (this.analysis.empty || this.analysis.multiline)) && ((this.flow_level && this.analysis.allow_flow_plain) || (!this.flow_level && this.analysis.allow_block_plain))) {
|
|
return '';
|
|
}
|
|
if (this.event.style && (ref = this.event.style, indexOf.call('|>', ref) >= 0) && !this.flow_level && !this.simple_key_context && this.analysis.allow_block) {
|
|
return this.event.style;
|
|
}
|
|
if ((!this.event.style || this.event.style === "'") && this.analysis.allow_single_quoted && !(this.simple_key_context && this.analysis.multiline)) {
|
|
return "'";
|
|
}
|
|
return '"';
|
|
}
|
|
|
|
// Analyzers
|
|
prepare_version([major, minor]) {
|
|
var version;
|
|
version = `${major}.${minor}`;
|
|
if (major === 1) {
|
|
return version;
|
|
} else {
|
|
return this.error('unsupported YAML version', version);
|
|
}
|
|
}
|
|
|
|
prepare_tag_handle(handle) {
|
|
var char, i, len, ref;
|
|
if (!handle) {
|
|
this.error('tag handle must not be empty');
|
|
}
|
|
if (handle[0] !== '!' || handle.slice(-1) !== '!') {
|
|
this.error("tag handle must start and end with '!':", handle);
|
|
}
|
|
ref = handle.slice(1, -1);
|
|
for (i = 0, len = ref.length; i < len; i++) {
|
|
char = ref[i];
|
|
if (!(('0' <= char && char <= '9') || ('A' <= char && char <= 'Z') || ('a' <= char && char <= 'z') || indexOf.call('-_', char) >= 0)) {
|
|
this.error(`invalid character '${char}' in the tag handle:`, handle);
|
|
}
|
|
}
|
|
return handle;
|
|
}
|
|
|
|
prepare_tag_prefix(prefix) {
|
|
var char, chunks, end, start;
|
|
if (!prefix) {
|
|
this.error('tag prefix must not be empty');
|
|
}
|
|
chunks = [];
|
|
start = 0;
|
|
end = +(prefix[0] === '!');
|
|
while (end < prefix.length) {
|
|
char = prefix[end];
|
|
if (('0' <= char && char <= '9') || ('A' <= char && char <= 'Z') || ('a' <= char && char <= 'z') || indexOf.call('-;/?!:@&=+$,_.~*\'()[]', char) >= 0) {
|
|
end++;
|
|
} else {
|
|
if (start < end) {
|
|
chunks.push(prefix.slice(start, end));
|
|
}
|
|
start = end = end + 1;
|
|
chunks.push(char);
|
|
}
|
|
}
|
|
if (start < end) {
|
|
chunks.push(prefix.slice(start, end));
|
|
}
|
|
return chunks.join('');
|
|
}
|
|
|
|
prepare_tag(tag) {
|
|
var char, chunks, end, handle, i, k, len, prefix, ref, start, suffix, suffix_text;
|
|
if (!tag) {
|
|
this.error('tag must not be empty');
|
|
}
|
|
if (tag === '!') {
|
|
return tag;
|
|
}
|
|
handle = null;
|
|
suffix = tag;
|
|
ref = ((function() {
|
|
var ref, results;
|
|
ref = this.tag_prefixes;
|
|
results = [];
|
|
for (k in ref) {
|
|
if (!hasProp.call(ref, k)) continue;
|
|
results.push(k);
|
|
}
|
|
return results;
|
|
}).call(this)).sort();
|
|
for (i = 0, len = ref.length; i < len; i++) {
|
|
prefix = ref[i];
|
|
if (tag.indexOf(prefix) === 0 && (prefix === '!' || prefix.length < tag.length)) {
|
|
handle = this.tag_prefixes[prefix];
|
|
suffix = tag.slice(prefix.length);
|
|
}
|
|
}
|
|
chunks = [];
|
|
start = end = 0;
|
|
while (end < suffix.length) {
|
|
char = suffix[end];
|
|
if (('0' <= char && char <= '9') || ('A' <= char && char <= 'Z') || ('a' <= char && char <= 'z') || indexOf.call('-;/?!:@&=+$,_.~*\'()[]', char) >= 0 || (char === '!' && handle !== '!')) {
|
|
end++;
|
|
} else {
|
|
if (start < end) {
|
|
chunks.push(suffix.slice(start, end));
|
|
}
|
|
start = end = end + 1;
|
|
chunks.push(char);
|
|
}
|
|
}
|
|
if (start < end) {
|
|
chunks.push(suffix.slice(start, end));
|
|
}
|
|
suffix_text = chunks.join('');
|
|
if (handle) {
|
|
return `${handle}${suffix_text}`;
|
|
} else {
|
|
return `!<${suffix_text}>`;
|
|
}
|
|
}
|
|
|
|
prepare_anchor(anchor) {
|
|
var char, i, len;
|
|
if (!anchor) {
|
|
this.error('anchor must not be empty');
|
|
}
|
|
for (i = 0, len = anchor.length; i < len; i++) {
|
|
char = anchor[i];
|
|
if (!(('0' <= char && char <= '9') || ('A' <= char && char <= 'Z') || ('a' <= char && char <= 'z') || indexOf.call('-_', char) >= 0)) {
|
|
this.error(`invalid character '${char}' in the anchor:`, anchor);
|
|
}
|
|
}
|
|
return anchor;
|
|
}
|
|
|
|
analyze_scalar(scalar) {
|
|
var allow_block, allow_block_plain, allow_double_quoted, allow_flow_plain, allow_single_quoted, block_indicators, break_space, char, flow_indicators, followed_by_whitespace, i, index, leading_break, leading_space, len, line_breaks, preceded_by_whitespace, previous_break, previous_space, ref, ref1, space_break, special_characters, trailing_break, trailing_space, unicode_characters;
|
|
// Empty scalar is a special case.
|
|
if (!scalar) {
|
|
new ScalarAnalysis(scalar, true, false, false, true, true, true, false);
|
|
}
|
|
// Indicators and special characters.
|
|
block_indicators = false;
|
|
flow_indicators = false;
|
|
line_breaks = false;
|
|
special_characters = false;
|
|
unicode_characters = false;
|
|
// Important whitespace combinations
|
|
leading_space = false;
|
|
leading_break = false;
|
|
trailing_space = false;
|
|
trailing_break = false;
|
|
break_space = false;
|
|
space_break = false;
|
|
// Check document indicators.
|
|
if (scalar.indexOf('---') === 0 || scalar.indexOf('...') === 0) {
|
|
block_indicators = true;
|
|
flow_indicators = true;
|
|
}
|
|
// First character or preceded by a whitespace.
|
|
preceded_by_whitespace = true;
|
|
// Last character or followed by a whitespace.
|
|
followed_by_whitespace = scalar.length === 1 || (ref = scalar[1], indexOf.call('\0 \t\r\n\x85\u2028\u2029', ref) >= 0);
|
|
// The previous character is a space.
|
|
previous_space = false;
|
|
// The previous character is a break
|
|
previous_break = false;
|
|
index = 0;
|
|
for (index = i = 0, len = scalar.length; i < len; index = ++i) {
|
|
char = scalar[index];
|
|
// Check for indicators.
|
|
if (index === 0) {
|
|
// Leading indicators are special characters.
|
|
if (indexOf.call('#,[]{}&*!|>\'"%@`', char) >= 0 || (char === '-' && followed_by_whitespace)) {
|
|
flow_indicators = true;
|
|
block_indicators = true;
|
|
} else if (indexOf.call('?:', char) >= 0) {
|
|
flow_indicators = true;
|
|
if (followed_by_whitespace) {
|
|
block_indicators = true;
|
|
}
|
|
}
|
|
} else {
|
|
// Some indicators cannot appear within a scalar as well.
|
|
if (indexOf.call(',?[]{}', char) >= 0) {
|
|
flow_indicators = true;
|
|
} else if (char === ':') {
|
|
flow_indicators = true;
|
|
if (followed_by_whitespace) {
|
|
block_indicators = true;
|
|
}
|
|
} else if (char === '#' && preceded_by_whitespace) {
|
|
flow_indicators = true;
|
|
block_indicators = true;
|
|
}
|
|
}
|
|
// Check for line breaks, special, and unicode characters.
|
|
if (indexOf.call('\n\x85\u2028\u2029', char) >= 0) {
|
|
line_breaks = true;
|
|
}
|
|
if (!(char === '\n' || ('\x20' <= char && char <= '\x7e'))) {
|
|
if (char !== '\uFEFF' && (char === '\x85' || ('\xA0' <= char && char <= '\uD7FF') || ('\uE000' <= char && char <= '\uFFFD'))) {
|
|
unicode_characters = true;
|
|
if (!this.allow_unicode) {
|
|
special_characters = true;
|
|
}
|
|
} else {
|
|
special_characters = true;
|
|
}
|
|
}
|
|
// Detect important whitespace combinations.
|
|
if (char === ' ') {
|
|
if (index === 0) {
|
|
leading_space = true;
|
|
}
|
|
if (index === scalar.length - 1) {
|
|
trailing_space = true;
|
|
}
|
|
if (previous_break) {
|
|
break_space = true;
|
|
}
|
|
previous_break = false;
|
|
previous_space = true;
|
|
} else if (indexOf.call('\n\x85\u2028\u2029', char) >= 0) {
|
|
if (index === 0) {
|
|
leading_break = true;
|
|
}
|
|
if (index === scalar.length - 1) {
|
|
trailing_break = true;
|
|
}
|
|
if (previous_space) {
|
|
space_break = true;
|
|
}
|
|
previous_break = true;
|
|
previous_space = false;
|
|
} else {
|
|
previous_break = false;
|
|
previous_space = false;
|
|
}
|
|
// Prepare for the next character.
|
|
preceded_by_whitespace = indexOf.call(C_WHITESPACE, char) >= 0;
|
|
followed_by_whitespace = index + 2 >= scalar.length || (ref1 = scalar[index + 2], indexOf.call(C_WHITESPACE, ref1) >= 0);
|
|
}
|
|
// Let's decide what styles are allowed.
|
|
allow_flow_plain = true;
|
|
allow_block_plain = true;
|
|
allow_single_quoted = true;
|
|
allow_double_quoted = true;
|
|
allow_block = true;
|
|
// Leading and trailing whitespaces are bad for plain scalars.
|
|
if (leading_space || leading_break || trailing_space || trailing_break) {
|
|
allow_flow_plain = allow_block_plain = false;
|
|
}
|
|
// We do not permit trailing spaces for block scalars.
|
|
if (trailing_space) {
|
|
allow_block = false;
|
|
}
|
|
// Spaces at the beginning of a new line are only acceptable for block scalars.
|
|
if (break_space) {
|
|
allow_flow_plain = allow_block_plain = allow_single_quoted = false;
|
|
}
|
|
// Spaces followed by breaks, as well as special character are only allowed for double quoted
|
|
// scalars.
|
|
if (space_break || special_characters) {
|
|
allow_flow_plain = allow_block_plain = allow_single_quoted = allow_block = false;
|
|
}
|
|
// Although the plain scalar writer supports breaks, we never emit multiline plain scalars.
|
|
if (line_breaks) {
|
|
allow_flow_plain = allow_block_plain = false;
|
|
}
|
|
// Flow indicators are forbidden for flow plain scalars.
|
|
if (flow_indicators) {
|
|
allow_flow_plain = false;
|
|
}
|
|
// Block indicators are forbidden for block plain scalars.
|
|
if (block_indicators) {
|
|
allow_block_plain = false;
|
|
}
|
|
return new ScalarAnalysis(scalar, false, line_breaks, allow_flow_plain, allow_block_plain, allow_single_quoted, allow_double_quoted, allow_block);
|
|
}
|
|
|
|
// Writers
|
|
/*
|
|
Write BOM if needed.
|
|
*/
|
|
write_stream_start() {
|
|
if (this.encoding && this.encoding.indexOf('utf-16') === 0) {
|
|
return this.stream.write('\uFEFF', this.encoding);
|
|
}
|
|
}
|
|
|
|
write_stream_end() {
|
|
return this.flush_stream();
|
|
}
|
|
|
|
write_indicator(indicator, need_whitespace, options = {}) {
|
|
var data;
|
|
data = this.whitespace || !need_whitespace ? indicator : ' ' + indicator;
|
|
this.whitespace = !!options.whitespace;
|
|
this.indentation && (this.indentation = !!options.indentation);
|
|
this.column += data.length;
|
|
this.open_ended = false;
|
|
return this.stream.write(data, this.encoding);
|
|
}
|
|
|
|
write_indent() {
|
|
var data, indent, ref;
|
|
indent = (ref = this.indent) != null ? ref : 0;
|
|
if (!this.indentation || this.column > indent || (this.column === indent && !this.whitespace)) {
|
|
this.write_line_break();
|
|
}
|
|
if (this.column < indent) {
|
|
this.whitespace = true;
|
|
data = new Array(indent - this.column + 1).join(' ');
|
|
this.column = indent;
|
|
return this.stream.write(data, this.encoding);
|
|
}
|
|
}
|
|
|
|
write_line_break(data) {
|
|
this.whitespace = true;
|
|
this.indentation = true;
|
|
this.line += 1;
|
|
this.column = 0;
|
|
return this.stream.write(data != null ? data : this.best_line_break, this.encoding);
|
|
}
|
|
|
|
write_version_directive(version_text) {
|
|
this.stream.write(`%YAML ${version_text}`, this.encoding);
|
|
return this.write_line_break();
|
|
}
|
|
|
|
write_tag_directive(handle_text, prefix_text) {
|
|
this.stream.write(`%TAG ${handle_text} ${prefix_text}`, this.encoding);
|
|
return this.write_line_break();
|
|
}
|
|
|
|
write_single_quoted(text, split = true) {
|
|
var br, breaks, char, data, end, i, len, ref, spaces, start;
|
|
this.write_indicator("'", true);
|
|
spaces = false;
|
|
breaks = false;
|
|
start = end = 0;
|
|
while (end <= text.length) {
|
|
char = text[end];
|
|
if (spaces) {
|
|
if ((char == null) || char !== ' ') {
|
|
if (start + 1 === end && this.column > this.best_width && split && start !== 0 && end !== text.length) {
|
|
this.write_indent();
|
|
} else {
|
|
data = text.slice(start, end);
|
|
this.column += data.length;
|
|
this.stream.write(data, this.encoding);
|
|
}
|
|
start = end;
|
|
}
|
|
} else if (breaks) {
|
|
if ((char == null) || indexOf.call('\n\x85\u2028\u2029', char) < 0) {
|
|
if (text[start] === '\n') {
|
|
this.write_line_break();
|
|
}
|
|
ref = text.slice(start, end);
|
|
for (i = 0, len = ref.length; i < len; i++) {
|
|
br = ref[i];
|
|
if (br === '\n') {
|
|
this.write_line_break();
|
|
} else {
|
|
this.write_line_break(br);
|
|
}
|
|
}
|
|
this.write_indent();
|
|
start = end;
|
|
}
|
|
} else if (((char == null) || indexOf.call(' \n\x85\u2028\u2029', char) >= 0 || char === "'") && start < end) {
|
|
data = text.slice(start, end);
|
|
this.column += data.length;
|
|
this.stream.write(data, this.encoding);
|
|
start = end;
|
|
}
|
|
if (char === "'") {
|
|
this.column += 2;
|
|
this.stream.write("''", this.encoding);
|
|
start = end + 1;
|
|
}
|
|
if (char != null) {
|
|
spaces = char === ' ';
|
|
breaks = indexOf.call('\n\x85\u2028\u2029', char) >= 0;
|
|
}
|
|
end++;
|
|
}
|
|
return this.write_indicator("'", false);
|
|
}
|
|
|
|
write_double_quoted(text, split = true) {
|
|
var char, data, end, start;
|
|
this.write_indicator('"', true);
|
|
start = end = 0;
|
|
while (end <= text.length) {
|
|
char = text[end];
|
|
if ((char == null) || indexOf.call('"\\\x85\u2028\u2029\uFEFF', char) >= 0 || !(('\x20' <= char && char <= '\x7E') || (this.allow_unicode && (('\xA0' <= char && char <= '\uD7FF') || ('\uE000' <= char && char <= '\uFFFD'))))) {
|
|
if (start < end) {
|
|
data = text.slice(start, end);
|
|
this.column += data.length;
|
|
this.stream.write(data, this.encoding);
|
|
start = end;
|
|
}
|
|
if (char != null) {
|
|
data = char in ESCAPE_REPLACEMENTS ? '\\' + ESCAPE_REPLACEMENTS[char] : char <= '\xFF' ? `\\x${util.pad_left(util.to_hex(char), '0', 2)}` : char <= '\uFFFF' ? `\\u${util.pad_left(util.to_hex(char), '0', 4)}` : `\\U${util.pad_left(util.to_hex(char), '0', 16)}`;
|
|
this.column += data.length;
|
|
this.stream.write(data, this.encoding);
|
|
start = end + 1;
|
|
}
|
|
}
|
|
if (split && (0 < end && end < text.length - 1) && (char === ' ' || start >= end) && this.column + (end - start) > this.best_width) {
|
|
data = `${text.slice(start, end)}\\`;
|
|
if (start < end) {
|
|
start = end;
|
|
}
|
|
this.column += data.length;
|
|
this.stream.write(data, this.encoding);
|
|
this.write_indent();
|
|
this.whitespace = false;
|
|
this.indentation = false;
|
|
if (text[start] === ' ') {
|
|
data = '\\';
|
|
this.column += data.length;
|
|
this.stream.write(data, this.encoding);
|
|
}
|
|
}
|
|
end++;
|
|
}
|
|
return this.write_indicator('"', false);
|
|
}
|
|
|
|
write_folded(text) {
|
|
var br, breaks, char, data, end, hints, i, leading_space, len, ref, results, spaces, start;
|
|
hints = this.determine_block_hints(text);
|
|
this.write_indicator(`>${hints}`, true);
|
|
if (hints.slice(-1) === '+') {
|
|
this.open_ended = true;
|
|
}
|
|
this.write_line_break();
|
|
leading_space = true;
|
|
breaks = true;
|
|
spaces = false;
|
|
start = end = 0;
|
|
results = [];
|
|
while (end <= text.length) {
|
|
char = text[end];
|
|
if (breaks) {
|
|
if ((char == null) || indexOf.call('\n\x85\u2028\u2029', char) < 0) {
|
|
if (!leading_space && (char != null) && char !== ' ' && text[start] === '\n') {
|
|
this.write_line_break();
|
|
}
|
|
leading_space = char === ' ';
|
|
ref = text.slice(start, end);
|
|
for (i = 0, len = ref.length; i < len; i++) {
|
|
br = ref[i];
|
|
if (br === '\n') {
|
|
this.write_line_break();
|
|
} else {
|
|
this.write_line_break(br);
|
|
}
|
|
}
|
|
if (char != null) {
|
|
this.write_indent();
|
|
}
|
|
start = end;
|
|
}
|
|
} else if (spaces) {
|
|
if (char !== ' ') {
|
|
if (start + 1 === end && this.column > this.best_width) {
|
|
this.write_indent();
|
|
} else {
|
|
data = text.slice(start, end);
|
|
this.column += data.length;
|
|
this.stream.write(data, this.encoding);
|
|
}
|
|
start = end;
|
|
}
|
|
} else if ((char == null) || indexOf.call(' \n\x85\u2028\u2029', char) >= 0) {
|
|
data = text.slice(start, end);
|
|
this.column += data.length;
|
|
this.stream.write(data, this.encoding);
|
|
if (char == null) {
|
|
this.write_line_break();
|
|
}
|
|
start = end;
|
|
}
|
|
if (char != null) {
|
|
breaks = indexOf.call('\n\x85\u2028\u2029', char) >= 0;
|
|
spaces = char === ' ';
|
|
}
|
|
results.push(end++);
|
|
}
|
|
return results;
|
|
}
|
|
|
|
write_literal(text) {
|
|
var br, breaks, char, data, end, hints, i, len, ref, results, start;
|
|
hints = this.determine_block_hints(text);
|
|
this.write_indicator(`|${hints}`, true);
|
|
if (hints.slice(-1) === '+') {
|
|
this.open_ended = true;
|
|
}
|
|
this.write_line_break();
|
|
breaks = true;
|
|
start = end = 0;
|
|
results = [];
|
|
while (end <= text.length) {
|
|
char = text[end];
|
|
if (breaks) {
|
|
if ((char == null) || indexOf.call('\n\x85\u2028\u2029', char) < 0) {
|
|
ref = text.slice(start, end);
|
|
for (i = 0, len = ref.length; i < len; i++) {
|
|
br = ref[i];
|
|
if (br === '\n') {
|
|
this.write_line_break();
|
|
} else {
|
|
this.write_line_break(br);
|
|
}
|
|
}
|
|
if (char != null) {
|
|
this.write_indent();
|
|
}
|
|
start = end;
|
|
}
|
|
} else {
|
|
if ((char == null) || indexOf.call('\n\x85\u2028\u2029', char) >= 0) {
|
|
data = text.slice(start, end);
|
|
this.stream.write(data, this.encoding);
|
|
if (char == null) {
|
|
this.write_line_break();
|
|
}
|
|
start = end;
|
|
}
|
|
}
|
|
if (char != null) {
|
|
breaks = indexOf.call('\n\x85\u2028\u2029', char) >= 0;
|
|
}
|
|
results.push(end++);
|
|
}
|
|
return results;
|
|
}
|
|
|
|
write_plain(text, split = true) {
|
|
var br, breaks, char, data, end, i, len, ref, results, spaces, start;
|
|
if (!text) {
|
|
return;
|
|
}
|
|
if (this.root_context) {
|
|
this.open_ended = true;
|
|
}
|
|
if (!this.whitespace) {
|
|
data = ' ';
|
|
this.column += data.length;
|
|
this.stream.write(data, this.encoding);
|
|
}
|
|
this.whitespace = false;
|
|
this.indentation = false;
|
|
spaces = false;
|
|
breaks = false;
|
|
start = end = 0;
|
|
results = [];
|
|
while (end <= text.length) {
|
|
char = text[end];
|
|
if (spaces) {
|
|
if (char !== ' ') {
|
|
if (start + 1 === end && this.column > this.best_width && split) {
|
|
this.write_indent();
|
|
this.whitespace = false;
|
|
this.indentation = false;
|
|
} else {
|
|
data = text.slice(start, end);
|
|
this.column += data.length;
|
|
this.stream.write(data, this.encoding);
|
|
}
|
|
start = end;
|
|
}
|
|
} else if (breaks) {
|
|
if (indexOf.call('\n\x85\u2028\u2029', char) < 0) {
|
|
if (text[start] === '\n') {
|
|
this.write_line_break();
|
|
}
|
|
ref = text.slice(start, end);
|
|
for (i = 0, len = ref.length; i < len; i++) {
|
|
br = ref[i];
|
|
if (br === '\n') {
|
|
this.write_line_break();
|
|
} else {
|
|
this.write_line_break(br);
|
|
}
|
|
}
|
|
this.write_indent();
|
|
this.whitespace = false;
|
|
this.indentation = false;
|
|
start = end;
|
|
}
|
|
} else {
|
|
if ((char == null) || indexOf.call(' \n\x85\u2028\u2029', char) >= 0) {
|
|
data = text.slice(start, end);
|
|
this.column += data.length;
|
|
this.stream.write(data, this.encoding);
|
|
start = end;
|
|
}
|
|
}
|
|
if (char != null) {
|
|
spaces = char === ' ';
|
|
breaks = indexOf.call('\n\x85\u2028\u2029', char) >= 0;
|
|
}
|
|
results.push(end++);
|
|
}
|
|
return results;
|
|
}
|
|
|
|
determine_block_hints(text) {
|
|
var first, hints, i, last, penultimate;
|
|
hints = '';
|
|
first = text[0], i = text.length - 2, penultimate = text[i++], last = text[i++];
|
|
if (indexOf.call(' \n\x85\u2028\u2029', first) >= 0) {
|
|
hints += this.best_indent;
|
|
}
|
|
if (indexOf.call('\n\x85\u2028\u2029', last) < 0) {
|
|
hints += '-';
|
|
} else if (text.length === 1 || indexOf.call('\n\x85\u2028\u2029', penultimate) >= 0) {
|
|
hints += '+';
|
|
}
|
|
return hints;
|
|
}
|
|
|
|
flush_stream() {
|
|
var base;
|
|
return typeof (base = this.stream).flush === "function" ? base.flush() : void 0;
|
|
}
|
|
|
|
/*
|
|
Helper for common error pattern.
|
|
*/
|
|
error(message, context) {
|
|
var ref, ref1;
|
|
if (context) {
|
|
context = (ref = context != null ? (ref1 = context.constructor) != null ? ref1.name : void 0 : void 0) != null ? ref : util.inspect(context);
|
|
}
|
|
throw new exports.EmitterError(`${message}${(context ? ` ${context}` : '')}`);
|
|
}
|
|
|
|
};
|
|
|
|
C_WHITESPACE = '\0 \t\r\n\x85\u2028\u2029';
|
|
|
|
DEFAULT_TAG_PREFIXES = {
|
|
'!': '!',
|
|
'tag:yaml.org,2002:': '!!'
|
|
};
|
|
|
|
ESCAPE_REPLACEMENTS = {
|
|
'\0': '0',
|
|
'\x07': 'a',
|
|
'\x08': 'b',
|
|
'\x09': 't',
|
|
'\x0A': 'n',
|
|
'\x0B': 'v',
|
|
'\x0C': 'f',
|
|
'\x0D': 'r',
|
|
'\x1B': 'e',
|
|
'"': '"',
|
|
'\\': '\\',
|
|
'\x85': 'N',
|
|
'\xA0': '_',
|
|
'\u2028': 'L',
|
|
'\u2029': 'P'
|
|
};
|
|
|
|
ctor = Emitter.prototype.initialise;
|
|
|
|
return Emitter;
|
|
|
|
}).call(this);
|
|
|
|
ScalarAnalysis = class ScalarAnalysis {
|
|
constructor(scalar1, empty, multiline, allow_flow_plain1, allow_block_plain1, allow_single_quoted1, allow_double_quoted1, allow_block1) {
|
|
this.scalar = scalar1;
|
|
this.empty = empty;
|
|
this.multiline = multiline;
|
|
this.allow_flow_plain = allow_flow_plain1;
|
|
this.allow_block_plain = allow_block_plain1;
|
|
this.allow_single_quoted = allow_single_quoted1;
|
|
this.allow_double_quoted = allow_double_quoted1;
|
|
this.allow_block = allow_block1;
|
|
}
|
|
|
|
};
|
|
|
|
}).call(this);
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 45372:
|
|
/***/ (function() {
|
|
|
|
(function() {
|
|
var indexOf = [].indexOf;
|
|
|
|
this.Mark = class Mark {
|
|
constructor(line, column, buffer, pointer) {
|
|
this.line = line;
|
|
this.column = column;
|
|
this.buffer = buffer;
|
|
this.pointer = pointer;
|
|
}
|
|
|
|
get_snippet(indent = 4, max_length = 75) {
|
|
var break_chars, end, head, ref, ref1, start, tail;
|
|
if (this.buffer == null) {
|
|
return null;
|
|
}
|
|
break_chars = '\x00\r\n\x85\u2028\u2029';
|
|
head = '';
|
|
start = this.pointer;
|
|
while (start > 0 && (ref = this.buffer[start - 1], indexOf.call(break_chars, ref) < 0)) {
|
|
start--;
|
|
if (this.pointer - start > max_length / 2 - 1) {
|
|
head = ' ... ';
|
|
start += 5;
|
|
break;
|
|
}
|
|
}
|
|
tail = '';
|
|
end = this.pointer;
|
|
while (end < this.buffer.length && (ref1 = this.buffer[end], indexOf.call(break_chars, ref1) < 0)) {
|
|
end++;
|
|
if (end - this.pointer > max_length / 2 - 1) {
|
|
tail = ' ... ';
|
|
end -= 5;
|
|
break;
|
|
}
|
|
}
|
|
return `${(new Array(indent)).join(' ')}${head}${this.buffer.slice(start, end)}${tail}\n${(new Array(indent + this.pointer - start + head.length)).join(' ')}^`;
|
|
}
|
|
|
|
toString() {
|
|
var snippet, where;
|
|
snippet = this.get_snippet();
|
|
where = ` on line ${this.line + 1}, column ${this.column + 1}`;
|
|
if (snippet) {
|
|
return where;
|
|
} else {
|
|
return `${where}:\n${snippet}`;
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
this.YAMLError = class YAMLError extends Error {
|
|
constructor(message) {
|
|
super(message);
|
|
// Hack to get the stack on the error somehow
|
|
Object.defineProperty(this, 'stack', {
|
|
get: function() {
|
|
return this.toString() + '\n' + (new Error).stack.split('\n').slice(1).join('\n');
|
|
}
|
|
});
|
|
}
|
|
|
|
toString() {
|
|
return this.message;
|
|
}
|
|
|
|
};
|
|
|
|
this.MarkedYAMLError = class MarkedYAMLError extends this.YAMLError {
|
|
constructor(context, context_mark, problem, problem_mark, note) {
|
|
super();
|
|
this.context = context;
|
|
this.context_mark = context_mark;
|
|
this.problem = problem;
|
|
this.problem_mark = problem_mark;
|
|
this.note = note;
|
|
}
|
|
|
|
toString() {
|
|
var lines;
|
|
lines = [];
|
|
if (this.context != null) {
|
|
lines.push(this.context);
|
|
}
|
|
if ((this.context_mark != null) && ((this.problem == null) || (this.problem_mark == null) || this.context_mark.line !== this.problem_mark.line || this.context_mark.column !== this.problem_mark.column)) {
|
|
lines.push(this.context_mark.toString());
|
|
}
|
|
if (this.problem != null) {
|
|
lines.push(this.problem);
|
|
}
|
|
if (this.problem_mark != null) {
|
|
lines.push(this.problem_mark.toString());
|
|
}
|
|
if (this.note != null) {
|
|
lines.push(this.note);
|
|
}
|
|
return lines.join('\n');
|
|
}
|
|
|
|
};
|
|
|
|
}).call(this);
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 35063:
|
|
/***/ (function() {
|
|
|
|
(function() {
|
|
this.Event = class Event {
|
|
constructor(start_mark1, end_mark1) {
|
|
this.start_mark = start_mark1;
|
|
this.end_mark = end_mark1;
|
|
}
|
|
|
|
};
|
|
|
|
this.NodeEvent = class NodeEvent extends this.Event {
|
|
constructor(anchor1, start_mark, end_mark) {
|
|
super(start_mark, end_mark);
|
|
this.anchor = anchor1;
|
|
}
|
|
|
|
};
|
|
|
|
this.CollectionStartEvent = class CollectionStartEvent extends this.NodeEvent {
|
|
constructor(anchor, tag, implicit, start_mark, end_mark, flow_style) {
|
|
super(anchor, start_mark, end_mark);
|
|
this.tag = tag;
|
|
this.implicit = implicit;
|
|
this.flow_style = flow_style;
|
|
}
|
|
|
|
};
|
|
|
|
this.CollectionEndEvent = class CollectionEndEvent extends this.Event {};
|
|
|
|
this.StreamStartEvent = class StreamStartEvent extends this.Event {
|
|
constructor(start_mark, end_mark, encoding) {
|
|
super(start_mark, end_mark);
|
|
this.encoding = encoding;
|
|
}
|
|
|
|
};
|
|
|
|
this.StreamEndEvent = class StreamEndEvent extends this.Event {};
|
|
|
|
this.DocumentStartEvent = class DocumentStartEvent extends this.Event {
|
|
constructor(start_mark, end_mark, explicit, version, tags) {
|
|
super(start_mark, end_mark);
|
|
this.explicit = explicit;
|
|
this.version = version;
|
|
this.tags = tags;
|
|
}
|
|
|
|
};
|
|
|
|
this.DocumentEndEvent = class DocumentEndEvent extends this.Event {
|
|
constructor(start_mark, end_mark, explicit) {
|
|
super(start_mark, end_mark);
|
|
this.explicit = explicit;
|
|
}
|
|
|
|
};
|
|
|
|
this.AliasEvent = class AliasEvent extends this.NodeEvent {};
|
|
|
|
this.ScalarEvent = class ScalarEvent extends this.NodeEvent {
|
|
constructor(anchor, tag, implicit, value, start_mark, end_mark, style) {
|
|
super(anchor, start_mark, end_mark);
|
|
this.tag = tag;
|
|
this.implicit = implicit;
|
|
this.value = value;
|
|
this.style = style;
|
|
}
|
|
|
|
};
|
|
|
|
this.SequenceStartEvent = class SequenceStartEvent extends this.CollectionStartEvent {};
|
|
|
|
this.SequenceEndEvent = class SequenceEndEvent extends this.CollectionEndEvent {};
|
|
|
|
this.MappingStartEvent = class MappingStartEvent extends this.CollectionStartEvent {};
|
|
|
|
this.MappingEndEvent = class MappingEndEvent extends this.CollectionEndEvent {};
|
|
|
|
}).call(this);
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 82696:
|
|
/***/ (function(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) {
|
|
|
|
(function() {
|
|
var composer, constructor, parser, reader, resolver, scanner, util;
|
|
|
|
util = __webpack_require__(23823);
|
|
|
|
reader = __webpack_require__(27026);
|
|
|
|
scanner = __webpack_require__(72265);
|
|
|
|
parser = __webpack_require__(72806);
|
|
|
|
composer = __webpack_require__(6391);
|
|
|
|
resolver = __webpack_require__(3579);
|
|
|
|
constructor = __webpack_require__(51574);
|
|
|
|
this.make_loader = function(Reader = reader.Reader, Scanner = scanner.Scanner, Parser = parser.Parser, Composer = composer.Composer, Resolver = resolver.Resolver, Constructor = constructor.Constructor) {
|
|
var Loader, components;
|
|
components = [Reader, Scanner, Parser, Composer, Resolver, Constructor];
|
|
return Loader = (function() {
|
|
var component;
|
|
|
|
class Loader {
|
|
constructor(stream) {
|
|
var i, len, ref;
|
|
components[0].prototype.initialise.call(this, stream);
|
|
ref = components.slice(1);
|
|
for (i = 0, len = ref.length; i < len; i++) {
|
|
component = ref[i];
|
|
component.prototype.initialise.call(this);
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
util.extend(Loader.prototype, ...((function() {
|
|
var i, len, results;
|
|
results = [];
|
|
for (i = 0, len = components.length; i < len; i++) {
|
|
component = components[i];
|
|
results.push(component.prototype);
|
|
}
|
|
return results;
|
|
})()));
|
|
|
|
return Loader;
|
|
|
|
}).call(this);
|
|
};
|
|
|
|
this.Loader = this.make_loader();
|
|
|
|
}).call(this);
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 96914:
|
|
/***/ (function() {
|
|
|
|
(function() {
|
|
var unique_id;
|
|
|
|
unique_id = 0;
|
|
|
|
this.Node = class Node {
|
|
constructor(tag1, value1, start_mark1, end_mark1) {
|
|
this.tag = tag1;
|
|
this.value = value1;
|
|
this.start_mark = start_mark1;
|
|
this.end_mark = end_mark1;
|
|
this.unique_id = `node_${unique_id++}`;
|
|
}
|
|
|
|
};
|
|
|
|
this.ScalarNode = (function() {
|
|
class ScalarNode extends this.Node {
|
|
constructor(tag, value, start_mark, end_mark, style) {
|
|
super(tag, value, start_mark, end_mark);
|
|
this.style = style;
|
|
}
|
|
|
|
};
|
|
|
|
ScalarNode.prototype.id = 'scalar';
|
|
|
|
return ScalarNode;
|
|
|
|
}).call(this);
|
|
|
|
this.CollectionNode = class CollectionNode extends this.Node {
|
|
constructor(tag, value, start_mark, end_mark, flow_style) {
|
|
super(tag, value, start_mark, end_mark);
|
|
this.flow_style = flow_style;
|
|
}
|
|
|
|
};
|
|
|
|
this.SequenceNode = (function() {
|
|
class SequenceNode extends this.CollectionNode {};
|
|
|
|
SequenceNode.prototype.id = 'sequence';
|
|
|
|
return SequenceNode;
|
|
|
|
}).call(this);
|
|
|
|
this.MappingNode = (function() {
|
|
class MappingNode extends this.CollectionNode {};
|
|
|
|
MappingNode.prototype.id = 'mapping';
|
|
|
|
return MappingNode;
|
|
|
|
}).call(this);
|
|
|
|
}).call(this);
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 72806:
|
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
|
|
(function() {
|
|
var MarkedYAMLError, events, tokens,
|
|
hasProp = {}.hasOwnProperty;
|
|
|
|
events = __webpack_require__(35063);
|
|
|
|
({MarkedYAMLError} = __webpack_require__(45372));
|
|
|
|
tokens = __webpack_require__(59902);
|
|
|
|
this.ParserError = class ParserError extends MarkedYAMLError {};
|
|
|
|
this.Parser = (function() {
|
|
var DEFAULT_TAGS, ctor;
|
|
|
|
class Parser {
|
|
constructor() {
|
|
return ctor.apply(this, arguments);
|
|
}
|
|
|
|
initialise() {
|
|
this.current_event = null;
|
|
this.yaml_version = null;
|
|
this.tag_handles = {};
|
|
this.states = [];
|
|
this.marks = [];
|
|
return this.state = 'parse_stream_start';
|
|
}
|
|
|
|
/*
|
|
Reset the state attributes.
|
|
*/
|
|
dispose() {
|
|
this.states = [];
|
|
return this.state = null;
|
|
}
|
|
|
|
/*
|
|
Check the type of the next event.
|
|
*/
|
|
check_event(...choices) {
|
|
var choice, i, len;
|
|
if (this.current_event === null) {
|
|
if (this.state != null) {
|
|
this.current_event = this[this.state]();
|
|
}
|
|
}
|
|
if (this.current_event !== null) {
|
|
if (choices.length === 0) {
|
|
return true;
|
|
}
|
|
for (i = 0, len = choices.length; i < len; i++) {
|
|
choice = choices[i];
|
|
if (this.current_event instanceof choice) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
Get the next event.
|
|
*/
|
|
peek_event() {
|
|
if (this.current_event === null && (this.state != null)) {
|
|
this.current_event = this[this.state]();
|
|
}
|
|
return this.current_event;
|
|
}
|
|
|
|
/*
|
|
Get the event and proceed further.
|
|
*/
|
|
get_event() {
|
|
var event;
|
|
if (this.current_event === null && (this.state != null)) {
|
|
this.current_event = this[this.state]();
|
|
}
|
|
event = this.current_event;
|
|
this.current_event = null;
|
|
return event;
|
|
}
|
|
|
|
// stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
|
|
// implicit_document ::= block_node DOCUMENT-END*
|
|
// explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END*
|
|
/*
|
|
Parse the stream start.
|
|
*/
|
|
parse_stream_start() {
|
|
var event, token;
|
|
token = this.get_token();
|
|
event = new events.StreamStartEvent(token.start_mark, token.end_mark);
|
|
// Prepare the next state,
|
|
this.state = 'parse_implicit_document_start';
|
|
return event;
|
|
}
|
|
|
|
/*
|
|
Parse an implicit document.
|
|
*/
|
|
parse_implicit_document_start() {
|
|
var end_mark, event, start_mark, token;
|
|
if (!this.check_token(tokens.DirectiveToken, tokens.DocumentStartToken, tokens.StreamEndToken)) {
|
|
this.tag_handles = DEFAULT_TAGS;
|
|
token = this.peek_token();
|
|
start_mark = end_mark = token.start_mark;
|
|
event = new events.DocumentStartEvent(start_mark, end_mark, false);
|
|
// Prepare the next state
|
|
this.states.push('parse_document_end');
|
|
this.state = 'parse_block_node';
|
|
return event;
|
|
} else {
|
|
return this.parse_document_start();
|
|
}
|
|
}
|
|
|
|
/*
|
|
Parse an explicit document.
|
|
*/
|
|
parse_document_start() {
|
|
var end_mark, event, start_mark, tags, token, version;
|
|
while (this.check_token(tokens.DocumentEndToken)) {
|
|
// Parse any extra document end indicators
|
|
this.get_token();
|
|
}
|
|
if (!this.check_token(tokens.StreamEndToken)) {
|
|
start_mark = this.peek_token().start_mark;
|
|
[version, tags] = this.process_directives();
|
|
if (!this.check_token(tokens.DocumentStartToken)) {
|
|
throw new exports.ParserError(`expected '<document start>', but found ${(this.peek_token().id)}`, this.peek_token().start_mark);
|
|
}
|
|
token = this.get_token();
|
|
end_mark = token.end_mark;
|
|
event = new events.DocumentStartEvent(start_mark, end_mark, true, version, tags);
|
|
this.states.push('parse_document_end');
|
|
this.state = 'parse_document_content';
|
|
} else {
|
|
// Parse the end of the stream.
|
|
token = this.get_token();
|
|
event = new events.StreamEndEvent(token.start_mark, token.end_mark);
|
|
if (this.states.length !== 0) {
|
|
throw new Error('assertion error, states should be empty');
|
|
}
|
|
if (this.marks.length !== 0) {
|
|
throw new Error('assertion error, marks should be empty');
|
|
}
|
|
this.state = null;
|
|
}
|
|
return event;
|
|
}
|
|
|
|
/*
|
|
Parse the document end.
|
|
*/
|
|
parse_document_end() {
|
|
var end_mark, event, explicit, start_mark, token;
|
|
token = this.peek_token();
|
|
start_mark = end_mark = token.start_mark;
|
|
explicit = false;
|
|
if (this.check_token(tokens.DocumentEndToken)) {
|
|
token = this.get_token();
|
|
end_mark = token.end_mark;
|
|
explicit = true;
|
|
}
|
|
event = new events.DocumentEndEvent(start_mark, end_mark, explicit);
|
|
// Prepare next state.
|
|
this.state = 'parse_document_start';
|
|
return event;
|
|
}
|
|
|
|
parse_document_content() {
|
|
var event;
|
|
if (this.check_token(tokens.DirectiveToken, tokens.DocumentStartToken, tokens.DocumentEndToken, tokens.StreamEndToken)) {
|
|
event = this.process_empty_scalar(this.peek_token().start_mark);
|
|
this.state = this.states.pop();
|
|
return event;
|
|
} else {
|
|
return this.parse_block_node();
|
|
}
|
|
}
|
|
|
|
process_directives() {
|
|
var handle, major, minor, prefix, ref, tag_handles_copy, token, value;
|
|
this.yaml_version = null;
|
|
this.tag_handles = {};
|
|
while (this.check_token(tokens.DirectiveToken)) {
|
|
token = this.get_token();
|
|
if (token.name === 'YAML') {
|
|
if (this.yaml_version !== null) {
|
|
throw new exports.ParserError(null, null, 'found duplicate YAML directive', token.start_mark);
|
|
}
|
|
[major, minor] = token.value;
|
|
if (major !== 1) {
|
|
throw new exports.ParserError(null, null, 'found incompatible YAML document (version 1.* is required)', token.start_mark);
|
|
}
|
|
this.yaml_version = token.value;
|
|
} else if (token.name === 'TAG') {
|
|
[handle, prefix] = token.value;
|
|
if (handle in this.tag_handles) {
|
|
throw new exports.ParserError(null, null, `duplicate tag handle ${handle}`, token.start_mark);
|
|
}
|
|
this.tag_handles[handle] = prefix;
|
|
}
|
|
}
|
|
tag_handles_copy = null;
|
|
ref = this.tag_handles;
|
|
for (handle in ref) {
|
|
if (!hasProp.call(ref, handle)) continue;
|
|
prefix = ref[handle];
|
|
if (tag_handles_copy == null) {
|
|
tag_handles_copy = {};
|
|
}
|
|
tag_handles_copy[handle] = prefix;
|
|
}
|
|
value = [this.yaml_version, tag_handles_copy];
|
|
for (handle in DEFAULT_TAGS) {
|
|
if (!hasProp.call(DEFAULT_TAGS, handle)) continue;
|
|
prefix = DEFAULT_TAGS[handle];
|
|
if (!(prefix in this.tag_handles)) {
|
|
this.tag_handles[handle] = prefix;
|
|
}
|
|
}
|
|
return value;
|
|
}
|
|
|
|
// block_node_or_indentless_sequence ::= ALIAS
|
|
// | properties (block_content | indentless_sequence)?
|
|
// | block_content
|
|
// | indentless_block_sequence
|
|
// block_node ::= ALIAS
|
|
// | properties block_content?
|
|
// | block_content
|
|
// flow_node ::= ALIAS
|
|
// | properties flow_content?
|
|
// | flow_content
|
|
// properties ::= TAG ANCHOR? | ANCHOR TAG?
|
|
// block_content ::= block_collection | flow_collection | SCALAR
|
|
// flow_content ::= flow_collection | SCALAR
|
|
// block_collection ::= block_sequence | block_mapping
|
|
// flow_collection ::= flow_sequence | flow_mapping
|
|
parse_block_node() {
|
|
return this.parse_node(true);
|
|
}
|
|
|
|
parse_flow_node() {
|
|
return this.parse_node();
|
|
}
|
|
|
|
parse_block_node_or_indentless_sequence() {
|
|
return this.parse_node(true, true);
|
|
}
|
|
|
|
parse_node(block = false, indentless_sequence = false) {
|
|
var anchor, end_mark, event, handle, implicit, node, start_mark, suffix, tag, tag_mark, token;
|
|
if (this.check_token(tokens.AliasToken)) {
|
|
token = this.get_token();
|
|
event = new events.AliasEvent(token.value, token.start_mark, token.end_mark);
|
|
this.state = this.states.pop();
|
|
} else {
|
|
anchor = null;
|
|
tag = null;
|
|
start_mark = end_mark = tag_mark = null;
|
|
if (this.check_token(tokens.AnchorToken)) {
|
|
token = this.get_token();
|
|
start_mark = token.start_mark;
|
|
end_mark = token.end_mark;
|
|
anchor = token.value;
|
|
if (this.check_token(tokens.TagToken)) {
|
|
token = this.get_token();
|
|
tag_mark = token.start_mark;
|
|
end_mark = token.end_mark;
|
|
tag = token.value;
|
|
}
|
|
} else if (this.check_token(tokens.TagToken)) {
|
|
token = this.get_token();
|
|
start_mark = tag_mark = token.start_mark;
|
|
end_mark = token.end_mark;
|
|
tag = token.value;
|
|
if (this.check_token(tokens.AnchorToken)) {
|
|
token = this.get_token();
|
|
end_mark = token.end_mark;
|
|
anchor = token.value;
|
|
}
|
|
}
|
|
if (tag !== null) {
|
|
[handle, suffix] = tag;
|
|
if (handle !== null) {
|
|
if (!(handle in this.tag_handles)) {
|
|
throw new exports.ParserError('while parsing a node', start_mark, `found undefined tag handle ${handle}`, tag_mark);
|
|
}
|
|
tag = this.tag_handles[handle] + suffix;
|
|
} else {
|
|
tag = suffix;
|
|
}
|
|
}
|
|
if (start_mark === null) {
|
|
start_mark = end_mark = this.peek_token().start_mark;
|
|
}
|
|
event = null;
|
|
implicit = tag === null || tag === '!';
|
|
if (indentless_sequence && this.check_token(tokens.BlockEntryToken)) {
|
|
end_mark = this.peek_token().end_mark;
|
|
event = new events.SequenceStartEvent(anchor, tag, implicit, start_mark, end_mark);
|
|
this.state = 'parse_indentless_sequence_entry';
|
|
} else {
|
|
if (this.check_token(tokens.ScalarToken)) {
|
|
token = this.get_token();
|
|
end_mark = token.end_mark;
|
|
if ((token.plain && tag === null) || tag === '!') {
|
|
implicit = [true, false];
|
|
} else if (tag === null) {
|
|
implicit = [false, true];
|
|
} else {
|
|
implicit = [false, false];
|
|
}
|
|
event = new events.ScalarEvent(anchor, tag, implicit, token.value, start_mark, end_mark, token.style);
|
|
this.state = this.states.pop();
|
|
} else if (this.check_token(tokens.FlowSequenceStartToken)) {
|
|
end_mark = this.peek_token().end_mark;
|
|
event = new events.SequenceStartEvent(anchor, tag, implicit, start_mark, end_mark, true);
|
|
this.state = 'parse_flow_sequence_first_entry';
|
|
} else if (this.check_token(tokens.FlowMappingStartToken)) {
|
|
end_mark = this.peek_token().end_mark;
|
|
event = new events.MappingStartEvent(anchor, tag, implicit, start_mark, end_mark, true);
|
|
this.state = 'parse_flow_mapping_first_key';
|
|
} else if (block && this.check_token(tokens.BlockSequenceStartToken)) {
|
|
end_mark = this.peek_token().end_mark;
|
|
event = new events.SequenceStartEvent(anchor, tag, implicit, start_mark, end_mark, false);
|
|
this.state = 'parse_block_sequence_first_entry';
|
|
} else if (block && this.check_token(tokens.BlockMappingStartToken)) {
|
|
end_mark = this.peek_token().end_mark;
|
|
event = new events.MappingStartEvent(anchor, tag, implicit, start_mark, end_mark, false);
|
|
this.state = 'parse_block_mapping_first_key';
|
|
} else if (anchor !== null || tag !== null) {
|
|
// Empty scalars are allowed even if a tag or an anchor is specified.
|
|
event = new events.ScalarEvent(anchor, tag, [implicit, false], '', start_mark, end_mark);
|
|
this.state = this.states.pop();
|
|
} else {
|
|
if (block) {
|
|
node = 'block';
|
|
} else {
|
|
node = 'flow';
|
|
}
|
|
token = this.peek_token();
|
|
throw new exports.ParserError(`while parsing a ${node} node`, start_mark, `expected the node content, but found ${token.id}`, token.start_mark);
|
|
}
|
|
}
|
|
}
|
|
return event;
|
|
}
|
|
|
|
// block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)*
|
|
// BLOCK-END
|
|
parse_block_sequence_first_entry() {
|
|
var token;
|
|
token = this.get_token();
|
|
this.marks.push(token.start_mark);
|
|
return this.parse_block_sequence_entry();
|
|
}
|
|
|
|
parse_block_sequence_entry() {
|
|
var event, token;
|
|
if (this.check_token(tokens.BlockEntryToken)) {
|
|
token = this.get_token();
|
|
if (!this.check_token(tokens.BlockEntryToken, tokens.BlockEndToken)) {
|
|
this.states.push('parse_block_sequence_entry');
|
|
return this.parse_block_node();
|
|
} else {
|
|
this.state = 'parse_block_sequence_entry';
|
|
return this.process_empty_scalar(token.end_mark);
|
|
}
|
|
}
|
|
if (!this.check_token(tokens.BlockEndToken)) {
|
|
token = this.peek_token();
|
|
throw new exports.ParserError('while parsing a block collection', this.marks.slice(-1)[0], `expected <block end>, but found ${token.id}`, token.start_mark);
|
|
}
|
|
token = this.get_token();
|
|
event = new events.SequenceEndEvent(token.start_mark, token.end_mark);
|
|
this.state = this.states.pop();
|
|
this.marks.pop();
|
|
return event;
|
|
}
|
|
|
|
// indentless_sequence ::= (BLOCK-ENTRY block_node?)+
|
|
parse_indentless_sequence_entry() {
|
|
var event, token;
|
|
if (this.check_token(tokens.BlockEntryToken)) {
|
|
token = this.get_token();
|
|
if (!this.check_token(tokens.BlockEntryToken, tokens.KeyToken, tokens.ValueToken, tokens.BlockEndToken)) {
|
|
this.states.push('parse_indentless_sequence_entry');
|
|
return this.parse_block_node();
|
|
} else {
|
|
this.state = 'parse_indentless_sequence_entry';
|
|
return this.process_empty_scalar(token.end_mark);
|
|
}
|
|
}
|
|
token = this.peek_token();
|
|
event = new events.SequenceEndEvent(token.start_mark, token.start_mark);
|
|
this.state = this.states.pop();
|
|
return event;
|
|
}
|
|
|
|
// block_mapping ::= BLOCK-MAPPING-START
|
|
// ((KEY block_node_or_indentless_sequence?)?
|
|
// (VALUE block_node_or_indentless_sequence?)?)* BLOCK-END
|
|
parse_block_mapping_first_key() {
|
|
var token;
|
|
token = this.get_token();
|
|
this.marks.push(token.start_mark);
|
|
return this.parse_block_mapping_key();
|
|
}
|
|
|
|
parse_block_mapping_key() {
|
|
var event, token;
|
|
if (this.check_token(tokens.KeyToken)) {
|
|
token = this.get_token();
|
|
if (!this.check_token(tokens.KeyToken, tokens.ValueToken, tokens.BlockEndToken)) {
|
|
this.states.push('parse_block_mapping_value');
|
|
return this.parse_block_node_or_indentless_sequence();
|
|
} else {
|
|
this.state = 'parse_block_mapping_value';
|
|
return this.process_empty_scalar(token.end_mark);
|
|
}
|
|
}
|
|
if (!this.check_token(tokens.BlockEndToken)) {
|
|
token = this.peek_token();
|
|
throw new exports.ParserError('while parsing a block mapping', this.marks.slice(-1)[0], `expected <block end>, but found ${token.id}`, token.start_mark);
|
|
}
|
|
token = this.get_token();
|
|
event = new events.MappingEndEvent(token.start_mark, token.end_mark);
|
|
this.state = this.states.pop();
|
|
this.marks.pop();
|
|
return event;
|
|
}
|
|
|
|
parse_block_mapping_value() {
|
|
var token;
|
|
if (this.check_token(tokens.ValueToken)) {
|
|
token = this.get_token();
|
|
if (!this.check_token(tokens.KeyToken, tokens.ValueToken, tokens.BlockEndToken)) {
|
|
this.states.push('parse_block_mapping_key');
|
|
return this.parse_block_node_or_indentless_sequence();
|
|
} else {
|
|
this.state = 'parse_block_mapping_key';
|
|
return this.process_empty_scalar(token.end_mark);
|
|
}
|
|
} else {
|
|
this.state = 'parse_block_mapping_key';
|
|
token = this.peek_token();
|
|
return this.process_empty_scalar(token.start_mark);
|
|
}
|
|
}
|
|
|
|
// flow_sequence ::= FLOW-SEQUENCE-START
|
|
// (flow_sequence_entry FLOW-ENTRY)* flow_sequence_entry? FLOW-SEQUENCE-END
|
|
// flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
|
|
|
|
// Note that while production rules for both flow_sequence_entry and
|
|
// flow_mapping_entry are equal, their interpretations are different. For
|
|
// `flow_sequence_entry`, the part `KEY flow_node? (VALUE flow_node?)?`
|
|
// generate an inline mapping (set syntax).
|
|
parse_flow_sequence_first_entry() {
|
|
var token;
|
|
token = this.get_token();
|
|
this.marks.push(token.start_mark);
|
|
return this.parse_flow_sequence_entry(true);
|
|
}
|
|
|
|
parse_flow_sequence_entry(first = false) {
|
|
var event, token;
|
|
if (!this.check_token(tokens.FlowSequenceEndToken)) {
|
|
if (!first) {
|
|
if (this.check_token(tokens.FlowEntryToken)) {
|
|
this.get_token();
|
|
} else {
|
|
token = this.peek_token();
|
|
throw new exports.ParserError('while parsing a flow sequence', this.marks.slice(-1)[0], `expected ',' or ']', but got ${token.id}`, token.start_mark);
|
|
}
|
|
}
|
|
if (this.check_token(tokens.KeyToken)) {
|
|
token = this.peek_token();
|
|
event = new events.MappingStartEvent(null, null, true, token.start_mark, token.end_mark, true);
|
|
this.state = 'parse_flow_sequence_entry_mapping_key';
|
|
return event;
|
|
} else if (!this.check_token(tokens.FlowSequenceEndToken)) {
|
|
this.states.push('parse_flow_sequence_entry');
|
|
return this.parse_flow_node();
|
|
}
|
|
}
|
|
token = this.get_token();
|
|
event = new events.SequenceEndEvent(token.start_mark, token.end_mark);
|
|
this.state = this.states.pop();
|
|
this.marks.pop();
|
|
return event;
|
|
}
|
|
|
|
parse_flow_sequence_entry_mapping_key() {
|
|
var token;
|
|
token = this.get_token();
|
|
if (!this.check_token(tokens.ValueToken, tokens.FlowEntryToken, tokens.FlowSequenceEndToken)) {
|
|
this.states.push('parse_flow_sequence_entry_mapping_value');
|
|
return this.parse_flow_node();
|
|
} else {
|
|
this.state = 'parse_flow_sequence_entry_mapping_value';
|
|
return this.process_empty_scalar(token.end_mark);
|
|
}
|
|
}
|
|
|
|
parse_flow_sequence_entry_mapping_value() {
|
|
var token;
|
|
if (this.check_token(tokens.ValueToken)) {
|
|
token = this.get_token();
|
|
if (!this.check_token(tokens.FlowEntryToken, tokens.FlowSequenceEndToken)) {
|
|
this.states.push('parse_flow_sequence_entry_mapping_end');
|
|
return this.parse_flow_node();
|
|
} else {
|
|
this.state = 'parse_flow_sequence_entry_mapping_end';
|
|
return this.process_empty_scalar(token.end_mark);
|
|
}
|
|
} else {
|
|
this.state = 'parse_flow_sequence_entry_mapping_end';
|
|
token = this.peek_token();
|
|
return this.process_empty_scalar(token.start_mark);
|
|
}
|
|
}
|
|
|
|
parse_flow_sequence_entry_mapping_end() {
|
|
var token;
|
|
this.state = 'parse_flow_sequence_entry';
|
|
token = this.peek_token();
|
|
return new events.MappingEndEvent(token.start_mark, token.start_mark);
|
|
}
|
|
|
|
// flow_mapping ::= FLOW-MAPPING-START (flow_mapping_entry FLOW-ENTRY)*
|
|
// flow_mapping_entry? FLOW-MAPPING-END
|
|
// flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
|
|
parse_flow_mapping_first_key() {
|
|
var token;
|
|
token = this.get_token();
|
|
this.marks.push(token.start_mark);
|
|
return this.parse_flow_mapping_key(true);
|
|
}
|
|
|
|
parse_flow_mapping_key(first = false) {
|
|
var event, token;
|
|
if (!this.check_token(tokens.FlowMappingEndToken)) {
|
|
if (!first) {
|
|
if (this.check_token(tokens.FlowEntryToken)) {
|
|
this.get_token();
|
|
} else {
|
|
token = this.peek_token();
|
|
throw new exports.ParserError('while parsing a flow mapping', this.marks.slice(-1)[0], `expected ',' or '}', but got ${token.id}`, token.start_mark);
|
|
}
|
|
}
|
|
if (this.check_token(tokens.KeyToken)) {
|
|
token = this.get_token();
|
|
if (!this.check_token(tokens.ValueToken, tokens.FlowEntryToken, tokens.FlowMappingEndToken)) {
|
|
this.states.push('parse_flow_mapping_value');
|
|
return this.parse_flow_node();
|
|
} else {
|
|
this.state = 'parse_flow_mapping_value';
|
|
return this.process_empty_scalar(token.end_mark);
|
|
}
|
|
} else if (!this.check_token(tokens.FlowMappingEndToken)) {
|
|
this.states.push('parse_flow_mapping_empty_value');
|
|
return this.parse_flow_node();
|
|
}
|
|
}
|
|
token = this.get_token();
|
|
event = new events.MappingEndEvent(token.start_mark, token.end_mark);
|
|
this.state = this.states.pop();
|
|
this.marks.pop();
|
|
return event;
|
|
}
|
|
|
|
parse_flow_mapping_value() {
|
|
var token;
|
|
if (this.check_token(tokens.ValueToken)) {
|
|
token = this.get_token();
|
|
if (!this.check_token(tokens.FlowEntryToken, tokens.FlowMappingEndToken)) {
|
|
this.states.push('parse_flow_mapping_key');
|
|
return this.parse_flow_node();
|
|
} else {
|
|
this.state = 'parse_flow_mapping_key';
|
|
return this.process_empty_scalar(token.end_mark);
|
|
}
|
|
} else {
|
|
this.state = 'parse_flow_mapping_key';
|
|
token = this.peek_token();
|
|
return this.process_empty_scalar(token.start_mark);
|
|
}
|
|
}
|
|
|
|
parse_flow_mapping_empty_value() {
|
|
this.state = 'parse_flow_mapping_key';
|
|
return this.process_empty_scalar(this.peek_token().start_mark);
|
|
}
|
|
|
|
process_empty_scalar(mark) {
|
|
return new events.ScalarEvent(null, null, [true, false], '', mark, mark);
|
|
}
|
|
|
|
};
|
|
|
|
DEFAULT_TAGS = {
|
|
'!': '!',
|
|
'!!': 'tag:yaml.org,2002:'
|
|
};
|
|
|
|
ctor = Parser.prototype.initialise;
|
|
|
|
return Parser;
|
|
|
|
}).call(this);
|
|
|
|
}).call(this);
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 27026:
|
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
|
|
(function() {
|
|
var Mark, YAMLError,
|
|
indexOf = [].indexOf;
|
|
|
|
({Mark, YAMLError} = __webpack_require__(45372));
|
|
|
|
this.ReaderError = class ReaderError extends YAMLError {
|
|
constructor(position1, character1, reason) {
|
|
super();
|
|
this.position = position1;
|
|
this.character = character1;
|
|
this.reason = reason;
|
|
}
|
|
|
|
toString() {
|
|
return `unacceptable character #${this.character.charCodeAt(0).toString(16)}: ${this.reason}\n position ${this.position}`;
|
|
}
|
|
|
|
};
|
|
|
|
/*
|
|
Reader:
|
|
checks if characters are within the allowed range
|
|
add '\x00' to the end
|
|
*/
|
|
this.Reader = (function() {
|
|
var NON_PRINTABLE, ctor;
|
|
|
|
class Reader {
|
|
constructor() {
|
|
return ctor.apply(this, arguments);
|
|
}
|
|
|
|
initialise(string) {
|
|
this.string = string;
|
|
this.line = 0;
|
|
this.column = 0;
|
|
this.index = 0;
|
|
this.check_printable();
|
|
return this.string += '\x00';
|
|
}
|
|
|
|
peek(index = 0) {
|
|
return this.string[this.index + index];
|
|
}
|
|
|
|
prefix(length = 1) {
|
|
return this.string.slice(this.index, this.index + length);
|
|
}
|
|
|
|
forward(length = 1) {
|
|
var char, results;
|
|
results = [];
|
|
while (length) {
|
|
char = this.string[this.index];
|
|
this.index++;
|
|
if (indexOf.call('\n\x85\u2082\u2029', char) >= 0 || (char === '\r' && this.string[this.index] !== '\n')) {
|
|
this.line++;
|
|
this.column = 0;
|
|
} else {
|
|
this.column++;
|
|
}
|
|
results.push(length--);
|
|
}
|
|
return results;
|
|
}
|
|
|
|
get_mark() {
|
|
return new Mark(this.line, this.column, this.string, this.index);
|
|
}
|
|
|
|
check_printable() {
|
|
var character, match, position;
|
|
match = NON_PRINTABLE.exec(this.string);
|
|
if (match) {
|
|
character = match[0];
|
|
position = (this.string.length - this.index) + match.index;
|
|
throw new exports.ReaderError(position, character, 'special characters are not allowed');
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
NON_PRINTABLE = /[^\x09\x0A\x0D\x20-\x7E\x85\xA0-\uFFFD]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/; // Invalid single characters
|
|
// Missing or invalid low surrogate
|
|
// Missing or invalid high surrogate
|
|
|
|
ctor = Reader.prototype.initialise;
|
|
|
|
return Reader;
|
|
|
|
}).call(this);
|
|
|
|
}).call(this);
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 13832:
|
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
|
|
(function() {
|
|
var YAMLError, nodes,
|
|
hasProp = {}.hasOwnProperty;
|
|
|
|
nodes = __webpack_require__(96914);
|
|
|
|
({YAMLError} = __webpack_require__(45372));
|
|
|
|
this.RepresenterError = class RepresenterError extends YAMLError {};
|
|
|
|
this.BaseRepresenter = (function() {
|
|
var ctor;
|
|
|
|
class BaseRepresenter {
|
|
constructor() {
|
|
return ctor.apply(this, arguments);
|
|
}
|
|
|
|
static add_representer(data_type, handler) {
|
|
if (!this.prototype.hasOwnProperty('yaml_representers_types')) {
|
|
this.prototype.yaml_representers_types = [].concat(this.prototype.yaml_representers_types);
|
|
}
|
|
if (!this.prototype.hasOwnProperty('yaml_representers_handlers')) {
|
|
this.prototype.yaml_representers_handlers = [].concat(this.prototype.yaml_representers_handlers);
|
|
}
|
|
this.prototype.yaml_representers_types.push(data_type);
|
|
return this.prototype.yaml_representers_handlers.push(handler);
|
|
}
|
|
|
|
static add_multi_representer(data_type, handler) {
|
|
if (!this.prototype.hasOwnProperty('yaml_multi_representers_types')) {
|
|
this.prototype.yaml_multi_representers_types = [].concat(this.prototype.yaml_multi_representers_types);
|
|
}
|
|
if (!this.prototype.hasOwnProperty('yaml_multi_representers_handlers')) {
|
|
this.prototype.yaml_multi_representers_handlers = [].concat(this.prototype.yaml_multi_representers_handlers);
|
|
}
|
|
this.prototype.yaml_multi_representers_types.push(data_type);
|
|
return this.prototype.yaml_multi_representers_handlers.push(handler);
|
|
}
|
|
|
|
initialise({
|
|
default_style: default_style,
|
|
default_flow_style: default_flow_style
|
|
} = {}) {
|
|
this.default_style = default_style;
|
|
this.default_flow_style = default_flow_style;
|
|
this.represented_objects = {};
|
|
this.object_keeper = [];
|
|
return this.alias_key = null;
|
|
}
|
|
|
|
represent(data) {
|
|
var node;
|
|
node = this.represent_data(data);
|
|
this.serialize(node);
|
|
this.represented_objects = {};
|
|
this.object_keeper = [];
|
|
return this.alias_key = null;
|
|
}
|
|
|
|
represent_data(data) {
|
|
var data_type, i, j, len, ref, representer, type;
|
|
if (this.ignore_aliases(data)) {
|
|
this.alias_key = null;
|
|
} else if ((i = this.object_keeper.indexOf(data)) !== -1) {
|
|
this.alias_key = i;
|
|
if (this.alias_key in this.represented_objects) {
|
|
return this.represented_objects[this.alias_key];
|
|
}
|
|
} else {
|
|
this.alias_key = this.object_keeper.length;
|
|
this.object_keeper.push(data);
|
|
}
|
|
// Bit fiddly: we look into our non-multi representers using the JS type if `data` is not an
|
|
// object, otherwise we use the object's constructor. For multi-representers we just use
|
|
// instanceof. A representer for `undefined` can be called for any type.
|
|
representer = null;
|
|
data_type = data === null ? 'null' : typeof data;
|
|
if (data_type === 'object') {
|
|
data_type = data.constructor;
|
|
}
|
|
if ((i = this.yaml_representers_types.lastIndexOf(data_type)) !== -1) {
|
|
representer = this.yaml_representers_handlers[i];
|
|
}
|
|
if (representer == null) {
|
|
ref = this.yaml_multi_representers_types;
|
|
for (i = j = 0, len = ref.length; j < len; i = ++j) {
|
|
type = ref[i];
|
|
if (!(data instanceof type)) {
|
|
continue;
|
|
}
|
|
representer = this.yaml_multi_representers_handlers[i];
|
|
break;
|
|
}
|
|
}
|
|
if (representer == null) {
|
|
if ((i = this.yaml_multi_representers_types.lastIndexOf(void 0)) !== -1) {
|
|
representer = this.yaml_multi_representers_handlers[i];
|
|
} else if ((i = this.yaml_representers_types.lastIndexOf(void 0)) !== -1) {
|
|
representer = this.yaml_representers_handlers[i];
|
|
}
|
|
}
|
|
if (representer != null) {
|
|
return representer.call(this, data);
|
|
} else {
|
|
return new nodes.ScalarNode(null, `${data}`);
|
|
}
|
|
}
|
|
|
|
represent_scalar(tag, value, style = this.default_style) {
|
|
var node;
|
|
node = new nodes.ScalarNode(tag, value, null, null, style);
|
|
if (this.alias_key != null) {
|
|
this.represented_objects[this.alias_key] = node;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
represent_sequence(tag, sequence, flow_style) {
|
|
var best_style, item, j, len, node, node_item, ref, value;
|
|
value = [];
|
|
node = new nodes.SequenceNode(tag, value, null, null, flow_style);
|
|
if (this.alias_key != null) {
|
|
this.represented_objects[this.alias_key] = node;
|
|
}
|
|
best_style = true;
|
|
for (j = 0, len = sequence.length; j < len; j++) {
|
|
item = sequence[j];
|
|
node_item = this.represent_data(item);
|
|
if (!(node_item instanceof nodes.ScalarNode || node_item.style)) {
|
|
best_style = false;
|
|
}
|
|
value.push(node_item);
|
|
}
|
|
if (flow_style == null) {
|
|
node.flow_style = (ref = this.default_flow_style) != null ? ref : best_style;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
represent_mapping(tag, mapping, flow_style) {
|
|
var best_style, item_key, item_value, node, node_key, node_value, ref, value;
|
|
value = [];
|
|
node = new nodes.MappingNode(tag, value, flow_style);
|
|
if (this.alias_key) {
|
|
this.represented_objects[this.alias_key] = node;
|
|
}
|
|
best_style = true;
|
|
for (item_key in mapping) {
|
|
if (!hasProp.call(mapping, item_key)) continue;
|
|
item_value = mapping[item_key];
|
|
node_key = this.represent_data(item_key);
|
|
node_value = this.represent_data(item_value);
|
|
if (!(node_key instanceof nodes.ScalarNode || node_key.style)) {
|
|
best_style = false;
|
|
}
|
|
if (!(node_value instanceof nodes.ScalarNode || node_value.style)) {
|
|
best_style = false;
|
|
}
|
|
value.push([node_key, node_value]);
|
|
}
|
|
if (!flow_style) {
|
|
node.flow_style = (ref = this.default_flow_style) != null ? ref : best_style;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
ignore_aliases(data) {
|
|
return false;
|
|
}
|
|
|
|
};
|
|
|
|
BaseRepresenter.prototype.yaml_representers_types = [];
|
|
|
|
BaseRepresenter.prototype.yaml_representers_handlers = [];
|
|
|
|
BaseRepresenter.prototype.yaml_multi_representers_types = [];
|
|
|
|
BaseRepresenter.prototype.yaml_multi_representers_handlers = [];
|
|
|
|
ctor = BaseRepresenter.prototype.initialise;
|
|
|
|
return BaseRepresenter;
|
|
|
|
}).call(this);
|
|
|
|
this.Representer = class Representer extends this.BaseRepresenter {
|
|
represent_boolean(data) {
|
|
return this.represent_scalar('tag:yaml.org,2002:bool', (data ? 'true' : 'false'));
|
|
}
|
|
|
|
represent_null(data) {
|
|
return this.represent_scalar('tag:yaml.org,2002:null', 'null');
|
|
}
|
|
|
|
represent_number(data) {
|
|
var tag, value;
|
|
tag = `tag:yaml.org,2002:${(data % 1 === 0 ? 'int' : 'float')}`;
|
|
value = data !== data ? '.nan' : data === 2e308 ? '.inf' : data === -2e308 ? '-.inf' : data.toString();
|
|
return this.represent_scalar(tag, value);
|
|
}
|
|
|
|
represent_string(data) {
|
|
return this.represent_scalar('tag:yaml.org,2002:str', data);
|
|
}
|
|
|
|
represent_array(data) {
|
|
return this.represent_sequence('tag:yaml.org,2002:seq', data);
|
|
}
|
|
|
|
represent_date(data) {
|
|
return this.represent_scalar('tag:yaml.org,2002:timestamp', data.toISOString());
|
|
}
|
|
|
|
represent_object(data) {
|
|
return this.represent_mapping('tag:yaml.org,2002:map', data);
|
|
}
|
|
|
|
represent_undefined(data) {
|
|
throw new exports.RepresenterError(`cannot represent an onbject: ${data}`);
|
|
}
|
|
|
|
ignore_aliases(data) {
|
|
var ref;
|
|
if (data == null) {
|
|
return true;
|
|
}
|
|
if ((ref = typeof data) === 'boolean' || ref === 'number' || ref === 'string') {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
};
|
|
|
|
this.Representer.add_representer('boolean', this.Representer.prototype.represent_boolean);
|
|
|
|
this.Representer.add_representer('null', this.Representer.prototype.represent_null);
|
|
|
|
this.Representer.add_representer('number', this.Representer.prototype.represent_number);
|
|
|
|
this.Representer.add_representer('string', this.Representer.prototype.represent_string);
|
|
|
|
this.Representer.add_representer(Array, this.Representer.prototype.represent_array);
|
|
|
|
this.Representer.add_representer(Date, this.Representer.prototype.represent_date);
|
|
|
|
this.Representer.add_representer(Object, this.Representer.prototype.represent_object);
|
|
|
|
this.Representer.add_representer(null, this.Representer.prototype.represent_undefined);
|
|
|
|
}).call(this);
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 3579:
|
|
/***/ (function(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) {
|
|
|
|
(function() {
|
|
var YAMLError, nodes, util,
|
|
indexOf = [].indexOf;
|
|
|
|
nodes = __webpack_require__(96914);
|
|
|
|
util = __webpack_require__(23823);
|
|
|
|
({YAMLError} = __webpack_require__(45372));
|
|
|
|
this.ResolverError = class ResolverError extends YAMLError {};
|
|
|
|
this.BaseResolver = (function() {
|
|
var DEFAULT_MAPPING_TAG, DEFAULT_SCALAR_TAG, DEFAULT_SEQUENCE_TAG, ctor;
|
|
|
|
class BaseResolver {
|
|
constructor() {
|
|
return ctor.apply(this, arguments);
|
|
}
|
|
|
|
static add_implicit_resolver(tag, regexp, first = [null]) {
|
|
var base, char, i, len, results;
|
|
if (!this.prototype.hasOwnProperty('yaml_implicit_resolvers')) {
|
|
this.prototype.yaml_implicit_resolvers = util.extend({}, this.prototype.yaml_implicit_resolvers);
|
|
}
|
|
results = [];
|
|
for (i = 0, len = first.length; i < len; i++) {
|
|
char = first[i];
|
|
results.push(((base = this.prototype.yaml_implicit_resolvers)[char] != null ? base[char] : base[char] = []).push([tag, regexp]));
|
|
}
|
|
return results;
|
|
}
|
|
|
|
initialise() {
|
|
this.resolver_exact_paths = [];
|
|
return this.resolver_prefix_paths = [];
|
|
}
|
|
|
|
descend_resolver(current_node, current_index) {
|
|
var depth, exact_paths, i, j, kind, len, len1, path, prefix_paths, ref, ref1;
|
|
if (util.is_empty(this.yaml_path_resolvers)) {
|
|
return;
|
|
}
|
|
exact_paths = {};
|
|
prefix_paths = [];
|
|
if (current_node) {
|
|
depth = this.resolver_prefix_paths.length;
|
|
ref = this.resolver_prefix_paths.slice(-1)[0];
|
|
for (i = 0, len = ref.length; i < len; i++) {
|
|
[path, kind] = ref[i];
|
|
if (this.check_resolver_prefix(depth, path, kind, current_node, current_index)) {
|
|
if (path.length > depth) {
|
|
prefix_paths.push([path, kind]);
|
|
} else {
|
|
exact_paths[kind] = this.yaml_path_resolvers[path][kind];
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
ref1 = this.yaml_path_resolvers;
|
|
for (j = 0, len1 = ref1.length; j < len1; j++) {
|
|
[path, kind] = ref1[j];
|
|
if (!path) {
|
|
exact_paths[kind] = this.yaml_path_resolvers[path][kind];
|
|
} else {
|
|
prefix_paths.push([path, kind]);
|
|
}
|
|
}
|
|
}
|
|
this.resolver_exact_paths.push(exact_paths);
|
|
return this.resolver_prefix_paths.push(prefix_paths);
|
|
}
|
|
|
|
ascend_resolver() {
|
|
if (util.is_empty(this.yaml_path_resolvers)) {
|
|
return;
|
|
}
|
|
this.resolver_exact_paths.pop();
|
|
return this.resolver_prefix_paths.pop();
|
|
}
|
|
|
|
check_resolver_prefix(depth, path, kind, current_node, current_index) {
|
|
var index_check, node_check;
|
|
[node_check, index_check] = path[depth - 1];
|
|
if (typeof node_check === 'string') {
|
|
if (current_node.tag !== node_check) {
|
|
return;
|
|
}
|
|
} else if (node_check !== null) {
|
|
if (!(current_node instanceof node_check)) {
|
|
return;
|
|
}
|
|
}
|
|
if (index_check === true && current_index !== null) {
|
|
return;
|
|
}
|
|
if ((index_check === false || index_check === null) && current_index === null) {
|
|
return;
|
|
}
|
|
if (typeof index_check === 'string') {
|
|
if (!(current_index instanceof nodes.ScalarNode) && index_check === current_index.value) {
|
|
return;
|
|
}
|
|
} else if (typeof index_check === 'number') {
|
|
if (index_check !== current_index) {
|
|
return;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
resolve(kind, value, implicit) {
|
|
var empty, exact_paths, i, k, len, ref, ref1, ref2, regexp, resolvers, tag;
|
|
if (kind === nodes.ScalarNode && implicit[0]) {
|
|
if (value === '') {
|
|
resolvers = (ref = this.yaml_implicit_resolvers['']) != null ? ref : [];
|
|
} else {
|
|
resolvers = (ref1 = this.yaml_implicit_resolvers[value[0]]) != null ? ref1 : [];
|
|
}
|
|
resolvers = resolvers.concat((ref2 = this.yaml_implicit_resolvers[null]) != null ? ref2 : []);
|
|
for (i = 0, len = resolvers.length; i < len; i++) {
|
|
[tag, regexp] = resolvers[i];
|
|
if (value.match(regexp)) {
|
|
return tag;
|
|
}
|
|
}
|
|
implicit = implicit[1];
|
|
}
|
|
empty = true;
|
|
for (k in this.yaml_path_resolvers) {
|
|
if ({}[k] == null) {
|
|
empty = false;
|
|
}
|
|
}
|
|
if (!empty) {
|
|
exact_paths = this.resolver_exact_paths.slice(-1)[0];
|
|
if (indexOf.call(exact_paths, kind) >= 0) {
|
|
return exact_paths[kind];
|
|
}
|
|
if (indexOf.call(exact_paths, null) >= 0) {
|
|
return exact_paths[null];
|
|
}
|
|
}
|
|
if (kind === nodes.ScalarNode) {
|
|
return DEFAULT_SCALAR_TAG;
|
|
}
|
|
if (kind === nodes.SequenceNode) {
|
|
return DEFAULT_SEQUENCE_TAG;
|
|
}
|
|
if (kind === nodes.MappingNode) {
|
|
return DEFAULT_MAPPING_TAG;
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
DEFAULT_SCALAR_TAG = 'tag:yaml.org,2002:str';
|
|
|
|
DEFAULT_SEQUENCE_TAG = 'tag:yaml.org,2002:seq';
|
|
|
|
DEFAULT_MAPPING_TAG = 'tag:yaml.org,2002:map';
|
|
|
|
BaseResolver.prototype.yaml_implicit_resolvers = {};
|
|
|
|
BaseResolver.prototype.yaml_path_resolvers = {};
|
|
|
|
ctor = BaseResolver.prototype.initialise;
|
|
|
|
return BaseResolver;
|
|
|
|
}).call(this);
|
|
|
|
this.Resolver = class Resolver extends this.BaseResolver {};
|
|
|
|
this.Resolver.add_implicit_resolver('tag:yaml.org,2002:bool', /^(?:yes|Yes|YES|true|True|TRUE|on|On|ON|no|No|NO|false|False|FALSE|off|Off|OFF)$/, 'yYnNtTfFoO');
|
|
|
|
this.Resolver.add_implicit_resolver('tag:yaml.org,2002:float', /^(?:[-+]?(?:[0-9][0-9_]*)\.[0-9_]*(?:[eE][-+][0-9]+)?|\.[0-9_]+(?:[eE][-+][0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\.[0-9_]*|[-+]?\.(?:inf|Inf|INF)|\.(?:nan|NaN|NAN))$/, '-+0123456789.');
|
|
|
|
this.Resolver.add_implicit_resolver('tag:yaml.org,2002:int', /^(?:[-+]?0b[01_]+|[-+]?0[0-7_]+|[-+]?(?:0|[1-9][0-9_]*)|[-+]?0x[0-9a-fA-F_]+|[-+]?0o[0-7_]+|[-+]?[1-9][0-9_]*(?::[0-5]?[0-9])+)$/, '-+0123456789');
|
|
|
|
this.Resolver.add_implicit_resolver('tag:yaml.org,2002:merge', /^(?:<<)$/, '<');
|
|
|
|
this.Resolver.add_implicit_resolver('tag:yaml.org,2002:null', /^(?:~|null|Null|NULL|)$/, ['~', 'n', 'N', '']);
|
|
|
|
this.Resolver.add_implicit_resolver('tag:yaml.org,2002:timestamp', /^(?:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]|[0-9][0-9][0-9][0-9]-[0-9][0-9]?-[0-9][0-9]?(?:[Tt]|[\x20\t]+)[0-9][0-9]?:[0-9][0-9]:[0-9][0-9](?:\.[0-9]*)?(?:[\x20\t]*(?:Z|[-+][0-9][0-9]?(?::[0-9][0-9])?))?)$/, '0123456789');
|
|
|
|
this.Resolver.add_implicit_resolver('tag:yaml.org,2002:value', /^(?:=)$/, '=');
|
|
|
|
// The following resolver is only for documentation purposes. It cannot work
|
|
// because plain scalars cannot start with '!', '&' or '*'.
|
|
this.Resolver.add_implicit_resolver('tag:yaml.org,2002:yaml', /^(?:!|&|\*)$/, '!&*');
|
|
|
|
}).call(this);
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 72265:
|
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
|
|
(function() {
|
|
var MarkedYAMLError, SimpleKey, tokens, util,
|
|
hasProp = {}.hasOwnProperty,
|
|
indexOf = [].indexOf;
|
|
|
|
({MarkedYAMLError} = __webpack_require__(45372));
|
|
|
|
tokens = __webpack_require__(59902);
|
|
|
|
util = __webpack_require__(23823);
|
|
|
|
/*
|
|
The Scanner throws these.
|
|
*/
|
|
this.ScannerError = class ScannerError extends MarkedYAMLError {};
|
|
|
|
/*
|
|
Represents a possible simple key.
|
|
*/
|
|
SimpleKey = class SimpleKey {
|
|
constructor(token_number1, required1, index, line, column1, mark1) {
|
|
this.token_number = token_number1;
|
|
this.required = required1;
|
|
this.index = index;
|
|
this.line = line;
|
|
this.column = column1;
|
|
this.mark = mark1;
|
|
}
|
|
|
|
};
|
|
|
|
/*
|
|
The Scanner class deals with converting a YAML stream into a token stream.
|
|
*/
|
|
this.Scanner = (function() {
|
|
var C_LB, C_NUMBERS, C_WS, ESCAPE_CODES, ESCAPE_REPLACEMENTS, ctor;
|
|
|
|
class Scanner {
|
|
constructor() {
|
|
return ctor.apply(this, arguments);
|
|
}
|
|
|
|
/*
|
|
Initialise the Scanner
|
|
*/
|
|
initialise() {
|
|
// Have we reached the end of the stream?
|
|
this.done = false;
|
|
// How many unclosed '{' or '[' have been seen. '0' implies block context.
|
|
this.flow_level = 0;
|
|
// List of processed tokens not yet emitted.
|
|
this.tokens = [];
|
|
// Add the STREAM-START token.
|
|
this.fetch_stream_start();
|
|
// Number of tokens emitted through the `get_token` method.
|
|
this.tokens_taken = 0;
|
|
// Current indentation level. '-1' means no indentation has been seen.
|
|
this.indent = -1;
|
|
// Previous indentation levels.
|
|
this.indents = [];
|
|
// Simple Key Treatment
|
|
// A simple key is a key that is not denoted by the '?' indicator, e.g.
|
|
// block simple key: value
|
|
// ? not a simple key
|
|
// : { flow simple key: value }
|
|
// We emit the KEY token before all keys, so when we find a potential
|
|
// simple key, we try to locate the corresponding ':' indicator. Simple
|
|
// keys should be limited to a single line and 1024 characters.
|
|
|
|
// Can a simple key start at the current position? A simple key may
|
|
// start
|
|
// at the beginning of the line, not counting indentation spaces
|
|
// (block context)
|
|
// after '{', '[', ',' (flow context)
|
|
// after '?', ':', '-' (block context)
|
|
// In the block context, this flag also signifies if a block collection
|
|
// may start at the current position.
|
|
this.allow_simple_key = true;
|
|
// Keep track of possible simple keys. This is an object. The key is
|
|
// `flow_level`; there can be no more than one possible simple key for
|
|
// each level. The value is a SimpleKey object. A simple key may start
|
|
// with ALIAS, ANCHOR, TAG, SCALAR (flow), '[' or '{' tokens.
|
|
return this.possible_simple_keys = {};
|
|
}
|
|
|
|
// API methods.
|
|
/*
|
|
Check if the next token is one of the given types.
|
|
*/
|
|
check_token(...choices) {
|
|
var choice, i, len;
|
|
while (this.need_more_tokens()) {
|
|
this.fetch_more_tokens();
|
|
}
|
|
if (this.tokens.length !== 0) {
|
|
if (choices.length === 0) {
|
|
return true;
|
|
}
|
|
for (i = 0, len = choices.length; i < len; i++) {
|
|
choice = choices[i];
|
|
if (this.tokens[0] instanceof choice) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
Return the next token, but do not delete it from the queue.
|
|
*/
|
|
peek_token() {
|
|
while (this.need_more_tokens()) {
|
|
this.fetch_more_tokens();
|
|
}
|
|
if (this.tokens.length !== 0) {
|
|
return this.tokens[0];
|
|
}
|
|
}
|
|
|
|
/*
|
|
Return the next token, and remove it from the queue.
|
|
*/
|
|
get_token() {
|
|
while (this.need_more_tokens()) {
|
|
this.fetch_more_tokens();
|
|
}
|
|
if (this.tokens.length !== 0) {
|
|
this.tokens_taken++;
|
|
return this.tokens.shift();
|
|
}
|
|
}
|
|
|
|
// Non-API methods.
|
|
need_more_tokens() {
|
|
if (this.done) {
|
|
return false;
|
|
}
|
|
if (this.tokens.length === 0) {
|
|
return true;
|
|
}
|
|
// The current token may be a potential simple key, so we need to look
|
|
// further.
|
|
this.stale_possible_simple_keys();
|
|
if (this.next_possible_simple_key() === this.tokens_taken) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
fetch_more_tokens() {
|
|
var char;
|
|
// Eat whitespace and comments until we reach the next token.
|
|
this.scan_to_next_token();
|
|
// Remove obsolete possible simple keys
|
|
this.stale_possible_simple_keys();
|
|
// Compare the current indentation and column. It may add some tokens and
|
|
// decrease the current indentation level.
|
|
this.unwind_indent(this.column);
|
|
// Peek the next character.
|
|
char = this.peek();
|
|
if (char === '\x00') {
|
|
// Is it the end of stream?
|
|
return this.fetch_stream_end();
|
|
}
|
|
if (char === '%' && this.check_directive()) {
|
|
// Is it a directive?
|
|
return this.fetch_directive();
|
|
}
|
|
if (char === '-' && this.check_document_start()) {
|
|
// Is it the document start?
|
|
return this.fetch_document_start();
|
|
}
|
|
if (char === '.' && this.check_document_end()) {
|
|
// Is it the document end?
|
|
return this.fetch_document_end();
|
|
}
|
|
if (char === '[') {
|
|
// TODO: support for BOM within a stream.
|
|
|
|
// Is it the flow sequence start indicator?
|
|
return this.fetch_flow_sequence_start();
|
|
}
|
|
if (char === '{') {
|
|
// Is it the flow mapping start indicator?
|
|
return this.fetch_flow_mapping_start();
|
|
}
|
|
if (char === ']') {
|
|
// Is it the flow sequence end indicator?
|
|
return this.fetch_flow_sequence_end();
|
|
}
|
|
if (char === '}') {
|
|
// Is it the flow mapping end indicator?
|
|
return this.fetch_flow_mapping_end();
|
|
}
|
|
if (char === ',') {
|
|
// Is it the flow entry indicator?
|
|
return this.fetch_flow_entry();
|
|
}
|
|
if (char === '-' && this.check_block_entry()) {
|
|
// Is it the block entry indicator?
|
|
return this.fetch_block_entry();
|
|
}
|
|
if (char === '?' && this.check_key()) {
|
|
// Is it the key indicator?
|
|
return this.fetch_key();
|
|
}
|
|
if (char === ':' && this.check_value()) {
|
|
// Is it the value indicator?
|
|
return this.fetch_value();
|
|
}
|
|
if (char === '*') {
|
|
// Is it an alias?
|
|
return this.fetch_alias();
|
|
}
|
|
if (char === '&') {
|
|
// Is it an anchor?
|
|
return this.fetch_anchor();
|
|
}
|
|
if (char === '!') {
|
|
// Is it a tag?
|
|
return this.fetch_tag();
|
|
}
|
|
if (char === '|' && this.flow_level === 0) {
|
|
// Is it a literal scalar?
|
|
return this.fetch_literal();
|
|
}
|
|
if (char === '>' && this.flow_level === 0) {
|
|
// Is it a folded scalar?
|
|
return this.fetch_folded();
|
|
}
|
|
if (char === '\'') {
|
|
// Is it a single quoted scalar?
|
|
return this.fetch_single();
|
|
}
|
|
if (char === '"') {
|
|
// Is it a double quoted scalar?
|
|
return this.fetch_double();
|
|
}
|
|
if (this.check_plain()) {
|
|
// It must be a plain scalar then.
|
|
return this.fetch_plain();
|
|
}
|
|
// No? It's an error.
|
|
throw new exports.ScannerError('while scanning for the next token', null, `found character ${char} that cannot start any token`, this.get_mark());
|
|
}
|
|
|
|
// Simple keys treatment.
|
|
/*
|
|
Return the number of the nearest possible simple key.
|
|
*/
|
|
next_possible_simple_key() {
|
|
var key, level, min_token_number, ref;
|
|
min_token_number = null;
|
|
ref = this.possible_simple_keys;
|
|
for (level in ref) {
|
|
if (!hasProp.call(ref, level)) continue;
|
|
key = ref[level];
|
|
if (min_token_number === null || key.token_number < min_token_number) {
|
|
min_token_number = key.token_number;
|
|
}
|
|
}
|
|
return min_token_number;
|
|
}
|
|
|
|
/*
|
|
Remove entries that are no longer possible simple keys. According to the
|
|
YAML spec, simple keys:
|
|
should be limited to a single line
|
|
should be no longer than 1024 characters
|
|
Disabling this procedure will allow simple keys of any length and height
|
|
(may cause problems if indentation is broken though).
|
|
*/
|
|
stale_possible_simple_keys() {
|
|
var key, level, ref, results;
|
|
ref = this.possible_simple_keys;
|
|
results = [];
|
|
for (level in ref) {
|
|
if (!hasProp.call(ref, level)) continue;
|
|
key = ref[level];
|
|
if (key.line === this.line && this.index - key.index <= 1024) {
|
|
continue;
|
|
}
|
|
if (!key.required) {
|
|
results.push(delete this.possible_simple_keys[level]);
|
|
} else {
|
|
throw new exports.ScannerError('while scanning a simple key', key.mark, 'could not find expected \':\'', this.get_mark());
|
|
}
|
|
}
|
|
return results;
|
|
}
|
|
|
|
/*
|
|
The next token may start a simple key. We check if it's possible and save
|
|
its position. This function is called for ALIAS, ANCHOR, TAG,
|
|
SCALAR (flow),'[' and '{'.
|
|
*/
|
|
save_possible_simple_key() {
|
|
var required, token_number;
|
|
// Check if a simple key is required at the current position.
|
|
required = this.flow_level === 0 && this.indent === this.column;
|
|
if (required && !this.allow_simple_key) {
|
|
// A simple key is required only if it is the first token in the current
|
|
// line. Therefore it is always allowed.
|
|
throw new Error('logic failure');
|
|
}
|
|
// If simple keys aren't allowed here we're done.
|
|
if (!this.allow_simple_key) {
|
|
return;
|
|
}
|
|
// The next token might be a simple key. Let's save its number and
|
|
// position.
|
|
this.remove_possible_simple_key();
|
|
token_number = this.tokens_taken + this.tokens.length;
|
|
return this.possible_simple_keys[this.flow_level] = new SimpleKey(token_number, required, this.index, this.line, this.column, this.get_mark());
|
|
}
|
|
|
|
/*
|
|
Remove the saved possible simple key at the current flow level.
|
|
*/
|
|
remove_possible_simple_key() {
|
|
var key;
|
|
if (!(key = this.possible_simple_keys[this.flow_level])) {
|
|
return;
|
|
}
|
|
if (!key.required) {
|
|
return delete this.possible_simple_keys[this.flow_level];
|
|
} else {
|
|
throw new exports.ScannerError('while scanning a simple key', key.mark, 'could not find expected \':\'', this.get_mark());
|
|
}
|
|
}
|
|
|
|
// Indentation functions
|
|
/*
|
|
In flow context, tokens should respect indentation.
|
|
Actually the condition should be `self.indent >= column` according to
|
|
the spec. But this condition will prohibit intuitively correct
|
|
constructions such as
|
|
key : {
|
|
}
|
|
*/
|
|
unwind_indent(column) {
|
|
var mark, results;
|
|
// In the flow context, indentation is ignored. We make the scanner less
|
|
// restrictive than the specification requires.
|
|
if (this.flow_level !== 0) {
|
|
return;
|
|
}
|
|
results = [];
|
|
// In block context we may need to issue the BLOCK-END tokens.
|
|
while (this.indent > column) {
|
|
mark = this.get_mark();
|
|
this.indent = this.indents.pop();
|
|
results.push(this.tokens.push(new tokens.BlockEndToken(mark, mark)));
|
|
}
|
|
return results;
|
|
}
|
|
|
|
/*
|
|
Check if we need to increase indentation.
|
|
*/
|
|
add_indent(column) {
|
|
if (!(column > this.indent)) {
|
|
return false;
|
|
}
|
|
this.indents.push(this.indent);
|
|
this.indent = column;
|
|
return true;
|
|
}
|
|
|
|
// Fetchers.
|
|
fetch_stream_start() {
|
|
var mark;
|
|
mark = this.get_mark();
|
|
return this.tokens.push(new tokens.StreamStartToken(mark, mark, this.encoding));
|
|
}
|
|
|
|
fetch_stream_end() {
|
|
var mark;
|
|
// Set the current indentation to -1.
|
|
this.unwind_indent(-1);
|
|
// Reset simple keys.
|
|
this.remove_possible_simple_key();
|
|
this.allow_possible_simple_key = false;
|
|
this.possible_simple_keys = {};
|
|
mark = this.get_mark();
|
|
this.tokens.push(new tokens.StreamEndToken(mark, mark));
|
|
// The stream is finished.
|
|
return this.done = true;
|
|
}
|
|
|
|
fetch_directive() {
|
|
// Set the current indentation to -1.
|
|
this.unwind_indent(-1);
|
|
// Reset simple keys.
|
|
this.remove_possible_simple_key();
|
|
this.allow_simple_key = false;
|
|
// Scan and add DIRECTIVE
|
|
return this.tokens.push(this.scan_directive());
|
|
}
|
|
|
|
fetch_document_start() {
|
|
return this.fetch_document_indicator(tokens.DocumentStartToken);
|
|
}
|
|
|
|
fetch_document_end() {
|
|
return this.fetch_document_indicator(tokens.DocumentEndToken);
|
|
}
|
|
|
|
fetch_document_indicator(TokenClass) {
|
|
var start_mark;
|
|
// Set the current indentation to -1.
|
|
this.unwind_indent(-1);
|
|
// Reset simple keys. Note that there would not be a block collection
|
|
// after '---'.
|
|
this.remove_possible_simple_key();
|
|
this.allow_simple_key = false;
|
|
// Add DOCUMENT-START or DOCUMENT-END.
|
|
start_mark = this.get_mark();
|
|
this.forward(3);
|
|
return this.tokens.push(new TokenClass(start_mark, this.get_mark()));
|
|
}
|
|
|
|
fetch_flow_sequence_start() {
|
|
return this.fetch_flow_collection_start(tokens.FlowSequenceStartToken);
|
|
}
|
|
|
|
fetch_flow_mapping_start() {
|
|
return this.fetch_flow_collection_start(tokens.FlowMappingStartToken);
|
|
}
|
|
|
|
fetch_flow_collection_start(TokenClass) {
|
|
var start_mark;
|
|
// '[' and '{' may start a simple key.
|
|
this.save_possible_simple_key();
|
|
// Increase flow level.
|
|
this.flow_level++;
|
|
// Simple keys are allowed after '[' and '{'
|
|
this.allow_simple_key = true;
|
|
// Add FLOW-SEQUENCE-START or FLOW-MAPPING-START.
|
|
start_mark = this.get_mark();
|
|
this.forward();
|
|
return this.tokens.push(new TokenClass(start_mark, this.get_mark()));
|
|
}
|
|
|
|
fetch_flow_sequence_end() {
|
|
return this.fetch_flow_collection_end(tokens.FlowSequenceEndToken);
|
|
}
|
|
|
|
fetch_flow_mapping_end() {
|
|
return this.fetch_flow_collection_end(tokens.FlowMappingEndToken);
|
|
}
|
|
|
|
fetch_flow_collection_end(TokenClass) {
|
|
var start_mark;
|
|
// Reset possible simple key on the current level.
|
|
this.remove_possible_simple_key();
|
|
// Decrease the flow level
|
|
this.flow_level--;
|
|
// No simple keys after ']' or '}'
|
|
this.allow_simple_key = false;
|
|
// Add FLOW-SEQUENCE-END or FLOW-MAPPING-END.
|
|
start_mark = this.get_mark();
|
|
this.forward();
|
|
return this.tokens.push(new TokenClass(start_mark, this.get_mark()));
|
|
}
|
|
|
|
fetch_flow_entry() {
|
|
var start_mark;
|
|
// Simple keys are allowed after ','.
|
|
this.allow_simple_key = true;
|
|
// Reset possible simple key on the current level.
|
|
this.remove_possible_simple_key();
|
|
// Add FLOW-ENTRY
|
|
start_mark = this.get_mark();
|
|
this.forward();
|
|
return this.tokens.push(new tokens.FlowEntryToken(start_mark, this.get_mark()));
|
|
}
|
|
|
|
fetch_block_entry() {
|
|
var mark, start_mark;
|
|
// Block context needs additional checks
|
|
if (this.flow_level === 0) {
|
|
// Are we allowed to start a new entry?
|
|
if (!this.allow_simple_key) {
|
|
throw new exports.ScannerError(null, null, 'sequence entries are not allowed here', this.get_mark());
|
|
}
|
|
// We may need to add BLOCK-SEQUENCE-START
|
|
if (this.add_indent(this.column)) {
|
|
mark = this.get_mark();
|
|
this.tokens.push(new tokens.BlockSequenceStartToken(mark, mark));
|
|
}
|
|
}
|
|
// It's an error for the block entry to occur in the flow context but we
|
|
// let the parser detect this.
|
|
|
|
// Simple keys are allowed after '-'
|
|
this.allow_simple_key = true;
|
|
// Reset possible simple key on the current level.
|
|
this.remove_possible_simple_key();
|
|
// Add BLOCK-ENTRY
|
|
start_mark = this.get_mark();
|
|
this.forward();
|
|
return this.tokens.push(new tokens.BlockEntryToken(start_mark, this.get_mark()));
|
|
}
|
|
|
|
fetch_key() {
|
|
var mark, start_mark;
|
|
// Block context needs additional checks.
|
|
if (this.flow_level === 0) {
|
|
// Are we allowed to start a key?
|
|
if (!this.allow_simple_key) {
|
|
throw new exports.ScannerError(null, null, 'mapping keys are not allowed here', this.get_mark());
|
|
}
|
|
// We may need to add BLOCK-MAPPING-START.
|
|
if (this.add_indent(this.column)) {
|
|
mark = this.get_mark();
|
|
this.tokens.push(new tokens.BlockMappingStartToken(mark, mark));
|
|
}
|
|
}
|
|
// Simple keys are allowed after '?' in the flow context.
|
|
this.allow_simple_key = !this.flow_level;
|
|
// Reset possible simple key on the current level.
|
|
this.remove_possible_simple_key();
|
|
// Add KEY.
|
|
start_mark = this.get_mark();
|
|
this.forward();
|
|
return this.tokens.push(new tokens.KeyToken(start_mark, this.get_mark()));
|
|
}
|
|
|
|
fetch_value() {
|
|
var key, mark, start_mark;
|
|
// Do we determine a simple key?
|
|
if (key = this.possible_simple_keys[this.flow_level]) {
|
|
// Add KEY.
|
|
delete this.possible_simple_keys[this.flow_level];
|
|
this.tokens.splice(key.token_number - this.tokens_taken, 0, new tokens.KeyToken(key.mark, key.mark));
|
|
// If this key starts a new block mapping we need to add
|
|
// BLOCK-MAPPING-START.
|
|
if (this.flow_level === 0) {
|
|
if (this.add_indent(key.column)) {
|
|
this.tokens.splice(key.token_number - this.tokens_taken, 0, new tokens.BlockMappingStartToken(key.mark, key.mark));
|
|
}
|
|
}
|
|
// There cannot be two simple keys one after the other.
|
|
this.allow_simple_key = false;
|
|
} else {
|
|
// Block context needs additional checks.
|
|
// TODO: do we really need them? Parser will catch them anyway.
|
|
// It must be part of a complex key.
|
|
if (this.flow_level === 0) {
|
|
// We are allowed to start a complex value if and only if we can start
|
|
// a simple key.
|
|
if (!this.allow_simple_key) {
|
|
throw new exports.ScannerError(null, null, 'mapping values are not allowed here', this.get_mark());
|
|
}
|
|
// If this value starts a new block mapping we need to add
|
|
// BLOCK-MAPPING-START. It will be detected as an error later by the
|
|
// parser.
|
|
if (this.add_indent(this.column)) {
|
|
mark = this.get_mark();
|
|
this.tokens.push(new tokens.BlockMappingStartToken(mark, mark));
|
|
}
|
|
}
|
|
// Simple keys are allowed after ':' in the block context.
|
|
this.allow_simple_key = !this.flow_level;
|
|
// Reset possible simple key on the current level.
|
|
this.remove_possible_simple_key();
|
|
}
|
|
// Add VALUE.
|
|
start_mark = this.get_mark();
|
|
this.forward();
|
|
return this.tokens.push(new tokens.ValueToken(start_mark, this.get_mark()));
|
|
}
|
|
|
|
fetch_alias() {
|
|
// ALIAS could be a simple key.
|
|
this.save_possible_simple_key();
|
|
// No simple keys after ALIAS.
|
|
this.allow_simple_key = false;
|
|
// Scan and add ALIAS.
|
|
return this.tokens.push(this.scan_anchor(tokens.AliasToken));
|
|
}
|
|
|
|
fetch_anchor() {
|
|
// ANCHOR could start a simple key.
|
|
this.save_possible_simple_key();
|
|
// No simple keys allowed after ANCHOR.
|
|
this.allow_simple_key = false;
|
|
// Scan and add ANCHOR.
|
|
return this.tokens.push(this.scan_anchor(tokens.AnchorToken));
|
|
}
|
|
|
|
fetch_tag() {
|
|
// TAG could start a simple key
|
|
this.save_possible_simple_key();
|
|
// No simple keys after TAG.
|
|
this.allow_simple_key = false;
|
|
// Scan and add TAG.
|
|
return this.tokens.push(this.scan_tag());
|
|
}
|
|
|
|
fetch_literal() {
|
|
return this.fetch_block_scalar('|');
|
|
}
|
|
|
|
fetch_folded() {
|
|
return this.fetch_block_scalar('>');
|
|
}
|
|
|
|
fetch_block_scalar(style) {
|
|
// A simple key may follow a block sclar.
|
|
this.allow_simple_key = true;
|
|
// Reset possible simple key on the current level.
|
|
this.remove_possible_simple_key();
|
|
// Scan and add SCALAR.
|
|
return this.tokens.push(this.scan_block_scalar(style));
|
|
}
|
|
|
|
fetch_single() {
|
|
return this.fetch_flow_scalar('\'');
|
|
}
|
|
|
|
fetch_double() {
|
|
return this.fetch_flow_scalar('"');
|
|
}
|
|
|
|
fetch_flow_scalar(style) {
|
|
// A flow scalar could be a simple key.
|
|
this.save_possible_simple_key();
|
|
// No simple keys after flow scalars.
|
|
this.allow_simple_key = false;
|
|
// Scan and add SCALAR.
|
|
return this.tokens.push(this.scan_flow_scalar(style));
|
|
}
|
|
|
|
fetch_plain() {
|
|
// A plain scalar could be a simple key.
|
|
this.save_possible_simple_key();
|
|
// No simple keys after plain scalars. But note that `scan_plain` will
|
|
// change this flag if the scan is finished at the beginning of the line.
|
|
this.allow_simple_key = false;
|
|
// Scan and add SCALAR. May change `allow_simple_key`.
|
|
return this.tokens.push(this.scan_plain());
|
|
}
|
|
|
|
// Checkers.
|
|
/*
|
|
DIRECTIVE: ^ '%'
|
|
*/
|
|
check_directive() {
|
|
if (this.column === 0) {
|
|
// The % indicator has already been checked.
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
DOCUMENT-START: ^ '---' (' '|'\n')
|
|
*/
|
|
check_document_start() {
|
|
var ref;
|
|
if (this.column === 0 && this.prefix(3) === '---' && (ref = this.peek(3), indexOf.call(C_LB + C_WS + '\x00', ref) >= 0)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
DOCUMENT-END: ^ '...' (' '|'\n')
|
|
*/
|
|
check_document_end() {
|
|
var ref;
|
|
if (this.column === 0 && this.prefix(3) === '...' && (ref = this.peek(3), indexOf.call(C_LB + C_WS + '\x00', ref) >= 0)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
BLOCK-ENTRY: '-' (' '|'\n')
|
|
*/
|
|
check_block_entry() {
|
|
var ref;
|
|
return ref = this.peek(1), indexOf.call(C_LB + C_WS + '\x00', ref) >= 0;
|
|
}
|
|
|
|
/*
|
|
KEY (flow context): '?'
|
|
KEY (block context): '?' (' '|'\n')
|
|
*/
|
|
check_key() {
|
|
var ref;
|
|
if (this.flow_level !== 0) {
|
|
// KEY (flow context)
|
|
return true;
|
|
}
|
|
// KEY (block context)
|
|
return ref = this.peek(1), indexOf.call(C_LB + C_WS + '\x00', ref) >= 0;
|
|
}
|
|
|
|
/*
|
|
VALUE (flow context): ':'
|
|
VALUE (block context): ':' (' '|'\n')
|
|
*/
|
|
check_value() {
|
|
var ref;
|
|
if (this.flow_level !== 0) {
|
|
// VALUE (flow context)
|
|
return true;
|
|
}
|
|
// VALUE (block context)
|
|
return ref = this.peek(1), indexOf.call(C_LB + C_WS + '\x00', ref) >= 0;
|
|
}
|
|
|
|
/*
|
|
A plain scalar may start with any non-space character except:
|
|
'-', '?', ':', ',', '[', ']', '{', '}',
|
|
'#', '&', '*', '!', '|', '>', '\'', '"',
|
|
'%', '@', '`'.
|
|
|
|
It may also start with
|
|
'-', '?', ':'
|
|
if it is followed by a non-space character.
|
|
|
|
Note that we limit the last rule to the block context (except the '-'
|
|
character) because we want the flow context to be space independent.
|
|
*/
|
|
check_plain() {
|
|
var char, ref;
|
|
char = this.peek();
|
|
return indexOf.call(C_LB + C_WS + '\x00-?:,[]{}#&*!|>\'"%@`', char) < 0 || ((ref = this.peek(1), indexOf.call(C_LB + C_WS + '\x00', ref) < 0) && (char === '-' || (this.flow_level === 0 && indexOf.call('?:', char) >= 0)));
|
|
}
|
|
|
|
// Scanners.
|
|
/*
|
|
We ignore spaces, line breaks and comments.
|
|
If we find a line break in the block context, we set the flag
|
|
`allow_simple_key` on.
|
|
The byte order mark is stripped if it's the first character in the stream.
|
|
We do not yet support BOM inside the stream as the specification requires.
|
|
Any such mark will be considered as a part of the document.
|
|
|
|
TODO: We need to make tab handling rules more sane. A good rule is
|
|
Tabs cannot precede tokens BLOCK-SEQUENCE-START, BLOCK-MAPPING-START,
|
|
BLOCK-END, KEY (block context), VALUE (block context), BLOCK-ENTRY
|
|
So the tab checking code is
|
|
@allow_simple_key = off if <TAB>
|
|
We also need to add the check for `allow_simple_key is on` to
|
|
`unwind_indent` before issuing BLOCK-END. Scanners for block, flow and
|
|
plain scalars need to be modified.
|
|
*/
|
|
scan_to_next_token() {
|
|
var found, ref, results;
|
|
if (this.index === 0 && this.peek() === '\uFEFF') {
|
|
this.forward();
|
|
}
|
|
found = false;
|
|
results = [];
|
|
while (!found) {
|
|
while (this.peek() === ' ') {
|
|
this.forward();
|
|
}
|
|
if (this.peek() === '#') {
|
|
while (ref = this.peek(), indexOf.call(C_LB + '\x00', ref) < 0) {
|
|
this.forward();
|
|
}
|
|
}
|
|
if (this.scan_line_break()) {
|
|
if (this.flow_level === 0) {
|
|
results.push(this.allow_simple_key = true);
|
|
} else {
|
|
results.push(void 0);
|
|
}
|
|
} else {
|
|
results.push(found = true);
|
|
}
|
|
}
|
|
return results;
|
|
}
|
|
|
|
/*
|
|
See the specification for details.
|
|
*/
|
|
scan_directive() {
|
|
var end_mark, name, ref, start_mark, value;
|
|
start_mark = this.get_mark();
|
|
this.forward();
|
|
name = this.scan_directive_name(start_mark);
|
|
value = null;
|
|
if (name === 'YAML') {
|
|
value = this.scan_yaml_directive_value(start_mark);
|
|
end_mark = this.get_mark();
|
|
} else if (name === 'TAG') {
|
|
value = this.scan_tag_directive_value(start_mark);
|
|
end_mark = this.get_mark();
|
|
} else {
|
|
end_mark = this.get_mark();
|
|
while (ref = this.peek(), indexOf.call(C_LB + '\x00', ref) < 0) {
|
|
this.forward();
|
|
}
|
|
}
|
|
this.scan_directive_ignored_line(start_mark);
|
|
return new tokens.DirectiveToken(name, value, start_mark, end_mark);
|
|
}
|
|
|
|
/*
|
|
See the specification for details.
|
|
*/
|
|
scan_directive_name(start_mark) {
|
|
var char, length, value;
|
|
length = 0;
|
|
char = this.peek(length);
|
|
while (('0' <= char && char <= '9') || ('A' <= char && char <= 'Z') || ('a' <= char && char <= 'z') || indexOf.call('-_', char) >= 0) {
|
|
length++;
|
|
char = this.peek(length);
|
|
}
|
|
if (length === 0) {
|
|
throw new exports.ScannerError('while scanning a directive', start_mark, `expected alphanumeric or numeric character but found ${char}`, this.get_mark());
|
|
}
|
|
value = this.prefix(length);
|
|
this.forward(length);
|
|
char = this.peek();
|
|
if (indexOf.call(C_LB + '\x00 ', char) < 0) {
|
|
throw new exports.ScannerError('while scanning a directive', start_mark, `expected alphanumeric or numeric character but found ${char}`, this.get_mark());
|
|
}
|
|
return value;
|
|
}
|
|
|
|
/*
|
|
See the specification for details.
|
|
*/
|
|
scan_yaml_directive_value(start_mark) {
|
|
var major, minor, ref;
|
|
while (this.peek() === ' ') {
|
|
this.forward();
|
|
}
|
|
major = this.scan_yaml_directive_number(start_mark);
|
|
if (this.peek() !== '.') {
|
|
throw new exports.ScannerError('while scanning a directive', start_mark, `expected a digit or '.' but found ${this.peek()}`, this.get_mark());
|
|
}
|
|
this.forward();
|
|
minor = this.scan_yaml_directive_number(start_mark);
|
|
if (ref = this.peek(), indexOf.call(C_LB + '\x00 ', ref) < 0) {
|
|
throw new exports.ScannerError('while scanning a directive', start_mark, `expected a digit or ' ' but found ${this.peek()}`, this.get_mark());
|
|
}
|
|
return [major, minor];
|
|
}
|
|
|
|
/*
|
|
See the specification for details.
|
|
*/
|
|
scan_yaml_directive_number(start_mark) {
|
|
var char, length, ref, value;
|
|
char = this.peek();
|
|
if (!(('0' <= char && char <= '9'))) {
|
|
throw new exports.ScannerError('while scanning a directive', start_mark, `expected a digit but found ${char}`, this.get_mark());
|
|
}
|
|
length = 0;
|
|
while (('0' <= (ref = this.peek(length)) && ref <= '9')) {
|
|
length++;
|
|
}
|
|
value = parseInt(this.prefix(length));
|
|
this.forward(length);
|
|
return value;
|
|
}
|
|
|
|
/*
|
|
See the specification for details.
|
|
*/
|
|
scan_tag_directive_value(start_mark) {
|
|
var handle, prefix;
|
|
while (this.peek() === ' ') {
|
|
this.forward();
|
|
}
|
|
handle = this.scan_tag_directive_handle(start_mark);
|
|
while (this.peek() === ' ') {
|
|
this.forward();
|
|
}
|
|
prefix = this.scan_tag_directive_prefix(start_mark);
|
|
return [handle, prefix];
|
|
}
|
|
|
|
/*
|
|
See the specification for details.
|
|
*/
|
|
scan_tag_directive_handle(start_mark) {
|
|
var char, value;
|
|
value = this.scan_tag_handle('directive', start_mark);
|
|
char = this.peek();
|
|
if (char !== ' ') {
|
|
throw new exports.ScannerError('while scanning a directive', start_mark, `expected ' ' but found ${char}`, this.get_mark());
|
|
}
|
|
return value;
|
|
}
|
|
|
|
/*
|
|
See the specification for details.
|
|
*/
|
|
scan_tag_directive_prefix(start_mark) {
|
|
var char, value;
|
|
value = this.scan_tag_uri('directive', start_mark);
|
|
char = this.peek();
|
|
if (indexOf.call(C_LB + '\x00 ', char) < 0) {
|
|
throw new exports.ScannerError('while scanning a directive', start_mark, `expected ' ' but found ${char}`, this.get_mark());
|
|
}
|
|
return value;
|
|
}
|
|
|
|
/*
|
|
See the specification for details.
|
|
*/
|
|
scan_directive_ignored_line(start_mark) {
|
|
var char, ref;
|
|
while (this.peek() === ' ') {
|
|
this.forward();
|
|
}
|
|
if (this.peek() === '#') {
|
|
while (ref = this.peek(), indexOf.call(C_LB + '\x00', ref) < 0) {
|
|
this.forward();
|
|
}
|
|
}
|
|
char = this.peek();
|
|
if (indexOf.call(C_LB + '\x00', char) < 0) {
|
|
throw new exports.ScannerError('while scanning a directive', start_mark, `expected a comment or a line break but found ${char}`, this.get_mark());
|
|
}
|
|
return this.scan_line_break();
|
|
}
|
|
|
|
/*
|
|
The specification does not restrict characters for anchors and aliases.
|
|
This may lead to problems, for instance, the document:
|
|
[ *alias, value ]
|
|
can be interpteted in two ways, as
|
|
[ "value" ]
|
|
and
|
|
[ *alias , "value" ]
|
|
Therefore we restrict aliases to numbers and ASCII letters.
|
|
*/
|
|
scan_anchor(TokenClass) {
|
|
var char, indicator, length, name, start_mark, value;
|
|
start_mark = this.get_mark();
|
|
indicator = this.peek();
|
|
if (indicator === '*') {
|
|
name = 'alias';
|
|
} else {
|
|
name = 'anchor';
|
|
}
|
|
this.forward();
|
|
length = 0;
|
|
char = this.peek(length);
|
|
while (('0' <= char && char <= '9') || ('A' <= char && char <= 'Z') || ('a' <= char && char <= 'z') || indexOf.call('-_', char) >= 0) {
|
|
length++;
|
|
char = this.peek(length);
|
|
}
|
|
if (length === 0) {
|
|
throw new exports.ScannerError(`while scanning an ${name}`, start_mark, `expected alphabetic or numeric character but found '${char}'`, this.get_mark());
|
|
}
|
|
value = this.prefix(length);
|
|
this.forward(length);
|
|
char = this.peek();
|
|
if (indexOf.call(C_LB + C_WS + '\x00' + '?:,]}%@`', char) < 0) {
|
|
throw new exports.ScannerError(`while scanning an ${name}`, start_mark, `expected alphabetic or numeric character but found '${char}'`, this.get_mark());
|
|
}
|
|
return new TokenClass(value, start_mark, this.get_mark());
|
|
}
|
|
|
|
/*
|
|
See the specification for details.
|
|
*/
|
|
scan_tag() {
|
|
var char, handle, length, start_mark, suffix, use_handle;
|
|
start_mark = this.get_mark();
|
|
char = this.peek(1);
|
|
if (char === '<') {
|
|
handle = null;
|
|
this.forward(2);
|
|
suffix = this.scan_tag_uri('tag', start_mark);
|
|
if (this.peek() !== '>') {
|
|
throw new exports.ScannerError('while parsing a tag', start_mark, `expected '>' but found ${this.peek()}`, this.get_mark());
|
|
}
|
|
this.forward();
|
|
} else if (indexOf.call(C_LB + C_WS + '\x00', char) >= 0) {
|
|
handle = null;
|
|
suffix = '!';
|
|
this.forward();
|
|
} else {
|
|
length = 1;
|
|
use_handle = false;
|
|
while (indexOf.call(C_LB + '\x00 ', char) < 0) {
|
|
if (char === '!') {
|
|
use_handle = true;
|
|
break;
|
|
}
|
|
length++;
|
|
char = this.peek(length);
|
|
}
|
|
if (use_handle) {
|
|
handle = this.scan_tag_handle('tag', start_mark);
|
|
} else {
|
|
handle = '!';
|
|
this.forward();
|
|
}
|
|
suffix = this.scan_tag_uri('tag', start_mark);
|
|
}
|
|
char = this.peek();
|
|
if (indexOf.call(C_LB + '\x00 ', char) < 0) {
|
|
throw new exports.ScannerError('while scanning a tag', start_mark, `expected ' ' but found ${char}`, this.get_mark());
|
|
}
|
|
return new tokens.TagToken([handle, suffix], start_mark, this.get_mark());
|
|
}
|
|
|
|
/*
|
|
See the specification for details.
|
|
*/
|
|
scan_block_scalar(style) {
|
|
var breaks, chomping, chunks, end_mark, folded, increment, indent, leading_non_space, length, line_break, max_indent, min_indent, ref, ref1, ref2, start_mark;
|
|
folded = style === '>';
|
|
chunks = [];
|
|
start_mark = this.get_mark();
|
|
// Scan the header.
|
|
this.forward();
|
|
[chomping, increment] = this.scan_block_scalar_indicators(start_mark);
|
|
this.scan_block_scalar_ignored_line(start_mark);
|
|
// Determine the indentation level and go to the first non-empty line.
|
|
min_indent = this.indent + 1;
|
|
if (min_indent < 1) {
|
|
min_indent = 1;
|
|
}
|
|
if (increment == null) {
|
|
[breaks, max_indent, end_mark] = this.scan_block_scalar_indentation();
|
|
indent = Math.max(min_indent, max_indent);
|
|
} else {
|
|
indent = min_indent + increment - 1;
|
|
[breaks, end_mark] = this.scan_block_scalar_breaks(indent);
|
|
}
|
|
line_break = '';
|
|
// Scan the inner part of the block scalar.
|
|
while (this.column === indent && this.peek() !== '\x00') {
|
|
chunks = chunks.concat(breaks);
|
|
leading_non_space = (ref = this.peek(), indexOf.call(' \t', ref) < 0);
|
|
length = 0;
|
|
while (ref1 = this.peek(length), indexOf.call(C_LB + '\x00', ref1) < 0) {
|
|
length++;
|
|
}
|
|
chunks.push(this.prefix(length));
|
|
this.forward(length);
|
|
line_break = this.scan_line_break();
|
|
[breaks, end_mark] = this.scan_block_scalar_breaks(indent);
|
|
if (this.column === indent && this.peek() !== '\x00') {
|
|
// Unfortunately, folding rules are ambiguous. This is the folding
|
|
// according to the specification:
|
|
if (folded && line_break === '\n' && leading_non_space && (ref2 = this.peek(), indexOf.call(' \t', ref2) < 0)) {
|
|
if (util.is_empty(breaks)) {
|
|
chunks.push(' ');
|
|
}
|
|
} else {
|
|
chunks.push(line_break);
|
|
}
|
|
} else {
|
|
// This is Clark Evan's interpretation (also in the spec examples):
|
|
// if folded and line_break is '\n'
|
|
// if not breaks
|
|
// if @peek() not in ' \t'
|
|
// chunks.push ' '
|
|
// else
|
|
// chunks.push line_break
|
|
// else
|
|
// chunks.push line_break
|
|
break;
|
|
}
|
|
}
|
|
if (chomping !== false) {
|
|
// Chomp the tail
|
|
chunks.push(line_break);
|
|
}
|
|
if (chomping === true) {
|
|
chunks = chunks.concat(breaks);
|
|
}
|
|
// And we're done.
|
|
return new tokens.ScalarToken(chunks.join(''), false, start_mark, end_mark, style);
|
|
}
|
|
|
|
/*
|
|
See the specification for details.
|
|
*/
|
|
scan_block_scalar_indicators(start_mark) {
|
|
var char, chomping, increment;
|
|
chomping = null;
|
|
increment = null;
|
|
char = this.peek();
|
|
if (indexOf.call('+-', char) >= 0) {
|
|
chomping = char === '+';
|
|
this.forward();
|
|
char = this.peek();
|
|
if (indexOf.call(C_NUMBERS, char) >= 0) {
|
|
increment = parseInt(char);
|
|
if (increment === 0) {
|
|
throw new exports.ScannerError('while scanning a block scalar', start_mark, 'expected indentation indicator in the range 1-9 but found 0', this.get_mark());
|
|
}
|
|
this.forward();
|
|
}
|
|
} else if (indexOf.call(C_NUMBERS, char) >= 0) {
|
|
increment = parseInt(char);
|
|
if (increment === 0) {
|
|
throw new exports.ScannerError('while scanning a block scalar', start_mark, 'expected indentation indicator in the range 1-9 but found 0', this.get_mark());
|
|
}
|
|
this.forward();
|
|
char = this.peek();
|
|
if (indexOf.call('+-', char) >= 0) {
|
|
chomping = char === '+';
|
|
this.forward();
|
|
}
|
|
}
|
|
char = this.peek();
|
|
if (indexOf.call(C_LB + '\x00 ', char) < 0) {
|
|
throw new exports.ScannerError('while scanning a block scalar', start_mark, `expected chomping or indentation indicators, but found ${char}`, this.get_mark());
|
|
}
|
|
return [chomping, increment];
|
|
}
|
|
|
|
/*
|
|
See the specification for details.
|
|
*/
|
|
scan_block_scalar_ignored_line(start_mark) {
|
|
var char, ref;
|
|
while (this.peek() === ' ') {
|
|
this.forward();
|
|
}
|
|
if (this.peek() === '#') {
|
|
while (ref = this.peek(), indexOf.call(C_LB + '\x00', ref) < 0) {
|
|
this.forward();
|
|
}
|
|
}
|
|
char = this.peek();
|
|
if (indexOf.call(C_LB + '\x00', char) < 0) {
|
|
throw new exports.ScannerError('while scanning a block scalar', start_mark, `expected a comment or a line break but found ${char}`, this.get_mark());
|
|
}
|
|
return this.scan_line_break();
|
|
}
|
|
|
|
/*
|
|
See the specification for details.
|
|
*/
|
|
scan_block_scalar_indentation() {
|
|
var chunks, end_mark, max_indent, ref;
|
|
chunks = [];
|
|
max_indent = 0;
|
|
end_mark = this.get_mark();
|
|
while (ref = this.peek(), indexOf.call(C_LB + ' ', ref) >= 0) {
|
|
if (this.peek() !== ' ') {
|
|
chunks.push(this.scan_line_break());
|
|
end_mark = this.get_mark();
|
|
} else {
|
|
this.forward();
|
|
if (this.column > max_indent) {
|
|
max_indent = this.column;
|
|
}
|
|
}
|
|
}
|
|
return [chunks, max_indent, end_mark];
|
|
}
|
|
|
|
/*
|
|
See the specification for details.
|
|
*/
|
|
scan_block_scalar_breaks(indent) {
|
|
var chunks, end_mark, ref;
|
|
chunks = [];
|
|
end_mark = this.get_mark();
|
|
while (this.column < indent && this.peek() === ' ') {
|
|
this.forward();
|
|
}
|
|
while (ref = this.peek(), indexOf.call(C_LB, ref) >= 0) {
|
|
chunks.push(this.scan_line_break());
|
|
end_mark = this.get_mark();
|
|
while (this.column < indent && this.peek() === ' ') {
|
|
this.forward();
|
|
}
|
|
}
|
|
return [chunks, end_mark];
|
|
}
|
|
|
|
/*
|
|
See the specification for details.
|
|
Note that we loose indentation rules for quoted scalars. Quoted scalars
|
|
don't need to adhere indentation because " and ' clearly mark the beginning
|
|
and the end of them. Therefore we are less restrictive than the
|
|
specification requires. We only need to check that document separators are
|
|
not included in scalars.
|
|
*/
|
|
scan_flow_scalar(style) {
|
|
var chunks, double, quote, start_mark;
|
|
double = style === '"';
|
|
chunks = [];
|
|
start_mark = this.get_mark();
|
|
quote = this.peek();
|
|
this.forward();
|
|
chunks = chunks.concat(this.scan_flow_scalar_non_spaces(double, start_mark));
|
|
while (this.peek() !== quote) {
|
|
chunks = chunks.concat(this.scan_flow_scalar_spaces(double, start_mark));
|
|
chunks = chunks.concat(this.scan_flow_scalar_non_spaces(double, start_mark));
|
|
}
|
|
this.forward();
|
|
return new tokens.ScalarToken(chunks.join(''), false, start_mark, this.get_mark(), style);
|
|
}
|
|
|
|
/*
|
|
See the specification for details.
|
|
*/
|
|
scan_flow_scalar_non_spaces(double, start_mark) {
|
|
var char, chunks, code, i, k, length, ref, ref1, ref2;
|
|
chunks = [];
|
|
while (true) {
|
|
length = 0;
|
|
while (ref = this.peek(length), indexOf.call(C_LB + C_WS + '\'"\\\x00', ref) < 0) {
|
|
length++;
|
|
}
|
|
if (length !== 0) {
|
|
chunks.push(this.prefix(length));
|
|
this.forward(length);
|
|
}
|
|
char = this.peek();
|
|
if (!double && char === '\'' && this.peek(1) === '\'') {
|
|
chunks.push('\'');
|
|
this.forward(2);
|
|
} else if ((double && char === '\'') || (!double && indexOf.call('"\\', char) >= 0)) {
|
|
chunks.push(char);
|
|
this.forward();
|
|
} else if (double && char === '\\') {
|
|
this.forward();
|
|
char = this.peek();
|
|
if (char in ESCAPE_REPLACEMENTS) {
|
|
chunks.push(ESCAPE_REPLACEMENTS[char]);
|
|
this.forward();
|
|
} else if (char in ESCAPE_CODES) {
|
|
length = ESCAPE_CODES[char];
|
|
this.forward();
|
|
for (k = i = 0, ref1 = length; 0 <= ref1 ? i < ref1 : i > ref1; k = 0 <= ref1 ? ++i : --i) {
|
|
if (ref2 = this.peek(k), indexOf.call(`${C_NUMBERS}ABCDEFabcdef`, ref2) < 0) {
|
|
throw new exports.ScannerError('while scanning a double-quoted scalar', start_mark, `expected escape sequence of ${length} hexadecimal numbers, but found ${this.peek(k)}`, this.get_mark());
|
|
}
|
|
}
|
|
code = parseInt(this.prefix(length), 16);
|
|
chunks.push(String.fromCharCode(code));
|
|
this.forward(length);
|
|
} else if (indexOf.call(C_LB, char) >= 0) {
|
|
this.scan_line_break();
|
|
chunks = chunks.concat(this.scan_flow_scalar_breaks(double, start_mark));
|
|
} else {
|
|
throw new exports.ScannerError('while scanning a double-quoted scalar', start_mark, `found unknown escape character ${char}`, this.get_mark());
|
|
}
|
|
} else {
|
|
return chunks;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
See the specification for details.
|
|
*/
|
|
scan_flow_scalar_spaces(double, start_mark) {
|
|
var breaks, char, chunks, length, line_break, ref, whitespaces;
|
|
chunks = [];
|
|
length = 0;
|
|
while (ref = this.peek(length), indexOf.call(C_WS, ref) >= 0) {
|
|
length++;
|
|
}
|
|
whitespaces = this.prefix(length);
|
|
this.forward(length);
|
|
char = this.peek();
|
|
if (char === '\x00') {
|
|
throw new exports.ScannerError('while scanning a quoted scalar', start_mark, 'found unexpected end of stream', this.get_mark());
|
|
}
|
|
if (indexOf.call(C_LB, char) >= 0) {
|
|
line_break = this.scan_line_break();
|
|
breaks = this.scan_flow_scalar_breaks(double, start_mark);
|
|
if (line_break !== '\n') {
|
|
chunks.push(line_break);
|
|
} else if (breaks.length === 0) {
|
|
chunks.push(' ');
|
|
}
|
|
chunks = chunks.concat(breaks);
|
|
} else {
|
|
chunks.push(whitespaces);
|
|
}
|
|
return chunks;
|
|
}
|
|
|
|
/*
|
|
See the specification for details.
|
|
*/
|
|
scan_flow_scalar_breaks(double, start_mark) {
|
|
var chunks, prefix, ref, ref1, ref2;
|
|
chunks = [];
|
|
while (true) {
|
|
// Instead of checking for indentation, we check for document separators.
|
|
prefix = this.prefix(3);
|
|
if (prefix === '---' || prefix === '...' && (ref = this.peek(3), indexOf.call(C_LB + C_WS + '\x00', ref) >= 0)) {
|
|
throw new exports.ScannerError('while scanning a quoted scalar', start_mark, 'found unexpected document separator', this.get_mark());
|
|
}
|
|
while (ref1 = this.peek(), indexOf.call(C_WS, ref1) >= 0) {
|
|
this.forward();
|
|
}
|
|
if (ref2 = this.peek(), indexOf.call(C_LB, ref2) >= 0) {
|
|
chunks.push(this.scan_line_break());
|
|
} else {
|
|
return chunks;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
See the specification for details.
|
|
We add an additional restriction for the flow context:
|
|
plain scalars in the flow context cannot contain ',', ':' and '?'.
|
|
We also keep track of the `allow_simple_key` flag here.
|
|
Indentation rules are loosed for the flow context.
|
|
*/
|
|
scan_plain() {
|
|
var char, chunks, end_mark, indent, length, ref, ref1, spaces, start_mark;
|
|
chunks = [];
|
|
start_mark = end_mark = this.get_mark();
|
|
indent = this.indent + 1;
|
|
// We allow zero indentation for scalars, but then we need to check for
|
|
// document separators at the beginning of the line.
|
|
// indent = 1 if indent is 0
|
|
spaces = [];
|
|
while (true) {
|
|
length = 0;
|
|
if (this.peek() === '#') {
|
|
break;
|
|
}
|
|
while (true) {
|
|
char = this.peek(length);
|
|
if (indexOf.call(C_LB + C_WS + '\x00', char) >= 0 || (this.flow_level === 0 && char === ':' && (ref = this.peek(length + 1), indexOf.call(C_LB + C_WS + '\x00', ref) >= 0)) || (this.flow_level !== 0 && indexOf.call(',:?[]{}', char) >= 0)) {
|
|
break;
|
|
}
|
|
length++;
|
|
}
|
|
// It's not clear what we should do with ':' in the flow context.
|
|
if (this.flow_level !== 0 && char === ':' && (ref1 = this.peek(length + 1), indexOf.call(C_LB + C_WS + '\x00,[]{}', ref1) < 0)) {
|
|
this.forward(length);
|
|
throw new exports.ScannerError('while scanning a plain scalar', start_mark, 'found unexpected \':\'', this.get_mark(), 'Please check http://pyyaml.org/wiki/YAMLColonInFlowContext');
|
|
}
|
|
if (length === 0) {
|
|
break;
|
|
}
|
|
this.allow_simple_key = false;
|
|
chunks = chunks.concat(spaces);
|
|
chunks.push(this.prefix(length));
|
|
this.forward(length);
|
|
end_mark = this.get_mark();
|
|
spaces = this.scan_plain_spaces(indent, start_mark);
|
|
if ((spaces == null) || spaces.length === 0 || this.peek() === '#' || (this.flow_level === 0 && this.column < indent)) {
|
|
break;
|
|
}
|
|
}
|
|
return new tokens.ScalarToken(chunks.join(''), true, start_mark, end_mark);
|
|
}
|
|
|
|
/*
|
|
See the specification for details.
|
|
The specification is really confusing about tabs in plain scalars.
|
|
We just forbid them completely. Do not use tabs in YAML!
|
|
*/
|
|
scan_plain_spaces(indent, start_mark) {
|
|
var breaks, char, chunks, length, line_break, prefix, ref, ref1, ref2, ref3, whitespaces;
|
|
chunks = [];
|
|
length = 0;
|
|
while (ref = this.peek(length), indexOf.call(' ', ref) >= 0) {
|
|
length++;
|
|
}
|
|
whitespaces = this.prefix(length);
|
|
this.forward(length);
|
|
char = this.peek();
|
|
if (indexOf.call(C_LB, char) >= 0) {
|
|
line_break = this.scan_line_break();
|
|
this.allow_simple_key = true;
|
|
prefix = this.prefix(3);
|
|
if (prefix === '---' || prefix === '...' && (ref1 = this.peek(3), indexOf.call(C_LB + C_WS + '\x00', ref1) >= 0)) {
|
|
return;
|
|
}
|
|
breaks = [];
|
|
while (ref3 = this.peek(), indexOf.call(C_LB + ' ', ref3) >= 0) {
|
|
if (this.peek() === ' ') {
|
|
this.forward();
|
|
} else {
|
|
breaks.push(this.scan_line_break());
|
|
prefix = this.prefix(3);
|
|
if (prefix === '---' || prefix === '...' && (ref2 = this.peek(3), indexOf.call(C_LB + C_WS + '\x00', ref2) >= 0)) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
if (line_break !== '\n') {
|
|
chunks.push(line_break);
|
|
} else if (breaks.length === 0) {
|
|
chunks.push(' ');
|
|
}
|
|
chunks = chunks.concat(breaks);
|
|
} else if (whitespaces) {
|
|
chunks.push(whitespaces);
|
|
}
|
|
return chunks;
|
|
}
|
|
|
|
/*
|
|
See the specification for details.
|
|
For some strange reasons, the specification does not allow '_' in tag
|
|
handles. I have allowed it anyway.
|
|
*/
|
|
scan_tag_handle(name, start_mark) {
|
|
var char, length, value;
|
|
char = this.peek();
|
|
if (char !== '!') {
|
|
throw new exports.ScannerError(`while scanning a ${name}`, start_mark, `expected '!' but found ${char}`, this.get_mark());
|
|
}
|
|
length = 1;
|
|
char = this.peek(length);
|
|
if (char !== ' ') {
|
|
while (('0' <= char && char <= '9') || ('A' <= char && char <= 'Z') || ('a' <= char && char <= 'z') || indexOf.call('-_', char) >= 0) {
|
|
length++;
|
|
char = this.peek(length);
|
|
}
|
|
if (char !== '!') {
|
|
this.forward(length);
|
|
throw new exports.ScannerError(`while scanning a ${name}`, start_mark, `expected '!' but found ${char}`, this.get_mark());
|
|
}
|
|
length++;
|
|
}
|
|
value = this.prefix(length);
|
|
this.forward(length);
|
|
return value;
|
|
}
|
|
|
|
/*
|
|
See the specification for details.
|
|
Note: we do not check if URI is well-formed.
|
|
*/
|
|
scan_tag_uri(name, start_mark) {
|
|
var char, chunks, length;
|
|
chunks = [];
|
|
length = 0;
|
|
char = this.peek(length);
|
|
while (('0' <= char && char <= '9') || ('A' <= char && char <= 'Z') || ('a' <= char && char <= 'z') || indexOf.call('-;/?:@&=+$,_.!~*\'()[]%', char) >= 0) {
|
|
if (char === '%') {
|
|
chunks.push(this.prefix(length));
|
|
this.forward(length);
|
|
length = 0;
|
|
chunks.push(this.scan_uri_escapes(name, start_mark));
|
|
} else {
|
|
length++;
|
|
}
|
|
char = this.peek(length);
|
|
}
|
|
if (length !== 0) {
|
|
chunks.push(this.prefix(length));
|
|
this.forward(length);
|
|
length = 0;
|
|
}
|
|
if (chunks.length === 0) {
|
|
throw new exports.ScannerError(`while parsing a ${name}`, start_mark, `expected URI but found ${char}`, this.get_mark());
|
|
}
|
|
return chunks.join('');
|
|
}
|
|
|
|
/*
|
|
See the specification for details.
|
|
*/
|
|
scan_uri_escapes(name, start_mark) {
|
|
var bytes, i, k, mark;
|
|
bytes = [];
|
|
mark = this.get_mark();
|
|
while (this.peek() === '%') {
|
|
this.forward();
|
|
for (k = i = 0; i <= 2; k = ++i) {
|
|
throw new exports.ScannerError(`while scanning a ${name}`, start_mark, `expected URI escape sequence of 2 hexadecimal numbers but found ${this.peek(k)}`, this.get_mark());
|
|
}
|
|
bytes.push(String.fromCharCode(parseInt(this.prefix(2), 16)));
|
|
this.forward(2);
|
|
}
|
|
return bytes.join('');
|
|
}
|
|
|
|
/*
|
|
Transforms:
|
|
'\r\n' : '\n'
|
|
'\r' : '\n'
|
|
'\n' : '\n'
|
|
'\x85' : '\n'
|
|
'\u2028' : '\u2028'
|
|
'\u2029 : '\u2029'
|
|
default : ''
|
|
*/
|
|
scan_line_break() {
|
|
var char;
|
|
char = this.peek();
|
|
if (indexOf.call('\r\n\x85', char) >= 0) {
|
|
if (this.prefix(2) === '\r\n') {
|
|
this.forward(2);
|
|
} else {
|
|
this.forward();
|
|
}
|
|
return '\n';
|
|
} else if (indexOf.call('\u2028\u2029', char) >= 0) {
|
|
this.forward();
|
|
return char;
|
|
}
|
|
return '';
|
|
}
|
|
|
|
};
|
|
|
|
C_LB = '\r\n\x85\u2028\u2029';
|
|
|
|
C_WS = '\t ';
|
|
|
|
C_NUMBERS = '0123456789';
|
|
|
|
ESCAPE_REPLACEMENTS = {
|
|
'0': '\x00',
|
|
'a': '\x07',
|
|
'b': '\x08',
|
|
't': '\x09',
|
|
'\t': '\x09',
|
|
'n': '\x0A',
|
|
'v': '\x0B',
|
|
'f': '\x0C',
|
|
'r': '\x0D',
|
|
'e': '\x1B',
|
|
' ': '\x20',
|
|
'"': '"',
|
|
'\\': '\\',
|
|
'N': '\x85',
|
|
'_': '\xA0',
|
|
'L': '\u2028',
|
|
'P': '\u2029'
|
|
};
|
|
|
|
ESCAPE_CODES = {
|
|
'x': 2,
|
|
'u': 4,
|
|
'U': 8
|
|
};
|
|
|
|
ctor = Scanner.prototype.initialise;
|
|
|
|
return Scanner;
|
|
|
|
}).call(this);
|
|
|
|
}).call(this);
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 56472:
|
|
/***/ (function(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) {
|
|
|
|
(function() {
|
|
var YAMLError, events, nodes, util;
|
|
|
|
events = __webpack_require__(35063);
|
|
|
|
nodes = __webpack_require__(96914);
|
|
|
|
util = __webpack_require__(23823);
|
|
|
|
({YAMLError} = __webpack_require__(45372));
|
|
|
|
this.SerializerError = class SerializerError extends YAMLError {};
|
|
|
|
this.Serializer = (function() {
|
|
var ctor;
|
|
|
|
class Serializer {
|
|
constructor() {
|
|
return ctor.apply(this, arguments);
|
|
}
|
|
|
|
initialise({
|
|
encoding: encoding,
|
|
explicit_start: explicit_start,
|
|
explicit_end: explicit_end,
|
|
version: version,
|
|
tags: tags
|
|
} = {}) {
|
|
this.encoding = encoding;
|
|
this.explicit_start = explicit_start;
|
|
this.explicit_end = explicit_end;
|
|
this.version = version;
|
|
this.tags = tags;
|
|
this.serialized_nodes = {};
|
|
this.anchors = {};
|
|
this.last_anchor_id = 0;
|
|
return this.closed = null;
|
|
}
|
|
|
|
open() {
|
|
if (this.closed === null) {
|
|
this.emit(new events.StreamStartEvent(this.encoding));
|
|
return this.closed = false;
|
|
} else if (this.closed) {
|
|
throw new SerializerError('serializer is closed');
|
|
} else {
|
|
throw new SerializerError('serializer is already open');
|
|
}
|
|
}
|
|
|
|
close() {
|
|
if (this.closed === null) {
|
|
throw new SerializerError('serializer is not opened');
|
|
} else if (!this.closed) {
|
|
this.emit(new events.StreamEndEvent);
|
|
return this.closed = true;
|
|
}
|
|
}
|
|
|
|
serialize(node) {
|
|
if (this.closed === null) {
|
|
throw new SerializerError('serializer is not opened');
|
|
} else if (this.closed) {
|
|
throw new SerializerError('serializer is closed');
|
|
}
|
|
if (node != null) {
|
|
this.emit(new events.DocumentStartEvent(void 0, void 0, this.explicit_start, this.version, this.tags));
|
|
this.anchor_node(node);
|
|
this.serialize_node(node);
|
|
this.emit(new events.DocumentEndEvent(void 0, void 0, this.explicit_end));
|
|
}
|
|
this.serialized_nodes = {};
|
|
this.anchors = {};
|
|
return this.last_anchor_id = 0;
|
|
}
|
|
|
|
anchor_node(node) {
|
|
var base, i, item, j, key, len, len1, name, ref, ref1, results, results1, value;
|
|
if (node.unique_id in this.anchors) {
|
|
return (base = this.anchors)[name = node.unique_id] != null ? base[name] : base[name] = this.generate_anchor(node);
|
|
} else {
|
|
this.anchors[node.unique_id] = null;
|
|
if (node instanceof nodes.SequenceNode) {
|
|
ref = node.value;
|
|
results = [];
|
|
for (i = 0, len = ref.length; i < len; i++) {
|
|
item = ref[i];
|
|
results.push(this.anchor_node(item));
|
|
}
|
|
return results;
|
|
} else if (node instanceof nodes.MappingNode) {
|
|
ref1 = node.value;
|
|
results1 = [];
|
|
for (j = 0, len1 = ref1.length; j < len1; j++) {
|
|
[key, value] = ref1[j];
|
|
this.anchor_node(key);
|
|
results1.push(this.anchor_node(value));
|
|
}
|
|
return results1;
|
|
}
|
|
}
|
|
}
|
|
|
|
generate_anchor(node) {
|
|
return `id${util.pad_left(++this.last_anchor_id, '0', 4)}`;
|
|
}
|
|
|
|
serialize_node(node, parent, index) {
|
|
var alias, default_tag, detected_tag, i, implicit, item, j, key, len, len1, ref, ref1, value;
|
|
alias = this.anchors[node.unique_id];
|
|
if (node.unique_id in this.serialized_nodes) {
|
|
return this.emit(new events.AliasEvent(alias));
|
|
} else {
|
|
this.serialized_nodes[node.unique_id] = true;
|
|
this.descend_resolver(parent, index);
|
|
if (node instanceof nodes.ScalarNode) {
|
|
detected_tag = this.resolve(nodes.ScalarNode, node.value, [true, false]);
|
|
default_tag = this.resolve(nodes.ScalarNode, node.value, [false, true]);
|
|
implicit = [node.tag === detected_tag, node.tag === default_tag];
|
|
this.emit(new events.ScalarEvent(alias, node.tag, implicit, node.value, void 0, void 0, node.style));
|
|
} else if (node instanceof nodes.SequenceNode) {
|
|
implicit = node.tag === this.resolve(nodes.SequenceNode, node.value, true);
|
|
this.emit(new events.SequenceStartEvent(alias, node.tag, implicit, void 0, void 0, node.flow_style));
|
|
ref = node.value;
|
|
for (index = i = 0, len = ref.length; i < len; index = ++i) {
|
|
item = ref[index];
|
|
this.serialize_node(item, node, index);
|
|
}
|
|
this.emit(new events.SequenceEndEvent);
|
|
} else if (node instanceof nodes.MappingNode) {
|
|
implicit = node.tag === this.resolve(nodes.MappingNode, node.value, true);
|
|
this.emit(new events.MappingStartEvent(alias, node.tag, implicit, void 0, void 0, node.flow_style));
|
|
ref1 = node.value;
|
|
for (j = 0, len1 = ref1.length; j < len1; j++) {
|
|
[key, value] = ref1[j];
|
|
this.serialize_node(key, node, null);
|
|
this.serialize_node(value, node, key);
|
|
}
|
|
this.emit(new events.MappingEndEvent);
|
|
}
|
|
return this.ascend_resolver();
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
ctor = Serializer.prototype.initialise;
|
|
|
|
return Serializer;
|
|
|
|
}).call(this);
|
|
|
|
}).call(this);
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 59902:
|
|
/***/ (function() {
|
|
|
|
(function() {
|
|
this.Token = class Token {
|
|
constructor(start_mark1, end_mark1) {
|
|
this.start_mark = start_mark1;
|
|
this.end_mark = end_mark1;
|
|
}
|
|
|
|
};
|
|
|
|
this.DirectiveToken = (function() {
|
|
class DirectiveToken extends this.Token {
|
|
constructor(name, value, start_mark, end_mark) {
|
|
super(start_mark, end_mark);
|
|
this.name = name;
|
|
this.value = value;
|
|
}
|
|
|
|
};
|
|
|
|
DirectiveToken.prototype.id = '<directive>';
|
|
|
|
return DirectiveToken;
|
|
|
|
}).call(this);
|
|
|
|
this.DocumentStartToken = (function() {
|
|
class DocumentStartToken extends this.Token {};
|
|
|
|
DocumentStartToken.prototype.id = '<document start>';
|
|
|
|
return DocumentStartToken;
|
|
|
|
}).call(this);
|
|
|
|
this.DocumentEndToken = (function() {
|
|
class DocumentEndToken extends this.Token {};
|
|
|
|
DocumentEndToken.prototype.id = '<document end>';
|
|
|
|
return DocumentEndToken;
|
|
|
|
}).call(this);
|
|
|
|
this.StreamStartToken = (function() {
|
|
class StreamStartToken extends this.Token {
|
|
constructor(start_mark, end_mark, encoding) {
|
|
super(start_mark, end_mark);
|
|
this.encoding = encoding;
|
|
}
|
|
|
|
};
|
|
|
|
StreamStartToken.prototype.id = '<stream start>';
|
|
|
|
return StreamStartToken;
|
|
|
|
}).call(this);
|
|
|
|
this.StreamEndToken = (function() {
|
|
class StreamEndToken extends this.Token {};
|
|
|
|
StreamEndToken.prototype.id = '<stream end>';
|
|
|
|
return StreamEndToken;
|
|
|
|
}).call(this);
|
|
|
|
this.BlockSequenceStartToken = (function() {
|
|
class BlockSequenceStartToken extends this.Token {};
|
|
|
|
BlockSequenceStartToken.prototype.id = '<block sequence start>';
|
|
|
|
return BlockSequenceStartToken;
|
|
|
|
}).call(this);
|
|
|
|
this.BlockMappingStartToken = (function() {
|
|
class BlockMappingStartToken extends this.Token {};
|
|
|
|
BlockMappingStartToken.prototype.id = '<block mapping end>';
|
|
|
|
return BlockMappingStartToken;
|
|
|
|
}).call(this);
|
|
|
|
this.BlockEndToken = (function() {
|
|
class BlockEndToken extends this.Token {};
|
|
|
|
BlockEndToken.prototype.id = '<block end>';
|
|
|
|
return BlockEndToken;
|
|
|
|
}).call(this);
|
|
|
|
this.FlowSequenceStartToken = (function() {
|
|
class FlowSequenceStartToken extends this.Token {};
|
|
|
|
FlowSequenceStartToken.prototype.id = '[';
|
|
|
|
return FlowSequenceStartToken;
|
|
|
|
}).call(this);
|
|
|
|
this.FlowMappingStartToken = (function() {
|
|
class FlowMappingStartToken extends this.Token {};
|
|
|
|
FlowMappingStartToken.prototype.id = '{';
|
|
|
|
return FlowMappingStartToken;
|
|
|
|
}).call(this);
|
|
|
|
this.FlowSequenceEndToken = (function() {
|
|
class FlowSequenceEndToken extends this.Token {};
|
|
|
|
FlowSequenceEndToken.prototype.id = ']';
|
|
|
|
return FlowSequenceEndToken;
|
|
|
|
}).call(this);
|
|
|
|
this.FlowMappingEndToken = (function() {
|
|
class FlowMappingEndToken extends this.Token {};
|
|
|
|
FlowMappingEndToken.prototype.id = '}';
|
|
|
|
return FlowMappingEndToken;
|
|
|
|
}).call(this);
|
|
|
|
this.KeyToken = (function() {
|
|
class KeyToken extends this.Token {};
|
|
|
|
KeyToken.prototype.id = '?';
|
|
|
|
return KeyToken;
|
|
|
|
}).call(this);
|
|
|
|
this.ValueToken = (function() {
|
|
class ValueToken extends this.Token {};
|
|
|
|
ValueToken.prototype.id = ':';
|
|
|
|
return ValueToken;
|
|
|
|
}).call(this);
|
|
|
|
this.BlockEntryToken = (function() {
|
|
class BlockEntryToken extends this.Token {};
|
|
|
|
BlockEntryToken.prototype.id = '-';
|
|
|
|
return BlockEntryToken;
|
|
|
|
}).call(this);
|
|
|
|
this.FlowEntryToken = (function() {
|
|
class FlowEntryToken extends this.Token {};
|
|
|
|
FlowEntryToken.prototype.id = ',';
|
|
|
|
return FlowEntryToken;
|
|
|
|
}).call(this);
|
|
|
|
this.AliasToken = (function() {
|
|
class AliasToken extends this.Token {
|
|
constructor(value, start_mark, end_mark) {
|
|
super(start_mark, end_mark);
|
|
this.value = value;
|
|
}
|
|
|
|
};
|
|
|
|
AliasToken.prototype.id = '<alias>';
|
|
|
|
return AliasToken;
|
|
|
|
}).call(this);
|
|
|
|
this.AnchorToken = (function() {
|
|
class AnchorToken extends this.Token {
|
|
constructor(value, start_mark, end_mark) {
|
|
super(start_mark, end_mark);
|
|
this.value = value;
|
|
}
|
|
|
|
};
|
|
|
|
AnchorToken.prototype.id = '<anchor>';
|
|
|
|
return AnchorToken;
|
|
|
|
}).call(this);
|
|
|
|
this.TagToken = (function() {
|
|
class TagToken extends this.Token {
|
|
constructor(value, start_mark, end_mark) {
|
|
super(start_mark, end_mark);
|
|
this.value = value;
|
|
}
|
|
|
|
};
|
|
|
|
TagToken.prototype.id = '<tag>';
|
|
|
|
return TagToken;
|
|
|
|
}).call(this);
|
|
|
|
this.ScalarToken = (function() {
|
|
class ScalarToken extends this.Token {
|
|
constructor(value, plain, start_mark, end_mark, style) {
|
|
super(start_mark, end_mark);
|
|
this.value = value;
|
|
this.plain = plain;
|
|
this.style = style;
|
|
}
|
|
|
|
};
|
|
|
|
ScalarToken.prototype.id = '<scalar>';
|
|
|
|
return ScalarToken;
|
|
|
|
}).call(this);
|
|
|
|
}).call(this);
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 23823:
|
|
/***/ (function(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) {
|
|
|
|
(function() {
|
|
/*
|
|
A small class to stand-in for a stream when you simply want to write to a string.
|
|
*/
|
|
var ref, ref1, ref2,
|
|
hasProp = {}.hasOwnProperty;
|
|
|
|
this.StringStream = class StringStream {
|
|
constructor() {
|
|
this.string = '';
|
|
}
|
|
|
|
write(chunk) {
|
|
return this.string += chunk;
|
|
}
|
|
|
|
};
|
|
|
|
this.clone = (obj) => {
|
|
return Object.assign({}, obj);
|
|
};
|
|
|
|
this.extend = function(destination, ...sources) {
|
|
var i, j, len, len1, name, ref, source;
|
|
for (i = 0, len = sources.length; i < len; i++) {
|
|
source = sources[i];
|
|
while (source !== Object.prototype) {
|
|
ref = Object.getOwnPropertyNames(source);
|
|
for (j = 0, len1 = ref.length; j < len1; j++) {
|
|
name = ref[j];
|
|
if (destination[name] == null) {
|
|
destination[name] = source[name];
|
|
}
|
|
}
|
|
source = Object.getPrototypeOf(source);
|
|
}
|
|
}
|
|
return destination;
|
|
};
|
|
|
|
this.is_empty = function(obj) {
|
|
var key;
|
|
if (Array.isArray(obj) || typeof obj === 'string') {
|
|
return obj.length === 0;
|
|
}
|
|
for (key in obj) {
|
|
if (!hasProp.call(obj, key)) continue;
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
|
|
this.inspect = (ref = (ref1 = (ref2 = __webpack_require__(31669)) != null ? ref2.inspect : void 0) != null ? ref1 : global.inspect) != null ? ref : function(a) {
|
|
return `${a}`;
|
|
};
|
|
|
|
this.pad_left = function(str, char, length) {
|
|
str = String(str);
|
|
if (str.length >= length) {
|
|
return str;
|
|
} else if (str.length + 1 === length) {
|
|
return `${char}${str}`;
|
|
} else {
|
|
return `${new Array(length - str.length + 1).join(char)}${str}`;
|
|
}
|
|
};
|
|
|
|
this.to_hex = function(num) {
|
|
if (typeof num === 'string') {
|
|
num = num.charCodeAt(0);
|
|
}
|
|
return num.toString(16);
|
|
};
|
|
|
|
}).call(this);
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 35740:
|
|
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
|
|
(function() {
|
|
var composer, constructor, dumper, errors, events, loader, nodes, parser, reader, resolver, scanner, tokens, util;
|
|
|
|
composer = this.composer = __webpack_require__(6391);
|
|
|
|
constructor = this.constructor = __webpack_require__(51574);
|
|
|
|
dumper = this.dumper = __webpack_require__(28190);
|
|
|
|
errors = this.errors = __webpack_require__(45372);
|
|
|
|
events = this.events = __webpack_require__(35063);
|
|
|
|
loader = this.loader = __webpack_require__(82696);
|
|
|
|
nodes = this.nodes = __webpack_require__(96914);
|
|
|
|
parser = this.parser = __webpack_require__(72806);
|
|
|
|
reader = this.reader = __webpack_require__(27026);
|
|
|
|
resolver = this.resolver = __webpack_require__(3579);
|
|
|
|
scanner = this.scanner = __webpack_require__(72265);
|
|
|
|
tokens = this.tokens = __webpack_require__(59902);
|
|
|
|
util = __webpack_require__(23823);
|
|
|
|
/*
|
|
Scan a YAML stream and produce scanning tokens.
|
|
*/
|
|
this.scan = function(stream, Loader = loader.Loader) {
|
|
var _loader, results;
|
|
_loader = new Loader(stream);
|
|
results = [];
|
|
while (_loader.check_token()) {
|
|
results.push(_loader.get_token());
|
|
}
|
|
return results;
|
|
};
|
|
|
|
/*
|
|
Parse a YAML stream and produce parsing events.
|
|
*/
|
|
this.parse = function(stream, Loader = loader.Loader) {
|
|
var _loader, results;
|
|
_loader = new Loader(stream);
|
|
results = [];
|
|
while (_loader.check_event()) {
|
|
results.push(_loader.get_event());
|
|
}
|
|
return results;
|
|
};
|
|
|
|
/*
|
|
Parse the first YAML document in a stream and produce the corresponding
|
|
representation tree.
|
|
*/
|
|
this.compose = function(stream, Loader = loader.Loader) {
|
|
var _loader;
|
|
_loader = new Loader(stream);
|
|
return _loader.get_single_node();
|
|
};
|
|
|
|
/*
|
|
Parse all YAML documents in a stream and produce corresponding representation
|
|
trees.
|
|
*/
|
|
this.compose_all = function(stream, Loader = loader.Loader) {
|
|
var _loader, results;
|
|
_loader = new Loader(stream);
|
|
results = [];
|
|
while (_loader.check_node()) {
|
|
results.push(_loader.get_node());
|
|
}
|
|
return results;
|
|
};
|
|
|
|
/*
|
|
Parse the first YAML document in a stream and produce the corresponding
|
|
Javascript object.
|
|
*/
|
|
this.load = function(stream, Loader = loader.Loader) {
|
|
var _loader;
|
|
_loader = new Loader(stream);
|
|
return _loader.get_single_data();
|
|
};
|
|
|
|
/*
|
|
Parse all YAML documents in a stream and produce the corresponing Javascript
|
|
object.
|
|
*/
|
|
this.load_all = function(stream, Loader = loader.Loader) {
|
|
var _loader, results;
|
|
_loader = new Loader(stream);
|
|
results = [];
|
|
while (_loader.check_data()) {
|
|
results.push(_loader.get_data());
|
|
}
|
|
return results;
|
|
};
|
|
|
|
/*
|
|
Emit YAML parsing events into a stream.
|
|
If stream is falsey, return the produced string instead.
|
|
*/
|
|
this.emit = function(events, stream, Dumper = dumper.Dumper, options = {}) {
|
|
var _dumper, dest, event, i, len;
|
|
dest = stream || new util.StringStream;
|
|
_dumper = new Dumper(dest, options);
|
|
try {
|
|
for (i = 0, len = events.length; i < len; i++) {
|
|
event = events[i];
|
|
_dumper.emit(event);
|
|
}
|
|
} finally {
|
|
_dumper.dispose();
|
|
}
|
|
return stream || dest.string;
|
|
};
|
|
|
|
/*
|
|
Serialize a representation tree into a YAML stream.
|
|
If stream is falsey, return the produced string instead.
|
|
*/
|
|
this.serialize = function(node, stream, Dumper = dumper.Dumper, options = {}) {
|
|
return exports.serialize_all([node], stream, Dumper, options);
|
|
};
|
|
|
|
/*
|
|
Serialize a sequence of representation tress into a YAML stream.
|
|
If stream is falsey, return the produced string instead.
|
|
*/
|
|
this.serialize_all = function(nodes, stream, Dumper = dumper.Dumper, options = {}) {
|
|
var _dumper, dest, i, len, node;
|
|
dest = stream || new util.StringStream;
|
|
_dumper = new Dumper(dest, options);
|
|
try {
|
|
_dumper.open();
|
|
for (i = 0, len = nodes.length; i < len; i++) {
|
|
node = nodes[i];
|
|
_dumper.serialize(node);
|
|
}
|
|
_dumper.close();
|
|
} finally {
|
|
_dumper.dispose();
|
|
}
|
|
return stream || dest.string;
|
|
};
|
|
|
|
/*
|
|
Serialize a Javascript object into a YAML stream.
|
|
If stream is falsey, return the produced string instead.
|
|
*/
|
|
this.dump = function(data, stream, Dumper = dumper.Dumper, options = {}) {
|
|
return exports.dump_all([data], stream, Dumper, options);
|
|
};
|
|
|
|
/*
|
|
Serialize a sequence of Javascript objects into a YAML stream.
|
|
If stream is falsey, return the produced string instead.
|
|
*/
|
|
this.dump_all = function(documents, stream, Dumper = dumper.Dumper, options = {}) {
|
|
var _dumper, dest, document, i, len;
|
|
dest = stream || new util.StringStream;
|
|
_dumper = new Dumper(dest, options);
|
|
try {
|
|
_dumper.open();
|
|
for (i = 0, len = documents.length; i < len; i++) {
|
|
document = documents[i];
|
|
_dumper.represent(document);
|
|
}
|
|
_dumper.close();
|
|
} finally {
|
|
_dumper.dispose();
|
|
}
|
|
return stream || dest.string;
|
|
};
|
|
|
|
}).call(this);
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ 79264:
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
module.exports = __webpack_require__(39026);
|
|
|
|
|
|
/***/ })
|
|
|
|
};
|
|
;
|
|
//# sourceMappingURL=305.index.js.map |