diff --git a/badges/coverage-badge.svg b/badges/coverage-badge.svg
index 9e7204d..d3c6bed 100644
--- a/badges/coverage-badge.svg
+++ b/badges/coverage-badge.svg
@@ -1 +1 @@
-
+
diff --git a/badges/tests-badge.svg b/badges/tests-badge.svg
index a1036d0..fbcf6a9 100644
--- a/badges/tests-badge.svg
+++ b/badges/tests-badge.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/dist/index-browser-esm.js b/dist/index-browser-esm.js
index 7cc39bf..38e8701 100644
--- a/dist/index-browser-esm.js
+++ b/dist/index-browser-esm.js
@@ -75,10 +75,7 @@ class Plugins {
* @param {PluginSetup} plugins.init The init function
* @public
*/
- register() {
- for (var _len = arguments.length, plugins = new Array(_len), _key = 0; _key < _len; _key++) {
- plugins[_key] = arguments[_key];
- }
+ register(...plugins) {
plugins.forEach(plugin => {
if (typeof plugin !== 'object' || !plugin.name || !plugin.init) {
throw new Error('Invalid JSEP plugin format');
@@ -1608,11 +1605,12 @@ JSONPath.prototype.evaluate = function (expr, json, callback, otherTypeCallback)
if (!expr && expr !== '' || !json) {
return undefined;
}
- const exprList = JSONPath.toPathArray(expr);
- if (exprList[0] === '$' && exprList.length > 1) {
+ const exprList = JSONPath.toPathParts(expr);
+ if (exprList[0] && exprList[0].type === 'root' && exprList.length > 1) {
exprList.shift();
}
this._hasParentSelector = null;
+ this._json = json; // Store root for parent selector navigation
const result = this._trace(exprList, json, ['$'], currParent, currParentProperty, callback).filter(function (ea) {
return ea && !ea.isParentSelector;
});
@@ -1640,7 +1638,7 @@ JSONPath.prototype._getPreferredOutput = function (ea) {
switch (resultType) {
case 'all':
{
- const path = Array.isArray(ea.path) ? ea.path : JSONPath.toPathArray(ea.path);
+ const path = Array.isArray(ea.path) ? ea.path : JSONPath.toPathParts(ea.path);
ea.pointer = JSONPath.toPointer(path);
ea.path = typeof ea.path === 'string' ? ea.path : JSONPath.toPathString(ea.path);
return ea;
@@ -1691,9 +1689,9 @@ JSONPath.prototype._trace = function (expr, val, path, parent, parentPropName, c
hasArrExpr
};
this._handleCallback(retObj, callback, 'value');
- return retObj;
+ return [retObj];
}
- const loc = expr[0],
+ const token = expr[0],
x = expr.slice(1);
// We need to gather the return value of recursive trace calls in order to
@@ -1716,168 +1714,266 @@ JSONPath.prototype._trace = function (expr, val, path, parent, parentPropName, c
ret.push(elems);
}
}
- if ((typeof loc !== 'string' || literalPriority) && val && Object.hasOwn(val, loc)) {
- // simple case--directly follow property
- addRet(this._trace(x, val[loc], push(path, loc), val, loc, callback, hasArrExpr));
- // eslint-disable-next-line unicorn/prefer-switch -- Part of larger `if`
- } else if (loc === '*') {
- // all child properties
- this._walk(val, m => {
- addRet(this._trace(x, val[m], push(path, m), val, m, callback, true, true));
- });
- } else if (loc === '..') {
- // all descendent parent properties
- // Check remaining expression with val's immediate children
- addRet(this._trace(x, val, path, parent, parentPropName, callback, hasArrExpr));
- this._walk(val, m => {
- // We don't join m and x here because we only want parents,
- // not scalar values
- if (typeof val[m] === 'object') {
- // Keep going with recursive descent on val's
- // object children
- addRet(this._trace(expr.slice(), val[m], push(path, m), val, m, callback, true));
- }
- });
- // The parent sel computation is handled in the frame above using the
- // ancestor object of val
- } else if (loc === '^') {
- // This is not a final endpoint, so we do not invoke the callback here
- this._hasParentSelector = true;
- return {
- path: path.slice(0, -1),
- expr: x,
- isParentSelector: true
- };
- } else if (loc === '~') {
- // property name
- retObj = {
- path: push(path, loc),
- value: parentPropName,
- parent,
- parentProperty: null
- };
- this._handleCallback(retObj, callback, 'property');
- return retObj;
- } else if (loc === '$') {
- // root only
- addRet(this._trace(x, val, path, null, null, callback, hasArrExpr));
- } else if (/^(-?\d*):(-?\d*):?(\d*)$/u.test(loc)) {
- // [start:end:step] Python slice syntax
- addRet(this._slice(loc, x, val, path, parent, parentPropName, callback));
- } else if (loc.indexOf('?(') === 0) {
- // [?(expr)] (filtering)
- if (this.currEval === false) {
- throw new Error('Eval [?(expr)] prevented in JSONPath expression.');
- }
- const safeLoc = loc.replace(/^\?\((.*?)\)$/u, '$1');
- // check for a nested filter expression
- const nested = /@.?([^?]*)[['](\??\(.*?\))(?!.\)\])[\]']/gu.exec(safeLoc);
- if (nested) {
- // find if there are matches in the nested expression
- // add them to the result set if there is at least one match
- this._walk(val, m => {
- const npath = [nested[2]];
- const nvalue = nested[1] ? val[m][nested[1]] : val[m];
- const filterResults = this._trace(npath, nvalue, path, parent, parentPropName, callback, true);
- if (filterResults.length > 0) {
- addRet(this._trace(x, val[m], push(path, m), val, m, callback, true));
- }
- });
- } else {
- this._walk(val, m => {
- if (this._eval(safeLoc, val[m], m, path, parent, parentPropName)) {
- addRet(this._trace(x, val[m], push(path, m), val, m, callback, true));
- }
- });
+
+ // Fast path for primitive tokens (strings and numbers)
+ if (typeof token === 'string') {
+ // Simple property access
+ if (val && Object.hasOwn(val, token)) {
+ addRet(this._trace(x, val[token], push(path, token), val, token, callback, hasArrExpr));
}
- } else if (loc[0] === '(') {
- // [(expr)] (dynamic property/index)
- if (this.currEval === false) {
- throw new Error('Eval [(expr)] prevented in JSONPath expression.');
- }
- // As this will resolve to a property name (but we don't know it
- // yet), property and parent information is relative to the
- // parent of the property to which this expression will resolve
- addRet(this._trace(unshift(this._eval(loc, val, path.at(-1), path.slice(0, -1), parent, parentPropName), x), val, path, parent, parentPropName, callback, hasArrExpr));
- } else if (loc[0] === '@') {
- // value type: @boolean(), etc.
- let addType = false;
- const valueType = loc.slice(1, -2);
- switch (valueType) {
- case 'scalar':
- if (!val || !['object', 'function'].includes(typeof val)) {
- addType = true;
- }
+ } else if (typeof token === 'number') {
+ // Simple numeric index access
+ if (Array.isArray(val) && token >= 0 && token < val.length) {
+ addRet(this._trace(x, val[token], push(path, token), val, token, callback, hasArrExpr));
+ }
+ } else if (token && typeof token === 'object' && token.type) {
+ // Handle complex token objects
+ switch (token.type) {
+ case 'root':
+ // $
+ addRet(this._trace(x, val, path, null, null, callback, hasArrExpr));
break;
- case 'boolean':
- case 'string':
- case 'undefined':
- case 'function':
- if (typeof val === valueType) {
- addType = true;
+ case 'property':
+ {
+ const propName = token.value;
+ // Check if property exists (escaped flag just means it's not wildcard)
+ if (val && Object.hasOwn(val, propName)) {
+ addRet(this._trace(x, val[propName], push(path, propName), val, propName, callback, hasArrExpr, true));
+ }
+ break;
}
+ case 'wildcard':
+ // *
+ this._walk(val, m => {
+ addRet(this._trace(x, val[m], push(path, m), val, m, callback, true, true));
+ });
break;
- case 'integer':
- if (Number.isFinite(val) && !(val % 1)) {
- addType = true;
- }
+ case 'descent':
+ // ..
+ // Check remaining expression with val's immediate children
+ addRet(this._trace(x, val, path, parent, parentPropName, callback, hasArrExpr));
+ this._walk(val, m => {
+ // We don't join m and x here because we only want parents,
+ // not scalar values
+ if (typeof val[m] === 'object') {
+ // Keep going with recursive descent on val's
+ // object children
+ addRet(this._trace(expr.slice(), val[m], push(path, m), val, m, callback, true));
+ }
+ });
break;
- case 'number':
- if (Number.isFinite(val)) {
- addType = true;
+ case 'parent':
+ // ^
+ // This is not a final endpoint, so we do not invoke the callback here
+ // Only allow parent selector if we're not already at root
+ if (path.length > 1) {
+ this._hasParentSelector = true;
+ ret.push({
+ path: path.slice(0, -1),
+ expr: x,
+ isParentSelector: true
+ });
}
break;
- case 'nonFinite':
- if (typeof val === 'number' && !Number.isFinite(val)) {
- addType = true;
- }
+ case 'propertyName':
+ // ~
+ retObj = {
+ path: push(path, '~'),
+ value: parentPropName,
+ parent,
+ parentProperty: null
+ };
+ this._handleCallback(retObj, callback, 'property');
+ ret.push(retObj);
break;
- case 'object':
- if (val && typeof val === valueType) {
- addType = true;
+ case 'index':
+ {
+ const idx = token.value;
+ if (Array.isArray(val) && idx >= 0 && idx < val.length || val && Object.hasOwn(val, idx)) {
+ addRet(this._trace(x, val[idx], push(path, idx), val, idx, callback, hasArrExpr, true));
+ }
+ break;
}
+ case 'slice':
+ addRet(this._slice(token, x, val, path, parent, parentPropName, callback));
break;
- case 'array':
- if (Array.isArray(val)) {
- addType = true;
+ case 'filter':
+ {
+ if (this.currEval === false) {
+ throw new Error('Eval [?(expr)] prevented in JSONPath expression.');
+ }
+
+ // Quick check: Does this filter have nested paths?
+ const hasNesting = token.expression.includes('[?(');
+ if (!hasNesting) {
+ // Fast path: No nesting, skip extraction
+ this._walk(val, m => {
+ if (this._eval(token.expression, val[m], m, path, parent, parentPropName)) {
+ addRet(this._trace(x, val[m], push(path, m), val, m, callback, true));
+ }
+ });
+ } else {
+ // Slow path: Extract and handle nested filters
+ const {
+ expression: modifiedExpr,
+ nestedPaths
+ } = this._extractNestedFilters(token.expression);
+
+ // Check if expression is JUST a nested path (no other JavaScript)
+ // If so, we need to check array length for truthiness
+ const isSingleNestedPath = nestedPaths.length === 1 && modifiedExpr.trim() === '_$_jp0';
+
+ // Evaluate filter for each item
+ this._walk(val, m => {
+ // Evaluate nested paths in context of current item
+ const nestedResults = {};
+ for (const [i, nestedPath] of nestedPaths.entries()) {
+ // Convert @ to $ for parsing (@ means current value)
+ const pathForParsing = nestedPath.replace(/^@/u, '$');
+ try {
+ const nestedTokens = JSONPath.toPathParts(pathForParsing);
+ // Evaluate nested path on current item
+ const nestedResult = this._trace(nestedTokens, val[m], push(path, m), val, m, null,
+ // no callback for nested evaluation
+ true);
+ // Extract values from result objects
+ nestedResults[`_$_jp${i}`] = nestedResult.map(r => r.value);
+ } catch (e) {
+ // If nested evaluation fails, treat as no matches
+ nestedResults[`_$_jp${i}`] = [];
+ }
+ }
+
+ // Add nested results to sandbox temporarily
+ const originalSandbox = {
+ ...this.currSandbox
+ };
+ Object.assign(this.currSandbox, nestedResults);
+ try {
+ // For single nested path, check if array has elements
+ // (empty arrays are truthy in JS but should be falsy in filter)
+ const matches = isSingleNestedPath ? nestedResults._$_jp0.length > 0 : this._eval(modifiedExpr, val[m], m, path, parent, parentPropName);
+ if (matches) {
+ addRet(this._trace(x, val[m], push(path, m), val, m, callback, true));
+ }
+ } finally {
+ // Restore original sandbox (remove nested result placeholders)
+ this.currSandbox = originalSandbox;
+ }
+ });
+ }
+ break;
}
- break;
- case 'other':
- addType = this.currOtherTypeCallback(val, path, parent, parentPropName);
- break;
- case 'null':
- if (val === null) {
- addType = true;
+ case 'dynamic':
+ {
+ if (this.currEval === false) {
+ throw new Error('Eval [(expr)] prevented in JSONPath expression.');
+ }
+ // As this will resolve to a property name (but we don't know it
+ // yet), property and parent information is relative to the
+ // parent of the property to which this expression will resolve
+ addRet(this._trace(unshift(this._eval(token.expression, val, path.at(-1), path.slice(0, -1), parent, parentPropName), x), val, path, parent, parentPropName, callback, hasArrExpr));
+ break;
+ }
+ case 'typeOperator':
+ {
+ let addType = false;
+ const {
+ valueType
+ } = token;
+ switch (valueType) {
+ case 'scalar':
+ if (!val || !['object', 'function'].includes(typeof val)) {
+ addType = true;
+ }
+ break;
+ case 'boolean':
+ case 'string':
+ case 'undefined':
+ case 'function':
+ if (typeof val === valueType) {
+ addType = true;
+ }
+ break;
+ case 'integer':
+ if (Number.isFinite(val) && !(val % 1)) {
+ addType = true;
+ }
+ break;
+ case 'number':
+ if (Number.isFinite(val)) {
+ addType = true;
+ }
+ break;
+ case 'nonFinite':
+ if (typeof val === 'number' && !Number.isFinite(val)) {
+ addType = true;
+ }
+ break;
+ case 'object':
+ if (val && typeof val === valueType) {
+ addType = true;
+ }
+ break;
+ case 'array':
+ if (Array.isArray(val)) {
+ addType = true;
+ }
+ break;
+ case 'other':
+ addType = this.currOtherTypeCallback(val, path, parent, parentPropName);
+ break;
+ case 'null':
+ if (val === null) {
+ addType = true;
+ }
+ break;
+ /* c8 ignore next 2 */
+ default:
+ throw new TypeError('Unknown value type ' + valueType);
+ }
+ if (addType) {
+ retObj = {
+ path,
+ value: val,
+ parent,
+ parentProperty: parentPropName
+ };
+ this._handleCallback(retObj, callback, 'value');
+ ret.push(retObj);
+ }
+ break;
+ }
+ case 'multiProperty':
+ {
+ const parts = token.properties;
+ const escapedFlags = token.escaped || [];
+ for (const [i, part] of parts.entries()) {
+ // Check if part is a number (multi-index) or string (multi-property)
+ let partToken;
+ if (typeof part === 'number') {
+ partToken = {
+ type: 'index',
+ value: part
+ };
+ } else {
+ const isEscaped = escapedFlags[i] || false;
+ partToken = {
+ type: 'property',
+ value: part,
+ escaped: isEscaped
+ };
+ }
+ addRet(this._trace(unshift(partToken, x), val, path, parent, parentPropName, callback, true));
+ }
+ break;
}
- break;
- /* c8 ignore next 2 */
- default:
- throw new TypeError('Unknown value type ' + valueType);
- }
- if (addType) {
- retObj = {
- path,
- value: val,
- parent,
- parentProperty: parentPropName
- };
- this._handleCallback(retObj, callback, 'value');
- return retObj;
- }
- // `-escaped property
- } else if (loc[0] === '`' && val && Object.hasOwn(val, loc.slice(1))) {
- const locProp = loc.slice(1);
- addRet(this._trace(x, val[locProp], push(path, locProp), val, locProp, callback, hasArrExpr, true));
- } else if (loc.includes(',')) {
- // [name1,name2,...]
- const parts = loc.split(',');
- for (const part of parts) {
- addRet(this._trace(unshift(part, x), val, path, parent, parentPropName, callback, true));
}
- // simple case--directly follow property
- } else if (!literalPriority && val && Object.hasOwn(val, loc)) {
- addRet(this._trace(x, val[loc], push(path, loc), val, loc, callback, hasArrExpr, true));
+ } else if ((typeof token !== 'string' || literalPriority) && val && Object.hasOwn(val, token)) {
+ // simple case--directly follow property (for object tokens or with literalPriority)
+ addRet(this._trace(x, val[token], push(path, token), val, token, callback, hasArrExpr));
}
+ // Note: Legacy string token handling removed - now handled by fast path above
// We check the resulting values for parent selections. For parent
// selections we discard the value object and continue the trace with the
@@ -1886,7 +1982,20 @@ JSONPath.prototype._trace = function (expr, val, path, parent, parentPropName, c
for (let t = 0; t < ret.length; t++) {
const rett = ret[t];
if (rett && rett.isParentSelector) {
- const tmp = this._trace(rett.expr, val, rett.path, parent, parentPropName, callback, hasArrExpr);
+ // Navigate from root to the parent path to get correct parent context
+ // rett.path is the path with last element removed (e.g., ['$', 'children'])
+ let resultVal = this._json;
+ let resultParent = null;
+ let resultParentProp = null;
+
+ // Navigate from root following the path
+ // Start at index 1 to skip '$'
+ for (let i = 1; i < rett.path.length; i++) {
+ resultParent = resultVal;
+ resultParentProp = rett.path[i];
+ resultVal = resultVal[rett.path[i]];
+ }
+ const tmp = this._trace(rett.expr, resultVal, rett.path, resultParent, resultParentProp, callback, hasArrExpr);
if (Array.isArray(tmp)) {
ret[t] = tmp[0];
const tl = tmp.length;
@@ -1916,15 +2025,229 @@ JSONPath.prototype._walk = function (val, f) {
});
}
};
-JSONPath.prototype._slice = function (loc, expr, val, path, parent, parentPropName, callback) {
+
+/**
+ * Extract nested JSONPath expressions from a filter expression.
+ * @param {string} expr - Filter expression (e.g., "@.children[?(@.price<10)]")
+ * @returns {{expression: string, nestedPaths: string[]}} Modified expression and extracted paths
+ */
+JSONPath.prototype._extractNestedFilters = function (expr) {
+ // Check cache first
+ const cache = JSONPath.filterExtractionCache;
+ if (cache[expr]) {
+ // Return shallow clone to prevent mutation
+ return {
+ expression: cache[expr].expression,
+ nestedPaths: [...cache[expr].nestedPaths]
+ };
+ }
+ const nestedPaths = [];
+ let result = expr;
+ let placeholderCount = 0;
+
+ // We need to find patterns like @.path[?(...)] or @[?(...)], etc.
+ // Use a stack-based approach to handle nested brackets properly
+
+ /**
+ * Find the next JSONPath expression starting with @.
+ * @param {string} str - String to search
+ * @param {number} startPos - Position to start searching
+ * @returns {{start: number, end: number, path: string} | null}
+ */
+ function findNextNestedPath(str, startPos) {
+ let i = startPos;
+
+ // Find next @ that's not in a string or regex literal
+ while (i < str.length) {
+ const ch = str[i];
+
+ // Skip string literals
+ if (ch === '"' || ch === "'") {
+ const quote = ch;
+ i++;
+ while (i < str.length) {
+ if (str[i] === '\\' && i + 1 < str.length) {
+ i += 2; // Skip escaped character
+ } else if (str[i] === quote) {
+ i++;
+ break;
+ } else {
+ i++;
+ }
+ }
+ continue;
+ }
+
+ // Skip regex literals (simplified detection)
+ if (ch === '/' && i > 0) {
+ // Check if this might be a regex (not division)
+ // Look back for operators that could precede a regex
+ const prevNonSpace = str.slice(0, i).trimEnd().slice(-1);
+ if ('=([{,;:!&|?'.includes(prevNonSpace) || i === startPos) {
+ i++;
+ while (i < str.length) {
+ if (str[i] === '\\' && i + 1 < str.length) {
+ i += 2;
+ } else if (str[i] === '/') {
+ i++;
+ // Skip regex flags
+ while (i < str.length && /[gimsuvy]/u.test(str[i])) {
+ i++;
+ }
+ break;
+ } else {
+ i++;
+ }
+ }
+ continue;
+ }
+ }
+
+ // Found @ - check if it's followed by JSONPath syntax
+ if (ch === '@') {
+ const pathStart = i;
+ i++; // Move past @
+
+ // Check if there's path syntax after @
+ // Could be: @.prop, @[, @.., @@
+ if (i >= str.length) {
+ return null;
+ }
+ let hasPathSyntax = false;
+ let path = '@';
+
+ // Parse the JSONPath expression
+ while (i < str.length) {
+ const c = str[i];
+
+ // Path components
+ if (c === '.' || c === '[' || c === '*' || c === '^' || c === '~') {
+ hasPathSyntax = true;
+ path += c;
+ i++;
+
+ // Handle bracket notation with bracket matching
+ if (c === '[') {
+ let depth = 1;
+ /* eslint-disable unicorn/prefer-switch --
+ Complex bracket matching with nested quotes */
+ while (i < str.length && depth > 0) {
+ if (str[i] === '\\' && i + 1 < str.length) {
+ path += str[i] + str[i + 1];
+ i += 2;
+ } else if (str[i] === '"' || str[i] === "'") {
+ // Handle quoted strings in brackets
+ const q = str[i];
+ path += str[i];
+ i++;
+ while (i < str.length && str[i] !== q) {
+ if (str[i] === '\\' && i + 1 < str.length) {
+ path += str[i] + str[i + 1];
+ i += 2;
+ } else {
+ path += str[i];
+ i++;
+ }
+ }
+ if (i < str.length) {
+ path += str[i];
+ i++;
+ }
+ } else if (str[i] === '[') {
+ depth++;
+ path += str[i];
+ i++;
+ } else if (str[i] === ']') {
+ depth--;
+ path += str[i];
+ i++;
+ } else {
+ path += str[i];
+ i++;
+ }
+ }
+ /* eslint-enable unicorn/prefer-switch --
+ Re-enable after bracket matching section */
+ }
+ } else if (/[\w$]/u.test(c)) {
+ // Property name characters
+ hasPathSyntax = true;
+ path += c;
+ i++;
+ } else {
+ // End of path
+ break;
+ }
+ }
+
+ // Check if this path contains a filter (has [?(...)])
+ // Only extract paths that have filters to avoid unnecessary evaluation
+ if (hasPathSyntax && path.includes('[?')) {
+ return {
+ start: pathStart,
+ end: i,
+ path
+ };
+ }
+
+ // No filter found, continue searching
+ continue;
+ }
+ i++;
+ }
+ return null;
+ }
+
+ // Extract all nested paths
+ let searchPos = 0;
+ const replacements = [];
+ while (searchPos < result.length) {
+ const found = findNextNestedPath(result, searchPos);
+ if (!found) {
+ break;
+ }
+
+ // Store the replacement to be made
+ replacements.push({
+ start: found.start,
+ end: found.end,
+ path: found.path,
+ placeholder: `_$_jp${placeholderCount}`
+ });
+ nestedPaths.push(found.path);
+ placeholderCount++;
+ searchPos = found.end;
+ }
+
+ // Apply replacements in reverse order to maintain positions
+ for (let i = replacements.length - 1; i >= 0; i--) {
+ const {
+ start,
+ end,
+ placeholder
+ } = replacements[i];
+ result = result.slice(0, start) + placeholder + result.slice(end);
+ }
+
+ // Cache the result
+ const extractionResult = {
+ expression: result,
+ nestedPaths
+ };
+ cache[expr] = extractionResult;
+ return {
+ expression: result,
+ nestedPaths: [...nestedPaths]
+ };
+};
+JSONPath.prototype._slice = function (token, expr, val, path, parent, parentPropName, callback) {
if (!Array.isArray(val)) {
return undefined;
}
- const len = val.length,
- parts = loc.split(':'),
- step = parts[2] && Number.parseInt(parts[2]) || 1;
- let start = parts[0] && Number.parseInt(parts[0]) || 0,
- end = parts[1] && Number.parseInt(parts[1]) || len;
+ const len = val.length;
+ let start = token.start === null ? 0 : token.start;
+ let end = token.end === null ? len : token.end;
+ const step = token.step === null ? 1 : token.step;
start = start < 0 ? Math.max(0, start + len) : Math.min(len, start);
end = end < 0 ? Math.max(0, end + len) : Math.min(len, end);
const ret = [];
@@ -1986,9 +2309,11 @@ JSONPath.prototype._eval = function (code, _v, _vname, path, parent, parentPropN
// Could store the cache object itself
JSONPath.cache = {};
+JSONPath.pathPartsCache = {};
+JSONPath.filterExtractionCache = {};
/**
- * @param {string[]} pathArr Array to convert
+ * @param {string[]|object[]} pathArr Array to convert
* @returns {string} The path string
*/
JSONPath.toPathString = function (pathArr) {
@@ -1996,15 +2321,54 @@ JSONPath.toPathString = function (pathArr) {
n = x.length;
let p = '$';
for (let i = 1; i < n; i++) {
- if (!/^(~|\^|@.*?\(\))$/u.test(x[i])) {
- p += /^[0-9*]+$/u.test(x[i]) ? '[' + x[i] + ']' : "['" + x[i] + "']";
+ const item = x[i];
+
+ // Handle both old string format and new token format
+ if (typeof item === 'number') {
+ // Array index
+ p += '[' + item + ']';
+ } else if (typeof item === 'string') {
+ // Legacy path
+ if (!/^(~|\^|@.*?\(\))$/u.test(item)) {
+ p += /^[0-9*]+$/u.test(item) ? '[' + item + ']' : "['" + item + "']";
+ }
+ } else if (item && typeof item === 'object') {
+ // New token format
+ switch (item.type) {
+ case 'property':
+ p += "['" + item.value + "']";
+ break;
+ case 'index':
+ p += '[' + item.value + ']';
+ break;
+ case 'wildcard':
+ p += '[*]';
+ break;
+ case 'slice':
+ p += '[' + item.raw + ']';
+ break;
+ case 'filter':
+ p += '[?(' + item.expression + ')]';
+ break;
+ case 'dynamic':
+ p += '[(' + item.expression + ')]';
+ break;
+ case 'typeOperator':
+ p += '@' + item.valueType + '()';
+ break;
+ case 'multiProperty':
+ p += "['" + item.properties.join("','") + "']";
+ break;
+ }
}
}
return p;
};
/**
- * @param {string} pointer JSON Path
+ * Converts path array to JSON Pointer format.
+ * Handles both legacy string arrays and new token objects.
+ * @param {string[]|object[]} pointer - Path array
* @returns {string} JSON Pointer
*/
JSONPath.toPointer = function (pointer) {
@@ -2012,59 +2376,653 @@ JSONPath.toPointer = function (pointer) {
n = x.length;
let p = '';
for (let i = 1; i < n; i++) {
- if (!/^(~|\^|@.*?\(\))$/u.test(x[i])) {
- p += '/' + x[i].toString().replaceAll('~', '~0').replaceAll('/', '~1');
+ const item = x[i];
+ let value;
+
+ // Handle different formats
+ if (typeof item === 'number') {
+ value = String(item);
+ } else if (typeof item === 'string') {
+ // Legacy string format or special operators
+ if (/^(~|\^|@.*?\(\))$/u.test(item)) {
+ continue; // Skip special operators
+ }
+ value = item;
+ } else if (item && typeof item === 'object') {
+ // New token format
+ switch (item.type) {
+ case 'property':
+ {
+ const {
+ value: propValue
+ } = item;
+ value = propValue;
+ break;
+ }
+ case 'index':
+ {
+ const {
+ value: indexValue
+ } = item;
+ value = String(indexValue);
+ break;
+ }
+ // Skip special operators
+ case 'root':
+ case 'wildcard':
+ case 'descent':
+ case 'parent':
+ case 'propertyName':
+ case 'filter':
+ case 'dynamic':
+ case 'slice':
+ case 'typeOperator':
+ case 'multiProperty':
+ continue;
+ default:
+ continue;
+ }
+ } else {
+ continue;
}
+
+ // Escape ~ and / per JSON Pointer spec
+ p += '/' + value.replaceAll('~', '~0').replaceAll('/', '~1');
}
return p;
};
/**
- * @param {string} expr Expression to convert
- * @returns {string[]}
+ * Parse a JSONPath expression into structured tokens.
+ * @param {string} expr - JSONPath expression
+ * @returns {Array} Array of tokens
+ */
+/**
+ * Parses a JSONPath expression into structured token objects.
+ * @param {string} expr - JSONPath expression to parse
+ * @returns {object[]} Array of token objects
*/
-JSONPath.toPathArray = function (expr) {
- const {
- cache
- } = JSONPath;
+JSONPath.toPathParts = function (expr) {
+ const cache = JSONPath.pathPartsCache;
if (cache[expr]) {
- return cache[expr].concat();
- }
- const subx = [];
- const normalized = expr
- // Properties
- .replaceAll(/@(?:null|boolean|number|string|integer|undefined|nonFinite|scalar|array|object|function|other)\(\)/gu, ';$&;')
- // Parenthetical evaluations (filtering and otherwise), directly
- // within brackets or single quotes
- .replaceAll(/[['](\??\(.*?\))[\]'](?!.\])/gu, function ($0, $1) {
- return '[#' + (subx.push($1) - 1) + ']';
- })
- // Escape periods and tildes within properties
- .replaceAll(/\[['"]([^'\]]*)['"]\]/gu, function ($0, prop) {
- return "['" + prop.replaceAll('.', '%@%').replaceAll('~', '%%@@%%') + "']";
- })
- // Properties operator
- .replaceAll('~', ';~;')
- // Split by property boundaries
- .replaceAll(/['"]?\.['"]?(?![^[]*\])|\[['"]?/gu, ';')
- // Reinsert periods within properties
- .replaceAll('%@%', '.')
- // Reinsert tildes within properties
- .replaceAll('%%@@%%', '~')
- // Parent
- .replaceAll(/(?:;)?(\^+)(?:;)?/gu, function ($0, ups) {
- return ';' + ups.split('').join(';') + ';';
- })
- // Descendents
- .replaceAll(/;;;|;;/gu, ';..;')
- // Remove trailing
- .replaceAll(/;$|'?\]|'$/gu, '');
- const exprList = normalized.split(';').map(function (exp) {
- const match = exp.match(/#(\d+)/u);
- return !match || !match[1] ? exp : subx[match[1]];
- });
- cache[expr] = exprList;
- return cache[expr].concat();
+ // Shallow clone array, shallow clone object tokens
+ // (tokens are simple objects with no nested objects)
+ return cache[expr].map(token => typeof token === 'object' && token !== null ? {
+ ...token
+ } : token);
+ }
+ const tokens = [];
+ let i = 0;
+
+ // Handle empty path - treat as empty property access
+ if (expr === '') {
+ // Hybrid token: empty property is a string
+ tokens.push('');
+ cache[expr] = tokens;
+ return cache[expr].map(token => typeof token === 'object' && token !== null ? {
+ ...token
+ } : token);
+ }
+
+ /**
+ * Extract balanced content between delimiters.
+ * @param {number} start - Starting position
+ * @param {string} open - Opening delimiter
+ * @param {string} close - Closing delimiter
+ * @throws {SyntaxError} If delimiters are unbalanced
+ * @returns {{content: string, end: number}} Extracted content and end position
+ */
+ function extractBalanced(start, open, close) {
+ let depth = 1;
+ let j = start;
+ while (j < expr.length && depth > 0) {
+ if (expr[j] === open) {
+ depth++;
+ } else if (expr[j] === close) {
+ depth--;
+ }
+ j++;
+ }
+ if (depth !== 0) {
+ throw new SyntaxError(`Unbalanced ${open}${close} in expression at position ${start}`);
+ }
+ return {
+ content: expr.slice(start, j - 1),
+ end: j
+ };
+ }
+
+ /**
+ * Extract quoted string.
+ * @param {number} start - Starting position (after quote)
+ * @param {string} quote - Quote character
+ * @throws {SyntaxError} If string is unterminated
+ * @returns {{content: string, end: number, escaped: boolean}} Extracted content, end position, and whether it's backtick-escaped
+ */
+ function extractQuoted(start, quote) {
+ let j = start;
+ let content = '';
+ let escaped = false;
+ while (j < expr.length) {
+ if (expr[j] === '\\' && j + 1 < expr.length) {
+ // Handle backslash escape sequences
+ content += expr[j + 1];
+ j += 2;
+ } else if (expr[j] === '`' && j + 1 < expr.length) {
+ // Handle backtick escape - backtick escapes next char
+ content += expr[j + 1];
+ escaped = true;
+ j += 2;
+ } else if (expr[j] === quote) {
+ return {
+ content,
+ end: j + 1,
+ escaped
+ };
+ } else {
+ content += expr[j];
+ j++;
+ }
+ }
+ throw new SyntaxError(`Unterminated string at position ${start - 1}`);
+ }
+
+ /**
+ * Handle dot notation (.property or ..descendant).
+ * @throws {SyntaxError} If malformed
+ * @returns {void}
+ */
+ function handleDotNotation() {
+ if (i + 1 < expr.length && expr[i + 1] === '.') {
+ // Descendant (..)
+ tokens.push({
+ type: 'descent'
+ });
+ i += 2;
+ } else {
+ // Skip the dot and parse property name
+ i++;
+ if (i >= expr.length) {
+ throw new SyntaxError('Unexpected end after dot at position ' + (i - 1));
+ }
+
+ // Check what follows the dot
+ switch (expr[i]) {
+ case '*':
+ tokens.push({
+ type: 'wildcard'
+ });
+ i++;
+ break;
+ case '`':
+ // Backtick escapes the next character
+ i++; // Skip backtick
+ if (i >= expr.length) {
+ throw new SyntaxError('Unexpected end after backtick at position ' + (i - 1));
+ }
+ // The escaped character becomes the property name
+ tokens.push({
+ type: 'property',
+ value: expr[i],
+ escaped: true
+ });
+ i++;
+ break;
+ case '[':
+ // Dot followed by bracket: interpret as descent
+ // e.g., $.[?(...)] becomes $ .. [?(...)]
+ tokens.push({
+ type: 'descent'
+ });
+ break;
+ default:
+ {
+ // Regular property name (until next special char)
+ let propName = '';
+ while (i < expr.length && !/[.[\]^~@*]/u.test(expr[i])) {
+ propName += expr[i];
+ i++;
+ }
+ if (propName) {
+ // Hybrid token: use string for unescaped properties
+ tokens.push(propName);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Handle bracket notation [...].
+ * @throws {SyntaxError} If malformed
+ * @returns {void}
+ */
+ function handleBracketNotation() {
+ i++; // Skip [
+ if (i >= expr.length) {
+ throw new SyntaxError('Unexpected end after [ at position ' + (i - 1));
+ }
+
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ const ch = expr[i];
+
+ // Wildcard [*]
+ if (ch === '*') {
+ i++;
+ // Skip whitespace and closing bracket
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after * at position ' + i);
+ }
+ i++;
+ tokens.push({
+ type: 'wildcard'
+ });
+ return;
+ }
+
+ // Filter [?(expression)]
+ if (ch === '?') {
+ if (i + 1 >= expr.length || expr[i + 1] !== '(') {
+ throw new SyntaxError('Expected ( after ? at position ' + i);
+ }
+ i += 2; // Skip ?(
+ const result = extractBalanced(i, '(', ')');
+ const {
+ content: expression
+ } = result;
+ i = result.end;
+
+ // Skip whitespace and closing bracket
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after filter at position ' + i);
+ }
+ i++;
+ tokens.push({
+ type: 'filter',
+ expression
+ });
+ return;
+ }
+
+ // Dynamic [(expression)]
+ if (ch === '(') {
+ i++; // Skip (
+ const result = extractBalanced(i, '(', ')');
+ const {
+ content: expression
+ } = result;
+ i = result.end;
+
+ // Skip whitespace and closing bracket
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after dynamic expression at position ' + i);
+ }
+ i++;
+ tokens.push({
+ type: 'dynamic',
+ expression
+ });
+ return;
+ }
+
+ // Quoted property ['name'] or ["name"]
+ if (ch === "'" || ch === '"') {
+ const quote = ch;
+ i++; // Skip opening quote
+ const result = extractQuoted(i, quote);
+ const {
+ content,
+ escaped
+ } = result;
+ i = result.end;
+
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+
+ // Check for comma (multi-property)
+ if (expr[i] === ',') {
+ const properties = [content];
+ const escapedFlags = [escaped];
+ while (expr[i] === ',') {
+ i++; // Skip comma
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ if (expr[i] !== "'" && expr[i] !== '"') {
+ throw new SyntaxError('Expected quoted property after comma at position ' + i);
+ }
+ const q = expr[i];
+ i++;
+ const r = extractQuoted(i, q);
+ properties.push(r.content);
+ escapedFlags.push(r.escaped);
+ i = r.end;
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after multi-property at position ' + i);
+ }
+ i++;
+ tokens.push({
+ type: 'multiProperty',
+ properties,
+ escaped: escapedFlags
+ });
+ return;
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after quoted property at position ' + i);
+ }
+ i++;
+ // Check if quoted property is wildcard
+ if (content === '*' && !escaped) {
+ tokens.push({
+ type: 'wildcard'
+ });
+ } else if (escaped) {
+ // Keep object for escaped properties (metadata needed)
+ tokens.push({
+ type: 'property',
+ value: content,
+ escaped: true
+ });
+ } else {
+ // Hybrid token: use string for unescaped properties
+ tokens.push(content);
+ }
+ return;
+ }
+
+ // Number (index, slice, or multi-index)
+ if (/[-\d]/u.test(ch) || ch === ':') {
+ let numStr = '';
+ while (i < expr.length && /[-\d:]/u.test(expr[i])) {
+ numStr += expr[i];
+ i++;
+ }
+
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+
+ // Check for comma (multi-index like [0,1,2])
+ if (expr[i] === ',') {
+ const indices = [Number.parseInt(numStr)];
+ while (expr[i] === ',') {
+ i++; // Skip comma
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ // Read next number
+ let nextNum = '';
+ while (i < expr.length && /[-\d]/u.test(expr[i])) {
+ nextNum += expr[i];
+ i++;
+ }
+ indices.push(Number.parseInt(nextNum));
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after multi-index at position ' + i);
+ }
+ i++;
+ // Create multiProperty token with numeric properties
+ tokens.push({
+ type: 'multiProperty',
+ properties: indices
+ });
+ return;
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after number at position ' + i);
+ }
+ i++;
+
+ // Check if it's a slice (contains :)
+ if (numStr.includes(':')) {
+ const parts = numStr.split(':');
+ const start = parts[0] === '' ? null : Number.parseInt(parts[0]);
+ const end = parts[1] === '' ? null : Number.parseInt(parts[1]);
+ const step = parts.length > 2 && parts[2] !== '' ? Number.parseInt(parts[2]) : null;
+ tokens.push({
+ type: 'slice',
+ start,
+ end,
+ step,
+ raw: numStr
+ });
+ } else {
+ // Simple index - Hybrid token: use number directly
+ const index = Number.parseInt(numStr);
+ tokens.push(index);
+ }
+ return;
+ }
+
+ // Unquoted property (identifier)
+ // In brackets, unquoted properties can have backtick escapes
+ let propName = '';
+ let escaped = false;
+ while (i < expr.length && expr[i] !== ']' && expr[i] !== ',' && !/\s/u.test(expr[i])) {
+ if (expr[i] === '`' && i + 1 < expr.length && expr[i + 1] !== ']' && expr[i + 1] !== ',') {
+ // Backtick escapes next character
+ propName += expr[i + 1];
+ escaped = true;
+ i += 2;
+ } else {
+ propName += expr[i];
+ i++;
+ }
+ }
+
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+
+ // Check for comma (multi-property with unquoted names)
+ if (expr[i] === ',') {
+ const properties = [propName];
+ const escapedFlags = [escaped];
+ while (expr[i] === ',') {
+ i++; // Skip comma
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ let prop = '';
+ let propEscaped = false;
+ while (i < expr.length && expr[i] !== ']' && expr[i] !== ',' && !/\s/u.test(expr[i])) {
+ if (expr[i] === '`' && i + 1 < expr.length && expr[i + 1] !== ']' && expr[i + 1] !== ',') {
+ // Backtick escapes next character
+ prop += expr[i + 1];
+ propEscaped = true;
+ i += 2;
+ } else {
+ prop += expr[i];
+ i++;
+ }
+ }
+ if (!prop) {
+ throw new SyntaxError('Expected property name after comma at position ' + i);
+ }
+ properties.push(prop);
+ escapedFlags.push(propEscaped);
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after multi-property at position ' + i);
+ }
+ i++;
+ tokens.push({
+ type: 'multiProperty',
+ properties,
+ escaped: escapedFlags
+ });
+ return;
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after property at position ' + i);
+ }
+ i++;
+ if (propName) {
+ if (escaped) {
+ // Keep object for escaped properties
+ tokens.push({
+ type: 'property',
+ value: propName,
+ escaped: true
+ });
+ } else {
+ // Hybrid token: use string for unescaped properties
+ tokens.push(propName);
+ }
+ }
+ }
+
+ /**
+ * Handle type operator `@type()`.
+ * @throws {SyntaxError} If malformed
+ * @returns {void}
+ */
+ function handleTypeOperator() {
+ i++; // Skip @
+ let typeName = '';
+ while (i < expr.length && /[a-z]/ui.test(expr[i])) {
+ typeName += expr[i];
+ i++;
+ }
+ if (i + 1 >= expr.length || expr[i] !== '(' || expr[i + 1] !== ')') {
+ throw new SyntaxError('Expected () after @' + typeName + ' at position ' + i);
+ }
+ i += 2; // Skip ()
+ tokens.push({
+ type: 'typeOperator',
+ valueType: typeName
+ });
+ }
+
+ // If path doesn't start with $, [, or other special char, add implicit root
+ if (expr.length > 0 && !['$', '[', '.', '^', '~', '@'].includes(expr[0])) {
+ tokens.push({
+ type: 'root'
+ });
+ // Prepend with a dot to make it valid for our parser
+ expr = '.' + expr;
+ }
+
+ // Main parsing loop
+ while (i < expr.length) {
+ const ch = expr[i];
+ switch (ch) {
+ case '$':
+ tokens.push({
+ type: 'root'
+ });
+ i++;
+ break;
+ case '.':
+ handleDotNotation();
+ break;
+ case '[':
+ handleBracketNotation();
+ break;
+ case '*':
+ // Wildcard (can appear after .. without a dot)
+ tokens.push({
+ type: 'wildcard'
+ });
+ i++;
+ break;
+ case '^':
+ // If parent selector comes right after root (or at start),
+ // add implicit empty string property
+ // This handles cases like "^" or "$^" which should be "['']^"
+ if (tokens.length === 0 || tokens.length === 1 && tokens[0].type === 'root') {
+ // Hybrid token: empty property is a string
+ tokens.push('');
+ }
+ tokens.push({
+ type: 'parent'
+ });
+ i++;
+ break;
+ case '~':
+ tokens.push({
+ type: 'propertyName'
+ });
+ i++;
+ break;
+ case '@':
+ // Check if this is a type operator like @boolean()
+ // Type operators have the pattern: @identifier()
+ if (/^@[a-z]+\(\)/ui.test(expr.slice(i))) {
+ handleTypeOperator();
+ } else {
+ // Treat @ as part of a property name
+ let propName = '';
+ while (i < expr.length && /[\w$@\\]/u.test(expr[i])) {
+ propName += expr[i];
+ i++;
+ }
+ if (propName) {
+ // Hybrid token: use string for unescaped properties
+ tokens.push(propName);
+ }
+ }
+ break;
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ // Skip whitespace
+ i++;
+ break;
+ default:
+ // Try to parse as identifier (property name)
+ if (/[\w$]/u.test(ch)) {
+ let propName = '';
+ while (i < expr.length && /[\w$]/u.test(expr[i])) {
+ propName += expr[i];
+ i++;
+ }
+ // Hybrid token: use string for unescaped properties
+ tokens.push(propName);
+ } else {
+ throw new SyntaxError(`Unexpected character '${ch}' at position ${i}`);
+ }
+ }
+ }
+ cache[expr] = tokens;
+ return tokens.map(token => typeof token === 'object' && token !== null ? {
+ ...token
+ } : token);
};
JSONPath.prototype.safeVm = {
Script: SafeScript
diff --git a/dist/index-browser-esm.min.js b/dist/index-browser-esm.min.js
index e799e2f..3f9e06c 100644
--- a/dist/index-browser-esm.min.js
+++ b/dist/index-browser-esm.min.js
@@ -1,2 +1,2 @@
-class e{static get version(){return"1.4.0"}static toString(){return"JavaScript Expression Parser (JSEP) v"+e.version}static addUnaryOp(t){return e.max_unop_len=Math.max(t.length,e.max_unop_len),e.unary_ops[t]=1,e}static addBinaryOp(t,r,s){return e.max_binop_len=Math.max(t.length,e.max_binop_len),e.binary_ops[t]=r,s?e.right_associative.add(t):e.right_associative.delete(t),e}static addIdentifierChar(t){return e.additional_identifier_chars.add(t),e}static addLiteral(t,r){return e.literals[t]=r,e}static removeUnaryOp(t){return delete e.unary_ops[t],t.length===e.max_unop_len&&(e.max_unop_len=e.getMaxKeyLen(e.unary_ops)),e}static removeAllUnaryOps(){return e.unary_ops={},e.max_unop_len=0,e}static removeIdentifierChar(t){return e.additional_identifier_chars.delete(t),e}static removeBinaryOp(t){return delete e.binary_ops[t],t.length===e.max_binop_len&&(e.max_binop_len=e.getMaxKeyLen(e.binary_ops)),e.right_associative.delete(t),e}static removeAllBinaryOps(){return e.binary_ops={},e.max_binop_len=0,e}static removeLiteral(t){return delete e.literals[t],e}static removeAllLiterals(){return e.literals={},e}get char(){return this.expr.charAt(this.index)}get code(){return this.expr.charCodeAt(this.index)}constructor(e){this.expr=e,this.index=0}static parse(t){return new e(t).parse()}static getMaxKeyLen(e){return Math.max(0,...Object.keys(e).map((e=>e.length)))}static isDecimalDigit(e){return e>=48&&e<=57}static binaryPrecedence(t){return e.binary_ops[t]||0}static isIdentifierStart(t){return t>=65&&t<=90||t>=97&&t<=122||t>=128&&!e.binary_ops[String.fromCharCode(t)]||e.additional_identifier_chars.has(String.fromCharCode(t))}static isIdentifierPart(t){return e.isIdentifierStart(t)||e.isDecimalDigit(t)}throwError(e){const t=new Error(e+" at character "+this.index);throw t.index=this.index,t.description=e,t}runHook(t,r){if(e.hooks[t]){const s={context:this,node:r};return e.hooks.run(t,s),s.node}return r}searchHook(t){if(e.hooks[t]){const r={context:this};return e.hooks[t].find((function(e){return e.call(r.context,r),r.node})),r.node}}gobbleSpaces(){let t=this.code;for(;t===e.SPACE_CODE||t===e.TAB_CODE||t===e.LF_CODE||t===e.CR_CODE;)t=this.expr.charCodeAt(++this.index);this.runHook("gobble-spaces")}parse(){this.runHook("before-all");const t=this.gobbleExpressions(),r=1===t.length?t[0]:{type:e.COMPOUND,body:t};return this.runHook("after-all",r)}gobbleExpressions(t){let r,s,n=[];for(;this.index0;){if(e.binary_ops.hasOwnProperty(t)&&(!e.isIdentifierStart(this.code)||this.index+t.lengthi.right_a&&e.right_a?s>e.prec:s<=e.prec;for(;n.length>2&&h(n[n.length-2]);)a=n.pop(),r=n.pop().value,o=n.pop(),t={type:e.BINARY_EXP,operator:r,left:o,right:a},n.push(t);t=this.gobbleToken(),t||this.throwError("Expected expression after "+l),n.push(i,t)}for(h=n.length-1,t=n[h];h>1;)t={type:e.BINARY_EXP,operator:n[h-1].value,left:n[h-2],right:t},h-=2;return t}gobbleToken(){let t,r,s,n;if(this.gobbleSpaces(),n=this.searchHook("gobble-token"),n)return this.runHook("after-token",n);if(t=this.code,e.isDecimalDigit(t)||t===e.PERIOD_CODE)return this.gobbleNumericLiteral();if(t===e.SQUOTE_CODE||t===e.DQUOTE_CODE)n=this.gobbleStringLiteral();else if(t===e.OBRACK_CODE)n=this.gobbleArray();else{for(r=this.expr.substr(this.index,e.max_unop_len),s=r.length;s>0;){if(e.unary_ops.hasOwnProperty(r)&&(!e.isIdentifierStart(this.code)||this.index+r.length=r.length&&this.throwError("Unexpected token "+String.fromCharCode(t));break}if(i===e.COMMA_CODE){if(this.index++,n++,n!==r.length)if(t===e.CPAREN_CODE)this.throwError("Unexpected token ,");else if(t===e.CBRACK_CODE)for(let e=r.length;e{if("object"!=typeof e||!e.name||!e.init)throw new Error("Invalid JSEP plugin format");this.registered[e.name]||(e.init(this.jsep),this.registered[e.name]=e)}))}}(e),COMPOUND:"Compound",SEQUENCE_EXP:"SequenceExpression",IDENTIFIER:"Identifier",MEMBER_EXP:"MemberExpression",LITERAL:"Literal",THIS_EXP:"ThisExpression",CALL_EXP:"CallExpression",UNARY_EXP:"UnaryExpression",BINARY_EXP:"BinaryExpression",ARRAY_EXP:"ArrayExpression",TAB_CODE:9,LF_CODE:10,CR_CODE:13,SPACE_CODE:32,PERIOD_CODE:46,COMMA_CODE:44,SQUOTE_CODE:39,DQUOTE_CODE:34,OPAREN_CODE:40,CPAREN_CODE:41,OBRACK_CODE:91,CBRACK_CODE:93,QUMARK_CODE:63,SEMCOL_CODE:59,COLON_CODE:58,unary_ops:{"-":1,"!":1,"~":1,"+":1},binary_ops:{"||":1,"??":1,"&&":2,"|":3,"^":4,"&":5,"==":6,"!=":6,"===":6,"!==":6,"<":7,">":7,"<=":7,">=":7,"<<":8,">>":8,">>>":8,"+":9,"-":9,"*":10,"/":10,"%":10,"**":11},right_associative:new Set(["**"]),additional_identifier_chars:new Set(["$","_"]),literals:{true:!0,false:!1,null:null},this_str:"this"}),e.max_unop_len=e.getMaxKeyLen(e.unary_ops),e.max_binop_len=e.getMaxKeyLen(e.binary_ops);const r=t=>new e(t).parse(),s=Object.getOwnPropertyNames(class{});Object.getOwnPropertyNames(e).filter((e=>!s.includes(e)&&void 0===r[e])).forEach((t=>{r[t]=e[t]})),r.Jsep=e;var n={name:"ternary",init(e){e.hooks.add("after-expression",(function(t){if(t.node&&this.code===e.QUMARK_CODE){this.index++;const r=t.node,s=this.gobbleExpression();if(s||this.throwError("Expected expression"),this.gobbleSpaces(),this.code===e.COLON_CODE){this.index++;const n=this.gobbleExpression();if(n||this.throwError("Expected expression"),t.node={type:"ConditionalExpression",test:r,consequent:s,alternate:n},r.operator&&e.binary_ops[r.operator]<=.9){let s=r;for(;s.right.operator&&e.binary_ops[s.right.operator]<=.9;)s=s.right;t.node.test=s.right,s.right=t.node,t.node=r}}else this.throwError("Expected :")}}))}};r.plugins.register(n);var i={name:"regex",init(e){e.hooks.add("gobble-token",(function(t){if(47===this.code){const r=++this.index;let s=!1;for(;this.index=97&&e<=122||e>=65&&e<=90||e>=48&&e<=57))break;i+=this.char}try{n=new RegExp(s,i)}catch(e){this.throwError(e.message)}return t.node={type:e.LITERAL,value:n,raw:this.expr.slice(r-1,this.index)},t.node=this.gobbleTokenProperty(t.node),t.node}this.code===e.OBRACK_CODE?s=!0:s&&this.code===e.CBRACK_CODE&&(s=!1),this.index+=92===this.code?2:1}this.throwError("Unclosed Regex")}}))}};const o={name:"assignment",assignmentOperators:new Set(["=","*=","**=","/=","%=","+=","-=","<<=",">>=",">>>=","&=","^=","|=","||=","&&=","??="]),updateOperators:[43,45],assignmentPrecedence:.9,init(e){const t=[e.IDENTIFIER,e.MEMBER_EXP];function r(e){o.assignmentOperators.has(e.operator)?(e.type="AssignmentExpression",r(e.left),r(e.right)):e.operator||Object.values(e).forEach((e=>{e&&"object"==typeof e&&r(e)}))}o.assignmentOperators.forEach((t=>e.addBinaryOp(t,o.assignmentPrecedence,!0))),e.hooks.add("gobble-token",(function(e){const r=this.code;o.updateOperators.some((e=>e===r&&e===this.expr.charCodeAt(this.index+1)))&&(this.index+=2,e.node={type:"UpdateExpression",operator:43===r?"++":"--",argument:this.gobbleTokenProperty(this.gobbleIdentifier()),prefix:!0},e.node.argument&&t.includes(e.node.argument.type)||this.throwError(`Unexpected ${e.node.operator}`))})),e.hooks.add("after-token",(function(e){if(e.node){const r=this.code;o.updateOperators.some((e=>e===r&&e===this.expr.charCodeAt(this.index+1)))&&(t.includes(e.node.type)||this.throwError(`Unexpected ${e.node.operator}`),this.index+=2,e.node={type:"UpdateExpression",operator:43===r?"++":"--",argument:e.node,prefix:!1})}})),e.hooks.add("after-expression",(function(e){e.node&&r(e.node)}))}};r.plugins.register(i,o),r.addUnaryOp("typeof"),r.addUnaryOp("void"),r.addLiteral("null",null),r.addLiteral("undefined",void 0);const a=new Set(["constructor","__proto__","__defineGetter__","__defineSetter__","__lookupGetter__","__lookupSetter__"]),h={evalAst(e,t){switch(e.type){case"BinaryExpression":case"LogicalExpression":return h.evalBinaryExpression(e,t);case"Compound":return h.evalCompound(e,t);case"ConditionalExpression":return h.evalConditionalExpression(e,t);case"Identifier":return h.evalIdentifier(e,t);case"Literal":return h.evalLiteral(e,t);case"MemberExpression":return h.evalMemberExpression(e,t);case"UnaryExpression":return h.evalUnaryExpression(e,t);case"ArrayExpression":return h.evalArrayExpression(e,t);case"CallExpression":return h.evalCallExpression(e,t);case"AssignmentExpression":return h.evalAssignmentExpression(e,t);default:throw SyntaxError("Unexpected expression",e)}},evalBinaryExpression:(e,t)=>({"||":(e,t)=>e||t(),"&&":(e,t)=>e&&t(),"|":(e,t)=>e|t(),"^":(e,t)=>e^t(),"&":(e,t)=>e&t(),"==":(e,t)=>e==t(),"!=":(e,t)=>e!=t(),"===":(e,t)=>e===t(),"!==":(e,t)=>e!==t(),"<":(e,t)=>e":(e,t)=>e>t(),"<=":(e,t)=>e<=t(),">=":(e,t)=>e>=t(),"<<":(e,t)=>e<>":(e,t)=>e>>t(),">>>":(e,t)=>e>>>t(),"+":(e,t)=>e+t(),"-":(e,t)=>e-t(),"*":(e,t)=>e*t(),"/":(e,t)=>e/t(),"%":(e,t)=>e%t()}[e.operator](h.evalAst(e.left,t),(()=>h.evalAst(e.right,t)))),evalCompound(e,t){let r;for(let s=0;sh.evalAst(e.test,t)?h.evalAst(e.consequent,t):h.evalAst(e.alternate,t),evalIdentifier(e,t){if(Object.hasOwn(t,e.name))return t[e.name];throw ReferenceError(`${e.name} is not defined`)},evalLiteral:e=>e.value,evalMemberExpression(e,t){const r=String(e.computed?h.evalAst(e.property):e.property.name),s=h.evalAst(e.object,t);if(null==s)throw TypeError(`Cannot read properties of ${s} (reading '${r}')`);if(!Object.hasOwn(s,r)&&a.has(r))throw TypeError(`Cannot read properties of ${s} (reading '${r}')`);const n=s[r];return"function"==typeof n?n.bind(s):n},evalUnaryExpression:(e,t)=>({"-":e=>-h.evalAst(e,t),"!":e=>!h.evalAst(e,t),"~":e=>~h.evalAst(e,t),"+":e=>+h.evalAst(e,t),typeof:e=>typeof h.evalAst(e,t),void:e=>{h.evalAst(e,t)}}[e.operator](e.argument)),evalArrayExpression:(e,t)=>e.elements.map((e=>h.evalAst(e,t))),evalCallExpression(e,t){const r=e.arguments.map((e=>h.evalAst(e,t))),s=h.evalAst(e.callee,t);if(s===Function)throw new Error("Function constructor is disabled");return s(...r)},evalAssignmentExpression(e,t){if("Identifier"!==e.left.type)throw SyntaxError("Invalid left-hand side in assignment");const r=e.left.name,s=h.evalAst(e.right,t);return t[r]=s,t[r]}};function l(e,t){return(e=e.slice()).push(t),e}function c(e,t){return(t=t.slice()).unshift(e),t}class p extends Error{constructor(e){super('JSONPath should not be called with "new" (it prevents return of (unwrapped) scalar values)'),this.avoidNew=!0,this.value=e,this.name="NewError"}}function u(e,t,r,s,n){if(!(this instanceof u))try{return new u(e,t,r,s,n)}catch(e){if(!e.avoidNew)throw e;return e.value}"string"==typeof e&&(n=s,s=r,r=t,t=e,e=null);const i=e&&"object"==typeof e;if(e=e||{},this.json=e.json||r,this.path=e.path||t,this.resultType=e.resultType||"value",this.flatten=e.flatten||!1,this.wrap=!Object.hasOwn(e,"wrap")||e.wrap,this.sandbox=e.sandbox||{},this.eval=void 0===e.eval?"safe":e.eval,this.ignoreEvalErrors=void 0!==e.ignoreEvalErrors&&e.ignoreEvalErrors,this.parent=e.parent||null,this.parentProperty=e.parentProperty||null,this.callback=e.callback||s||null,this.otherTypeCallback=e.otherTypeCallback||n||function(){throw new TypeError("You must supply an otherTypeCallback callback option with the @other() operator.")},!1!==e.autostart){const s={path:i?e.path:t};i?"json"in e&&(s.json=e.json):s.json=r;const n=this.evaluate(s);if(!n||"object"!=typeof n)throw new p(n);return n}}u.prototype.evaluate=function(e,t,r,s){let n=this.parent,i=this.parentProperty,{flatten:o,wrap:a}=this;if(this.currResultType=this.resultType,this.currEval=this.eval,this.currSandbox=this.sandbox,r=r||this.callback,this.currOtherTypeCallback=s||this.otherTypeCallback,t=t||this.json,(e=e||this.path)&&"object"==typeof e&&!Array.isArray(e)){if(!e.path&&""!==e.path)throw new TypeError('You must supply a "path" property when providing an object argument to JSONPath.evaluate().');if(!Object.hasOwn(e,"json"))throw new TypeError('You must supply a "json" property when providing an object argument to JSONPath.evaluate().');({json:t}=e),o=Object.hasOwn(e,"flatten")?e.flatten:o,this.currResultType=Object.hasOwn(e,"resultType")?e.resultType:this.currResultType,this.currSandbox=Object.hasOwn(e,"sandbox")?e.sandbox:this.currSandbox,a=Object.hasOwn(e,"wrap")?e.wrap:a,this.currEval=Object.hasOwn(e,"eval")?e.eval:this.currEval,r=Object.hasOwn(e,"callback")?e.callback:r,this.currOtherTypeCallback=Object.hasOwn(e,"otherTypeCallback")?e.otherTypeCallback:this.currOtherTypeCallback,n=Object.hasOwn(e,"parent")?e.parent:n,i=Object.hasOwn(e,"parentProperty")?e.parentProperty:i,e=e.path}if(n=n||null,i=i||null,Array.isArray(e)&&(e=u.toPathString(e)),!e&&""!==e||!t)return;const h=u.toPathArray(e);"$"===h[0]&&h.length>1&&h.shift(),this._hasParentSelector=null;const l=this._trace(h,t,["$"],n,i,r).filter((function(e){return e&&!e.isParentSelector}));return l.length?a||1!==l.length||l[0].hasArrExpr?l.reduce(((e,t)=>{const r=this._getPreferredOutput(t);return o&&Array.isArray(r)?e=e.concat(r):e.push(r),e}),[]):this._getPreferredOutput(l[0]):a?[]:void 0},u.prototype._getPreferredOutput=function(e){const t=this.currResultType;switch(t){case"all":{const t=Array.isArray(e.path)?e.path:u.toPathArray(e.path);return e.pointer=u.toPointer(t),e.path="string"==typeof e.path?e.path:u.toPathString(e.path),e}case"value":case"parent":case"parentProperty":return e[t];case"path":return u.toPathString(e[t]);case"pointer":return u.toPointer(e.path);default:throw new TypeError("Unknown result type")}},u.prototype._handleCallback=function(e,t,r){if(t){const s=this._getPreferredOutput(e);e.path="string"==typeof e.path?e.path:u.toPathString(e.path),t(s,r,e)}},u.prototype._trace=function(e,t,r,s,n,i,o,a){let h;if(!e.length)return h={path:r,value:t,parent:s,parentProperty:n,hasArrExpr:o},this._handleCallback(h,i,"value"),h;const p=e[0],u=e.slice(1),d=[];function f(e){Array.isArray(e)?e.forEach((e=>{d.push(e)})):d.push(e)}if(("string"!=typeof p||a)&&t&&Object.hasOwn(t,p))f(this._trace(u,t[p],l(r,p),t,p,i,o));else if("*"===p)this._walk(t,(e=>{f(this._trace(u,t[e],l(r,e),t,e,i,!0,!0))}));else if(".."===p)f(this._trace(u,t,r,s,n,i,o)),this._walk(t,(s=>{"object"==typeof t[s]&&f(this._trace(e.slice(),t[s],l(r,s),t,s,i,!0))}));else{if("^"===p)return this._hasParentSelector=!0,{path:r.slice(0,-1),expr:u,isParentSelector:!0};if("~"===p)return h={path:l(r,p),value:n,parent:s,parentProperty:null},this._handleCallback(h,i,"property"),h;if("$"===p)f(this._trace(u,t,r,null,null,i,o));else if(/^(-?\d*):(-?\d*):?(\d*)$/u.test(p))f(this._slice(p,u,t,r,s,n,i));else if(0===p.indexOf("?(")){if(!1===this.currEval)throw new Error("Eval [?(expr)] prevented in JSONPath expression.");const e=p.replace(/^\?\((.*?)\)$/u,"$1"),o=/@.?([^?]*)[['](\??\(.*?\))(?!.\)\])[\]']/gu.exec(e);o?this._walk(t,(e=>{const a=[o[2]],h=o[1]?t[e][o[1]]:t[e];this._trace(a,h,r,s,n,i,!0).length>0&&f(this._trace(u,t[e],l(r,e),t,e,i,!0))})):this._walk(t,(o=>{this._eval(e,t[o],o,r,s,n)&&f(this._trace(u,t[o],l(r,o),t,o,i,!0))}))}else if("("===p[0]){if(!1===this.currEval)throw new Error("Eval [(expr)] prevented in JSONPath expression.");f(this._trace(c(this._eval(p,t,r.at(-1),r.slice(0,-1),s,n),u),t,r,s,n,i,o))}else if("@"===p[0]){let e=!1;const o=p.slice(1,-2);switch(o){case"scalar":t&&["object","function"].includes(typeof t)||(e=!0);break;case"boolean":case"string":case"undefined":case"function":typeof t===o&&(e=!0);break;case"integer":!Number.isFinite(t)||t%1||(e=!0);break;case"number":Number.isFinite(t)&&(e=!0);break;case"nonFinite":"number"!=typeof t||Number.isFinite(t)||(e=!0);break;case"object":t&&typeof t===o&&(e=!0);break;case"array":Array.isArray(t)&&(e=!0);break;case"other":e=this.currOtherTypeCallback(t,r,s,n);break;case"null":null===t&&(e=!0);break;default:throw new TypeError("Unknown value type "+o)}if(e)return h={path:r,value:t,parent:s,parentProperty:n},this._handleCallback(h,i,"value"),h}else if("`"===p[0]&&t&&Object.hasOwn(t,p.slice(1))){const e=p.slice(1);f(this._trace(u,t[e],l(r,e),t,e,i,o,!0))}else if(p.includes(",")){const e=p.split(",");for(const o of e)f(this._trace(c(o,u),t,r,s,n,i,!0))}else!a&&t&&Object.hasOwn(t,p)&&f(this._trace(u,t[p],l(r,p),t,p,i,o,!0))}if(this._hasParentSelector)for(let e=0;e{t(e)}))},u.prototype._slice=function(e,t,r,s,n,i,o){if(!Array.isArray(r))return;const a=r.length,h=e.split(":"),l=h[2]&&Number.parseInt(h[2])||1;let p=h[0]&&Number.parseInt(h[0])||0,u=h[1]&&Number.parseInt(h[1])||a;p=p<0?Math.max(0,p+a):Math.min(a,p),u=u<0?Math.max(0,u+a):Math.min(a,u);const d=[];for(let e=p;e{d.push(e)}))}return d},u.prototype._eval=function(e,t,r,s,n,i){this.currSandbox._$_parentProperty=i,this.currSandbox._$_parent=n,this.currSandbox._$_property=r,this.currSandbox._$_root=this.json,this.currSandbox._$_v=t;const o=e.includes("@path");o&&(this.currSandbox._$_path=u.toPathString(s.concat([r])));const a=this.currEval+"Script:"+e;if(!u.cache[a]){let t=e.replaceAll("@parentProperty","_$_parentProperty").replaceAll("@parent","_$_parent").replaceAll("@property","_$_property").replaceAll("@root","_$_root").replaceAll(/@([.\s)[])/gu,"_$_v$1");if(o&&(t=t.replaceAll("@path","_$_path")),"safe"===this.currEval||!0===this.currEval||void 0===this.currEval)u.cache[a]=new this.safeVm.Script(t);else if("native"===this.currEval)u.cache[a]=new this.vm.Script(t);else if("function"==typeof this.currEval&&this.currEval.prototype&&Object.hasOwn(this.currEval.prototype,"runInNewContext")){const e=this.currEval;u.cache[a]=new e(t)}else{if("function"!=typeof this.currEval)throw new TypeError(`Unknown "eval" property "${this.currEval}"`);u.cache[a]={runInNewContext:e=>this.currEval(t,e)}}}try{return u.cache[a].runInNewContext(this.currSandbox)}catch(t){if(this.ignoreEvalErrors)return!1;throw new Error("jsonPath: "+t.message+": "+e)}},u.cache={},u.toPathString=function(e){const t=e,r=t.length;let s="$";for(let e=1;e"function"==typeof e[t]));const n=r.map((t=>e[t]));t=s.reduce(((t,r)=>{let s=e[r].toString();return/function/u.test(s)||(s="function "+s),"var "+r+"="+s+";"+t}),"")+t,/(['"])use strict\1/u.test(t)||r.includes("arguments")||(t="var arguments = undefined;"+t),t=t.replace(/;\s*$/u,"");const i=t.lastIndexOf(";"),o=-1!==i?t.slice(0,i+1)+" return "+t.slice(i+1):" return "+t;return new Function(...r,o)(...n)}}};export{u as JSONPath};
+class e{static get version(){return"1.4.0"}static toString(){return"JavaScript Expression Parser (JSEP) v"+e.version}static addUnaryOp(t){return e.max_unop_len=Math.max(t.length,e.max_unop_len),e.unary_ops[t]=1,e}static addBinaryOp(t,r,s){return e.max_binop_len=Math.max(t.length,e.max_binop_len),e.binary_ops[t]=r,s?e.right_associative.add(t):e.right_associative.delete(t),e}static addIdentifierChar(t){return e.additional_identifier_chars.add(t),e}static addLiteral(t,r){return e.literals[t]=r,e}static removeUnaryOp(t){return delete e.unary_ops[t],t.length===e.max_unop_len&&(e.max_unop_len=e.getMaxKeyLen(e.unary_ops)),e}static removeAllUnaryOps(){return e.unary_ops={},e.max_unop_len=0,e}static removeIdentifierChar(t){return e.additional_identifier_chars.delete(t),e}static removeBinaryOp(t){return delete e.binary_ops[t],t.length===e.max_binop_len&&(e.max_binop_len=e.getMaxKeyLen(e.binary_ops)),e.right_associative.delete(t),e}static removeAllBinaryOps(){return e.binary_ops={},e.max_binop_len=0,e}static removeLiteral(t){return delete e.literals[t],e}static removeAllLiterals(){return e.literals={},e}get char(){return this.expr.charAt(this.index)}get code(){return this.expr.charCodeAt(this.index)}constructor(e){this.expr=e,this.index=0}static parse(t){return new e(t).parse()}static getMaxKeyLen(e){return Math.max(0,...Object.keys(e).map(e=>e.length))}static isDecimalDigit(e){return e>=48&&e<=57}static binaryPrecedence(t){return e.binary_ops[t]||0}static isIdentifierStart(t){return t>=65&&t<=90||t>=97&&t<=122||t>=128&&!e.binary_ops[String.fromCharCode(t)]||e.additional_identifier_chars.has(String.fromCharCode(t))}static isIdentifierPart(t){return e.isIdentifierStart(t)||e.isDecimalDigit(t)}throwError(e){const t=new Error(e+" at character "+this.index);throw t.index=this.index,t.description=e,t}runHook(t,r){if(e.hooks[t]){const s={context:this,node:r};return e.hooks.run(t,s),s.node}return r}searchHook(t){if(e.hooks[t]){const r={context:this};return e.hooks[t].find(function(e){return e.call(r.context,r),r.node}),r.node}}gobbleSpaces(){let t=this.code;for(;t===e.SPACE_CODE||t===e.TAB_CODE||t===e.LF_CODE||t===e.CR_CODE;)t=this.expr.charCodeAt(++this.index);this.runHook("gobble-spaces")}parse(){this.runHook("before-all");const t=this.gobbleExpressions(),r=1===t.length?t[0]:{type:e.COMPOUND,body:t};return this.runHook("after-all",r)}gobbleExpressions(t){let r,s,n=[];for(;this.index0;){if(e.binary_ops.hasOwnProperty(t)&&(!e.isIdentifierStart(this.code)||this.index+t.lengthi.right_a&&e.right_a?s>e.prec:s<=e.prec;for(;n.length>2&&h(n[n.length-2]);)a=n.pop(),r=n.pop().value,o=n.pop(),t={type:e.BINARY_EXP,operator:r,left:o,right:a},n.push(t);t=this.gobbleToken(),t||this.throwError("Expected expression after "+l),n.push(i,t)}for(h=n.length-1,t=n[h];h>1;)t={type:e.BINARY_EXP,operator:n[h-1].value,left:n[h-2],right:t},h-=2;return t}gobbleToken(){let t,r,s,n;if(this.gobbleSpaces(),n=this.searchHook("gobble-token"),n)return this.runHook("after-token",n);if(t=this.code,e.isDecimalDigit(t)||t===e.PERIOD_CODE)return this.gobbleNumericLiteral();if(t===e.SQUOTE_CODE||t===e.DQUOTE_CODE)n=this.gobbleStringLiteral();else if(t===e.OBRACK_CODE)n=this.gobbleArray();else{for(r=this.expr.substr(this.index,e.max_unop_len),s=r.length;s>0;){if(e.unary_ops.hasOwnProperty(r)&&(!e.isIdentifierStart(this.code)||this.index+r.length=r.length&&this.throwError("Unexpected token "+String.fromCharCode(t));break}if(i===e.COMMA_CODE){if(this.index++,n++,n!==r.length)if(t===e.CPAREN_CODE)this.throwError("Unexpected token ,");else if(t===e.CBRACK_CODE)for(let e=r.length;e{if("object"!=typeof e||!e.name||!e.init)throw new Error("Invalid JSEP plugin format");this.registered[e.name]||(e.init(this.jsep),this.registered[e.name]=e)})}}(e),COMPOUND:"Compound",SEQUENCE_EXP:"SequenceExpression",IDENTIFIER:"Identifier",MEMBER_EXP:"MemberExpression",LITERAL:"Literal",THIS_EXP:"ThisExpression",CALL_EXP:"CallExpression",UNARY_EXP:"UnaryExpression",BINARY_EXP:"BinaryExpression",ARRAY_EXP:"ArrayExpression",TAB_CODE:9,LF_CODE:10,CR_CODE:13,SPACE_CODE:32,PERIOD_CODE:46,COMMA_CODE:44,SQUOTE_CODE:39,DQUOTE_CODE:34,OPAREN_CODE:40,CPAREN_CODE:41,OBRACK_CODE:91,CBRACK_CODE:93,QUMARK_CODE:63,SEMCOL_CODE:59,COLON_CODE:58,unary_ops:{"-":1,"!":1,"~":1,"+":1},binary_ops:{"||":1,"??":1,"&&":2,"|":3,"^":4,"&":5,"==":6,"!=":6,"===":6,"!==":6,"<":7,">":7,"<=":7,">=":7,"<<":8,">>":8,">>>":8,"+":9,"-":9,"*":10,"/":10,"%":10,"**":11},right_associative:new Set(["**"]),additional_identifier_chars:new Set(["$","_"]),literals:{true:!0,false:!1,null:null},this_str:"this"}),e.max_unop_len=e.getMaxKeyLen(e.unary_ops),e.max_binop_len=e.getMaxKeyLen(e.binary_ops);const r=t=>new e(t).parse(),s=Object.getOwnPropertyNames(class{});Object.getOwnPropertyNames(e).filter(e=>!s.includes(e)&&void 0===r[e]).forEach(t=>{r[t]=e[t]}),r.Jsep=e;var n={name:"ternary",init(e){e.hooks.add("after-expression",function(t){if(t.node&&this.code===e.QUMARK_CODE){this.index++;const r=t.node,s=this.gobbleExpression();if(s||this.throwError("Expected expression"),this.gobbleSpaces(),this.code===e.COLON_CODE){this.index++;const n=this.gobbleExpression();if(n||this.throwError("Expected expression"),t.node={type:"ConditionalExpression",test:r,consequent:s,alternate:n},r.operator&&e.binary_ops[r.operator]<=.9){let s=r;for(;s.right.operator&&e.binary_ops[s.right.operator]<=.9;)s=s.right;t.node.test=s.right,s.right=t.node,t.node=r}}else this.throwError("Expected :")}})}};r.plugins.register(n);var i={name:"regex",init(e){e.hooks.add("gobble-token",function(t){if(47===this.code){const r=++this.index;let s=!1;for(;this.index=97&&e<=122||e>=65&&e<=90||e>=48&&e<=57))break;i+=this.char}try{n=new RegExp(s,i)}catch(e){this.throwError(e.message)}return t.node={type:e.LITERAL,value:n,raw:this.expr.slice(r-1,this.index)},t.node=this.gobbleTokenProperty(t.node),t.node}this.code===e.OBRACK_CODE?s=!0:s&&this.code===e.CBRACK_CODE&&(s=!1),this.index+=92===this.code?2:1}this.throwError("Unclosed Regex")}})}};const o={name:"assignment",assignmentOperators:new Set(["=","*=","**=","/=","%=","+=","-=","<<=",">>=",">>>=","&=","^=","|=","||=","&&=","??="]),updateOperators:[43,45],assignmentPrecedence:.9,init(e){const t=[e.IDENTIFIER,e.MEMBER_EXP];function r(e){o.assignmentOperators.has(e.operator)?(e.type="AssignmentExpression",r(e.left),r(e.right)):e.operator||Object.values(e).forEach(e=>{e&&"object"==typeof e&&r(e)})}o.assignmentOperators.forEach(t=>e.addBinaryOp(t,o.assignmentPrecedence,!0)),e.hooks.add("gobble-token",function(e){const r=this.code;o.updateOperators.some(e=>e===r&&e===this.expr.charCodeAt(this.index+1))&&(this.index+=2,e.node={type:"UpdateExpression",operator:43===r?"++":"--",argument:this.gobbleTokenProperty(this.gobbleIdentifier()),prefix:!0},e.node.argument&&t.includes(e.node.argument.type)||this.throwError(`Unexpected ${e.node.operator}`))}),e.hooks.add("after-token",function(e){if(e.node){const r=this.code;o.updateOperators.some(e=>e===r&&e===this.expr.charCodeAt(this.index+1))&&(t.includes(e.node.type)||this.throwError(`Unexpected ${e.node.operator}`),this.index+=2,e.node={type:"UpdateExpression",operator:43===r?"++":"--",argument:e.node,prefix:!1})}}),e.hooks.add("after-expression",function(e){e.node&&r(e.node)})}};r.plugins.register(i,o),r.addUnaryOp("typeof"),r.addUnaryOp("void"),r.addLiteral("null",null),r.addLiteral("undefined",void 0);const a=new Set(["constructor","__proto__","__defineGetter__","__defineSetter__","__lookupGetter__","__lookupSetter__"]),h={evalAst(e,t){switch(e.type){case"BinaryExpression":case"LogicalExpression":return h.evalBinaryExpression(e,t);case"Compound":return h.evalCompound(e,t);case"ConditionalExpression":return h.evalConditionalExpression(e,t);case"Identifier":return h.evalIdentifier(e,t);case"Literal":return h.evalLiteral(e,t);case"MemberExpression":return h.evalMemberExpression(e,t);case"UnaryExpression":return h.evalUnaryExpression(e,t);case"ArrayExpression":return h.evalArrayExpression(e,t);case"CallExpression":return h.evalCallExpression(e,t);case"AssignmentExpression":return h.evalAssignmentExpression(e,t);default:throw SyntaxError("Unexpected expression",e)}},evalBinaryExpression:(e,t)=>({"||":(e,t)=>e||t(),"&&":(e,t)=>e&&t(),"|":(e,t)=>e|t(),"^":(e,t)=>e^t(),"&":(e,t)=>e&t(),"==":(e,t)=>e==t(),"!=":(e,t)=>e!=t(),"===":(e,t)=>e===t(),"!==":(e,t)=>e!==t(),"<":(e,t)=>e":(e,t)=>e>t(),"<=":(e,t)=>e<=t(),">=":(e,t)=>e>=t(),"<<":(e,t)=>e<>":(e,t)=>e>>t(),">>>":(e,t)=>e>>>t(),"+":(e,t)=>e+t(),"-":(e,t)=>e-t(),"*":(e,t)=>e*t(),"/":(e,t)=>e/t(),"%":(e,t)=>e%t()}[e.operator](h.evalAst(e.left,t),()=>h.evalAst(e.right,t))),evalCompound(e,t){let r;for(let s=0;sh.evalAst(e.test,t)?h.evalAst(e.consequent,t):h.evalAst(e.alternate,t),evalIdentifier(e,t){if(Object.hasOwn(t,e.name))return t[e.name];throw ReferenceError(`${e.name} is not defined`)},evalLiteral:e=>e.value,evalMemberExpression(e,t){const r=String(e.computed?h.evalAst(e.property):e.property.name),s=h.evalAst(e.object,t);if(null==s)throw TypeError(`Cannot read properties of ${s} (reading '${r}')`);if(!Object.hasOwn(s,r)&&a.has(r))throw TypeError(`Cannot read properties of ${s} (reading '${r}')`);const n=s[r];return"function"==typeof n?n.bind(s):n},evalUnaryExpression:(e,t)=>({"-":e=>-h.evalAst(e,t),"!":e=>!h.evalAst(e,t),"~":e=>~h.evalAst(e,t),"+":e=>+h.evalAst(e,t),typeof:e=>typeof h.evalAst(e,t),void:e=>{h.evalAst(e,t)}}[e.operator](e.argument)),evalArrayExpression:(e,t)=>e.elements.map(e=>h.evalAst(e,t)),evalCallExpression(e,t){const r=e.arguments.map(e=>h.evalAst(e,t)),s=h.evalAst(e.callee,t);if(s===Function)throw new Error("Function constructor is disabled");return s(...r)},evalAssignmentExpression(e,t){if("Identifier"!==e.left.type)throw SyntaxError("Invalid left-hand side in assignment");const r=e.left.name,s=h.evalAst(e.right,t);return t[r]=s,t[r]}};function l(e,t){return(e=e.slice()).push(t),e}function p(e,t){return(t=t.slice()).unshift(e),t}class c extends Error{constructor(e){super('JSONPath should not be called with "new" (it prevents return of (unwrapped) scalar values)'),this.avoidNew=!0,this.value=e,this.name="NewError"}}function u(e,t,r,s,n){if(!(this instanceof u))try{return new u(e,t,r,s,n)}catch(e){if(!e.avoidNew)throw e;return e.value}"string"==typeof e&&(n=s,s=r,r=t,t=e,e=null);const i=e&&"object"==typeof e;if(e=e||{},this.json=e.json||r,this.path=e.path||t,this.resultType=e.resultType||"value",this.flatten=e.flatten||!1,this.wrap=!Object.hasOwn(e,"wrap")||e.wrap,this.sandbox=e.sandbox||{},this.eval=void 0===e.eval?"safe":e.eval,this.ignoreEvalErrors=void 0!==e.ignoreEvalErrors&&e.ignoreEvalErrors,this.parent=e.parent||null,this.parentProperty=e.parentProperty||null,this.callback=e.callback||s||null,this.otherTypeCallback=e.otherTypeCallback||n||function(){throw new TypeError("You must supply an otherTypeCallback callback option with the @other() operator.")},!1!==e.autostart){const s={path:i?e.path:t};i?"json"in e&&(s.json=e.json):s.json=r;const n=this.evaluate(s);if(!n||"object"!=typeof n)throw new c(n);return n}}u.prototype.evaluate=function(e,t,r,s){let n=this.parent,i=this.parentProperty,{flatten:o,wrap:a}=this;if(this.currResultType=this.resultType,this.currEval=this.eval,this.currSandbox=this.sandbox,r=r||this.callback,this.currOtherTypeCallback=s||this.otherTypeCallback,t=t||this.json,(e=e||this.path)&&"object"==typeof e&&!Array.isArray(e)){if(!e.path&&""!==e.path)throw new TypeError('You must supply a "path" property when providing an object argument to JSONPath.evaluate().');if(!Object.hasOwn(e,"json"))throw new TypeError('You must supply a "json" property when providing an object argument to JSONPath.evaluate().');({json:t}=e),o=Object.hasOwn(e,"flatten")?e.flatten:o,this.currResultType=Object.hasOwn(e,"resultType")?e.resultType:this.currResultType,this.currSandbox=Object.hasOwn(e,"sandbox")?e.sandbox:this.currSandbox,a=Object.hasOwn(e,"wrap")?e.wrap:a,this.currEval=Object.hasOwn(e,"eval")?e.eval:this.currEval,r=Object.hasOwn(e,"callback")?e.callback:r,this.currOtherTypeCallback=Object.hasOwn(e,"otherTypeCallback")?e.otherTypeCallback:this.currOtherTypeCallback,n=Object.hasOwn(e,"parent")?e.parent:n,i=Object.hasOwn(e,"parentProperty")?e.parentProperty:i,e=e.path}if(n=n||null,i=i||null,Array.isArray(e)&&(e=u.toPathString(e)),!e&&""!==e||!t)return;const h=u.toPathParts(e);h[0]&&"root"===h[0].type&&h.length>1&&h.shift(),this._hasParentSelector=null,this._json=t;const l=this._trace(h,t,["$"],n,i,r).filter(function(e){return e&&!e.isParentSelector});return l.length?a||1!==l.length||l[0].hasArrExpr?l.reduce((e,t)=>{const r=this._getPreferredOutput(t);return o&&Array.isArray(r)?e=e.concat(r):e.push(r),e},[]):this._getPreferredOutput(l[0]):a?[]:void 0},u.prototype._getPreferredOutput=function(e){const t=this.currResultType;switch(t){case"all":{const t=Array.isArray(e.path)?e.path:u.toPathParts(e.path);return e.pointer=u.toPointer(t),e.path="string"==typeof e.path?e.path:u.toPathString(e.path),e}case"value":case"parent":case"parentProperty":return e[t];case"path":return u.toPathString(e[t]);case"pointer":return u.toPointer(e.path);default:throw new TypeError("Unknown result type")}},u.prototype._handleCallback=function(e,t,r){if(t){const s=this._getPreferredOutput(e);e.path="string"==typeof e.path?e.path:u.toPathString(e.path),t(s,r,e)}},u.prototype._trace=function(e,t,r,s,n,i,o,a){let h;if(!e.length)return h={path:r,value:t,parent:s,parentProperty:n,hasArrExpr:o},this._handleCallback(h,i,"value"),[h];const c=e[0],d=e.slice(1),f=[];function y(e){Array.isArray(e)?e.forEach(e=>{f.push(e)}):f.push(e)}if("string"==typeof c)t&&Object.hasOwn(t,c)&&y(this._trace(d,t[c],l(r,c),t,c,i,o));else if("number"==typeof c)Array.isArray(t)&&c>=0&&c{y(this._trace(d,t[e],l(r,e),t,e,i,!0,!0))});break;case"descent":y(this._trace(d,t,r,s,n,i,o)),this._walk(t,s=>{"object"==typeof t[s]&&y(this._trace(e.slice(),t[s],l(r,s),t,s,i,!0))});break;case"parent":r.length>1&&(this._hasParentSelector=!0,f.push({path:r.slice(0,-1),expr:d,isParentSelector:!0}));break;case"propertyName":h={path:l(r,"~"),value:n,parent:s,parentProperty:null},this._handleCallback(h,i,"property"),f.push(h);break;case"index":{const e=c.value;(Array.isArray(t)&&e>=0&&e{const p={};for(const[e,s]of o.entries()){const n=s.replace(/^@/u,"$");try{const s=u.toPathParts(n),i=this._trace(s,t[h],l(r,h),t,h,null,!0);p[`_$_jp${e}`]=i.map(e=>e.value)}catch(t){p[`_$_jp${e}`]=[]}}const c={...this.currSandbox};Object.assign(this.currSandbox,p);try{(a?p._$_jp0.length>0:this._eval(e,t[h],h,r,s,n))&&y(this._trace(d,t[h],l(r,h),t,h,i,!0))}finally{this.currSandbox=c}})}else this._walk(t,e=>{this._eval(c.expression,t[e],e,r,s,n)&&y(this._trace(d,t[e],l(r,e),t,e,i,!0))});break;case"dynamic":if(!1===this.currEval)throw new Error("Eval [(expr)] prevented in JSONPath expression.");y(this._trace(p(this._eval(c.expression,t,r.at(-1),r.slice(0,-1),s,n),d),t,r,s,n,i,o));break;case"typeOperator":{let e=!1;const{valueType:o}=c;switch(o){case"scalar":t&&["object","function"].includes(typeof t)||(e=!0);break;case"boolean":case"string":case"undefined":case"function":typeof t===o&&(e=!0);break;case"integer":!Number.isFinite(t)||t%1||(e=!0);break;case"number":Number.isFinite(t)&&(e=!0);break;case"nonFinite":"number"!=typeof t||Number.isFinite(t)||(e=!0);break;case"object":t&&typeof t===o&&(e=!0);break;case"array":Array.isArray(t)&&(e=!0);break;case"other":e=this.currOtherTypeCallback(t,r,s,n);break;case"null":null===t&&(e=!0);break;default:throw new TypeError("Unknown value type "+o)}e&&(h={path:r,value:t,parent:s,parentProperty:n},this._handleCallback(h,i,"value"),f.push(h));break}case"multiProperty":{const e=c.properties,o=c.escaped||[];for(const[a,h]of e.entries()){let e;if("number"==typeof h)e={type:"index",value:h};else{e={type:"property",value:h,escaped:o[a]||!1}}y(this._trace(p(e,d),t,r,s,n,i,!0))}break}}else("string"!=typeof c||a)&&t&&Object.hasOwn(t,c)&&y(this._trace(d,t[c],l(r,c),t,c,i,o));if(this._hasParentSelector)for(let e=0;e{t(e)})},u.prototype._extractNestedFilters=function(e){const t=u.filterExtractionCache;if(t[e])return{expression:t[e].expression,nestedPaths:[...t[e].nestedPaths]};const r=[];let s=e,n=0;function i(e,t){let r=t;for(;r0){const s=e.slice(0,r).trimEnd().slice(-1);if("=([{,;:!&|?".includes(s)||r===t){for(r++;r=e.length)return null;let s=!1,n="@";for(;r0;)if("\\"===e[r]&&r+1=0;e--){const{start:t,end:r,placeholder:n}=a[e];s=s.slice(0,t)+n+s.slice(r)}const h={expression:s,nestedPaths:r};return t[e]=h,{expression:s,nestedPaths:[...r]}},u.prototype._slice=function(e,t,r,s,n,i,o){if(!Array.isArray(r))return;const a=r.length;let h=null===e.start?0:e.start,l=null===e.end?a:e.end;const c=null===e.step?1:e.step;h=h<0?Math.max(0,h+a):Math.min(a,h),l=l<0?Math.max(0,l+a):Math.min(a,l);const u=[];for(let e=h;e{u.push(e)})}return u},u.prototype._eval=function(e,t,r,s,n,i){this.currSandbox._$_parentProperty=i,this.currSandbox._$_parent=n,this.currSandbox._$_property=r,this.currSandbox._$_root=this.json,this.currSandbox._$_v=t;const o=e.includes("@path");o&&(this.currSandbox._$_path=u.toPathString(s.concat([r])));const a=this.currEval+"Script:"+e;if(!u.cache[a]){let t=e.replaceAll("@parentProperty","_$_parentProperty").replaceAll("@parent","_$_parent").replaceAll("@property","_$_property").replaceAll("@root","_$_root").replaceAll(/@([.\s)[])/gu,"_$_v$1");if(o&&(t=t.replaceAll("@path","_$_path")),"safe"===this.currEval||!0===this.currEval||void 0===this.currEval)u.cache[a]=new this.safeVm.Script(t);else if("native"===this.currEval)u.cache[a]=new this.vm.Script(t);else if("function"==typeof this.currEval&&this.currEval.prototype&&Object.hasOwn(this.currEval.prototype,"runInNewContext")){const e=this.currEval;u.cache[a]=new e(t)}else{if("function"!=typeof this.currEval)throw new TypeError(`Unknown "eval" property "${this.currEval}"`);u.cache[a]={runInNewContext:e=>this.currEval(t,e)}}}try{return u.cache[a].runInNewContext(this.currSandbox)}catch(t){if(this.ignoreEvalErrors)return!1;throw new Error("jsonPath: "+t.message+": "+e)}},u.cache={},u.pathPartsCache={},u.filterExtractionCache={},u.toPathString=function(e){const t=e,r=t.length;let s="$";for(let e=1;e"object"==typeof e&&null!==e?{...e}:e);const r=[];let s=0;if(""===e)return r.push(""),t[e]=r,t[e].map(e=>"object"==typeof e&&null!==e?{...e}:e);function n(t,r,s){let n=1,i=t;for(;i0;)e[i]===r?n++:e[i]===s&&n--,i++;if(0!==n)throw new SyntaxError(`Unbalanced ${r}${s} in expression at position ${t}`);return{content:e.slice(t,i-1),end:i}}function i(t,r){let s=t,n="",i=!1;for(;s=e.length)throw new SyntaxError("Unexpected end after dot at position "+(s-1));switch(e[s]){case"*":r.push({type:"wildcard"}),s++;break;case"`":if(s++,s>=e.length)throw new SyntaxError("Unexpected end after backtick at position "+(s-1));r.push({type:"property",value:e[s],escaped:!0}),s++;break;case"[":r.push({type:"descent"});break;default:{let t="";for(;s=e.length)throw new SyntaxError("Unexpected end after [ at position "+(s-1));for(;s=e.length||"("!==e[s+1])throw new SyntaxError("Expected ( after ? at position "+s);s+=2;const t=n(s,"(",")"),{content:i}=t;for(s=t.end;s2&&""!==e[2]?Number.parseInt(e[2]):null;r.push({type:"slice",start:s,end:n,step:i,raw:t})}else{const e=Number.parseInt(t);r.push(e)}return}let o="",a=!1;for(;s=e.length||"("!==e[s]||")"!==e[s+1])throw new SyntaxError("Expected () after @"+t+" at position "+s);s+=2,r.push({type:"typeOperator",valueType:t})}for(e.length>0&&!["$","[",".","^","~","@"].includes(e[0])&&(r.push({type:"root"}),e="."+e);s"object"==typeof e&&null!==e?{...e}:e)},u.prototype.safeVm={Script:class{constructor(e){this.code=e,this.ast=r(this.code)}runInNewContext(e){const t=Object.assign(Object.create(null),e);return h.evalAst(this.ast,t)}}};u.prototype.vm={Script:class{constructor(e){this.code=e}runInNewContext(e){let t=this.code;const r=Object.keys(e),s=[];!function(e,t,r){const s=e.length;for(let n=0;n"function"==typeof e[t]);const n=r.map(t=>e[t]);t=s.reduce((t,r)=>{let s=e[r].toString();return/function/u.test(s)||(s="function "+s),"var "+r+"="+s+";"+t},"")+t,/(['"])use strict\1/u.test(t)||r.includes("arguments")||(t="var arguments = undefined;"+t),t=t.replace(/;\s*$/u,"");const i=t.lastIndexOf(";"),o=-1!==i?t.slice(0,i+1)+" return "+t.slice(i+1):" return "+t;return new Function(...r,o)(...n)}}};export{u as JSONPath};
//# sourceMappingURL=index-browser-esm.min.js.map
diff --git a/dist/index-browser-esm.min.js.map b/dist/index-browser-esm.min.js.map
index 756d602..7dc37b2 100644
--- a/dist/index-browser-esm.min.js.map
+++ b/dist/index-browser-esm.min.js.map
@@ -1 +1 @@
-{"version":3,"file":"index-browser-esm.min.js","sources":["../node_modules/.pnpm/jsep@1.4.0/node_modules/jsep/dist/jsep.js","../node_modules/.pnpm/@jsep-plugin+regex@1.0.4_jsep@1.4.0/node_modules/@jsep-plugin/regex/dist/index.js","../node_modules/.pnpm/@jsep-plugin+assignment@1.3.0_jsep@1.4.0/node_modules/@jsep-plugin/assignment/dist/index.js","../src/Safe-Script.js","../src/jsonpath.js","../src/jsonpath-browser.js"],"sourcesContent":["/**\n * @implements {IHooks}\n */\nclass Hooks {\n\t/**\n\t * @callback HookCallback\n\t * @this {*|Jsep} this\n\t * @param {Jsep} env\n\t * @returns: void\n\t */\n\t/**\n\t * Adds the given callback to the list of callbacks for the given hook.\n\t *\n\t * The callback will be invoked when the hook it is registered for is run.\n\t *\n\t * One callback function can be registered to multiple hooks and the same hook multiple times.\n\t *\n\t * @param {string|object} name The name of the hook, or an object of callbacks keyed by name\n\t * @param {HookCallback|boolean} callback The callback function which is given environment variables.\n\t * @param {?boolean} [first=false] Will add the hook to the top of the list (defaults to the bottom)\n\t * @public\n\t */\n\tadd(name, callback, first) {\n\t\tif (typeof arguments[0] != 'string') {\n\t\t\t// Multiple hook callbacks, keyed by name\n\t\t\tfor (let name in arguments[0]) {\n\t\t\t\tthis.add(name, arguments[0][name], arguments[1]);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\t(Array.isArray(name) ? name : [name]).forEach(function (name) {\n\t\t\t\tthis[name] = this[name] || [];\n\n\t\t\t\tif (callback) {\n\t\t\t\t\tthis[name][first ? 'unshift' : 'push'](callback);\n\t\t\t\t}\n\t\t\t}, this);\n\t\t}\n\t}\n\n\t/**\n\t * Runs a hook invoking all registered callbacks with the given environment variables.\n\t *\n\t * Callbacks will be invoked synchronously and in the order in which they were registered.\n\t *\n\t * @param {string} name The name of the hook.\n\t * @param {Object} env The environment variables of the hook passed to all callbacks registered.\n\t * @public\n\t */\n\trun(name, env) {\n\t\tthis[name] = this[name] || [];\n\t\tthis[name].forEach(function (callback) {\n\t\t\tcallback.call(env && env.context ? env.context : env, env);\n\t\t});\n\t}\n}\n\n/**\n * @implements {IPlugins}\n */\nclass Plugins {\n\tconstructor(jsep) {\n\t\tthis.jsep = jsep;\n\t\tthis.registered = {};\n\t}\n\n\t/**\n\t * @callback PluginSetup\n\t * @this {Jsep} jsep\n\t * @returns: void\n\t */\n\t/**\n\t * Adds the given plugin(s) to the registry\n\t *\n\t * @param {object} plugins\n\t * @param {string} plugins.name The name of the plugin\n\t * @param {PluginSetup} plugins.init The init function\n\t * @public\n\t */\n\tregister(...plugins) {\n\t\tplugins.forEach((plugin) => {\n\t\t\tif (typeof plugin !== 'object' || !plugin.name || !plugin.init) {\n\t\t\t\tthrow new Error('Invalid JSEP plugin format');\n\t\t\t}\n\t\t\tif (this.registered[plugin.name]) {\n\t\t\t\t// already registered. Ignore.\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tplugin.init(this.jsep);\n\t\t\tthis.registered[plugin.name] = plugin;\n\t\t});\n\t}\n}\n\n// JavaScript Expression Parser (JSEP) 1.4.0\n\nclass Jsep {\n\t/**\n\t * @returns {string}\n\t */\n\tstatic get version() {\n\t\t// To be filled in by the template\n\t\treturn '1.4.0';\n\t}\n\n\t/**\n\t * @returns {string}\n\t */\n\tstatic toString() {\n\t\treturn 'JavaScript Expression Parser (JSEP) v' + Jsep.version;\n\t};\n\n\t// ==================== CONFIG ================================\n\t/**\n\t * @method addUnaryOp\n\t * @param {string} op_name The name of the unary op to add\n\t * @returns {Jsep}\n\t */\n\tstatic addUnaryOp(op_name) {\n\t\tJsep.max_unop_len = Math.max(op_name.length, Jsep.max_unop_len);\n\t\tJsep.unary_ops[op_name] = 1;\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method jsep.addBinaryOp\n\t * @param {string} op_name The name of the binary op to add\n\t * @param {number} precedence The precedence of the binary op (can be a float). Higher number = higher precedence\n\t * @param {boolean} [isRightAssociative=false] whether operator is right-associative\n\t * @returns {Jsep}\n\t */\n\tstatic addBinaryOp(op_name, precedence, isRightAssociative) {\n\t\tJsep.max_binop_len = Math.max(op_name.length, Jsep.max_binop_len);\n\t\tJsep.binary_ops[op_name] = precedence;\n\t\tif (isRightAssociative) {\n\t\t\tJsep.right_associative.add(op_name);\n\t\t}\n\t\telse {\n\t\t\tJsep.right_associative.delete(op_name);\n\t\t}\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method addIdentifierChar\n\t * @param {string} char The additional character to treat as a valid part of an identifier\n\t * @returns {Jsep}\n\t */\n\tstatic addIdentifierChar(char) {\n\t\tJsep.additional_identifier_chars.add(char);\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method addLiteral\n\t * @param {string} literal_name The name of the literal to add\n\t * @param {*} literal_value The value of the literal\n\t * @returns {Jsep}\n\t */\n\tstatic addLiteral(literal_name, literal_value) {\n\t\tJsep.literals[literal_name] = literal_value;\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method removeUnaryOp\n\t * @param {string} op_name The name of the unary op to remove\n\t * @returns {Jsep}\n\t */\n\tstatic removeUnaryOp(op_name) {\n\t\tdelete Jsep.unary_ops[op_name];\n\t\tif (op_name.length === Jsep.max_unop_len) {\n\t\t\tJsep.max_unop_len = Jsep.getMaxKeyLen(Jsep.unary_ops);\n\t\t}\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method removeAllUnaryOps\n\t * @returns {Jsep}\n\t */\n\tstatic removeAllUnaryOps() {\n\t\tJsep.unary_ops = {};\n\t\tJsep.max_unop_len = 0;\n\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method removeIdentifierChar\n\t * @param {string} char The additional character to stop treating as a valid part of an identifier\n\t * @returns {Jsep}\n\t */\n\tstatic removeIdentifierChar(char) {\n\t\tJsep.additional_identifier_chars.delete(char);\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method removeBinaryOp\n\t * @param {string} op_name The name of the binary op to remove\n\t * @returns {Jsep}\n\t */\n\tstatic removeBinaryOp(op_name) {\n\t\tdelete Jsep.binary_ops[op_name];\n\n\t\tif (op_name.length === Jsep.max_binop_len) {\n\t\t\tJsep.max_binop_len = Jsep.getMaxKeyLen(Jsep.binary_ops);\n\t\t}\n\t\tJsep.right_associative.delete(op_name);\n\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method removeAllBinaryOps\n\t * @returns {Jsep}\n\t */\n\tstatic removeAllBinaryOps() {\n\t\tJsep.binary_ops = {};\n\t\tJsep.max_binop_len = 0;\n\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method removeLiteral\n\t * @param {string} literal_name The name of the literal to remove\n\t * @returns {Jsep}\n\t */\n\tstatic removeLiteral(literal_name) {\n\t\tdelete Jsep.literals[literal_name];\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method removeAllLiterals\n\t * @returns {Jsep}\n\t */\n\tstatic removeAllLiterals() {\n\t\tJsep.literals = {};\n\n\t\treturn Jsep;\n\t}\n\t// ==================== END CONFIG ============================\n\n\n\t/**\n\t * @returns {string}\n\t */\n\tget char() {\n\t\treturn this.expr.charAt(this.index);\n\t}\n\n\t/**\n\t * @returns {number}\n\t */\n\tget code() {\n\t\treturn this.expr.charCodeAt(this.index);\n\t};\n\n\n\t/**\n\t * @param {string} expr a string with the passed in express\n\t * @returns Jsep\n\t */\n\tconstructor(expr) {\n\t\t// `index` stores the character number we are currently at\n\t\t// All of the gobbles below will modify `index` as we move along\n\t\tthis.expr = expr;\n\t\tthis.index = 0;\n\t}\n\n\t/**\n\t * static top-level parser\n\t * @returns {jsep.Expression}\n\t */\n\tstatic parse(expr) {\n\t\treturn (new Jsep(expr)).parse();\n\t}\n\n\t/**\n\t * Get the longest key length of any object\n\t * @param {object} obj\n\t * @returns {number}\n\t */\n\tstatic getMaxKeyLen(obj) {\n\t\treturn Math.max(0, ...Object.keys(obj).map(k => k.length));\n\t}\n\n\t/**\n\t * `ch` is a character code in the next three functions\n\t * @param {number} ch\n\t * @returns {boolean}\n\t */\n\tstatic isDecimalDigit(ch) {\n\t\treturn (ch >= 48 && ch <= 57); // 0...9\n\t}\n\n\t/**\n\t * Returns the precedence of a binary operator or `0` if it isn't a binary operator. Can be float.\n\t * @param {string} op_val\n\t * @returns {number}\n\t */\n\tstatic binaryPrecedence(op_val) {\n\t\treturn Jsep.binary_ops[op_val] || 0;\n\t}\n\n\t/**\n\t * Looks for start of identifier\n\t * @param {number} ch\n\t * @returns {boolean}\n\t */\n\tstatic isIdentifierStart(ch) {\n\t\treturn (ch >= 65 && ch <= 90) || // A...Z\n\t\t\t(ch >= 97 && ch <= 122) || // a...z\n\t\t\t(ch >= 128 && !Jsep.binary_ops[String.fromCharCode(ch)]) || // any non-ASCII that is not an operator\n\t\t\t(Jsep.additional_identifier_chars.has(String.fromCharCode(ch))); // additional characters\n\t}\n\n\t/**\n\t * @param {number} ch\n\t * @returns {boolean}\n\t */\n\tstatic isIdentifierPart(ch) {\n\t\treturn Jsep.isIdentifierStart(ch) || Jsep.isDecimalDigit(ch);\n\t}\n\n\t/**\n\t * throw error at index of the expression\n\t * @param {string} message\n\t * @throws\n\t */\n\tthrowError(message) {\n\t\tconst error = new Error(message + ' at character ' + this.index);\n\t\terror.index = this.index;\n\t\terror.description = message;\n\t\tthrow error;\n\t}\n\n\t/**\n\t * Run a given hook\n\t * @param {string} name\n\t * @param {jsep.Expression|false} [node]\n\t * @returns {?jsep.Expression}\n\t */\n\trunHook(name, node) {\n\t\tif (Jsep.hooks[name]) {\n\t\t\tconst env = { context: this, node };\n\t\t\tJsep.hooks.run(name, env);\n\t\t\treturn env.node;\n\t\t}\n\t\treturn node;\n\t}\n\n\t/**\n\t * Runs a given hook until one returns a node\n\t * @param {string} name\n\t * @returns {?jsep.Expression}\n\t */\n\tsearchHook(name) {\n\t\tif (Jsep.hooks[name]) {\n\t\t\tconst env = { context: this };\n\t\t\tJsep.hooks[name].find(function (callback) {\n\t\t\t\tcallback.call(env.context, env);\n\t\t\t\treturn env.node;\n\t\t\t});\n\t\t\treturn env.node;\n\t\t}\n\t}\n\n\t/**\n\t * Push `index` up to the next non-space character\n\t */\n\tgobbleSpaces() {\n\t\tlet ch = this.code;\n\t\t// Whitespace\n\t\twhile (ch === Jsep.SPACE_CODE\n\t\t|| ch === Jsep.TAB_CODE\n\t\t|| ch === Jsep.LF_CODE\n\t\t|| ch === Jsep.CR_CODE) {\n\t\t\tch = this.expr.charCodeAt(++this.index);\n\t\t}\n\t\tthis.runHook('gobble-spaces');\n\t}\n\n\t/**\n\t * Top-level method to parse all expressions and returns compound or single node\n\t * @returns {jsep.Expression}\n\t */\n\tparse() {\n\t\tthis.runHook('before-all');\n\t\tconst nodes = this.gobbleExpressions();\n\n\t\t// If there's only one expression just try returning the expression\n\t\tconst node = nodes.length === 1\n\t\t ? nodes[0]\n\t\t\t: {\n\t\t\t\ttype: Jsep.COMPOUND,\n\t\t\t\tbody: nodes\n\t\t\t};\n\t\treturn this.runHook('after-all', node);\n\t}\n\n\t/**\n\t * top-level parser (but can be reused within as well)\n\t * @param {number} [untilICode]\n\t * @returns {jsep.Expression[]}\n\t */\n\tgobbleExpressions(untilICode) {\n\t\tlet nodes = [], ch_i, node;\n\n\t\twhile (this.index < this.expr.length) {\n\t\t\tch_i = this.code;\n\n\t\t\t// Expressions can be separated by semicolons, commas, or just inferred without any\n\t\t\t// separators\n\t\t\tif (ch_i === Jsep.SEMCOL_CODE || ch_i === Jsep.COMMA_CODE) {\n\t\t\t\tthis.index++; // ignore separators\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Try to gobble each expression individually\n\t\t\t\tif (node = this.gobbleExpression()) {\n\t\t\t\t\tnodes.push(node);\n\t\t\t\t\t// If we weren't able to find a binary expression and are out of room, then\n\t\t\t\t\t// the expression passed in probably has too much\n\t\t\t\t}\n\t\t\t\telse if (this.index < this.expr.length) {\n\t\t\t\t\tif (ch_i === untilICode) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tthis.throwError('Unexpected \"' + this.char + '\"');\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn nodes;\n\t}\n\n\t/**\n\t * The main parsing function.\n\t * @returns {?jsep.Expression}\n\t */\n\tgobbleExpression() {\n\t\tconst node = this.searchHook('gobble-expression') || this.gobbleBinaryExpression();\n\t\tthis.gobbleSpaces();\n\n\t\treturn this.runHook('after-expression', node);\n\t}\n\n\t/**\n\t * Search for the operation portion of the string (e.g. `+`, `===`)\n\t * Start by taking the longest possible binary operations (3 characters: `===`, `!==`, `>>>`)\n\t * and move down from 3 to 2 to 1 character until a matching binary operation is found\n\t * then, return that binary operation\n\t * @returns {string|boolean}\n\t */\n\tgobbleBinaryOp() {\n\t\tthis.gobbleSpaces();\n\t\tlet to_check = this.expr.substr(this.index, Jsep.max_binop_len);\n\t\tlet tc_len = to_check.length;\n\n\t\twhile (tc_len > 0) {\n\t\t\t// Don't accept a binary op when it is an identifier.\n\t\t\t// Binary ops that start with a identifier-valid character must be followed\n\t\t\t// by a non identifier-part valid character\n\t\t\tif (Jsep.binary_ops.hasOwnProperty(to_check) && (\n\t\t\t\t!Jsep.isIdentifierStart(this.code) ||\n\t\t\t\t(this.index + to_check.length < this.expr.length && !Jsep.isIdentifierPart(this.expr.charCodeAt(this.index + to_check.length)))\n\t\t\t)) {\n\t\t\t\tthis.index += tc_len;\n\t\t\t\treturn to_check;\n\t\t\t}\n\t\t\tto_check = to_check.substr(0, --tc_len);\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * This function is responsible for gobbling an individual expression,\n\t * e.g. `1`, `1+2`, `a+(b*2)-Math.sqrt(2)`\n\t * @returns {?jsep.BinaryExpression}\n\t */\n\tgobbleBinaryExpression() {\n\t\tlet node, biop, prec, stack, biop_info, left, right, i, cur_biop;\n\n\t\t// First, try to get the leftmost thing\n\t\t// Then, check to see if there's a binary operator operating on that leftmost thing\n\t\t// Don't gobbleBinaryOp without a left-hand-side\n\t\tleft = this.gobbleToken();\n\t\tif (!left) {\n\t\t\treturn left;\n\t\t}\n\t\tbiop = this.gobbleBinaryOp();\n\n\t\t// If there wasn't a binary operator, just return the leftmost node\n\t\tif (!biop) {\n\t\t\treturn left;\n\t\t}\n\n\t\t// Otherwise, we need to start a stack to properly place the binary operations in their\n\t\t// precedence structure\n\t\tbiop_info = { value: biop, prec: Jsep.binaryPrecedence(biop), right_a: Jsep.right_associative.has(biop) };\n\n\t\tright = this.gobbleToken();\n\n\t\tif (!right) {\n\t\t\tthis.throwError(\"Expected expression after \" + biop);\n\t\t}\n\n\t\tstack = [left, biop_info, right];\n\n\t\t// Properly deal with precedence using [recursive descent](http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm)\n\t\twhile ((biop = this.gobbleBinaryOp())) {\n\t\t\tprec = Jsep.binaryPrecedence(biop);\n\n\t\t\tif (prec === 0) {\n\t\t\t\tthis.index -= biop.length;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tbiop_info = { value: biop, prec, right_a: Jsep.right_associative.has(biop) };\n\n\t\t\tcur_biop = biop;\n\n\t\t\t// Reduce: make a binary expression from the three topmost entries.\n\t\t\tconst comparePrev = prev => biop_info.right_a && prev.right_a\n\t\t\t\t? prec > prev.prec\n\t\t\t\t: prec <= prev.prec;\n\t\t\twhile ((stack.length > 2) && comparePrev(stack[stack.length - 2])) {\n\t\t\t\tright = stack.pop();\n\t\t\t\tbiop = stack.pop().value;\n\t\t\t\tleft = stack.pop();\n\t\t\t\tnode = {\n\t\t\t\t\ttype: Jsep.BINARY_EXP,\n\t\t\t\t\toperator: biop,\n\t\t\t\t\tleft,\n\t\t\t\t\tright\n\t\t\t\t};\n\t\t\t\tstack.push(node);\n\t\t\t}\n\n\t\t\tnode = this.gobbleToken();\n\n\t\t\tif (!node) {\n\t\t\t\tthis.throwError(\"Expected expression after \" + cur_biop);\n\t\t\t}\n\n\t\t\tstack.push(biop_info, node);\n\t\t}\n\n\t\ti = stack.length - 1;\n\t\tnode = stack[i];\n\n\t\twhile (i > 1) {\n\t\t\tnode = {\n\t\t\t\ttype: Jsep.BINARY_EXP,\n\t\t\t\toperator: stack[i - 1].value,\n\t\t\t\tleft: stack[i - 2],\n\t\t\t\tright: node\n\t\t\t};\n\t\t\ti -= 2;\n\t\t}\n\n\t\treturn node;\n\t}\n\n\t/**\n\t * An individual part of a binary expression:\n\t * e.g. `foo.bar(baz)`, `1`, `\"abc\"`, `(a % 2)` (because it's in parenthesis)\n\t * @returns {boolean|jsep.Expression}\n\t */\n\tgobbleToken() {\n\t\tlet ch, to_check, tc_len, node;\n\n\t\tthis.gobbleSpaces();\n\t\tnode = this.searchHook('gobble-token');\n\t\tif (node) {\n\t\t\treturn this.runHook('after-token', node);\n\t\t}\n\n\t\tch = this.code;\n\n\t\tif (Jsep.isDecimalDigit(ch) || ch === Jsep.PERIOD_CODE) {\n\t\t\t// Char code 46 is a dot `.` which can start off a numeric literal\n\t\t\treturn this.gobbleNumericLiteral();\n\t\t}\n\n\t\tif (ch === Jsep.SQUOTE_CODE || ch === Jsep.DQUOTE_CODE) {\n\t\t\t// Single or double quotes\n\t\t\tnode = this.gobbleStringLiteral();\n\t\t}\n\t\telse if (ch === Jsep.OBRACK_CODE) {\n\t\t\tnode = this.gobbleArray();\n\t\t}\n\t\telse {\n\t\t\tto_check = this.expr.substr(this.index, Jsep.max_unop_len);\n\t\t\ttc_len = to_check.length;\n\n\t\t\twhile (tc_len > 0) {\n\t\t\t\t// Don't accept an unary op when it is an identifier.\n\t\t\t\t// Unary ops that start with a identifier-valid character must be followed\n\t\t\t\t// by a non identifier-part valid character\n\t\t\t\tif (Jsep.unary_ops.hasOwnProperty(to_check) && (\n\t\t\t\t\t!Jsep.isIdentifierStart(this.code) ||\n\t\t\t\t\t(this.index + to_check.length < this.expr.length && !Jsep.isIdentifierPart(this.expr.charCodeAt(this.index + to_check.length)))\n\t\t\t\t)) {\n\t\t\t\t\tthis.index += tc_len;\n\t\t\t\t\tconst argument = this.gobbleToken();\n\t\t\t\t\tif (!argument) {\n\t\t\t\t\t\tthis.throwError('missing unaryOp argument');\n\t\t\t\t\t}\n\t\t\t\t\treturn this.runHook('after-token', {\n\t\t\t\t\t\ttype: Jsep.UNARY_EXP,\n\t\t\t\t\t\toperator: to_check,\n\t\t\t\t\t\targument,\n\t\t\t\t\t\tprefix: true\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tto_check = to_check.substr(0, --tc_len);\n\t\t\t}\n\n\t\t\tif (Jsep.isIdentifierStart(ch)) {\n\t\t\t\tnode = this.gobbleIdentifier();\n\t\t\t\tif (Jsep.literals.hasOwnProperty(node.name)) {\n\t\t\t\t\tnode = {\n\t\t\t\t\t\ttype: Jsep.LITERAL,\n\t\t\t\t\t\tvalue: Jsep.literals[node.name],\n\t\t\t\t\t\traw: node.name,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\telse if (node.name === Jsep.this_str) {\n\t\t\t\t\tnode = { type: Jsep.THIS_EXP };\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (ch === Jsep.OPAREN_CODE) { // open parenthesis\n\t\t\t\tnode = this.gobbleGroup();\n\t\t\t}\n\t\t}\n\n\t\tif (!node) {\n\t\t\treturn this.runHook('after-token', false);\n\t\t}\n\n\t\tnode = this.gobbleTokenProperty(node);\n\t\treturn this.runHook('after-token', node);\n\t}\n\n\t/**\n\t * Gobble properties of of identifiers/strings/arrays/groups.\n\t * e.g. `foo`, `bar.baz`, `foo['bar'].baz`\n\t * It also gobbles function calls:\n\t * e.g. `Math.acos(obj.angle)`\n\t * @param {jsep.Expression} node\n\t * @returns {jsep.Expression}\n\t */\n\tgobbleTokenProperty(node) {\n\t\tthis.gobbleSpaces();\n\n\t\tlet ch = this.code;\n\t\twhile (ch === Jsep.PERIOD_CODE || ch === Jsep.OBRACK_CODE || ch === Jsep.OPAREN_CODE || ch === Jsep.QUMARK_CODE) {\n\t\t\tlet optional;\n\t\t\tif (ch === Jsep.QUMARK_CODE) {\n\t\t\t\tif (this.expr.charCodeAt(this.index + 1) !== Jsep.PERIOD_CODE) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\toptional = true;\n\t\t\t\tthis.index += 2;\n\t\t\t\tthis.gobbleSpaces();\n\t\t\t\tch = this.code;\n\t\t\t}\n\t\t\tthis.index++;\n\n\t\t\tif (ch === Jsep.OBRACK_CODE) {\n\t\t\t\tnode = {\n\t\t\t\t\ttype: Jsep.MEMBER_EXP,\n\t\t\t\t\tcomputed: true,\n\t\t\t\t\tobject: node,\n\t\t\t\t\tproperty: this.gobbleExpression()\n\t\t\t\t};\n\t\t\t\tif (!node.property) {\n\t\t\t\t\tthis.throwError('Unexpected \"' + this.char + '\"');\n\t\t\t\t}\n\t\t\t\tthis.gobbleSpaces();\n\t\t\t\tch = this.code;\n\t\t\t\tif (ch !== Jsep.CBRACK_CODE) {\n\t\t\t\t\tthis.throwError('Unclosed [');\n\t\t\t\t}\n\t\t\t\tthis.index++;\n\t\t\t}\n\t\t\telse if (ch === Jsep.OPAREN_CODE) {\n\t\t\t\t// A function call is being made; gobble all the arguments\n\t\t\t\tnode = {\n\t\t\t\t\ttype: Jsep.CALL_EXP,\n\t\t\t\t\t'arguments': this.gobbleArguments(Jsep.CPAREN_CODE),\n\t\t\t\t\tcallee: node\n\t\t\t\t};\n\t\t\t}\n\t\t\telse if (ch === Jsep.PERIOD_CODE || optional) {\n\t\t\t\tif (optional) {\n\t\t\t\t\tthis.index--;\n\t\t\t\t}\n\t\t\t\tthis.gobbleSpaces();\n\t\t\t\tnode = {\n\t\t\t\t\ttype: Jsep.MEMBER_EXP,\n\t\t\t\t\tcomputed: false,\n\t\t\t\t\tobject: node,\n\t\t\t\t\tproperty: this.gobbleIdentifier(),\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (optional) {\n\t\t\t\tnode.optional = true;\n\t\t\t} // else leave undefined for compatibility with esprima\n\n\t\t\tthis.gobbleSpaces();\n\t\t\tch = this.code;\n\t\t}\n\n\t\treturn node;\n\t}\n\n\t/**\n\t * Parse simple numeric literals: `12`, `3.4`, `.5`. Do this by using a string to\n\t * keep track of everything in the numeric literal and then calling `parseFloat` on that string\n\t * @returns {jsep.Literal}\n\t */\n\tgobbleNumericLiteral() {\n\t\tlet number = '', ch, chCode;\n\n\t\twhile (Jsep.isDecimalDigit(this.code)) {\n\t\t\tnumber += this.expr.charAt(this.index++);\n\t\t}\n\n\t\tif (this.code === Jsep.PERIOD_CODE) { // can start with a decimal marker\n\t\t\tnumber += this.expr.charAt(this.index++);\n\n\t\t\twhile (Jsep.isDecimalDigit(this.code)) {\n\t\t\t\tnumber += this.expr.charAt(this.index++);\n\t\t\t}\n\t\t}\n\n\t\tch = this.char;\n\n\t\tif (ch === 'e' || ch === 'E') { // exponent marker\n\t\t\tnumber += this.expr.charAt(this.index++);\n\t\t\tch = this.char;\n\n\t\t\tif (ch === '+' || ch === '-') { // exponent sign\n\t\t\t\tnumber += this.expr.charAt(this.index++);\n\t\t\t}\n\n\t\t\twhile (Jsep.isDecimalDigit(this.code)) { // exponent itself\n\t\t\t\tnumber += this.expr.charAt(this.index++);\n\t\t\t}\n\n\t\t\tif (!Jsep.isDecimalDigit(this.expr.charCodeAt(this.index - 1)) ) {\n\t\t\t\tthis.throwError('Expected exponent (' + number + this.char + ')');\n\t\t\t}\n\t\t}\n\n\t\tchCode = this.code;\n\n\t\t// Check to make sure this isn't a variable name that start with a number (123abc)\n\t\tif (Jsep.isIdentifierStart(chCode)) {\n\t\t\tthis.throwError('Variable names cannot start with a number (' +\n\t\t\t\tnumber + this.char + ')');\n\t\t}\n\t\telse if (chCode === Jsep.PERIOD_CODE || (number.length === 1 && number.charCodeAt(0) === Jsep.PERIOD_CODE)) {\n\t\t\tthis.throwError('Unexpected period');\n\t\t}\n\n\t\treturn {\n\t\t\ttype: Jsep.LITERAL,\n\t\t\tvalue: parseFloat(number),\n\t\t\traw: number\n\t\t};\n\t}\n\n\t/**\n\t * Parses a string literal, staring with single or double quotes with basic support for escape codes\n\t * e.g. `\"hello world\"`, `'this is\\nJSEP'`\n\t * @returns {jsep.Literal}\n\t */\n\tgobbleStringLiteral() {\n\t\tlet str = '';\n\t\tconst startIndex = this.index;\n\t\tconst quote = this.expr.charAt(this.index++);\n\t\tlet closed = false;\n\n\t\twhile (this.index < this.expr.length) {\n\t\t\tlet ch = this.expr.charAt(this.index++);\n\n\t\t\tif (ch === quote) {\n\t\t\t\tclosed = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\telse if (ch === '\\\\') {\n\t\t\t\t// Check for all of the common escape codes\n\t\t\t\tch = this.expr.charAt(this.index++);\n\n\t\t\t\tswitch (ch) {\n\t\t\t\t\tcase 'n': str += '\\n'; break;\n\t\t\t\t\tcase 'r': str += '\\r'; break;\n\t\t\t\t\tcase 't': str += '\\t'; break;\n\t\t\t\t\tcase 'b': str += '\\b'; break;\n\t\t\t\t\tcase 'f': str += '\\f'; break;\n\t\t\t\t\tcase 'v': str += '\\x0B'; break;\n\t\t\t\t\tdefault : str += ch;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tstr += ch;\n\t\t\t}\n\t\t}\n\n\t\tif (!closed) {\n\t\t\tthis.throwError('Unclosed quote after \"' + str + '\"');\n\t\t}\n\n\t\treturn {\n\t\t\ttype: Jsep.LITERAL,\n\t\t\tvalue: str,\n\t\t\traw: this.expr.substring(startIndex, this.index),\n\t\t};\n\t}\n\n\t/**\n\t * Gobbles only identifiers\n\t * e.g.: `foo`, `_value`, `$x1`\n\t * Also, this function checks if that identifier is a literal:\n\t * (e.g. `true`, `false`, `null`) or `this`\n\t * @returns {jsep.Identifier}\n\t */\n\tgobbleIdentifier() {\n\t\tlet ch = this.code, start = this.index;\n\n\t\tif (Jsep.isIdentifierStart(ch)) {\n\t\t\tthis.index++;\n\t\t}\n\t\telse {\n\t\t\tthis.throwError('Unexpected ' + this.char);\n\t\t}\n\n\t\twhile (this.index < this.expr.length) {\n\t\t\tch = this.code;\n\n\t\t\tif (Jsep.isIdentifierPart(ch)) {\n\t\t\t\tthis.index++;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\ttype: Jsep.IDENTIFIER,\n\t\t\tname: this.expr.slice(start, this.index),\n\t\t};\n\t}\n\n\t/**\n\t * Gobbles a list of arguments within the context of a function call\n\t * or array literal. This function also assumes that the opening character\n\t * `(` or `[` has already been gobbled, and gobbles expressions and commas\n\t * until the terminator character `)` or `]` is encountered.\n\t * e.g. `foo(bar, baz)`, `my_func()`, or `[bar, baz]`\n\t * @param {number} termination\n\t * @returns {jsep.Expression[]}\n\t */\n\tgobbleArguments(termination) {\n\t\tconst args = [];\n\t\tlet closed = false;\n\t\tlet separator_count = 0;\n\n\t\twhile (this.index < this.expr.length) {\n\t\t\tthis.gobbleSpaces();\n\t\t\tlet ch_i = this.code;\n\n\t\t\tif (ch_i === termination) { // done parsing\n\t\t\t\tclosed = true;\n\t\t\t\tthis.index++;\n\n\t\t\t\tif (termination === Jsep.CPAREN_CODE && separator_count && separator_count >= args.length){\n\t\t\t\t\tthis.throwError('Unexpected token ' + String.fromCharCode(termination));\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\telse if (ch_i === Jsep.COMMA_CODE) { // between expressions\n\t\t\t\tthis.index++;\n\t\t\t\tseparator_count++;\n\n\t\t\t\tif (separator_count !== args.length) { // missing argument\n\t\t\t\t\tif (termination === Jsep.CPAREN_CODE) {\n\t\t\t\t\t\tthis.throwError('Unexpected token ,');\n\t\t\t\t\t}\n\t\t\t\t\telse if (termination === Jsep.CBRACK_CODE) {\n\t\t\t\t\t\tfor (let arg = args.length; arg < separator_count; arg++) {\n\t\t\t\t\t\t\targs.push(null);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (args.length !== separator_count && separator_count !== 0) {\n\t\t\t\t// NOTE: `&& separator_count !== 0` allows for either all commas, or all spaces as arguments\n\t\t\t\tthis.throwError('Expected comma');\n\t\t\t}\n\t\t\telse {\n\t\t\t\tconst node = this.gobbleExpression();\n\n\t\t\t\tif (!node || node.type === Jsep.COMPOUND) {\n\t\t\t\t\tthis.throwError('Expected comma');\n\t\t\t\t}\n\n\t\t\t\targs.push(node);\n\t\t\t}\n\t\t}\n\n\t\tif (!closed) {\n\t\t\tthis.throwError('Expected ' + String.fromCharCode(termination));\n\t\t}\n\n\t\treturn args;\n\t}\n\n\t/**\n\t * Responsible for parsing a group of things within parentheses `()`\n\t * that have no identifier in front (so not a function call)\n\t * This function assumes that it needs to gobble the opening parenthesis\n\t * and then tries to gobble everything within that parenthesis, assuming\n\t * that the next thing it should see is the close parenthesis. If not,\n\t * then the expression probably doesn't have a `)`\n\t * @returns {boolean|jsep.Expression}\n\t */\n\tgobbleGroup() {\n\t\tthis.index++;\n\t\tlet nodes = this.gobbleExpressions(Jsep.CPAREN_CODE);\n\t\tif (this.code === Jsep.CPAREN_CODE) {\n\t\t\tthis.index++;\n\t\t\tif (nodes.length === 1) {\n\t\t\t\treturn nodes[0];\n\t\t\t}\n\t\t\telse if (!nodes.length) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn {\n\t\t\t\t\ttype: Jsep.SEQUENCE_EXP,\n\t\t\t\t\texpressions: nodes,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tthis.throwError('Unclosed (');\n\t\t}\n\t}\n\n\t/**\n\t * Responsible for parsing Array literals `[1, 2, 3]`\n\t * This function assumes that it needs to gobble the opening bracket\n\t * and then tries to gobble the expressions as arguments.\n\t * @returns {jsep.ArrayExpression}\n\t */\n\tgobbleArray() {\n\t\tthis.index++;\n\n\t\treturn {\n\t\t\ttype: Jsep.ARRAY_EXP,\n\t\t\telements: this.gobbleArguments(Jsep.CBRACK_CODE)\n\t\t};\n\t}\n}\n\n// Static fields:\nconst hooks = new Hooks();\nObject.assign(Jsep, {\n\thooks,\n\tplugins: new Plugins(Jsep),\n\n\t// Node Types\n\t// ----------\n\t// This is the full set of types that any JSEP node can be.\n\t// Store them here to save space when minified\n\tCOMPOUND: 'Compound',\n\tSEQUENCE_EXP: 'SequenceExpression',\n\tIDENTIFIER: 'Identifier',\n\tMEMBER_EXP: 'MemberExpression',\n\tLITERAL: 'Literal',\n\tTHIS_EXP: 'ThisExpression',\n\tCALL_EXP: 'CallExpression',\n\tUNARY_EXP: 'UnaryExpression',\n\tBINARY_EXP: 'BinaryExpression',\n\tARRAY_EXP: 'ArrayExpression',\n\n\tTAB_CODE: 9,\n\tLF_CODE: 10,\n\tCR_CODE: 13,\n\tSPACE_CODE: 32,\n\tPERIOD_CODE: 46, // '.'\n\tCOMMA_CODE: 44, // ','\n\tSQUOTE_CODE: 39, // single quote\n\tDQUOTE_CODE: 34, // double quotes\n\tOPAREN_CODE: 40, // (\n\tCPAREN_CODE: 41, // )\n\tOBRACK_CODE: 91, // [\n\tCBRACK_CODE: 93, // ]\n\tQUMARK_CODE: 63, // ?\n\tSEMCOL_CODE: 59, // ;\n\tCOLON_CODE: 58, // :\n\n\n\t// Operations\n\t// ----------\n\t// Use a quickly-accessible map to store all of the unary operators\n\t// Values are set to `1` (it really doesn't matter)\n\tunary_ops: {\n\t\t'-': 1,\n\t\t'!': 1,\n\t\t'~': 1,\n\t\t'+': 1\n\t},\n\n\t// Also use a map for the binary operations but set their values to their\n\t// binary precedence for quick reference (higher number = higher precedence)\n\t// see [Order of operations](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence)\n\tbinary_ops: {\n\t\t'||': 1, '??': 1,\n\t\t'&&': 2, '|': 3, '^': 4, '&': 5,\n\t\t'==': 6, '!=': 6, '===': 6, '!==': 6,\n\t\t'<': 7, '>': 7, '<=': 7, '>=': 7,\n\t\t'<<': 8, '>>': 8, '>>>': 8,\n\t\t'+': 9, '-': 9,\n\t\t'*': 10, '/': 10, '%': 10,\n\t\t'**': 11,\n\t},\n\n\t// sets specific binary_ops as right-associative\n\tright_associative: new Set(['**']),\n\n\t// Additional valid identifier chars, apart from a-z, A-Z and 0-9 (except on the starting char)\n\tadditional_identifier_chars: new Set(['$', '_']),\n\n\t// Literals\n\t// ----------\n\t// Store the values to return for the various literals we may encounter\n\tliterals: {\n\t\t'true': true,\n\t\t'false': false,\n\t\t'null': null\n\t},\n\n\t// Except for `this`, which is special. This could be changed to something like `'self'` as well\n\tthis_str: 'this',\n});\nJsep.max_unop_len = Jsep.getMaxKeyLen(Jsep.unary_ops);\nJsep.max_binop_len = Jsep.getMaxKeyLen(Jsep.binary_ops);\n\n// Backward Compatibility:\nconst jsep = expr => (new Jsep(expr)).parse();\nconst stdClassProps = Object.getOwnPropertyNames(class Test{});\nObject.getOwnPropertyNames(Jsep)\n\t.filter(prop => !stdClassProps.includes(prop) && jsep[prop] === undefined)\n\t.forEach((m) => {\n\t\tjsep[m] = Jsep[m];\n\t});\njsep.Jsep = Jsep; // allows for const { Jsep } = require('jsep');\n\nconst CONDITIONAL_EXP = 'ConditionalExpression';\n\nvar ternary = {\n\tname: 'ternary',\n\n\tinit(jsep) {\n\t\t// Ternary expression: test ? consequent : alternate\n\t\tjsep.hooks.add('after-expression', function gobbleTernary(env) {\n\t\t\tif (env.node && this.code === jsep.QUMARK_CODE) {\n\t\t\t\tthis.index++;\n\t\t\t\tconst test = env.node;\n\t\t\t\tconst consequent = this.gobbleExpression();\n\n\t\t\t\tif (!consequent) {\n\t\t\t\t\tthis.throwError('Expected expression');\n\t\t\t\t}\n\n\t\t\t\tthis.gobbleSpaces();\n\n\t\t\t\tif (this.code === jsep.COLON_CODE) {\n\t\t\t\t\tthis.index++;\n\t\t\t\t\tconst alternate = this.gobbleExpression();\n\n\t\t\t\t\tif (!alternate) {\n\t\t\t\t\t\tthis.throwError('Expected expression');\n\t\t\t\t\t}\n\t\t\t\t\tenv.node = {\n\t\t\t\t\t\ttype: CONDITIONAL_EXP,\n\t\t\t\t\t\ttest,\n\t\t\t\t\t\tconsequent,\n\t\t\t\t\t\talternate,\n\t\t\t\t\t};\n\n\t\t\t\t\t// check for operators of higher priority than ternary (i.e. assignment)\n\t\t\t\t\t// jsep sets || at 1, and assignment at 0.9, and conditional should be between them\n\t\t\t\t\tif (test.operator && jsep.binary_ops[test.operator] <= 0.9) {\n\t\t\t\t\t\tlet newTest = test;\n\t\t\t\t\t\twhile (newTest.right.operator && jsep.binary_ops[newTest.right.operator] <= 0.9) {\n\t\t\t\t\t\t\tnewTest = newTest.right;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tenv.node.test = newTest.right;\n\t\t\t\t\t\tnewTest.right = env.node;\n\t\t\t\t\t\tenv.node = test;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis.throwError('Expected :');\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n};\n\n// Add default plugins:\n\njsep.plugins.register(ternary);\n\nexport { Jsep, jsep as default };\n","const FSLASH_CODE = 47; // '/'\nconst BSLASH_CODE = 92; // '\\\\'\n\nvar index = {\n\tname: 'regex',\n\n\tinit(jsep) {\n\t\t// Regex literal: /abc123/ig\n\t\tjsep.hooks.add('gobble-token', function gobbleRegexLiteral(env) {\n\t\t\tif (this.code === FSLASH_CODE) {\n\t\t\t\tconst patternIndex = ++this.index;\n\n\t\t\t\tlet inCharSet = false;\n\t\t\t\twhile (this.index < this.expr.length) {\n\t\t\t\t\tif (this.code === FSLASH_CODE && !inCharSet) {\n\t\t\t\t\t\tconst pattern = this.expr.slice(patternIndex, this.index);\n\n\t\t\t\t\t\tlet flags = '';\n\t\t\t\t\t\twhile (++this.index < this.expr.length) {\n\t\t\t\t\t\t\tconst code = this.code;\n\t\t\t\t\t\t\tif ((code >= 97 && code <= 122) // a...z\n\t\t\t\t\t\t\t\t|| (code >= 65 && code <= 90) // A...Z\n\t\t\t\t\t\t\t\t|| (code >= 48 && code <= 57)) { // 0-9\n\t\t\t\t\t\t\t\tflags += this.char;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tlet value;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tvalue = new RegExp(pattern, flags);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch (e) {\n\t\t\t\t\t\t\tthis.throwError(e.message);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tenv.node = {\n\t\t\t\t\t\t\ttype: jsep.LITERAL,\n\t\t\t\t\t\t\tvalue,\n\t\t\t\t\t\t\traw: this.expr.slice(patternIndex - 1, this.index),\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\t// allow . [] and () after regex: /regex/.test(a)\n\t\t\t\t\t\tenv.node = this.gobbleTokenProperty(env.node);\n\t\t\t\t\t\treturn env.node;\n\t\t\t\t\t}\n\t\t\t\t\tif (this.code === jsep.OBRACK_CODE) {\n\t\t\t\t\t\tinCharSet = true;\n\t\t\t\t\t}\n\t\t\t\t\telse if (inCharSet && this.code === jsep.CBRACK_CODE) {\n\t\t\t\t\t\tinCharSet = false;\n\t\t\t\t\t}\n\t\t\t\t\tthis.index += this.code === BSLASH_CODE ? 2 : 1;\n\t\t\t\t}\n\t\t\t\tthis.throwError('Unclosed Regex');\n\t\t\t}\n\t\t});\n\t},\n};\n\nexport { index as default };\n","const PLUS_CODE = 43; // +\nconst MINUS_CODE = 45; // -\n\nconst plugin = {\n\tname: 'assignment',\n\n\tassignmentOperators: new Set([\n\t\t'=',\n\t\t'*=',\n\t\t'**=',\n\t\t'/=',\n\t\t'%=',\n\t\t'+=',\n\t\t'-=',\n\t\t'<<=',\n\t\t'>>=',\n\t\t'>>>=',\n\t\t'&=',\n\t\t'^=',\n\t\t'|=',\n\t\t'||=',\n\t\t'&&=',\n\t\t'??=',\n\t]),\n\tupdateOperators: [PLUS_CODE, MINUS_CODE],\n\tassignmentPrecedence: 0.9,\n\n\tinit(jsep) {\n\t\tconst updateNodeTypes = [jsep.IDENTIFIER, jsep.MEMBER_EXP];\n\t\tplugin.assignmentOperators.forEach(op => jsep.addBinaryOp(op, plugin.assignmentPrecedence, true));\n\n\t\tjsep.hooks.add('gobble-token', function gobbleUpdatePrefix(env) {\n\t\t\tconst code = this.code;\n\t\t\tif (plugin.updateOperators.some(c => c === code && c === this.expr.charCodeAt(this.index + 1))) {\n\t\t\t\tthis.index += 2;\n\t\t\t\tenv.node = {\n\t\t\t\t\ttype: 'UpdateExpression',\n\t\t\t\t\toperator: code === PLUS_CODE ? '++' : '--',\n\t\t\t\t\targument: this.gobbleTokenProperty(this.gobbleIdentifier()),\n\t\t\t\t\tprefix: true,\n\t\t\t\t};\n\t\t\t\tif (!env.node.argument || !updateNodeTypes.includes(env.node.argument.type)) {\n\t\t\t\t\tthis.throwError(`Unexpected ${env.node.operator}`);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tjsep.hooks.add('after-token', function gobbleUpdatePostfix(env) {\n\t\t\tif (env.node) {\n\t\t\t\tconst code = this.code;\n\t\t\t\tif (plugin.updateOperators.some(c => c === code && c === this.expr.charCodeAt(this.index + 1))) {\n\t\t\t\t\tif (!updateNodeTypes.includes(env.node.type)) {\n\t\t\t\t\t\tthis.throwError(`Unexpected ${env.node.operator}`);\n\t\t\t\t\t}\n\t\t\t\t\tthis.index += 2;\n\t\t\t\t\tenv.node = {\n\t\t\t\t\t\ttype: 'UpdateExpression',\n\t\t\t\t\t\toperator: code === PLUS_CODE ? '++' : '--',\n\t\t\t\t\t\targument: env.node,\n\t\t\t\t\t\tprefix: false,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tjsep.hooks.add('after-expression', function gobbleAssignment(env) {\n\t\t\tif (env.node) {\n\t\t\t\t// Note: Binaries can be chained in a single expression to respect\n\t\t\t\t// operator precedence (i.e. a = b = 1 + 2 + 3)\n\t\t\t\t// Update all binary assignment nodes in the tree\n\t\t\t\tupdateBinariesToAssignments(env.node);\n\t\t\t}\n\t\t});\n\n\t\tfunction updateBinariesToAssignments(node) {\n\t\t\tif (plugin.assignmentOperators.has(node.operator)) {\n\t\t\t\tnode.type = 'AssignmentExpression';\n\t\t\t\tupdateBinariesToAssignments(node.left);\n\t\t\t\tupdateBinariesToAssignments(node.right);\n\t\t\t}\n\t\t\telse if (!node.operator) {\n\t\t\t\tObject.values(node).forEach((val) => {\n\t\t\t\t\tif (val && typeof val === 'object') {\n\t\t\t\t\t\tupdateBinariesToAssignments(val);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t},\n};\n\nexport { plugin as default };\n","/* eslint-disable no-bitwise -- Convenient */\nimport jsep from 'jsep';\nimport jsepRegex from '@jsep-plugin/regex';\nimport jsepAssignment from '@jsep-plugin/assignment';\n\n// register plugins\njsep.plugins.register(jsepRegex, jsepAssignment);\njsep.addUnaryOp('typeof');\njsep.addUnaryOp('void');\njsep.addLiteral('null', null);\njsep.addLiteral('undefined', undefined);\n\nconst BLOCKED_PROTO_PROPERTIES = new Set([\n 'constructor',\n '__proto__',\n '__defineGetter__',\n '__defineSetter__',\n '__lookupGetter__',\n '__lookupSetter__'\n]);\n\nconst SafeEval = {\n /**\n * @param {jsep.Expression} ast\n * @param {Record} subs\n */\n evalAst (ast, subs) {\n switch (ast.type) {\n case 'BinaryExpression':\n case 'LogicalExpression':\n return SafeEval.evalBinaryExpression(ast, subs);\n case 'Compound':\n return SafeEval.evalCompound(ast, subs);\n case 'ConditionalExpression':\n return SafeEval.evalConditionalExpression(ast, subs);\n case 'Identifier':\n return SafeEval.evalIdentifier(ast, subs);\n case 'Literal':\n return SafeEval.evalLiteral(ast, subs);\n case 'MemberExpression':\n return SafeEval.evalMemberExpression(ast, subs);\n case 'UnaryExpression':\n return SafeEval.evalUnaryExpression(ast, subs);\n case 'ArrayExpression':\n return SafeEval.evalArrayExpression(ast, subs);\n case 'CallExpression':\n return SafeEval.evalCallExpression(ast, subs);\n case 'AssignmentExpression':\n return SafeEval.evalAssignmentExpression(ast, subs);\n default:\n throw SyntaxError('Unexpected expression', ast);\n }\n },\n evalBinaryExpression (ast, subs) {\n const result = {\n '||': (a, b) => a || b(),\n '&&': (a, b) => a && b(),\n '|': (a, b) => a | b(),\n '^': (a, b) => a ^ b(),\n '&': (a, b) => a & b(),\n // eslint-disable-next-line eqeqeq -- API\n '==': (a, b) => a == b(),\n // eslint-disable-next-line eqeqeq -- API\n '!=': (a, b) => a != b(),\n '===': (a, b) => a === b(),\n '!==': (a, b) => a !== b(),\n '<': (a, b) => a < b(),\n '>': (a, b) => a > b(),\n '<=': (a, b) => a <= b(),\n '>=': (a, b) => a >= b(),\n '<<': (a, b) => a << b(),\n '>>': (a, b) => a >> b(),\n '>>>': (a, b) => a >>> b(),\n '+': (a, b) => a + b(),\n '-': (a, b) => a - b(),\n '*': (a, b) => a * b(),\n '/': (a, b) => a / b(),\n '%': (a, b) => a % b()\n }[ast.operator](\n SafeEval.evalAst(ast.left, subs),\n () => SafeEval.evalAst(ast.right, subs)\n );\n return result;\n },\n evalCompound (ast, subs) {\n let last;\n for (let i = 0; i < ast.body.length; i++) {\n if (\n ast.body[i].type === 'Identifier' &&\n ['var', 'let', 'const'].includes(ast.body[i].name) &&\n ast.body[i + 1] &&\n ast.body[i + 1].type === 'AssignmentExpression'\n ) {\n // var x=2; is detected as\n // [{Identifier var}, {AssignmentExpression x=2}]\n // eslint-disable-next-line @stylistic/max-len -- Long\n // eslint-disable-next-line sonarjs/updated-loop-counter -- Convenient\n i += 1;\n }\n const expr = ast.body[i];\n last = SafeEval.evalAst(expr, subs);\n }\n return last;\n },\n evalConditionalExpression (ast, subs) {\n if (SafeEval.evalAst(ast.test, subs)) {\n return SafeEval.evalAst(ast.consequent, subs);\n }\n return SafeEval.evalAst(ast.alternate, subs);\n },\n evalIdentifier (ast, subs) {\n if (Object.hasOwn(subs, ast.name)) {\n return subs[ast.name];\n }\n throw ReferenceError(`${ast.name} is not defined`);\n },\n evalLiteral (ast) {\n return ast.value;\n },\n evalMemberExpression (ast, subs) {\n const prop = String(\n // NOTE: `String(value)` throws error when\n // value has overwritten the toString method to return non-string\n // i.e. `value = {toString: () => []}`\n ast.computed\n ? SafeEval.evalAst(ast.property) // `object[property]`\n : ast.property.name // `object.property` property is Identifier\n );\n const obj = SafeEval.evalAst(ast.object, subs);\n if (obj === undefined || obj === null) {\n throw TypeError(\n `Cannot read properties of ${obj} (reading '${prop}')`\n );\n }\n if (!Object.hasOwn(obj, prop) && BLOCKED_PROTO_PROPERTIES.has(prop)) {\n throw TypeError(\n `Cannot read properties of ${obj} (reading '${prop}')`\n );\n }\n const result = obj[prop];\n if (typeof result === 'function') {\n return result.bind(obj); // arrow functions aren't affected by bind.\n }\n return result;\n },\n evalUnaryExpression (ast, subs) {\n const result = {\n '-': (a) => -SafeEval.evalAst(a, subs),\n '!': (a) => !SafeEval.evalAst(a, subs),\n '~': (a) => ~SafeEval.evalAst(a, subs),\n // eslint-disable-next-line no-implicit-coercion -- API\n '+': (a) => +SafeEval.evalAst(a, subs),\n typeof: (a) => typeof SafeEval.evalAst(a, subs),\n // eslint-disable-next-line no-void, sonarjs/void-use -- feature\n void: (a) => void SafeEval.evalAst(a, subs)\n }[ast.operator](ast.argument);\n return result;\n },\n evalArrayExpression (ast, subs) {\n return ast.elements.map((el) => SafeEval.evalAst(el, subs));\n },\n evalCallExpression (ast, subs) {\n const args = ast.arguments.map((arg) => SafeEval.evalAst(arg, subs));\n const func = SafeEval.evalAst(ast.callee, subs);\n /* c8 ignore start */\n if (func === Function) {\n // unreachable since BLOCKED_PROTO_PROPERTIES includes 'constructor'\n throw new Error('Function constructor is disabled');\n }\n /* c8 ignore end */\n return func(...args);\n },\n evalAssignmentExpression (ast, subs) {\n if (ast.left.type !== 'Identifier') {\n throw SyntaxError('Invalid left-hand side in assignment');\n }\n const id = ast.left.name;\n const value = SafeEval.evalAst(ast.right, subs);\n subs[id] = value;\n return subs[id];\n }\n};\n\n/**\n * A replacement for NodeJS' VM.Script which is also {@link https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP | Content Security Policy} friendly.\n */\nclass SafeScript {\n /**\n * @param {string} expr Expression to evaluate\n */\n constructor (expr) {\n this.code = expr;\n this.ast = jsep(this.code);\n }\n\n /**\n * @param {object} context Object whose items will be added\n * to evaluation\n * @returns {EvaluatedResult} Result of evaluated code\n */\n runInNewContext (context) {\n // `Object.create(null)` creates a prototypeless object\n const keyMap = Object.assign(Object.create(null), context);\n return SafeEval.evalAst(this.ast, keyMap);\n }\n}\n\nexport {SafeScript};\n","/* eslint-disable camelcase -- Convenient for escaping */\n\nimport {SafeScript} from './Safe-Script.js';\n\n/**\n * @typedef {null|boolean|number|string|object|GenericArray} JSONObject\n */\n\n/**\n * @typedef {any} AnyItem\n */\n\n/**\n * @typedef {any} AnyResult\n */\n\n/**\n * Copies array and then pushes item into it.\n * @param {GenericArray} arr Array to copy and into which to push\n * @param {AnyItem} item Array item to add (to end)\n * @returns {GenericArray} Copy of the original array\n */\nfunction push (arr, item) {\n arr = arr.slice();\n arr.push(item);\n return arr;\n}\n/**\n * Copies array and then unshifts item into it.\n * @param {AnyItem} item Array item to add (to beginning)\n * @param {GenericArray} arr Array to copy and into which to unshift\n * @returns {GenericArray} Copy of the original array\n */\nfunction unshift (item, arr) {\n arr = arr.slice();\n arr.unshift(item);\n return arr;\n}\n\n/**\n * Caught when JSONPath is used without `new` but rethrown if with `new`\n * @extends Error\n */\nclass NewError extends Error {\n /**\n * @param {AnyResult} value The evaluated scalar value\n */\n constructor (value) {\n super(\n 'JSONPath should not be called with \"new\" (it prevents return ' +\n 'of (unwrapped) scalar values)'\n );\n this.avoidNew = true;\n this.value = value;\n this.name = 'NewError';\n }\n}\n\n/**\n* @typedef {object} ReturnObject\n* @property {string} path\n* @property {JSONObject} value\n* @property {object|GenericArray} parent\n* @property {string} parentProperty\n*/\n\n/**\n* @callback JSONPathCallback\n* @param {string|object} preferredOutput\n* @param {\"value\"|\"property\"} type\n* @param {ReturnObject} fullRetObj\n* @returns {void}\n*/\n\n/**\n* @callback OtherTypeCallback\n* @param {JSONObject} val\n* @param {string} path\n* @param {object|GenericArray} parent\n* @param {string} parentPropName\n* @returns {boolean}\n*/\n\n/**\n * @typedef {any} ContextItem\n */\n\n/**\n * @typedef {any} EvaluatedResult\n */\n\n/**\n* @callback EvalCallback\n* @param {string} code\n* @param {ContextItem} context\n* @returns {EvaluatedResult}\n*/\n\n/**\n * @typedef {typeof SafeScript} EvalClass\n */\n\n/**\n * @typedef {object} JSONPathOptions\n * @property {JSON} json\n * @property {string|string[]} path\n * @property {\"value\"|\"path\"|\"pointer\"|\"parent\"|\"parentProperty\"|\n * \"all\"} [resultType=\"value\"]\n * @property {boolean} [flatten=false]\n * @property {boolean} [wrap=true]\n * @property {object} [sandbox={}]\n * @property {EvalCallback|EvalClass|'safe'|'native'|\n * boolean} [eval = 'safe']\n * @property {object|GenericArray|null} [parent=null]\n * @property {string|null} [parentProperty=null]\n * @property {JSONPathCallback} [callback]\n * @property {OtherTypeCallback} [otherTypeCallback] Defaults to\n * function which throws on encountering `@other`\n * @property {boolean} [autostart=true]\n */\n\n/**\n * @param {string|JSONPathOptions} opts If a string, will be treated as `expr`\n * @param {string} [expr] JSON path to evaluate\n * @param {JSON} [obj] JSON object to evaluate against\n * @param {JSONPathCallback} [callback] Passed 3 arguments: 1) desired payload\n * per `resultType`, 2) `\"value\"|\"property\"`, 3) Full returned object with\n * all payloads\n * @param {OtherTypeCallback} [otherTypeCallback] If `@other()` is at the end\n * of one's query, this will be invoked with the value of the item, its\n * path, its parent, and its parent's property name, and it should return\n * a boolean indicating whether the supplied value belongs to the \"other\"\n * type or not (or it may handle transformations and return `false`).\n * @returns {JSONPath}\n * @class\n */\nfunction JSONPath (opts, expr, obj, callback, otherTypeCallback) {\n // eslint-disable-next-line no-restricted-syntax -- Allow for pseudo-class\n if (!(this instanceof JSONPath)) {\n try {\n return new JSONPath(opts, expr, obj, callback, otherTypeCallback);\n } catch (e) {\n if (!e.avoidNew) {\n throw e;\n }\n return e.value;\n }\n }\n\n if (typeof opts === 'string') {\n otherTypeCallback = callback;\n callback = obj;\n obj = expr;\n expr = opts;\n opts = null;\n }\n const optObj = opts && typeof opts === 'object';\n opts = opts || {};\n this.json = opts.json || obj;\n this.path = opts.path || expr;\n this.resultType = opts.resultType || 'value';\n this.flatten = opts.flatten || false;\n this.wrap = Object.hasOwn(opts, 'wrap') ? opts.wrap : true;\n this.sandbox = opts.sandbox || {};\n this.eval = opts.eval === undefined ? 'safe' : opts.eval;\n this.ignoreEvalErrors = (typeof opts.ignoreEvalErrors === 'undefined')\n ? false\n : opts.ignoreEvalErrors;\n this.parent = opts.parent || null;\n this.parentProperty = opts.parentProperty || null;\n this.callback = opts.callback || callback || null;\n this.otherTypeCallback = opts.otherTypeCallback ||\n otherTypeCallback ||\n function () {\n throw new TypeError(\n 'You must supply an otherTypeCallback callback option ' +\n 'with the @other() operator.'\n );\n };\n\n if (opts.autostart !== false) {\n const args = {\n path: (optObj ? opts.path : expr)\n };\n if (!optObj) {\n args.json = obj;\n } else if ('json' in opts) {\n args.json = opts.json;\n }\n const ret = this.evaluate(args);\n if (!ret || typeof ret !== 'object') {\n throw new NewError(ret);\n }\n return ret;\n }\n}\n\n// PUBLIC METHODS\nJSONPath.prototype.evaluate = function (\n expr, json, callback, otherTypeCallback\n) {\n let currParent = this.parent,\n currParentProperty = this.parentProperty;\n let {flatten, wrap} = this;\n\n this.currResultType = this.resultType;\n this.currEval = this.eval;\n this.currSandbox = this.sandbox;\n callback = callback || this.callback;\n this.currOtherTypeCallback = otherTypeCallback || this.otherTypeCallback;\n\n json = json || this.json;\n expr = expr || this.path;\n if (expr && typeof expr === 'object' && !Array.isArray(expr)) {\n if (!expr.path && expr.path !== '') {\n throw new TypeError(\n 'You must supply a \"path\" property when providing an object ' +\n 'argument to JSONPath.evaluate().'\n );\n }\n if (!(Object.hasOwn(expr, 'json'))) {\n throw new TypeError(\n 'You must supply a \"json\" property when providing an object ' +\n 'argument to JSONPath.evaluate().'\n );\n }\n ({json} = expr);\n flatten = Object.hasOwn(expr, 'flatten') ? expr.flatten : flatten;\n this.currResultType = Object.hasOwn(expr, 'resultType')\n ? expr.resultType\n : this.currResultType;\n this.currSandbox = Object.hasOwn(expr, 'sandbox')\n ? expr.sandbox\n : this.currSandbox;\n wrap = Object.hasOwn(expr, 'wrap') ? expr.wrap : wrap;\n this.currEval = Object.hasOwn(expr, 'eval')\n ? expr.eval\n : this.currEval;\n callback = Object.hasOwn(expr, 'callback') ? expr.callback : callback;\n this.currOtherTypeCallback = Object.hasOwn(expr, 'otherTypeCallback')\n ? expr.otherTypeCallback\n : this.currOtherTypeCallback;\n currParent = Object.hasOwn(expr, 'parent') ? expr.parent : currParent;\n currParentProperty = Object.hasOwn(expr, 'parentProperty')\n ? expr.parentProperty\n : currParentProperty;\n expr = expr.path;\n }\n currParent = currParent || null;\n currParentProperty = currParentProperty || null;\n\n if (Array.isArray(expr)) {\n expr = JSONPath.toPathString(expr);\n }\n if ((!expr && expr !== '') || !json) {\n return undefined;\n }\n\n const exprList = JSONPath.toPathArray(expr);\n if (exprList[0] === '$' && exprList.length > 1) {\n exprList.shift();\n }\n this._hasParentSelector = null;\n const result = this\n ._trace(\n exprList, json, ['$'], currParent, currParentProperty, callback\n )\n .filter(function (ea) {\n return ea && !ea.isParentSelector;\n });\n\n if (!result.length) {\n return wrap ? [] : undefined;\n }\n if (!wrap && result.length === 1 && !result[0].hasArrExpr) {\n return this._getPreferredOutput(result[0]);\n }\n return result.reduce((rslt, ea) => {\n const valOrPath = this._getPreferredOutput(ea);\n if (flatten && Array.isArray(valOrPath)) {\n rslt = rslt.concat(valOrPath);\n } else {\n rslt.push(valOrPath);\n }\n return rslt;\n }, []);\n};\n\n// PRIVATE METHODS\n\nJSONPath.prototype._getPreferredOutput = function (ea) {\n const resultType = this.currResultType;\n switch (resultType) {\n case 'all': {\n const path = Array.isArray(ea.path)\n ? ea.path\n : JSONPath.toPathArray(ea.path);\n ea.pointer = JSONPath.toPointer(path);\n ea.path = typeof ea.path === 'string'\n ? ea.path\n : JSONPath.toPathString(ea.path);\n return ea;\n } case 'value': case 'parent': case 'parentProperty':\n return ea[resultType];\n case 'path':\n return JSONPath.toPathString(ea[resultType]);\n case 'pointer':\n return JSONPath.toPointer(ea.path);\n default:\n throw new TypeError('Unknown result type');\n }\n};\n\nJSONPath.prototype._handleCallback = function (fullRetObj, callback, type) {\n if (callback) {\n const preferredOutput = this._getPreferredOutput(fullRetObj);\n fullRetObj.path = typeof fullRetObj.path === 'string'\n ? fullRetObj.path\n : JSONPath.toPathString(fullRetObj.path);\n // eslint-disable-next-line n/callback-return -- No need to return\n callback(preferredOutput, type, fullRetObj);\n }\n};\n\n/**\n *\n * @param {string} expr\n * @param {JSONObject} val\n * @param {string} path\n * @param {object|GenericArray} parent\n * @param {string} parentPropName\n * @param {JSONPathCallback} callback\n * @param {boolean} hasArrExpr\n * @param {boolean} literalPriority\n * @returns {ReturnObject|ReturnObject[]}\n */\nJSONPath.prototype._trace = function (\n expr, val, path, parent, parentPropName, callback, hasArrExpr,\n literalPriority\n) {\n // No expr to follow? return path and value as the result of\n // this trace branch\n let retObj;\n if (!expr.length) {\n retObj = {\n path,\n value: val,\n parent,\n parentProperty: parentPropName,\n hasArrExpr\n };\n this._handleCallback(retObj, callback, 'value');\n return retObj;\n }\n\n const loc = expr[0], x = expr.slice(1);\n\n // We need to gather the return value of recursive trace calls in order to\n // do the parent sel computation.\n const ret = [];\n /**\n *\n * @param {ReturnObject|ReturnObject[]} elems\n * @returns {void}\n */\n function addRet (elems) {\n if (Array.isArray(elems)) {\n // This was causing excessive stack size in Node (with or\n // without Babel) against our performance test:\n // `ret.push(...elems);`\n elems.forEach((t) => {\n ret.push(t);\n });\n } else {\n ret.push(elems);\n }\n }\n if ((typeof loc !== 'string' || literalPriority) && val &&\n Object.hasOwn(val, loc)\n ) { // simple case--directly follow property\n addRet(this._trace(x, val[loc], push(path, loc), val, loc, callback,\n hasArrExpr));\n // eslint-disable-next-line unicorn/prefer-switch -- Part of larger `if`\n } else if (loc === '*') { // all child properties\n this._walk(val, (m) => {\n addRet(this._trace(\n x, val[m], push(path, m), val, m, callback, true, true\n ));\n });\n } else if (loc === '..') { // all descendent parent properties\n // Check remaining expression with val's immediate children\n addRet(\n this._trace(x, val, path, parent, parentPropName, callback,\n hasArrExpr)\n );\n this._walk(val, (m) => {\n // We don't join m and x here because we only want parents,\n // not scalar values\n if (typeof val[m] === 'object') {\n // Keep going with recursive descent on val's\n // object children\n addRet(this._trace(\n expr.slice(), val[m], push(path, m), val, m, callback, true\n ));\n }\n });\n // The parent sel computation is handled in the frame above using the\n // ancestor object of val\n } else if (loc === '^') {\n // This is not a final endpoint, so we do not invoke the callback here\n this._hasParentSelector = true;\n return {\n path: path.slice(0, -1),\n expr: x,\n isParentSelector: true\n };\n } else if (loc === '~') { // property name\n retObj = {\n path: push(path, loc),\n value: parentPropName,\n parent,\n parentProperty: null\n };\n this._handleCallback(retObj, callback, 'property');\n return retObj;\n } else if (loc === '$') { // root only\n addRet(this._trace(x, val, path, null, null, callback, hasArrExpr));\n } else if ((/^(-?\\d*):(-?\\d*):?(\\d*)$/u).test(loc)) { // [start:end:step] Python slice syntax\n addRet(\n this._slice(loc, x, val, path, parent, parentPropName, callback)\n );\n } else if (loc.indexOf('?(') === 0) { // [?(expr)] (filtering)\n if (this.currEval === false) {\n throw new Error('Eval [?(expr)] prevented in JSONPath expression.');\n }\n const safeLoc = loc.replace(/^\\?\\((.*?)\\)$/u, '$1');\n // check for a nested filter expression\n const nested = (/@.?([^?]*)[['](\\??\\(.*?\\))(?!.\\)\\])[\\]']/gu).exec(safeLoc);\n if (nested) {\n // find if there are matches in the nested expression\n // add them to the result set if there is at least one match\n this._walk(val, (m) => {\n const npath = [nested[2]];\n const nvalue = nested[1]\n ? val[m][nested[1]]\n : val[m];\n const filterResults = this._trace(npath, nvalue, path,\n parent, parentPropName, callback, true);\n if (filterResults.length > 0) {\n addRet(this._trace(x, val[m], push(path, m), val,\n m, callback, true));\n }\n });\n } else {\n this._walk(val, (m) => {\n if (this._eval(safeLoc, val[m], m, path, parent,\n parentPropName)) {\n addRet(this._trace(x, val[m], push(path, m), val, m,\n callback, true));\n }\n });\n }\n } else if (loc[0] === '(') { // [(expr)] (dynamic property/index)\n if (this.currEval === false) {\n throw new Error('Eval [(expr)] prevented in JSONPath expression.');\n }\n // As this will resolve to a property name (but we don't know it\n // yet), property and parent information is relative to the\n // parent of the property to which this expression will resolve\n addRet(this._trace(unshift(\n this._eval(\n loc, val, path.at(-1),\n path.slice(0, -1), parent, parentPropName\n ),\n x\n ), val, path, parent, parentPropName, callback, hasArrExpr));\n } else if (loc[0] === '@') { // value type: @boolean(), etc.\n let addType = false;\n const valueType = loc.slice(1, -2);\n switch (valueType) {\n case 'scalar':\n if (!val || !(['object', 'function'].includes(typeof val))) {\n addType = true;\n }\n break;\n case 'boolean': case 'string': case 'undefined': case 'function':\n if (typeof val === valueType) {\n addType = true;\n }\n break;\n case 'integer':\n if (Number.isFinite(val) && !(val % 1)) {\n addType = true;\n }\n break;\n case 'number':\n if (Number.isFinite(val)) {\n addType = true;\n }\n break;\n case 'nonFinite':\n if (typeof val === 'number' && !Number.isFinite(val)) {\n addType = true;\n }\n break;\n case 'object':\n if (val && typeof val === valueType) {\n addType = true;\n }\n break;\n case 'array':\n if (Array.isArray(val)) {\n addType = true;\n }\n break;\n case 'other':\n addType = this.currOtherTypeCallback(\n val, path, parent, parentPropName\n );\n break;\n case 'null':\n if (val === null) {\n addType = true;\n }\n break;\n /* c8 ignore next 2 */\n default:\n throw new TypeError('Unknown value type ' + valueType);\n }\n if (addType) {\n retObj = {path, value: val, parent, parentProperty: parentPropName};\n this._handleCallback(retObj, callback, 'value');\n return retObj;\n }\n // `-escaped property\n } else if (loc[0] === '`' && val && Object.hasOwn(val, loc.slice(1))) {\n const locProp = loc.slice(1);\n addRet(this._trace(\n x, val[locProp], push(path, locProp), val, locProp, callback,\n hasArrExpr, true\n ));\n } else if (loc.includes(',')) { // [name1,name2,...]\n const parts = loc.split(',');\n for (const part of parts) {\n addRet(this._trace(\n unshift(part, x), val, path, parent, parentPropName, callback,\n true\n ));\n }\n // simple case--directly follow property\n } else if (\n !literalPriority && val && Object.hasOwn(val, loc)\n ) {\n addRet(\n this._trace(x, val[loc], push(path, loc), val, loc, callback,\n hasArrExpr, true)\n );\n }\n\n // We check the resulting values for parent selections. For parent\n // selections we discard the value object and continue the trace with the\n // current val object\n if (this._hasParentSelector) {\n for (let t = 0; t < ret.length; t++) {\n const rett = ret[t];\n if (rett && rett.isParentSelector) {\n const tmp = this._trace(\n rett.expr, val, rett.path, parent, parentPropName, callback,\n hasArrExpr\n );\n if (Array.isArray(tmp)) {\n ret[t] = tmp[0];\n const tl = tmp.length;\n for (let tt = 1; tt < tl; tt++) {\n // eslint-disable-next-line @stylistic/max-len -- Long\n // eslint-disable-next-line sonarjs/updated-loop-counter -- Convenient\n t++;\n ret.splice(t, 0, tmp[tt]);\n }\n } else {\n ret[t] = tmp;\n }\n }\n }\n }\n return ret;\n};\n\nJSONPath.prototype._walk = function (val, f) {\n if (Array.isArray(val)) {\n const n = val.length;\n for (let i = 0; i < n; i++) {\n f(i);\n }\n } else if (val && typeof val === 'object') {\n Object.keys(val).forEach((m) => {\n f(m);\n });\n }\n};\n\nJSONPath.prototype._slice = function (\n loc, expr, val, path, parent, parentPropName, callback\n) {\n if (!Array.isArray(val)) {\n return undefined;\n }\n const len = val.length, parts = loc.split(':'),\n step = (parts[2] && Number.parseInt(parts[2])) || 1;\n let start = (parts[0] && Number.parseInt(parts[0])) || 0,\n end = (parts[1] && Number.parseInt(parts[1])) || len;\n start = (start < 0) ? Math.max(0, start + len) : Math.min(len, start);\n end = (end < 0) ? Math.max(0, end + len) : Math.min(len, end);\n const ret = [];\n for (let i = start; i < end; i += step) {\n const tmp = this._trace(\n unshift(i, expr), val, path, parent, parentPropName, callback, true\n );\n // Should only be possible to be an array here since first part of\n // ``unshift(i, expr)` passed in above would not be empty, nor `~`,\n // nor begin with `@` (as could return objects)\n // This was causing excessive stack size in Node (with or\n // without Babel) against our performance test: `ret.push(...tmp);`\n tmp.forEach((t) => {\n ret.push(t);\n });\n }\n return ret;\n};\n\nJSONPath.prototype._eval = function (\n code, _v, _vname, path, parent, parentPropName\n) {\n this.currSandbox._$_parentProperty = parentPropName;\n this.currSandbox._$_parent = parent;\n this.currSandbox._$_property = _vname;\n this.currSandbox._$_root = this.json;\n this.currSandbox._$_v = _v;\n\n const containsPath = code.includes('@path');\n if (containsPath) {\n this.currSandbox._$_path = JSONPath.toPathString(path.concat([_vname]));\n }\n\n const scriptCacheKey = this.currEval + 'Script:' + code;\n if (!JSONPath.cache[scriptCacheKey]) {\n let script = code\n .replaceAll('@parentProperty', '_$_parentProperty')\n .replaceAll('@parent', '_$_parent')\n .replaceAll('@property', '_$_property')\n .replaceAll('@root', '_$_root')\n .replaceAll(/@([.\\s)[])/gu, '_$_v$1');\n if (containsPath) {\n script = script.replaceAll('@path', '_$_path');\n }\n if (\n this.currEval === 'safe' ||\n this.currEval === true ||\n this.currEval === undefined\n ) {\n JSONPath.cache[scriptCacheKey] = new this.safeVm.Script(script);\n } else if (this.currEval === 'native') {\n JSONPath.cache[scriptCacheKey] = new this.vm.Script(script);\n } else if (\n typeof this.currEval === 'function' &&\n this.currEval.prototype &&\n Object.hasOwn(this.currEval.prototype, 'runInNewContext')\n ) {\n const CurrEval = this.currEval;\n JSONPath.cache[scriptCacheKey] = new CurrEval(script);\n } else if (typeof this.currEval === 'function') {\n JSONPath.cache[scriptCacheKey] = {\n runInNewContext: (context) => this.currEval(script, context)\n };\n } else {\n throw new TypeError(`Unknown \"eval\" property \"${this.currEval}\"`);\n }\n }\n\n try {\n return JSONPath.cache[scriptCacheKey].runInNewContext(this.currSandbox);\n } catch (e) {\n if (this.ignoreEvalErrors) {\n return false;\n }\n throw new Error('jsonPath: ' + e.message + ': ' + code);\n }\n};\n\n// PUBLIC CLASS PROPERTIES AND METHODS\n\n// Could store the cache object itself\nJSONPath.cache = {};\n\n/**\n * @param {string[]} pathArr Array to convert\n * @returns {string} The path string\n */\nJSONPath.toPathString = function (pathArr) {\n const x = pathArr, n = x.length;\n let p = '$';\n for (let i = 1; i < n; i++) {\n if (!(/^(~|\\^|@.*?\\(\\))$/u).test(x[i])) {\n p += (/^[0-9*]+$/u).test(x[i]) ? ('[' + x[i] + ']') : (\"['\" + x[i] + \"']\");\n }\n }\n return p;\n};\n\n/**\n * @param {string} pointer JSON Path\n * @returns {string} JSON Pointer\n */\nJSONPath.toPointer = function (pointer) {\n const x = pointer, n = x.length;\n let p = '';\n for (let i = 1; i < n; i++) {\n if (!(/^(~|\\^|@.*?\\(\\))$/u).test(x[i])) {\n p += '/' + x[i].toString()\n .replaceAll('~', '~0')\n .replaceAll('/', '~1');\n }\n }\n return p;\n};\n\n/**\n * @param {string} expr Expression to convert\n * @returns {string[]}\n */\nJSONPath.toPathArray = function (expr) {\n const {cache} = JSONPath;\n if (cache[expr]) {\n return cache[expr].concat();\n }\n const subx = [];\n const normalized = expr\n // Properties\n .replaceAll(\n /@(?:null|boolean|number|string|integer|undefined|nonFinite|scalar|array|object|function|other)\\(\\)/gu,\n ';$&;'\n )\n // Parenthetical evaluations (filtering and otherwise), directly\n // within brackets or single quotes\n .replaceAll(/[['](\\??\\(.*?\\))[\\]'](?!.\\])/gu, function ($0, $1) {\n return '[#' + (subx.push($1) - 1) + ']';\n })\n // Escape periods and tildes within properties\n .replaceAll(/\\[['\"]([^'\\]]*)['\"]\\]/gu, function ($0, prop) {\n return \"['\" + prop\n .replaceAll('.', '%@%')\n .replaceAll('~', '%%@@%%') +\n \"']\";\n })\n // Properties operator\n .replaceAll('~', ';~;')\n // Split by property boundaries\n .replaceAll(/['\"]?\\.['\"]?(?![^[]*\\])|\\[['\"]?/gu, ';')\n // Reinsert periods within properties\n .replaceAll('%@%', '.')\n // Reinsert tildes within properties\n .replaceAll('%%@@%%', '~')\n // Parent\n .replaceAll(/(?:;)?(\\^+)(?:;)?/gu, function ($0, ups) {\n return ';' + ups.split('').join(';') + ';';\n })\n // Descendents\n .replaceAll(/;;;|;;/gu, ';..;')\n // Remove trailing\n .replaceAll(/;$|'?\\]|'$/gu, '');\n\n const exprList = normalized.split(';').map(function (exp) {\n const match = exp.match(/#(\\d+)/u);\n return !match || !match[1] ? exp : subx[match[1]];\n });\n cache[expr] = exprList;\n return cache[expr].concat();\n};\n\nJSONPath.prototype.safeVm = {\n Script: SafeScript\n};\n\nexport {JSONPath};\n","import {JSONPath} from './jsonpath.js';\n\n/**\n * @typedef {any} ContextItem\n */\n\n/**\n * @typedef {any} EvaluatedResult\n */\n\n/**\n * @callback ConditionCallback\n * @param {ContextItem} item\n * @returns {boolean}\n */\n\n/**\n * Copy items out of one array into another.\n * @param {GenericArray} source Array with items to copy\n * @param {GenericArray} target Array to which to copy\n * @param {ConditionCallback} conditionCb Callback passed the current item;\n * will move item if evaluates to `true`\n * @returns {void}\n */\nconst moveToAnotherArray = function (source, target, conditionCb) {\n const il = source.length;\n for (let i = 0; i < il; i++) {\n const item = source[i];\n if (conditionCb(item)) {\n // eslint-disable-next-line @stylistic/max-len -- Long\n // eslint-disable-next-line sonarjs/updated-loop-counter -- Convenient\n target.push(source.splice(i--, 1)[0]);\n }\n }\n};\n\n/**\n * In-browser replacement for NodeJS' VM.Script.\n */\nclass Script {\n /**\n * @param {string} expr Expression to evaluate\n */\n constructor (expr) {\n this.code = expr;\n }\n\n /**\n * @param {object} context Object whose items will be added\n * to evaluation\n * @returns {EvaluatedResult} Result of evaluated code\n */\n runInNewContext (context) {\n let expr = this.code;\n const keys = Object.keys(context);\n const funcs = [];\n moveToAnotherArray(keys, funcs, (key) => {\n return typeof context[key] === 'function';\n });\n const values = keys.map((vr) => {\n return context[vr];\n });\n\n const funcString = funcs.reduce((s, func) => {\n let fString = context[func].toString();\n if (!(/function/u).test(fString)) {\n fString = 'function ' + fString;\n }\n return 'var ' + func + '=' + fString + ';' + s;\n }, '');\n\n expr = funcString + expr;\n\n // Mitigate http://perfectionkills.com/global-eval-what-are-the-options/#new_function\n if (!(/(['\"])use strict\\1/u).test(expr) && !keys.includes('arguments')) {\n expr = 'var arguments = undefined;' + expr;\n }\n\n // Remove last semi so `return` will be inserted before\n // the previous one instead, allowing for the return\n // of a bare ending expression\n expr = expr.replace(/;\\s*$/u, '');\n\n // Insert `return`\n const lastStatementEnd = expr.lastIndexOf(';');\n const code =\n lastStatementEnd !== -1\n ? expr.slice(0, lastStatementEnd + 1) +\n ' return ' +\n expr.slice(lastStatementEnd + 1)\n : ' return ' + expr;\n\n // eslint-disable-next-line no-new-func -- User's choice\n return new Function(...keys, code)(...values);\n }\n}\n\nJSONPath.prototype.vm = {\n Script\n};\n\nexport {JSONPath};\n"],"names":["Jsep","version","toString","addUnaryOp","op_name","max_unop_len","Math","max","length","unary_ops","addBinaryOp","precedence","isRightAssociative","max_binop_len","binary_ops","right_associative","add","delete","addIdentifierChar","char","additional_identifier_chars","addLiteral","literal_name","literal_value","literals","removeUnaryOp","getMaxKeyLen","removeAllUnaryOps","removeIdentifierChar","removeBinaryOp","removeAllBinaryOps","removeLiteral","removeAllLiterals","this","expr","charAt","index","code","charCodeAt","constructor","parse","obj","Object","keys","map","k","isDecimalDigit","ch","binaryPrecedence","op_val","isIdentifierStart","String","fromCharCode","has","isIdentifierPart","throwError","message","error","Error","description","runHook","name","node","hooks","env","context","run","searchHook","find","callback","call","gobbleSpaces","SPACE_CODE","TAB_CODE","LF_CODE","CR_CODE","nodes","gobbleExpressions","type","COMPOUND","body","untilICode","ch_i","SEMCOL_CODE","COMMA_CODE","gobbleExpression","push","gobbleBinaryExpression","gobbleBinaryOp","to_check","substr","tc_len","hasOwnProperty","biop","prec","stack","biop_info","left","right","i","cur_biop","gobbleToken","value","right_a","comparePrev","prev","pop","BINARY_EXP","operator","PERIOD_CODE","gobbleNumericLiteral","SQUOTE_CODE","DQUOTE_CODE","gobbleStringLiteral","OBRACK_CODE","gobbleArray","argument","UNARY_EXP","prefix","gobbleIdentifier","LITERAL","raw","this_str","THIS_EXP","OPAREN_CODE","gobbleGroup","gobbleTokenProperty","QUMARK_CODE","optional","MEMBER_EXP","computed","object","property","CBRACK_CODE","CALL_EXP","arguments","gobbleArguments","CPAREN_CODE","callee","chCode","number","parseFloat","str","startIndex","quote","closed","substring","start","IDENTIFIER","slice","termination","args","separator_count","arg","SEQUENCE_EXP","expressions","ARRAY_EXP","elements","first","Array","isArray","forEach","assign","plugins","jsep","registered","register","_len","_key","plugin","init","COLON_CODE","Set","true","false","null","stdClassProps","getOwnPropertyNames","filter","prop","includes","undefined","m","ternary","test","consequent","alternate","newTest","patternIndex","inCharSet","pattern","flags","RegExp","e","assignmentOperators","updateOperators","assignmentPrecedence","updateNodeTypes","updateBinariesToAssignments","values","val","op","some","c","jsepRegex","jsepAssignment","BLOCKED_PROTO_PROPERTIES","SafeEval","evalAst","ast","subs","evalBinaryExpression","evalCompound","evalConditionalExpression","evalIdentifier","evalLiteral","evalMemberExpression","evalUnaryExpression","evalArrayExpression","evalCallExpression","evalAssignmentExpression","SyntaxError","||","a","b","&&","|","^","&","==","!=","===","!==","<",">","<=",">=","<<",">>",">>>","+","-","*","/","%","last","hasOwn","ReferenceError","TypeError","result","bind","typeof","void","el","func","Function","id","arr","item","unshift","NewError","super","avoidNew","JSONPath","opts","otherTypeCallback","optObj","json","path","resultType","flatten","wrap","sandbox","eval","ignoreEvalErrors","parent","parentProperty","autostart","ret","evaluate","prototype","currParent","currParentProperty","currResultType","currEval","currSandbox","currOtherTypeCallback","toPathString","exprList","toPathArray","shift","_hasParentSelector","_trace","ea","isParentSelector","hasArrExpr","reduce","rslt","valOrPath","_getPreferredOutput","concat","pointer","toPointer","_handleCallback","fullRetObj","preferredOutput","parentPropName","literalPriority","retObj","loc","x","addRet","elems","t","_walk","_slice","indexOf","safeLoc","replace","nested","exec","npath","nvalue","_eval","at","addType","valueType","Number","isFinite","locProp","parts","split","part","rett","tmp","tl","tt","splice","f","n","len","step","parseInt","end","min","_v","_vname","_$_parentProperty","_$_parent","_$_property","_$_root","_$_v","containsPath","_$_path","scriptCacheKey","cache","script","replaceAll","safeVm","Script","vm","CurrEval","runInNewContext","pathArr","p","subx","$0","$1","ups","join","exp","match","keyMap","create","funcs","source","target","conditionCb","il","moveToAnotherArray","key","vr","s","fString","lastStatementEnd","lastIndexOf"],"mappings":"AAgGA,MAAMA,EAIL,kBAAWC,GAEV,MAAO,OACR,CAKA,eAAOC,GACN,MAAO,wCAA0CF,EAAKC,OACvD,CAQA,iBAAOE,CAAWC,GAGjB,OAFAJ,EAAKK,aAAeC,KAAKC,IAAIH,EAAQI,OAAQR,EAAKK,cAClDL,EAAKS,UAAUL,GAAW,EACnBJ,CACR,CASA,kBAAOU,CAAYN,EAASO,EAAYC,GASvC,OARAZ,EAAKa,cAAgBP,KAAKC,IAAIH,EAAQI,OAAQR,EAAKa,eACnDb,EAAKc,WAAWV,GAAWO,EACvBC,EACHZ,EAAKe,kBAAkBC,IAAIZ,GAG3BJ,EAAKe,kBAAkBE,OAAOb,GAExBJ,CACR,CAOA,wBAAOkB,CAAkBC,GAExB,OADAnB,EAAKoB,4BAA4BJ,IAAIG,GAC9BnB,CACR,CAQA,iBAAOqB,CAAWC,EAAcC,GAE/B,OADAvB,EAAKwB,SAASF,GAAgBC,EACvBvB,CACR,CAOA,oBAAOyB,CAAcrB,GAKpB,cAJOJ,EAAKS,UAAUL,GAClBA,EAAQI,SAAWR,EAAKK,eAC3BL,EAAKK,aAAeL,EAAK0B,aAAa1B,EAAKS,YAErCT,CACR,CAMA,wBAAO2B,GAIN,OAHA3B,EAAKS,UAAY,CAAE,EACnBT,EAAKK,aAAe,EAEbL,CACR,CAOA,2BAAO4B,CAAqBT,GAE3B,OADAnB,EAAKoB,4BAA4BH,OAAOE,GACjCnB,CACR,CAOA,qBAAO6B,CAAezB,GAQrB,cAPOJ,EAAKc,WAAWV,GAEnBA,EAAQI,SAAWR,EAAKa,gBAC3Bb,EAAKa,cAAgBb,EAAK0B,aAAa1B,EAAKc,aAE7Cd,EAAKe,kBAAkBE,OAAOb,GAEvBJ,CACR,CAMA,yBAAO8B,GAIN,OAHA9B,EAAKc,WAAa,CAAE,EACpBd,EAAKa,cAAgB,EAEdb,CACR,CAOA,oBAAO+B,CAAcT,GAEpB,cADOtB,EAAKwB,SAASF,GACdtB,CACR,CAMA,wBAAOgC,GAGN,OAFAhC,EAAKwB,SAAW,CAAE,EAEXxB,CACR,CAOA,QAAImB,GACH,OAAOc,KAAKC,KAAKC,OAAOF,KAAKG,MAC9B,CAKA,QAAIC,GACH,OAAOJ,KAAKC,KAAKI,WAAWL,KAAKG,MAClC,CAOAG,WAAAA,CAAYL,GAGXD,KAAKC,KAAOA,EACZD,KAAKG,MAAQ,CACd,CAMA,YAAOI,CAAMN,GACZ,OAAQ,IAAIlC,EAAKkC,GAAOM,OACzB,CAOA,mBAAOd,CAAae,GACnB,OAAOnC,KAAKC,IAAI,KAAMmC,OAAOC,KAAKF,GAAKG,KAAIC,GAAKA,EAAErC,SACnD,CAOA,qBAAOsC,CAAeC,GACrB,OAAQA,GAAM,IAAMA,GAAM,EAC3B,CAOA,uBAAOC,CAAiBC,GACvB,OAAOjD,EAAKc,WAAWmC,IAAW,CACnC,CAOA,wBAAOC,CAAkBH,GACxB,OAASA,GAAM,IAAMA,GAAM,IACzBA,GAAM,IAAMA,GAAM,KAClBA,GAAM,MAAQ/C,EAAKc,WAAWqC,OAAOC,aAAaL,KAClD/C,EAAKoB,4BAA4BiC,IAAIF,OAAOC,aAAaL,GAC5D,CAMA,uBAAOO,CAAiBP,GACvB,OAAO/C,EAAKkD,kBAAkBH,IAAO/C,EAAK8C,eAAeC,EAC1D,CAOAQ,UAAAA,CAAWC,GACV,MAAMC,EAAQ,IAAIC,MAAMF,EAAU,iBAAmBvB,KAAKG,OAG1D,MAFAqB,EAAMrB,MAAQH,KAAKG,MACnBqB,EAAME,YAAcH,EACdC,CACP,CAQAG,OAAAA,CAAQC,EAAMC,GACb,GAAI9D,EAAK+D,MAAMF,GAAO,CACrB,MAAMG,EAAM,CAAEC,QAAShC,KAAM6B,QAE7B,OADA9D,EAAK+D,MAAMG,IAAIL,EAAMG,GACdA,EAAIF,IACZ,CACA,OAAOA,CACR,CAOAK,UAAAA,CAAWN,GACV,GAAI7D,EAAK+D,MAAMF,GAAO,CACrB,MAAMG,EAAM,CAAEC,QAAShC,MAKvB,OAJAjC,EAAK+D,MAAMF,GAAMO,MAAK,SAAUC,GAE/B,OADAA,EAASC,KAAKN,EAAIC,QAASD,GACpBA,EAAIF,IACZ,IACOE,EAAIF,IACZ,CACD,CAKAS,YAAAA,GACC,IAAIxB,EAAKd,KAAKI,KAEd,KAAOU,IAAO/C,EAAKwE,YAChBzB,IAAO/C,EAAKyE,UACZ1B,IAAO/C,EAAK0E,SACZ3B,IAAO/C,EAAK2E,SACd5B,EAAKd,KAAKC,KAAKI,aAAaL,KAAKG,OAElCH,KAAK2B,QAAQ,gBACd,CAMApB,KAAAA,GACCP,KAAK2B,QAAQ,cACb,MAAMgB,EAAQ3C,KAAK4C,oBAGbf,EAAwB,IAAjBc,EAAMpE,OACfoE,EAAM,GACP,CACDE,KAAM9E,EAAK+E,SACXC,KAAMJ,GAER,OAAO3C,KAAK2B,QAAQ,YAAaE,EAClC,CAOAe,iBAAAA,CAAkBI,GACjB,IAAgBC,EAAMpB,EAAlBc,EAAQ,GAEZ,KAAO3C,KAAKG,MAAQH,KAAKC,KAAK1B,QAK7B,GAJA0E,EAAOjD,KAAKI,KAIR6C,IAASlF,EAAKmF,aAAeD,IAASlF,EAAKoF,WAC9CnD,KAAKG,aAIL,GAAI0B,EAAO7B,KAAKoD,mBACfT,EAAMU,KAAKxB,QAIP,GAAI7B,KAAKG,MAAQH,KAAKC,KAAK1B,OAAQ,CACvC,GAAI0E,IAASD,EACZ,MAEDhD,KAAKsB,WAAW,eAAiBtB,KAAKd,KAAO,IAC9C,CAIF,OAAOyD,CACR,CAMAS,gBAAAA,GACC,MAAMvB,EAAO7B,KAAKkC,WAAW,sBAAwBlC,KAAKsD,yBAG1D,OAFAtD,KAAKsC,eAEEtC,KAAK2B,QAAQ,mBAAoBE,EACzC,CASA0B,cAAAA,GACCvD,KAAKsC,eACL,IAAIkB,EAAWxD,KAAKC,KAAKwD,OAAOzD,KAAKG,MAAOpC,EAAKa,eAC7C8E,EAASF,EAASjF,OAEtB,KAAOmF,EAAS,GAAG,CAIlB,GAAI3F,EAAKc,WAAW8E,eAAeH,MACjCzF,EAAKkD,kBAAkBjB,KAAKI,OAC5BJ,KAAKG,MAAQqD,EAASjF,OAASyB,KAAKC,KAAK1B,SAAWR,EAAKsD,iBAAiBrB,KAAKC,KAAKI,WAAWL,KAAKG,MAAQqD,EAASjF,UAGtH,OADAyB,KAAKG,OAASuD,EACPF,EAERA,EAAWA,EAASC,OAAO,IAAKC,EACjC,CACA,OAAO,CACR,CAOAJ,sBAAAA,GACC,IAAIzB,EAAM+B,EAAMC,EAAMC,EAAOC,EAAWC,EAAMC,EAAOC,EAAGC,EAMxD,GADAH,EAAOhE,KAAKoE,eACPJ,EACJ,OAAOA,EAKR,GAHAJ,EAAO5D,KAAKuD,kBAGPK,EACJ,OAAOI,EAgBR,IAXAD,EAAY,CAAEM,MAAOT,EAAMC,KAAM9F,EAAKgD,iBAAiB6C,GAAOU,QAASvG,EAAKe,kBAAkBsC,IAAIwC,IAElGK,EAAQjE,KAAKoE,cAERH,GACJjE,KAAKsB,WAAW,6BAA+BsC,GAGhDE,EAAQ,CAACE,EAAMD,EAAWE,GAGlBL,EAAO5D,KAAKuD,kBAAmB,CAGtC,GAFAM,EAAO9F,EAAKgD,iBAAiB6C,GAEhB,IAATC,EAAY,CACf7D,KAAKG,OAASyD,EAAKrF,OACnB,KACD,CAEAwF,EAAY,CAAEM,MAAOT,EAAMC,OAAMS,QAASvG,EAAKe,kBAAkBsC,IAAIwC,IAErEO,EAAWP,EAGX,MAAMW,EAAcC,GAAQT,EAAUO,SAAWE,EAAKF,QACnDT,EAAOW,EAAKX,KACZA,GAAQW,EAAKX,KAChB,KAAQC,EAAMvF,OAAS,GAAMgG,EAAYT,EAAMA,EAAMvF,OAAS,KAC7D0F,EAAQH,EAAMW,MACdb,EAAOE,EAAMW,MAAMJ,MACnBL,EAAOF,EAAMW,MACb5C,EAAO,CACNgB,KAAM9E,EAAK2G,WACXC,SAAUf,EACVI,OACAC,SAEDH,EAAMT,KAAKxB,GAGZA,EAAO7B,KAAKoE,cAEPvC,GACJ7B,KAAKsB,WAAW,6BAA+B6C,GAGhDL,EAAMT,KAAKU,EAAWlC,EACvB,CAKA,IAHAqC,EAAIJ,EAAMvF,OAAS,EACnBsD,EAAOiC,EAAMI,GAENA,EAAI,GACVrC,EAAO,CACNgB,KAAM9E,EAAK2G,WACXC,SAAUb,EAAMI,EAAI,GAAGG,MACvBL,KAAMF,EAAMI,EAAI,GAChBD,MAAOpC,GAERqC,GAAK,EAGN,OAAOrC,CACR,CAOAuC,WAAAA,GACC,IAAItD,EAAI0C,EAAUE,EAAQ7B,EAI1B,GAFA7B,KAAKsC,eACLT,EAAO7B,KAAKkC,WAAW,gBACnBL,EACH,OAAO7B,KAAK2B,QAAQ,cAAeE,GAKpC,GAFAf,EAAKd,KAAKI,KAENrC,EAAK8C,eAAeC,IAAOA,IAAO/C,EAAK6G,YAE1C,OAAO5E,KAAK6E,uBAGb,GAAI/D,IAAO/C,EAAK+G,aAAehE,IAAO/C,EAAKgH,YAE1ClD,EAAO7B,KAAKgF,2BAER,GAAIlE,IAAO/C,EAAKkH,YACpBpD,EAAO7B,KAAKkF,kBAER,CAIJ,IAHA1B,EAAWxD,KAAKC,KAAKwD,OAAOzD,KAAKG,MAAOpC,EAAKK,cAC7CsF,EAASF,EAASjF,OAEXmF,EAAS,GAAG,CAIlB,GAAI3F,EAAKS,UAAUmF,eAAeH,MAChCzF,EAAKkD,kBAAkBjB,KAAKI,OAC5BJ,KAAKG,MAAQqD,EAASjF,OAASyB,KAAKC,KAAK1B,SAAWR,EAAKsD,iBAAiBrB,KAAKC,KAAKI,WAAWL,KAAKG,MAAQqD,EAASjF,UACpH,CACFyB,KAAKG,OAASuD,EACd,MAAMyB,EAAWnF,KAAKoE,cAItB,OAHKe,GACJnF,KAAKsB,WAAW,4BAEVtB,KAAK2B,QAAQ,cAAe,CAClCkB,KAAM9E,EAAKqH,UACXT,SAAUnB,EACV2B,WACAE,QAAQ,GAEV,CAEA7B,EAAWA,EAASC,OAAO,IAAKC,EACjC,CAEI3F,EAAKkD,kBAAkBH,IAC1Be,EAAO7B,KAAKsF,mBACRvH,EAAKwB,SAASoE,eAAe9B,EAAKD,MACrCC,EAAO,CACNgB,KAAM9E,EAAKwH,QACXlB,MAAOtG,EAAKwB,SAASsC,EAAKD,MAC1B4D,IAAK3D,EAAKD,MAGHC,EAAKD,OAAS7D,EAAK0H,WAC3B5D,EAAO,CAAEgB,KAAM9E,EAAK2H,YAGb5E,IAAO/C,EAAK4H,cACpB9D,EAAO7B,KAAK4F,cAEd,CAEA,OAAK/D,GAILA,EAAO7B,KAAK6F,oBAAoBhE,GACzB7B,KAAK2B,QAAQ,cAAeE,IAJ3B7B,KAAK2B,QAAQ,eAAe,EAKrC,CAUAkE,mBAAAA,CAAoBhE,GACnB7B,KAAKsC,eAEL,IAAIxB,EAAKd,KAAKI,KACd,KAAOU,IAAO/C,EAAK6G,aAAe9D,IAAO/C,EAAKkH,aAAenE,IAAO/C,EAAK4H,aAAe7E,IAAO/C,EAAK+H,aAAa,CAChH,IAAIC,EACJ,GAAIjF,IAAO/C,EAAK+H,YAAa,CAC5B,GAAI9F,KAAKC,KAAKI,WAAWL,KAAKG,MAAQ,KAAOpC,EAAK6G,YACjD,MAEDmB,GAAW,EACX/F,KAAKG,OAAS,EACdH,KAAKsC,eACLxB,EAAKd,KAAKI,IACX,CACAJ,KAAKG,QAEDW,IAAO/C,EAAKkH,cACfpD,EAAO,CACNgB,KAAM9E,EAAKiI,WACXC,UAAU,EACVC,OAAQrE,EACRsE,SAAUnG,KAAKoD,qBAEN+C,UACTnG,KAAKsB,WAAW,eAAiBtB,KAAKd,KAAO,KAE9Cc,KAAKsC,eACLxB,EAAKd,KAAKI,KACNU,IAAO/C,EAAKqI,aACfpG,KAAKsB,WAAW,cAEjBtB,KAAKG,SAEGW,IAAO/C,EAAK4H,YAEpB9D,EAAO,CACNgB,KAAM9E,EAAKsI,SACXC,UAAatG,KAAKuG,gBAAgBxI,EAAKyI,aACvCC,OAAQ5E,IAGDf,IAAO/C,EAAK6G,aAAemB,KAC/BA,GACH/F,KAAKG,QAENH,KAAKsC,eACLT,EAAO,CACNgB,KAAM9E,EAAKiI,WACXC,UAAU,EACVC,OAAQrE,EACRsE,SAAUnG,KAAKsF,qBAIbS,IACHlE,EAAKkE,UAAW,GAGjB/F,KAAKsC,eACLxB,EAAKd,KAAKI,IACX,CAEA,OAAOyB,CACR,CAOAgD,oBAAAA,GACC,IAAiB/D,EAAI4F,EAAjBC,EAAS,GAEb,KAAO5I,EAAK8C,eAAeb,KAAKI,OAC/BuG,GAAU3G,KAAKC,KAAKC,OAAOF,KAAKG,SAGjC,GAAIH,KAAKI,OAASrC,EAAK6G,YAGtB,IAFA+B,GAAU3G,KAAKC,KAAKC,OAAOF,KAAKG,SAEzBpC,EAAK8C,eAAeb,KAAKI,OAC/BuG,GAAU3G,KAAKC,KAAKC,OAAOF,KAAKG,SAMlC,GAFAW,EAAKd,KAAKd,KAEC,MAAP4B,GAAqB,MAAPA,EAAY,CAQ7B,IAPA6F,GAAU3G,KAAKC,KAAKC,OAAOF,KAAKG,SAChCW,EAAKd,KAAKd,KAEC,MAAP4B,GAAqB,MAAPA,IACjB6F,GAAU3G,KAAKC,KAAKC,OAAOF,KAAKG,UAG1BpC,EAAK8C,eAAeb,KAAKI,OAC/BuG,GAAU3G,KAAKC,KAAKC,OAAOF,KAAKG,SAG5BpC,EAAK8C,eAAeb,KAAKC,KAAKI,WAAWL,KAAKG,MAAQ,KAC1DH,KAAKsB,WAAW,sBAAwBqF,EAAS3G,KAAKd,KAAO,IAE/D,CAaA,OAXAwH,EAAS1G,KAAKI,KAGVrC,EAAKkD,kBAAkByF,GAC1B1G,KAAKsB,WAAW,8CACfqF,EAAS3G,KAAKd,KAAO,MAEdwH,IAAW3I,EAAK6G,aAAkC,IAAlB+B,EAAOpI,QAAgBoI,EAAOtG,WAAW,KAAOtC,EAAK6G,cAC7F5E,KAAKsB,WAAW,qBAGV,CACNuB,KAAM9E,EAAKwH,QACXlB,MAAOuC,WAAWD,GAClBnB,IAAKmB,EAEP,CAOA3B,mBAAAA,GACC,IAAI6B,EAAM,GACV,MAAMC,EAAa9G,KAAKG,MAClB4G,EAAQ/G,KAAKC,KAAKC,OAAOF,KAAKG,SACpC,IAAI6G,GAAS,EAEb,KAAOhH,KAAKG,MAAQH,KAAKC,KAAK1B,QAAQ,CACrC,IAAIuC,EAAKd,KAAKC,KAAKC,OAAOF,KAAKG,SAE/B,GAAIW,IAAOiG,EAAO,CACjBC,GAAS,EACT,KACD,CACK,GAAW,OAAPlG,EAIR,OAFAA,EAAKd,KAAKC,KAAKC,OAAOF,KAAKG,SAEnBW,GACP,IAAK,IAAK+F,GAAO,KAAM,MACvB,IAAK,IAAKA,GAAO,KAAM,MACvB,IAAK,IAAKA,GAAO,KAAM,MACvB,IAAK,IAAKA,GAAO,KAAM,MACvB,IAAK,IAAKA,GAAO,KAAM,MACvB,IAAK,IAAKA,GAAO,KAAQ,MACzB,QAAUA,GAAO/F,OAIlB+F,GAAO/F,CAET,CAMA,OAJKkG,GACJhH,KAAKsB,WAAW,yBAA2BuF,EAAM,KAG3C,CACNhE,KAAM9E,EAAKwH,QACXlB,MAAOwC,EACPrB,IAAKxF,KAAKC,KAAKgH,UAAUH,EAAY9G,KAAKG,OAE5C,CASAmF,gBAAAA,GACC,IAAIxE,EAAKd,KAAKI,KAAM8G,EAAQlH,KAAKG,MASjC,IAPIpC,EAAKkD,kBAAkBH,GAC1Bd,KAAKG,QAGLH,KAAKsB,WAAW,cAAgBtB,KAAKd,MAG/Bc,KAAKG,MAAQH,KAAKC,KAAK1B,SAC7BuC,EAAKd,KAAKI,KAENrC,EAAKsD,iBAAiBP,KACzBd,KAAKG,QAMP,MAAO,CACN0C,KAAM9E,EAAKoJ,WACXvF,KAAM5B,KAAKC,KAAKmH,MAAMF,EAAOlH,KAAKG,OAEpC,CAWAoG,eAAAA,CAAgBc,GACf,MAAMC,EAAO,GACb,IAAIN,GAAS,EACTO,EAAkB,EAEtB,KAAOvH,KAAKG,MAAQH,KAAKC,KAAK1B,QAAQ,CACrCyB,KAAKsC,eACL,IAAIW,EAAOjD,KAAKI,KAEhB,GAAI6C,IAASoE,EAAa,CACzBL,GAAS,EACThH,KAAKG,QAEDkH,IAAgBtJ,EAAKyI,aAAee,GAAmBA,GAAmBD,EAAK/I,QAClFyB,KAAKsB,WAAW,oBAAsBJ,OAAOC,aAAakG,IAG3D,KACD,CACK,GAAIpE,IAASlF,EAAKoF,YAItB,GAHAnD,KAAKG,QACLoH,IAEIA,IAAoBD,EAAK/I,OAC5B,GAAI8I,IAAgBtJ,EAAKyI,YACxBxG,KAAKsB,WAAW,2BAEZ,GAAI+F,IAAgBtJ,EAAKqI,YAC7B,IAAK,IAAIoB,EAAMF,EAAK/I,OAAQiJ,EAAMD,EAAiBC,IAClDF,EAAKjE,KAAK,WAKT,GAAIiE,EAAK/I,SAAWgJ,GAAuC,IAApBA,EAE3CvH,KAAKsB,WAAW,sBAEZ,CACJ,MAAMO,EAAO7B,KAAKoD,mBAEbvB,GAAQA,EAAKgB,OAAS9E,EAAK+E,UAC/B9C,KAAKsB,WAAW,kBAGjBgG,EAAKjE,KAAKxB,EACX,CACD,CAMA,OAJKmF,GACJhH,KAAKsB,WAAW,YAAcJ,OAAOC,aAAakG,IAG5CC,CACR,CAWA1B,WAAAA,GACC5F,KAAKG,QACL,IAAIwC,EAAQ3C,KAAK4C,kBAAkB7E,EAAKyI,aACxC,GAAIxG,KAAKI,OAASrC,EAAKyI,YAEtB,OADAxG,KAAKG,QACgB,IAAjBwC,EAAMpE,OACFoE,EAAM,KAEJA,EAAMpE,QAIR,CACNsE,KAAM9E,EAAK0J,aACXC,YAAa/E,GAKf3C,KAAKsB,WAAW,aAElB,CAQA4D,WAAAA,GAGC,OAFAlF,KAAKG,QAEE,CACN0C,KAAM9E,EAAK4J,UACXC,SAAU5H,KAAKuG,gBAAgBxI,EAAKqI,aAEtC,EAID,MAAMtE,EAAQ,IA58Bd,MAmBC/C,GAAAA,CAAI6C,EAAMQ,EAAUyF,GACnB,GAA2B,iBAAhBvB,UAAU,GAEpB,IAAK,IAAI1E,KAAQ0E,UAAU,GAC1BtG,KAAKjB,IAAI6C,EAAM0E,UAAU,GAAG1E,GAAO0E,UAAU,SAI7CwB,MAAMC,QAAQnG,GAAQA,EAAO,CAACA,IAAOoG,SAAQ,SAAUpG,GACvD5B,KAAK4B,GAAQ5B,KAAK4B,IAAS,GAEvBQ,GACHpC,KAAK4B,GAAMiG,EAAQ,UAAY,QAAQzF,EAExC,GAAEpC,KAEL,CAWAiC,GAAAA,CAAIL,EAAMG,GACT/B,KAAK4B,GAAQ5B,KAAK4B,IAAS,GAC3B5B,KAAK4B,GAAMoG,SAAQ,SAAU5F,GAC5BA,EAASC,KAAKN,GAAOA,EAAIC,QAAUD,EAAIC,QAAUD,EAAKA,EACvD,GACD,GA05BDtB,OAAOwH,OAAOlK,EAAM,CACnB+D,QACAoG,QAAS,IAt5BV,MACC5H,WAAAA,CAAY6H,GACXnI,KAAKmI,KAAOA,EACZnI,KAAKoI,WAAa,CAAE,CACrB,CAeAC,QAAAA,GAAqB,IAAA,IAAAC,EAAAhC,UAAA/H,OAAT2J,EAAOJ,IAAAA,MAAAQ,GAAAC,EAAA,EAAAA,EAAAD,EAAAC,IAAPL,EAAOK,GAAAjC,UAAAiC,GAClBL,EAAQF,SAASQ,IAChB,GAAsB,iBAAXA,IAAwBA,EAAO5G,OAAS4G,EAAOC,KACzD,MAAM,IAAIhH,MAAM,8BAEbzB,KAAKoI,WAAWI,EAAO5G,QAI3B4G,EAAOC,KAAKzI,KAAKmI,MACjBnI,KAAKoI,WAAWI,EAAO5G,MAAQ4G,EAAM,GAEvC,GAu3BqBzK,GAMrB+E,SAAiB,WACjB2E,aAAiB,qBACjBN,WAAiB,aACjBnB,WAAiB,mBACjBT,QAAiB,UACjBG,SAAiB,iBACjBW,SAAiB,iBACjBjB,UAAiB,kBACjBV,WAAiB,mBACjBiD,UAAiB,kBAEjBnF,SAAa,EACbC,QAAa,GACbC,QAAa,GACbH,WAAa,GACbqC,YAAa,GACbzB,WAAa,GACb2B,YAAa,GACbC,YAAa,GACbY,YAAa,GACba,YAAa,GACbvB,YAAa,GACbmB,YAAa,GACbN,YAAa,GACb5C,YAAa,GACbwF,WAAa,GAOblK,UAAW,CACV,IAAK,EACL,IAAK,EACL,IAAK,EACL,IAAK,GAMNK,WAAY,CACX,KAAM,EAAG,KAAM,EACf,KAAM,EAAG,IAAK,EAAG,IAAK,EAAG,IAAK,EAC9B,KAAM,EAAG,KAAM,EAAG,MAAO,EAAG,MAAO,EACnC,IAAK,EAAG,IAAK,EAAG,KAAM,EAAG,KAAM,EAC/B,KAAM,EAAG,KAAM,EAAG,MAAO,EACzB,IAAK,EAAG,IAAK,EACb,IAAK,GAAI,IAAK,GAAI,IAAK,GACvB,KAAM,IAIPC,kBAAmB,IAAI6J,IAAI,CAAC,OAG5BxJ,4BAA6B,IAAIwJ,IAAI,CAAC,IAAK,MAK3CpJ,SAAU,CACTqJ,MAAQ,EACRC,OAAS,EACTC,KAAQ,MAITrD,SAAU,SAEX1H,EAAKK,aAAeL,EAAK0B,aAAa1B,EAAKS,WAC3CT,EAAKa,cAAgBb,EAAK0B,aAAa1B,EAAKc,YAG5C,MAAMsJ,EAAOlI,GAAS,IAAIlC,EAAKkC,GAAOM,QAChCwI,EAAgBtI,OAAOuI,oBAAoB,SACjDvI,OAAOuI,oBAAoBjL,GACzBkL,QAAOC,IAASH,EAAcI,SAASD,SAAwBE,IAAfjB,EAAKe,KACrDlB,SAASqB,IACTlB,EAAKkB,GAAKtL,EAAKsL,EAAE,IAEnBlB,EAAKpK,KAAOA,EAIZ,IAAIuL,EAAU,CACb1H,KAAM,UAEN6G,IAAAA,CAAKN,GAEJA,EAAKrG,MAAM/C,IAAI,oBAAoB,SAAuBgD,GACzD,GAAIA,EAAIF,MAAQ7B,KAAKI,OAAS+H,EAAKrC,YAAa,CAC/C9F,KAAKG,QACL,MAAMoJ,EAAOxH,EAAIF,KACX2H,EAAaxJ,KAAKoD,mBAQxB,GANKoG,GACJxJ,KAAKsB,WAAW,uBAGjBtB,KAAKsC,eAEDtC,KAAKI,OAAS+H,EAAKO,WAAY,CAClC1I,KAAKG,QACL,MAAMsJ,EAAYzJ,KAAKoD,mBAcvB,GAZKqG,GACJzJ,KAAKsB,WAAW,uBAEjBS,EAAIF,KAAO,CACVgB,KA3BkB,wBA4BlB0G,OACAC,aACAC,aAKGF,EAAK5E,UAAYwD,EAAKtJ,WAAW0K,EAAK5E,WAAa,GAAK,CAC3D,IAAI+E,EAAUH,EACd,KAAOG,EAAQzF,MAAMU,UAAYwD,EAAKtJ,WAAW6K,EAAQzF,MAAMU,WAAa,IAC3E+E,EAAUA,EAAQzF,MAEnBlC,EAAIF,KAAK0H,KAAOG,EAAQzF,MACxByF,EAAQzF,MAAQlC,EAAIF,KACpBE,EAAIF,KAAO0H,CACZ,CACD,MAECvJ,KAAKsB,WAAW,aAElB,CACD,GACD,GAKD6G,EAAKD,QAAQG,SAASiB,GChmCtB,IAAInJ,EAAQ,CACXyB,KAAM,QAEN6G,IAAAA,CAAKN,GAEJA,EAAKrG,MAAM/C,IAAI,gBAAgB,SAA4BgD,GAC1D,GATiB,KASb/B,KAAKI,KAAsB,CAC9B,MAAMuJ,IAAiB3J,KAAKG,MAE5B,IAAIyJ,GAAY,EAChB,KAAO5J,KAAKG,MAAQH,KAAKC,KAAK1B,QAAQ,CACrC,GAde,KAcXyB,KAAKI,OAAyBwJ,EAAW,CAC5C,MAAMC,EAAU7J,KAAKC,KAAKmH,MAAMuC,EAAc3J,KAAKG,OAEnD,IAaIkE,EAbAyF,EAAQ,GACZ,OAAS9J,KAAKG,MAAQH,KAAKC,KAAK1B,QAAQ,CACvC,MAAM6B,EAAOJ,KAAKI,KAClB,KAAKA,GAAQ,IAAMA,GAAQ,KACtBA,GAAQ,IAAMA,GAAQ,IACtBA,GAAQ,IAAMA,GAAQ,IAI1B,MAHA0J,GAAS9J,KAAKd,IAKhB,CAGA,IACCmF,EAAQ,IAAI0F,OAAOF,EAASC,EAC5B,CACD,MAAOE,GACNhK,KAAKsB,WAAW0I,EAAEzI,QACnB,CAUA,OARAQ,EAAIF,KAAO,CACVgB,KAAMsF,EAAK5C,QACXlB,QACAmB,IAAKxF,KAAKC,KAAKmH,MAAMuC,EAAe,EAAG3J,KAAKG,QAI7C4B,EAAIF,KAAO7B,KAAK6F,oBAAoB9D,EAAIF,MACjCE,EAAIF,IACZ,CACI7B,KAAKI,OAAS+H,EAAKlD,YACtB2E,GAAY,EAEJA,GAAa5J,KAAKI,OAAS+H,EAAK/B,cACxCwD,GAAY,GAEb5J,KAAKG,OArDU,KAqDDH,KAAKI,KAAuB,EAAI,CAC/C,CACAJ,KAAKsB,WAAW,iBACjB,CACD,GACD,GC3DD,MAGMkH,EAAS,CACd5G,KAAM,aAENqI,oBAAqB,IAAItB,IAAI,CAC5B,IACA,KACA,MACA,KACA,KACA,KACA,KACA,MACA,MACA,OACA,KACA,KACA,KACA,MACA,MACA,QAEDuB,gBAAiB,CAxBA,GACC,IAwBlBC,qBAAsB,GAEtB1B,IAAAA,CAAKN,GACJ,MAAMiC,EAAkB,CAACjC,EAAKhB,WAAYgB,EAAKnC,YA8C/C,SAASqE,EAA4BxI,GAChC2G,EAAOyB,oBAAoB7I,IAAIS,EAAK8C,WACvC9C,EAAKgB,KAAO,uBACZwH,EAA4BxI,EAAKmC,MACjCqG,EAA4BxI,EAAKoC,QAExBpC,EAAK8C,UACdlE,OAAO6J,OAAOzI,GAAMmG,SAASuC,IACxBA,GAAsB,iBAARA,GACjBF,EAA4BE,EAC7B,GAGH,CA1DA/B,EAAOyB,oBAAoBjC,SAAQwC,GAAMrC,EAAK1J,YAAY+L,EAAIhC,EAAO2B,sBAAsB,KAE3FhC,EAAKrG,MAAM/C,IAAI,gBAAgB,SAA4BgD,GAC1D,MAAM3B,EAAOJ,KAAKI,KACdoI,EAAO0B,gBAAgBO,MAAKC,GAAKA,IAAMtK,GAAQsK,IAAM1K,KAAKC,KAAKI,WAAWL,KAAKG,MAAQ,OAC1FH,KAAKG,OAAS,EACd4B,EAAIF,KAAO,CACVgB,KAAM,mBACN8B,SArCa,KAqCHvE,EAAqB,KAAO,KACtC+E,SAAUnF,KAAK6F,oBAAoB7F,KAAKsF,oBACxCD,QAAQ,GAEJtD,EAAIF,KAAKsD,UAAaiF,EAAgBjB,SAASpH,EAAIF,KAAKsD,SAAStC,OACrE7C,KAAKsB,WAAW,cAAcS,EAAIF,KAAK8C,YAG1C,IAEAwD,EAAKrG,MAAM/C,IAAI,eAAe,SAA6BgD,GAC1D,GAAIA,EAAIF,KAAM,CACb,MAAMzB,EAAOJ,KAAKI,KACdoI,EAAO0B,gBAAgBO,MAAKC,GAAKA,IAAMtK,GAAQsK,IAAM1K,KAAKC,KAAKI,WAAWL,KAAKG,MAAQ,OACrFiK,EAAgBjB,SAASpH,EAAIF,KAAKgB,OACtC7C,KAAKsB,WAAW,cAAcS,EAAIF,KAAK8C,YAExC3E,KAAKG,OAAS,EACd4B,EAAIF,KAAO,CACVgB,KAAM,mBACN8B,SAzDY,KAyDFvE,EAAqB,KAAO,KACtC+E,SAAUpD,EAAIF,KACdwD,QAAQ,GAGX,CACD,IAEA8C,EAAKrG,MAAM/C,IAAI,oBAAoB,SAA0BgD,GACxDA,EAAIF,MAIPwI,EAA4BtI,EAAIF,KAElC,GAgBD,GClFDsG,EAAKD,QAAQG,SAASsC,EAAWC,GACjCzC,EAAKjK,WAAW,UAChBiK,EAAKjK,WAAW,QAChBiK,EAAK/I,WAAW,OAAQ,MACxB+I,EAAK/I,WAAW,iBAAagK,GAE7B,MAAMyB,EAA2B,IAAIlC,IAAI,CACrC,cACA,YACA,mBACA,mBACA,mBACA,qBAGEmC,EAAW,CAKbC,OAAAA,CAASC,EAAKC,GACV,OAAQD,EAAInI,MACZ,IAAK,mBACL,IAAK,oBACD,OAAOiI,EAASI,qBAAqBF,EAAKC,GAC9C,IAAK,WACD,OAAOH,EAASK,aAAaH,EAAKC,GACtC,IAAK,wBACD,OAAOH,EAASM,0BAA0BJ,EAAKC,GACnD,IAAK,aACD,OAAOH,EAASO,eAAeL,EAAKC,GACxC,IAAK,UACD,OAAOH,EAASQ,YAAYN,EAAKC,GACrC,IAAK,mBACD,OAAOH,EAASS,qBAAqBP,EAAKC,GAC9C,IAAK,kBACD,OAAOH,EAASU,oBAAoBR,EAAKC,GAC7C,IAAK,kBACD,OAAOH,EAASW,oBAAoBT,EAAKC,GAC7C,IAAK,iBACD,OAAOH,EAASY,mBAAmBV,EAAKC,GAC5C,IAAK,uBACD,OAAOH,EAASa,yBAAyBX,EAAKC,GAClD,QACI,MAAMW,YAAY,wBAAyBZ,GAElD,EACDE,qBAAoBA,CAAEF,EAAKC,KACR,CACX,KAAMY,CAACC,EAAGC,IAAMD,GAAKC,IACrB,KAAMC,CAACF,EAAGC,IAAMD,GAAKC,IACrB,IAAKE,CAACH,EAAGC,IAAMD,EAAIC,IACnB,IAAKG,CAACJ,EAAGC,IAAMD,EAAIC,IACnB,IAAKI,CAACL,EAAGC,IAAMD,EAAIC,IAEnB,KAAMK,CAACN,EAAGC,IAAMD,GAAKC,IAErB,KAAMM,CAACP,EAAGC,IAAMD,GAAKC,IACrB,MAAOO,CAACR,EAAGC,IAAMD,IAAMC,IACvB,MAAOQ,CAACT,EAAGC,IAAMD,IAAMC,IACvB,IAAKS,CAACV,EAAGC,IAAMD,EAAIC,IACnB,IAAKU,CAACX,EAAGC,IAAMD,EAAIC,IACnB,KAAMW,CAACZ,EAAGC,IAAMD,GAAKC,IACrB,KAAMY,CAACb,EAAGC,IAAMD,GAAKC,IACrB,KAAMa,CAACd,EAAGC,IAAMD,GAAKC,IACrB,KAAMc,CAACf,EAAGC,IAAMD,GAAKC,IACrB,MAAOe,CAAChB,EAAGC,IAAMD,IAAMC,IACvB,IAAKgB,CAACjB,EAAGC,IAAMD,EAAIC,IACnB,IAAKiB,CAAClB,EAAGC,IAAMD,EAAIC,IACnB,IAAKkB,CAACnB,EAAGC,IAAMD,EAAIC,IACnB,IAAKmB,CAACpB,EAAGC,IAAMD,EAAIC,IACnB,IAAKoB,CAACrB,EAAGC,IAAMD,EAAIC,KACrBf,EAAIrG,UACFmG,EAASC,QAAQC,EAAIhH,KAAMiH,IAC3B,IAAMH,EAASC,QAAQC,EAAI/G,MAAOgH,MAI1CE,YAAAA,CAAcH,EAAKC,GACf,IAAImC,EACJ,IAAK,IAAIlJ,EAAI,EAAGA,EAAI8G,EAAIjI,KAAKxE,OAAQ2F,IAAK,CAEb,eAArB8G,EAAIjI,KAAKmB,GAAGrB,MACZ,CAAC,MAAO,MAAO,SAASsG,SAAS6B,EAAIjI,KAAKmB,GAAGtC,OAC7CoJ,EAAIjI,KAAKmB,EAAI,IACY,yBAAzB8G,EAAIjI,KAAKmB,EAAI,GAAGrB,OAMhBqB,GAAK,GAET,MAAMjE,EAAO+K,EAAIjI,KAAKmB,GACtBkJ,EAAOtC,EAASC,QAAQ9K,EAAMgL,EAClC,CACA,OAAOmC,CACV,EACDhC,0BAAyBA,CAAEJ,EAAKC,IACxBH,EAASC,QAAQC,EAAIzB,KAAM0B,GACpBH,EAASC,QAAQC,EAAIxB,WAAYyB,GAErCH,EAASC,QAAQC,EAAIvB,UAAWwB,GAE3CI,cAAAA,CAAgBL,EAAKC,GACjB,GAAIxK,OAAO4M,OAAOpC,EAAMD,EAAIpJ,MACxB,OAAOqJ,EAAKD,EAAIpJ,MAEpB,MAAM0L,eAAe,GAAGtC,EAAIpJ,sBAC/B,EACD0J,YAAaN,GACFA,EAAI3G,MAEfkH,oBAAAA,CAAsBP,EAAKC,GACvB,MAAM/B,EAAOhI,OAIT8J,EAAI/E,SACE6E,EAASC,QAAQC,EAAI7E,UACrB6E,EAAI7E,SAASvE,MAEjBpB,EAAMsK,EAASC,QAAQC,EAAI9E,OAAQ+E,GACzC,GAAIzK,QACA,MAAM+M,UACF,6BAA6B/M,eAAiB0I,OAGtD,IAAKzI,OAAO4M,OAAO7M,EAAK0I,IAAS2B,EAAyBzJ,IAAI8H,GAC1D,MAAMqE,UACF,6BAA6B/M,eAAiB0I,OAGtD,MAAMsE,EAAShN,EAAI0I,GACnB,MAAsB,mBAAXsE,EACAA,EAAOC,KAAKjN,GAEhBgN,CACV,EACDhC,oBAAmBA,CAAER,EAAKC,KACP,CACX,IAAMa,IAAOhB,EAASC,QAAQe,EAAGb,GACjC,IAAMa,IAAOhB,EAASC,QAAQe,EAAGb,GACjC,IAAMa,IAAOhB,EAASC,QAAQe,EAAGb,GAEjC,IAAMa,IAAOhB,EAASC,QAAQe,EAAGb,GACjCyC,OAAS5B,UAAahB,EAASC,QAAQe,EAAGb,GAE1C0C,KAAO7B,IAAWhB,EAASC,QAAQe,EAAGb,EACzC,GAACD,EAAIrG,UAAUqG,EAAI7F,WAGxBsG,oBAAmBA,CAAET,EAAKC,IACfD,EAAIpD,SAASjH,KAAKiN,GAAO9C,EAASC,QAAQ6C,EAAI3C,KAEzDS,kBAAAA,CAAoBV,EAAKC,GACrB,MAAM3D,EAAO0D,EAAI1E,UAAU3F,KAAK6G,GAAQsD,EAASC,QAAQvD,EAAKyD,KACxD4C,EAAO/C,EAASC,QAAQC,EAAIvE,OAAQwE,GAE1C,GAAI4C,IAASC,SAET,MAAM,IAAIrM,MAAM,oCAGpB,OAAOoM,KAAQvG,EAClB,EACDqE,wBAAAA,CAA0BX,EAAKC,GAC3B,GAAsB,eAAlBD,EAAIhH,KAAKnB,KACT,MAAM+I,YAAY,wCAEtB,MAAMmC,EAAK/C,EAAIhH,KAAKpC,KACdyC,EAAQyG,EAASC,QAAQC,EAAI/G,MAAOgH,GAE1C,OADAA,EAAK8C,GAAM1J,EACJ4G,EAAK8C,EAChB,GC9JJ,SAAS1K,EAAM2K,EAAKC,GAGhB,OAFAD,EAAMA,EAAI5G,SACN/D,KAAK4K,GACFD,CACX,CAOA,SAASE,EAASD,EAAMD,GAGpB,OAFAA,EAAMA,EAAI5G,SACN8G,QAAQD,GACLD,CACX,CAMA,MAAMG,UAAiB1M,MAInBnB,WAAAA,CAAa+D,GACT+J,MACI,8FAGJpO,KAAKqO,UAAW,EAChBrO,KAAKqE,MAAQA,EACbrE,KAAK4B,KAAO,UAChB,EAiFJ,SAAS0M,EAAUC,EAAMtO,EAAMO,EAAK4B,EAAUoM,GAE1C,KAAMxO,gBAAgBsO,GAClB,IACI,OAAO,IAAIA,EAASC,EAAMtO,EAAMO,EAAK4B,EAAUoM,EAClD,CAAC,MAAOxE,GACL,IAAKA,EAAEqE,SACH,MAAMrE,EAEV,OAAOA,EAAE3F,KACb,CAGgB,iBAATkK,IACPC,EAAoBpM,EACpBA,EAAW5B,EACXA,EAAMP,EACNA,EAAOsO,EACPA,EAAO,MAEX,MAAME,EAASF,GAAwB,iBAATA,EAwB9B,GAvBAA,EAAOA,GAAQ,CAAE,EACjBvO,KAAK0O,KAAOH,EAAKG,MAAQlO,EACzBR,KAAK2O,KAAOJ,EAAKI,MAAQ1O,EACzBD,KAAK4O,WAAaL,EAAKK,YAAc,QACrC5O,KAAK6O,QAAUN,EAAKM,UAAW,EAC/B7O,KAAK8O,MAAOrO,OAAO4M,OAAOkB,EAAM,SAAUA,EAAKO,KAC/C9O,KAAK+O,QAAUR,EAAKQ,SAAW,CAAE,EACjC/O,KAAKgP,UAAqB5F,IAAdmF,EAAKS,KAAqB,OAAST,EAAKS,KACpDhP,KAAKiP,sBAAqD,IAA1BV,EAAKU,kBAE/BV,EAAKU,iBACXjP,KAAKkP,OAASX,EAAKW,QAAU,KAC7BlP,KAAKmP,eAAiBZ,EAAKY,gBAAkB,KAC7CnP,KAAKoC,SAAWmM,EAAKnM,UAAYA,GAAY,KAC7CpC,KAAKwO,kBAAoBD,EAAKC,mBAC1BA,GACA,WACI,MAAM,IAAIjB,UACN,mFAGP,GAEkB,IAAnBgB,EAAKa,UAAqB,CAC1B,MAAM9H,EAAO,CACTqH,KAAOF,EAASF,EAAKI,KAAO1O,GAE3BwO,EAEM,SAAUF,IACjBjH,EAAKoH,KAAOH,EAAKG,MAFjBpH,EAAKoH,KAAOlO,EAIhB,MAAM6O,EAAMrP,KAAKsP,SAAShI,GAC1B,IAAK+H,GAAsB,iBAARA,EACf,MAAM,IAAIlB,EAASkB,GAEvB,OAAOA,CACX,CACJ,CAGAf,EAASiB,UAAUD,SAAW,SAC1BrP,EAAMyO,EAAMtM,EAAUoM,GAEtB,IAAIgB,EAAaxP,KAAKkP,OAClBO,EAAqBzP,KAAKmP,gBAC1BN,QAACA,EAAOC,KAAEA,GAAQ9O,KAUtB,GARAA,KAAK0P,eAAiB1P,KAAK4O,WAC3B5O,KAAK2P,SAAW3P,KAAKgP,KACrBhP,KAAK4P,YAAc5P,KAAK+O,QACxB3M,EAAWA,GAAYpC,KAAKoC,SAC5BpC,KAAK6P,sBAAwBrB,GAAqBxO,KAAKwO,kBAEvDE,EAAOA,GAAQ1O,KAAK0O,MACpBzO,EAAOA,GAAQD,KAAK2O,OACQ,iBAAT1O,IAAsB6H,MAAMC,QAAQ9H,GAAO,CAC1D,IAAKA,EAAK0O,MAAsB,KAAd1O,EAAK0O,KACnB,MAAM,IAAIpB,UACN,+FAIR,IAAM9M,OAAO4M,OAAOpN,EAAM,QACtB,MAAM,IAAIsN,UACN,iGAINmB,QAAQzO,GACV4O,EAAUpO,OAAO4M,OAAOpN,EAAM,WAAaA,EAAK4O,QAAUA,EAC1D7O,KAAK0P,eAAiBjP,OAAO4M,OAAOpN,EAAM,cACpCA,EAAK2O,WACL5O,KAAK0P,eACX1P,KAAK4P,YAAcnP,OAAO4M,OAAOpN,EAAM,WACjCA,EAAK8O,QACL/O,KAAK4P,YACXd,EAAOrO,OAAO4M,OAAOpN,EAAM,QAAUA,EAAK6O,KAAOA,EACjD9O,KAAK2P,SAAWlP,OAAO4M,OAAOpN,EAAM,QAC9BA,EAAK+O,KACLhP,KAAK2P,SACXvN,EAAW3B,OAAO4M,OAAOpN,EAAM,YAAcA,EAAKmC,SAAWA,EAC7DpC,KAAK6P,sBAAwBpP,OAAO4M,OAAOpN,EAAM,qBAC3CA,EAAKuO,kBACLxO,KAAK6P,sBACXL,EAAa/O,OAAO4M,OAAOpN,EAAM,UAAYA,EAAKiP,OAASM,EAC3DC,EAAqBhP,OAAO4M,OAAOpN,EAAM,kBACnCA,EAAKkP,eACLM,EACNxP,EAAOA,EAAK0O,IAChB,CAOA,GANAa,EAAaA,GAAc,KAC3BC,EAAqBA,GAAsB,KAEvC3H,MAAMC,QAAQ9H,KACdA,EAAOqO,EAASwB,aAAa7P,KAE3BA,GAAiB,KAATA,IAAiByO,EAC3B,OAGJ,MAAMqB,EAAWzB,EAAS0B,YAAY/P,GAClB,MAAhB8P,EAAS,IAAcA,EAASxR,OAAS,GACzCwR,EAASE,QAEbjQ,KAAKkQ,mBAAqB,KAC1B,MAAM1C,EAASxN,KACVmQ,OACGJ,EAAUrB,EAAM,CAAC,KAAMc,EAAYC,EAAoBrN,GAE1D6G,QAAO,SAAUmH,GACd,OAAOA,IAAOA,EAAGC,gBACrB,IAEJ,OAAK7C,EAAOjP,OAGPuQ,GAA0B,IAAlBtB,EAAOjP,QAAiBiP,EAAO,GAAG8C,WAGxC9C,EAAO+C,QAAO,CAACC,EAAMJ,KACxB,MAAMK,EAAYzQ,KAAK0Q,oBAAoBN,GAM3C,OALIvB,GAAW/G,MAAMC,QAAQ0I,GACzBD,EAAOA,EAAKG,OAAOF,GAEnBD,EAAKnN,KAAKoN,GAEPD,CAAI,GACZ,IAVQxQ,KAAK0Q,oBAAoBlD,EAAO,IAHhCsB,EAAO,QAAK1F,CAc3B,EAIAkF,EAASiB,UAAUmB,oBAAsB,SAAUN,GAC/C,MAAMxB,EAAa5O,KAAK0P,eACxB,OAAQd,GACR,IAAK,MAAO,CACR,MAAMD,EAAO7G,MAAMC,QAAQqI,EAAGzB,MACxByB,EAAGzB,KACHL,EAAS0B,YAAYI,EAAGzB,MAK9B,OAJAyB,EAAGQ,QAAUtC,EAASuC,UAAUlC,GAChCyB,EAAGzB,KAA0B,iBAAZyB,EAAGzB,KACdyB,EAAGzB,KACHL,EAASwB,aAAaM,EAAGzB,MACxByB,CACX,CAAE,IAAK,QAAS,IAAK,SAAU,IAAK,iBAChC,OAAOA,EAAGxB,GACd,IAAK,OACD,OAAON,EAASwB,aAAaM,EAAGxB,IACpC,IAAK,UACD,OAAON,EAASuC,UAAUT,EAAGzB,MACjC,QACI,MAAM,IAAIpB,UAAU,uBAE5B,EAEAe,EAASiB,UAAUuB,gBAAkB,SAAUC,EAAY3O,EAAUS,GACjE,GAAIT,EAAU,CACV,MAAM4O,EAAkBhR,KAAK0Q,oBAAoBK,GACjDA,EAAWpC,KAAkC,iBAApBoC,EAAWpC,KAC9BoC,EAAWpC,KACXL,EAASwB,aAAaiB,EAAWpC,MAEvCvM,EAAS4O,EAAiBnO,EAAMkO,EACpC,CACJ,EAcAzC,EAASiB,UAAUY,OAAS,SACxBlQ,EAAMsK,EAAKoE,EAAMO,EAAQ+B,EAAgB7O,EAAUkO,EACnDY,GAIA,IAAIC,EACJ,IAAKlR,EAAK1B,OASN,OARA4S,EAAS,CACLxC,OACAtK,MAAOkG,EACP2E,SACAC,eAAgB8B,EAChBX,cAEJtQ,KAAK8Q,gBAAgBK,EAAQ/O,EAAU,SAChC+O,EAGX,MAAMC,EAAMnR,EAAK,GAAIoR,EAAIpR,EAAKmH,MAAM,GAI9BiI,EAAM,GAMZ,SAASiC,EAAQC,GACTzJ,MAAMC,QAAQwJ,GAIdA,EAAMvJ,SAASwJ,IACXnC,EAAIhM,KAAKmO,EAAE,IAGfnC,EAAIhM,KAAKkO,EAEjB,CACA,IAAoB,iBAARH,GAAoBF,IAAoB3G,GAChD9J,OAAO4M,OAAO9C,EAAK6G,GAEnBE,EAAOtR,KAAKmQ,OAAOkB,EAAG9G,EAAI6G,GAAM/N,EAAKsL,EAAMyC,GAAM7G,EAAK6G,EAAKhP,EACvDkO,SAED,GAAY,MAARc,EACPpR,KAAKyR,MAAMlH,GAAMlB,IACbiI,EAAOtR,KAAKmQ,OACRkB,EAAG9G,EAAIlB,GAAIhG,EAAKsL,EAAMtF,GAAIkB,EAAKlB,EAAGjH,GAAU,GAAM,GACpD,SAEH,GAAY,OAARgP,EAEPE,EACItR,KAAKmQ,OAAOkB,EAAG9G,EAAKoE,EAAMO,EAAQ+B,EAAgB7O,EAC9CkO,IAERtQ,KAAKyR,MAAMlH,GAAMlB,IAGS,iBAAXkB,EAAIlB,IAGXiI,EAAOtR,KAAKmQ,OACRlQ,EAAKmH,QAASmD,EAAIlB,GAAIhG,EAAKsL,EAAMtF,GAAIkB,EAAKlB,EAAGjH,GAAU,GAE/D,QAID,IAAY,MAARgP,EAGP,OADApR,KAAKkQ,oBAAqB,EACnB,CACHvB,KAAMA,EAAKvH,MAAM,GAAI,GACrBnH,KAAMoR,EACNhB,kBAAkB,GAEnB,GAAY,MAARe,EAQP,OAPAD,EAAS,CACLxC,KAAMtL,EAAKsL,EAAMyC,GACjB/M,MAAO4M,EACP/B,SACAC,eAAgB,MAEpBnP,KAAK8Q,gBAAgBK,EAAQ/O,EAAU,YAChC+O,EACJ,GAAY,MAARC,EACPE,EAAOtR,KAAKmQ,OAAOkB,EAAG9G,EAAKoE,EAAM,KAAM,KAAMvM,EAAUkO,SACpD,GAAK,4BAA6B/G,KAAK6H,GAC1CE,EACItR,KAAK0R,OAAON,EAAKC,EAAG9G,EAAKoE,EAAMO,EAAQ+B,EAAgB7O,SAExD,GAA0B,IAAtBgP,EAAIO,QAAQ,MAAa,CAChC,IAAsB,IAAlB3R,KAAK2P,SACL,MAAM,IAAIlO,MAAM,oDAEpB,MAAMmQ,EAAUR,EAAIS,QAAQ,iBAAkB,MAExCC,EAAU,6CAA8CC,KAAKH,GAC/DE,EAGA9R,KAAKyR,MAAMlH,GAAMlB,IACb,MAAM2I,EAAQ,CAACF,EAAO,IAChBG,EAASH,EAAO,GAChBvH,EAAIlB,GAAGyI,EAAO,IACdvH,EAAIlB,GACYrJ,KAAKmQ,OAAO6B,EAAOC,EAAQtD,EAC7CO,EAAQ+B,EAAgB7O,GAAU,GACpB7D,OAAS,GACvB+S,EAAOtR,KAAKmQ,OAAOkB,EAAG9G,EAAIlB,GAAIhG,EAAKsL,EAAMtF,GAAIkB,EACzClB,EAAGjH,GAAU,GACrB,IAGJpC,KAAKyR,MAAMlH,GAAMlB,IACTrJ,KAAKkS,MAAMN,EAASrH,EAAIlB,GAAIA,EAAGsF,EAAMO,EACrC+B,IACAK,EAAOtR,KAAKmQ,OAAOkB,EAAG9G,EAAIlB,GAAIhG,EAAKsL,EAAMtF,GAAIkB,EAAKlB,EAC9CjH,GAAU,GAClB,GAGX,MAAM,GAAe,MAAXgP,EAAI,GAAY,CACvB,IAAsB,IAAlBpR,KAAK2P,SACL,MAAM,IAAIlO,MAAM,mDAKpB6P,EAAOtR,KAAKmQ,OAAOjC,EACflO,KAAKkS,MACDd,EAAK7G,EAAKoE,EAAKwD,IAAI,GACnBxD,EAAKvH,MAAM,GAAI,GAAI8H,EAAQ+B,GAE/BI,GACD9G,EAAKoE,EAAMO,EAAQ+B,EAAgB7O,EAAUkO,GACnD,MAAM,GAAe,MAAXc,EAAI,GAAY,CACvB,IAAIgB,GAAU,EACd,MAAMC,EAAYjB,EAAIhK,MAAM,GAAI,GAChC,OAAQiL,GACR,IAAK,SACI9H,GAAS,CAAC,SAAU,YAAYpB,gBAAgBoB,KACjD6H,GAAU,GAEd,MACJ,IAAK,UAAW,IAAK,SAAU,IAAK,YAAa,IAAK,kBACvC7H,IAAQ8H,IACfD,GAAU,GAEd,MACJ,IAAK,WACGE,OAAOC,SAAShI,IAAUA,EAAM,IAChC6H,GAAU,GAEd,MACJ,IAAK,SACGE,OAAOC,SAAShI,KAChB6H,GAAU,GAEd,MACJ,IAAK,YACkB,iBAAR7H,GAAqB+H,OAAOC,SAAShI,KAC5C6H,GAAU,GAEd,MACJ,IAAK,SACG7H,UAAcA,IAAQ8H,IACtBD,GAAU,GAEd,MACJ,IAAK,QACGtK,MAAMC,QAAQwC,KACd6H,GAAU,GAEd,MACJ,IAAK,QACDA,EAAUpS,KAAK6P,sBACXtF,EAAKoE,EAAMO,EAAQ+B,GAEvB,MACJ,IAAK,OACW,OAAR1G,IACA6H,GAAU,GAEd,MAEJ,QACI,MAAM,IAAI7E,UAAU,sBAAwB8E,GAEhD,GAAID,EAGA,OAFAjB,EAAS,CAACxC,OAAMtK,MAAOkG,EAAK2E,SAAQC,eAAgB8B,GACpDjR,KAAK8Q,gBAAgBK,EAAQ/O,EAAU,SAChC+O,CAGd,MAAM,GAAe,MAAXC,EAAI,IAAc7G,GAAO9J,OAAO4M,OAAO9C,EAAK6G,EAAIhK,MAAM,IAAK,CAClE,MAAMoL,EAAUpB,EAAIhK,MAAM,GAC1BkK,EAAOtR,KAAKmQ,OACRkB,EAAG9G,EAAIiI,GAAUnP,EAAKsL,EAAM6D,GAAUjI,EAAKiI,EAASpQ,EACpDkO,GAAY,GAEnB,MAAM,GAAIc,EAAIjI,SAAS,KAAM,CAC1B,MAAMsJ,EAAQrB,EAAIsB,MAAM,KACxB,IAAK,MAAMC,KAAQF,EACfnB,EAAOtR,KAAKmQ,OACRjC,EAAQyE,EAAMtB,GAAI9G,EAAKoE,EAAMO,EAAQ+B,EAAgB7O,GACrD,GAIZ,MACK8O,GAAmB3G,GAAO9J,OAAO4M,OAAO9C,EAAK6G,IAE9CE,EACItR,KAAKmQ,OAAOkB,EAAG9G,EAAI6G,GAAM/N,EAAKsL,EAAMyC,GAAM7G,EAAK6G,EAAKhP,EAChDkO,GAAY,GAExB,CAKA,GAAItQ,KAAKkQ,mBACL,IAAK,IAAIsB,EAAI,EAAGA,EAAInC,EAAI9Q,OAAQiT,IAAK,CACjC,MAAMoB,EAAOvD,EAAImC,GACjB,GAAIoB,GAAQA,EAAKvC,iBAAkB,CAC/B,MAAMwC,EAAM7S,KAAKmQ,OACbyC,EAAK3S,KAAMsK,EAAKqI,EAAKjE,KAAMO,EAAQ+B,EAAgB7O,EACnDkO,GAEJ,GAAIxI,MAAMC,QAAQ8K,GAAM,CACpBxD,EAAImC,GAAKqB,EAAI,GACb,MAAMC,EAAKD,EAAItU,OACf,IAAK,IAAIwU,EAAK,EAAGA,EAAKD,EAAIC,IAGtBvB,IACAnC,EAAI2D,OAAOxB,EAAG,EAAGqB,EAAIE,GAE7B,MACI1D,EAAImC,GAAKqB,CAEjB,CACJ,CAEJ,OAAOxD,CACX,EAEAf,EAASiB,UAAUkC,MAAQ,SAAUlH,EAAK0I,GACtC,GAAInL,MAAMC,QAAQwC,GAAM,CACpB,MAAM2I,EAAI3I,EAAIhM,OACd,IAAK,IAAI2F,EAAI,EAAGA,EAAIgP,EAAGhP,IACnB+O,EAAE/O,EAET,MAAUqG,GAAsB,iBAARA,GACrB9J,OAAOC,KAAK6J,GAAKvC,SAASqB,IACtB4J,EAAE5J,EAAE,GAGhB,EAEAiF,EAASiB,UAAUmC,OAAS,SACxBN,EAAKnR,EAAMsK,EAAKoE,EAAMO,EAAQ+B,EAAgB7O,GAE9C,IAAK0F,MAAMC,QAAQwC,GACf,OAEJ,MAAM4I,EAAM5I,EAAIhM,OAAQkU,EAAQrB,EAAIsB,MAAM,KACtCU,EAAQX,EAAM,IAAMH,OAAOe,SAASZ,EAAM,KAAQ,EACtD,IAAIvL,EAASuL,EAAM,IAAMH,OAAOe,SAASZ,EAAM,KAAQ,EACnDa,EAAOb,EAAM,IAAMH,OAAOe,SAASZ,EAAM,KAAQU,EACrDjM,EAASA,EAAQ,EAAK7I,KAAKC,IAAI,EAAG4I,EAAQiM,GAAO9U,KAAKkV,IAAIJ,EAAKjM,GAC/DoM,EAAOA,EAAM,EAAKjV,KAAKC,IAAI,EAAGgV,EAAMH,GAAO9U,KAAKkV,IAAIJ,EAAKG,GACzD,MAAMjE,EAAM,GACZ,IAAK,IAAInL,EAAIgD,EAAOhD,EAAIoP,EAAKpP,GAAKkP,EAAM,CACxBpT,KAAKmQ,OACbjC,EAAQhK,EAAGjE,GAAOsK,EAAKoE,EAAMO,EAAQ+B,EAAgB7O,GAAU,GAO/D4F,SAASwJ,IACTnC,EAAIhM,KAAKmO,EAAE,GAEnB,CACA,OAAOnC,CACX,EAEAf,EAASiB,UAAU2C,MAAQ,SACvB9R,EAAMoT,EAAIC,EAAQ9E,EAAMO,EAAQ+B,GAEhCjR,KAAK4P,YAAY8D,kBAAoBzC,EACrCjR,KAAK4P,YAAY+D,UAAYzE,EAC7BlP,KAAK4P,YAAYgE,YAAcH,EAC/BzT,KAAK4P,YAAYiE,QAAU7T,KAAK0O,KAChC1O,KAAK4P,YAAYkE,KAAON,EAExB,MAAMO,EAAe3T,EAAK+I,SAAS,SAC/B4K,IACA/T,KAAK4P,YAAYoE,QAAU1F,EAASwB,aAAanB,EAAKgC,OAAO,CAAC8C,MAGlE,MAAMQ,EAAiBjU,KAAK2P,SAAW,UAAYvP,EACnD,IAAKkO,EAAS4F,MAAMD,GAAiB,CACjC,IAAIE,EAAS/T,EACRgU,WAAW,kBAAmB,qBAC9BA,WAAW,UAAW,aACtBA,WAAW,YAAa,eACxBA,WAAW,QAAS,WACpBA,WAAW,eAAgB,UAIhC,GAHIL,IACAI,EAASA,EAAOC,WAAW,QAAS,YAGlB,SAAlBpU,KAAK2P,WACa,IAAlB3P,KAAK2P,eACavG,IAAlBpJ,KAAK2P,SAELrB,EAAS4F,MAAMD,GAAkB,IAAIjU,KAAKqU,OAAOC,OAAOH,QACrD,GAAsB,WAAlBnU,KAAK2P,SACZrB,EAAS4F,MAAMD,GAAkB,IAAIjU,KAAKuU,GAAGD,OAAOH,QACjD,GACsB,mBAAlBnU,KAAK2P,UACZ3P,KAAK2P,SAASJ,WACd9O,OAAO4M,OAAOrN,KAAK2P,SAASJ,UAAW,mBACzC,CACE,MAAMiF,EAAWxU,KAAK2P,SACtBrB,EAAS4F,MAAMD,GAAkB,IAAIO,EAASL,EACjD,KAAM,IAA6B,mBAAlBnU,KAAK2P,SAKnB,MAAM,IAAIpC,UAAU,4BAA4BvN,KAAK2P,aAJrDrB,EAAS4F,MAAMD,GAAkB,CAC7BQ,gBAAkBzS,GAAYhC,KAAK2P,SAASwE,EAAQnS,GAI5D,CACJ,CAEA,IACI,OAAOsM,EAAS4F,MAAMD,GAAgBQ,gBAAgBzU,KAAK4P,YAC9D,CAAC,MAAO5F,GACL,GAAIhK,KAAKiP,iBACL,OAAO,EAEX,MAAM,IAAIxN,MAAM,aAAeuI,EAAEzI,QAAU,KAAOnB,EACtD,CACJ,EAKAkO,EAAS4F,MAAQ,CAAE,EAMnB5F,EAASwB,aAAe,SAAU4E,GAC9B,MAAMrD,EAAIqD,EAASxB,EAAI7B,EAAE9S,OACzB,IAAIoW,EAAI,IACR,IAAK,IAAIzQ,EAAI,EAAGA,EAAIgP,EAAGhP,IACb,qBAAsBqF,KAAK8H,EAAEnN,MAC/ByQ,GAAM,aAAcpL,KAAK8H,EAAEnN,IAAO,IAAMmN,EAAEnN,GAAK,IAAQ,KAAOmN,EAAEnN,GAAK,MAG7E,OAAOyQ,CACX,EAMArG,EAASuC,UAAY,SAAUD,GAC3B,MAAMS,EAAIT,EAASsC,EAAI7B,EAAE9S,OACzB,IAAIoW,EAAI,GACR,IAAK,IAAIzQ,EAAI,EAAGA,EAAIgP,EAAGhP,IACb,qBAAsBqF,KAAK8H,EAAEnN,MAC/ByQ,GAAK,IAAMtD,EAAEnN,GAAGjG,WACXmW,WAAW,IAAK,MAChBA,WAAW,IAAK,OAG7B,OAAOO,CACX,EAMArG,EAAS0B,YAAc,SAAU/P,GAC7B,MAAMiU,MAACA,GAAS5F,EAChB,GAAI4F,EAAMjU,GACN,OAAOiU,EAAMjU,GAAM0Q,SAEvB,MAAMiE,EAAO,GAoCP7E,EAnCa9P,EAEdmU,WACG,uGACA,QAIHA,WAAW,kCAAkC,SAAUS,EAAIC,GACxD,MAAO,MAAQF,EAAKvR,KAAKyR,GAAM,GAAK,GACvC,IAEAV,WAAW,2BAA2B,SAAUS,EAAI3L,GACjD,MAAO,KAAOA,EACTkL,WAAW,IAAK,OAChBA,WAAW,IAAK,UACjB,IACP,IAEAA,WAAW,IAAK,OAEhBA,WAAW,oCAAqC,KAEhDA,WAAW,MAAO,KAElBA,WAAW,SAAU,KAErBA,WAAW,uBAAuB,SAAUS,EAAIE,GAC7C,MAAO,IAAMA,EAAIrC,MAAM,IAAIsC,KAAK,KAAO,GAC1C,IAEAZ,WAAW,WAAY,QAEvBA,WAAW,eAAgB,IAEJ1B,MAAM,KAAK/R,KAAI,SAAUsU,GACjD,MAAMC,EAAQD,EAAIC,MAAM,WACxB,OAAQA,GAAUA,EAAM,GAAWN,EAAKM,EAAM,IAAjBD,CACjC,IAEA,OADAf,EAAMjU,GAAQ8P,EACPmE,EAAMjU,GAAM0Q,QACvB,EAEArC,EAASiB,UAAU8E,OAAS,CACxBC,ODllBJ,MAIIhU,WAAAA,CAAaL,GACTD,KAAKI,KAAOH,EACZD,KAAKgL,IAAM7C,EAAKnI,KAAKI,KACzB,CAOAqU,eAAAA,CAAiBzS,GAEb,MAAMmT,EAAS1U,OAAOwH,OAAOxH,OAAO2U,OAAO,MAAOpT,GAClD,OAAO8I,EAASC,QAAQ/K,KAAKgL,IAAKmK,EACtC,IE3GJ7G,EAASiB,UAAUgF,GAAK,CACpBD,OA3DJ,MAIIhU,WAAAA,CAAaL,GACTD,KAAKI,KAAOH,CAChB,CAOAwU,eAAAA,CAAiBzS,GACb,IAAI/B,EAAOD,KAAKI,KAChB,MAAMM,EAAOD,OAAOC,KAAKsB,GACnBqT,EAAQ,IA/BK,SAAUC,EAAQC,EAAQC,GACjD,MAAMC,EAAKH,EAAO/W,OAClB,IAAK,IAAI2F,EAAI,EAAGA,EAAIuR,EAAIvR,IAEhBsR,EADSF,EAAOpR,KAIhBqR,EAAOlS,KAAKiS,EAAOtC,OAAO9O,IAAK,GAAG,GAG9C,CAsBQwR,CAAmBhV,EAAM2U,GAAQM,GACE,mBAAjB3T,EAAQ2T,KAE1B,MAAMrL,EAAS5J,EAAKC,KAAKiV,GACd5T,EAAQ4T,KAWnB3V,EARmBoV,EAAM9E,QAAO,CAACsF,EAAGhI,KAChC,IAAIiI,EAAU9T,EAAQ6L,GAAM5P,WAI5B,MAHM,YAAasL,KAAKuM,KACpBA,EAAU,YAAcA,GAErB,OAASjI,EAAO,IAAMiI,EAAU,IAAMD,CAAC,GAC/C,IAEiB5V,EAGd,sBAAuBsJ,KAAKtJ,IAAUS,EAAKyI,SAAS,eACtDlJ,EAAO,6BAA+BA,GAM1CA,EAAOA,EAAK4R,QAAQ,SAAU,IAG9B,MAAMkE,EAAmB9V,EAAK+V,YAAY,KACpC5V,GACoB,IAAtB2V,EACM9V,EAAKmH,MAAM,EAAG2O,EAAmB,GACjC,WACA9V,EAAKmH,MAAM2O,EAAmB,GAC9B,WAAa9V,EAGvB,OAAO,IAAI6N,YAAYpN,EAAMN,EAAtB,IAA+BkK,EAC1C","x_google_ignoreList":[0,1,2]}
\ No newline at end of file
+{"version":3,"file":"index-browser-esm.min.js","sources":["../node_modules/.pnpm/jsep@1.4.0/node_modules/jsep/dist/jsep.js","../node_modules/.pnpm/@jsep-plugin+regex@1.0.4_jsep@1.4.0/node_modules/@jsep-plugin/regex/dist/index.js","../node_modules/.pnpm/@jsep-plugin+assignment@1.3.0_jsep@1.4.0/node_modules/@jsep-plugin/assignment/dist/index.js","../src/Safe-Script.js","../src/jsonpath.js","../src/jsonpath-browser.js"],"sourcesContent":["/**\n * @implements {IHooks}\n */\nclass Hooks {\n\t/**\n\t * @callback HookCallback\n\t * @this {*|Jsep} this\n\t * @param {Jsep} env\n\t * @returns: void\n\t */\n\t/**\n\t * Adds the given callback to the list of callbacks for the given hook.\n\t *\n\t * The callback will be invoked when the hook it is registered for is run.\n\t *\n\t * One callback function can be registered to multiple hooks and the same hook multiple times.\n\t *\n\t * @param {string|object} name The name of the hook, or an object of callbacks keyed by name\n\t * @param {HookCallback|boolean} callback The callback function which is given environment variables.\n\t * @param {?boolean} [first=false] Will add the hook to the top of the list (defaults to the bottom)\n\t * @public\n\t */\n\tadd(name, callback, first) {\n\t\tif (typeof arguments[0] != 'string') {\n\t\t\t// Multiple hook callbacks, keyed by name\n\t\t\tfor (let name in arguments[0]) {\n\t\t\t\tthis.add(name, arguments[0][name], arguments[1]);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\t(Array.isArray(name) ? name : [name]).forEach(function (name) {\n\t\t\t\tthis[name] = this[name] || [];\n\n\t\t\t\tif (callback) {\n\t\t\t\t\tthis[name][first ? 'unshift' : 'push'](callback);\n\t\t\t\t}\n\t\t\t}, this);\n\t\t}\n\t}\n\n\t/**\n\t * Runs a hook invoking all registered callbacks with the given environment variables.\n\t *\n\t * Callbacks will be invoked synchronously and in the order in which they were registered.\n\t *\n\t * @param {string} name The name of the hook.\n\t * @param {Object} env The environment variables of the hook passed to all callbacks registered.\n\t * @public\n\t */\n\trun(name, env) {\n\t\tthis[name] = this[name] || [];\n\t\tthis[name].forEach(function (callback) {\n\t\t\tcallback.call(env && env.context ? env.context : env, env);\n\t\t});\n\t}\n}\n\n/**\n * @implements {IPlugins}\n */\nclass Plugins {\n\tconstructor(jsep) {\n\t\tthis.jsep = jsep;\n\t\tthis.registered = {};\n\t}\n\n\t/**\n\t * @callback PluginSetup\n\t * @this {Jsep} jsep\n\t * @returns: void\n\t */\n\t/**\n\t * Adds the given plugin(s) to the registry\n\t *\n\t * @param {object} plugins\n\t * @param {string} plugins.name The name of the plugin\n\t * @param {PluginSetup} plugins.init The init function\n\t * @public\n\t */\n\tregister(...plugins) {\n\t\tplugins.forEach((plugin) => {\n\t\t\tif (typeof plugin !== 'object' || !plugin.name || !plugin.init) {\n\t\t\t\tthrow new Error('Invalid JSEP plugin format');\n\t\t\t}\n\t\t\tif (this.registered[plugin.name]) {\n\t\t\t\t// already registered. Ignore.\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tplugin.init(this.jsep);\n\t\t\tthis.registered[plugin.name] = plugin;\n\t\t});\n\t}\n}\n\n// JavaScript Expression Parser (JSEP) 1.4.0\n\nclass Jsep {\n\t/**\n\t * @returns {string}\n\t */\n\tstatic get version() {\n\t\t// To be filled in by the template\n\t\treturn '1.4.0';\n\t}\n\n\t/**\n\t * @returns {string}\n\t */\n\tstatic toString() {\n\t\treturn 'JavaScript Expression Parser (JSEP) v' + Jsep.version;\n\t};\n\n\t// ==================== CONFIG ================================\n\t/**\n\t * @method addUnaryOp\n\t * @param {string} op_name The name of the unary op to add\n\t * @returns {Jsep}\n\t */\n\tstatic addUnaryOp(op_name) {\n\t\tJsep.max_unop_len = Math.max(op_name.length, Jsep.max_unop_len);\n\t\tJsep.unary_ops[op_name] = 1;\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method jsep.addBinaryOp\n\t * @param {string} op_name The name of the binary op to add\n\t * @param {number} precedence The precedence of the binary op (can be a float). Higher number = higher precedence\n\t * @param {boolean} [isRightAssociative=false] whether operator is right-associative\n\t * @returns {Jsep}\n\t */\n\tstatic addBinaryOp(op_name, precedence, isRightAssociative) {\n\t\tJsep.max_binop_len = Math.max(op_name.length, Jsep.max_binop_len);\n\t\tJsep.binary_ops[op_name] = precedence;\n\t\tif (isRightAssociative) {\n\t\t\tJsep.right_associative.add(op_name);\n\t\t}\n\t\telse {\n\t\t\tJsep.right_associative.delete(op_name);\n\t\t}\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method addIdentifierChar\n\t * @param {string} char The additional character to treat as a valid part of an identifier\n\t * @returns {Jsep}\n\t */\n\tstatic addIdentifierChar(char) {\n\t\tJsep.additional_identifier_chars.add(char);\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method addLiteral\n\t * @param {string} literal_name The name of the literal to add\n\t * @param {*} literal_value The value of the literal\n\t * @returns {Jsep}\n\t */\n\tstatic addLiteral(literal_name, literal_value) {\n\t\tJsep.literals[literal_name] = literal_value;\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method removeUnaryOp\n\t * @param {string} op_name The name of the unary op to remove\n\t * @returns {Jsep}\n\t */\n\tstatic removeUnaryOp(op_name) {\n\t\tdelete Jsep.unary_ops[op_name];\n\t\tif (op_name.length === Jsep.max_unop_len) {\n\t\t\tJsep.max_unop_len = Jsep.getMaxKeyLen(Jsep.unary_ops);\n\t\t}\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method removeAllUnaryOps\n\t * @returns {Jsep}\n\t */\n\tstatic removeAllUnaryOps() {\n\t\tJsep.unary_ops = {};\n\t\tJsep.max_unop_len = 0;\n\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method removeIdentifierChar\n\t * @param {string} char The additional character to stop treating as a valid part of an identifier\n\t * @returns {Jsep}\n\t */\n\tstatic removeIdentifierChar(char) {\n\t\tJsep.additional_identifier_chars.delete(char);\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method removeBinaryOp\n\t * @param {string} op_name The name of the binary op to remove\n\t * @returns {Jsep}\n\t */\n\tstatic removeBinaryOp(op_name) {\n\t\tdelete Jsep.binary_ops[op_name];\n\n\t\tif (op_name.length === Jsep.max_binop_len) {\n\t\t\tJsep.max_binop_len = Jsep.getMaxKeyLen(Jsep.binary_ops);\n\t\t}\n\t\tJsep.right_associative.delete(op_name);\n\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method removeAllBinaryOps\n\t * @returns {Jsep}\n\t */\n\tstatic removeAllBinaryOps() {\n\t\tJsep.binary_ops = {};\n\t\tJsep.max_binop_len = 0;\n\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method removeLiteral\n\t * @param {string} literal_name The name of the literal to remove\n\t * @returns {Jsep}\n\t */\n\tstatic removeLiteral(literal_name) {\n\t\tdelete Jsep.literals[literal_name];\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method removeAllLiterals\n\t * @returns {Jsep}\n\t */\n\tstatic removeAllLiterals() {\n\t\tJsep.literals = {};\n\n\t\treturn Jsep;\n\t}\n\t// ==================== END CONFIG ============================\n\n\n\t/**\n\t * @returns {string}\n\t */\n\tget char() {\n\t\treturn this.expr.charAt(this.index);\n\t}\n\n\t/**\n\t * @returns {number}\n\t */\n\tget code() {\n\t\treturn this.expr.charCodeAt(this.index);\n\t};\n\n\n\t/**\n\t * @param {string} expr a string with the passed in express\n\t * @returns Jsep\n\t */\n\tconstructor(expr) {\n\t\t// `index` stores the character number we are currently at\n\t\t// All of the gobbles below will modify `index` as we move along\n\t\tthis.expr = expr;\n\t\tthis.index = 0;\n\t}\n\n\t/**\n\t * static top-level parser\n\t * @returns {jsep.Expression}\n\t */\n\tstatic parse(expr) {\n\t\treturn (new Jsep(expr)).parse();\n\t}\n\n\t/**\n\t * Get the longest key length of any object\n\t * @param {object} obj\n\t * @returns {number}\n\t */\n\tstatic getMaxKeyLen(obj) {\n\t\treturn Math.max(0, ...Object.keys(obj).map(k => k.length));\n\t}\n\n\t/**\n\t * `ch` is a character code in the next three functions\n\t * @param {number} ch\n\t * @returns {boolean}\n\t */\n\tstatic isDecimalDigit(ch) {\n\t\treturn (ch >= 48 && ch <= 57); // 0...9\n\t}\n\n\t/**\n\t * Returns the precedence of a binary operator or `0` if it isn't a binary operator. Can be float.\n\t * @param {string} op_val\n\t * @returns {number}\n\t */\n\tstatic binaryPrecedence(op_val) {\n\t\treturn Jsep.binary_ops[op_val] || 0;\n\t}\n\n\t/**\n\t * Looks for start of identifier\n\t * @param {number} ch\n\t * @returns {boolean}\n\t */\n\tstatic isIdentifierStart(ch) {\n\t\treturn (ch >= 65 && ch <= 90) || // A...Z\n\t\t\t(ch >= 97 && ch <= 122) || // a...z\n\t\t\t(ch >= 128 && !Jsep.binary_ops[String.fromCharCode(ch)]) || // any non-ASCII that is not an operator\n\t\t\t(Jsep.additional_identifier_chars.has(String.fromCharCode(ch))); // additional characters\n\t}\n\n\t/**\n\t * @param {number} ch\n\t * @returns {boolean}\n\t */\n\tstatic isIdentifierPart(ch) {\n\t\treturn Jsep.isIdentifierStart(ch) || Jsep.isDecimalDigit(ch);\n\t}\n\n\t/**\n\t * throw error at index of the expression\n\t * @param {string} message\n\t * @throws\n\t */\n\tthrowError(message) {\n\t\tconst error = new Error(message + ' at character ' + this.index);\n\t\terror.index = this.index;\n\t\terror.description = message;\n\t\tthrow error;\n\t}\n\n\t/**\n\t * Run a given hook\n\t * @param {string} name\n\t * @param {jsep.Expression|false} [node]\n\t * @returns {?jsep.Expression}\n\t */\n\trunHook(name, node) {\n\t\tif (Jsep.hooks[name]) {\n\t\t\tconst env = { context: this, node };\n\t\t\tJsep.hooks.run(name, env);\n\t\t\treturn env.node;\n\t\t}\n\t\treturn node;\n\t}\n\n\t/**\n\t * Runs a given hook until one returns a node\n\t * @param {string} name\n\t * @returns {?jsep.Expression}\n\t */\n\tsearchHook(name) {\n\t\tif (Jsep.hooks[name]) {\n\t\t\tconst env = { context: this };\n\t\t\tJsep.hooks[name].find(function (callback) {\n\t\t\t\tcallback.call(env.context, env);\n\t\t\t\treturn env.node;\n\t\t\t});\n\t\t\treturn env.node;\n\t\t}\n\t}\n\n\t/**\n\t * Push `index` up to the next non-space character\n\t */\n\tgobbleSpaces() {\n\t\tlet ch = this.code;\n\t\t// Whitespace\n\t\twhile (ch === Jsep.SPACE_CODE\n\t\t|| ch === Jsep.TAB_CODE\n\t\t|| ch === Jsep.LF_CODE\n\t\t|| ch === Jsep.CR_CODE) {\n\t\t\tch = this.expr.charCodeAt(++this.index);\n\t\t}\n\t\tthis.runHook('gobble-spaces');\n\t}\n\n\t/**\n\t * Top-level method to parse all expressions and returns compound or single node\n\t * @returns {jsep.Expression}\n\t */\n\tparse() {\n\t\tthis.runHook('before-all');\n\t\tconst nodes = this.gobbleExpressions();\n\n\t\t// If there's only one expression just try returning the expression\n\t\tconst node = nodes.length === 1\n\t\t ? nodes[0]\n\t\t\t: {\n\t\t\t\ttype: Jsep.COMPOUND,\n\t\t\t\tbody: nodes\n\t\t\t};\n\t\treturn this.runHook('after-all', node);\n\t}\n\n\t/**\n\t * top-level parser (but can be reused within as well)\n\t * @param {number} [untilICode]\n\t * @returns {jsep.Expression[]}\n\t */\n\tgobbleExpressions(untilICode) {\n\t\tlet nodes = [], ch_i, node;\n\n\t\twhile (this.index < this.expr.length) {\n\t\t\tch_i = this.code;\n\n\t\t\t// Expressions can be separated by semicolons, commas, or just inferred without any\n\t\t\t// separators\n\t\t\tif (ch_i === Jsep.SEMCOL_CODE || ch_i === Jsep.COMMA_CODE) {\n\t\t\t\tthis.index++; // ignore separators\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Try to gobble each expression individually\n\t\t\t\tif (node = this.gobbleExpression()) {\n\t\t\t\t\tnodes.push(node);\n\t\t\t\t\t// If we weren't able to find a binary expression and are out of room, then\n\t\t\t\t\t// the expression passed in probably has too much\n\t\t\t\t}\n\t\t\t\telse if (this.index < this.expr.length) {\n\t\t\t\t\tif (ch_i === untilICode) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tthis.throwError('Unexpected \"' + this.char + '\"');\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn nodes;\n\t}\n\n\t/**\n\t * The main parsing function.\n\t * @returns {?jsep.Expression}\n\t */\n\tgobbleExpression() {\n\t\tconst node = this.searchHook('gobble-expression') || this.gobbleBinaryExpression();\n\t\tthis.gobbleSpaces();\n\n\t\treturn this.runHook('after-expression', node);\n\t}\n\n\t/**\n\t * Search for the operation portion of the string (e.g. `+`, `===`)\n\t * Start by taking the longest possible binary operations (3 characters: `===`, `!==`, `>>>`)\n\t * and move down from 3 to 2 to 1 character until a matching binary operation is found\n\t * then, return that binary operation\n\t * @returns {string|boolean}\n\t */\n\tgobbleBinaryOp() {\n\t\tthis.gobbleSpaces();\n\t\tlet to_check = this.expr.substr(this.index, Jsep.max_binop_len);\n\t\tlet tc_len = to_check.length;\n\n\t\twhile (tc_len > 0) {\n\t\t\t// Don't accept a binary op when it is an identifier.\n\t\t\t// Binary ops that start with a identifier-valid character must be followed\n\t\t\t// by a non identifier-part valid character\n\t\t\tif (Jsep.binary_ops.hasOwnProperty(to_check) && (\n\t\t\t\t!Jsep.isIdentifierStart(this.code) ||\n\t\t\t\t(this.index + to_check.length < this.expr.length && !Jsep.isIdentifierPart(this.expr.charCodeAt(this.index + to_check.length)))\n\t\t\t)) {\n\t\t\t\tthis.index += tc_len;\n\t\t\t\treturn to_check;\n\t\t\t}\n\t\t\tto_check = to_check.substr(0, --tc_len);\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * This function is responsible for gobbling an individual expression,\n\t * e.g. `1`, `1+2`, `a+(b*2)-Math.sqrt(2)`\n\t * @returns {?jsep.BinaryExpression}\n\t */\n\tgobbleBinaryExpression() {\n\t\tlet node, biop, prec, stack, biop_info, left, right, i, cur_biop;\n\n\t\t// First, try to get the leftmost thing\n\t\t// Then, check to see if there's a binary operator operating on that leftmost thing\n\t\t// Don't gobbleBinaryOp without a left-hand-side\n\t\tleft = this.gobbleToken();\n\t\tif (!left) {\n\t\t\treturn left;\n\t\t}\n\t\tbiop = this.gobbleBinaryOp();\n\n\t\t// If there wasn't a binary operator, just return the leftmost node\n\t\tif (!biop) {\n\t\t\treturn left;\n\t\t}\n\n\t\t// Otherwise, we need to start a stack to properly place the binary operations in their\n\t\t// precedence structure\n\t\tbiop_info = { value: biop, prec: Jsep.binaryPrecedence(biop), right_a: Jsep.right_associative.has(biop) };\n\n\t\tright = this.gobbleToken();\n\n\t\tif (!right) {\n\t\t\tthis.throwError(\"Expected expression after \" + biop);\n\t\t}\n\n\t\tstack = [left, biop_info, right];\n\n\t\t// Properly deal with precedence using [recursive descent](http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm)\n\t\twhile ((biop = this.gobbleBinaryOp())) {\n\t\t\tprec = Jsep.binaryPrecedence(biop);\n\n\t\t\tif (prec === 0) {\n\t\t\t\tthis.index -= biop.length;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tbiop_info = { value: biop, prec, right_a: Jsep.right_associative.has(biop) };\n\n\t\t\tcur_biop = biop;\n\n\t\t\t// Reduce: make a binary expression from the three topmost entries.\n\t\t\tconst comparePrev = prev => biop_info.right_a && prev.right_a\n\t\t\t\t? prec > prev.prec\n\t\t\t\t: prec <= prev.prec;\n\t\t\twhile ((stack.length > 2) && comparePrev(stack[stack.length - 2])) {\n\t\t\t\tright = stack.pop();\n\t\t\t\tbiop = stack.pop().value;\n\t\t\t\tleft = stack.pop();\n\t\t\t\tnode = {\n\t\t\t\t\ttype: Jsep.BINARY_EXP,\n\t\t\t\t\toperator: biop,\n\t\t\t\t\tleft,\n\t\t\t\t\tright\n\t\t\t\t};\n\t\t\t\tstack.push(node);\n\t\t\t}\n\n\t\t\tnode = this.gobbleToken();\n\n\t\t\tif (!node) {\n\t\t\t\tthis.throwError(\"Expected expression after \" + cur_biop);\n\t\t\t}\n\n\t\t\tstack.push(biop_info, node);\n\t\t}\n\n\t\ti = stack.length - 1;\n\t\tnode = stack[i];\n\n\t\twhile (i > 1) {\n\t\t\tnode = {\n\t\t\t\ttype: Jsep.BINARY_EXP,\n\t\t\t\toperator: stack[i - 1].value,\n\t\t\t\tleft: stack[i - 2],\n\t\t\t\tright: node\n\t\t\t};\n\t\t\ti -= 2;\n\t\t}\n\n\t\treturn node;\n\t}\n\n\t/**\n\t * An individual part of a binary expression:\n\t * e.g. `foo.bar(baz)`, `1`, `\"abc\"`, `(a % 2)` (because it's in parenthesis)\n\t * @returns {boolean|jsep.Expression}\n\t */\n\tgobbleToken() {\n\t\tlet ch, to_check, tc_len, node;\n\n\t\tthis.gobbleSpaces();\n\t\tnode = this.searchHook('gobble-token');\n\t\tif (node) {\n\t\t\treturn this.runHook('after-token', node);\n\t\t}\n\n\t\tch = this.code;\n\n\t\tif (Jsep.isDecimalDigit(ch) || ch === Jsep.PERIOD_CODE) {\n\t\t\t// Char code 46 is a dot `.` which can start off a numeric literal\n\t\t\treturn this.gobbleNumericLiteral();\n\t\t}\n\n\t\tif (ch === Jsep.SQUOTE_CODE || ch === Jsep.DQUOTE_CODE) {\n\t\t\t// Single or double quotes\n\t\t\tnode = this.gobbleStringLiteral();\n\t\t}\n\t\telse if (ch === Jsep.OBRACK_CODE) {\n\t\t\tnode = this.gobbleArray();\n\t\t}\n\t\telse {\n\t\t\tto_check = this.expr.substr(this.index, Jsep.max_unop_len);\n\t\t\ttc_len = to_check.length;\n\n\t\t\twhile (tc_len > 0) {\n\t\t\t\t// Don't accept an unary op when it is an identifier.\n\t\t\t\t// Unary ops that start with a identifier-valid character must be followed\n\t\t\t\t// by a non identifier-part valid character\n\t\t\t\tif (Jsep.unary_ops.hasOwnProperty(to_check) && (\n\t\t\t\t\t!Jsep.isIdentifierStart(this.code) ||\n\t\t\t\t\t(this.index + to_check.length < this.expr.length && !Jsep.isIdentifierPart(this.expr.charCodeAt(this.index + to_check.length)))\n\t\t\t\t)) {\n\t\t\t\t\tthis.index += tc_len;\n\t\t\t\t\tconst argument = this.gobbleToken();\n\t\t\t\t\tif (!argument) {\n\t\t\t\t\t\tthis.throwError('missing unaryOp argument');\n\t\t\t\t\t}\n\t\t\t\t\treturn this.runHook('after-token', {\n\t\t\t\t\t\ttype: Jsep.UNARY_EXP,\n\t\t\t\t\t\toperator: to_check,\n\t\t\t\t\t\targument,\n\t\t\t\t\t\tprefix: true\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tto_check = to_check.substr(0, --tc_len);\n\t\t\t}\n\n\t\t\tif (Jsep.isIdentifierStart(ch)) {\n\t\t\t\tnode = this.gobbleIdentifier();\n\t\t\t\tif (Jsep.literals.hasOwnProperty(node.name)) {\n\t\t\t\t\tnode = {\n\t\t\t\t\t\ttype: Jsep.LITERAL,\n\t\t\t\t\t\tvalue: Jsep.literals[node.name],\n\t\t\t\t\t\traw: node.name,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\telse if (node.name === Jsep.this_str) {\n\t\t\t\t\tnode = { type: Jsep.THIS_EXP };\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (ch === Jsep.OPAREN_CODE) { // open parenthesis\n\t\t\t\tnode = this.gobbleGroup();\n\t\t\t}\n\t\t}\n\n\t\tif (!node) {\n\t\t\treturn this.runHook('after-token', false);\n\t\t}\n\n\t\tnode = this.gobbleTokenProperty(node);\n\t\treturn this.runHook('after-token', node);\n\t}\n\n\t/**\n\t * Gobble properties of of identifiers/strings/arrays/groups.\n\t * e.g. `foo`, `bar.baz`, `foo['bar'].baz`\n\t * It also gobbles function calls:\n\t * e.g. `Math.acos(obj.angle)`\n\t * @param {jsep.Expression} node\n\t * @returns {jsep.Expression}\n\t */\n\tgobbleTokenProperty(node) {\n\t\tthis.gobbleSpaces();\n\n\t\tlet ch = this.code;\n\t\twhile (ch === Jsep.PERIOD_CODE || ch === Jsep.OBRACK_CODE || ch === Jsep.OPAREN_CODE || ch === Jsep.QUMARK_CODE) {\n\t\t\tlet optional;\n\t\t\tif (ch === Jsep.QUMARK_CODE) {\n\t\t\t\tif (this.expr.charCodeAt(this.index + 1) !== Jsep.PERIOD_CODE) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\toptional = true;\n\t\t\t\tthis.index += 2;\n\t\t\t\tthis.gobbleSpaces();\n\t\t\t\tch = this.code;\n\t\t\t}\n\t\t\tthis.index++;\n\n\t\t\tif (ch === Jsep.OBRACK_CODE) {\n\t\t\t\tnode = {\n\t\t\t\t\ttype: Jsep.MEMBER_EXP,\n\t\t\t\t\tcomputed: true,\n\t\t\t\t\tobject: node,\n\t\t\t\t\tproperty: this.gobbleExpression()\n\t\t\t\t};\n\t\t\t\tif (!node.property) {\n\t\t\t\t\tthis.throwError('Unexpected \"' + this.char + '\"');\n\t\t\t\t}\n\t\t\t\tthis.gobbleSpaces();\n\t\t\t\tch = this.code;\n\t\t\t\tif (ch !== Jsep.CBRACK_CODE) {\n\t\t\t\t\tthis.throwError('Unclosed [');\n\t\t\t\t}\n\t\t\t\tthis.index++;\n\t\t\t}\n\t\t\telse if (ch === Jsep.OPAREN_CODE) {\n\t\t\t\t// A function call is being made; gobble all the arguments\n\t\t\t\tnode = {\n\t\t\t\t\ttype: Jsep.CALL_EXP,\n\t\t\t\t\t'arguments': this.gobbleArguments(Jsep.CPAREN_CODE),\n\t\t\t\t\tcallee: node\n\t\t\t\t};\n\t\t\t}\n\t\t\telse if (ch === Jsep.PERIOD_CODE || optional) {\n\t\t\t\tif (optional) {\n\t\t\t\t\tthis.index--;\n\t\t\t\t}\n\t\t\t\tthis.gobbleSpaces();\n\t\t\t\tnode = {\n\t\t\t\t\ttype: Jsep.MEMBER_EXP,\n\t\t\t\t\tcomputed: false,\n\t\t\t\t\tobject: node,\n\t\t\t\t\tproperty: this.gobbleIdentifier(),\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (optional) {\n\t\t\t\tnode.optional = true;\n\t\t\t} // else leave undefined for compatibility with esprima\n\n\t\t\tthis.gobbleSpaces();\n\t\t\tch = this.code;\n\t\t}\n\n\t\treturn node;\n\t}\n\n\t/**\n\t * Parse simple numeric literals: `12`, `3.4`, `.5`. Do this by using a string to\n\t * keep track of everything in the numeric literal and then calling `parseFloat` on that string\n\t * @returns {jsep.Literal}\n\t */\n\tgobbleNumericLiteral() {\n\t\tlet number = '', ch, chCode;\n\n\t\twhile (Jsep.isDecimalDigit(this.code)) {\n\t\t\tnumber += this.expr.charAt(this.index++);\n\t\t}\n\n\t\tif (this.code === Jsep.PERIOD_CODE) { // can start with a decimal marker\n\t\t\tnumber += this.expr.charAt(this.index++);\n\n\t\t\twhile (Jsep.isDecimalDigit(this.code)) {\n\t\t\t\tnumber += this.expr.charAt(this.index++);\n\t\t\t}\n\t\t}\n\n\t\tch = this.char;\n\n\t\tif (ch === 'e' || ch === 'E') { // exponent marker\n\t\t\tnumber += this.expr.charAt(this.index++);\n\t\t\tch = this.char;\n\n\t\t\tif (ch === '+' || ch === '-') { // exponent sign\n\t\t\t\tnumber += this.expr.charAt(this.index++);\n\t\t\t}\n\n\t\t\twhile (Jsep.isDecimalDigit(this.code)) { // exponent itself\n\t\t\t\tnumber += this.expr.charAt(this.index++);\n\t\t\t}\n\n\t\t\tif (!Jsep.isDecimalDigit(this.expr.charCodeAt(this.index - 1)) ) {\n\t\t\t\tthis.throwError('Expected exponent (' + number + this.char + ')');\n\t\t\t}\n\t\t}\n\n\t\tchCode = this.code;\n\n\t\t// Check to make sure this isn't a variable name that start with a number (123abc)\n\t\tif (Jsep.isIdentifierStart(chCode)) {\n\t\t\tthis.throwError('Variable names cannot start with a number (' +\n\t\t\t\tnumber + this.char + ')');\n\t\t}\n\t\telse if (chCode === Jsep.PERIOD_CODE || (number.length === 1 && number.charCodeAt(0) === Jsep.PERIOD_CODE)) {\n\t\t\tthis.throwError('Unexpected period');\n\t\t}\n\n\t\treturn {\n\t\t\ttype: Jsep.LITERAL,\n\t\t\tvalue: parseFloat(number),\n\t\t\traw: number\n\t\t};\n\t}\n\n\t/**\n\t * Parses a string literal, staring with single or double quotes with basic support for escape codes\n\t * e.g. `\"hello world\"`, `'this is\\nJSEP'`\n\t * @returns {jsep.Literal}\n\t */\n\tgobbleStringLiteral() {\n\t\tlet str = '';\n\t\tconst startIndex = this.index;\n\t\tconst quote = this.expr.charAt(this.index++);\n\t\tlet closed = false;\n\n\t\twhile (this.index < this.expr.length) {\n\t\t\tlet ch = this.expr.charAt(this.index++);\n\n\t\t\tif (ch === quote) {\n\t\t\t\tclosed = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\telse if (ch === '\\\\') {\n\t\t\t\t// Check for all of the common escape codes\n\t\t\t\tch = this.expr.charAt(this.index++);\n\n\t\t\t\tswitch (ch) {\n\t\t\t\t\tcase 'n': str += '\\n'; break;\n\t\t\t\t\tcase 'r': str += '\\r'; break;\n\t\t\t\t\tcase 't': str += '\\t'; break;\n\t\t\t\t\tcase 'b': str += '\\b'; break;\n\t\t\t\t\tcase 'f': str += '\\f'; break;\n\t\t\t\t\tcase 'v': str += '\\x0B'; break;\n\t\t\t\t\tdefault : str += ch;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tstr += ch;\n\t\t\t}\n\t\t}\n\n\t\tif (!closed) {\n\t\t\tthis.throwError('Unclosed quote after \"' + str + '\"');\n\t\t}\n\n\t\treturn {\n\t\t\ttype: Jsep.LITERAL,\n\t\t\tvalue: str,\n\t\t\traw: this.expr.substring(startIndex, this.index),\n\t\t};\n\t}\n\n\t/**\n\t * Gobbles only identifiers\n\t * e.g.: `foo`, `_value`, `$x1`\n\t * Also, this function checks if that identifier is a literal:\n\t * (e.g. `true`, `false`, `null`) or `this`\n\t * @returns {jsep.Identifier}\n\t */\n\tgobbleIdentifier() {\n\t\tlet ch = this.code, start = this.index;\n\n\t\tif (Jsep.isIdentifierStart(ch)) {\n\t\t\tthis.index++;\n\t\t}\n\t\telse {\n\t\t\tthis.throwError('Unexpected ' + this.char);\n\t\t}\n\n\t\twhile (this.index < this.expr.length) {\n\t\t\tch = this.code;\n\n\t\t\tif (Jsep.isIdentifierPart(ch)) {\n\t\t\t\tthis.index++;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\ttype: Jsep.IDENTIFIER,\n\t\t\tname: this.expr.slice(start, this.index),\n\t\t};\n\t}\n\n\t/**\n\t * Gobbles a list of arguments within the context of a function call\n\t * or array literal. This function also assumes that the opening character\n\t * `(` or `[` has already been gobbled, and gobbles expressions and commas\n\t * until the terminator character `)` or `]` is encountered.\n\t * e.g. `foo(bar, baz)`, `my_func()`, or `[bar, baz]`\n\t * @param {number} termination\n\t * @returns {jsep.Expression[]}\n\t */\n\tgobbleArguments(termination) {\n\t\tconst args = [];\n\t\tlet closed = false;\n\t\tlet separator_count = 0;\n\n\t\twhile (this.index < this.expr.length) {\n\t\t\tthis.gobbleSpaces();\n\t\t\tlet ch_i = this.code;\n\n\t\t\tif (ch_i === termination) { // done parsing\n\t\t\t\tclosed = true;\n\t\t\t\tthis.index++;\n\n\t\t\t\tif (termination === Jsep.CPAREN_CODE && separator_count && separator_count >= args.length){\n\t\t\t\t\tthis.throwError('Unexpected token ' + String.fromCharCode(termination));\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\telse if (ch_i === Jsep.COMMA_CODE) { // between expressions\n\t\t\t\tthis.index++;\n\t\t\t\tseparator_count++;\n\n\t\t\t\tif (separator_count !== args.length) { // missing argument\n\t\t\t\t\tif (termination === Jsep.CPAREN_CODE) {\n\t\t\t\t\t\tthis.throwError('Unexpected token ,');\n\t\t\t\t\t}\n\t\t\t\t\telse if (termination === Jsep.CBRACK_CODE) {\n\t\t\t\t\t\tfor (let arg = args.length; arg < separator_count; arg++) {\n\t\t\t\t\t\t\targs.push(null);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (args.length !== separator_count && separator_count !== 0) {\n\t\t\t\t// NOTE: `&& separator_count !== 0` allows for either all commas, or all spaces as arguments\n\t\t\t\tthis.throwError('Expected comma');\n\t\t\t}\n\t\t\telse {\n\t\t\t\tconst node = this.gobbleExpression();\n\n\t\t\t\tif (!node || node.type === Jsep.COMPOUND) {\n\t\t\t\t\tthis.throwError('Expected comma');\n\t\t\t\t}\n\n\t\t\t\targs.push(node);\n\t\t\t}\n\t\t}\n\n\t\tif (!closed) {\n\t\t\tthis.throwError('Expected ' + String.fromCharCode(termination));\n\t\t}\n\n\t\treturn args;\n\t}\n\n\t/**\n\t * Responsible for parsing a group of things within parentheses `()`\n\t * that have no identifier in front (so not a function call)\n\t * This function assumes that it needs to gobble the opening parenthesis\n\t * and then tries to gobble everything within that parenthesis, assuming\n\t * that the next thing it should see is the close parenthesis. If not,\n\t * then the expression probably doesn't have a `)`\n\t * @returns {boolean|jsep.Expression}\n\t */\n\tgobbleGroup() {\n\t\tthis.index++;\n\t\tlet nodes = this.gobbleExpressions(Jsep.CPAREN_CODE);\n\t\tif (this.code === Jsep.CPAREN_CODE) {\n\t\t\tthis.index++;\n\t\t\tif (nodes.length === 1) {\n\t\t\t\treturn nodes[0];\n\t\t\t}\n\t\t\telse if (!nodes.length) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn {\n\t\t\t\t\ttype: Jsep.SEQUENCE_EXP,\n\t\t\t\t\texpressions: nodes,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tthis.throwError('Unclosed (');\n\t\t}\n\t}\n\n\t/**\n\t * Responsible for parsing Array literals `[1, 2, 3]`\n\t * This function assumes that it needs to gobble the opening bracket\n\t * and then tries to gobble the expressions as arguments.\n\t * @returns {jsep.ArrayExpression}\n\t */\n\tgobbleArray() {\n\t\tthis.index++;\n\n\t\treturn {\n\t\t\ttype: Jsep.ARRAY_EXP,\n\t\t\telements: this.gobbleArguments(Jsep.CBRACK_CODE)\n\t\t};\n\t}\n}\n\n// Static fields:\nconst hooks = new Hooks();\nObject.assign(Jsep, {\n\thooks,\n\tplugins: new Plugins(Jsep),\n\n\t// Node Types\n\t// ----------\n\t// This is the full set of types that any JSEP node can be.\n\t// Store them here to save space when minified\n\tCOMPOUND: 'Compound',\n\tSEQUENCE_EXP: 'SequenceExpression',\n\tIDENTIFIER: 'Identifier',\n\tMEMBER_EXP: 'MemberExpression',\n\tLITERAL: 'Literal',\n\tTHIS_EXP: 'ThisExpression',\n\tCALL_EXP: 'CallExpression',\n\tUNARY_EXP: 'UnaryExpression',\n\tBINARY_EXP: 'BinaryExpression',\n\tARRAY_EXP: 'ArrayExpression',\n\n\tTAB_CODE: 9,\n\tLF_CODE: 10,\n\tCR_CODE: 13,\n\tSPACE_CODE: 32,\n\tPERIOD_CODE: 46, // '.'\n\tCOMMA_CODE: 44, // ','\n\tSQUOTE_CODE: 39, // single quote\n\tDQUOTE_CODE: 34, // double quotes\n\tOPAREN_CODE: 40, // (\n\tCPAREN_CODE: 41, // )\n\tOBRACK_CODE: 91, // [\n\tCBRACK_CODE: 93, // ]\n\tQUMARK_CODE: 63, // ?\n\tSEMCOL_CODE: 59, // ;\n\tCOLON_CODE: 58, // :\n\n\n\t// Operations\n\t// ----------\n\t// Use a quickly-accessible map to store all of the unary operators\n\t// Values are set to `1` (it really doesn't matter)\n\tunary_ops: {\n\t\t'-': 1,\n\t\t'!': 1,\n\t\t'~': 1,\n\t\t'+': 1\n\t},\n\n\t// Also use a map for the binary operations but set their values to their\n\t// binary precedence for quick reference (higher number = higher precedence)\n\t// see [Order of operations](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence)\n\tbinary_ops: {\n\t\t'||': 1, '??': 1,\n\t\t'&&': 2, '|': 3, '^': 4, '&': 5,\n\t\t'==': 6, '!=': 6, '===': 6, '!==': 6,\n\t\t'<': 7, '>': 7, '<=': 7, '>=': 7,\n\t\t'<<': 8, '>>': 8, '>>>': 8,\n\t\t'+': 9, '-': 9,\n\t\t'*': 10, '/': 10, '%': 10,\n\t\t'**': 11,\n\t},\n\n\t// sets specific binary_ops as right-associative\n\tright_associative: new Set(['**']),\n\n\t// Additional valid identifier chars, apart from a-z, A-Z and 0-9 (except on the starting char)\n\tadditional_identifier_chars: new Set(['$', '_']),\n\n\t// Literals\n\t// ----------\n\t// Store the values to return for the various literals we may encounter\n\tliterals: {\n\t\t'true': true,\n\t\t'false': false,\n\t\t'null': null\n\t},\n\n\t// Except for `this`, which is special. This could be changed to something like `'self'` as well\n\tthis_str: 'this',\n});\nJsep.max_unop_len = Jsep.getMaxKeyLen(Jsep.unary_ops);\nJsep.max_binop_len = Jsep.getMaxKeyLen(Jsep.binary_ops);\n\n// Backward Compatibility:\nconst jsep = expr => (new Jsep(expr)).parse();\nconst stdClassProps = Object.getOwnPropertyNames(class Test{});\nObject.getOwnPropertyNames(Jsep)\n\t.filter(prop => !stdClassProps.includes(prop) && jsep[prop] === undefined)\n\t.forEach((m) => {\n\t\tjsep[m] = Jsep[m];\n\t});\njsep.Jsep = Jsep; // allows for const { Jsep } = require('jsep');\n\nconst CONDITIONAL_EXP = 'ConditionalExpression';\n\nvar ternary = {\n\tname: 'ternary',\n\n\tinit(jsep) {\n\t\t// Ternary expression: test ? consequent : alternate\n\t\tjsep.hooks.add('after-expression', function gobbleTernary(env) {\n\t\t\tif (env.node && this.code === jsep.QUMARK_CODE) {\n\t\t\t\tthis.index++;\n\t\t\t\tconst test = env.node;\n\t\t\t\tconst consequent = this.gobbleExpression();\n\n\t\t\t\tif (!consequent) {\n\t\t\t\t\tthis.throwError('Expected expression');\n\t\t\t\t}\n\n\t\t\t\tthis.gobbleSpaces();\n\n\t\t\t\tif (this.code === jsep.COLON_CODE) {\n\t\t\t\t\tthis.index++;\n\t\t\t\t\tconst alternate = this.gobbleExpression();\n\n\t\t\t\t\tif (!alternate) {\n\t\t\t\t\t\tthis.throwError('Expected expression');\n\t\t\t\t\t}\n\t\t\t\t\tenv.node = {\n\t\t\t\t\t\ttype: CONDITIONAL_EXP,\n\t\t\t\t\t\ttest,\n\t\t\t\t\t\tconsequent,\n\t\t\t\t\t\talternate,\n\t\t\t\t\t};\n\n\t\t\t\t\t// check for operators of higher priority than ternary (i.e. assignment)\n\t\t\t\t\t// jsep sets || at 1, and assignment at 0.9, and conditional should be between them\n\t\t\t\t\tif (test.operator && jsep.binary_ops[test.operator] <= 0.9) {\n\t\t\t\t\t\tlet newTest = test;\n\t\t\t\t\t\twhile (newTest.right.operator && jsep.binary_ops[newTest.right.operator] <= 0.9) {\n\t\t\t\t\t\t\tnewTest = newTest.right;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tenv.node.test = newTest.right;\n\t\t\t\t\t\tnewTest.right = env.node;\n\t\t\t\t\t\tenv.node = test;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis.throwError('Expected :');\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n};\n\n// Add default plugins:\n\njsep.plugins.register(ternary);\n\nexport { Jsep, jsep as default };\n","const FSLASH_CODE = 47; // '/'\nconst BSLASH_CODE = 92; // '\\\\'\n\nvar index = {\n\tname: 'regex',\n\n\tinit(jsep) {\n\t\t// Regex literal: /abc123/ig\n\t\tjsep.hooks.add('gobble-token', function gobbleRegexLiteral(env) {\n\t\t\tif (this.code === FSLASH_CODE) {\n\t\t\t\tconst patternIndex = ++this.index;\n\n\t\t\t\tlet inCharSet = false;\n\t\t\t\twhile (this.index < this.expr.length) {\n\t\t\t\t\tif (this.code === FSLASH_CODE && !inCharSet) {\n\t\t\t\t\t\tconst pattern = this.expr.slice(patternIndex, this.index);\n\n\t\t\t\t\t\tlet flags = '';\n\t\t\t\t\t\twhile (++this.index < this.expr.length) {\n\t\t\t\t\t\t\tconst code = this.code;\n\t\t\t\t\t\t\tif ((code >= 97 && code <= 122) // a...z\n\t\t\t\t\t\t\t\t|| (code >= 65 && code <= 90) // A...Z\n\t\t\t\t\t\t\t\t|| (code >= 48 && code <= 57)) { // 0-9\n\t\t\t\t\t\t\t\tflags += this.char;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tlet value;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tvalue = new RegExp(pattern, flags);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch (e) {\n\t\t\t\t\t\t\tthis.throwError(e.message);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tenv.node = {\n\t\t\t\t\t\t\ttype: jsep.LITERAL,\n\t\t\t\t\t\t\tvalue,\n\t\t\t\t\t\t\traw: this.expr.slice(patternIndex - 1, this.index),\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\t// allow . [] and () after regex: /regex/.test(a)\n\t\t\t\t\t\tenv.node = this.gobbleTokenProperty(env.node);\n\t\t\t\t\t\treturn env.node;\n\t\t\t\t\t}\n\t\t\t\t\tif (this.code === jsep.OBRACK_CODE) {\n\t\t\t\t\t\tinCharSet = true;\n\t\t\t\t\t}\n\t\t\t\t\telse if (inCharSet && this.code === jsep.CBRACK_CODE) {\n\t\t\t\t\t\tinCharSet = false;\n\t\t\t\t\t}\n\t\t\t\t\tthis.index += this.code === BSLASH_CODE ? 2 : 1;\n\t\t\t\t}\n\t\t\t\tthis.throwError('Unclosed Regex');\n\t\t\t}\n\t\t});\n\t},\n};\n\nexport { index as default };\n","const PLUS_CODE = 43; // +\nconst MINUS_CODE = 45; // -\n\nconst plugin = {\n\tname: 'assignment',\n\n\tassignmentOperators: new Set([\n\t\t'=',\n\t\t'*=',\n\t\t'**=',\n\t\t'/=',\n\t\t'%=',\n\t\t'+=',\n\t\t'-=',\n\t\t'<<=',\n\t\t'>>=',\n\t\t'>>>=',\n\t\t'&=',\n\t\t'^=',\n\t\t'|=',\n\t\t'||=',\n\t\t'&&=',\n\t\t'??=',\n\t]),\n\tupdateOperators: [PLUS_CODE, MINUS_CODE],\n\tassignmentPrecedence: 0.9,\n\n\tinit(jsep) {\n\t\tconst updateNodeTypes = [jsep.IDENTIFIER, jsep.MEMBER_EXP];\n\t\tplugin.assignmentOperators.forEach(op => jsep.addBinaryOp(op, plugin.assignmentPrecedence, true));\n\n\t\tjsep.hooks.add('gobble-token', function gobbleUpdatePrefix(env) {\n\t\t\tconst code = this.code;\n\t\t\tif (plugin.updateOperators.some(c => c === code && c === this.expr.charCodeAt(this.index + 1))) {\n\t\t\t\tthis.index += 2;\n\t\t\t\tenv.node = {\n\t\t\t\t\ttype: 'UpdateExpression',\n\t\t\t\t\toperator: code === PLUS_CODE ? '++' : '--',\n\t\t\t\t\targument: this.gobbleTokenProperty(this.gobbleIdentifier()),\n\t\t\t\t\tprefix: true,\n\t\t\t\t};\n\t\t\t\tif (!env.node.argument || !updateNodeTypes.includes(env.node.argument.type)) {\n\t\t\t\t\tthis.throwError(`Unexpected ${env.node.operator}`);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tjsep.hooks.add('after-token', function gobbleUpdatePostfix(env) {\n\t\t\tif (env.node) {\n\t\t\t\tconst code = this.code;\n\t\t\t\tif (plugin.updateOperators.some(c => c === code && c === this.expr.charCodeAt(this.index + 1))) {\n\t\t\t\t\tif (!updateNodeTypes.includes(env.node.type)) {\n\t\t\t\t\t\tthis.throwError(`Unexpected ${env.node.operator}`);\n\t\t\t\t\t}\n\t\t\t\t\tthis.index += 2;\n\t\t\t\t\tenv.node = {\n\t\t\t\t\t\ttype: 'UpdateExpression',\n\t\t\t\t\t\toperator: code === PLUS_CODE ? '++' : '--',\n\t\t\t\t\t\targument: env.node,\n\t\t\t\t\t\tprefix: false,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tjsep.hooks.add('after-expression', function gobbleAssignment(env) {\n\t\t\tif (env.node) {\n\t\t\t\t// Note: Binaries can be chained in a single expression to respect\n\t\t\t\t// operator precedence (i.e. a = b = 1 + 2 + 3)\n\t\t\t\t// Update all binary assignment nodes in the tree\n\t\t\t\tupdateBinariesToAssignments(env.node);\n\t\t\t}\n\t\t});\n\n\t\tfunction updateBinariesToAssignments(node) {\n\t\t\tif (plugin.assignmentOperators.has(node.operator)) {\n\t\t\t\tnode.type = 'AssignmentExpression';\n\t\t\t\tupdateBinariesToAssignments(node.left);\n\t\t\t\tupdateBinariesToAssignments(node.right);\n\t\t\t}\n\t\t\telse if (!node.operator) {\n\t\t\t\tObject.values(node).forEach((val) => {\n\t\t\t\t\tif (val && typeof val === 'object') {\n\t\t\t\t\t\tupdateBinariesToAssignments(val);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t},\n};\n\nexport { plugin as default };\n","/* eslint-disable no-bitwise -- Convenient */\nimport jsep from 'jsep';\nimport jsepRegex from '@jsep-plugin/regex';\nimport jsepAssignment from '@jsep-plugin/assignment';\n\n// register plugins\njsep.plugins.register(jsepRegex, jsepAssignment);\njsep.addUnaryOp('typeof');\njsep.addUnaryOp('void');\njsep.addLiteral('null', null);\njsep.addLiteral('undefined', undefined);\n\nconst BLOCKED_PROTO_PROPERTIES = new Set([\n 'constructor',\n '__proto__',\n '__defineGetter__',\n '__defineSetter__',\n '__lookupGetter__',\n '__lookupSetter__'\n]);\n\nconst SafeEval = {\n /**\n * @param {jsep.Expression} ast\n * @param {Record} subs\n */\n evalAst (ast, subs) {\n switch (ast.type) {\n case 'BinaryExpression':\n case 'LogicalExpression':\n return SafeEval.evalBinaryExpression(ast, subs);\n case 'Compound':\n return SafeEval.evalCompound(ast, subs);\n case 'ConditionalExpression':\n return SafeEval.evalConditionalExpression(ast, subs);\n case 'Identifier':\n return SafeEval.evalIdentifier(ast, subs);\n case 'Literal':\n return SafeEval.evalLiteral(ast, subs);\n case 'MemberExpression':\n return SafeEval.evalMemberExpression(ast, subs);\n case 'UnaryExpression':\n return SafeEval.evalUnaryExpression(ast, subs);\n case 'ArrayExpression':\n return SafeEval.evalArrayExpression(ast, subs);\n case 'CallExpression':\n return SafeEval.evalCallExpression(ast, subs);\n case 'AssignmentExpression':\n return SafeEval.evalAssignmentExpression(ast, subs);\n default:\n throw SyntaxError('Unexpected expression', ast);\n }\n },\n evalBinaryExpression (ast, subs) {\n const result = {\n '||': (a, b) => a || b(),\n '&&': (a, b) => a && b(),\n '|': (a, b) => a | b(),\n '^': (a, b) => a ^ b(),\n '&': (a, b) => a & b(),\n // eslint-disable-next-line eqeqeq -- API\n '==': (a, b) => a == b(),\n // eslint-disable-next-line eqeqeq -- API\n '!=': (a, b) => a != b(),\n '===': (a, b) => a === b(),\n '!==': (a, b) => a !== b(),\n '<': (a, b) => a < b(),\n '>': (a, b) => a > b(),\n '<=': (a, b) => a <= b(),\n '>=': (a, b) => a >= b(),\n '<<': (a, b) => a << b(),\n '>>': (a, b) => a >> b(),\n '>>>': (a, b) => a >>> b(),\n '+': (a, b) => a + b(),\n '-': (a, b) => a - b(),\n '*': (a, b) => a * b(),\n '/': (a, b) => a / b(),\n '%': (a, b) => a % b()\n }[ast.operator](\n SafeEval.evalAst(ast.left, subs),\n () => SafeEval.evalAst(ast.right, subs)\n );\n return result;\n },\n evalCompound (ast, subs) {\n let last;\n for (let i = 0; i < ast.body.length; i++) {\n if (\n ast.body[i].type === 'Identifier' &&\n ['var', 'let', 'const'].includes(ast.body[i].name) &&\n ast.body[i + 1] &&\n ast.body[i + 1].type === 'AssignmentExpression'\n ) {\n // var x=2; is detected as\n // [{Identifier var}, {AssignmentExpression x=2}]\n // eslint-disable-next-line @stylistic/max-len -- Long\n // eslint-disable-next-line sonarjs/updated-loop-counter -- Convenient\n i += 1;\n }\n const expr = ast.body[i];\n last = SafeEval.evalAst(expr, subs);\n }\n return last;\n },\n evalConditionalExpression (ast, subs) {\n if (SafeEval.evalAst(ast.test, subs)) {\n return SafeEval.evalAst(ast.consequent, subs);\n }\n return SafeEval.evalAst(ast.alternate, subs);\n },\n evalIdentifier (ast, subs) {\n if (Object.hasOwn(subs, ast.name)) {\n return subs[ast.name];\n }\n throw ReferenceError(`${ast.name} is not defined`);\n },\n evalLiteral (ast) {\n return ast.value;\n },\n evalMemberExpression (ast, subs) {\n const prop = String(\n // NOTE: `String(value)` throws error when\n // value has overwritten the toString method to return non-string\n // i.e. `value = {toString: () => []}`\n ast.computed\n ? SafeEval.evalAst(ast.property) // `object[property]`\n : ast.property.name // `object.property` property is Identifier\n );\n const obj = SafeEval.evalAst(ast.object, subs);\n if (obj === undefined || obj === null) {\n throw TypeError(\n `Cannot read properties of ${obj} (reading '${prop}')`\n );\n }\n if (!Object.hasOwn(obj, prop) && BLOCKED_PROTO_PROPERTIES.has(prop)) {\n throw TypeError(\n `Cannot read properties of ${obj} (reading '${prop}')`\n );\n }\n const result = obj[prop];\n if (typeof result === 'function') {\n return result.bind(obj); // arrow functions aren't affected by bind.\n }\n return result;\n },\n evalUnaryExpression (ast, subs) {\n const result = {\n '-': (a) => -SafeEval.evalAst(a, subs),\n '!': (a) => !SafeEval.evalAst(a, subs),\n '~': (a) => ~SafeEval.evalAst(a, subs),\n // eslint-disable-next-line no-implicit-coercion -- API\n '+': (a) => +SafeEval.evalAst(a, subs),\n typeof: (a) => typeof SafeEval.evalAst(a, subs),\n // eslint-disable-next-line no-void, sonarjs/void-use -- feature\n void: (a) => void SafeEval.evalAst(a, subs)\n }[ast.operator](ast.argument);\n return result;\n },\n evalArrayExpression (ast, subs) {\n return ast.elements.map((el) => SafeEval.evalAst(el, subs));\n },\n evalCallExpression (ast, subs) {\n const args = ast.arguments.map((arg) => SafeEval.evalAst(arg, subs));\n const func = SafeEval.evalAst(ast.callee, subs);\n /* c8 ignore start */\n if (func === Function) {\n // unreachable since BLOCKED_PROTO_PROPERTIES includes 'constructor'\n throw new Error('Function constructor is disabled');\n }\n /* c8 ignore end */\n return func(...args);\n },\n evalAssignmentExpression (ast, subs) {\n if (ast.left.type !== 'Identifier') {\n throw SyntaxError('Invalid left-hand side in assignment');\n }\n const id = ast.left.name;\n const value = SafeEval.evalAst(ast.right, subs);\n subs[id] = value;\n return subs[id];\n }\n};\n\n/**\n * A replacement for NodeJS' VM.Script which is also {@link https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP | Content Security Policy} friendly.\n */\nclass SafeScript {\n /**\n * @param {string} expr Expression to evaluate\n */\n constructor (expr) {\n this.code = expr;\n this.ast = jsep(this.code);\n }\n\n /**\n * @param {object} context Object whose items will be added\n * to evaluation\n * @returns {EvaluatedResult} Result of evaluated code\n */\n runInNewContext (context) {\n // `Object.create(null)` creates a prototypeless object\n const keyMap = Object.assign(Object.create(null), context);\n return SafeEval.evalAst(this.ast, keyMap);\n }\n}\n\nexport {SafeScript};\n","/* eslint-disable camelcase -- Convenient for escaping */\n\nimport {SafeScript} from './Safe-Script.js';\n\n/**\n * @typedef {null|boolean|number|string|object|GenericArray} JSONObject\n */\n\n/**\n * @typedef {any} AnyItem\n */\n\n/**\n * @typedef {any} AnyResult\n */\n\n/**\n * Copies array and then pushes item into it.\n * @param {GenericArray} arr Array to copy and into which to push\n * @param {AnyItem} item Array item to add (to end)\n * @returns {GenericArray} Copy of the original array\n */\nfunction push (arr, item) {\n arr = arr.slice();\n arr.push(item);\n return arr;\n}\n/**\n * Copies array and then unshifts item into it.\n * @param {AnyItem} item Array item to add (to beginning)\n * @param {GenericArray} arr Array to copy and into which to unshift\n * @returns {GenericArray} Copy of the original array\n */\nfunction unshift (item, arr) {\n arr = arr.slice();\n arr.unshift(item);\n return arr;\n}\n\n/**\n * Caught when JSONPath is used without `new` but rethrown if with `new`\n * @extends Error\n */\nclass NewError extends Error {\n /**\n * @param {AnyResult} value The evaluated scalar value\n */\n constructor (value) {\n super(\n 'JSONPath should not be called with \"new\" (it prevents return ' +\n 'of (unwrapped) scalar values)'\n );\n this.avoidNew = true;\n this.value = value;\n this.name = 'NewError';\n }\n}\n\n/**\n* @typedef {object} ReturnObject\n* @property {string} path\n* @property {JSONObject} value\n* @property {object|GenericArray} parent\n* @property {string} parentProperty\n*/\n\n/**\n* @callback JSONPathCallback\n* @param {string|object} preferredOutput\n* @param {\"value\"|\"property\"} type\n* @param {ReturnObject} fullRetObj\n* @returns {void}\n*/\n\n/**\n* @callback OtherTypeCallback\n* @param {JSONObject} val\n* @param {string} path\n* @param {object|GenericArray} parent\n* @param {string} parentPropName\n* @returns {boolean}\n*/\n\n/**\n * @typedef {any} ContextItem\n */\n\n/**\n * @typedef {any} EvaluatedResult\n */\n\n/**\n* @callback EvalCallback\n* @param {string} code\n* @param {ContextItem} context\n* @returns {EvaluatedResult}\n*/\n\n/**\n * @typedef {typeof SafeScript} EvalClass\n */\n\n/**\n * @typedef {object} JSONPathOptions\n * @property {JSON} json\n * @property {string|string[]} path\n * @property {\"value\"|\"path\"|\"pointer\"|\"parent\"|\"parentProperty\"|\n * \"all\"} [resultType=\"value\"]\n * @property {boolean} [flatten=false]\n * @property {boolean} [wrap=true]\n * @property {object} [sandbox={}]\n * @property {EvalCallback|EvalClass|'safe'|'native'|\n * boolean} [eval = 'safe']\n * @property {object|GenericArray|null} [parent=null]\n * @property {string|null} [parentProperty=null]\n * @property {JSONPathCallback} [callback]\n * @property {OtherTypeCallback} [otherTypeCallback] Defaults to\n * function which throws on encountering `@other`\n * @property {boolean} [autostart=true]\n */\n\n/**\n * @param {string|JSONPathOptions} opts If a string, will be treated as `expr`\n * @param {string} [expr] JSON path to evaluate\n * @param {JSON} [obj] JSON object to evaluate against\n * @param {JSONPathCallback} [callback] Passed 3 arguments: 1) desired payload\n * per `resultType`, 2) `\"value\"|\"property\"`, 3) Full returned object with\n * all payloads\n * @param {OtherTypeCallback} [otherTypeCallback] If `@other()` is at the end\n * of one's query, this will be invoked with the value of the item, its\n * path, its parent, and its parent's property name, and it should return\n * a boolean indicating whether the supplied value belongs to the \"other\"\n * type or not (or it may handle transformations and return `false`).\n * @returns {JSONPath}\n * @class\n */\nfunction JSONPath (opts, expr, obj, callback, otherTypeCallback) {\n // eslint-disable-next-line no-restricted-syntax -- Allow for pseudo-class\n if (!(this instanceof JSONPath)) {\n try {\n return new JSONPath(opts, expr, obj, callback, otherTypeCallback);\n } catch (e) {\n if (!e.avoidNew) {\n throw e;\n }\n return e.value;\n }\n }\n\n if (typeof opts === 'string') {\n otherTypeCallback = callback;\n callback = obj;\n obj = expr;\n expr = opts;\n opts = null;\n }\n const optObj = opts && typeof opts === 'object';\n opts = opts || {};\n this.json = opts.json || obj;\n this.path = opts.path || expr;\n this.resultType = opts.resultType || 'value';\n this.flatten = opts.flatten || false;\n this.wrap = Object.hasOwn(opts, 'wrap') ? opts.wrap : true;\n this.sandbox = opts.sandbox || {};\n this.eval = opts.eval === undefined ? 'safe' : opts.eval;\n this.ignoreEvalErrors = (typeof opts.ignoreEvalErrors === 'undefined')\n ? false\n : opts.ignoreEvalErrors;\n this.parent = opts.parent || null;\n this.parentProperty = opts.parentProperty || null;\n this.callback = opts.callback || callback || null;\n this.otherTypeCallback = opts.otherTypeCallback ||\n otherTypeCallback ||\n function () {\n throw new TypeError(\n 'You must supply an otherTypeCallback callback option ' +\n 'with the @other() operator.'\n );\n };\n\n if (opts.autostart !== false) {\n const args = {\n path: (optObj ? opts.path : expr)\n };\n if (!optObj) {\n args.json = obj;\n } else if ('json' in opts) {\n args.json = opts.json;\n }\n const ret = this.evaluate(args);\n if (!ret || typeof ret !== 'object') {\n throw new NewError(ret);\n }\n return ret;\n }\n}\n\n// PUBLIC METHODS\nJSONPath.prototype.evaluate = function (\n expr, json, callback, otherTypeCallback\n) {\n let currParent = this.parent,\n currParentProperty = this.parentProperty;\n let {flatten, wrap} = this;\n\n this.currResultType = this.resultType;\n this.currEval = this.eval;\n this.currSandbox = this.sandbox;\n callback = callback || this.callback;\n this.currOtherTypeCallback = otherTypeCallback || this.otherTypeCallback;\n\n json = json || this.json;\n expr = expr || this.path;\n if (expr && typeof expr === 'object' && !Array.isArray(expr)) {\n if (!expr.path && expr.path !== '') {\n throw new TypeError(\n 'You must supply a \"path\" property when providing an object ' +\n 'argument to JSONPath.evaluate().'\n );\n }\n if (!(Object.hasOwn(expr, 'json'))) {\n throw new TypeError(\n 'You must supply a \"json\" property when providing an object ' +\n 'argument to JSONPath.evaluate().'\n );\n }\n ({json} = expr);\n flatten = Object.hasOwn(expr, 'flatten') ? expr.flatten : flatten;\n this.currResultType = Object.hasOwn(expr, 'resultType')\n ? expr.resultType\n : this.currResultType;\n this.currSandbox = Object.hasOwn(expr, 'sandbox')\n ? expr.sandbox\n : this.currSandbox;\n wrap = Object.hasOwn(expr, 'wrap') ? expr.wrap : wrap;\n this.currEval = Object.hasOwn(expr, 'eval')\n ? expr.eval\n : this.currEval;\n callback = Object.hasOwn(expr, 'callback') ? expr.callback : callback;\n this.currOtherTypeCallback = Object.hasOwn(expr, 'otherTypeCallback')\n ? expr.otherTypeCallback\n : this.currOtherTypeCallback;\n currParent = Object.hasOwn(expr, 'parent') ? expr.parent : currParent;\n currParentProperty = Object.hasOwn(expr, 'parentProperty')\n ? expr.parentProperty\n : currParentProperty;\n expr = expr.path;\n }\n currParent = currParent || null;\n currParentProperty = currParentProperty || null;\n\n if (Array.isArray(expr)) {\n expr = JSONPath.toPathString(expr);\n }\n if ((!expr && expr !== '') || !json) {\n return undefined;\n }\n\n const exprList = JSONPath.toPathParts(expr);\n if (exprList[0] && exprList[0].type === 'root' && exprList.length > 1) {\n exprList.shift();\n }\n this._hasParentSelector = null;\n this._json = json; // Store root for parent selector navigation\n const result = this\n ._trace(\n exprList, json, ['$'], currParent, currParentProperty, callback\n )\n .filter(function (ea) {\n return ea && !ea.isParentSelector;\n });\n\n if (!result.length) {\n return wrap ? [] : undefined;\n }\n if (!wrap && result.length === 1 && !result[0].hasArrExpr) {\n return this._getPreferredOutput(result[0]);\n }\n return result.reduce((rslt, ea) => {\n const valOrPath = this._getPreferredOutput(ea);\n if (flatten && Array.isArray(valOrPath)) {\n rslt = rslt.concat(valOrPath);\n } else {\n rslt.push(valOrPath);\n }\n return rslt;\n }, []);\n};\n\n// PRIVATE METHODS\n\nJSONPath.prototype._getPreferredOutput = function (ea) {\n const resultType = this.currResultType;\n switch (resultType) {\n case 'all': {\n const path = Array.isArray(ea.path)\n ? ea.path\n : JSONPath.toPathParts(ea.path);\n ea.pointer = JSONPath.toPointer(path);\n ea.path = typeof ea.path === 'string'\n ? ea.path\n : JSONPath.toPathString(ea.path);\n return ea;\n } case 'value': case 'parent': case 'parentProperty':\n return ea[resultType];\n case 'path':\n return JSONPath.toPathString(ea[resultType]);\n case 'pointer':\n return JSONPath.toPointer(ea.path);\n default:\n throw new TypeError('Unknown result type');\n }\n};\n\nJSONPath.prototype._handleCallback = function (fullRetObj, callback, type) {\n if (callback) {\n const preferredOutput = this._getPreferredOutput(fullRetObj);\n fullRetObj.path = typeof fullRetObj.path === 'string'\n ? fullRetObj.path\n : JSONPath.toPathString(fullRetObj.path);\n // eslint-disable-next-line n/callback-return -- No need to return\n callback(preferredOutput, type, fullRetObj);\n }\n};\n\n/**\n *\n * @param {string} expr\n * @param {JSONObject} val\n * @param {string} path\n * @param {object|GenericArray} parent\n * @param {string} parentPropName\n * @param {JSONPathCallback} callback\n * @param {boolean} hasArrExpr\n * @param {boolean} literalPriority\n * @returns {ReturnObject|ReturnObject[]}\n */\nJSONPath.prototype._trace = function (\n expr, val, path, parent, parentPropName, callback, hasArrExpr,\n literalPriority\n) {\n // No expr to follow? return path and value as the result of\n // this trace branch\n let retObj;\n if (!expr.length) {\n retObj = {\n path,\n value: val,\n parent,\n parentProperty: parentPropName,\n hasArrExpr\n };\n this._handleCallback(retObj, callback, 'value');\n return [retObj];\n }\n\n const token = expr[0], x = expr.slice(1);\n\n // We need to gather the return value of recursive trace calls in order to\n // do the parent sel computation.\n const ret = [];\n /**\n *\n * @param {ReturnObject|ReturnObject[]} elems\n * @returns {void}\n */\n function addRet (elems) {\n if (Array.isArray(elems)) {\n // This was causing excessive stack size in Node (with or\n // without Babel) against our performance test:\n // `ret.push(...elems);`\n elems.forEach((t) => {\n ret.push(t);\n });\n } else {\n ret.push(elems);\n }\n }\n\n // Fast path for primitive tokens (strings and numbers)\n if (typeof token === 'string') {\n // Simple property access\n if (val && Object.hasOwn(val, token)) {\n addRet(this._trace(\n x, val[token], push(path, token), val, token, callback, hasArrExpr\n ));\n }\n } else if (typeof token === 'number') {\n // Simple numeric index access\n if (Array.isArray(val) && token >= 0 && token < val.length) {\n addRet(this._trace(\n x, val[token], push(path, token), val, token, callback, hasArrExpr\n ));\n }\n } else if (token && typeof token === 'object' && token.type) {\n // Handle complex token objects\n switch (token.type) {\n case 'root': // $\n addRet(this._trace(x, val, path, null, null, callback, hasArrExpr));\n break;\n\n case 'property': {\n const propName = token.value;\n // Check if property exists (escaped flag just means it's not wildcard)\n if (val && Object.hasOwn(val, propName)) {\n addRet(this._trace(\n x, val[propName], push(path, propName), val, propName, callback,\n hasArrExpr, true\n ));\n }\n break;\n }\n\n case 'wildcard': // *\n this._walk(val, (m) => {\n addRet(this._trace(\n x, val[m], push(path, m), val, m, callback, true, true\n ));\n });\n break;\n\n case 'descent': // ..\n // Check remaining expression with val's immediate children\n addRet(\n this._trace(x, val, path, parent, parentPropName, callback,\n hasArrExpr)\n );\n this._walk(val, (m) => {\n // We don't join m and x here because we only want parents,\n // not scalar values\n if (typeof val[m] === 'object') {\n // Keep going with recursive descent on val's\n // object children\n addRet(this._trace(\n expr.slice(), val[m], push(path, m), val, m, callback, true\n ));\n }\n });\n break;\n\n case 'parent': // ^\n // This is not a final endpoint, so we do not invoke the callback here\n // Only allow parent selector if we're not already at root\n if (path.length > 1) {\n this._hasParentSelector = true;\n ret.push({\n path: path.slice(0, -1),\n expr: x,\n isParentSelector: true\n });\n }\n break;\n\n case 'propertyName': // ~\n retObj = {\n path: push(path, '~'),\n value: parentPropName,\n parent,\n parentProperty: null\n };\n this._handleCallback(retObj, callback, 'property');\n ret.push(retObj);\n break;\n\n case 'index': {\n const idx = token.value;\n if ((Array.isArray(val) && idx >= 0 && idx < val.length) ||\n (val && Object.hasOwn(val, idx))) {\n addRet(this._trace(\n x, val[idx], push(path, idx), val, idx, callback,\n hasArrExpr, true\n ));\n }\n break;\n }\n\n case 'slice':\n addRet(\n this._slice(token, x, val, path, parent, parentPropName, callback)\n );\n break;\n\n case 'filter': {\n if (this.currEval === false) {\n throw new Error('Eval [?(expr)] prevented in JSONPath expression.');\n }\n\n // Quick check: Does this filter have nested paths?\n const hasNesting = token.expression.includes('[?(');\n\n if (!hasNesting) {\n // Fast path: No nesting, skip extraction\n this._walk(val, (m) => {\n if (this._eval(token.expression, val[m], m, path,\n parent, parentPropName)) {\n addRet(this._trace(x, val[m], push(path, m), val, m,\n callback, true));\n }\n });\n } else {\n // Slow path: Extract and handle nested filters\n const {expression: modifiedExpr, nestedPaths} =\n this._extractNestedFilters(token.expression);\n\n // Check if expression is JUST a nested path (no other JavaScript)\n // If so, we need to check array length for truthiness\n const isSingleNestedPath = nestedPaths.length === 1 &&\n modifiedExpr.trim() === '_$_jp0';\n\n // Evaluate filter for each item\n this._walk(val, (m) => {\n // Evaluate nested paths in context of current item\n const nestedResults = {};\n for (const [i, nestedPath] of nestedPaths.entries()) {\n // Convert @ to $ for parsing (@ means current value)\n const pathForParsing = nestedPath.replace(/^@/u, '$');\n try {\n const nestedTokens = JSONPath.toPathParts(pathForParsing);\n // Evaluate nested path on current item\n const nestedResult = this._trace(\n nestedTokens,\n val[m],\n push(path, m),\n val,\n m,\n null, // no callback for nested evaluation\n true\n );\n // Extract values from result objects\n nestedResults[`_$_jp${i}`] =\n nestedResult.map((r) => r.value);\n } catch (e) {\n // If nested evaluation fails, treat as no matches\n nestedResults[`_$_jp${i}`] = [];\n }\n }\n\n // Add nested results to sandbox temporarily\n const originalSandbox = {...this.currSandbox};\n Object.assign(this.currSandbox, nestedResults);\n\n try {\n // For single nested path, check if array has elements\n // (empty arrays are truthy in JS but should be falsy in filter)\n const matches = isSingleNestedPath\n ? nestedResults._$_jp0.length > 0\n : this._eval(modifiedExpr, val[m], m, path,\n parent, parentPropName);\n\n if (matches) {\n addRet(this._trace(x, val[m], push(path, m), val, m,\n callback, true));\n }\n } finally {\n // Restore original sandbox (remove nested result placeholders)\n this.currSandbox = originalSandbox;\n }\n });\n }\n break;\n }\n\n case 'dynamic': {\n if (this.currEval === false) {\n throw new Error('Eval [(expr)] prevented in JSONPath expression.');\n }\n // As this will resolve to a property name (but we don't know it\n // yet), property and parent information is relative to the\n // parent of the property to which this expression will resolve\n addRet(this._trace(unshift(\n this._eval(\n token.expression, val, path.at(-1),\n path.slice(0, -1), parent, parentPropName\n ),\n x\n ), val, path, parent, parentPropName, callback, hasArrExpr));\n break;\n }\n\n case 'typeOperator': {\n let addType = false;\n const {valueType} = token;\n switch (valueType) {\n case 'scalar':\n if (!val || !(['object', 'function'].includes(typeof val))) {\n addType = true;\n }\n break;\n case 'boolean': case 'string': case 'undefined': case 'function':\n if (typeof val === valueType) {\n addType = true;\n }\n break;\n case 'integer':\n if (Number.isFinite(val) && !(val % 1)) {\n addType = true;\n }\n break;\n case 'number':\n if (Number.isFinite(val)) {\n addType = true;\n }\n break;\n case 'nonFinite':\n if (typeof val === 'number' && !Number.isFinite(val)) {\n addType = true;\n }\n break;\n case 'object':\n if (val && typeof val === valueType) {\n addType = true;\n }\n break;\n case 'array':\n if (Array.isArray(val)) {\n addType = true;\n }\n break;\n case 'other':\n addType = this.currOtherTypeCallback(\n val, path, parent, parentPropName\n );\n break;\n case 'null':\n if (val === null) {\n addType = true;\n }\n break;\n /* c8 ignore next 2 */\n default:\n throw new TypeError('Unknown value type ' + valueType);\n }\n if (addType) {\n retObj = {\n path, value: val, parent, parentProperty: parentPropName\n };\n this._handleCallback(retObj, callback, 'value');\n ret.push(retObj);\n }\n break;\n }\n\n case 'multiProperty': {\n const parts = token.properties;\n const escapedFlags = token.escaped || [];\n for (const [i, part] of parts.entries()) {\n // Check if part is a number (multi-index) or string (multi-property)\n let partToken;\n if (typeof part === 'number') {\n partToken = {type: 'index', value: part};\n } else {\n const isEscaped = escapedFlags[i] || false;\n partToken = {\n type: 'property',\n value: part,\n escaped: isEscaped\n };\n }\n addRet(this._trace(\n unshift(partToken, x), val, path, parent, parentPropName,\n callback, true\n ));\n }\n break;\n }\n }\n } else if ((typeof token !== 'string' || literalPriority) && val &&\n Object.hasOwn(val, token)\n ) { // simple case--directly follow property (for object tokens or with literalPriority)\n addRet(this._trace(x, val[token], push(path, token), val, token, callback,\n hasArrExpr));\n }\n // Note: Legacy string token handling removed - now handled by fast path above\n\n // We check the resulting values for parent selections. For parent\n // selections we discard the value object and continue the trace with the\n // current val object\n if (this._hasParentSelector) {\n for (let t = 0; t < ret.length; t++) {\n const rett = ret[t];\n if (rett && rett.isParentSelector) {\n // Navigate from root to the parent path to get correct parent context\n // rett.path is the path with last element removed (e.g., ['$', 'children'])\n let resultVal = this._json;\n let resultParent = null;\n let resultParentProp = null;\n\n // Navigate from root following the path\n // Start at index 1 to skip '$'\n for (let i = 1; i < rett.path.length; i++) {\n resultParent = resultVal;\n resultParentProp = rett.path[i];\n resultVal = resultVal[rett.path[i]];\n }\n\n const tmp = this._trace(\n rett.expr, resultVal, rett.path, resultParent,\n resultParentProp, callback, hasArrExpr\n );\n if (Array.isArray(tmp)) {\n ret[t] = tmp[0];\n const tl = tmp.length;\n for (let tt = 1; tt < tl; tt++) {\n // eslint-disable-next-line @stylistic/max-len -- Long\n // eslint-disable-next-line sonarjs/updated-loop-counter -- Convenient\n t++;\n ret.splice(t, 0, tmp[tt]);\n }\n } else {\n ret[t] = tmp;\n }\n }\n }\n }\n return ret;\n};\n\nJSONPath.prototype._walk = function (val, f) {\n if (Array.isArray(val)) {\n const n = val.length;\n for (let i = 0; i < n; i++) {\n f(i);\n }\n } else if (val && typeof val === 'object') {\n Object.keys(val).forEach((m) => {\n f(m);\n });\n }\n};\n\n/**\n * Extract nested JSONPath expressions from a filter expression.\n * @param {string} expr - Filter expression (e.g., \"@.children[?(@.price<10)]\")\n * @returns {{expression: string, nestedPaths: string[]}} Modified expression and extracted paths\n */\nJSONPath.prototype._extractNestedFilters = function (expr) {\n // Check cache first\n const cache = JSONPath.filterExtractionCache;\n if (cache[expr]) {\n // Return shallow clone to prevent mutation\n return {\n expression: cache[expr].expression,\n nestedPaths: [...cache[expr].nestedPaths]\n };\n }\n\n const nestedPaths = [];\n let result = expr;\n let placeholderCount = 0;\n\n // We need to find patterns like @.path[?(...)] or @[?(...)], etc.\n // Use a stack-based approach to handle nested brackets properly\n\n /**\n * Find the next JSONPath expression starting with @.\n * @param {string} str - String to search\n * @param {number} startPos - Position to start searching\n * @returns {{start: number, end: number, path: string} | null}\n */\n function findNextNestedPath (str, startPos) {\n let i = startPos;\n\n // Find next @ that's not in a string or regex literal\n while (i < str.length) {\n const ch = str[i];\n\n // Skip string literals\n if (ch === '\"' || ch === \"'\") {\n const quote = ch;\n i++;\n while (i < str.length) {\n if (str[i] === '\\\\' && i + 1 < str.length) {\n i += 2; // Skip escaped character\n } else if (str[i] === quote) {\n i++;\n break;\n } else {\n i++;\n }\n }\n continue;\n }\n\n // Skip regex literals (simplified detection)\n if (ch === '/' && i > 0) {\n // Check if this might be a regex (not division)\n // Look back for operators that could precede a regex\n const prevNonSpace = str.slice(0, i).trimEnd().slice(-1);\n if ('=([{,;:!&|?'.includes(prevNonSpace) || i === startPos) {\n i++;\n while (i < str.length) {\n if (str[i] === '\\\\' && i + 1 < str.length) {\n i += 2;\n } else if (str[i] === '/') {\n i++;\n // Skip regex flags\n while (i < str.length && (/[gimsuvy]/u).test(str[i])) {\n i++;\n }\n break;\n } else {\n i++;\n }\n }\n continue;\n }\n }\n\n // Found @ - check if it's followed by JSONPath syntax\n if (ch === '@') {\n const pathStart = i;\n i++; // Move past @\n\n // Check if there's path syntax after @\n // Could be: @.prop, @[, @.., @@\n if (i >= str.length) {\n return null;\n }\n\n let hasPathSyntax = false;\n let path = '@';\n\n // Parse the JSONPath expression\n while (i < str.length) {\n const c = str[i];\n\n // Path components\n if (c === '.' || c === '[' || c === '*' ||\n c === '^' || c === '~') {\n hasPathSyntax = true;\n path += c;\n i++;\n\n // Handle bracket notation with bracket matching\n if (c === '[') {\n let depth = 1;\n /* eslint-disable unicorn/prefer-switch --\n Complex bracket matching with nested quotes */\n while (i < str.length && depth > 0) {\n if (str[i] === '\\\\' && i + 1 < str.length) {\n path += str[i] + str[i + 1];\n i += 2;\n } else if (str[i] === '\"' || str[i] === \"'\") {\n // Handle quoted strings in brackets\n const q = str[i];\n path += str[i];\n i++;\n while (i < str.length && str[i] !== q) {\n if (str[i] === '\\\\' && i + 1 < str.length) {\n path += str[i] + str[i + 1];\n i += 2;\n } else {\n path += str[i];\n i++;\n }\n }\n if (i < str.length) {\n path += str[i];\n i++;\n }\n } else if (str[i] === '[') {\n depth++;\n path += str[i];\n i++;\n } else if (str[i] === ']') {\n depth--;\n path += str[i];\n i++;\n } else {\n path += str[i];\n i++;\n }\n }\n /* eslint-enable unicorn/prefer-switch --\n Re-enable after bracket matching section */\n }\n } else if ((/[\\w$]/u).test(c)) {\n // Property name characters\n hasPathSyntax = true;\n path += c;\n i++;\n } else {\n // End of path\n break;\n }\n }\n\n // Check if this path contains a filter (has [?(...)])\n // Only extract paths that have filters to avoid unnecessary evaluation\n if (hasPathSyntax && path.includes('[?')) {\n return {\n start: pathStart,\n end: i,\n path\n };\n }\n\n // No filter found, continue searching\n continue;\n }\n\n i++;\n }\n\n return null;\n }\n\n // Extract all nested paths\n let searchPos = 0;\n const replacements = [];\n\n while (searchPos < result.length) {\n const found = findNextNestedPath(result, searchPos);\n if (!found) {\n break;\n }\n\n // Store the replacement to be made\n replacements.push({\n start: found.start,\n end: found.end,\n path: found.path,\n placeholder: `_$_jp${placeholderCount}`\n });\n\n nestedPaths.push(found.path);\n placeholderCount++;\n searchPos = found.end;\n }\n\n // Apply replacements in reverse order to maintain positions\n for (let i = replacements.length - 1; i >= 0; i--) {\n const {start, end, placeholder} = replacements[i];\n result = result.slice(0, start) + placeholder + result.slice(end);\n }\n\n // Cache the result\n const extractionResult = {\n expression: result,\n nestedPaths\n };\n cache[expr] = extractionResult;\n\n return {\n expression: result,\n nestedPaths: [...nestedPaths]\n };\n};\n\nJSONPath.prototype._slice = function (\n token, expr, val, path, parent, parentPropName, callback\n) {\n if (!Array.isArray(val)) {\n return undefined;\n }\n const len = val.length;\n let start = token.start === null ? 0 : token.start;\n let end = token.end === null ? len : token.end;\n const step = token.step === null ? 1 : token.step;\n\n start = (start < 0) ? Math.max(0, start + len) : Math.min(len, start);\n end = (end < 0) ? Math.max(0, end + len) : Math.min(len, end);\n const ret = [];\n for (let i = start; i < end; i += step) {\n const tmp = this._trace(\n unshift(i, expr), val, path, parent, parentPropName, callback, true\n );\n // Should only be possible to be an array here since first part of\n // ``unshift(i, expr)` passed in above would not be empty, nor `~`,\n // nor begin with `@` (as could return objects)\n // This was causing excessive stack size in Node (with or\n // without Babel) against our performance test: `ret.push(...tmp);`\n tmp.forEach((t) => {\n ret.push(t);\n });\n }\n return ret;\n};\n\nJSONPath.prototype._eval = function (\n code, _v, _vname, path, parent, parentPropName\n) {\n this.currSandbox._$_parentProperty = parentPropName;\n this.currSandbox._$_parent = parent;\n this.currSandbox._$_property = _vname;\n this.currSandbox._$_root = this.json;\n this.currSandbox._$_v = _v;\n\n const containsPath = code.includes('@path');\n if (containsPath) {\n this.currSandbox._$_path = JSONPath.toPathString(path.concat([_vname]));\n }\n\n const scriptCacheKey = this.currEval + 'Script:' + code;\n if (!JSONPath.cache[scriptCacheKey]) {\n let script = code\n .replaceAll('@parentProperty', '_$_parentProperty')\n .replaceAll('@parent', '_$_parent')\n .replaceAll('@property', '_$_property')\n .replaceAll('@root', '_$_root')\n .replaceAll(/@([.\\s)[])/gu, '_$_v$1');\n if (containsPath) {\n script = script.replaceAll('@path', '_$_path');\n }\n if (\n this.currEval === 'safe' ||\n this.currEval === true ||\n this.currEval === undefined\n ) {\n JSONPath.cache[scriptCacheKey] = new this.safeVm.Script(script);\n } else if (this.currEval === 'native') {\n JSONPath.cache[scriptCacheKey] = new this.vm.Script(script);\n } else if (\n typeof this.currEval === 'function' &&\n this.currEval.prototype &&\n Object.hasOwn(this.currEval.prototype, 'runInNewContext')\n ) {\n const CurrEval = this.currEval;\n JSONPath.cache[scriptCacheKey] = new CurrEval(script);\n } else if (typeof this.currEval === 'function') {\n JSONPath.cache[scriptCacheKey] = {\n runInNewContext: (context) => this.currEval(script, context)\n };\n } else {\n throw new TypeError(`Unknown \"eval\" property \"${this.currEval}\"`);\n }\n }\n\n try {\n return JSONPath.cache[scriptCacheKey].runInNewContext(this.currSandbox);\n } catch (e) {\n if (this.ignoreEvalErrors) {\n return false;\n }\n throw new Error('jsonPath: ' + e.message + ': ' + code);\n }\n};\n\n// PUBLIC CLASS PROPERTIES AND METHODS\n\n// Could store the cache object itself\nJSONPath.cache = {};\nJSONPath.pathPartsCache = {};\nJSONPath.filterExtractionCache = {};\n\n/**\n * @param {string[]|object[]} pathArr Array to convert\n * @returns {string} The path string\n */\nJSONPath.toPathString = function (pathArr) {\n const x = pathArr, n = x.length;\n let p = '$';\n for (let i = 1; i < n; i++) {\n const item = x[i];\n\n // Handle both old string format and new token format\n if (typeof item === 'number') {\n // Array index\n p += '[' + item + ']';\n } else if (typeof item === 'string') {\n // Legacy path\n if (!(/^(~|\\^|@.*?\\(\\))$/u).test(item)) {\n p += (/^[0-9*]+$/u).test(item) ? ('[' + item + ']') : (\"['\" + item + \"']\");\n }\n } else if (item && typeof item === 'object') {\n // New token format\n switch (item.type) {\n case 'property':\n p += \"['\" + item.value + \"']\";\n break;\n case 'index':\n p += '[' + item.value + ']';\n break;\n case 'wildcard':\n p += '[*]';\n break;\n case 'slice':\n p += '[' + item.raw + ']';\n break;\n case 'filter':\n p += '[?(' + item.expression + ')]';\n break;\n case 'dynamic':\n p += '[(' + item.expression + ')]';\n break;\n case 'typeOperator':\n p += '@' + item.valueType + '()';\n break;\n case 'multiProperty':\n p += \"['\" + item.properties.join(\"','\") + \"']\";\n break;\n // Special operators don't add to path string\n case 'root':\n case 'descent':\n case 'parent':\n case 'propertyName':\n break;\n }\n }\n }\n return p;\n};\n\n/**\n * Converts path array to JSON Pointer format.\n * Handles both legacy string arrays and new token objects.\n * @param {string[]|object[]} pointer - Path array\n * @returns {string} JSON Pointer\n */\nJSONPath.toPointer = function (pointer) {\n const x = pointer, n = x.length;\n let p = '';\n for (let i = 1; i < n; i++) {\n const item = x[i];\n let value;\n\n // Handle different formats\n if (typeof item === 'number') {\n value = String(item);\n } else if (typeof item === 'string') {\n // Legacy string format or special operators\n if ((/^(~|\\^|@.*?\\(\\))$/u).test(item)) {\n continue; // Skip special operators\n }\n value = item;\n } else if (item && typeof item === 'object') {\n // New token format\n switch (item.type) {\n case 'property': {\n const {value: propValue} = item;\n value = propValue;\n break;\n }\n case 'index': {\n const {value: indexValue} = item;\n value = String(indexValue);\n break;\n }\n // Skip special operators\n case 'root':\n case 'wildcard':\n case 'descent':\n case 'parent':\n case 'propertyName':\n case 'filter':\n case 'dynamic':\n case 'slice':\n case 'typeOperator':\n case 'multiProperty':\n continue;\n default:\n continue;\n }\n } else {\n continue;\n }\n\n // Escape ~ and / per JSON Pointer spec\n p += '/' + value\n .replaceAll('~', '~0')\n .replaceAll('/', '~1');\n }\n return p;\n};\n\n\n/**\n * Parse a JSONPath expression into structured tokens.\n * @param {string} expr - JSONPath expression\n * @returns {Array} Array of tokens\n */\n/**\n * Parses a JSONPath expression into structured token objects.\n * @param {string} expr - JSONPath expression to parse\n * @returns {object[]} Array of token objects\n */\nJSONPath.toPathParts = function (expr) {\n const cache = JSONPath.pathPartsCache;\n if (cache[expr]) {\n // Shallow clone array, shallow clone object tokens\n // (tokens are simple objects with no nested objects)\n return cache[expr].map((token) => (\n typeof token === 'object' && token !== null ? {...token} : token\n ));\n }\n\n const tokens = [];\n let i = 0;\n\n // Handle empty path - treat as empty property access\n if (expr === '') {\n // Hybrid token: empty property is a string\n tokens.push('');\n cache[expr] = tokens;\n return cache[expr].map((token) => (\n typeof token === 'object' && token !== null ? {...token} : token\n ));\n }\n\n /**\n * Extract balanced content between delimiters.\n * @param {number} start - Starting position\n * @param {string} open - Opening delimiter\n * @param {string} close - Closing delimiter\n * @throws {SyntaxError} If delimiters are unbalanced\n * @returns {{content: string, end: number}} Extracted content and end position\n */\n function extractBalanced (start, open, close) {\n let depth = 1;\n let j = start;\n while (j < expr.length && depth > 0) {\n if (expr[j] === open) {\n depth++;\n } else if (expr[j] === close) {\n depth--;\n }\n j++;\n }\n if (depth !== 0) {\n throw new SyntaxError(\n `Unbalanced ${open}${close} in expression at position ${start}`\n );\n }\n return {content: expr.slice(start, j - 1), end: j};\n }\n\n /**\n * Extract quoted string.\n * @param {number} start - Starting position (after quote)\n * @param {string} quote - Quote character\n * @throws {SyntaxError} If string is unterminated\n * @returns {{content: string, end: number, escaped: boolean}} Extracted content, end position, and whether it's backtick-escaped\n */\n function extractQuoted (start, quote) {\n let j = start;\n let content = '';\n let escaped = false;\n\n while (j < expr.length) {\n if (expr[j] === '\\\\' && j + 1 < expr.length) {\n // Handle backslash escape sequences\n content += expr[j + 1];\n j += 2;\n } else if (expr[j] === '`' && j + 1 < expr.length) {\n // Handle backtick escape - backtick escapes next char\n content += expr[j + 1];\n escaped = true;\n j += 2;\n } else if (expr[j] === quote) {\n return {content, end: j + 1, escaped};\n } else {\n content += expr[j];\n j++;\n }\n }\n throw new SyntaxError(`Unterminated string at position ${start - 1}`);\n }\n\n /**\n * Handle dot notation (.property or ..descendant).\n * @throws {SyntaxError} If malformed\n * @returns {void}\n */\n function handleDotNotation () {\n if (i + 1 < expr.length && expr[i + 1] === '.') {\n // Descendant (..)\n tokens.push({type: 'descent'});\n i += 2;\n } else {\n // Skip the dot and parse property name\n i++;\n if (i >= expr.length) {\n throw new SyntaxError('Unexpected end after dot at position ' + (i - 1));\n }\n\n // Check what follows the dot\n switch (expr[i]) {\n case '*':\n tokens.push({type: 'wildcard'});\n i++;\n break;\n case '`':\n // Backtick escapes the next character\n i++; // Skip backtick\n if (i >= expr.length) {\n throw new SyntaxError(\n 'Unexpected end after backtick at position ' + (i - 1)\n );\n }\n // The escaped character becomes the property name\n tokens.push({\n type: 'property',\n value: expr[i],\n escaped: true\n });\n i++;\n break;\n case '[':\n // Dot followed by bracket: interpret as descent\n // e.g., $.[?(...)] becomes $ .. [?(...)]\n tokens.push({type: 'descent'});\n break;\n default: {\n // Regular property name (until next special char)\n let propName = '';\n while (i < expr.length && !(/[.[\\]^~@*]/u).test(expr[i])) {\n propName += expr[i];\n i++;\n }\n if (propName) {\n // Hybrid token: use string for unescaped properties\n tokens.push(propName);\n }\n }\n }\n }\n }\n\n /**\n * Handle bracket notation [...].\n * @throws {SyntaxError} If malformed\n * @returns {void}\n */\n function handleBracketNotation () {\n i++; // Skip [\n if (i >= expr.length) {\n throw new SyntaxError('Unexpected end after [ at position ' + (i - 1));\n }\n\n // Skip whitespace\n while (i < expr.length && (/\\s/u).test(expr[i])) {\n i++;\n }\n\n const ch = expr[i];\n\n // Wildcard [*]\n if (ch === '*') {\n i++;\n // Skip whitespace and closing bracket\n while (i < expr.length && (/\\s/u).test(expr[i])) {\n i++;\n }\n if (expr[i] !== ']') {\n throw new SyntaxError('Expected ] after * at position ' + i);\n }\n i++;\n tokens.push({type: 'wildcard'});\n return;\n }\n\n // Filter [?(expression)]\n if (ch === '?') {\n if (i + 1 >= expr.length || expr[i + 1] !== '(') {\n throw new SyntaxError(\n 'Expected ( after ? at position ' + i\n );\n }\n i += 2; // Skip ?(\n const result = extractBalanced(i, '(', ')');\n const {content: expression} = result;\n i = result.end;\n\n // Skip whitespace and closing bracket\n while (i < expr.length && (/\\s/u).test(expr[i])) {\n i++;\n }\n if (expr[i] !== ']') {\n throw new SyntaxError(\n 'Expected ] after filter at position ' + i\n );\n }\n i++;\n tokens.push({type: 'filter', expression});\n return;\n }\n\n // Dynamic [(expression)]\n if (ch === '(') {\n i++; // Skip (\n const result = extractBalanced(i, '(', ')');\n const {content: expression} = result;\n i = result.end;\n\n // Skip whitespace and closing bracket\n while (i < expr.length && (/\\s/u).test(expr[i])) {\n i++;\n }\n if (expr[i] !== ']') {\n throw new SyntaxError(\n 'Expected ] after dynamic expression at position ' + i\n );\n }\n i++;\n tokens.push({type: 'dynamic', expression});\n return;\n }\n\n // Quoted property ['name'] or [\"name\"]\n if (ch === \"'\" || ch === '\"') {\n const quote = ch;\n i++; // Skip opening quote\n const result = extractQuoted(i, quote);\n const {content, escaped} = result;\n i = result.end;\n\n // Skip whitespace\n while (i < expr.length && (/\\s/u).test(expr[i])) {\n i++;\n }\n\n // Check for comma (multi-property)\n if (expr[i] === ',') {\n const properties = [content];\n const escapedFlags = [escaped];\n while (expr[i] === ',') {\n i++; // Skip comma\n // Skip whitespace\n while (i < expr.length && (/\\s/u).test(expr[i])) {\n i++;\n }\n if (expr[i] !== \"'\" && expr[i] !== '\"') {\n throw new SyntaxError(\n 'Expected quoted property after comma at position ' + i\n );\n }\n const q = expr[i];\n i++;\n const r = extractQuoted(i, q);\n properties.push(r.content);\n escapedFlags.push(r.escaped);\n i = r.end;\n // Skip whitespace\n while (i < expr.length && (/\\s/u).test(expr[i])) {\n i++;\n }\n }\n if (expr[i] !== ']') {\n throw new SyntaxError(\n 'Expected ] after multi-property at position ' + i\n );\n }\n i++;\n tokens.push({\n type: 'multiProperty',\n properties,\n escaped: escapedFlags\n });\n return;\n }\n\n if (expr[i] !== ']') {\n throw new SyntaxError(\n 'Expected ] after quoted property at position ' + i\n );\n }\n i++;\n // Check if quoted property is wildcard\n if (content === '*' && !escaped) {\n tokens.push({type: 'wildcard'});\n } else if (escaped) {\n // Keep object for escaped properties (metadata needed)\n tokens.push({type: 'property', value: content, escaped: true});\n } else {\n // Hybrid token: use string for unescaped properties\n tokens.push(content);\n }\n return;\n }\n\n // Number (index, slice, or multi-index)\n if ((/[-\\d]/u).test(ch) || ch === ':') {\n let numStr = '';\n while (i < expr.length && (/[-\\d:]/u).test(expr[i])) {\n numStr += expr[i];\n i++;\n }\n\n // Skip whitespace\n while (i < expr.length && (/\\s/u).test(expr[i])) {\n i++;\n }\n\n // Check for comma (multi-index like [0,1,2])\n if (expr[i] === ',') {\n const indices = [Number.parseInt(numStr)];\n while (expr[i] === ',') {\n i++; // Skip comma\n // Skip whitespace\n while (i < expr.length && (/\\s/u).test(expr[i])) {\n i++;\n }\n // Read next number\n let nextNum = '';\n while (i < expr.length && (/[-\\d]/u).test(expr[i])) {\n nextNum += expr[i];\n i++;\n }\n indices.push(Number.parseInt(nextNum));\n // Skip whitespace\n while (i < expr.length && (/\\s/u).test(expr[i])) {\n i++;\n }\n }\n if (expr[i] !== ']') {\n throw new SyntaxError(\n 'Expected ] after multi-index at position ' + i\n );\n }\n i++;\n // Create multiProperty token with numeric properties\n tokens.push({type: 'multiProperty', properties: indices});\n return;\n }\n\n if (expr[i] !== ']') {\n throw new SyntaxError(\n 'Expected ] after number at position ' + i\n );\n }\n i++;\n\n // Check if it's a slice (contains :)\n if (numStr.includes(':')) {\n const parts = numStr.split(':');\n const start = parts[0] === ''\n ? null\n : Number.parseInt(parts[0]);\n const end = parts[1] === ''\n ? null\n : Number.parseInt(parts[1]);\n const step = parts.length > 2 && parts[2] !== ''\n ? Number.parseInt(parts[2])\n : null;\n tokens.push({type: 'slice', start, end, step, raw: numStr});\n } else {\n // Simple index - Hybrid token: use number directly\n const index = Number.parseInt(numStr);\n tokens.push(index);\n }\n return;\n }\n\n // Unquoted property (identifier)\n // In brackets, unquoted properties can have backtick escapes\n let propName = '';\n let escaped = false;\n while (i < expr.length && expr[i] !== ']' && expr[i] !== ',' &&\n !(/\\s/u).test(expr[i])) {\n if (expr[i] === '`' && i + 1 < expr.length &&\n expr[i + 1] !== ']' && expr[i + 1] !== ',') {\n // Backtick escapes next character\n propName += expr[i + 1];\n escaped = true;\n i += 2;\n } else {\n propName += expr[i];\n i++;\n }\n }\n\n // Skip whitespace\n while (i < expr.length && (/\\s/u).test(expr[i])) {\n i++;\n }\n\n // Check for comma (multi-property with unquoted names)\n if (expr[i] === ',') {\n const properties = [propName];\n const escapedFlags = [escaped];\n while (expr[i] === ',') {\n i++; // Skip comma\n // Skip whitespace\n while (i < expr.length && (/\\s/u).test(expr[i])) {\n i++;\n }\n let prop = '';\n let propEscaped = false;\n while (i < expr.length && expr[i] !== ']' && expr[i] !== ',' &&\n !(/\\s/u).test(expr[i])) {\n if (expr[i] === '`' && i + 1 < expr.length &&\n expr[i + 1] !== ']' && expr[i + 1] !== ',') {\n // Backtick escapes next character\n prop += expr[i + 1];\n propEscaped = true;\n i += 2;\n } else {\n prop += expr[i];\n i++;\n }\n }\n if (!prop) {\n throw new SyntaxError(\n 'Expected property name after comma at position ' + i\n );\n }\n properties.push(prop);\n escapedFlags.push(propEscaped);\n // Skip whitespace\n while (i < expr.length && (/\\s/u).test(expr[i])) {\n i++;\n }\n }\n if (expr[i] !== ']') {\n throw new SyntaxError(\n 'Expected ] after multi-property at position ' + i\n );\n }\n i++;\n tokens.push({\n type: 'multiProperty',\n properties,\n escaped: escapedFlags\n });\n return;\n }\n\n if (expr[i] !== ']') {\n throw new SyntaxError(\n 'Expected ] after property at position ' + i\n );\n }\n i++;\n if (propName) {\n if (escaped) {\n // Keep object for escaped properties\n tokens.push({type: 'property', value: propName, escaped: true});\n } else {\n // Hybrid token: use string for unescaped properties\n tokens.push(propName);\n }\n }\n }\n\n /**\n * Handle type operator `@type()`.\n * @throws {SyntaxError} If malformed\n * @returns {void}\n */\n function handleTypeOperator () {\n i++; // Skip @\n let typeName = '';\n while (i < expr.length && (/[a-z]/ui).test(expr[i])) {\n typeName += expr[i];\n i++;\n }\n if (i + 1 >= expr.length || expr[i] !== '(' || expr[i + 1] !== ')') {\n throw new SyntaxError(\n 'Expected () after @' + typeName + ' at position ' + i\n );\n }\n i += 2; // Skip ()\n tokens.push({type: 'typeOperator', valueType: typeName});\n }\n\n // If path doesn't start with $, [, or other special char, add implicit root\n if (expr.length > 0 && !['$', '[', '.', '^', '~', '@'].includes(expr[0])) {\n tokens.push({type: 'root'});\n // Prepend with a dot to make it valid for our parser\n expr = '.' + expr;\n }\n\n // Main parsing loop\n while (i < expr.length) {\n const ch = expr[i];\n\n switch (ch) {\n case '$':\n tokens.push({type: 'root'});\n i++;\n break;\n case '.':\n handleDotNotation();\n break;\n case '[':\n handleBracketNotation();\n break;\n case '*':\n // Wildcard (can appear after .. without a dot)\n tokens.push({type: 'wildcard'});\n i++;\n break;\n case '^':\n // If parent selector comes right after root (or at start),\n // add implicit empty string property\n // This handles cases like \"^\" or \"$^\" which should be \"['']^\"\n if (tokens.length === 0 ||\n (tokens.length === 1 && tokens[0].type === 'root')) {\n // Hybrid token: empty property is a string\n tokens.push('');\n }\n tokens.push({type: 'parent'});\n i++;\n break;\n case '~':\n tokens.push({type: 'propertyName'});\n i++;\n break;\n case '@':\n // Check if this is a type operator like @boolean()\n // Type operators have the pattern: @identifier()\n if ((/^@[a-z]+\\(\\)/ui).test(expr.slice(i))) {\n handleTypeOperator();\n } else {\n // Treat @ as part of a property name\n let propName = '';\n while (i < expr.length && (/[\\w$@\\\\]/u).test(expr[i])) {\n propName += expr[i];\n i++;\n }\n if (propName) {\n // Hybrid token: use string for unescaped properties\n tokens.push(propName);\n }\n }\n break;\n case ' ':\n case '\\t':\n case '\\n':\n case '\\r':\n // Skip whitespace\n i++;\n break;\n default:\n // Try to parse as identifier (property name)\n if ((/[\\w$]/u).test(ch)) {\n let propName = '';\n while (i < expr.length && (/[\\w$]/u).test(expr[i])) {\n propName += expr[i];\n i++;\n }\n // Hybrid token: use string for unescaped properties\n tokens.push(propName);\n } else {\n throw new SyntaxError(\n `Unexpected character '${ch}' at position ${i}`\n );\n }\n }\n }\n\n cache[expr] = tokens;\n return tokens.map((token) => (\n typeof token === 'object' && token !== null ? {...token} : token\n ));\n};\n\nJSONPath.prototype.safeVm = {\n Script: SafeScript\n};\n\nexport {JSONPath};\n","import {JSONPath} from './jsonpath.js';\n\n/**\n * @typedef {any} ContextItem\n */\n\n/**\n * @typedef {any} EvaluatedResult\n */\n\n/**\n * @callback ConditionCallback\n * @param {ContextItem} item\n * @returns {boolean}\n */\n\n/**\n * Copy items out of one array into another.\n * @param {GenericArray} source Array with items to copy\n * @param {GenericArray} target Array to which to copy\n * @param {ConditionCallback} conditionCb Callback passed the current item;\n * will move item if evaluates to `true`\n * @returns {void}\n */\nconst moveToAnotherArray = function (source, target, conditionCb) {\n const il = source.length;\n for (let i = 0; i < il; i++) {\n const item = source[i];\n if (conditionCb(item)) {\n // eslint-disable-next-line @stylistic/max-len -- Long\n // eslint-disable-next-line sonarjs/updated-loop-counter -- Convenient\n target.push(source.splice(i--, 1)[0]);\n }\n }\n};\n\n/**\n * In-browser replacement for NodeJS' VM.Script.\n */\nclass Script {\n /**\n * @param {string} expr Expression to evaluate\n */\n constructor (expr) {\n this.code = expr;\n }\n\n /**\n * @param {object} context Object whose items will be added\n * to evaluation\n * @returns {EvaluatedResult} Result of evaluated code\n */\n runInNewContext (context) {\n let expr = this.code;\n const keys = Object.keys(context);\n const funcs = [];\n moveToAnotherArray(keys, funcs, (key) => {\n return typeof context[key] === 'function';\n });\n const values = keys.map((vr) => {\n return context[vr];\n });\n\n const funcString = funcs.reduce((s, func) => {\n let fString = context[func].toString();\n if (!(/function/u).test(fString)) {\n fString = 'function ' + fString;\n }\n return 'var ' + func + '=' + fString + ';' + s;\n }, '');\n\n expr = funcString + expr;\n\n // Mitigate http://perfectionkills.com/global-eval-what-are-the-options/#new_function\n if (!(/(['\"])use strict\\1/u).test(expr) && !keys.includes('arguments')) {\n expr = 'var arguments = undefined;' + expr;\n }\n\n // Remove last semi so `return` will be inserted before\n // the previous one instead, allowing for the return\n // of a bare ending expression\n expr = expr.replace(/;\\s*$/u, '');\n\n // Insert `return`\n const lastStatementEnd = expr.lastIndexOf(';');\n const code =\n lastStatementEnd !== -1\n ? expr.slice(0, lastStatementEnd + 1) +\n ' return ' +\n expr.slice(lastStatementEnd + 1)\n : ' return ' + expr;\n\n // eslint-disable-next-line no-new-func -- User's choice\n return new Function(...keys, code)(...values);\n }\n}\n\nJSONPath.prototype.vm = {\n Script\n};\n\nexport {JSONPath};\n"],"names":["Jsep","version","toString","addUnaryOp","op_name","max_unop_len","Math","max","length","unary_ops","addBinaryOp","precedence","isRightAssociative","max_binop_len","binary_ops","right_associative","add","delete","addIdentifierChar","char","additional_identifier_chars","addLiteral","literal_name","literal_value","literals","removeUnaryOp","getMaxKeyLen","removeAllUnaryOps","removeIdentifierChar","removeBinaryOp","removeAllBinaryOps","removeLiteral","removeAllLiterals","this","expr","charAt","index","code","charCodeAt","constructor","parse","obj","Object","keys","map","k","isDecimalDigit","ch","binaryPrecedence","op_val","isIdentifierStart","String","fromCharCode","has","isIdentifierPart","throwError","message","error","Error","description","runHook","name","node","hooks","env","context","run","searchHook","find","callback","call","gobbleSpaces","SPACE_CODE","TAB_CODE","LF_CODE","CR_CODE","nodes","gobbleExpressions","type","COMPOUND","body","untilICode","ch_i","SEMCOL_CODE","COMMA_CODE","gobbleExpression","push","gobbleBinaryExpression","gobbleBinaryOp","to_check","substr","tc_len","hasOwnProperty","biop","prec","stack","biop_info","left","right","i","cur_biop","gobbleToken","value","right_a","comparePrev","prev","pop","BINARY_EXP","operator","PERIOD_CODE","gobbleNumericLiteral","SQUOTE_CODE","DQUOTE_CODE","gobbleStringLiteral","OBRACK_CODE","gobbleArray","argument","UNARY_EXP","prefix","gobbleIdentifier","LITERAL","raw","this_str","THIS_EXP","OPAREN_CODE","gobbleGroup","gobbleTokenProperty","QUMARK_CODE","optional","MEMBER_EXP","computed","object","property","CBRACK_CODE","CALL_EXP","arguments","gobbleArguments","CPAREN_CODE","callee","chCode","number","parseFloat","str","startIndex","quote","closed","substring","start","IDENTIFIER","slice","termination","args","separator_count","arg","SEQUENCE_EXP","expressions","ARRAY_EXP","elements","first","Array","isArray","forEach","assign","plugins","jsep","registered","register","plugin","init","COLON_CODE","Set","true","false","null","stdClassProps","getOwnPropertyNames","filter","prop","includes","undefined","m","ternary","test","consequent","alternate","newTest","patternIndex","inCharSet","pattern","flags","RegExp","e","assignmentOperators","updateOperators","assignmentPrecedence","updateNodeTypes","updateBinariesToAssignments","values","val","op","some","c","jsepRegex","jsepAssignment","BLOCKED_PROTO_PROPERTIES","SafeEval","evalAst","ast","subs","evalBinaryExpression","evalCompound","evalConditionalExpression","evalIdentifier","evalLiteral","evalMemberExpression","evalUnaryExpression","evalArrayExpression","evalCallExpression","evalAssignmentExpression","SyntaxError","||","a","b","&&","|","^","&","==","!=","===","!==","<",">","<=",">=","<<",">>",">>>","+","-","*","/","%","last","hasOwn","ReferenceError","TypeError","result","bind","typeof","void","el","func","Function","id","arr","item","unshift","NewError","super","avoidNew","JSONPath","opts","otherTypeCallback","optObj","json","path","resultType","flatten","wrap","sandbox","eval","ignoreEvalErrors","parent","parentProperty","autostart","ret","evaluate","prototype","currParent","currParentProperty","currResultType","currEval","currSandbox","currOtherTypeCallback","toPathString","exprList","toPathParts","shift","_hasParentSelector","_json","_trace","ea","isParentSelector","hasArrExpr","reduce","rslt","valOrPath","_getPreferredOutput","concat","pointer","toPointer","_handleCallback","fullRetObj","preferredOutput","parentPropName","literalPriority","retObj","token","x","addRet","elems","t","propName","_walk","idx","_slice","expression","modifiedExpr","nestedPaths","_extractNestedFilters","isSingleNestedPath","trim","nestedResults","nestedPath","entries","pathForParsing","replace","nestedTokens","nestedResult","r","originalSandbox","_$_jp0","_eval","at","addType","valueType","Number","isFinite","parts","properties","escapedFlags","escaped","part","partToken","rett","resultVal","resultParent","resultParentProp","tmp","tl","tt","splice","f","n","cache","filterExtractionCache","placeholderCount","findNextNestedPath","startPos","prevNonSpace","trimEnd","pathStart","hasPathSyntax","depth","q","end","searchPos","replacements","found","placeholder","extractionResult","len","step","min","_v","_vname","_$_parentProperty","_$_parent","_$_property","_$_root","_$_v","containsPath","_$_path","scriptCacheKey","script","replaceAll","safeVm","Script","vm","CurrEval","runInNewContext","pathPartsCache","pathArr","p","join","propValue","indexValue","tokens","extractBalanced","open","close","j","content","extractQuoted","handleDotNotation","handleBracketNotation","numStr","indices","parseInt","nextNum","split","propEscaped","handleTypeOperator","typeName","keyMap","create","funcs","source","target","conditionCb","il","moveToAnotherArray","key","vr","s","fString","lastStatementEnd","lastIndexOf"],"mappings":"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","x_google_ignoreList":[0,1,2]}
\ No newline at end of file
diff --git a/dist/index-browser-umd.cjs b/dist/index-browser-umd.cjs
index a1c55bd..1b369c5 100644
--- a/dist/index-browser-umd.cjs
+++ b/dist/index-browser-umd.cjs
@@ -81,10 +81,7 @@
* @param {PluginSetup} plugins.init The init function
* @public
*/
- register() {
- for (var _len = arguments.length, plugins = new Array(_len), _key = 0; _key < _len; _key++) {
- plugins[_key] = arguments[_key];
- }
+ register(...plugins) {
plugins.forEach(plugin => {
if (typeof plugin !== 'object' || !plugin.name || !plugin.init) {
throw new Error('Invalid JSEP plugin format');
@@ -1614,11 +1611,12 @@
if (!expr && expr !== '' || !json) {
return undefined;
}
- const exprList = JSONPath.toPathArray(expr);
- if (exprList[0] === '$' && exprList.length > 1) {
+ const exprList = JSONPath.toPathParts(expr);
+ if (exprList[0] && exprList[0].type === 'root' && exprList.length > 1) {
exprList.shift();
}
this._hasParentSelector = null;
+ this._json = json; // Store root for parent selector navigation
const result = this._trace(exprList, json, ['$'], currParent, currParentProperty, callback).filter(function (ea) {
return ea && !ea.isParentSelector;
});
@@ -1646,7 +1644,7 @@
switch (resultType) {
case 'all':
{
- const path = Array.isArray(ea.path) ? ea.path : JSONPath.toPathArray(ea.path);
+ const path = Array.isArray(ea.path) ? ea.path : JSONPath.toPathParts(ea.path);
ea.pointer = JSONPath.toPointer(path);
ea.path = typeof ea.path === 'string' ? ea.path : JSONPath.toPathString(ea.path);
return ea;
@@ -1697,9 +1695,9 @@
hasArrExpr
};
this._handleCallback(retObj, callback, 'value');
- return retObj;
+ return [retObj];
}
- const loc = expr[0],
+ const token = expr[0],
x = expr.slice(1);
// We need to gather the return value of recursive trace calls in order to
@@ -1722,168 +1720,266 @@
ret.push(elems);
}
}
- if ((typeof loc !== 'string' || literalPriority) && val && Object.hasOwn(val, loc)) {
- // simple case--directly follow property
- addRet(this._trace(x, val[loc], push(path, loc), val, loc, callback, hasArrExpr));
- // eslint-disable-next-line unicorn/prefer-switch -- Part of larger `if`
- } else if (loc === '*') {
- // all child properties
- this._walk(val, m => {
- addRet(this._trace(x, val[m], push(path, m), val, m, callback, true, true));
- });
- } else if (loc === '..') {
- // all descendent parent properties
- // Check remaining expression with val's immediate children
- addRet(this._trace(x, val, path, parent, parentPropName, callback, hasArrExpr));
- this._walk(val, m => {
- // We don't join m and x here because we only want parents,
- // not scalar values
- if (typeof val[m] === 'object') {
- // Keep going with recursive descent on val's
- // object children
- addRet(this._trace(expr.slice(), val[m], push(path, m), val, m, callback, true));
- }
- });
- // The parent sel computation is handled in the frame above using the
- // ancestor object of val
- } else if (loc === '^') {
- // This is not a final endpoint, so we do not invoke the callback here
- this._hasParentSelector = true;
- return {
- path: path.slice(0, -1),
- expr: x,
- isParentSelector: true
- };
- } else if (loc === '~') {
- // property name
- retObj = {
- path: push(path, loc),
- value: parentPropName,
- parent,
- parentProperty: null
- };
- this._handleCallback(retObj, callback, 'property');
- return retObj;
- } else if (loc === '$') {
- // root only
- addRet(this._trace(x, val, path, null, null, callback, hasArrExpr));
- } else if (/^(-?\d*):(-?\d*):?(\d*)$/u.test(loc)) {
- // [start:end:step] Python slice syntax
- addRet(this._slice(loc, x, val, path, parent, parentPropName, callback));
- } else if (loc.indexOf('?(') === 0) {
- // [?(expr)] (filtering)
- if (this.currEval === false) {
- throw new Error('Eval [?(expr)] prevented in JSONPath expression.');
- }
- const safeLoc = loc.replace(/^\?\((.*?)\)$/u, '$1');
- // check for a nested filter expression
- const nested = /@.?([^?]*)[['](\??\(.*?\))(?!.\)\])[\]']/gu.exec(safeLoc);
- if (nested) {
- // find if there are matches in the nested expression
- // add them to the result set if there is at least one match
- this._walk(val, m => {
- const npath = [nested[2]];
- const nvalue = nested[1] ? val[m][nested[1]] : val[m];
- const filterResults = this._trace(npath, nvalue, path, parent, parentPropName, callback, true);
- if (filterResults.length > 0) {
- addRet(this._trace(x, val[m], push(path, m), val, m, callback, true));
- }
- });
- } else {
- this._walk(val, m => {
- if (this._eval(safeLoc, val[m], m, path, parent, parentPropName)) {
- addRet(this._trace(x, val[m], push(path, m), val, m, callback, true));
- }
- });
+
+ // Fast path for primitive tokens (strings and numbers)
+ if (typeof token === 'string') {
+ // Simple property access
+ if (val && Object.hasOwn(val, token)) {
+ addRet(this._trace(x, val[token], push(path, token), val, token, callback, hasArrExpr));
}
- } else if (loc[0] === '(') {
- // [(expr)] (dynamic property/index)
- if (this.currEval === false) {
- throw new Error('Eval [(expr)] prevented in JSONPath expression.');
- }
- // As this will resolve to a property name (but we don't know it
- // yet), property and parent information is relative to the
- // parent of the property to which this expression will resolve
- addRet(this._trace(unshift(this._eval(loc, val, path.at(-1), path.slice(0, -1), parent, parentPropName), x), val, path, parent, parentPropName, callback, hasArrExpr));
- } else if (loc[0] === '@') {
- // value type: @boolean(), etc.
- let addType = false;
- const valueType = loc.slice(1, -2);
- switch (valueType) {
- case 'scalar':
- if (!val || !['object', 'function'].includes(typeof val)) {
- addType = true;
- }
+ } else if (typeof token === 'number') {
+ // Simple numeric index access
+ if (Array.isArray(val) && token >= 0 && token < val.length) {
+ addRet(this._trace(x, val[token], push(path, token), val, token, callback, hasArrExpr));
+ }
+ } else if (token && typeof token === 'object' && token.type) {
+ // Handle complex token objects
+ switch (token.type) {
+ case 'root':
+ // $
+ addRet(this._trace(x, val, path, null, null, callback, hasArrExpr));
break;
- case 'boolean':
- case 'string':
- case 'undefined':
- case 'function':
- if (typeof val === valueType) {
- addType = true;
+ case 'property':
+ {
+ const propName = token.value;
+ // Check if property exists (escaped flag just means it's not wildcard)
+ if (val && Object.hasOwn(val, propName)) {
+ addRet(this._trace(x, val[propName], push(path, propName), val, propName, callback, hasArrExpr, true));
+ }
+ break;
}
+ case 'wildcard':
+ // *
+ this._walk(val, m => {
+ addRet(this._trace(x, val[m], push(path, m), val, m, callback, true, true));
+ });
break;
- case 'integer':
- if (Number.isFinite(val) && !(val % 1)) {
- addType = true;
- }
+ case 'descent':
+ // ..
+ // Check remaining expression with val's immediate children
+ addRet(this._trace(x, val, path, parent, parentPropName, callback, hasArrExpr));
+ this._walk(val, m => {
+ // We don't join m and x here because we only want parents,
+ // not scalar values
+ if (typeof val[m] === 'object') {
+ // Keep going with recursive descent on val's
+ // object children
+ addRet(this._trace(expr.slice(), val[m], push(path, m), val, m, callback, true));
+ }
+ });
break;
- case 'number':
- if (Number.isFinite(val)) {
- addType = true;
+ case 'parent':
+ // ^
+ // This is not a final endpoint, so we do not invoke the callback here
+ // Only allow parent selector if we're not already at root
+ if (path.length > 1) {
+ this._hasParentSelector = true;
+ ret.push({
+ path: path.slice(0, -1),
+ expr: x,
+ isParentSelector: true
+ });
}
break;
- case 'nonFinite':
- if (typeof val === 'number' && !Number.isFinite(val)) {
- addType = true;
- }
+ case 'propertyName':
+ // ~
+ retObj = {
+ path: push(path, '~'),
+ value: parentPropName,
+ parent,
+ parentProperty: null
+ };
+ this._handleCallback(retObj, callback, 'property');
+ ret.push(retObj);
break;
- case 'object':
- if (val && typeof val === valueType) {
- addType = true;
+ case 'index':
+ {
+ const idx = token.value;
+ if (Array.isArray(val) && idx >= 0 && idx < val.length || val && Object.hasOwn(val, idx)) {
+ addRet(this._trace(x, val[idx], push(path, idx), val, idx, callback, hasArrExpr, true));
+ }
+ break;
}
+ case 'slice':
+ addRet(this._slice(token, x, val, path, parent, parentPropName, callback));
break;
- case 'array':
- if (Array.isArray(val)) {
- addType = true;
+ case 'filter':
+ {
+ if (this.currEval === false) {
+ throw new Error('Eval [?(expr)] prevented in JSONPath expression.');
+ }
+
+ // Quick check: Does this filter have nested paths?
+ const hasNesting = token.expression.includes('[?(');
+ if (!hasNesting) {
+ // Fast path: No nesting, skip extraction
+ this._walk(val, m => {
+ if (this._eval(token.expression, val[m], m, path, parent, parentPropName)) {
+ addRet(this._trace(x, val[m], push(path, m), val, m, callback, true));
+ }
+ });
+ } else {
+ // Slow path: Extract and handle nested filters
+ const {
+ expression: modifiedExpr,
+ nestedPaths
+ } = this._extractNestedFilters(token.expression);
+
+ // Check if expression is JUST a nested path (no other JavaScript)
+ // If so, we need to check array length for truthiness
+ const isSingleNestedPath = nestedPaths.length === 1 && modifiedExpr.trim() === '_$_jp0';
+
+ // Evaluate filter for each item
+ this._walk(val, m => {
+ // Evaluate nested paths in context of current item
+ const nestedResults = {};
+ for (const [i, nestedPath] of nestedPaths.entries()) {
+ // Convert @ to $ for parsing (@ means current value)
+ const pathForParsing = nestedPath.replace(/^@/u, '$');
+ try {
+ const nestedTokens = JSONPath.toPathParts(pathForParsing);
+ // Evaluate nested path on current item
+ const nestedResult = this._trace(nestedTokens, val[m], push(path, m), val, m, null,
+ // no callback for nested evaluation
+ true);
+ // Extract values from result objects
+ nestedResults[`_$_jp${i}`] = nestedResult.map(r => r.value);
+ } catch (e) {
+ // If nested evaluation fails, treat as no matches
+ nestedResults[`_$_jp${i}`] = [];
+ }
+ }
+
+ // Add nested results to sandbox temporarily
+ const originalSandbox = {
+ ...this.currSandbox
+ };
+ Object.assign(this.currSandbox, nestedResults);
+ try {
+ // For single nested path, check if array has elements
+ // (empty arrays are truthy in JS but should be falsy in filter)
+ const matches = isSingleNestedPath ? nestedResults._$_jp0.length > 0 : this._eval(modifiedExpr, val[m], m, path, parent, parentPropName);
+ if (matches) {
+ addRet(this._trace(x, val[m], push(path, m), val, m, callback, true));
+ }
+ } finally {
+ // Restore original sandbox (remove nested result placeholders)
+ this.currSandbox = originalSandbox;
+ }
+ });
+ }
+ break;
}
- break;
- case 'other':
- addType = this.currOtherTypeCallback(val, path, parent, parentPropName);
- break;
- case 'null':
- if (val === null) {
- addType = true;
+ case 'dynamic':
+ {
+ if (this.currEval === false) {
+ throw new Error('Eval [(expr)] prevented in JSONPath expression.');
+ }
+ // As this will resolve to a property name (but we don't know it
+ // yet), property and parent information is relative to the
+ // parent of the property to which this expression will resolve
+ addRet(this._trace(unshift(this._eval(token.expression, val, path.at(-1), path.slice(0, -1), parent, parentPropName), x), val, path, parent, parentPropName, callback, hasArrExpr));
+ break;
+ }
+ case 'typeOperator':
+ {
+ let addType = false;
+ const {
+ valueType
+ } = token;
+ switch (valueType) {
+ case 'scalar':
+ if (!val || !['object', 'function'].includes(typeof val)) {
+ addType = true;
+ }
+ break;
+ case 'boolean':
+ case 'string':
+ case 'undefined':
+ case 'function':
+ if (typeof val === valueType) {
+ addType = true;
+ }
+ break;
+ case 'integer':
+ if (Number.isFinite(val) && !(val % 1)) {
+ addType = true;
+ }
+ break;
+ case 'number':
+ if (Number.isFinite(val)) {
+ addType = true;
+ }
+ break;
+ case 'nonFinite':
+ if (typeof val === 'number' && !Number.isFinite(val)) {
+ addType = true;
+ }
+ break;
+ case 'object':
+ if (val && typeof val === valueType) {
+ addType = true;
+ }
+ break;
+ case 'array':
+ if (Array.isArray(val)) {
+ addType = true;
+ }
+ break;
+ case 'other':
+ addType = this.currOtherTypeCallback(val, path, parent, parentPropName);
+ break;
+ case 'null':
+ if (val === null) {
+ addType = true;
+ }
+ break;
+ /* c8 ignore next 2 */
+ default:
+ throw new TypeError('Unknown value type ' + valueType);
+ }
+ if (addType) {
+ retObj = {
+ path,
+ value: val,
+ parent,
+ parentProperty: parentPropName
+ };
+ this._handleCallback(retObj, callback, 'value');
+ ret.push(retObj);
+ }
+ break;
+ }
+ case 'multiProperty':
+ {
+ const parts = token.properties;
+ const escapedFlags = token.escaped || [];
+ for (const [i, part] of parts.entries()) {
+ // Check if part is a number (multi-index) or string (multi-property)
+ let partToken;
+ if (typeof part === 'number') {
+ partToken = {
+ type: 'index',
+ value: part
+ };
+ } else {
+ const isEscaped = escapedFlags[i] || false;
+ partToken = {
+ type: 'property',
+ value: part,
+ escaped: isEscaped
+ };
+ }
+ addRet(this._trace(unshift(partToken, x), val, path, parent, parentPropName, callback, true));
+ }
+ break;
}
- break;
- /* c8 ignore next 2 */
- default:
- throw new TypeError('Unknown value type ' + valueType);
- }
- if (addType) {
- retObj = {
- path,
- value: val,
- parent,
- parentProperty: parentPropName
- };
- this._handleCallback(retObj, callback, 'value');
- return retObj;
- }
- // `-escaped property
- } else if (loc[0] === '`' && val && Object.hasOwn(val, loc.slice(1))) {
- const locProp = loc.slice(1);
- addRet(this._trace(x, val[locProp], push(path, locProp), val, locProp, callback, hasArrExpr, true));
- } else if (loc.includes(',')) {
- // [name1,name2,...]
- const parts = loc.split(',');
- for (const part of parts) {
- addRet(this._trace(unshift(part, x), val, path, parent, parentPropName, callback, true));
}
- // simple case--directly follow property
- } else if (!literalPriority && val && Object.hasOwn(val, loc)) {
- addRet(this._trace(x, val[loc], push(path, loc), val, loc, callback, hasArrExpr, true));
+ } else if ((typeof token !== 'string' || literalPriority) && val && Object.hasOwn(val, token)) {
+ // simple case--directly follow property (for object tokens or with literalPriority)
+ addRet(this._trace(x, val[token], push(path, token), val, token, callback, hasArrExpr));
}
+ // Note: Legacy string token handling removed - now handled by fast path above
// We check the resulting values for parent selections. For parent
// selections we discard the value object and continue the trace with the
@@ -1892,7 +1988,20 @@
for (let t = 0; t < ret.length; t++) {
const rett = ret[t];
if (rett && rett.isParentSelector) {
- const tmp = this._trace(rett.expr, val, rett.path, parent, parentPropName, callback, hasArrExpr);
+ // Navigate from root to the parent path to get correct parent context
+ // rett.path is the path with last element removed (e.g., ['$', 'children'])
+ let resultVal = this._json;
+ let resultParent = null;
+ let resultParentProp = null;
+
+ // Navigate from root following the path
+ // Start at index 1 to skip '$'
+ for (let i = 1; i < rett.path.length; i++) {
+ resultParent = resultVal;
+ resultParentProp = rett.path[i];
+ resultVal = resultVal[rett.path[i]];
+ }
+ const tmp = this._trace(rett.expr, resultVal, rett.path, resultParent, resultParentProp, callback, hasArrExpr);
if (Array.isArray(tmp)) {
ret[t] = tmp[0];
const tl = tmp.length;
@@ -1922,15 +2031,229 @@
});
}
};
- JSONPath.prototype._slice = function (loc, expr, val, path, parent, parentPropName, callback) {
+
+ /**
+ * Extract nested JSONPath expressions from a filter expression.
+ * @param {string} expr - Filter expression (e.g., "@.children[?(@.price<10)]")
+ * @returns {{expression: string, nestedPaths: string[]}} Modified expression and extracted paths
+ */
+ JSONPath.prototype._extractNestedFilters = function (expr) {
+ // Check cache first
+ const cache = JSONPath.filterExtractionCache;
+ if (cache[expr]) {
+ // Return shallow clone to prevent mutation
+ return {
+ expression: cache[expr].expression,
+ nestedPaths: [...cache[expr].nestedPaths]
+ };
+ }
+ const nestedPaths = [];
+ let result = expr;
+ let placeholderCount = 0;
+
+ // We need to find patterns like @.path[?(...)] or @[?(...)], etc.
+ // Use a stack-based approach to handle nested brackets properly
+
+ /**
+ * Find the next JSONPath expression starting with @.
+ * @param {string} str - String to search
+ * @param {number} startPos - Position to start searching
+ * @returns {{start: number, end: number, path: string} | null}
+ */
+ function findNextNestedPath(str, startPos) {
+ let i = startPos;
+
+ // Find next @ that's not in a string or regex literal
+ while (i < str.length) {
+ const ch = str[i];
+
+ // Skip string literals
+ if (ch === '"' || ch === "'") {
+ const quote = ch;
+ i++;
+ while (i < str.length) {
+ if (str[i] === '\\' && i + 1 < str.length) {
+ i += 2; // Skip escaped character
+ } else if (str[i] === quote) {
+ i++;
+ break;
+ } else {
+ i++;
+ }
+ }
+ continue;
+ }
+
+ // Skip regex literals (simplified detection)
+ if (ch === '/' && i > 0) {
+ // Check if this might be a regex (not division)
+ // Look back for operators that could precede a regex
+ const prevNonSpace = str.slice(0, i).trimEnd().slice(-1);
+ if ('=([{,;:!&|?'.includes(prevNonSpace) || i === startPos) {
+ i++;
+ while (i < str.length) {
+ if (str[i] === '\\' && i + 1 < str.length) {
+ i += 2;
+ } else if (str[i] === '/') {
+ i++;
+ // Skip regex flags
+ while (i < str.length && /[gimsuvy]/u.test(str[i])) {
+ i++;
+ }
+ break;
+ } else {
+ i++;
+ }
+ }
+ continue;
+ }
+ }
+
+ // Found @ - check if it's followed by JSONPath syntax
+ if (ch === '@') {
+ const pathStart = i;
+ i++; // Move past @
+
+ // Check if there's path syntax after @
+ // Could be: @.prop, @[, @.., @@
+ if (i >= str.length) {
+ return null;
+ }
+ let hasPathSyntax = false;
+ let path = '@';
+
+ // Parse the JSONPath expression
+ while (i < str.length) {
+ const c = str[i];
+
+ // Path components
+ if (c === '.' || c === '[' || c === '*' || c === '^' || c === '~') {
+ hasPathSyntax = true;
+ path += c;
+ i++;
+
+ // Handle bracket notation with bracket matching
+ if (c === '[') {
+ let depth = 1;
+ /* eslint-disable unicorn/prefer-switch --
+ Complex bracket matching with nested quotes */
+ while (i < str.length && depth > 0) {
+ if (str[i] === '\\' && i + 1 < str.length) {
+ path += str[i] + str[i + 1];
+ i += 2;
+ } else if (str[i] === '"' || str[i] === "'") {
+ // Handle quoted strings in brackets
+ const q = str[i];
+ path += str[i];
+ i++;
+ while (i < str.length && str[i] !== q) {
+ if (str[i] === '\\' && i + 1 < str.length) {
+ path += str[i] + str[i + 1];
+ i += 2;
+ } else {
+ path += str[i];
+ i++;
+ }
+ }
+ if (i < str.length) {
+ path += str[i];
+ i++;
+ }
+ } else if (str[i] === '[') {
+ depth++;
+ path += str[i];
+ i++;
+ } else if (str[i] === ']') {
+ depth--;
+ path += str[i];
+ i++;
+ } else {
+ path += str[i];
+ i++;
+ }
+ }
+ /* eslint-enable unicorn/prefer-switch --
+ Re-enable after bracket matching section */
+ }
+ } else if (/[\w$]/u.test(c)) {
+ // Property name characters
+ hasPathSyntax = true;
+ path += c;
+ i++;
+ } else {
+ // End of path
+ break;
+ }
+ }
+
+ // Check if this path contains a filter (has [?(...)])
+ // Only extract paths that have filters to avoid unnecessary evaluation
+ if (hasPathSyntax && path.includes('[?')) {
+ return {
+ start: pathStart,
+ end: i,
+ path
+ };
+ }
+
+ // No filter found, continue searching
+ continue;
+ }
+ i++;
+ }
+ return null;
+ }
+
+ // Extract all nested paths
+ let searchPos = 0;
+ const replacements = [];
+ while (searchPos < result.length) {
+ const found = findNextNestedPath(result, searchPos);
+ if (!found) {
+ break;
+ }
+
+ // Store the replacement to be made
+ replacements.push({
+ start: found.start,
+ end: found.end,
+ path: found.path,
+ placeholder: `_$_jp${placeholderCount}`
+ });
+ nestedPaths.push(found.path);
+ placeholderCount++;
+ searchPos = found.end;
+ }
+
+ // Apply replacements in reverse order to maintain positions
+ for (let i = replacements.length - 1; i >= 0; i--) {
+ const {
+ start,
+ end,
+ placeholder
+ } = replacements[i];
+ result = result.slice(0, start) + placeholder + result.slice(end);
+ }
+
+ // Cache the result
+ const extractionResult = {
+ expression: result,
+ nestedPaths
+ };
+ cache[expr] = extractionResult;
+ return {
+ expression: result,
+ nestedPaths: [...nestedPaths]
+ };
+ };
+ JSONPath.prototype._slice = function (token, expr, val, path, parent, parentPropName, callback) {
if (!Array.isArray(val)) {
return undefined;
}
- const len = val.length,
- parts = loc.split(':'),
- step = parts[2] && Number.parseInt(parts[2]) || 1;
- let start = parts[0] && Number.parseInt(parts[0]) || 0,
- end = parts[1] && Number.parseInt(parts[1]) || len;
+ const len = val.length;
+ let start = token.start === null ? 0 : token.start;
+ let end = token.end === null ? len : token.end;
+ const step = token.step === null ? 1 : token.step;
start = start < 0 ? Math.max(0, start + len) : Math.min(len, start);
end = end < 0 ? Math.max(0, end + len) : Math.min(len, end);
const ret = [];
@@ -1992,9 +2315,11 @@
// Could store the cache object itself
JSONPath.cache = {};
+ JSONPath.pathPartsCache = {};
+ JSONPath.filterExtractionCache = {};
/**
- * @param {string[]} pathArr Array to convert
+ * @param {string[]|object[]} pathArr Array to convert
* @returns {string} The path string
*/
JSONPath.toPathString = function (pathArr) {
@@ -2002,15 +2327,54 @@
n = x.length;
let p = '$';
for (let i = 1; i < n; i++) {
- if (!/^(~|\^|@.*?\(\))$/u.test(x[i])) {
- p += /^[0-9*]+$/u.test(x[i]) ? '[' + x[i] + ']' : "['" + x[i] + "']";
+ const item = x[i];
+
+ // Handle both old string format and new token format
+ if (typeof item === 'number') {
+ // Array index
+ p += '[' + item + ']';
+ } else if (typeof item === 'string') {
+ // Legacy path
+ if (!/^(~|\^|@.*?\(\))$/u.test(item)) {
+ p += /^[0-9*]+$/u.test(item) ? '[' + item + ']' : "['" + item + "']";
+ }
+ } else if (item && typeof item === 'object') {
+ // New token format
+ switch (item.type) {
+ case 'property':
+ p += "['" + item.value + "']";
+ break;
+ case 'index':
+ p += '[' + item.value + ']';
+ break;
+ case 'wildcard':
+ p += '[*]';
+ break;
+ case 'slice':
+ p += '[' + item.raw + ']';
+ break;
+ case 'filter':
+ p += '[?(' + item.expression + ')]';
+ break;
+ case 'dynamic':
+ p += '[(' + item.expression + ')]';
+ break;
+ case 'typeOperator':
+ p += '@' + item.valueType + '()';
+ break;
+ case 'multiProperty':
+ p += "['" + item.properties.join("','") + "']";
+ break;
+ }
}
}
return p;
};
/**
- * @param {string} pointer JSON Path
+ * Converts path array to JSON Pointer format.
+ * Handles both legacy string arrays and new token objects.
+ * @param {string[]|object[]} pointer - Path array
* @returns {string} JSON Pointer
*/
JSONPath.toPointer = function (pointer) {
@@ -2018,59 +2382,653 @@
n = x.length;
let p = '';
for (let i = 1; i < n; i++) {
- if (!/^(~|\^|@.*?\(\))$/u.test(x[i])) {
- p += '/' + x[i].toString().replaceAll('~', '~0').replaceAll('/', '~1');
+ const item = x[i];
+ let value;
+
+ // Handle different formats
+ if (typeof item === 'number') {
+ value = String(item);
+ } else if (typeof item === 'string') {
+ // Legacy string format or special operators
+ if (/^(~|\^|@.*?\(\))$/u.test(item)) {
+ continue; // Skip special operators
+ }
+ value = item;
+ } else if (item && typeof item === 'object') {
+ // New token format
+ switch (item.type) {
+ case 'property':
+ {
+ const {
+ value: propValue
+ } = item;
+ value = propValue;
+ break;
+ }
+ case 'index':
+ {
+ const {
+ value: indexValue
+ } = item;
+ value = String(indexValue);
+ break;
+ }
+ // Skip special operators
+ case 'root':
+ case 'wildcard':
+ case 'descent':
+ case 'parent':
+ case 'propertyName':
+ case 'filter':
+ case 'dynamic':
+ case 'slice':
+ case 'typeOperator':
+ case 'multiProperty':
+ continue;
+ default:
+ continue;
+ }
+ } else {
+ continue;
}
+
+ // Escape ~ and / per JSON Pointer spec
+ p += '/' + value.replaceAll('~', '~0').replaceAll('/', '~1');
}
return p;
};
/**
- * @param {string} expr Expression to convert
- * @returns {string[]}
+ * Parse a JSONPath expression into structured tokens.
+ * @param {string} expr - JSONPath expression
+ * @returns {Array} Array of tokens
+ */
+ /**
+ * Parses a JSONPath expression into structured token objects.
+ * @param {string} expr - JSONPath expression to parse
+ * @returns {object[]} Array of token objects
*/
- JSONPath.toPathArray = function (expr) {
- const {
- cache
- } = JSONPath;
+ JSONPath.toPathParts = function (expr) {
+ const cache = JSONPath.pathPartsCache;
if (cache[expr]) {
- return cache[expr].concat();
- }
- const subx = [];
- const normalized = expr
- // Properties
- .replaceAll(/@(?:null|boolean|number|string|integer|undefined|nonFinite|scalar|array|object|function|other)\(\)/gu, ';$&;')
- // Parenthetical evaluations (filtering and otherwise), directly
- // within brackets or single quotes
- .replaceAll(/[['](\??\(.*?\))[\]'](?!.\])/gu, function ($0, $1) {
- return '[#' + (subx.push($1) - 1) + ']';
- })
- // Escape periods and tildes within properties
- .replaceAll(/\[['"]([^'\]]*)['"]\]/gu, function ($0, prop) {
- return "['" + prop.replaceAll('.', '%@%').replaceAll('~', '%%@@%%') + "']";
- })
- // Properties operator
- .replaceAll('~', ';~;')
- // Split by property boundaries
- .replaceAll(/['"]?\.['"]?(?![^[]*\])|\[['"]?/gu, ';')
- // Reinsert periods within properties
- .replaceAll('%@%', '.')
- // Reinsert tildes within properties
- .replaceAll('%%@@%%', '~')
- // Parent
- .replaceAll(/(?:;)?(\^+)(?:;)?/gu, function ($0, ups) {
- return ';' + ups.split('').join(';') + ';';
- })
- // Descendents
- .replaceAll(/;;;|;;/gu, ';..;')
- // Remove trailing
- .replaceAll(/;$|'?\]|'$/gu, '');
- const exprList = normalized.split(';').map(function (exp) {
- const match = exp.match(/#(\d+)/u);
- return !match || !match[1] ? exp : subx[match[1]];
- });
- cache[expr] = exprList;
- return cache[expr].concat();
+ // Shallow clone array, shallow clone object tokens
+ // (tokens are simple objects with no nested objects)
+ return cache[expr].map(token => typeof token === 'object' && token !== null ? {
+ ...token
+ } : token);
+ }
+ const tokens = [];
+ let i = 0;
+
+ // Handle empty path - treat as empty property access
+ if (expr === '') {
+ // Hybrid token: empty property is a string
+ tokens.push('');
+ cache[expr] = tokens;
+ return cache[expr].map(token => typeof token === 'object' && token !== null ? {
+ ...token
+ } : token);
+ }
+
+ /**
+ * Extract balanced content between delimiters.
+ * @param {number} start - Starting position
+ * @param {string} open - Opening delimiter
+ * @param {string} close - Closing delimiter
+ * @throws {SyntaxError} If delimiters are unbalanced
+ * @returns {{content: string, end: number}} Extracted content and end position
+ */
+ function extractBalanced(start, open, close) {
+ let depth = 1;
+ let j = start;
+ while (j < expr.length && depth > 0) {
+ if (expr[j] === open) {
+ depth++;
+ } else if (expr[j] === close) {
+ depth--;
+ }
+ j++;
+ }
+ if (depth !== 0) {
+ throw new SyntaxError(`Unbalanced ${open}${close} in expression at position ${start}`);
+ }
+ return {
+ content: expr.slice(start, j - 1),
+ end: j
+ };
+ }
+
+ /**
+ * Extract quoted string.
+ * @param {number} start - Starting position (after quote)
+ * @param {string} quote - Quote character
+ * @throws {SyntaxError} If string is unterminated
+ * @returns {{content: string, end: number, escaped: boolean}} Extracted content, end position, and whether it's backtick-escaped
+ */
+ function extractQuoted(start, quote) {
+ let j = start;
+ let content = '';
+ let escaped = false;
+ while (j < expr.length) {
+ if (expr[j] === '\\' && j + 1 < expr.length) {
+ // Handle backslash escape sequences
+ content += expr[j + 1];
+ j += 2;
+ } else if (expr[j] === '`' && j + 1 < expr.length) {
+ // Handle backtick escape - backtick escapes next char
+ content += expr[j + 1];
+ escaped = true;
+ j += 2;
+ } else if (expr[j] === quote) {
+ return {
+ content,
+ end: j + 1,
+ escaped
+ };
+ } else {
+ content += expr[j];
+ j++;
+ }
+ }
+ throw new SyntaxError(`Unterminated string at position ${start - 1}`);
+ }
+
+ /**
+ * Handle dot notation (.property or ..descendant).
+ * @throws {SyntaxError} If malformed
+ * @returns {void}
+ */
+ function handleDotNotation() {
+ if (i + 1 < expr.length && expr[i + 1] === '.') {
+ // Descendant (..)
+ tokens.push({
+ type: 'descent'
+ });
+ i += 2;
+ } else {
+ // Skip the dot and parse property name
+ i++;
+ if (i >= expr.length) {
+ throw new SyntaxError('Unexpected end after dot at position ' + (i - 1));
+ }
+
+ // Check what follows the dot
+ switch (expr[i]) {
+ case '*':
+ tokens.push({
+ type: 'wildcard'
+ });
+ i++;
+ break;
+ case '`':
+ // Backtick escapes the next character
+ i++; // Skip backtick
+ if (i >= expr.length) {
+ throw new SyntaxError('Unexpected end after backtick at position ' + (i - 1));
+ }
+ // The escaped character becomes the property name
+ tokens.push({
+ type: 'property',
+ value: expr[i],
+ escaped: true
+ });
+ i++;
+ break;
+ case '[':
+ // Dot followed by bracket: interpret as descent
+ // e.g., $.[?(...)] becomes $ .. [?(...)]
+ tokens.push({
+ type: 'descent'
+ });
+ break;
+ default:
+ {
+ // Regular property name (until next special char)
+ let propName = '';
+ while (i < expr.length && !/[.[\]^~@*]/u.test(expr[i])) {
+ propName += expr[i];
+ i++;
+ }
+ if (propName) {
+ // Hybrid token: use string for unescaped properties
+ tokens.push(propName);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Handle bracket notation [...].
+ * @throws {SyntaxError} If malformed
+ * @returns {void}
+ */
+ function handleBracketNotation() {
+ i++; // Skip [
+ if (i >= expr.length) {
+ throw new SyntaxError('Unexpected end after [ at position ' + (i - 1));
+ }
+
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ const ch = expr[i];
+
+ // Wildcard [*]
+ if (ch === '*') {
+ i++;
+ // Skip whitespace and closing bracket
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after * at position ' + i);
+ }
+ i++;
+ tokens.push({
+ type: 'wildcard'
+ });
+ return;
+ }
+
+ // Filter [?(expression)]
+ if (ch === '?') {
+ if (i + 1 >= expr.length || expr[i + 1] !== '(') {
+ throw new SyntaxError('Expected ( after ? at position ' + i);
+ }
+ i += 2; // Skip ?(
+ const result = extractBalanced(i, '(', ')');
+ const {
+ content: expression
+ } = result;
+ i = result.end;
+
+ // Skip whitespace and closing bracket
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after filter at position ' + i);
+ }
+ i++;
+ tokens.push({
+ type: 'filter',
+ expression
+ });
+ return;
+ }
+
+ // Dynamic [(expression)]
+ if (ch === '(') {
+ i++; // Skip (
+ const result = extractBalanced(i, '(', ')');
+ const {
+ content: expression
+ } = result;
+ i = result.end;
+
+ // Skip whitespace and closing bracket
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after dynamic expression at position ' + i);
+ }
+ i++;
+ tokens.push({
+ type: 'dynamic',
+ expression
+ });
+ return;
+ }
+
+ // Quoted property ['name'] or ["name"]
+ if (ch === "'" || ch === '"') {
+ const quote = ch;
+ i++; // Skip opening quote
+ const result = extractQuoted(i, quote);
+ const {
+ content,
+ escaped
+ } = result;
+ i = result.end;
+
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+
+ // Check for comma (multi-property)
+ if (expr[i] === ',') {
+ const properties = [content];
+ const escapedFlags = [escaped];
+ while (expr[i] === ',') {
+ i++; // Skip comma
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ if (expr[i] !== "'" && expr[i] !== '"') {
+ throw new SyntaxError('Expected quoted property after comma at position ' + i);
+ }
+ const q = expr[i];
+ i++;
+ const r = extractQuoted(i, q);
+ properties.push(r.content);
+ escapedFlags.push(r.escaped);
+ i = r.end;
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after multi-property at position ' + i);
+ }
+ i++;
+ tokens.push({
+ type: 'multiProperty',
+ properties,
+ escaped: escapedFlags
+ });
+ return;
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after quoted property at position ' + i);
+ }
+ i++;
+ // Check if quoted property is wildcard
+ if (content === '*' && !escaped) {
+ tokens.push({
+ type: 'wildcard'
+ });
+ } else if (escaped) {
+ // Keep object for escaped properties (metadata needed)
+ tokens.push({
+ type: 'property',
+ value: content,
+ escaped: true
+ });
+ } else {
+ // Hybrid token: use string for unescaped properties
+ tokens.push(content);
+ }
+ return;
+ }
+
+ // Number (index, slice, or multi-index)
+ if (/[-\d]/u.test(ch) || ch === ':') {
+ let numStr = '';
+ while (i < expr.length && /[-\d:]/u.test(expr[i])) {
+ numStr += expr[i];
+ i++;
+ }
+
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+
+ // Check for comma (multi-index like [0,1,2])
+ if (expr[i] === ',') {
+ const indices = [Number.parseInt(numStr)];
+ while (expr[i] === ',') {
+ i++; // Skip comma
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ // Read next number
+ let nextNum = '';
+ while (i < expr.length && /[-\d]/u.test(expr[i])) {
+ nextNum += expr[i];
+ i++;
+ }
+ indices.push(Number.parseInt(nextNum));
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after multi-index at position ' + i);
+ }
+ i++;
+ // Create multiProperty token with numeric properties
+ tokens.push({
+ type: 'multiProperty',
+ properties: indices
+ });
+ return;
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after number at position ' + i);
+ }
+ i++;
+
+ // Check if it's a slice (contains :)
+ if (numStr.includes(':')) {
+ const parts = numStr.split(':');
+ const start = parts[0] === '' ? null : Number.parseInt(parts[0]);
+ const end = parts[1] === '' ? null : Number.parseInt(parts[1]);
+ const step = parts.length > 2 && parts[2] !== '' ? Number.parseInt(parts[2]) : null;
+ tokens.push({
+ type: 'slice',
+ start,
+ end,
+ step,
+ raw: numStr
+ });
+ } else {
+ // Simple index - Hybrid token: use number directly
+ const index = Number.parseInt(numStr);
+ tokens.push(index);
+ }
+ return;
+ }
+
+ // Unquoted property (identifier)
+ // In brackets, unquoted properties can have backtick escapes
+ let propName = '';
+ let escaped = false;
+ while (i < expr.length && expr[i] !== ']' && expr[i] !== ',' && !/\s/u.test(expr[i])) {
+ if (expr[i] === '`' && i + 1 < expr.length && expr[i + 1] !== ']' && expr[i + 1] !== ',') {
+ // Backtick escapes next character
+ propName += expr[i + 1];
+ escaped = true;
+ i += 2;
+ } else {
+ propName += expr[i];
+ i++;
+ }
+ }
+
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+
+ // Check for comma (multi-property with unquoted names)
+ if (expr[i] === ',') {
+ const properties = [propName];
+ const escapedFlags = [escaped];
+ while (expr[i] === ',') {
+ i++; // Skip comma
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ let prop = '';
+ let propEscaped = false;
+ while (i < expr.length && expr[i] !== ']' && expr[i] !== ',' && !/\s/u.test(expr[i])) {
+ if (expr[i] === '`' && i + 1 < expr.length && expr[i + 1] !== ']' && expr[i + 1] !== ',') {
+ // Backtick escapes next character
+ prop += expr[i + 1];
+ propEscaped = true;
+ i += 2;
+ } else {
+ prop += expr[i];
+ i++;
+ }
+ }
+ if (!prop) {
+ throw new SyntaxError('Expected property name after comma at position ' + i);
+ }
+ properties.push(prop);
+ escapedFlags.push(propEscaped);
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after multi-property at position ' + i);
+ }
+ i++;
+ tokens.push({
+ type: 'multiProperty',
+ properties,
+ escaped: escapedFlags
+ });
+ return;
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after property at position ' + i);
+ }
+ i++;
+ if (propName) {
+ if (escaped) {
+ // Keep object for escaped properties
+ tokens.push({
+ type: 'property',
+ value: propName,
+ escaped: true
+ });
+ } else {
+ // Hybrid token: use string for unescaped properties
+ tokens.push(propName);
+ }
+ }
+ }
+
+ /**
+ * Handle type operator `@type()`.
+ * @throws {SyntaxError} If malformed
+ * @returns {void}
+ */
+ function handleTypeOperator() {
+ i++; // Skip @
+ let typeName = '';
+ while (i < expr.length && /[a-z]/ui.test(expr[i])) {
+ typeName += expr[i];
+ i++;
+ }
+ if (i + 1 >= expr.length || expr[i] !== '(' || expr[i + 1] !== ')') {
+ throw new SyntaxError('Expected () after @' + typeName + ' at position ' + i);
+ }
+ i += 2; // Skip ()
+ tokens.push({
+ type: 'typeOperator',
+ valueType: typeName
+ });
+ }
+
+ // If path doesn't start with $, [, or other special char, add implicit root
+ if (expr.length > 0 && !['$', '[', '.', '^', '~', '@'].includes(expr[0])) {
+ tokens.push({
+ type: 'root'
+ });
+ // Prepend with a dot to make it valid for our parser
+ expr = '.' + expr;
+ }
+
+ // Main parsing loop
+ while (i < expr.length) {
+ const ch = expr[i];
+ switch (ch) {
+ case '$':
+ tokens.push({
+ type: 'root'
+ });
+ i++;
+ break;
+ case '.':
+ handleDotNotation();
+ break;
+ case '[':
+ handleBracketNotation();
+ break;
+ case '*':
+ // Wildcard (can appear after .. without a dot)
+ tokens.push({
+ type: 'wildcard'
+ });
+ i++;
+ break;
+ case '^':
+ // If parent selector comes right after root (or at start),
+ // add implicit empty string property
+ // This handles cases like "^" or "$^" which should be "['']^"
+ if (tokens.length === 0 || tokens.length === 1 && tokens[0].type === 'root') {
+ // Hybrid token: empty property is a string
+ tokens.push('');
+ }
+ tokens.push({
+ type: 'parent'
+ });
+ i++;
+ break;
+ case '~':
+ tokens.push({
+ type: 'propertyName'
+ });
+ i++;
+ break;
+ case '@':
+ // Check if this is a type operator like @boolean()
+ // Type operators have the pattern: @identifier()
+ if (/^@[a-z]+\(\)/ui.test(expr.slice(i))) {
+ handleTypeOperator();
+ } else {
+ // Treat @ as part of a property name
+ let propName = '';
+ while (i < expr.length && /[\w$@\\]/u.test(expr[i])) {
+ propName += expr[i];
+ i++;
+ }
+ if (propName) {
+ // Hybrid token: use string for unescaped properties
+ tokens.push(propName);
+ }
+ }
+ break;
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ // Skip whitespace
+ i++;
+ break;
+ default:
+ // Try to parse as identifier (property name)
+ if (/[\w$]/u.test(ch)) {
+ let propName = '';
+ while (i < expr.length && /[\w$]/u.test(expr[i])) {
+ propName += expr[i];
+ i++;
+ }
+ // Hybrid token: use string for unescaped properties
+ tokens.push(propName);
+ } else {
+ throw new SyntaxError(`Unexpected character '${ch}' at position ${i}`);
+ }
+ }
+ }
+ cache[expr] = tokens;
+ return tokens.map(token => typeof token === 'object' && token !== null ? {
+ ...token
+ } : token);
};
JSONPath.prototype.safeVm = {
Script: SafeScript
diff --git a/dist/index-browser-umd.min.cjs b/dist/index-browser-umd.min.cjs
index a01400b..2e5ef2a 100644
--- a/dist/index-browser-umd.min.cjs
+++ b/dist/index-browser-umd.min.cjs
@@ -1,2 +1,2 @@
-!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).JSONPath={})}(this,(function(e){"use strict";class t{static get version(){return"1.4.0"}static toString(){return"JavaScript Expression Parser (JSEP) v"+t.version}static addUnaryOp(e){return t.max_unop_len=Math.max(e.length,t.max_unop_len),t.unary_ops[e]=1,t}static addBinaryOp(e,r,s){return t.max_binop_len=Math.max(e.length,t.max_binop_len),t.binary_ops[e]=r,s?t.right_associative.add(e):t.right_associative.delete(e),t}static addIdentifierChar(e){return t.additional_identifier_chars.add(e),t}static addLiteral(e,r){return t.literals[e]=r,t}static removeUnaryOp(e){return delete t.unary_ops[e],e.length===t.max_unop_len&&(t.max_unop_len=t.getMaxKeyLen(t.unary_ops)),t}static removeAllUnaryOps(){return t.unary_ops={},t.max_unop_len=0,t}static removeIdentifierChar(e){return t.additional_identifier_chars.delete(e),t}static removeBinaryOp(e){return delete t.binary_ops[e],e.length===t.max_binop_len&&(t.max_binop_len=t.getMaxKeyLen(t.binary_ops)),t.right_associative.delete(e),t}static removeAllBinaryOps(){return t.binary_ops={},t.max_binop_len=0,t}static removeLiteral(e){return delete t.literals[e],t}static removeAllLiterals(){return t.literals={},t}get char(){return this.expr.charAt(this.index)}get code(){return this.expr.charCodeAt(this.index)}constructor(e){this.expr=e,this.index=0}static parse(e){return new t(e).parse()}static getMaxKeyLen(e){return Math.max(0,...Object.keys(e).map((e=>e.length)))}static isDecimalDigit(e){return e>=48&&e<=57}static binaryPrecedence(e){return t.binary_ops[e]||0}static isIdentifierStart(e){return e>=65&&e<=90||e>=97&&e<=122||e>=128&&!t.binary_ops[String.fromCharCode(e)]||t.additional_identifier_chars.has(String.fromCharCode(e))}static isIdentifierPart(e){return t.isIdentifierStart(e)||t.isDecimalDigit(e)}throwError(e){const t=new Error(e+" at character "+this.index);throw t.index=this.index,t.description=e,t}runHook(e,r){if(t.hooks[e]){const s={context:this,node:r};return t.hooks.run(e,s),s.node}return r}searchHook(e){if(t.hooks[e]){const r={context:this};return t.hooks[e].find((function(e){return e.call(r.context,r),r.node})),r.node}}gobbleSpaces(){let e=this.code;for(;e===t.SPACE_CODE||e===t.TAB_CODE||e===t.LF_CODE||e===t.CR_CODE;)e=this.expr.charCodeAt(++this.index);this.runHook("gobble-spaces")}parse(){this.runHook("before-all");const e=this.gobbleExpressions(),r=1===e.length?e[0]:{type:t.COMPOUND,body:e};return this.runHook("after-all",r)}gobbleExpressions(e){let r,s,n=[];for(;this.index0;){if(t.binary_ops.hasOwnProperty(e)&&(!t.isIdentifierStart(this.code)||this.index+e.lengthi.right_a&&e.right_a?s>e.prec:s<=e.prec;for(;n.length>2&&h(n[n.length-2]);)a=n.pop(),r=n.pop().value,o=n.pop(),e={type:t.BINARY_EXP,operator:r,left:o,right:a},n.push(e);e=this.gobbleToken(),e||this.throwError("Expected expression after "+l),n.push(i,e)}for(h=n.length-1,e=n[h];h>1;)e={type:t.BINARY_EXP,operator:n[h-1].value,left:n[h-2],right:e},h-=2;return e}gobbleToken(){let e,r,s,n;if(this.gobbleSpaces(),n=this.searchHook("gobble-token"),n)return this.runHook("after-token",n);if(e=this.code,t.isDecimalDigit(e)||e===t.PERIOD_CODE)return this.gobbleNumericLiteral();if(e===t.SQUOTE_CODE||e===t.DQUOTE_CODE)n=this.gobbleStringLiteral();else if(e===t.OBRACK_CODE)n=this.gobbleArray();else{for(r=this.expr.substr(this.index,t.max_unop_len),s=r.length;s>0;){if(t.unary_ops.hasOwnProperty(r)&&(!t.isIdentifierStart(this.code)||this.index+r.length=r.length&&this.throwError("Unexpected token "+String.fromCharCode(e));break}if(i===t.COMMA_CODE){if(this.index++,n++,n!==r.length)if(e===t.CPAREN_CODE)this.throwError("Unexpected token ,");else if(e===t.CBRACK_CODE)for(let e=r.length;e{if("object"!=typeof e||!e.name||!e.init)throw new Error("Invalid JSEP plugin format");this.registered[e.name]||(e.init(this.jsep),this.registered[e.name]=e)}))}}(t),COMPOUND:"Compound",SEQUENCE_EXP:"SequenceExpression",IDENTIFIER:"Identifier",MEMBER_EXP:"MemberExpression",LITERAL:"Literal",THIS_EXP:"ThisExpression",CALL_EXP:"CallExpression",UNARY_EXP:"UnaryExpression",BINARY_EXP:"BinaryExpression",ARRAY_EXP:"ArrayExpression",TAB_CODE:9,LF_CODE:10,CR_CODE:13,SPACE_CODE:32,PERIOD_CODE:46,COMMA_CODE:44,SQUOTE_CODE:39,DQUOTE_CODE:34,OPAREN_CODE:40,CPAREN_CODE:41,OBRACK_CODE:91,CBRACK_CODE:93,QUMARK_CODE:63,SEMCOL_CODE:59,COLON_CODE:58,unary_ops:{"-":1,"!":1,"~":1,"+":1},binary_ops:{"||":1,"??":1,"&&":2,"|":3,"^":4,"&":5,"==":6,"!=":6,"===":6,"!==":6,"<":7,">":7,"<=":7,">=":7,"<<":8,">>":8,">>>":8,"+":9,"-":9,"*":10,"/":10,"%":10,"**":11},right_associative:new Set(["**"]),additional_identifier_chars:new Set(["$","_"]),literals:{true:!0,false:!1,null:null},this_str:"this"}),t.max_unop_len=t.getMaxKeyLen(t.unary_ops),t.max_binop_len=t.getMaxKeyLen(t.binary_ops);const s=e=>new t(e).parse(),n=Object.getOwnPropertyNames(class{});Object.getOwnPropertyNames(t).filter((e=>!n.includes(e)&&void 0===s[e])).forEach((e=>{s[e]=t[e]})),s.Jsep=t;var i={name:"ternary",init(e){e.hooks.add("after-expression",(function(t){if(t.node&&this.code===e.QUMARK_CODE){this.index++;const r=t.node,s=this.gobbleExpression();if(s||this.throwError("Expected expression"),this.gobbleSpaces(),this.code===e.COLON_CODE){this.index++;const n=this.gobbleExpression();if(n||this.throwError("Expected expression"),t.node={type:"ConditionalExpression",test:r,consequent:s,alternate:n},r.operator&&e.binary_ops[r.operator]<=.9){let s=r;for(;s.right.operator&&e.binary_ops[s.right.operator]<=.9;)s=s.right;t.node.test=s.right,s.right=t.node,t.node=r}}else this.throwError("Expected :")}}))}};s.plugins.register(i);var o={name:"regex",init(e){e.hooks.add("gobble-token",(function(t){if(47===this.code){const r=++this.index;let s=!1;for(;this.index=97&&e<=122||e>=65&&e<=90||e>=48&&e<=57))break;i+=this.char}try{n=new RegExp(s,i)}catch(e){this.throwError(e.message)}return t.node={type:e.LITERAL,value:n,raw:this.expr.slice(r-1,this.index)},t.node=this.gobbleTokenProperty(t.node),t.node}this.code===e.OBRACK_CODE?s=!0:s&&this.code===e.CBRACK_CODE&&(s=!1),this.index+=92===this.code?2:1}this.throwError("Unclosed Regex")}}))}};const a={name:"assignment",assignmentOperators:new Set(["=","*=","**=","/=","%=","+=","-=","<<=",">>=",">>>=","&=","^=","|=","||=","&&=","??="]),updateOperators:[43,45],assignmentPrecedence:.9,init(e){const t=[e.IDENTIFIER,e.MEMBER_EXP];function r(e){a.assignmentOperators.has(e.operator)?(e.type="AssignmentExpression",r(e.left),r(e.right)):e.operator||Object.values(e).forEach((e=>{e&&"object"==typeof e&&r(e)}))}a.assignmentOperators.forEach((t=>e.addBinaryOp(t,a.assignmentPrecedence,!0))),e.hooks.add("gobble-token",(function(e){const r=this.code;a.updateOperators.some((e=>e===r&&e===this.expr.charCodeAt(this.index+1)))&&(this.index+=2,e.node={type:"UpdateExpression",operator:43===r?"++":"--",argument:this.gobbleTokenProperty(this.gobbleIdentifier()),prefix:!0},e.node.argument&&t.includes(e.node.argument.type)||this.throwError(`Unexpected ${e.node.operator}`))})),e.hooks.add("after-token",(function(e){if(e.node){const r=this.code;a.updateOperators.some((e=>e===r&&e===this.expr.charCodeAt(this.index+1)))&&(t.includes(e.node.type)||this.throwError(`Unexpected ${e.node.operator}`),this.index+=2,e.node={type:"UpdateExpression",operator:43===r?"++":"--",argument:e.node,prefix:!1})}})),e.hooks.add("after-expression",(function(e){e.node&&r(e.node)}))}};s.plugins.register(o,a),s.addUnaryOp("typeof"),s.addUnaryOp("void"),s.addLiteral("null",null),s.addLiteral("undefined",void 0);const h=new Set(["constructor","__proto__","__defineGetter__","__defineSetter__","__lookupGetter__","__lookupSetter__"]),l={evalAst(e,t){switch(e.type){case"BinaryExpression":case"LogicalExpression":return l.evalBinaryExpression(e,t);case"Compound":return l.evalCompound(e,t);case"ConditionalExpression":return l.evalConditionalExpression(e,t);case"Identifier":return l.evalIdentifier(e,t);case"Literal":return l.evalLiteral(e,t);case"MemberExpression":return l.evalMemberExpression(e,t);case"UnaryExpression":return l.evalUnaryExpression(e,t);case"ArrayExpression":return l.evalArrayExpression(e,t);case"CallExpression":return l.evalCallExpression(e,t);case"AssignmentExpression":return l.evalAssignmentExpression(e,t);default:throw SyntaxError("Unexpected expression",e)}},evalBinaryExpression:(e,t)=>({"||":(e,t)=>e||t(),"&&":(e,t)=>e&&t(),"|":(e,t)=>e|t(),"^":(e,t)=>e^t(),"&":(e,t)=>e&t(),"==":(e,t)=>e==t(),"!=":(e,t)=>e!=t(),"===":(e,t)=>e===t(),"!==":(e,t)=>e!==t(),"<":(e,t)=>e":(e,t)=>e>t(),"<=":(e,t)=>e<=t(),">=":(e,t)=>e>=t(),"<<":(e,t)=>e<>":(e,t)=>e>>t(),">>>":(e,t)=>e>>>t(),"+":(e,t)=>e+t(),"-":(e,t)=>e-t(),"*":(e,t)=>e*t(),"/":(e,t)=>e/t(),"%":(e,t)=>e%t()}[e.operator](l.evalAst(e.left,t),(()=>l.evalAst(e.right,t)))),evalCompound(e,t){let r;for(let s=0;sl.evalAst(e.test,t)?l.evalAst(e.consequent,t):l.evalAst(e.alternate,t),evalIdentifier(e,t){if(Object.hasOwn(t,e.name))return t[e.name];throw ReferenceError(`${e.name} is not defined`)},evalLiteral:e=>e.value,evalMemberExpression(e,t){const r=String(e.computed?l.evalAst(e.property):e.property.name),s=l.evalAst(e.object,t);if(null==s)throw TypeError(`Cannot read properties of ${s} (reading '${r}')`);if(!Object.hasOwn(s,r)&&h.has(r))throw TypeError(`Cannot read properties of ${s} (reading '${r}')`);const n=s[r];return"function"==typeof n?n.bind(s):n},evalUnaryExpression:(e,t)=>({"-":e=>-l.evalAst(e,t),"!":e=>!l.evalAst(e,t),"~":e=>~l.evalAst(e,t),"+":e=>+l.evalAst(e,t),typeof:e=>typeof l.evalAst(e,t),void:e=>{l.evalAst(e,t)}}[e.operator](e.argument)),evalArrayExpression:(e,t)=>e.elements.map((e=>l.evalAst(e,t))),evalCallExpression(e,t){const r=e.arguments.map((e=>l.evalAst(e,t))),s=l.evalAst(e.callee,t);if(s===Function)throw new Error("Function constructor is disabled");return s(...r)},evalAssignmentExpression(e,t){if("Identifier"!==e.left.type)throw SyntaxError("Invalid left-hand side in assignment");const r=e.left.name,s=l.evalAst(e.right,t);return t[r]=s,t[r]}};function c(e,t){return(e=e.slice()).push(t),e}function p(e,t){return(t=t.slice()).unshift(e),t}class u extends Error{constructor(e){super('JSONPath should not be called with "new" (it prevents return of (unwrapped) scalar values)'),this.avoidNew=!0,this.value=e,this.name="NewError"}}function d(e,t,r,s,n){if(!(this instanceof d))try{return new d(e,t,r,s,n)}catch(e){if(!e.avoidNew)throw e;return e.value}"string"==typeof e&&(n=s,s=r,r=t,t=e,e=null);const i=e&&"object"==typeof e;if(e=e||{},this.json=e.json||r,this.path=e.path||t,this.resultType=e.resultType||"value",this.flatten=e.flatten||!1,this.wrap=!Object.hasOwn(e,"wrap")||e.wrap,this.sandbox=e.sandbox||{},this.eval=void 0===e.eval?"safe":e.eval,this.ignoreEvalErrors=void 0!==e.ignoreEvalErrors&&e.ignoreEvalErrors,this.parent=e.parent||null,this.parentProperty=e.parentProperty||null,this.callback=e.callback||s||null,this.otherTypeCallback=e.otherTypeCallback||n||function(){throw new TypeError("You must supply an otherTypeCallback callback option with the @other() operator.")},!1!==e.autostart){const s={path:i?e.path:t};i?"json"in e&&(s.json=e.json):s.json=r;const n=this.evaluate(s);if(!n||"object"!=typeof n)throw new u(n);return n}}d.prototype.evaluate=function(e,t,r,s){let n=this.parent,i=this.parentProperty,{flatten:o,wrap:a}=this;if(this.currResultType=this.resultType,this.currEval=this.eval,this.currSandbox=this.sandbox,r=r||this.callback,this.currOtherTypeCallback=s||this.otherTypeCallback,t=t||this.json,(e=e||this.path)&&"object"==typeof e&&!Array.isArray(e)){if(!e.path&&""!==e.path)throw new TypeError('You must supply a "path" property when providing an object argument to JSONPath.evaluate().');if(!Object.hasOwn(e,"json"))throw new TypeError('You must supply a "json" property when providing an object argument to JSONPath.evaluate().');({json:t}=e),o=Object.hasOwn(e,"flatten")?e.flatten:o,this.currResultType=Object.hasOwn(e,"resultType")?e.resultType:this.currResultType,this.currSandbox=Object.hasOwn(e,"sandbox")?e.sandbox:this.currSandbox,a=Object.hasOwn(e,"wrap")?e.wrap:a,this.currEval=Object.hasOwn(e,"eval")?e.eval:this.currEval,r=Object.hasOwn(e,"callback")?e.callback:r,this.currOtherTypeCallback=Object.hasOwn(e,"otherTypeCallback")?e.otherTypeCallback:this.currOtherTypeCallback,n=Object.hasOwn(e,"parent")?e.parent:n,i=Object.hasOwn(e,"parentProperty")?e.parentProperty:i,e=e.path}if(n=n||null,i=i||null,Array.isArray(e)&&(e=d.toPathString(e)),!e&&""!==e||!t)return;const h=d.toPathArray(e);"$"===h[0]&&h.length>1&&h.shift(),this._hasParentSelector=null;const l=this._trace(h,t,["$"],n,i,r).filter((function(e){return e&&!e.isParentSelector}));return l.length?a||1!==l.length||l[0].hasArrExpr?l.reduce(((e,t)=>{const r=this._getPreferredOutput(t);return o&&Array.isArray(r)?e=e.concat(r):e.push(r),e}),[]):this._getPreferredOutput(l[0]):a?[]:void 0},d.prototype._getPreferredOutput=function(e){const t=this.currResultType;switch(t){case"all":{const t=Array.isArray(e.path)?e.path:d.toPathArray(e.path);return e.pointer=d.toPointer(t),e.path="string"==typeof e.path?e.path:d.toPathString(e.path),e}case"value":case"parent":case"parentProperty":return e[t];case"path":return d.toPathString(e[t]);case"pointer":return d.toPointer(e.path);default:throw new TypeError("Unknown result type")}},d.prototype._handleCallback=function(e,t,r){if(t){const s=this._getPreferredOutput(e);e.path="string"==typeof e.path?e.path:d.toPathString(e.path),t(s,r,e)}},d.prototype._trace=function(e,t,r,s,n,i,o,a){let h;if(!e.length)return h={path:r,value:t,parent:s,parentProperty:n,hasArrExpr:o},this._handleCallback(h,i,"value"),h;const l=e[0],u=e.slice(1),d=[];function f(e){Array.isArray(e)?e.forEach((e=>{d.push(e)})):d.push(e)}if(("string"!=typeof l||a)&&t&&Object.hasOwn(t,l))f(this._trace(u,t[l],c(r,l),t,l,i,o));else if("*"===l)this._walk(t,(e=>{f(this._trace(u,t[e],c(r,e),t,e,i,!0,!0))}));else if(".."===l)f(this._trace(u,t,r,s,n,i,o)),this._walk(t,(s=>{"object"==typeof t[s]&&f(this._trace(e.slice(),t[s],c(r,s),t,s,i,!0))}));else{if("^"===l)return this._hasParentSelector=!0,{path:r.slice(0,-1),expr:u,isParentSelector:!0};if("~"===l)return h={path:c(r,l),value:n,parent:s,parentProperty:null},this._handleCallback(h,i,"property"),h;if("$"===l)f(this._trace(u,t,r,null,null,i,o));else if(/^(-?\d*):(-?\d*):?(\d*)$/u.test(l))f(this._slice(l,u,t,r,s,n,i));else if(0===l.indexOf("?(")){if(!1===this.currEval)throw new Error("Eval [?(expr)] prevented in JSONPath expression.");const e=l.replace(/^\?\((.*?)\)$/u,"$1"),o=/@.?([^?]*)[['](\??\(.*?\))(?!.\)\])[\]']/gu.exec(e);o?this._walk(t,(e=>{const a=[o[2]],h=o[1]?t[e][o[1]]:t[e];this._trace(a,h,r,s,n,i,!0).length>0&&f(this._trace(u,t[e],c(r,e),t,e,i,!0))})):this._walk(t,(o=>{this._eval(e,t[o],o,r,s,n)&&f(this._trace(u,t[o],c(r,o),t,o,i,!0))}))}else if("("===l[0]){if(!1===this.currEval)throw new Error("Eval [(expr)] prevented in JSONPath expression.");f(this._trace(p(this._eval(l,t,r.at(-1),r.slice(0,-1),s,n),u),t,r,s,n,i,o))}else if("@"===l[0]){let e=!1;const o=l.slice(1,-2);switch(o){case"scalar":t&&["object","function"].includes(typeof t)||(e=!0);break;case"boolean":case"string":case"undefined":case"function":typeof t===o&&(e=!0);break;case"integer":!Number.isFinite(t)||t%1||(e=!0);break;case"number":Number.isFinite(t)&&(e=!0);break;case"nonFinite":"number"!=typeof t||Number.isFinite(t)||(e=!0);break;case"object":t&&typeof t===o&&(e=!0);break;case"array":Array.isArray(t)&&(e=!0);break;case"other":e=this.currOtherTypeCallback(t,r,s,n);break;case"null":null===t&&(e=!0);break;default:throw new TypeError("Unknown value type "+o)}if(e)return h={path:r,value:t,parent:s,parentProperty:n},this._handleCallback(h,i,"value"),h}else if("`"===l[0]&&t&&Object.hasOwn(t,l.slice(1))){const e=l.slice(1);f(this._trace(u,t[e],c(r,e),t,e,i,o,!0))}else if(l.includes(",")){const e=l.split(",");for(const o of e)f(this._trace(p(o,u),t,r,s,n,i,!0))}else!a&&t&&Object.hasOwn(t,l)&&f(this._trace(u,t[l],c(r,l),t,l,i,o,!0))}if(this._hasParentSelector)for(let e=0;e{t(e)}))},d.prototype._slice=function(e,t,r,s,n,i,o){if(!Array.isArray(r))return;const a=r.length,h=e.split(":"),l=h[2]&&Number.parseInt(h[2])||1;let c=h[0]&&Number.parseInt(h[0])||0,u=h[1]&&Number.parseInt(h[1])||a;c=c<0?Math.max(0,c+a):Math.min(a,c),u=u<0?Math.max(0,u+a):Math.min(a,u);const d=[];for(let e=c;e{d.push(e)}))}return d},d.prototype._eval=function(e,t,r,s,n,i){this.currSandbox._$_parentProperty=i,this.currSandbox._$_parent=n,this.currSandbox._$_property=r,this.currSandbox._$_root=this.json,this.currSandbox._$_v=t;const o=e.includes("@path");o&&(this.currSandbox._$_path=d.toPathString(s.concat([r])));const a=this.currEval+"Script:"+e;if(!d.cache[a]){let t=e.replaceAll("@parentProperty","_$_parentProperty").replaceAll("@parent","_$_parent").replaceAll("@property","_$_property").replaceAll("@root","_$_root").replaceAll(/@([.\s)[])/gu,"_$_v$1");if(o&&(t=t.replaceAll("@path","_$_path")),"safe"===this.currEval||!0===this.currEval||void 0===this.currEval)d.cache[a]=new this.safeVm.Script(t);else if("native"===this.currEval)d.cache[a]=new this.vm.Script(t);else if("function"==typeof this.currEval&&this.currEval.prototype&&Object.hasOwn(this.currEval.prototype,"runInNewContext")){const e=this.currEval;d.cache[a]=new e(t)}else{if("function"!=typeof this.currEval)throw new TypeError(`Unknown "eval" property "${this.currEval}"`);d.cache[a]={runInNewContext:e=>this.currEval(t,e)}}}try{return d.cache[a].runInNewContext(this.currSandbox)}catch(t){if(this.ignoreEvalErrors)return!1;throw new Error("jsonPath: "+t.message+": "+e)}},d.cache={},d.toPathString=function(e){const t=e,r=t.length;let s="$";for(let e=1;e"function"==typeof e[t]));const n=r.map((t=>e[t]));t=s.reduce(((t,r)=>{let s=e[r].toString();return/function/u.test(s)||(s="function "+s),"var "+r+"="+s+";"+t}),"")+t,/(['"])use strict\1/u.test(t)||r.includes("arguments")||(t="var arguments = undefined;"+t),t=t.replace(/;\s*$/u,"");const i=t.lastIndexOf(";"),o=-1!==i?t.slice(0,i+1)+" return "+t.slice(i+1):" return "+t;return new Function(...r,o)(...n)}}},e.JSONPath=d}));
+!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).JSONPath={})}(this,function(e){"use strict";class t{static get version(){return"1.4.0"}static toString(){return"JavaScript Expression Parser (JSEP) v"+t.version}static addUnaryOp(e){return t.max_unop_len=Math.max(e.length,t.max_unop_len),t.unary_ops[e]=1,t}static addBinaryOp(e,r,s){return t.max_binop_len=Math.max(e.length,t.max_binop_len),t.binary_ops[e]=r,s?t.right_associative.add(e):t.right_associative.delete(e),t}static addIdentifierChar(e){return t.additional_identifier_chars.add(e),t}static addLiteral(e,r){return t.literals[e]=r,t}static removeUnaryOp(e){return delete t.unary_ops[e],e.length===t.max_unop_len&&(t.max_unop_len=t.getMaxKeyLen(t.unary_ops)),t}static removeAllUnaryOps(){return t.unary_ops={},t.max_unop_len=0,t}static removeIdentifierChar(e){return t.additional_identifier_chars.delete(e),t}static removeBinaryOp(e){return delete t.binary_ops[e],e.length===t.max_binop_len&&(t.max_binop_len=t.getMaxKeyLen(t.binary_ops)),t.right_associative.delete(e),t}static removeAllBinaryOps(){return t.binary_ops={},t.max_binop_len=0,t}static removeLiteral(e){return delete t.literals[e],t}static removeAllLiterals(){return t.literals={},t}get char(){return this.expr.charAt(this.index)}get code(){return this.expr.charCodeAt(this.index)}constructor(e){this.expr=e,this.index=0}static parse(e){return new t(e).parse()}static getMaxKeyLen(e){return Math.max(0,...Object.keys(e).map(e=>e.length))}static isDecimalDigit(e){return e>=48&&e<=57}static binaryPrecedence(e){return t.binary_ops[e]||0}static isIdentifierStart(e){return e>=65&&e<=90||e>=97&&e<=122||e>=128&&!t.binary_ops[String.fromCharCode(e)]||t.additional_identifier_chars.has(String.fromCharCode(e))}static isIdentifierPart(e){return t.isIdentifierStart(e)||t.isDecimalDigit(e)}throwError(e){const t=new Error(e+" at character "+this.index);throw t.index=this.index,t.description=e,t}runHook(e,r){if(t.hooks[e]){const s={context:this,node:r};return t.hooks.run(e,s),s.node}return r}searchHook(e){if(t.hooks[e]){const r={context:this};return t.hooks[e].find(function(e){return e.call(r.context,r),r.node}),r.node}}gobbleSpaces(){let e=this.code;for(;e===t.SPACE_CODE||e===t.TAB_CODE||e===t.LF_CODE||e===t.CR_CODE;)e=this.expr.charCodeAt(++this.index);this.runHook("gobble-spaces")}parse(){this.runHook("before-all");const e=this.gobbleExpressions(),r=1===e.length?e[0]:{type:t.COMPOUND,body:e};return this.runHook("after-all",r)}gobbleExpressions(e){let r,s,n=[];for(;this.index0;){if(t.binary_ops.hasOwnProperty(e)&&(!t.isIdentifierStart(this.code)||this.index+e.lengthi.right_a&&e.right_a?s>e.prec:s<=e.prec;for(;n.length>2&&h(n[n.length-2]);)a=n.pop(),r=n.pop().value,o=n.pop(),e={type:t.BINARY_EXP,operator:r,left:o,right:a},n.push(e);e=this.gobbleToken(),e||this.throwError("Expected expression after "+l),n.push(i,e)}for(h=n.length-1,e=n[h];h>1;)e={type:t.BINARY_EXP,operator:n[h-1].value,left:n[h-2],right:e},h-=2;return e}gobbleToken(){let e,r,s,n;if(this.gobbleSpaces(),n=this.searchHook("gobble-token"),n)return this.runHook("after-token",n);if(e=this.code,t.isDecimalDigit(e)||e===t.PERIOD_CODE)return this.gobbleNumericLiteral();if(e===t.SQUOTE_CODE||e===t.DQUOTE_CODE)n=this.gobbleStringLiteral();else if(e===t.OBRACK_CODE)n=this.gobbleArray();else{for(r=this.expr.substr(this.index,t.max_unop_len),s=r.length;s>0;){if(t.unary_ops.hasOwnProperty(r)&&(!t.isIdentifierStart(this.code)||this.index+r.length=r.length&&this.throwError("Unexpected token "+String.fromCharCode(e));break}if(i===t.COMMA_CODE){if(this.index++,n++,n!==r.length)if(e===t.CPAREN_CODE)this.throwError("Unexpected token ,");else if(e===t.CBRACK_CODE)for(let e=r.length;e{if("object"!=typeof e||!e.name||!e.init)throw new Error("Invalid JSEP plugin format");this.registered[e.name]||(e.init(this.jsep),this.registered[e.name]=e)})}}(t),COMPOUND:"Compound",SEQUENCE_EXP:"SequenceExpression",IDENTIFIER:"Identifier",MEMBER_EXP:"MemberExpression",LITERAL:"Literal",THIS_EXP:"ThisExpression",CALL_EXP:"CallExpression",UNARY_EXP:"UnaryExpression",BINARY_EXP:"BinaryExpression",ARRAY_EXP:"ArrayExpression",TAB_CODE:9,LF_CODE:10,CR_CODE:13,SPACE_CODE:32,PERIOD_CODE:46,COMMA_CODE:44,SQUOTE_CODE:39,DQUOTE_CODE:34,OPAREN_CODE:40,CPAREN_CODE:41,OBRACK_CODE:91,CBRACK_CODE:93,QUMARK_CODE:63,SEMCOL_CODE:59,COLON_CODE:58,unary_ops:{"-":1,"!":1,"~":1,"+":1},binary_ops:{"||":1,"??":1,"&&":2,"|":3,"^":4,"&":5,"==":6,"!=":6,"===":6,"!==":6,"<":7,">":7,"<=":7,">=":7,"<<":8,">>":8,">>>":8,"+":9,"-":9,"*":10,"/":10,"%":10,"**":11},right_associative:new Set(["**"]),additional_identifier_chars:new Set(["$","_"]),literals:{true:!0,false:!1,null:null},this_str:"this"}),t.max_unop_len=t.getMaxKeyLen(t.unary_ops),t.max_binop_len=t.getMaxKeyLen(t.binary_ops);const s=e=>new t(e).parse(),n=Object.getOwnPropertyNames(class{});Object.getOwnPropertyNames(t).filter(e=>!n.includes(e)&&void 0===s[e]).forEach(e=>{s[e]=t[e]}),s.Jsep=t;var i={name:"ternary",init(e){e.hooks.add("after-expression",function(t){if(t.node&&this.code===e.QUMARK_CODE){this.index++;const r=t.node,s=this.gobbleExpression();if(s||this.throwError("Expected expression"),this.gobbleSpaces(),this.code===e.COLON_CODE){this.index++;const n=this.gobbleExpression();if(n||this.throwError("Expected expression"),t.node={type:"ConditionalExpression",test:r,consequent:s,alternate:n},r.operator&&e.binary_ops[r.operator]<=.9){let s=r;for(;s.right.operator&&e.binary_ops[s.right.operator]<=.9;)s=s.right;t.node.test=s.right,s.right=t.node,t.node=r}}else this.throwError("Expected :")}})}};s.plugins.register(i);var o={name:"regex",init(e){e.hooks.add("gobble-token",function(t){if(47===this.code){const r=++this.index;let s=!1;for(;this.index=97&&e<=122||e>=65&&e<=90||e>=48&&e<=57))break;i+=this.char}try{n=new RegExp(s,i)}catch(e){this.throwError(e.message)}return t.node={type:e.LITERAL,value:n,raw:this.expr.slice(r-1,this.index)},t.node=this.gobbleTokenProperty(t.node),t.node}this.code===e.OBRACK_CODE?s=!0:s&&this.code===e.CBRACK_CODE&&(s=!1),this.index+=92===this.code?2:1}this.throwError("Unclosed Regex")}})}};const a={name:"assignment",assignmentOperators:new Set(["=","*=","**=","/=","%=","+=","-=","<<=",">>=",">>>=","&=","^=","|=","||=","&&=","??="]),updateOperators:[43,45],assignmentPrecedence:.9,init(e){const t=[e.IDENTIFIER,e.MEMBER_EXP];function r(e){a.assignmentOperators.has(e.operator)?(e.type="AssignmentExpression",r(e.left),r(e.right)):e.operator||Object.values(e).forEach(e=>{e&&"object"==typeof e&&r(e)})}a.assignmentOperators.forEach(t=>e.addBinaryOp(t,a.assignmentPrecedence,!0)),e.hooks.add("gobble-token",function(e){const r=this.code;a.updateOperators.some(e=>e===r&&e===this.expr.charCodeAt(this.index+1))&&(this.index+=2,e.node={type:"UpdateExpression",operator:43===r?"++":"--",argument:this.gobbleTokenProperty(this.gobbleIdentifier()),prefix:!0},e.node.argument&&t.includes(e.node.argument.type)||this.throwError(`Unexpected ${e.node.operator}`))}),e.hooks.add("after-token",function(e){if(e.node){const r=this.code;a.updateOperators.some(e=>e===r&&e===this.expr.charCodeAt(this.index+1))&&(t.includes(e.node.type)||this.throwError(`Unexpected ${e.node.operator}`),this.index+=2,e.node={type:"UpdateExpression",operator:43===r?"++":"--",argument:e.node,prefix:!1})}}),e.hooks.add("after-expression",function(e){e.node&&r(e.node)})}};s.plugins.register(o,a),s.addUnaryOp("typeof"),s.addUnaryOp("void"),s.addLiteral("null",null),s.addLiteral("undefined",void 0);const h=new Set(["constructor","__proto__","__defineGetter__","__defineSetter__","__lookupGetter__","__lookupSetter__"]),l={evalAst(e,t){switch(e.type){case"BinaryExpression":case"LogicalExpression":return l.evalBinaryExpression(e,t);case"Compound":return l.evalCompound(e,t);case"ConditionalExpression":return l.evalConditionalExpression(e,t);case"Identifier":return l.evalIdentifier(e,t);case"Literal":return l.evalLiteral(e,t);case"MemberExpression":return l.evalMemberExpression(e,t);case"UnaryExpression":return l.evalUnaryExpression(e,t);case"ArrayExpression":return l.evalArrayExpression(e,t);case"CallExpression":return l.evalCallExpression(e,t);case"AssignmentExpression":return l.evalAssignmentExpression(e,t);default:throw SyntaxError("Unexpected expression",e)}},evalBinaryExpression:(e,t)=>({"||":(e,t)=>e||t(),"&&":(e,t)=>e&&t(),"|":(e,t)=>e|t(),"^":(e,t)=>e^t(),"&":(e,t)=>e&t(),"==":(e,t)=>e==t(),"!=":(e,t)=>e!=t(),"===":(e,t)=>e===t(),"!==":(e,t)=>e!==t(),"<":(e,t)=>e":(e,t)=>e>t(),"<=":(e,t)=>e<=t(),">=":(e,t)=>e>=t(),"<<":(e,t)=>e<>":(e,t)=>e>>t(),">>>":(e,t)=>e>>>t(),"+":(e,t)=>e+t(),"-":(e,t)=>e-t(),"*":(e,t)=>e*t(),"/":(e,t)=>e/t(),"%":(e,t)=>e%t()}[e.operator](l.evalAst(e.left,t),()=>l.evalAst(e.right,t))),evalCompound(e,t){let r;for(let s=0;sl.evalAst(e.test,t)?l.evalAst(e.consequent,t):l.evalAst(e.alternate,t),evalIdentifier(e,t){if(Object.hasOwn(t,e.name))return t[e.name];throw ReferenceError(`${e.name} is not defined`)},evalLiteral:e=>e.value,evalMemberExpression(e,t){const r=String(e.computed?l.evalAst(e.property):e.property.name),s=l.evalAst(e.object,t);if(null==s)throw TypeError(`Cannot read properties of ${s} (reading '${r}')`);if(!Object.hasOwn(s,r)&&h.has(r))throw TypeError(`Cannot read properties of ${s} (reading '${r}')`);const n=s[r];return"function"==typeof n?n.bind(s):n},evalUnaryExpression:(e,t)=>({"-":e=>-l.evalAst(e,t),"!":e=>!l.evalAst(e,t),"~":e=>~l.evalAst(e,t),"+":e=>+l.evalAst(e,t),typeof:e=>typeof l.evalAst(e,t),void:e=>{l.evalAst(e,t)}}[e.operator](e.argument)),evalArrayExpression:(e,t)=>e.elements.map(e=>l.evalAst(e,t)),evalCallExpression(e,t){const r=e.arguments.map(e=>l.evalAst(e,t)),s=l.evalAst(e.callee,t);if(s===Function)throw new Error("Function constructor is disabled");return s(...r)},evalAssignmentExpression(e,t){if("Identifier"!==e.left.type)throw SyntaxError("Invalid left-hand side in assignment");const r=e.left.name,s=l.evalAst(e.right,t);return t[r]=s,t[r]}};function p(e,t){return(e=e.slice()).push(t),e}function c(e,t){return(t=t.slice()).unshift(e),t}class u extends Error{constructor(e){super('JSONPath should not be called with "new" (it prevents return of (unwrapped) scalar values)'),this.avoidNew=!0,this.value=e,this.name="NewError"}}function d(e,t,r,s,n){if(!(this instanceof d))try{return new d(e,t,r,s,n)}catch(e){if(!e.avoidNew)throw e;return e.value}"string"==typeof e&&(n=s,s=r,r=t,t=e,e=null);const i=e&&"object"==typeof e;if(e=e||{},this.json=e.json||r,this.path=e.path||t,this.resultType=e.resultType||"value",this.flatten=e.flatten||!1,this.wrap=!Object.hasOwn(e,"wrap")||e.wrap,this.sandbox=e.sandbox||{},this.eval=void 0===e.eval?"safe":e.eval,this.ignoreEvalErrors=void 0!==e.ignoreEvalErrors&&e.ignoreEvalErrors,this.parent=e.parent||null,this.parentProperty=e.parentProperty||null,this.callback=e.callback||s||null,this.otherTypeCallback=e.otherTypeCallback||n||function(){throw new TypeError("You must supply an otherTypeCallback callback option with the @other() operator.")},!1!==e.autostart){const s={path:i?e.path:t};i?"json"in e&&(s.json=e.json):s.json=r;const n=this.evaluate(s);if(!n||"object"!=typeof n)throw new u(n);return n}}d.prototype.evaluate=function(e,t,r,s){let n=this.parent,i=this.parentProperty,{flatten:o,wrap:a}=this;if(this.currResultType=this.resultType,this.currEval=this.eval,this.currSandbox=this.sandbox,r=r||this.callback,this.currOtherTypeCallback=s||this.otherTypeCallback,t=t||this.json,(e=e||this.path)&&"object"==typeof e&&!Array.isArray(e)){if(!e.path&&""!==e.path)throw new TypeError('You must supply a "path" property when providing an object argument to JSONPath.evaluate().');if(!Object.hasOwn(e,"json"))throw new TypeError('You must supply a "json" property when providing an object argument to JSONPath.evaluate().');({json:t}=e),o=Object.hasOwn(e,"flatten")?e.flatten:o,this.currResultType=Object.hasOwn(e,"resultType")?e.resultType:this.currResultType,this.currSandbox=Object.hasOwn(e,"sandbox")?e.sandbox:this.currSandbox,a=Object.hasOwn(e,"wrap")?e.wrap:a,this.currEval=Object.hasOwn(e,"eval")?e.eval:this.currEval,r=Object.hasOwn(e,"callback")?e.callback:r,this.currOtherTypeCallback=Object.hasOwn(e,"otherTypeCallback")?e.otherTypeCallback:this.currOtherTypeCallback,n=Object.hasOwn(e,"parent")?e.parent:n,i=Object.hasOwn(e,"parentProperty")?e.parentProperty:i,e=e.path}if(n=n||null,i=i||null,Array.isArray(e)&&(e=d.toPathString(e)),!e&&""!==e||!t)return;const h=d.toPathParts(e);h[0]&&"root"===h[0].type&&h.length>1&&h.shift(),this._hasParentSelector=null,this._json=t;const l=this._trace(h,t,["$"],n,i,r).filter(function(e){return e&&!e.isParentSelector});return l.length?a||1!==l.length||l[0].hasArrExpr?l.reduce((e,t)=>{const r=this._getPreferredOutput(t);return o&&Array.isArray(r)?e=e.concat(r):e.push(r),e},[]):this._getPreferredOutput(l[0]):a?[]:void 0},d.prototype._getPreferredOutput=function(e){const t=this.currResultType;switch(t){case"all":{const t=Array.isArray(e.path)?e.path:d.toPathParts(e.path);return e.pointer=d.toPointer(t),e.path="string"==typeof e.path?e.path:d.toPathString(e.path),e}case"value":case"parent":case"parentProperty":return e[t];case"path":return d.toPathString(e[t]);case"pointer":return d.toPointer(e.path);default:throw new TypeError("Unknown result type")}},d.prototype._handleCallback=function(e,t,r){if(t){const s=this._getPreferredOutput(e);e.path="string"==typeof e.path?e.path:d.toPathString(e.path),t(s,r,e)}},d.prototype._trace=function(e,t,r,s,n,i,o,a){let h;if(!e.length)return h={path:r,value:t,parent:s,parentProperty:n,hasArrExpr:o},this._handleCallback(h,i,"value"),[h];const l=e[0],u=e.slice(1),f=[];function y(e){Array.isArray(e)?e.forEach(e=>{f.push(e)}):f.push(e)}if("string"==typeof l)t&&Object.hasOwn(t,l)&&y(this._trace(u,t[l],p(r,l),t,l,i,o));else if("number"==typeof l)Array.isArray(t)&&l>=0&&l{y(this._trace(u,t[e],p(r,e),t,e,i,!0,!0))});break;case"descent":y(this._trace(u,t,r,s,n,i,o)),this._walk(t,s=>{"object"==typeof t[s]&&y(this._trace(e.slice(),t[s],p(r,s),t,s,i,!0))});break;case"parent":r.length>1&&(this._hasParentSelector=!0,f.push({path:r.slice(0,-1),expr:u,isParentSelector:!0}));break;case"propertyName":h={path:p(r,"~"),value:n,parent:s,parentProperty:null},this._handleCallback(h,i,"property"),f.push(h);break;case"index":{const e=l.value;(Array.isArray(t)&&e>=0&&e{const l={};for(const[e,s]of o.entries()){const n=s.replace(/^@/u,"$");try{const s=d.toPathParts(n),i=this._trace(s,t[h],p(r,h),t,h,null,!0);l[`_$_jp${e}`]=i.map(e=>e.value)}catch(t){l[`_$_jp${e}`]=[]}}const c={...this.currSandbox};Object.assign(this.currSandbox,l);try{(a?l._$_jp0.length>0:this._eval(e,t[h],h,r,s,n))&&y(this._trace(u,t[h],p(r,h),t,h,i,!0))}finally{this.currSandbox=c}})}else this._walk(t,e=>{this._eval(l.expression,t[e],e,r,s,n)&&y(this._trace(u,t[e],p(r,e),t,e,i,!0))});break;case"dynamic":if(!1===this.currEval)throw new Error("Eval [(expr)] prevented in JSONPath expression.");y(this._trace(c(this._eval(l.expression,t,r.at(-1),r.slice(0,-1),s,n),u),t,r,s,n,i,o));break;case"typeOperator":{let e=!1;const{valueType:o}=l;switch(o){case"scalar":t&&["object","function"].includes(typeof t)||(e=!0);break;case"boolean":case"string":case"undefined":case"function":typeof t===o&&(e=!0);break;case"integer":!Number.isFinite(t)||t%1||(e=!0);break;case"number":Number.isFinite(t)&&(e=!0);break;case"nonFinite":"number"!=typeof t||Number.isFinite(t)||(e=!0);break;case"object":t&&typeof t===o&&(e=!0);break;case"array":Array.isArray(t)&&(e=!0);break;case"other":e=this.currOtherTypeCallback(t,r,s,n);break;case"null":null===t&&(e=!0);break;default:throw new TypeError("Unknown value type "+o)}e&&(h={path:r,value:t,parent:s,parentProperty:n},this._handleCallback(h,i,"value"),f.push(h));break}case"multiProperty":{const e=l.properties,o=l.escaped||[];for(const[a,h]of e.entries()){let e;if("number"==typeof h)e={type:"index",value:h};else{e={type:"property",value:h,escaped:o[a]||!1}}y(this._trace(c(e,u),t,r,s,n,i,!0))}break}}else("string"!=typeof l||a)&&t&&Object.hasOwn(t,l)&&y(this._trace(u,t[l],p(r,l),t,l,i,o));if(this._hasParentSelector)for(let e=0;e{t(e)})},d.prototype._extractNestedFilters=function(e){const t=d.filterExtractionCache;if(t[e])return{expression:t[e].expression,nestedPaths:[...t[e].nestedPaths]};const r=[];let s=e,n=0;function i(e,t){let r=t;for(;r0){const s=e.slice(0,r).trimEnd().slice(-1);if("=([{,;:!&|?".includes(s)||r===t){for(r++;r=e.length)return null;let s=!1,n="@";for(;r0;)if("\\"===e[r]&&r+1=0;e--){const{start:t,end:r,placeholder:n}=a[e];s=s.slice(0,t)+n+s.slice(r)}const h={expression:s,nestedPaths:r};return t[e]=h,{expression:s,nestedPaths:[...r]}},d.prototype._slice=function(e,t,r,s,n,i,o){if(!Array.isArray(r))return;const a=r.length;let h=null===e.start?0:e.start,l=null===e.end?a:e.end;const p=null===e.step?1:e.step;h=h<0?Math.max(0,h+a):Math.min(a,h),l=l<0?Math.max(0,l+a):Math.min(a,l);const u=[];for(let e=h;e{u.push(e)})}return u},d.prototype._eval=function(e,t,r,s,n,i){this.currSandbox._$_parentProperty=i,this.currSandbox._$_parent=n,this.currSandbox._$_property=r,this.currSandbox._$_root=this.json,this.currSandbox._$_v=t;const o=e.includes("@path");o&&(this.currSandbox._$_path=d.toPathString(s.concat([r])));const a=this.currEval+"Script:"+e;if(!d.cache[a]){let t=e.replaceAll("@parentProperty","_$_parentProperty").replaceAll("@parent","_$_parent").replaceAll("@property","_$_property").replaceAll("@root","_$_root").replaceAll(/@([.\s)[])/gu,"_$_v$1");if(o&&(t=t.replaceAll("@path","_$_path")),"safe"===this.currEval||!0===this.currEval||void 0===this.currEval)d.cache[a]=new this.safeVm.Script(t);else if("native"===this.currEval)d.cache[a]=new this.vm.Script(t);else if("function"==typeof this.currEval&&this.currEval.prototype&&Object.hasOwn(this.currEval.prototype,"runInNewContext")){const e=this.currEval;d.cache[a]=new e(t)}else{if("function"!=typeof this.currEval)throw new TypeError(`Unknown "eval" property "${this.currEval}"`);d.cache[a]={runInNewContext:e=>this.currEval(t,e)}}}try{return d.cache[a].runInNewContext(this.currSandbox)}catch(t){if(this.ignoreEvalErrors)return!1;throw new Error("jsonPath: "+t.message+": "+e)}},d.cache={},d.pathPartsCache={},d.filterExtractionCache={},d.toPathString=function(e){const t=e,r=t.length;let s="$";for(let e=1;e"object"==typeof e&&null!==e?{...e}:e);const r=[];let s=0;if(""===e)return r.push(""),t[e]=r,t[e].map(e=>"object"==typeof e&&null!==e?{...e}:e);function n(t,r,s){let n=1,i=t;for(;i0;)e[i]===r?n++:e[i]===s&&n--,i++;if(0!==n)throw new SyntaxError(`Unbalanced ${r}${s} in expression at position ${t}`);return{content:e.slice(t,i-1),end:i}}function i(t,r){let s=t,n="",i=!1;for(;s=e.length)throw new SyntaxError("Unexpected end after dot at position "+(s-1));switch(e[s]){case"*":r.push({type:"wildcard"}),s++;break;case"`":if(s++,s>=e.length)throw new SyntaxError("Unexpected end after backtick at position "+(s-1));r.push({type:"property",value:e[s],escaped:!0}),s++;break;case"[":r.push({type:"descent"});break;default:{let t="";for(;s=e.length)throw new SyntaxError("Unexpected end after [ at position "+(s-1));for(;s=e.length||"("!==e[s+1])throw new SyntaxError("Expected ( after ? at position "+s);s+=2;const t=n(s,"(",")"),{content:i}=t;for(s=t.end;s2&&""!==e[2]?Number.parseInt(e[2]):null;r.push({type:"slice",start:s,end:n,step:i,raw:t})}else{const e=Number.parseInt(t);r.push(e)}return}let o="",a=!1;for(;s=e.length||"("!==e[s]||")"!==e[s+1])throw new SyntaxError("Expected () after @"+t+" at position "+s);s+=2,r.push({type:"typeOperator",valueType:t})}for(e.length>0&&!["$","[",".","^","~","@"].includes(e[0])&&(r.push({type:"root"}),e="."+e);s"object"==typeof e&&null!==e?{...e}:e)},d.prototype.safeVm={Script:class{constructor(e){this.code=e,this.ast=s(this.code)}runInNewContext(e){const t=Object.assign(Object.create(null),e);return l.evalAst(this.ast,t)}}};d.prototype.vm={Script:class{constructor(e){this.code=e}runInNewContext(e){let t=this.code;const r=Object.keys(e),s=[];!function(e,t,r){const s=e.length;for(let n=0;n"function"==typeof e[t]);const n=r.map(t=>e[t]);t=s.reduce((t,r)=>{let s=e[r].toString();return/function/u.test(s)||(s="function "+s),"var "+r+"="+s+";"+t},"")+t,/(['"])use strict\1/u.test(t)||r.includes("arguments")||(t="var arguments = undefined;"+t),t=t.replace(/;\s*$/u,"");const i=t.lastIndexOf(";"),o=-1!==i?t.slice(0,i+1)+" return "+t.slice(i+1):" return "+t;return new Function(...r,o)(...n)}}},e.JSONPath=d});
//# sourceMappingURL=index-browser-umd.min.cjs.map
diff --git a/dist/index-browser-umd.min.cjs.map b/dist/index-browser-umd.min.cjs.map
index e6269d3..330c0d3 100644
--- a/dist/index-browser-umd.min.cjs.map
+++ b/dist/index-browser-umd.min.cjs.map
@@ -1 +1 @@
-{"version":3,"file":"index-browser-umd.min.cjs","sources":["../node_modules/.pnpm/jsep@1.4.0/node_modules/jsep/dist/jsep.js","../node_modules/.pnpm/@jsep-plugin+regex@1.0.4_jsep@1.4.0/node_modules/@jsep-plugin/regex/dist/index.js","../node_modules/.pnpm/@jsep-plugin+assignment@1.3.0_jsep@1.4.0/node_modules/@jsep-plugin/assignment/dist/index.js","../src/Safe-Script.js","../src/jsonpath.js","../src/jsonpath-browser.js"],"sourcesContent":["/**\n * @implements {IHooks}\n */\nclass Hooks {\n\t/**\n\t * @callback HookCallback\n\t * @this {*|Jsep} this\n\t * @param {Jsep} env\n\t * @returns: void\n\t */\n\t/**\n\t * Adds the given callback to the list of callbacks for the given hook.\n\t *\n\t * The callback will be invoked when the hook it is registered for is run.\n\t *\n\t * One callback function can be registered to multiple hooks and the same hook multiple times.\n\t *\n\t * @param {string|object} name The name of the hook, or an object of callbacks keyed by name\n\t * @param {HookCallback|boolean} callback The callback function which is given environment variables.\n\t * @param {?boolean} [first=false] Will add the hook to the top of the list (defaults to the bottom)\n\t * @public\n\t */\n\tadd(name, callback, first) {\n\t\tif (typeof arguments[0] != 'string') {\n\t\t\t// Multiple hook callbacks, keyed by name\n\t\t\tfor (let name in arguments[0]) {\n\t\t\t\tthis.add(name, arguments[0][name], arguments[1]);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\t(Array.isArray(name) ? name : [name]).forEach(function (name) {\n\t\t\t\tthis[name] = this[name] || [];\n\n\t\t\t\tif (callback) {\n\t\t\t\t\tthis[name][first ? 'unshift' : 'push'](callback);\n\t\t\t\t}\n\t\t\t}, this);\n\t\t}\n\t}\n\n\t/**\n\t * Runs a hook invoking all registered callbacks with the given environment variables.\n\t *\n\t * Callbacks will be invoked synchronously and in the order in which they were registered.\n\t *\n\t * @param {string} name The name of the hook.\n\t * @param {Object} env The environment variables of the hook passed to all callbacks registered.\n\t * @public\n\t */\n\trun(name, env) {\n\t\tthis[name] = this[name] || [];\n\t\tthis[name].forEach(function (callback) {\n\t\t\tcallback.call(env && env.context ? env.context : env, env);\n\t\t});\n\t}\n}\n\n/**\n * @implements {IPlugins}\n */\nclass Plugins {\n\tconstructor(jsep) {\n\t\tthis.jsep = jsep;\n\t\tthis.registered = {};\n\t}\n\n\t/**\n\t * @callback PluginSetup\n\t * @this {Jsep} jsep\n\t * @returns: void\n\t */\n\t/**\n\t * Adds the given plugin(s) to the registry\n\t *\n\t * @param {object} plugins\n\t * @param {string} plugins.name The name of the plugin\n\t * @param {PluginSetup} plugins.init The init function\n\t * @public\n\t */\n\tregister(...plugins) {\n\t\tplugins.forEach((plugin) => {\n\t\t\tif (typeof plugin !== 'object' || !plugin.name || !plugin.init) {\n\t\t\t\tthrow new Error('Invalid JSEP plugin format');\n\t\t\t}\n\t\t\tif (this.registered[plugin.name]) {\n\t\t\t\t// already registered. Ignore.\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tplugin.init(this.jsep);\n\t\t\tthis.registered[plugin.name] = plugin;\n\t\t});\n\t}\n}\n\n// JavaScript Expression Parser (JSEP) 1.4.0\n\nclass Jsep {\n\t/**\n\t * @returns {string}\n\t */\n\tstatic get version() {\n\t\t// To be filled in by the template\n\t\treturn '1.4.0';\n\t}\n\n\t/**\n\t * @returns {string}\n\t */\n\tstatic toString() {\n\t\treturn 'JavaScript Expression Parser (JSEP) v' + Jsep.version;\n\t};\n\n\t// ==================== CONFIG ================================\n\t/**\n\t * @method addUnaryOp\n\t * @param {string} op_name The name of the unary op to add\n\t * @returns {Jsep}\n\t */\n\tstatic addUnaryOp(op_name) {\n\t\tJsep.max_unop_len = Math.max(op_name.length, Jsep.max_unop_len);\n\t\tJsep.unary_ops[op_name] = 1;\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method jsep.addBinaryOp\n\t * @param {string} op_name The name of the binary op to add\n\t * @param {number} precedence The precedence of the binary op (can be a float). Higher number = higher precedence\n\t * @param {boolean} [isRightAssociative=false] whether operator is right-associative\n\t * @returns {Jsep}\n\t */\n\tstatic addBinaryOp(op_name, precedence, isRightAssociative) {\n\t\tJsep.max_binop_len = Math.max(op_name.length, Jsep.max_binop_len);\n\t\tJsep.binary_ops[op_name] = precedence;\n\t\tif (isRightAssociative) {\n\t\t\tJsep.right_associative.add(op_name);\n\t\t}\n\t\telse {\n\t\t\tJsep.right_associative.delete(op_name);\n\t\t}\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method addIdentifierChar\n\t * @param {string} char The additional character to treat as a valid part of an identifier\n\t * @returns {Jsep}\n\t */\n\tstatic addIdentifierChar(char) {\n\t\tJsep.additional_identifier_chars.add(char);\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method addLiteral\n\t * @param {string} literal_name The name of the literal to add\n\t * @param {*} literal_value The value of the literal\n\t * @returns {Jsep}\n\t */\n\tstatic addLiteral(literal_name, literal_value) {\n\t\tJsep.literals[literal_name] = literal_value;\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method removeUnaryOp\n\t * @param {string} op_name The name of the unary op to remove\n\t * @returns {Jsep}\n\t */\n\tstatic removeUnaryOp(op_name) {\n\t\tdelete Jsep.unary_ops[op_name];\n\t\tif (op_name.length === Jsep.max_unop_len) {\n\t\t\tJsep.max_unop_len = Jsep.getMaxKeyLen(Jsep.unary_ops);\n\t\t}\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method removeAllUnaryOps\n\t * @returns {Jsep}\n\t */\n\tstatic removeAllUnaryOps() {\n\t\tJsep.unary_ops = {};\n\t\tJsep.max_unop_len = 0;\n\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method removeIdentifierChar\n\t * @param {string} char The additional character to stop treating as a valid part of an identifier\n\t * @returns {Jsep}\n\t */\n\tstatic removeIdentifierChar(char) {\n\t\tJsep.additional_identifier_chars.delete(char);\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method removeBinaryOp\n\t * @param {string} op_name The name of the binary op to remove\n\t * @returns {Jsep}\n\t */\n\tstatic removeBinaryOp(op_name) {\n\t\tdelete Jsep.binary_ops[op_name];\n\n\t\tif (op_name.length === Jsep.max_binop_len) {\n\t\t\tJsep.max_binop_len = Jsep.getMaxKeyLen(Jsep.binary_ops);\n\t\t}\n\t\tJsep.right_associative.delete(op_name);\n\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method removeAllBinaryOps\n\t * @returns {Jsep}\n\t */\n\tstatic removeAllBinaryOps() {\n\t\tJsep.binary_ops = {};\n\t\tJsep.max_binop_len = 0;\n\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method removeLiteral\n\t * @param {string} literal_name The name of the literal to remove\n\t * @returns {Jsep}\n\t */\n\tstatic removeLiteral(literal_name) {\n\t\tdelete Jsep.literals[literal_name];\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method removeAllLiterals\n\t * @returns {Jsep}\n\t */\n\tstatic removeAllLiterals() {\n\t\tJsep.literals = {};\n\n\t\treturn Jsep;\n\t}\n\t// ==================== END CONFIG ============================\n\n\n\t/**\n\t * @returns {string}\n\t */\n\tget char() {\n\t\treturn this.expr.charAt(this.index);\n\t}\n\n\t/**\n\t * @returns {number}\n\t */\n\tget code() {\n\t\treturn this.expr.charCodeAt(this.index);\n\t};\n\n\n\t/**\n\t * @param {string} expr a string with the passed in express\n\t * @returns Jsep\n\t */\n\tconstructor(expr) {\n\t\t// `index` stores the character number we are currently at\n\t\t// All of the gobbles below will modify `index` as we move along\n\t\tthis.expr = expr;\n\t\tthis.index = 0;\n\t}\n\n\t/**\n\t * static top-level parser\n\t * @returns {jsep.Expression}\n\t */\n\tstatic parse(expr) {\n\t\treturn (new Jsep(expr)).parse();\n\t}\n\n\t/**\n\t * Get the longest key length of any object\n\t * @param {object} obj\n\t * @returns {number}\n\t */\n\tstatic getMaxKeyLen(obj) {\n\t\treturn Math.max(0, ...Object.keys(obj).map(k => k.length));\n\t}\n\n\t/**\n\t * `ch` is a character code in the next three functions\n\t * @param {number} ch\n\t * @returns {boolean}\n\t */\n\tstatic isDecimalDigit(ch) {\n\t\treturn (ch >= 48 && ch <= 57); // 0...9\n\t}\n\n\t/**\n\t * Returns the precedence of a binary operator or `0` if it isn't a binary operator. Can be float.\n\t * @param {string} op_val\n\t * @returns {number}\n\t */\n\tstatic binaryPrecedence(op_val) {\n\t\treturn Jsep.binary_ops[op_val] || 0;\n\t}\n\n\t/**\n\t * Looks for start of identifier\n\t * @param {number} ch\n\t * @returns {boolean}\n\t */\n\tstatic isIdentifierStart(ch) {\n\t\treturn (ch >= 65 && ch <= 90) || // A...Z\n\t\t\t(ch >= 97 && ch <= 122) || // a...z\n\t\t\t(ch >= 128 && !Jsep.binary_ops[String.fromCharCode(ch)]) || // any non-ASCII that is not an operator\n\t\t\t(Jsep.additional_identifier_chars.has(String.fromCharCode(ch))); // additional characters\n\t}\n\n\t/**\n\t * @param {number} ch\n\t * @returns {boolean}\n\t */\n\tstatic isIdentifierPart(ch) {\n\t\treturn Jsep.isIdentifierStart(ch) || Jsep.isDecimalDigit(ch);\n\t}\n\n\t/**\n\t * throw error at index of the expression\n\t * @param {string} message\n\t * @throws\n\t */\n\tthrowError(message) {\n\t\tconst error = new Error(message + ' at character ' + this.index);\n\t\terror.index = this.index;\n\t\terror.description = message;\n\t\tthrow error;\n\t}\n\n\t/**\n\t * Run a given hook\n\t * @param {string} name\n\t * @param {jsep.Expression|false} [node]\n\t * @returns {?jsep.Expression}\n\t */\n\trunHook(name, node) {\n\t\tif (Jsep.hooks[name]) {\n\t\t\tconst env = { context: this, node };\n\t\t\tJsep.hooks.run(name, env);\n\t\t\treturn env.node;\n\t\t}\n\t\treturn node;\n\t}\n\n\t/**\n\t * Runs a given hook until one returns a node\n\t * @param {string} name\n\t * @returns {?jsep.Expression}\n\t */\n\tsearchHook(name) {\n\t\tif (Jsep.hooks[name]) {\n\t\t\tconst env = { context: this };\n\t\t\tJsep.hooks[name].find(function (callback) {\n\t\t\t\tcallback.call(env.context, env);\n\t\t\t\treturn env.node;\n\t\t\t});\n\t\t\treturn env.node;\n\t\t}\n\t}\n\n\t/**\n\t * Push `index` up to the next non-space character\n\t */\n\tgobbleSpaces() {\n\t\tlet ch = this.code;\n\t\t// Whitespace\n\t\twhile (ch === Jsep.SPACE_CODE\n\t\t|| ch === Jsep.TAB_CODE\n\t\t|| ch === Jsep.LF_CODE\n\t\t|| ch === Jsep.CR_CODE) {\n\t\t\tch = this.expr.charCodeAt(++this.index);\n\t\t}\n\t\tthis.runHook('gobble-spaces');\n\t}\n\n\t/**\n\t * Top-level method to parse all expressions and returns compound or single node\n\t * @returns {jsep.Expression}\n\t */\n\tparse() {\n\t\tthis.runHook('before-all');\n\t\tconst nodes = this.gobbleExpressions();\n\n\t\t// If there's only one expression just try returning the expression\n\t\tconst node = nodes.length === 1\n\t\t ? nodes[0]\n\t\t\t: {\n\t\t\t\ttype: Jsep.COMPOUND,\n\t\t\t\tbody: nodes\n\t\t\t};\n\t\treturn this.runHook('after-all', node);\n\t}\n\n\t/**\n\t * top-level parser (but can be reused within as well)\n\t * @param {number} [untilICode]\n\t * @returns {jsep.Expression[]}\n\t */\n\tgobbleExpressions(untilICode) {\n\t\tlet nodes = [], ch_i, node;\n\n\t\twhile (this.index < this.expr.length) {\n\t\t\tch_i = this.code;\n\n\t\t\t// Expressions can be separated by semicolons, commas, or just inferred without any\n\t\t\t// separators\n\t\t\tif (ch_i === Jsep.SEMCOL_CODE || ch_i === Jsep.COMMA_CODE) {\n\t\t\t\tthis.index++; // ignore separators\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Try to gobble each expression individually\n\t\t\t\tif (node = this.gobbleExpression()) {\n\t\t\t\t\tnodes.push(node);\n\t\t\t\t\t// If we weren't able to find a binary expression and are out of room, then\n\t\t\t\t\t// the expression passed in probably has too much\n\t\t\t\t}\n\t\t\t\telse if (this.index < this.expr.length) {\n\t\t\t\t\tif (ch_i === untilICode) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tthis.throwError('Unexpected \"' + this.char + '\"');\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn nodes;\n\t}\n\n\t/**\n\t * The main parsing function.\n\t * @returns {?jsep.Expression}\n\t */\n\tgobbleExpression() {\n\t\tconst node = this.searchHook('gobble-expression') || this.gobbleBinaryExpression();\n\t\tthis.gobbleSpaces();\n\n\t\treturn this.runHook('after-expression', node);\n\t}\n\n\t/**\n\t * Search for the operation portion of the string (e.g. `+`, `===`)\n\t * Start by taking the longest possible binary operations (3 characters: `===`, `!==`, `>>>`)\n\t * and move down from 3 to 2 to 1 character until a matching binary operation is found\n\t * then, return that binary operation\n\t * @returns {string|boolean}\n\t */\n\tgobbleBinaryOp() {\n\t\tthis.gobbleSpaces();\n\t\tlet to_check = this.expr.substr(this.index, Jsep.max_binop_len);\n\t\tlet tc_len = to_check.length;\n\n\t\twhile (tc_len > 0) {\n\t\t\t// Don't accept a binary op when it is an identifier.\n\t\t\t// Binary ops that start with a identifier-valid character must be followed\n\t\t\t// by a non identifier-part valid character\n\t\t\tif (Jsep.binary_ops.hasOwnProperty(to_check) && (\n\t\t\t\t!Jsep.isIdentifierStart(this.code) ||\n\t\t\t\t(this.index + to_check.length < this.expr.length && !Jsep.isIdentifierPart(this.expr.charCodeAt(this.index + to_check.length)))\n\t\t\t)) {\n\t\t\t\tthis.index += tc_len;\n\t\t\t\treturn to_check;\n\t\t\t}\n\t\t\tto_check = to_check.substr(0, --tc_len);\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * This function is responsible for gobbling an individual expression,\n\t * e.g. `1`, `1+2`, `a+(b*2)-Math.sqrt(2)`\n\t * @returns {?jsep.BinaryExpression}\n\t */\n\tgobbleBinaryExpression() {\n\t\tlet node, biop, prec, stack, biop_info, left, right, i, cur_biop;\n\n\t\t// First, try to get the leftmost thing\n\t\t// Then, check to see if there's a binary operator operating on that leftmost thing\n\t\t// Don't gobbleBinaryOp without a left-hand-side\n\t\tleft = this.gobbleToken();\n\t\tif (!left) {\n\t\t\treturn left;\n\t\t}\n\t\tbiop = this.gobbleBinaryOp();\n\n\t\t// If there wasn't a binary operator, just return the leftmost node\n\t\tif (!biop) {\n\t\t\treturn left;\n\t\t}\n\n\t\t// Otherwise, we need to start a stack to properly place the binary operations in their\n\t\t// precedence structure\n\t\tbiop_info = { value: biop, prec: Jsep.binaryPrecedence(biop), right_a: Jsep.right_associative.has(biop) };\n\n\t\tright = this.gobbleToken();\n\n\t\tif (!right) {\n\t\t\tthis.throwError(\"Expected expression after \" + biop);\n\t\t}\n\n\t\tstack = [left, biop_info, right];\n\n\t\t// Properly deal with precedence using [recursive descent](http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm)\n\t\twhile ((biop = this.gobbleBinaryOp())) {\n\t\t\tprec = Jsep.binaryPrecedence(biop);\n\n\t\t\tif (prec === 0) {\n\t\t\t\tthis.index -= biop.length;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tbiop_info = { value: biop, prec, right_a: Jsep.right_associative.has(biop) };\n\n\t\t\tcur_biop = biop;\n\n\t\t\t// Reduce: make a binary expression from the three topmost entries.\n\t\t\tconst comparePrev = prev => biop_info.right_a && prev.right_a\n\t\t\t\t? prec > prev.prec\n\t\t\t\t: prec <= prev.prec;\n\t\t\twhile ((stack.length > 2) && comparePrev(stack[stack.length - 2])) {\n\t\t\t\tright = stack.pop();\n\t\t\t\tbiop = stack.pop().value;\n\t\t\t\tleft = stack.pop();\n\t\t\t\tnode = {\n\t\t\t\t\ttype: Jsep.BINARY_EXP,\n\t\t\t\t\toperator: biop,\n\t\t\t\t\tleft,\n\t\t\t\t\tright\n\t\t\t\t};\n\t\t\t\tstack.push(node);\n\t\t\t}\n\n\t\t\tnode = this.gobbleToken();\n\n\t\t\tif (!node) {\n\t\t\t\tthis.throwError(\"Expected expression after \" + cur_biop);\n\t\t\t}\n\n\t\t\tstack.push(biop_info, node);\n\t\t}\n\n\t\ti = stack.length - 1;\n\t\tnode = stack[i];\n\n\t\twhile (i > 1) {\n\t\t\tnode = {\n\t\t\t\ttype: Jsep.BINARY_EXP,\n\t\t\t\toperator: stack[i - 1].value,\n\t\t\t\tleft: stack[i - 2],\n\t\t\t\tright: node\n\t\t\t};\n\t\t\ti -= 2;\n\t\t}\n\n\t\treturn node;\n\t}\n\n\t/**\n\t * An individual part of a binary expression:\n\t * e.g. `foo.bar(baz)`, `1`, `\"abc\"`, `(a % 2)` (because it's in parenthesis)\n\t * @returns {boolean|jsep.Expression}\n\t */\n\tgobbleToken() {\n\t\tlet ch, to_check, tc_len, node;\n\n\t\tthis.gobbleSpaces();\n\t\tnode = this.searchHook('gobble-token');\n\t\tif (node) {\n\t\t\treturn this.runHook('after-token', node);\n\t\t}\n\n\t\tch = this.code;\n\n\t\tif (Jsep.isDecimalDigit(ch) || ch === Jsep.PERIOD_CODE) {\n\t\t\t// Char code 46 is a dot `.` which can start off a numeric literal\n\t\t\treturn this.gobbleNumericLiteral();\n\t\t}\n\n\t\tif (ch === Jsep.SQUOTE_CODE || ch === Jsep.DQUOTE_CODE) {\n\t\t\t// Single or double quotes\n\t\t\tnode = this.gobbleStringLiteral();\n\t\t}\n\t\telse if (ch === Jsep.OBRACK_CODE) {\n\t\t\tnode = this.gobbleArray();\n\t\t}\n\t\telse {\n\t\t\tto_check = this.expr.substr(this.index, Jsep.max_unop_len);\n\t\t\ttc_len = to_check.length;\n\n\t\t\twhile (tc_len > 0) {\n\t\t\t\t// Don't accept an unary op when it is an identifier.\n\t\t\t\t// Unary ops that start with a identifier-valid character must be followed\n\t\t\t\t// by a non identifier-part valid character\n\t\t\t\tif (Jsep.unary_ops.hasOwnProperty(to_check) && (\n\t\t\t\t\t!Jsep.isIdentifierStart(this.code) ||\n\t\t\t\t\t(this.index + to_check.length < this.expr.length && !Jsep.isIdentifierPart(this.expr.charCodeAt(this.index + to_check.length)))\n\t\t\t\t)) {\n\t\t\t\t\tthis.index += tc_len;\n\t\t\t\t\tconst argument = this.gobbleToken();\n\t\t\t\t\tif (!argument) {\n\t\t\t\t\t\tthis.throwError('missing unaryOp argument');\n\t\t\t\t\t}\n\t\t\t\t\treturn this.runHook('after-token', {\n\t\t\t\t\t\ttype: Jsep.UNARY_EXP,\n\t\t\t\t\t\toperator: to_check,\n\t\t\t\t\t\targument,\n\t\t\t\t\t\tprefix: true\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tto_check = to_check.substr(0, --tc_len);\n\t\t\t}\n\n\t\t\tif (Jsep.isIdentifierStart(ch)) {\n\t\t\t\tnode = this.gobbleIdentifier();\n\t\t\t\tif (Jsep.literals.hasOwnProperty(node.name)) {\n\t\t\t\t\tnode = {\n\t\t\t\t\t\ttype: Jsep.LITERAL,\n\t\t\t\t\t\tvalue: Jsep.literals[node.name],\n\t\t\t\t\t\traw: node.name,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\telse if (node.name === Jsep.this_str) {\n\t\t\t\t\tnode = { type: Jsep.THIS_EXP };\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (ch === Jsep.OPAREN_CODE) { // open parenthesis\n\t\t\t\tnode = this.gobbleGroup();\n\t\t\t}\n\t\t}\n\n\t\tif (!node) {\n\t\t\treturn this.runHook('after-token', false);\n\t\t}\n\n\t\tnode = this.gobbleTokenProperty(node);\n\t\treturn this.runHook('after-token', node);\n\t}\n\n\t/**\n\t * Gobble properties of of identifiers/strings/arrays/groups.\n\t * e.g. `foo`, `bar.baz`, `foo['bar'].baz`\n\t * It also gobbles function calls:\n\t * e.g. `Math.acos(obj.angle)`\n\t * @param {jsep.Expression} node\n\t * @returns {jsep.Expression}\n\t */\n\tgobbleTokenProperty(node) {\n\t\tthis.gobbleSpaces();\n\n\t\tlet ch = this.code;\n\t\twhile (ch === Jsep.PERIOD_CODE || ch === Jsep.OBRACK_CODE || ch === Jsep.OPAREN_CODE || ch === Jsep.QUMARK_CODE) {\n\t\t\tlet optional;\n\t\t\tif (ch === Jsep.QUMARK_CODE) {\n\t\t\t\tif (this.expr.charCodeAt(this.index + 1) !== Jsep.PERIOD_CODE) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\toptional = true;\n\t\t\t\tthis.index += 2;\n\t\t\t\tthis.gobbleSpaces();\n\t\t\t\tch = this.code;\n\t\t\t}\n\t\t\tthis.index++;\n\n\t\t\tif (ch === Jsep.OBRACK_CODE) {\n\t\t\t\tnode = {\n\t\t\t\t\ttype: Jsep.MEMBER_EXP,\n\t\t\t\t\tcomputed: true,\n\t\t\t\t\tobject: node,\n\t\t\t\t\tproperty: this.gobbleExpression()\n\t\t\t\t};\n\t\t\t\tif (!node.property) {\n\t\t\t\t\tthis.throwError('Unexpected \"' + this.char + '\"');\n\t\t\t\t}\n\t\t\t\tthis.gobbleSpaces();\n\t\t\t\tch = this.code;\n\t\t\t\tif (ch !== Jsep.CBRACK_CODE) {\n\t\t\t\t\tthis.throwError('Unclosed [');\n\t\t\t\t}\n\t\t\t\tthis.index++;\n\t\t\t}\n\t\t\telse if (ch === Jsep.OPAREN_CODE) {\n\t\t\t\t// A function call is being made; gobble all the arguments\n\t\t\t\tnode = {\n\t\t\t\t\ttype: Jsep.CALL_EXP,\n\t\t\t\t\t'arguments': this.gobbleArguments(Jsep.CPAREN_CODE),\n\t\t\t\t\tcallee: node\n\t\t\t\t};\n\t\t\t}\n\t\t\telse if (ch === Jsep.PERIOD_CODE || optional) {\n\t\t\t\tif (optional) {\n\t\t\t\t\tthis.index--;\n\t\t\t\t}\n\t\t\t\tthis.gobbleSpaces();\n\t\t\t\tnode = {\n\t\t\t\t\ttype: Jsep.MEMBER_EXP,\n\t\t\t\t\tcomputed: false,\n\t\t\t\t\tobject: node,\n\t\t\t\t\tproperty: this.gobbleIdentifier(),\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (optional) {\n\t\t\t\tnode.optional = true;\n\t\t\t} // else leave undefined for compatibility with esprima\n\n\t\t\tthis.gobbleSpaces();\n\t\t\tch = this.code;\n\t\t}\n\n\t\treturn node;\n\t}\n\n\t/**\n\t * Parse simple numeric literals: `12`, `3.4`, `.5`. Do this by using a string to\n\t * keep track of everything in the numeric literal and then calling `parseFloat` on that string\n\t * @returns {jsep.Literal}\n\t */\n\tgobbleNumericLiteral() {\n\t\tlet number = '', ch, chCode;\n\n\t\twhile (Jsep.isDecimalDigit(this.code)) {\n\t\t\tnumber += this.expr.charAt(this.index++);\n\t\t}\n\n\t\tif (this.code === Jsep.PERIOD_CODE) { // can start with a decimal marker\n\t\t\tnumber += this.expr.charAt(this.index++);\n\n\t\t\twhile (Jsep.isDecimalDigit(this.code)) {\n\t\t\t\tnumber += this.expr.charAt(this.index++);\n\t\t\t}\n\t\t}\n\n\t\tch = this.char;\n\n\t\tif (ch === 'e' || ch === 'E') { // exponent marker\n\t\t\tnumber += this.expr.charAt(this.index++);\n\t\t\tch = this.char;\n\n\t\t\tif (ch === '+' || ch === '-') { // exponent sign\n\t\t\t\tnumber += this.expr.charAt(this.index++);\n\t\t\t}\n\n\t\t\twhile (Jsep.isDecimalDigit(this.code)) { // exponent itself\n\t\t\t\tnumber += this.expr.charAt(this.index++);\n\t\t\t}\n\n\t\t\tif (!Jsep.isDecimalDigit(this.expr.charCodeAt(this.index - 1)) ) {\n\t\t\t\tthis.throwError('Expected exponent (' + number + this.char + ')');\n\t\t\t}\n\t\t}\n\n\t\tchCode = this.code;\n\n\t\t// Check to make sure this isn't a variable name that start with a number (123abc)\n\t\tif (Jsep.isIdentifierStart(chCode)) {\n\t\t\tthis.throwError('Variable names cannot start with a number (' +\n\t\t\t\tnumber + this.char + ')');\n\t\t}\n\t\telse if (chCode === Jsep.PERIOD_CODE || (number.length === 1 && number.charCodeAt(0) === Jsep.PERIOD_CODE)) {\n\t\t\tthis.throwError('Unexpected period');\n\t\t}\n\n\t\treturn {\n\t\t\ttype: Jsep.LITERAL,\n\t\t\tvalue: parseFloat(number),\n\t\t\traw: number\n\t\t};\n\t}\n\n\t/**\n\t * Parses a string literal, staring with single or double quotes with basic support for escape codes\n\t * e.g. `\"hello world\"`, `'this is\\nJSEP'`\n\t * @returns {jsep.Literal}\n\t */\n\tgobbleStringLiteral() {\n\t\tlet str = '';\n\t\tconst startIndex = this.index;\n\t\tconst quote = this.expr.charAt(this.index++);\n\t\tlet closed = false;\n\n\t\twhile (this.index < this.expr.length) {\n\t\t\tlet ch = this.expr.charAt(this.index++);\n\n\t\t\tif (ch === quote) {\n\t\t\t\tclosed = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\telse if (ch === '\\\\') {\n\t\t\t\t// Check for all of the common escape codes\n\t\t\t\tch = this.expr.charAt(this.index++);\n\n\t\t\t\tswitch (ch) {\n\t\t\t\t\tcase 'n': str += '\\n'; break;\n\t\t\t\t\tcase 'r': str += '\\r'; break;\n\t\t\t\t\tcase 't': str += '\\t'; break;\n\t\t\t\t\tcase 'b': str += '\\b'; break;\n\t\t\t\t\tcase 'f': str += '\\f'; break;\n\t\t\t\t\tcase 'v': str += '\\x0B'; break;\n\t\t\t\t\tdefault : str += ch;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tstr += ch;\n\t\t\t}\n\t\t}\n\n\t\tif (!closed) {\n\t\t\tthis.throwError('Unclosed quote after \"' + str + '\"');\n\t\t}\n\n\t\treturn {\n\t\t\ttype: Jsep.LITERAL,\n\t\t\tvalue: str,\n\t\t\traw: this.expr.substring(startIndex, this.index),\n\t\t};\n\t}\n\n\t/**\n\t * Gobbles only identifiers\n\t * e.g.: `foo`, `_value`, `$x1`\n\t * Also, this function checks if that identifier is a literal:\n\t * (e.g. `true`, `false`, `null`) or `this`\n\t * @returns {jsep.Identifier}\n\t */\n\tgobbleIdentifier() {\n\t\tlet ch = this.code, start = this.index;\n\n\t\tif (Jsep.isIdentifierStart(ch)) {\n\t\t\tthis.index++;\n\t\t}\n\t\telse {\n\t\t\tthis.throwError('Unexpected ' + this.char);\n\t\t}\n\n\t\twhile (this.index < this.expr.length) {\n\t\t\tch = this.code;\n\n\t\t\tif (Jsep.isIdentifierPart(ch)) {\n\t\t\t\tthis.index++;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\ttype: Jsep.IDENTIFIER,\n\t\t\tname: this.expr.slice(start, this.index),\n\t\t};\n\t}\n\n\t/**\n\t * Gobbles a list of arguments within the context of a function call\n\t * or array literal. This function also assumes that the opening character\n\t * `(` or `[` has already been gobbled, and gobbles expressions and commas\n\t * until the terminator character `)` or `]` is encountered.\n\t * e.g. `foo(bar, baz)`, `my_func()`, or `[bar, baz]`\n\t * @param {number} termination\n\t * @returns {jsep.Expression[]}\n\t */\n\tgobbleArguments(termination) {\n\t\tconst args = [];\n\t\tlet closed = false;\n\t\tlet separator_count = 0;\n\n\t\twhile (this.index < this.expr.length) {\n\t\t\tthis.gobbleSpaces();\n\t\t\tlet ch_i = this.code;\n\n\t\t\tif (ch_i === termination) { // done parsing\n\t\t\t\tclosed = true;\n\t\t\t\tthis.index++;\n\n\t\t\t\tif (termination === Jsep.CPAREN_CODE && separator_count && separator_count >= args.length){\n\t\t\t\t\tthis.throwError('Unexpected token ' + String.fromCharCode(termination));\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\telse if (ch_i === Jsep.COMMA_CODE) { // between expressions\n\t\t\t\tthis.index++;\n\t\t\t\tseparator_count++;\n\n\t\t\t\tif (separator_count !== args.length) { // missing argument\n\t\t\t\t\tif (termination === Jsep.CPAREN_CODE) {\n\t\t\t\t\t\tthis.throwError('Unexpected token ,');\n\t\t\t\t\t}\n\t\t\t\t\telse if (termination === Jsep.CBRACK_CODE) {\n\t\t\t\t\t\tfor (let arg = args.length; arg < separator_count; arg++) {\n\t\t\t\t\t\t\targs.push(null);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (args.length !== separator_count && separator_count !== 0) {\n\t\t\t\t// NOTE: `&& separator_count !== 0` allows for either all commas, or all spaces as arguments\n\t\t\t\tthis.throwError('Expected comma');\n\t\t\t}\n\t\t\telse {\n\t\t\t\tconst node = this.gobbleExpression();\n\n\t\t\t\tif (!node || node.type === Jsep.COMPOUND) {\n\t\t\t\t\tthis.throwError('Expected comma');\n\t\t\t\t}\n\n\t\t\t\targs.push(node);\n\t\t\t}\n\t\t}\n\n\t\tif (!closed) {\n\t\t\tthis.throwError('Expected ' + String.fromCharCode(termination));\n\t\t}\n\n\t\treturn args;\n\t}\n\n\t/**\n\t * Responsible for parsing a group of things within parentheses `()`\n\t * that have no identifier in front (so not a function call)\n\t * This function assumes that it needs to gobble the opening parenthesis\n\t * and then tries to gobble everything within that parenthesis, assuming\n\t * that the next thing it should see is the close parenthesis. If not,\n\t * then the expression probably doesn't have a `)`\n\t * @returns {boolean|jsep.Expression}\n\t */\n\tgobbleGroup() {\n\t\tthis.index++;\n\t\tlet nodes = this.gobbleExpressions(Jsep.CPAREN_CODE);\n\t\tif (this.code === Jsep.CPAREN_CODE) {\n\t\t\tthis.index++;\n\t\t\tif (nodes.length === 1) {\n\t\t\t\treturn nodes[0];\n\t\t\t}\n\t\t\telse if (!nodes.length) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn {\n\t\t\t\t\ttype: Jsep.SEQUENCE_EXP,\n\t\t\t\t\texpressions: nodes,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tthis.throwError('Unclosed (');\n\t\t}\n\t}\n\n\t/**\n\t * Responsible for parsing Array literals `[1, 2, 3]`\n\t * This function assumes that it needs to gobble the opening bracket\n\t * and then tries to gobble the expressions as arguments.\n\t * @returns {jsep.ArrayExpression}\n\t */\n\tgobbleArray() {\n\t\tthis.index++;\n\n\t\treturn {\n\t\t\ttype: Jsep.ARRAY_EXP,\n\t\t\telements: this.gobbleArguments(Jsep.CBRACK_CODE)\n\t\t};\n\t}\n}\n\n// Static fields:\nconst hooks = new Hooks();\nObject.assign(Jsep, {\n\thooks,\n\tplugins: new Plugins(Jsep),\n\n\t// Node Types\n\t// ----------\n\t// This is the full set of types that any JSEP node can be.\n\t// Store them here to save space when minified\n\tCOMPOUND: 'Compound',\n\tSEQUENCE_EXP: 'SequenceExpression',\n\tIDENTIFIER: 'Identifier',\n\tMEMBER_EXP: 'MemberExpression',\n\tLITERAL: 'Literal',\n\tTHIS_EXP: 'ThisExpression',\n\tCALL_EXP: 'CallExpression',\n\tUNARY_EXP: 'UnaryExpression',\n\tBINARY_EXP: 'BinaryExpression',\n\tARRAY_EXP: 'ArrayExpression',\n\n\tTAB_CODE: 9,\n\tLF_CODE: 10,\n\tCR_CODE: 13,\n\tSPACE_CODE: 32,\n\tPERIOD_CODE: 46, // '.'\n\tCOMMA_CODE: 44, // ','\n\tSQUOTE_CODE: 39, // single quote\n\tDQUOTE_CODE: 34, // double quotes\n\tOPAREN_CODE: 40, // (\n\tCPAREN_CODE: 41, // )\n\tOBRACK_CODE: 91, // [\n\tCBRACK_CODE: 93, // ]\n\tQUMARK_CODE: 63, // ?\n\tSEMCOL_CODE: 59, // ;\n\tCOLON_CODE: 58, // :\n\n\n\t// Operations\n\t// ----------\n\t// Use a quickly-accessible map to store all of the unary operators\n\t// Values are set to `1` (it really doesn't matter)\n\tunary_ops: {\n\t\t'-': 1,\n\t\t'!': 1,\n\t\t'~': 1,\n\t\t'+': 1\n\t},\n\n\t// Also use a map for the binary operations but set their values to their\n\t// binary precedence for quick reference (higher number = higher precedence)\n\t// see [Order of operations](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence)\n\tbinary_ops: {\n\t\t'||': 1, '??': 1,\n\t\t'&&': 2, '|': 3, '^': 4, '&': 5,\n\t\t'==': 6, '!=': 6, '===': 6, '!==': 6,\n\t\t'<': 7, '>': 7, '<=': 7, '>=': 7,\n\t\t'<<': 8, '>>': 8, '>>>': 8,\n\t\t'+': 9, '-': 9,\n\t\t'*': 10, '/': 10, '%': 10,\n\t\t'**': 11,\n\t},\n\n\t// sets specific binary_ops as right-associative\n\tright_associative: new Set(['**']),\n\n\t// Additional valid identifier chars, apart from a-z, A-Z and 0-9 (except on the starting char)\n\tadditional_identifier_chars: new Set(['$', '_']),\n\n\t// Literals\n\t// ----------\n\t// Store the values to return for the various literals we may encounter\n\tliterals: {\n\t\t'true': true,\n\t\t'false': false,\n\t\t'null': null\n\t},\n\n\t// Except for `this`, which is special. This could be changed to something like `'self'` as well\n\tthis_str: 'this',\n});\nJsep.max_unop_len = Jsep.getMaxKeyLen(Jsep.unary_ops);\nJsep.max_binop_len = Jsep.getMaxKeyLen(Jsep.binary_ops);\n\n// Backward Compatibility:\nconst jsep = expr => (new Jsep(expr)).parse();\nconst stdClassProps = Object.getOwnPropertyNames(class Test{});\nObject.getOwnPropertyNames(Jsep)\n\t.filter(prop => !stdClassProps.includes(prop) && jsep[prop] === undefined)\n\t.forEach((m) => {\n\t\tjsep[m] = Jsep[m];\n\t});\njsep.Jsep = Jsep; // allows for const { Jsep } = require('jsep');\n\nconst CONDITIONAL_EXP = 'ConditionalExpression';\n\nvar ternary = {\n\tname: 'ternary',\n\n\tinit(jsep) {\n\t\t// Ternary expression: test ? consequent : alternate\n\t\tjsep.hooks.add('after-expression', function gobbleTernary(env) {\n\t\t\tif (env.node && this.code === jsep.QUMARK_CODE) {\n\t\t\t\tthis.index++;\n\t\t\t\tconst test = env.node;\n\t\t\t\tconst consequent = this.gobbleExpression();\n\n\t\t\t\tif (!consequent) {\n\t\t\t\t\tthis.throwError('Expected expression');\n\t\t\t\t}\n\n\t\t\t\tthis.gobbleSpaces();\n\n\t\t\t\tif (this.code === jsep.COLON_CODE) {\n\t\t\t\t\tthis.index++;\n\t\t\t\t\tconst alternate = this.gobbleExpression();\n\n\t\t\t\t\tif (!alternate) {\n\t\t\t\t\t\tthis.throwError('Expected expression');\n\t\t\t\t\t}\n\t\t\t\t\tenv.node = {\n\t\t\t\t\t\ttype: CONDITIONAL_EXP,\n\t\t\t\t\t\ttest,\n\t\t\t\t\t\tconsequent,\n\t\t\t\t\t\talternate,\n\t\t\t\t\t};\n\n\t\t\t\t\t// check for operators of higher priority than ternary (i.e. assignment)\n\t\t\t\t\t// jsep sets || at 1, and assignment at 0.9, and conditional should be between them\n\t\t\t\t\tif (test.operator && jsep.binary_ops[test.operator] <= 0.9) {\n\t\t\t\t\t\tlet newTest = test;\n\t\t\t\t\t\twhile (newTest.right.operator && jsep.binary_ops[newTest.right.operator] <= 0.9) {\n\t\t\t\t\t\t\tnewTest = newTest.right;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tenv.node.test = newTest.right;\n\t\t\t\t\t\tnewTest.right = env.node;\n\t\t\t\t\t\tenv.node = test;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis.throwError('Expected :');\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n};\n\n// Add default plugins:\n\njsep.plugins.register(ternary);\n\nexport { Jsep, jsep as default };\n","const FSLASH_CODE = 47; // '/'\nconst BSLASH_CODE = 92; // '\\\\'\n\nvar index = {\n\tname: 'regex',\n\n\tinit(jsep) {\n\t\t// Regex literal: /abc123/ig\n\t\tjsep.hooks.add('gobble-token', function gobbleRegexLiteral(env) {\n\t\t\tif (this.code === FSLASH_CODE) {\n\t\t\t\tconst patternIndex = ++this.index;\n\n\t\t\t\tlet inCharSet = false;\n\t\t\t\twhile (this.index < this.expr.length) {\n\t\t\t\t\tif (this.code === FSLASH_CODE && !inCharSet) {\n\t\t\t\t\t\tconst pattern = this.expr.slice(patternIndex, this.index);\n\n\t\t\t\t\t\tlet flags = '';\n\t\t\t\t\t\twhile (++this.index < this.expr.length) {\n\t\t\t\t\t\t\tconst code = this.code;\n\t\t\t\t\t\t\tif ((code >= 97 && code <= 122) // a...z\n\t\t\t\t\t\t\t\t|| (code >= 65 && code <= 90) // A...Z\n\t\t\t\t\t\t\t\t|| (code >= 48 && code <= 57)) { // 0-9\n\t\t\t\t\t\t\t\tflags += this.char;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tlet value;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tvalue = new RegExp(pattern, flags);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch (e) {\n\t\t\t\t\t\t\tthis.throwError(e.message);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tenv.node = {\n\t\t\t\t\t\t\ttype: jsep.LITERAL,\n\t\t\t\t\t\t\tvalue,\n\t\t\t\t\t\t\traw: this.expr.slice(patternIndex - 1, this.index),\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\t// allow . [] and () after regex: /regex/.test(a)\n\t\t\t\t\t\tenv.node = this.gobbleTokenProperty(env.node);\n\t\t\t\t\t\treturn env.node;\n\t\t\t\t\t}\n\t\t\t\t\tif (this.code === jsep.OBRACK_CODE) {\n\t\t\t\t\t\tinCharSet = true;\n\t\t\t\t\t}\n\t\t\t\t\telse if (inCharSet && this.code === jsep.CBRACK_CODE) {\n\t\t\t\t\t\tinCharSet = false;\n\t\t\t\t\t}\n\t\t\t\t\tthis.index += this.code === BSLASH_CODE ? 2 : 1;\n\t\t\t\t}\n\t\t\t\tthis.throwError('Unclosed Regex');\n\t\t\t}\n\t\t});\n\t},\n};\n\nexport { index as default };\n","const PLUS_CODE = 43; // +\nconst MINUS_CODE = 45; // -\n\nconst plugin = {\n\tname: 'assignment',\n\n\tassignmentOperators: new Set([\n\t\t'=',\n\t\t'*=',\n\t\t'**=',\n\t\t'/=',\n\t\t'%=',\n\t\t'+=',\n\t\t'-=',\n\t\t'<<=',\n\t\t'>>=',\n\t\t'>>>=',\n\t\t'&=',\n\t\t'^=',\n\t\t'|=',\n\t\t'||=',\n\t\t'&&=',\n\t\t'??=',\n\t]),\n\tupdateOperators: [PLUS_CODE, MINUS_CODE],\n\tassignmentPrecedence: 0.9,\n\n\tinit(jsep) {\n\t\tconst updateNodeTypes = [jsep.IDENTIFIER, jsep.MEMBER_EXP];\n\t\tplugin.assignmentOperators.forEach(op => jsep.addBinaryOp(op, plugin.assignmentPrecedence, true));\n\n\t\tjsep.hooks.add('gobble-token', function gobbleUpdatePrefix(env) {\n\t\t\tconst code = this.code;\n\t\t\tif (plugin.updateOperators.some(c => c === code && c === this.expr.charCodeAt(this.index + 1))) {\n\t\t\t\tthis.index += 2;\n\t\t\t\tenv.node = {\n\t\t\t\t\ttype: 'UpdateExpression',\n\t\t\t\t\toperator: code === PLUS_CODE ? '++' : '--',\n\t\t\t\t\targument: this.gobbleTokenProperty(this.gobbleIdentifier()),\n\t\t\t\t\tprefix: true,\n\t\t\t\t};\n\t\t\t\tif (!env.node.argument || !updateNodeTypes.includes(env.node.argument.type)) {\n\t\t\t\t\tthis.throwError(`Unexpected ${env.node.operator}`);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tjsep.hooks.add('after-token', function gobbleUpdatePostfix(env) {\n\t\t\tif (env.node) {\n\t\t\t\tconst code = this.code;\n\t\t\t\tif (plugin.updateOperators.some(c => c === code && c === this.expr.charCodeAt(this.index + 1))) {\n\t\t\t\t\tif (!updateNodeTypes.includes(env.node.type)) {\n\t\t\t\t\t\tthis.throwError(`Unexpected ${env.node.operator}`);\n\t\t\t\t\t}\n\t\t\t\t\tthis.index += 2;\n\t\t\t\t\tenv.node = {\n\t\t\t\t\t\ttype: 'UpdateExpression',\n\t\t\t\t\t\toperator: code === PLUS_CODE ? '++' : '--',\n\t\t\t\t\t\targument: env.node,\n\t\t\t\t\t\tprefix: false,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tjsep.hooks.add('after-expression', function gobbleAssignment(env) {\n\t\t\tif (env.node) {\n\t\t\t\t// Note: Binaries can be chained in a single expression to respect\n\t\t\t\t// operator precedence (i.e. a = b = 1 + 2 + 3)\n\t\t\t\t// Update all binary assignment nodes in the tree\n\t\t\t\tupdateBinariesToAssignments(env.node);\n\t\t\t}\n\t\t});\n\n\t\tfunction updateBinariesToAssignments(node) {\n\t\t\tif (plugin.assignmentOperators.has(node.operator)) {\n\t\t\t\tnode.type = 'AssignmentExpression';\n\t\t\t\tupdateBinariesToAssignments(node.left);\n\t\t\t\tupdateBinariesToAssignments(node.right);\n\t\t\t}\n\t\t\telse if (!node.operator) {\n\t\t\t\tObject.values(node).forEach((val) => {\n\t\t\t\t\tif (val && typeof val === 'object') {\n\t\t\t\t\t\tupdateBinariesToAssignments(val);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t},\n};\n\nexport { plugin as default };\n","/* eslint-disable no-bitwise -- Convenient */\nimport jsep from 'jsep';\nimport jsepRegex from '@jsep-plugin/regex';\nimport jsepAssignment from '@jsep-plugin/assignment';\n\n// register plugins\njsep.plugins.register(jsepRegex, jsepAssignment);\njsep.addUnaryOp('typeof');\njsep.addUnaryOp('void');\njsep.addLiteral('null', null);\njsep.addLiteral('undefined', undefined);\n\nconst BLOCKED_PROTO_PROPERTIES = new Set([\n 'constructor',\n '__proto__',\n '__defineGetter__',\n '__defineSetter__',\n '__lookupGetter__',\n '__lookupSetter__'\n]);\n\nconst SafeEval = {\n /**\n * @param {jsep.Expression} ast\n * @param {Record} subs\n */\n evalAst (ast, subs) {\n switch (ast.type) {\n case 'BinaryExpression':\n case 'LogicalExpression':\n return SafeEval.evalBinaryExpression(ast, subs);\n case 'Compound':\n return SafeEval.evalCompound(ast, subs);\n case 'ConditionalExpression':\n return SafeEval.evalConditionalExpression(ast, subs);\n case 'Identifier':\n return SafeEval.evalIdentifier(ast, subs);\n case 'Literal':\n return SafeEval.evalLiteral(ast, subs);\n case 'MemberExpression':\n return SafeEval.evalMemberExpression(ast, subs);\n case 'UnaryExpression':\n return SafeEval.evalUnaryExpression(ast, subs);\n case 'ArrayExpression':\n return SafeEval.evalArrayExpression(ast, subs);\n case 'CallExpression':\n return SafeEval.evalCallExpression(ast, subs);\n case 'AssignmentExpression':\n return SafeEval.evalAssignmentExpression(ast, subs);\n default:\n throw SyntaxError('Unexpected expression', ast);\n }\n },\n evalBinaryExpression (ast, subs) {\n const result = {\n '||': (a, b) => a || b(),\n '&&': (a, b) => a && b(),\n '|': (a, b) => a | b(),\n '^': (a, b) => a ^ b(),\n '&': (a, b) => a & b(),\n // eslint-disable-next-line eqeqeq -- API\n '==': (a, b) => a == b(),\n // eslint-disable-next-line eqeqeq -- API\n '!=': (a, b) => a != b(),\n '===': (a, b) => a === b(),\n '!==': (a, b) => a !== b(),\n '<': (a, b) => a < b(),\n '>': (a, b) => a > b(),\n '<=': (a, b) => a <= b(),\n '>=': (a, b) => a >= b(),\n '<<': (a, b) => a << b(),\n '>>': (a, b) => a >> b(),\n '>>>': (a, b) => a >>> b(),\n '+': (a, b) => a + b(),\n '-': (a, b) => a - b(),\n '*': (a, b) => a * b(),\n '/': (a, b) => a / b(),\n '%': (a, b) => a % b()\n }[ast.operator](\n SafeEval.evalAst(ast.left, subs),\n () => SafeEval.evalAst(ast.right, subs)\n );\n return result;\n },\n evalCompound (ast, subs) {\n let last;\n for (let i = 0; i < ast.body.length; i++) {\n if (\n ast.body[i].type === 'Identifier' &&\n ['var', 'let', 'const'].includes(ast.body[i].name) &&\n ast.body[i + 1] &&\n ast.body[i + 1].type === 'AssignmentExpression'\n ) {\n // var x=2; is detected as\n // [{Identifier var}, {AssignmentExpression x=2}]\n // eslint-disable-next-line @stylistic/max-len -- Long\n // eslint-disable-next-line sonarjs/updated-loop-counter -- Convenient\n i += 1;\n }\n const expr = ast.body[i];\n last = SafeEval.evalAst(expr, subs);\n }\n return last;\n },\n evalConditionalExpression (ast, subs) {\n if (SafeEval.evalAst(ast.test, subs)) {\n return SafeEval.evalAst(ast.consequent, subs);\n }\n return SafeEval.evalAst(ast.alternate, subs);\n },\n evalIdentifier (ast, subs) {\n if (Object.hasOwn(subs, ast.name)) {\n return subs[ast.name];\n }\n throw ReferenceError(`${ast.name} is not defined`);\n },\n evalLiteral (ast) {\n return ast.value;\n },\n evalMemberExpression (ast, subs) {\n const prop = String(\n // NOTE: `String(value)` throws error when\n // value has overwritten the toString method to return non-string\n // i.e. `value = {toString: () => []}`\n ast.computed\n ? SafeEval.evalAst(ast.property) // `object[property]`\n : ast.property.name // `object.property` property is Identifier\n );\n const obj = SafeEval.evalAst(ast.object, subs);\n if (obj === undefined || obj === null) {\n throw TypeError(\n `Cannot read properties of ${obj} (reading '${prop}')`\n );\n }\n if (!Object.hasOwn(obj, prop) && BLOCKED_PROTO_PROPERTIES.has(prop)) {\n throw TypeError(\n `Cannot read properties of ${obj} (reading '${prop}')`\n );\n }\n const result = obj[prop];\n if (typeof result === 'function') {\n return result.bind(obj); // arrow functions aren't affected by bind.\n }\n return result;\n },\n evalUnaryExpression (ast, subs) {\n const result = {\n '-': (a) => -SafeEval.evalAst(a, subs),\n '!': (a) => !SafeEval.evalAst(a, subs),\n '~': (a) => ~SafeEval.evalAst(a, subs),\n // eslint-disable-next-line no-implicit-coercion -- API\n '+': (a) => +SafeEval.evalAst(a, subs),\n typeof: (a) => typeof SafeEval.evalAst(a, subs),\n // eslint-disable-next-line no-void, sonarjs/void-use -- feature\n void: (a) => void SafeEval.evalAst(a, subs)\n }[ast.operator](ast.argument);\n return result;\n },\n evalArrayExpression (ast, subs) {\n return ast.elements.map((el) => SafeEval.evalAst(el, subs));\n },\n evalCallExpression (ast, subs) {\n const args = ast.arguments.map((arg) => SafeEval.evalAst(arg, subs));\n const func = SafeEval.evalAst(ast.callee, subs);\n /* c8 ignore start */\n if (func === Function) {\n // unreachable since BLOCKED_PROTO_PROPERTIES includes 'constructor'\n throw new Error('Function constructor is disabled');\n }\n /* c8 ignore end */\n return func(...args);\n },\n evalAssignmentExpression (ast, subs) {\n if (ast.left.type !== 'Identifier') {\n throw SyntaxError('Invalid left-hand side in assignment');\n }\n const id = ast.left.name;\n const value = SafeEval.evalAst(ast.right, subs);\n subs[id] = value;\n return subs[id];\n }\n};\n\n/**\n * A replacement for NodeJS' VM.Script which is also {@link https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP | Content Security Policy} friendly.\n */\nclass SafeScript {\n /**\n * @param {string} expr Expression to evaluate\n */\n constructor (expr) {\n this.code = expr;\n this.ast = jsep(this.code);\n }\n\n /**\n * @param {object} context Object whose items will be added\n * to evaluation\n * @returns {EvaluatedResult} Result of evaluated code\n */\n runInNewContext (context) {\n // `Object.create(null)` creates a prototypeless object\n const keyMap = Object.assign(Object.create(null), context);\n return SafeEval.evalAst(this.ast, keyMap);\n }\n}\n\nexport {SafeScript};\n","/* eslint-disable camelcase -- Convenient for escaping */\n\nimport {SafeScript} from './Safe-Script.js';\n\n/**\n * @typedef {null|boolean|number|string|object|GenericArray} JSONObject\n */\n\n/**\n * @typedef {any} AnyItem\n */\n\n/**\n * @typedef {any} AnyResult\n */\n\n/**\n * Copies array and then pushes item into it.\n * @param {GenericArray} arr Array to copy and into which to push\n * @param {AnyItem} item Array item to add (to end)\n * @returns {GenericArray} Copy of the original array\n */\nfunction push (arr, item) {\n arr = arr.slice();\n arr.push(item);\n return arr;\n}\n/**\n * Copies array and then unshifts item into it.\n * @param {AnyItem} item Array item to add (to beginning)\n * @param {GenericArray} arr Array to copy and into which to unshift\n * @returns {GenericArray} Copy of the original array\n */\nfunction unshift (item, arr) {\n arr = arr.slice();\n arr.unshift(item);\n return arr;\n}\n\n/**\n * Caught when JSONPath is used without `new` but rethrown if with `new`\n * @extends Error\n */\nclass NewError extends Error {\n /**\n * @param {AnyResult} value The evaluated scalar value\n */\n constructor (value) {\n super(\n 'JSONPath should not be called with \"new\" (it prevents return ' +\n 'of (unwrapped) scalar values)'\n );\n this.avoidNew = true;\n this.value = value;\n this.name = 'NewError';\n }\n}\n\n/**\n* @typedef {object} ReturnObject\n* @property {string} path\n* @property {JSONObject} value\n* @property {object|GenericArray} parent\n* @property {string} parentProperty\n*/\n\n/**\n* @callback JSONPathCallback\n* @param {string|object} preferredOutput\n* @param {\"value\"|\"property\"} type\n* @param {ReturnObject} fullRetObj\n* @returns {void}\n*/\n\n/**\n* @callback OtherTypeCallback\n* @param {JSONObject} val\n* @param {string} path\n* @param {object|GenericArray} parent\n* @param {string} parentPropName\n* @returns {boolean}\n*/\n\n/**\n * @typedef {any} ContextItem\n */\n\n/**\n * @typedef {any} EvaluatedResult\n */\n\n/**\n* @callback EvalCallback\n* @param {string} code\n* @param {ContextItem} context\n* @returns {EvaluatedResult}\n*/\n\n/**\n * @typedef {typeof SafeScript} EvalClass\n */\n\n/**\n * @typedef {object} JSONPathOptions\n * @property {JSON} json\n * @property {string|string[]} path\n * @property {\"value\"|\"path\"|\"pointer\"|\"parent\"|\"parentProperty\"|\n * \"all\"} [resultType=\"value\"]\n * @property {boolean} [flatten=false]\n * @property {boolean} [wrap=true]\n * @property {object} [sandbox={}]\n * @property {EvalCallback|EvalClass|'safe'|'native'|\n * boolean} [eval = 'safe']\n * @property {object|GenericArray|null} [parent=null]\n * @property {string|null} [parentProperty=null]\n * @property {JSONPathCallback} [callback]\n * @property {OtherTypeCallback} [otherTypeCallback] Defaults to\n * function which throws on encountering `@other`\n * @property {boolean} [autostart=true]\n */\n\n/**\n * @param {string|JSONPathOptions} opts If a string, will be treated as `expr`\n * @param {string} [expr] JSON path to evaluate\n * @param {JSON} [obj] JSON object to evaluate against\n * @param {JSONPathCallback} [callback] Passed 3 arguments: 1) desired payload\n * per `resultType`, 2) `\"value\"|\"property\"`, 3) Full returned object with\n * all payloads\n * @param {OtherTypeCallback} [otherTypeCallback] If `@other()` is at the end\n * of one's query, this will be invoked with the value of the item, its\n * path, its parent, and its parent's property name, and it should return\n * a boolean indicating whether the supplied value belongs to the \"other\"\n * type or not (or it may handle transformations and return `false`).\n * @returns {JSONPath}\n * @class\n */\nfunction JSONPath (opts, expr, obj, callback, otherTypeCallback) {\n // eslint-disable-next-line no-restricted-syntax -- Allow for pseudo-class\n if (!(this instanceof JSONPath)) {\n try {\n return new JSONPath(opts, expr, obj, callback, otherTypeCallback);\n } catch (e) {\n if (!e.avoidNew) {\n throw e;\n }\n return e.value;\n }\n }\n\n if (typeof opts === 'string') {\n otherTypeCallback = callback;\n callback = obj;\n obj = expr;\n expr = opts;\n opts = null;\n }\n const optObj = opts && typeof opts === 'object';\n opts = opts || {};\n this.json = opts.json || obj;\n this.path = opts.path || expr;\n this.resultType = opts.resultType || 'value';\n this.flatten = opts.flatten || false;\n this.wrap = Object.hasOwn(opts, 'wrap') ? opts.wrap : true;\n this.sandbox = opts.sandbox || {};\n this.eval = opts.eval === undefined ? 'safe' : opts.eval;\n this.ignoreEvalErrors = (typeof opts.ignoreEvalErrors === 'undefined')\n ? false\n : opts.ignoreEvalErrors;\n this.parent = opts.parent || null;\n this.parentProperty = opts.parentProperty || null;\n this.callback = opts.callback || callback || null;\n this.otherTypeCallback = opts.otherTypeCallback ||\n otherTypeCallback ||\n function () {\n throw new TypeError(\n 'You must supply an otherTypeCallback callback option ' +\n 'with the @other() operator.'\n );\n };\n\n if (opts.autostart !== false) {\n const args = {\n path: (optObj ? opts.path : expr)\n };\n if (!optObj) {\n args.json = obj;\n } else if ('json' in opts) {\n args.json = opts.json;\n }\n const ret = this.evaluate(args);\n if (!ret || typeof ret !== 'object') {\n throw new NewError(ret);\n }\n return ret;\n }\n}\n\n// PUBLIC METHODS\nJSONPath.prototype.evaluate = function (\n expr, json, callback, otherTypeCallback\n) {\n let currParent = this.parent,\n currParentProperty = this.parentProperty;\n let {flatten, wrap} = this;\n\n this.currResultType = this.resultType;\n this.currEval = this.eval;\n this.currSandbox = this.sandbox;\n callback = callback || this.callback;\n this.currOtherTypeCallback = otherTypeCallback || this.otherTypeCallback;\n\n json = json || this.json;\n expr = expr || this.path;\n if (expr && typeof expr === 'object' && !Array.isArray(expr)) {\n if (!expr.path && expr.path !== '') {\n throw new TypeError(\n 'You must supply a \"path\" property when providing an object ' +\n 'argument to JSONPath.evaluate().'\n );\n }\n if (!(Object.hasOwn(expr, 'json'))) {\n throw new TypeError(\n 'You must supply a \"json\" property when providing an object ' +\n 'argument to JSONPath.evaluate().'\n );\n }\n ({json} = expr);\n flatten = Object.hasOwn(expr, 'flatten') ? expr.flatten : flatten;\n this.currResultType = Object.hasOwn(expr, 'resultType')\n ? expr.resultType\n : this.currResultType;\n this.currSandbox = Object.hasOwn(expr, 'sandbox')\n ? expr.sandbox\n : this.currSandbox;\n wrap = Object.hasOwn(expr, 'wrap') ? expr.wrap : wrap;\n this.currEval = Object.hasOwn(expr, 'eval')\n ? expr.eval\n : this.currEval;\n callback = Object.hasOwn(expr, 'callback') ? expr.callback : callback;\n this.currOtherTypeCallback = Object.hasOwn(expr, 'otherTypeCallback')\n ? expr.otherTypeCallback\n : this.currOtherTypeCallback;\n currParent = Object.hasOwn(expr, 'parent') ? expr.parent : currParent;\n currParentProperty = Object.hasOwn(expr, 'parentProperty')\n ? expr.parentProperty\n : currParentProperty;\n expr = expr.path;\n }\n currParent = currParent || null;\n currParentProperty = currParentProperty || null;\n\n if (Array.isArray(expr)) {\n expr = JSONPath.toPathString(expr);\n }\n if ((!expr && expr !== '') || !json) {\n return undefined;\n }\n\n const exprList = JSONPath.toPathArray(expr);\n if (exprList[0] === '$' && exprList.length > 1) {\n exprList.shift();\n }\n this._hasParentSelector = null;\n const result = this\n ._trace(\n exprList, json, ['$'], currParent, currParentProperty, callback\n )\n .filter(function (ea) {\n return ea && !ea.isParentSelector;\n });\n\n if (!result.length) {\n return wrap ? [] : undefined;\n }\n if (!wrap && result.length === 1 && !result[0].hasArrExpr) {\n return this._getPreferredOutput(result[0]);\n }\n return result.reduce((rslt, ea) => {\n const valOrPath = this._getPreferredOutput(ea);\n if (flatten && Array.isArray(valOrPath)) {\n rslt = rslt.concat(valOrPath);\n } else {\n rslt.push(valOrPath);\n }\n return rslt;\n }, []);\n};\n\n// PRIVATE METHODS\n\nJSONPath.prototype._getPreferredOutput = function (ea) {\n const resultType = this.currResultType;\n switch (resultType) {\n case 'all': {\n const path = Array.isArray(ea.path)\n ? ea.path\n : JSONPath.toPathArray(ea.path);\n ea.pointer = JSONPath.toPointer(path);\n ea.path = typeof ea.path === 'string'\n ? ea.path\n : JSONPath.toPathString(ea.path);\n return ea;\n } case 'value': case 'parent': case 'parentProperty':\n return ea[resultType];\n case 'path':\n return JSONPath.toPathString(ea[resultType]);\n case 'pointer':\n return JSONPath.toPointer(ea.path);\n default:\n throw new TypeError('Unknown result type');\n }\n};\n\nJSONPath.prototype._handleCallback = function (fullRetObj, callback, type) {\n if (callback) {\n const preferredOutput = this._getPreferredOutput(fullRetObj);\n fullRetObj.path = typeof fullRetObj.path === 'string'\n ? fullRetObj.path\n : JSONPath.toPathString(fullRetObj.path);\n // eslint-disable-next-line n/callback-return -- No need to return\n callback(preferredOutput, type, fullRetObj);\n }\n};\n\n/**\n *\n * @param {string} expr\n * @param {JSONObject} val\n * @param {string} path\n * @param {object|GenericArray} parent\n * @param {string} parentPropName\n * @param {JSONPathCallback} callback\n * @param {boolean} hasArrExpr\n * @param {boolean} literalPriority\n * @returns {ReturnObject|ReturnObject[]}\n */\nJSONPath.prototype._trace = function (\n expr, val, path, parent, parentPropName, callback, hasArrExpr,\n literalPriority\n) {\n // No expr to follow? return path and value as the result of\n // this trace branch\n let retObj;\n if (!expr.length) {\n retObj = {\n path,\n value: val,\n parent,\n parentProperty: parentPropName,\n hasArrExpr\n };\n this._handleCallback(retObj, callback, 'value');\n return retObj;\n }\n\n const loc = expr[0], x = expr.slice(1);\n\n // We need to gather the return value of recursive trace calls in order to\n // do the parent sel computation.\n const ret = [];\n /**\n *\n * @param {ReturnObject|ReturnObject[]} elems\n * @returns {void}\n */\n function addRet (elems) {\n if (Array.isArray(elems)) {\n // This was causing excessive stack size in Node (with or\n // without Babel) against our performance test:\n // `ret.push(...elems);`\n elems.forEach((t) => {\n ret.push(t);\n });\n } else {\n ret.push(elems);\n }\n }\n if ((typeof loc !== 'string' || literalPriority) && val &&\n Object.hasOwn(val, loc)\n ) { // simple case--directly follow property\n addRet(this._trace(x, val[loc], push(path, loc), val, loc, callback,\n hasArrExpr));\n // eslint-disable-next-line unicorn/prefer-switch -- Part of larger `if`\n } else if (loc === '*') { // all child properties\n this._walk(val, (m) => {\n addRet(this._trace(\n x, val[m], push(path, m), val, m, callback, true, true\n ));\n });\n } else if (loc === '..') { // all descendent parent properties\n // Check remaining expression with val's immediate children\n addRet(\n this._trace(x, val, path, parent, parentPropName, callback,\n hasArrExpr)\n );\n this._walk(val, (m) => {\n // We don't join m and x here because we only want parents,\n // not scalar values\n if (typeof val[m] === 'object') {\n // Keep going with recursive descent on val's\n // object children\n addRet(this._trace(\n expr.slice(), val[m], push(path, m), val, m, callback, true\n ));\n }\n });\n // The parent sel computation is handled in the frame above using the\n // ancestor object of val\n } else if (loc === '^') {\n // This is not a final endpoint, so we do not invoke the callback here\n this._hasParentSelector = true;\n return {\n path: path.slice(0, -1),\n expr: x,\n isParentSelector: true\n };\n } else if (loc === '~') { // property name\n retObj = {\n path: push(path, loc),\n value: parentPropName,\n parent,\n parentProperty: null\n };\n this._handleCallback(retObj, callback, 'property');\n return retObj;\n } else if (loc === '$') { // root only\n addRet(this._trace(x, val, path, null, null, callback, hasArrExpr));\n } else if ((/^(-?\\d*):(-?\\d*):?(\\d*)$/u).test(loc)) { // [start:end:step] Python slice syntax\n addRet(\n this._slice(loc, x, val, path, parent, parentPropName, callback)\n );\n } else if (loc.indexOf('?(') === 0) { // [?(expr)] (filtering)\n if (this.currEval === false) {\n throw new Error('Eval [?(expr)] prevented in JSONPath expression.');\n }\n const safeLoc = loc.replace(/^\\?\\((.*?)\\)$/u, '$1');\n // check for a nested filter expression\n const nested = (/@.?([^?]*)[['](\\??\\(.*?\\))(?!.\\)\\])[\\]']/gu).exec(safeLoc);\n if (nested) {\n // find if there are matches in the nested expression\n // add them to the result set if there is at least one match\n this._walk(val, (m) => {\n const npath = [nested[2]];\n const nvalue = nested[1]\n ? val[m][nested[1]]\n : val[m];\n const filterResults = this._trace(npath, nvalue, path,\n parent, parentPropName, callback, true);\n if (filterResults.length > 0) {\n addRet(this._trace(x, val[m], push(path, m), val,\n m, callback, true));\n }\n });\n } else {\n this._walk(val, (m) => {\n if (this._eval(safeLoc, val[m], m, path, parent,\n parentPropName)) {\n addRet(this._trace(x, val[m], push(path, m), val, m,\n callback, true));\n }\n });\n }\n } else if (loc[0] === '(') { // [(expr)] (dynamic property/index)\n if (this.currEval === false) {\n throw new Error('Eval [(expr)] prevented in JSONPath expression.');\n }\n // As this will resolve to a property name (but we don't know it\n // yet), property and parent information is relative to the\n // parent of the property to which this expression will resolve\n addRet(this._trace(unshift(\n this._eval(\n loc, val, path.at(-1),\n path.slice(0, -1), parent, parentPropName\n ),\n x\n ), val, path, parent, parentPropName, callback, hasArrExpr));\n } else if (loc[0] === '@') { // value type: @boolean(), etc.\n let addType = false;\n const valueType = loc.slice(1, -2);\n switch (valueType) {\n case 'scalar':\n if (!val || !(['object', 'function'].includes(typeof val))) {\n addType = true;\n }\n break;\n case 'boolean': case 'string': case 'undefined': case 'function':\n if (typeof val === valueType) {\n addType = true;\n }\n break;\n case 'integer':\n if (Number.isFinite(val) && !(val % 1)) {\n addType = true;\n }\n break;\n case 'number':\n if (Number.isFinite(val)) {\n addType = true;\n }\n break;\n case 'nonFinite':\n if (typeof val === 'number' && !Number.isFinite(val)) {\n addType = true;\n }\n break;\n case 'object':\n if (val && typeof val === valueType) {\n addType = true;\n }\n break;\n case 'array':\n if (Array.isArray(val)) {\n addType = true;\n }\n break;\n case 'other':\n addType = this.currOtherTypeCallback(\n val, path, parent, parentPropName\n );\n break;\n case 'null':\n if (val === null) {\n addType = true;\n }\n break;\n /* c8 ignore next 2 */\n default:\n throw new TypeError('Unknown value type ' + valueType);\n }\n if (addType) {\n retObj = {path, value: val, parent, parentProperty: parentPropName};\n this._handleCallback(retObj, callback, 'value');\n return retObj;\n }\n // `-escaped property\n } else if (loc[0] === '`' && val && Object.hasOwn(val, loc.slice(1))) {\n const locProp = loc.slice(1);\n addRet(this._trace(\n x, val[locProp], push(path, locProp), val, locProp, callback,\n hasArrExpr, true\n ));\n } else if (loc.includes(',')) { // [name1,name2,...]\n const parts = loc.split(',');\n for (const part of parts) {\n addRet(this._trace(\n unshift(part, x), val, path, parent, parentPropName, callback,\n true\n ));\n }\n // simple case--directly follow property\n } else if (\n !literalPriority && val && Object.hasOwn(val, loc)\n ) {\n addRet(\n this._trace(x, val[loc], push(path, loc), val, loc, callback,\n hasArrExpr, true)\n );\n }\n\n // We check the resulting values for parent selections. For parent\n // selections we discard the value object and continue the trace with the\n // current val object\n if (this._hasParentSelector) {\n for (let t = 0; t < ret.length; t++) {\n const rett = ret[t];\n if (rett && rett.isParentSelector) {\n const tmp = this._trace(\n rett.expr, val, rett.path, parent, parentPropName, callback,\n hasArrExpr\n );\n if (Array.isArray(tmp)) {\n ret[t] = tmp[0];\n const tl = tmp.length;\n for (let tt = 1; tt < tl; tt++) {\n // eslint-disable-next-line @stylistic/max-len -- Long\n // eslint-disable-next-line sonarjs/updated-loop-counter -- Convenient\n t++;\n ret.splice(t, 0, tmp[tt]);\n }\n } else {\n ret[t] = tmp;\n }\n }\n }\n }\n return ret;\n};\n\nJSONPath.prototype._walk = function (val, f) {\n if (Array.isArray(val)) {\n const n = val.length;\n for (let i = 0; i < n; i++) {\n f(i);\n }\n } else if (val && typeof val === 'object') {\n Object.keys(val).forEach((m) => {\n f(m);\n });\n }\n};\n\nJSONPath.prototype._slice = function (\n loc, expr, val, path, parent, parentPropName, callback\n) {\n if (!Array.isArray(val)) {\n return undefined;\n }\n const len = val.length, parts = loc.split(':'),\n step = (parts[2] && Number.parseInt(parts[2])) || 1;\n let start = (parts[0] && Number.parseInt(parts[0])) || 0,\n end = (parts[1] && Number.parseInt(parts[1])) || len;\n start = (start < 0) ? Math.max(0, start + len) : Math.min(len, start);\n end = (end < 0) ? Math.max(0, end + len) : Math.min(len, end);\n const ret = [];\n for (let i = start; i < end; i += step) {\n const tmp = this._trace(\n unshift(i, expr), val, path, parent, parentPropName, callback, true\n );\n // Should only be possible to be an array here since first part of\n // ``unshift(i, expr)` passed in above would not be empty, nor `~`,\n // nor begin with `@` (as could return objects)\n // This was causing excessive stack size in Node (with or\n // without Babel) against our performance test: `ret.push(...tmp);`\n tmp.forEach((t) => {\n ret.push(t);\n });\n }\n return ret;\n};\n\nJSONPath.prototype._eval = function (\n code, _v, _vname, path, parent, parentPropName\n) {\n this.currSandbox._$_parentProperty = parentPropName;\n this.currSandbox._$_parent = parent;\n this.currSandbox._$_property = _vname;\n this.currSandbox._$_root = this.json;\n this.currSandbox._$_v = _v;\n\n const containsPath = code.includes('@path');\n if (containsPath) {\n this.currSandbox._$_path = JSONPath.toPathString(path.concat([_vname]));\n }\n\n const scriptCacheKey = this.currEval + 'Script:' + code;\n if (!JSONPath.cache[scriptCacheKey]) {\n let script = code\n .replaceAll('@parentProperty', '_$_parentProperty')\n .replaceAll('@parent', '_$_parent')\n .replaceAll('@property', '_$_property')\n .replaceAll('@root', '_$_root')\n .replaceAll(/@([.\\s)[])/gu, '_$_v$1');\n if (containsPath) {\n script = script.replaceAll('@path', '_$_path');\n }\n if (\n this.currEval === 'safe' ||\n this.currEval === true ||\n this.currEval === undefined\n ) {\n JSONPath.cache[scriptCacheKey] = new this.safeVm.Script(script);\n } else if (this.currEval === 'native') {\n JSONPath.cache[scriptCacheKey] = new this.vm.Script(script);\n } else if (\n typeof this.currEval === 'function' &&\n this.currEval.prototype &&\n Object.hasOwn(this.currEval.prototype, 'runInNewContext')\n ) {\n const CurrEval = this.currEval;\n JSONPath.cache[scriptCacheKey] = new CurrEval(script);\n } else if (typeof this.currEval === 'function') {\n JSONPath.cache[scriptCacheKey] = {\n runInNewContext: (context) => this.currEval(script, context)\n };\n } else {\n throw new TypeError(`Unknown \"eval\" property \"${this.currEval}\"`);\n }\n }\n\n try {\n return JSONPath.cache[scriptCacheKey].runInNewContext(this.currSandbox);\n } catch (e) {\n if (this.ignoreEvalErrors) {\n return false;\n }\n throw new Error('jsonPath: ' + e.message + ': ' + code);\n }\n};\n\n// PUBLIC CLASS PROPERTIES AND METHODS\n\n// Could store the cache object itself\nJSONPath.cache = {};\n\n/**\n * @param {string[]} pathArr Array to convert\n * @returns {string} The path string\n */\nJSONPath.toPathString = function (pathArr) {\n const x = pathArr, n = x.length;\n let p = '$';\n for (let i = 1; i < n; i++) {\n if (!(/^(~|\\^|@.*?\\(\\))$/u).test(x[i])) {\n p += (/^[0-9*]+$/u).test(x[i]) ? ('[' + x[i] + ']') : (\"['\" + x[i] + \"']\");\n }\n }\n return p;\n};\n\n/**\n * @param {string} pointer JSON Path\n * @returns {string} JSON Pointer\n */\nJSONPath.toPointer = function (pointer) {\n const x = pointer, n = x.length;\n let p = '';\n for (let i = 1; i < n; i++) {\n if (!(/^(~|\\^|@.*?\\(\\))$/u).test(x[i])) {\n p += '/' + x[i].toString()\n .replaceAll('~', '~0')\n .replaceAll('/', '~1');\n }\n }\n return p;\n};\n\n/**\n * @param {string} expr Expression to convert\n * @returns {string[]}\n */\nJSONPath.toPathArray = function (expr) {\n const {cache} = JSONPath;\n if (cache[expr]) {\n return cache[expr].concat();\n }\n const subx = [];\n const normalized = expr\n // Properties\n .replaceAll(\n /@(?:null|boolean|number|string|integer|undefined|nonFinite|scalar|array|object|function|other)\\(\\)/gu,\n ';$&;'\n )\n // Parenthetical evaluations (filtering and otherwise), directly\n // within brackets or single quotes\n .replaceAll(/[['](\\??\\(.*?\\))[\\]'](?!.\\])/gu, function ($0, $1) {\n return '[#' + (subx.push($1) - 1) + ']';\n })\n // Escape periods and tildes within properties\n .replaceAll(/\\[['\"]([^'\\]]*)['\"]\\]/gu, function ($0, prop) {\n return \"['\" + prop\n .replaceAll('.', '%@%')\n .replaceAll('~', '%%@@%%') +\n \"']\";\n })\n // Properties operator\n .replaceAll('~', ';~;')\n // Split by property boundaries\n .replaceAll(/['\"]?\\.['\"]?(?![^[]*\\])|\\[['\"]?/gu, ';')\n // Reinsert periods within properties\n .replaceAll('%@%', '.')\n // Reinsert tildes within properties\n .replaceAll('%%@@%%', '~')\n // Parent\n .replaceAll(/(?:;)?(\\^+)(?:;)?/gu, function ($0, ups) {\n return ';' + ups.split('').join(';') + ';';\n })\n // Descendents\n .replaceAll(/;;;|;;/gu, ';..;')\n // Remove trailing\n .replaceAll(/;$|'?\\]|'$/gu, '');\n\n const exprList = normalized.split(';').map(function (exp) {\n const match = exp.match(/#(\\d+)/u);\n return !match || !match[1] ? exp : subx[match[1]];\n });\n cache[expr] = exprList;\n return cache[expr].concat();\n};\n\nJSONPath.prototype.safeVm = {\n Script: SafeScript\n};\n\nexport {JSONPath};\n","import {JSONPath} from './jsonpath.js';\n\n/**\n * @typedef {any} ContextItem\n */\n\n/**\n * @typedef {any} EvaluatedResult\n */\n\n/**\n * @callback ConditionCallback\n * @param {ContextItem} item\n * @returns {boolean}\n */\n\n/**\n * Copy items out of one array into another.\n * @param {GenericArray} source Array with items to copy\n * @param {GenericArray} target Array to which to copy\n * @param {ConditionCallback} conditionCb Callback passed the current item;\n * will move item if evaluates to `true`\n * @returns {void}\n */\nconst moveToAnotherArray = function (source, target, conditionCb) {\n const il = source.length;\n for (let i = 0; i < il; i++) {\n const item = source[i];\n if (conditionCb(item)) {\n // eslint-disable-next-line @stylistic/max-len -- Long\n // eslint-disable-next-line sonarjs/updated-loop-counter -- Convenient\n target.push(source.splice(i--, 1)[0]);\n }\n }\n};\n\n/**\n * In-browser replacement for NodeJS' VM.Script.\n */\nclass Script {\n /**\n * @param {string} expr Expression to evaluate\n */\n constructor (expr) {\n this.code = expr;\n }\n\n /**\n * @param {object} context Object whose items will be added\n * to evaluation\n * @returns {EvaluatedResult} Result of evaluated code\n */\n runInNewContext (context) {\n let expr = this.code;\n const keys = Object.keys(context);\n const funcs = [];\n moveToAnotherArray(keys, funcs, (key) => {\n return typeof context[key] === 'function';\n });\n const values = keys.map((vr) => {\n return context[vr];\n });\n\n const funcString = funcs.reduce((s, func) => {\n let fString = context[func].toString();\n if (!(/function/u).test(fString)) {\n fString = 'function ' + fString;\n }\n return 'var ' + func + '=' + fString + ';' + s;\n }, '');\n\n expr = funcString + expr;\n\n // Mitigate http://perfectionkills.com/global-eval-what-are-the-options/#new_function\n if (!(/(['\"])use strict\\1/u).test(expr) && !keys.includes('arguments')) {\n expr = 'var arguments = undefined;' + expr;\n }\n\n // Remove last semi so `return` will be inserted before\n // the previous one instead, allowing for the return\n // of a bare ending expression\n expr = expr.replace(/;\\s*$/u, '');\n\n // Insert `return`\n const lastStatementEnd = expr.lastIndexOf(';');\n const code =\n lastStatementEnd !== -1\n ? expr.slice(0, lastStatementEnd + 1) +\n ' return ' +\n expr.slice(lastStatementEnd + 1)\n : ' return ' + expr;\n\n // eslint-disable-next-line no-new-func -- User's choice\n return new Function(...keys, code)(...values);\n }\n}\n\nJSONPath.prototype.vm = {\n Script\n};\n\nexport {JSONPath};\n"],"names":["Jsep","version","toString","addUnaryOp","op_name","max_unop_len","Math","max","length","unary_ops","addBinaryOp","precedence","isRightAssociative","max_binop_len","binary_ops","right_associative","add","delete","addIdentifierChar","char","additional_identifier_chars","addLiteral","literal_name","literal_value","literals","removeUnaryOp","getMaxKeyLen","removeAllUnaryOps","removeIdentifierChar","removeBinaryOp","removeAllBinaryOps","removeLiteral","removeAllLiterals","this","expr","charAt","index","code","charCodeAt","constructor","parse","obj","Object","keys","map","k","isDecimalDigit","ch","binaryPrecedence","op_val","isIdentifierStart","String","fromCharCode","has","isIdentifierPart","throwError","message","error","Error","description","runHook","name","node","hooks","env","context","run","searchHook","find","callback","call","gobbleSpaces","SPACE_CODE","TAB_CODE","LF_CODE","CR_CODE","nodes","gobbleExpressions","type","COMPOUND","body","untilICode","ch_i","SEMCOL_CODE","COMMA_CODE","gobbleExpression","push","gobbleBinaryExpression","gobbleBinaryOp","to_check","substr","tc_len","hasOwnProperty","biop","prec","stack","biop_info","left","right","i","cur_biop","gobbleToken","value","right_a","comparePrev","prev","pop","BINARY_EXP","operator","PERIOD_CODE","gobbleNumericLiteral","SQUOTE_CODE","DQUOTE_CODE","gobbleStringLiteral","OBRACK_CODE","gobbleArray","argument","UNARY_EXP","prefix","gobbleIdentifier","LITERAL","raw","this_str","THIS_EXP","OPAREN_CODE","gobbleGroup","gobbleTokenProperty","QUMARK_CODE","optional","MEMBER_EXP","computed","object","property","CBRACK_CODE","CALL_EXP","arguments","gobbleArguments","CPAREN_CODE","callee","chCode","number","parseFloat","str","startIndex","quote","closed","substring","start","IDENTIFIER","slice","termination","args","separator_count","arg","SEQUENCE_EXP","expressions","ARRAY_EXP","elements","first","Array","isArray","forEach","assign","plugins","jsep","registered","register","_len","_key","plugin","init","COLON_CODE","Set","true","false","null","stdClassProps","getOwnPropertyNames","filter","prop","includes","undefined","m","ternary","test","consequent","alternate","newTest","patternIndex","inCharSet","pattern","flags","RegExp","e","assignmentOperators","updateOperators","assignmentPrecedence","updateNodeTypes","updateBinariesToAssignments","values","val","op","some","c","jsepRegex","jsepAssignment","BLOCKED_PROTO_PROPERTIES","SafeEval","evalAst","ast","subs","evalBinaryExpression","evalCompound","evalConditionalExpression","evalIdentifier","evalLiteral","evalMemberExpression","evalUnaryExpression","evalArrayExpression","evalCallExpression","evalAssignmentExpression","SyntaxError","||","a","b","&&","|","^","&","==","!=","===","!==","<",">","<=",">=","<<",">>",">>>","+","-","*","/","%","last","hasOwn","ReferenceError","TypeError","result","bind","typeof","void","el","func","Function","id","arr","item","unshift","NewError","super","avoidNew","JSONPath","opts","otherTypeCallback","optObj","json","path","resultType","flatten","wrap","sandbox","eval","ignoreEvalErrors","parent","parentProperty","autostart","ret","evaluate","prototype","currParent","currParentProperty","currResultType","currEval","currSandbox","currOtherTypeCallback","toPathString","exprList","toPathArray","shift","_hasParentSelector","_trace","ea","isParentSelector","hasArrExpr","reduce","rslt","valOrPath","_getPreferredOutput","concat","pointer","toPointer","_handleCallback","fullRetObj","preferredOutput","parentPropName","literalPriority","retObj","loc","x","addRet","elems","t","_walk","_slice","indexOf","safeLoc","replace","nested","exec","npath","nvalue","_eval","at","addType","valueType","Number","isFinite","locProp","parts","split","part","rett","tmp","tl","tt","splice","f","n","len","step","parseInt","end","min","_v","_vname","_$_parentProperty","_$_parent","_$_property","_$_root","_$_v","containsPath","_$_path","scriptCacheKey","cache","script","replaceAll","safeVm","Script","vm","CurrEval","runInNewContext","pathArr","p","subx","$0","$1","ups","join","exp","match","keyMap","create","funcs","source","target","conditionCb","il","moveToAnotherArray","key","vr","s","fString","lastStatementEnd","lastIndexOf"],"mappings":"gPAgGA,MAAMA,EAIL,kBAAWC,GAEV,MAAO,OACR,CAKA,eAAOC,GACN,MAAO,wCAA0CF,EAAKC,OACvD,CAQA,iBAAOE,CAAWC,GAGjB,OAFAJ,EAAKK,aAAeC,KAAKC,IAAIH,EAAQI,OAAQR,EAAKK,cAClDL,EAAKS,UAAUL,GAAW,EACnBJ,CACR,CASA,kBAAOU,CAAYN,EAASO,EAAYC,GASvC,OARAZ,EAAKa,cAAgBP,KAAKC,IAAIH,EAAQI,OAAQR,EAAKa,eACnDb,EAAKc,WAAWV,GAAWO,EACvBC,EACHZ,EAAKe,kBAAkBC,IAAIZ,GAG3BJ,EAAKe,kBAAkBE,OAAOb,GAExBJ,CACR,CAOA,wBAAOkB,CAAkBC,GAExB,OADAnB,EAAKoB,4BAA4BJ,IAAIG,GAC9BnB,CACR,CAQA,iBAAOqB,CAAWC,EAAcC,GAE/B,OADAvB,EAAKwB,SAASF,GAAgBC,EACvBvB,CACR,CAOA,oBAAOyB,CAAcrB,GAKpB,cAJOJ,EAAKS,UAAUL,GAClBA,EAAQI,SAAWR,EAAKK,eAC3BL,EAAKK,aAAeL,EAAK0B,aAAa1B,EAAKS,YAErCT,CACR,CAMA,wBAAO2B,GAIN,OAHA3B,EAAKS,UAAY,CAAE,EACnBT,EAAKK,aAAe,EAEbL,CACR,CAOA,2BAAO4B,CAAqBT,GAE3B,OADAnB,EAAKoB,4BAA4BH,OAAOE,GACjCnB,CACR,CAOA,qBAAO6B,CAAezB,GAQrB,cAPOJ,EAAKc,WAAWV,GAEnBA,EAAQI,SAAWR,EAAKa,gBAC3Bb,EAAKa,cAAgBb,EAAK0B,aAAa1B,EAAKc,aAE7Cd,EAAKe,kBAAkBE,OAAOb,GAEvBJ,CACR,CAMA,yBAAO8B,GAIN,OAHA9B,EAAKc,WAAa,CAAE,EACpBd,EAAKa,cAAgB,EAEdb,CACR,CAOA,oBAAO+B,CAAcT,GAEpB,cADOtB,EAAKwB,SAASF,GACdtB,CACR,CAMA,wBAAOgC,GAGN,OAFAhC,EAAKwB,SAAW,CAAE,EAEXxB,CACR,CAOA,QAAImB,GACH,OAAOc,KAAKC,KAAKC,OAAOF,KAAKG,MAC9B,CAKA,QAAIC,GACH,OAAOJ,KAAKC,KAAKI,WAAWL,KAAKG,MAClC,CAOAG,WAAAA,CAAYL,GAGXD,KAAKC,KAAOA,EACZD,KAAKG,MAAQ,CACd,CAMA,YAAOI,CAAMN,GACZ,OAAQ,IAAIlC,EAAKkC,GAAOM,OACzB,CAOA,mBAAOd,CAAae,GACnB,OAAOnC,KAAKC,IAAI,KAAMmC,OAAOC,KAAKF,GAAKG,KAAIC,GAAKA,EAAErC,SACnD,CAOA,qBAAOsC,CAAeC,GACrB,OAAQA,GAAM,IAAMA,GAAM,EAC3B,CAOA,uBAAOC,CAAiBC,GACvB,OAAOjD,EAAKc,WAAWmC,IAAW,CACnC,CAOA,wBAAOC,CAAkBH,GACxB,OAASA,GAAM,IAAMA,GAAM,IACzBA,GAAM,IAAMA,GAAM,KAClBA,GAAM,MAAQ/C,EAAKc,WAAWqC,OAAOC,aAAaL,KAClD/C,EAAKoB,4BAA4BiC,IAAIF,OAAOC,aAAaL,GAC5D,CAMA,uBAAOO,CAAiBP,GACvB,OAAO/C,EAAKkD,kBAAkBH,IAAO/C,EAAK8C,eAAeC,EAC1D,CAOAQ,UAAAA,CAAWC,GACV,MAAMC,EAAQ,IAAIC,MAAMF,EAAU,iBAAmBvB,KAAKG,OAG1D,MAFAqB,EAAMrB,MAAQH,KAAKG,MACnBqB,EAAME,YAAcH,EACdC,CACP,CAQAG,OAAAA,CAAQC,EAAMC,GACb,GAAI9D,EAAK+D,MAAMF,GAAO,CACrB,MAAMG,EAAM,CAAEC,QAAShC,KAAM6B,QAE7B,OADA9D,EAAK+D,MAAMG,IAAIL,EAAMG,GACdA,EAAIF,IACZ,CACA,OAAOA,CACR,CAOAK,UAAAA,CAAWN,GACV,GAAI7D,EAAK+D,MAAMF,GAAO,CACrB,MAAMG,EAAM,CAAEC,QAAShC,MAKvB,OAJAjC,EAAK+D,MAAMF,GAAMO,MAAK,SAAUC,GAE/B,OADAA,EAASC,KAAKN,EAAIC,QAASD,GACpBA,EAAIF,IACZ,IACOE,EAAIF,IACZ,CACD,CAKAS,YAAAA,GACC,IAAIxB,EAAKd,KAAKI,KAEd,KAAOU,IAAO/C,EAAKwE,YAChBzB,IAAO/C,EAAKyE,UACZ1B,IAAO/C,EAAK0E,SACZ3B,IAAO/C,EAAK2E,SACd5B,EAAKd,KAAKC,KAAKI,aAAaL,KAAKG,OAElCH,KAAK2B,QAAQ,gBACd,CAMApB,KAAAA,GACCP,KAAK2B,QAAQ,cACb,MAAMgB,EAAQ3C,KAAK4C,oBAGbf,EAAwB,IAAjBc,EAAMpE,OACfoE,EAAM,GACP,CACDE,KAAM9E,EAAK+E,SACXC,KAAMJ,GAER,OAAO3C,KAAK2B,QAAQ,YAAaE,EAClC,CAOAe,iBAAAA,CAAkBI,GACjB,IAAgBC,EAAMpB,EAAlBc,EAAQ,GAEZ,KAAO3C,KAAKG,MAAQH,KAAKC,KAAK1B,QAK7B,GAJA0E,EAAOjD,KAAKI,KAIR6C,IAASlF,EAAKmF,aAAeD,IAASlF,EAAKoF,WAC9CnD,KAAKG,aAIL,GAAI0B,EAAO7B,KAAKoD,mBACfT,EAAMU,KAAKxB,QAIP,GAAI7B,KAAKG,MAAQH,KAAKC,KAAK1B,OAAQ,CACvC,GAAI0E,IAASD,EACZ,MAEDhD,KAAKsB,WAAW,eAAiBtB,KAAKd,KAAO,IAC9C,CAIF,OAAOyD,CACR,CAMAS,gBAAAA,GACC,MAAMvB,EAAO7B,KAAKkC,WAAW,sBAAwBlC,KAAKsD,yBAG1D,OAFAtD,KAAKsC,eAEEtC,KAAK2B,QAAQ,mBAAoBE,EACzC,CASA0B,cAAAA,GACCvD,KAAKsC,eACL,IAAIkB,EAAWxD,KAAKC,KAAKwD,OAAOzD,KAAKG,MAAOpC,EAAKa,eAC7C8E,EAASF,EAASjF,OAEtB,KAAOmF,EAAS,GAAG,CAIlB,GAAI3F,EAAKc,WAAW8E,eAAeH,MACjCzF,EAAKkD,kBAAkBjB,KAAKI,OAC5BJ,KAAKG,MAAQqD,EAASjF,OAASyB,KAAKC,KAAK1B,SAAWR,EAAKsD,iBAAiBrB,KAAKC,KAAKI,WAAWL,KAAKG,MAAQqD,EAASjF,UAGtH,OADAyB,KAAKG,OAASuD,EACPF,EAERA,EAAWA,EAASC,OAAO,IAAKC,EACjC,CACA,OAAO,CACR,CAOAJ,sBAAAA,GACC,IAAIzB,EAAM+B,EAAMC,EAAMC,EAAOC,EAAWC,EAAMC,EAAOC,EAAGC,EAMxD,GADAH,EAAOhE,KAAKoE,eACPJ,EACJ,OAAOA,EAKR,GAHAJ,EAAO5D,KAAKuD,kBAGPK,EACJ,OAAOI,EAgBR,IAXAD,EAAY,CAAEM,MAAOT,EAAMC,KAAM9F,EAAKgD,iBAAiB6C,GAAOU,QAASvG,EAAKe,kBAAkBsC,IAAIwC,IAElGK,EAAQjE,KAAKoE,cAERH,GACJjE,KAAKsB,WAAW,6BAA+BsC,GAGhDE,EAAQ,CAACE,EAAMD,EAAWE,GAGlBL,EAAO5D,KAAKuD,kBAAmB,CAGtC,GAFAM,EAAO9F,EAAKgD,iBAAiB6C,GAEhB,IAATC,EAAY,CACf7D,KAAKG,OAASyD,EAAKrF,OACnB,KACD,CAEAwF,EAAY,CAAEM,MAAOT,EAAMC,OAAMS,QAASvG,EAAKe,kBAAkBsC,IAAIwC,IAErEO,EAAWP,EAGX,MAAMW,EAAcC,GAAQT,EAAUO,SAAWE,EAAKF,QACnDT,EAAOW,EAAKX,KACZA,GAAQW,EAAKX,KAChB,KAAQC,EAAMvF,OAAS,GAAMgG,EAAYT,EAAMA,EAAMvF,OAAS,KAC7D0F,EAAQH,EAAMW,MACdb,EAAOE,EAAMW,MAAMJ,MACnBL,EAAOF,EAAMW,MACb5C,EAAO,CACNgB,KAAM9E,EAAK2G,WACXC,SAAUf,EACVI,OACAC,SAEDH,EAAMT,KAAKxB,GAGZA,EAAO7B,KAAKoE,cAEPvC,GACJ7B,KAAKsB,WAAW,6BAA+B6C,GAGhDL,EAAMT,KAAKU,EAAWlC,EACvB,CAKA,IAHAqC,EAAIJ,EAAMvF,OAAS,EACnBsD,EAAOiC,EAAMI,GAENA,EAAI,GACVrC,EAAO,CACNgB,KAAM9E,EAAK2G,WACXC,SAAUb,EAAMI,EAAI,GAAGG,MACvBL,KAAMF,EAAMI,EAAI,GAChBD,MAAOpC,GAERqC,GAAK,EAGN,OAAOrC,CACR,CAOAuC,WAAAA,GACC,IAAItD,EAAI0C,EAAUE,EAAQ7B,EAI1B,GAFA7B,KAAKsC,eACLT,EAAO7B,KAAKkC,WAAW,gBACnBL,EACH,OAAO7B,KAAK2B,QAAQ,cAAeE,GAKpC,GAFAf,EAAKd,KAAKI,KAENrC,EAAK8C,eAAeC,IAAOA,IAAO/C,EAAK6G,YAE1C,OAAO5E,KAAK6E,uBAGb,GAAI/D,IAAO/C,EAAK+G,aAAehE,IAAO/C,EAAKgH,YAE1ClD,EAAO7B,KAAKgF,2BAER,GAAIlE,IAAO/C,EAAKkH,YACpBpD,EAAO7B,KAAKkF,kBAER,CAIJ,IAHA1B,EAAWxD,KAAKC,KAAKwD,OAAOzD,KAAKG,MAAOpC,EAAKK,cAC7CsF,EAASF,EAASjF,OAEXmF,EAAS,GAAG,CAIlB,GAAI3F,EAAKS,UAAUmF,eAAeH,MAChCzF,EAAKkD,kBAAkBjB,KAAKI,OAC5BJ,KAAKG,MAAQqD,EAASjF,OAASyB,KAAKC,KAAK1B,SAAWR,EAAKsD,iBAAiBrB,KAAKC,KAAKI,WAAWL,KAAKG,MAAQqD,EAASjF,UACpH,CACFyB,KAAKG,OAASuD,EACd,MAAMyB,EAAWnF,KAAKoE,cAItB,OAHKe,GACJnF,KAAKsB,WAAW,4BAEVtB,KAAK2B,QAAQ,cAAe,CAClCkB,KAAM9E,EAAKqH,UACXT,SAAUnB,EACV2B,WACAE,QAAQ,GAEV,CAEA7B,EAAWA,EAASC,OAAO,IAAKC,EACjC,CAEI3F,EAAKkD,kBAAkBH,IAC1Be,EAAO7B,KAAKsF,mBACRvH,EAAKwB,SAASoE,eAAe9B,EAAKD,MACrCC,EAAO,CACNgB,KAAM9E,EAAKwH,QACXlB,MAAOtG,EAAKwB,SAASsC,EAAKD,MAC1B4D,IAAK3D,EAAKD,MAGHC,EAAKD,OAAS7D,EAAK0H,WAC3B5D,EAAO,CAAEgB,KAAM9E,EAAK2H,YAGb5E,IAAO/C,EAAK4H,cACpB9D,EAAO7B,KAAK4F,cAEd,CAEA,OAAK/D,GAILA,EAAO7B,KAAK6F,oBAAoBhE,GACzB7B,KAAK2B,QAAQ,cAAeE,IAJ3B7B,KAAK2B,QAAQ,eAAe,EAKrC,CAUAkE,mBAAAA,CAAoBhE,GACnB7B,KAAKsC,eAEL,IAAIxB,EAAKd,KAAKI,KACd,KAAOU,IAAO/C,EAAK6G,aAAe9D,IAAO/C,EAAKkH,aAAenE,IAAO/C,EAAK4H,aAAe7E,IAAO/C,EAAK+H,aAAa,CAChH,IAAIC,EACJ,GAAIjF,IAAO/C,EAAK+H,YAAa,CAC5B,GAAI9F,KAAKC,KAAKI,WAAWL,KAAKG,MAAQ,KAAOpC,EAAK6G,YACjD,MAEDmB,GAAW,EACX/F,KAAKG,OAAS,EACdH,KAAKsC,eACLxB,EAAKd,KAAKI,IACX,CACAJ,KAAKG,QAEDW,IAAO/C,EAAKkH,cACfpD,EAAO,CACNgB,KAAM9E,EAAKiI,WACXC,UAAU,EACVC,OAAQrE,EACRsE,SAAUnG,KAAKoD,qBAEN+C,UACTnG,KAAKsB,WAAW,eAAiBtB,KAAKd,KAAO,KAE9Cc,KAAKsC,eACLxB,EAAKd,KAAKI,KACNU,IAAO/C,EAAKqI,aACfpG,KAAKsB,WAAW,cAEjBtB,KAAKG,SAEGW,IAAO/C,EAAK4H,YAEpB9D,EAAO,CACNgB,KAAM9E,EAAKsI,SACXC,UAAatG,KAAKuG,gBAAgBxI,EAAKyI,aACvCC,OAAQ5E,IAGDf,IAAO/C,EAAK6G,aAAemB,KAC/BA,GACH/F,KAAKG,QAENH,KAAKsC,eACLT,EAAO,CACNgB,KAAM9E,EAAKiI,WACXC,UAAU,EACVC,OAAQrE,EACRsE,SAAUnG,KAAKsF,qBAIbS,IACHlE,EAAKkE,UAAW,GAGjB/F,KAAKsC,eACLxB,EAAKd,KAAKI,IACX,CAEA,OAAOyB,CACR,CAOAgD,oBAAAA,GACC,IAAiB/D,EAAI4F,EAAjBC,EAAS,GAEb,KAAO5I,EAAK8C,eAAeb,KAAKI,OAC/BuG,GAAU3G,KAAKC,KAAKC,OAAOF,KAAKG,SAGjC,GAAIH,KAAKI,OAASrC,EAAK6G,YAGtB,IAFA+B,GAAU3G,KAAKC,KAAKC,OAAOF,KAAKG,SAEzBpC,EAAK8C,eAAeb,KAAKI,OAC/BuG,GAAU3G,KAAKC,KAAKC,OAAOF,KAAKG,SAMlC,GAFAW,EAAKd,KAAKd,KAEC,MAAP4B,GAAqB,MAAPA,EAAY,CAQ7B,IAPA6F,GAAU3G,KAAKC,KAAKC,OAAOF,KAAKG,SAChCW,EAAKd,KAAKd,KAEC,MAAP4B,GAAqB,MAAPA,IACjB6F,GAAU3G,KAAKC,KAAKC,OAAOF,KAAKG,UAG1BpC,EAAK8C,eAAeb,KAAKI,OAC/BuG,GAAU3G,KAAKC,KAAKC,OAAOF,KAAKG,SAG5BpC,EAAK8C,eAAeb,KAAKC,KAAKI,WAAWL,KAAKG,MAAQ,KAC1DH,KAAKsB,WAAW,sBAAwBqF,EAAS3G,KAAKd,KAAO,IAE/D,CAaA,OAXAwH,EAAS1G,KAAKI,KAGVrC,EAAKkD,kBAAkByF,GAC1B1G,KAAKsB,WAAW,8CACfqF,EAAS3G,KAAKd,KAAO,MAEdwH,IAAW3I,EAAK6G,aAAkC,IAAlB+B,EAAOpI,QAAgBoI,EAAOtG,WAAW,KAAOtC,EAAK6G,cAC7F5E,KAAKsB,WAAW,qBAGV,CACNuB,KAAM9E,EAAKwH,QACXlB,MAAOuC,WAAWD,GAClBnB,IAAKmB,EAEP,CAOA3B,mBAAAA,GACC,IAAI6B,EAAM,GACV,MAAMC,EAAa9G,KAAKG,MAClB4G,EAAQ/G,KAAKC,KAAKC,OAAOF,KAAKG,SACpC,IAAI6G,GAAS,EAEb,KAAOhH,KAAKG,MAAQH,KAAKC,KAAK1B,QAAQ,CACrC,IAAIuC,EAAKd,KAAKC,KAAKC,OAAOF,KAAKG,SAE/B,GAAIW,IAAOiG,EAAO,CACjBC,GAAS,EACT,KACD,CACK,GAAW,OAAPlG,EAIR,OAFAA,EAAKd,KAAKC,KAAKC,OAAOF,KAAKG,SAEnBW,GACP,IAAK,IAAK+F,GAAO,KAAM,MACvB,IAAK,IAAKA,GAAO,KAAM,MACvB,IAAK,IAAKA,GAAO,KAAM,MACvB,IAAK,IAAKA,GAAO,KAAM,MACvB,IAAK,IAAKA,GAAO,KAAM,MACvB,IAAK,IAAKA,GAAO,KAAQ,MACzB,QAAUA,GAAO/F,OAIlB+F,GAAO/F,CAET,CAMA,OAJKkG,GACJhH,KAAKsB,WAAW,yBAA2BuF,EAAM,KAG3C,CACNhE,KAAM9E,EAAKwH,QACXlB,MAAOwC,EACPrB,IAAKxF,KAAKC,KAAKgH,UAAUH,EAAY9G,KAAKG,OAE5C,CASAmF,gBAAAA,GACC,IAAIxE,EAAKd,KAAKI,KAAM8G,EAAQlH,KAAKG,MASjC,IAPIpC,EAAKkD,kBAAkBH,GAC1Bd,KAAKG,QAGLH,KAAKsB,WAAW,cAAgBtB,KAAKd,MAG/Bc,KAAKG,MAAQH,KAAKC,KAAK1B,SAC7BuC,EAAKd,KAAKI,KAENrC,EAAKsD,iBAAiBP,KACzBd,KAAKG,QAMP,MAAO,CACN0C,KAAM9E,EAAKoJ,WACXvF,KAAM5B,KAAKC,KAAKmH,MAAMF,EAAOlH,KAAKG,OAEpC,CAWAoG,eAAAA,CAAgBc,GACf,MAAMC,EAAO,GACb,IAAIN,GAAS,EACTO,EAAkB,EAEtB,KAAOvH,KAAKG,MAAQH,KAAKC,KAAK1B,QAAQ,CACrCyB,KAAKsC,eACL,IAAIW,EAAOjD,KAAKI,KAEhB,GAAI6C,IAASoE,EAAa,CACzBL,GAAS,EACThH,KAAKG,QAEDkH,IAAgBtJ,EAAKyI,aAAee,GAAmBA,GAAmBD,EAAK/I,QAClFyB,KAAKsB,WAAW,oBAAsBJ,OAAOC,aAAakG,IAG3D,KACD,CACK,GAAIpE,IAASlF,EAAKoF,YAItB,GAHAnD,KAAKG,QACLoH,IAEIA,IAAoBD,EAAK/I,OAC5B,GAAI8I,IAAgBtJ,EAAKyI,YACxBxG,KAAKsB,WAAW,2BAEZ,GAAI+F,IAAgBtJ,EAAKqI,YAC7B,IAAK,IAAIoB,EAAMF,EAAK/I,OAAQiJ,EAAMD,EAAiBC,IAClDF,EAAKjE,KAAK,WAKT,GAAIiE,EAAK/I,SAAWgJ,GAAuC,IAApBA,EAE3CvH,KAAKsB,WAAW,sBAEZ,CACJ,MAAMO,EAAO7B,KAAKoD,mBAEbvB,GAAQA,EAAKgB,OAAS9E,EAAK+E,UAC/B9C,KAAKsB,WAAW,kBAGjBgG,EAAKjE,KAAKxB,EACX,CACD,CAMA,OAJKmF,GACJhH,KAAKsB,WAAW,YAAcJ,OAAOC,aAAakG,IAG5CC,CACR,CAWA1B,WAAAA,GACC5F,KAAKG,QACL,IAAIwC,EAAQ3C,KAAK4C,kBAAkB7E,EAAKyI,aACxC,GAAIxG,KAAKI,OAASrC,EAAKyI,YAEtB,OADAxG,KAAKG,QACgB,IAAjBwC,EAAMpE,OACFoE,EAAM,KAEJA,EAAMpE,QAIR,CACNsE,KAAM9E,EAAK0J,aACXC,YAAa/E,GAKf3C,KAAKsB,WAAW,aAElB,CAQA4D,WAAAA,GAGC,OAFAlF,KAAKG,QAEE,CACN0C,KAAM9E,EAAK4J,UACXC,SAAU5H,KAAKuG,gBAAgBxI,EAAKqI,aAEtC,EAID,MAAMtE,EAAQ,IA58Bd,MAmBC/C,GAAAA,CAAI6C,EAAMQ,EAAUyF,GACnB,GAA2B,iBAAhBvB,UAAU,GAEpB,IAAK,IAAI1E,KAAQ0E,UAAU,GAC1BtG,KAAKjB,IAAI6C,EAAM0E,UAAU,GAAG1E,GAAO0E,UAAU,SAI7CwB,MAAMC,QAAQnG,GAAQA,EAAO,CAACA,IAAOoG,SAAQ,SAAUpG,GACvD5B,KAAK4B,GAAQ5B,KAAK4B,IAAS,GAEvBQ,GACHpC,KAAK4B,GAAMiG,EAAQ,UAAY,QAAQzF,EAExC,GAAEpC,KAEL,CAWAiC,GAAAA,CAAIL,EAAMG,GACT/B,KAAK4B,GAAQ5B,KAAK4B,IAAS,GAC3B5B,KAAK4B,GAAMoG,SAAQ,SAAU5F,GAC5BA,EAASC,KAAKN,GAAOA,EAAIC,QAAUD,EAAIC,QAAUD,EAAKA,EACvD,GACD,GA05BDtB,OAAOwH,OAAOlK,EAAM,CACnB+D,QACAoG,QAAS,IAt5BV,MACC5H,WAAAA,CAAY6H,GACXnI,KAAKmI,KAAOA,EACZnI,KAAKoI,WAAa,CAAE,CACrB,CAeAC,QAAAA,GAAqB,IAAA,IAAAC,EAAAhC,UAAA/H,OAAT2J,EAAOJ,IAAAA,MAAAQ,GAAAC,EAAA,EAAAA,EAAAD,EAAAC,IAAPL,EAAOK,GAAAjC,UAAAiC,GAClBL,EAAQF,SAASQ,IAChB,GAAsB,iBAAXA,IAAwBA,EAAO5G,OAAS4G,EAAOC,KACzD,MAAM,IAAIhH,MAAM,8BAEbzB,KAAKoI,WAAWI,EAAO5G,QAI3B4G,EAAOC,KAAKzI,KAAKmI,MACjBnI,KAAKoI,WAAWI,EAAO5G,MAAQ4G,EAAM,GAEvC,GAu3BqBzK,GAMrB+E,SAAiB,WACjB2E,aAAiB,qBACjBN,WAAiB,aACjBnB,WAAiB,mBACjBT,QAAiB,UACjBG,SAAiB,iBACjBW,SAAiB,iBACjBjB,UAAiB,kBACjBV,WAAiB,mBACjBiD,UAAiB,kBAEjBnF,SAAa,EACbC,QAAa,GACbC,QAAa,GACbH,WAAa,GACbqC,YAAa,GACbzB,WAAa,GACb2B,YAAa,GACbC,YAAa,GACbY,YAAa,GACba,YAAa,GACbvB,YAAa,GACbmB,YAAa,GACbN,YAAa,GACb5C,YAAa,GACbwF,WAAa,GAOblK,UAAW,CACV,IAAK,EACL,IAAK,EACL,IAAK,EACL,IAAK,GAMNK,WAAY,CACX,KAAM,EAAG,KAAM,EACf,KAAM,EAAG,IAAK,EAAG,IAAK,EAAG,IAAK,EAC9B,KAAM,EAAG,KAAM,EAAG,MAAO,EAAG,MAAO,EACnC,IAAK,EAAG,IAAK,EAAG,KAAM,EAAG,KAAM,EAC/B,KAAM,EAAG,KAAM,EAAG,MAAO,EACzB,IAAK,EAAG,IAAK,EACb,IAAK,GAAI,IAAK,GAAI,IAAK,GACvB,KAAM,IAIPC,kBAAmB,IAAI6J,IAAI,CAAC,OAG5BxJ,4BAA6B,IAAIwJ,IAAI,CAAC,IAAK,MAK3CpJ,SAAU,CACTqJ,MAAQ,EACRC,OAAS,EACTC,KAAQ,MAITrD,SAAU,SAEX1H,EAAKK,aAAeL,EAAK0B,aAAa1B,EAAKS,WAC3CT,EAAKa,cAAgBb,EAAK0B,aAAa1B,EAAKc,YAG5C,MAAMsJ,EAAOlI,GAAS,IAAIlC,EAAKkC,GAAOM,QAChCwI,EAAgBtI,OAAOuI,oBAAoB,SACjDvI,OAAOuI,oBAAoBjL,GACzBkL,QAAOC,IAASH,EAAcI,SAASD,SAAwBE,IAAfjB,EAAKe,KACrDlB,SAASqB,IACTlB,EAAKkB,GAAKtL,EAAKsL,EAAE,IAEnBlB,EAAKpK,KAAOA,EAIZ,IAAIuL,EAAU,CACb1H,KAAM,UAEN6G,IAAAA,CAAKN,GAEJA,EAAKrG,MAAM/C,IAAI,oBAAoB,SAAuBgD,GACzD,GAAIA,EAAIF,MAAQ7B,KAAKI,OAAS+H,EAAKrC,YAAa,CAC/C9F,KAAKG,QACL,MAAMoJ,EAAOxH,EAAIF,KACX2H,EAAaxJ,KAAKoD,mBAQxB,GANKoG,GACJxJ,KAAKsB,WAAW,uBAGjBtB,KAAKsC,eAEDtC,KAAKI,OAAS+H,EAAKO,WAAY,CAClC1I,KAAKG,QACL,MAAMsJ,EAAYzJ,KAAKoD,mBAcvB,GAZKqG,GACJzJ,KAAKsB,WAAW,uBAEjBS,EAAIF,KAAO,CACVgB,KA3BkB,wBA4BlB0G,OACAC,aACAC,aAKGF,EAAK5E,UAAYwD,EAAKtJ,WAAW0K,EAAK5E,WAAa,GAAK,CAC3D,IAAI+E,EAAUH,EACd,KAAOG,EAAQzF,MAAMU,UAAYwD,EAAKtJ,WAAW6K,EAAQzF,MAAMU,WAAa,IAC3E+E,EAAUA,EAAQzF,MAEnBlC,EAAIF,KAAK0H,KAAOG,EAAQzF,MACxByF,EAAQzF,MAAQlC,EAAIF,KACpBE,EAAIF,KAAO0H,CACZ,CACD,MAECvJ,KAAKsB,WAAW,aAElB,CACD,GACD,GAKD6G,EAAKD,QAAQG,SAASiB,GChmCtB,IAAInJ,EAAQ,CACXyB,KAAM,QAEN6G,IAAAA,CAAKN,GAEJA,EAAKrG,MAAM/C,IAAI,gBAAgB,SAA4BgD,GAC1D,GATiB,KASb/B,KAAKI,KAAsB,CAC9B,MAAMuJ,IAAiB3J,KAAKG,MAE5B,IAAIyJ,GAAY,EAChB,KAAO5J,KAAKG,MAAQH,KAAKC,KAAK1B,QAAQ,CACrC,GAde,KAcXyB,KAAKI,OAAyBwJ,EAAW,CAC5C,MAAMC,EAAU7J,KAAKC,KAAKmH,MAAMuC,EAAc3J,KAAKG,OAEnD,IAaIkE,EAbAyF,EAAQ,GACZ,OAAS9J,KAAKG,MAAQH,KAAKC,KAAK1B,QAAQ,CACvC,MAAM6B,EAAOJ,KAAKI,KAClB,KAAKA,GAAQ,IAAMA,GAAQ,KACtBA,GAAQ,IAAMA,GAAQ,IACtBA,GAAQ,IAAMA,GAAQ,IAI1B,MAHA0J,GAAS9J,KAAKd,IAKhB,CAGA,IACCmF,EAAQ,IAAI0F,OAAOF,EAASC,EAC5B,CACD,MAAOE,GACNhK,KAAKsB,WAAW0I,EAAEzI,QACnB,CAUA,OARAQ,EAAIF,KAAO,CACVgB,KAAMsF,EAAK5C,QACXlB,QACAmB,IAAKxF,KAAKC,KAAKmH,MAAMuC,EAAe,EAAG3J,KAAKG,QAI7C4B,EAAIF,KAAO7B,KAAK6F,oBAAoB9D,EAAIF,MACjCE,EAAIF,IACZ,CACI7B,KAAKI,OAAS+H,EAAKlD,YACtB2E,GAAY,EAEJA,GAAa5J,KAAKI,OAAS+H,EAAK/B,cACxCwD,GAAY,GAEb5J,KAAKG,OArDU,KAqDDH,KAAKI,KAAuB,EAAI,CAC/C,CACAJ,KAAKsB,WAAW,iBACjB,CACD,GACD,GC3DD,MAGMkH,EAAS,CACd5G,KAAM,aAENqI,oBAAqB,IAAItB,IAAI,CAC5B,IACA,KACA,MACA,KACA,KACA,KACA,KACA,MACA,MACA,OACA,KACA,KACA,KACA,MACA,MACA,QAEDuB,gBAAiB,CAxBA,GACC,IAwBlBC,qBAAsB,GAEtB1B,IAAAA,CAAKN,GACJ,MAAMiC,EAAkB,CAACjC,EAAKhB,WAAYgB,EAAKnC,YA8C/C,SAASqE,EAA4BxI,GAChC2G,EAAOyB,oBAAoB7I,IAAIS,EAAK8C,WACvC9C,EAAKgB,KAAO,uBACZwH,EAA4BxI,EAAKmC,MACjCqG,EAA4BxI,EAAKoC,QAExBpC,EAAK8C,UACdlE,OAAO6J,OAAOzI,GAAMmG,SAASuC,IACxBA,GAAsB,iBAARA,GACjBF,EAA4BE,EAC7B,GAGH,CA1DA/B,EAAOyB,oBAAoBjC,SAAQwC,GAAMrC,EAAK1J,YAAY+L,EAAIhC,EAAO2B,sBAAsB,KAE3FhC,EAAKrG,MAAM/C,IAAI,gBAAgB,SAA4BgD,GAC1D,MAAM3B,EAAOJ,KAAKI,KACdoI,EAAO0B,gBAAgBO,MAAKC,GAAKA,IAAMtK,GAAQsK,IAAM1K,KAAKC,KAAKI,WAAWL,KAAKG,MAAQ,OAC1FH,KAAKG,OAAS,EACd4B,EAAIF,KAAO,CACVgB,KAAM,mBACN8B,SArCa,KAqCHvE,EAAqB,KAAO,KACtC+E,SAAUnF,KAAK6F,oBAAoB7F,KAAKsF,oBACxCD,QAAQ,GAEJtD,EAAIF,KAAKsD,UAAaiF,EAAgBjB,SAASpH,EAAIF,KAAKsD,SAAStC,OACrE7C,KAAKsB,WAAW,cAAcS,EAAIF,KAAK8C,YAG1C,IAEAwD,EAAKrG,MAAM/C,IAAI,eAAe,SAA6BgD,GAC1D,GAAIA,EAAIF,KAAM,CACb,MAAMzB,EAAOJ,KAAKI,KACdoI,EAAO0B,gBAAgBO,MAAKC,GAAKA,IAAMtK,GAAQsK,IAAM1K,KAAKC,KAAKI,WAAWL,KAAKG,MAAQ,OACrFiK,EAAgBjB,SAASpH,EAAIF,KAAKgB,OACtC7C,KAAKsB,WAAW,cAAcS,EAAIF,KAAK8C,YAExC3E,KAAKG,OAAS,EACd4B,EAAIF,KAAO,CACVgB,KAAM,mBACN8B,SAzDY,KAyDFvE,EAAqB,KAAO,KACtC+E,SAAUpD,EAAIF,KACdwD,QAAQ,GAGX,CACD,IAEA8C,EAAKrG,MAAM/C,IAAI,oBAAoB,SAA0BgD,GACxDA,EAAIF,MAIPwI,EAA4BtI,EAAIF,KAElC,GAgBD,GClFDsG,EAAKD,QAAQG,SAASsC,EAAWC,GACjCzC,EAAKjK,WAAW,UAChBiK,EAAKjK,WAAW,QAChBiK,EAAK/I,WAAW,OAAQ,MACxB+I,EAAK/I,WAAW,iBAAagK,GAE7B,MAAMyB,EAA2B,IAAIlC,IAAI,CACrC,cACA,YACA,mBACA,mBACA,mBACA,qBAGEmC,EAAW,CAKbC,OAAAA,CAASC,EAAKC,GACV,OAAQD,EAAInI,MACZ,IAAK,mBACL,IAAK,oBACD,OAAOiI,EAASI,qBAAqBF,EAAKC,GAC9C,IAAK,WACD,OAAOH,EAASK,aAAaH,EAAKC,GACtC,IAAK,wBACD,OAAOH,EAASM,0BAA0BJ,EAAKC,GACnD,IAAK,aACD,OAAOH,EAASO,eAAeL,EAAKC,GACxC,IAAK,UACD,OAAOH,EAASQ,YAAYN,EAAKC,GACrC,IAAK,mBACD,OAAOH,EAASS,qBAAqBP,EAAKC,GAC9C,IAAK,kBACD,OAAOH,EAASU,oBAAoBR,EAAKC,GAC7C,IAAK,kBACD,OAAOH,EAASW,oBAAoBT,EAAKC,GAC7C,IAAK,iBACD,OAAOH,EAASY,mBAAmBV,EAAKC,GAC5C,IAAK,uBACD,OAAOH,EAASa,yBAAyBX,EAAKC,GAClD,QACI,MAAMW,YAAY,wBAAyBZ,GAElD,EACDE,qBAAoBA,CAAEF,EAAKC,KACR,CACX,KAAMY,CAACC,EAAGC,IAAMD,GAAKC,IACrB,KAAMC,CAACF,EAAGC,IAAMD,GAAKC,IACrB,IAAKE,CAACH,EAAGC,IAAMD,EAAIC,IACnB,IAAKG,CAACJ,EAAGC,IAAMD,EAAIC,IACnB,IAAKI,CAACL,EAAGC,IAAMD,EAAIC,IAEnB,KAAMK,CAACN,EAAGC,IAAMD,GAAKC,IAErB,KAAMM,CAACP,EAAGC,IAAMD,GAAKC,IACrB,MAAOO,CAACR,EAAGC,IAAMD,IAAMC,IACvB,MAAOQ,CAACT,EAAGC,IAAMD,IAAMC,IACvB,IAAKS,CAACV,EAAGC,IAAMD,EAAIC,IACnB,IAAKU,CAACX,EAAGC,IAAMD,EAAIC,IACnB,KAAMW,CAACZ,EAAGC,IAAMD,GAAKC,IACrB,KAAMY,CAACb,EAAGC,IAAMD,GAAKC,IACrB,KAAMa,CAACd,EAAGC,IAAMD,GAAKC,IACrB,KAAMc,CAACf,EAAGC,IAAMD,GAAKC,IACrB,MAAOe,CAAChB,EAAGC,IAAMD,IAAMC,IACvB,IAAKgB,CAACjB,EAAGC,IAAMD,EAAIC,IACnB,IAAKiB,CAAClB,EAAGC,IAAMD,EAAIC,IACnB,IAAKkB,CAACnB,EAAGC,IAAMD,EAAIC,IACnB,IAAKmB,CAACpB,EAAGC,IAAMD,EAAIC,IACnB,IAAKoB,CAACrB,EAAGC,IAAMD,EAAIC,KACrBf,EAAIrG,UACFmG,EAASC,QAAQC,EAAIhH,KAAMiH,IAC3B,IAAMH,EAASC,QAAQC,EAAI/G,MAAOgH,MAI1CE,YAAAA,CAAcH,EAAKC,GACf,IAAImC,EACJ,IAAK,IAAIlJ,EAAI,EAAGA,EAAI8G,EAAIjI,KAAKxE,OAAQ2F,IAAK,CAEb,eAArB8G,EAAIjI,KAAKmB,GAAGrB,MACZ,CAAC,MAAO,MAAO,SAASsG,SAAS6B,EAAIjI,KAAKmB,GAAGtC,OAC7CoJ,EAAIjI,KAAKmB,EAAI,IACY,yBAAzB8G,EAAIjI,KAAKmB,EAAI,GAAGrB,OAMhBqB,GAAK,GAET,MAAMjE,EAAO+K,EAAIjI,KAAKmB,GACtBkJ,EAAOtC,EAASC,QAAQ9K,EAAMgL,EAClC,CACA,OAAOmC,CACV,EACDhC,0BAAyBA,CAAEJ,EAAKC,IACxBH,EAASC,QAAQC,EAAIzB,KAAM0B,GACpBH,EAASC,QAAQC,EAAIxB,WAAYyB,GAErCH,EAASC,QAAQC,EAAIvB,UAAWwB,GAE3CI,cAAAA,CAAgBL,EAAKC,GACjB,GAAIxK,OAAO4M,OAAOpC,EAAMD,EAAIpJ,MACxB,OAAOqJ,EAAKD,EAAIpJ,MAEpB,MAAM0L,eAAe,GAAGtC,EAAIpJ,sBAC/B,EACD0J,YAAaN,GACFA,EAAI3G,MAEfkH,oBAAAA,CAAsBP,EAAKC,GACvB,MAAM/B,EAAOhI,OAIT8J,EAAI/E,SACE6E,EAASC,QAAQC,EAAI7E,UACrB6E,EAAI7E,SAASvE,MAEjBpB,EAAMsK,EAASC,QAAQC,EAAI9E,OAAQ+E,GACzC,GAAIzK,QACA,MAAM+M,UACF,6BAA6B/M,eAAiB0I,OAGtD,IAAKzI,OAAO4M,OAAO7M,EAAK0I,IAAS2B,EAAyBzJ,IAAI8H,GAC1D,MAAMqE,UACF,6BAA6B/M,eAAiB0I,OAGtD,MAAMsE,EAAShN,EAAI0I,GACnB,MAAsB,mBAAXsE,EACAA,EAAOC,KAAKjN,GAEhBgN,CACV,EACDhC,oBAAmBA,CAAER,EAAKC,KACP,CACX,IAAMa,IAAOhB,EAASC,QAAQe,EAAGb,GACjC,IAAMa,IAAOhB,EAASC,QAAQe,EAAGb,GACjC,IAAMa,IAAOhB,EAASC,QAAQe,EAAGb,GAEjC,IAAMa,IAAOhB,EAASC,QAAQe,EAAGb,GACjCyC,OAAS5B,UAAahB,EAASC,QAAQe,EAAGb,GAE1C0C,KAAO7B,IAAWhB,EAASC,QAAQe,EAAGb,EACzC,GAACD,EAAIrG,UAAUqG,EAAI7F,WAGxBsG,oBAAmBA,CAAET,EAAKC,IACfD,EAAIpD,SAASjH,KAAKiN,GAAO9C,EAASC,QAAQ6C,EAAI3C,KAEzDS,kBAAAA,CAAoBV,EAAKC,GACrB,MAAM3D,EAAO0D,EAAI1E,UAAU3F,KAAK6G,GAAQsD,EAASC,QAAQvD,EAAKyD,KACxD4C,EAAO/C,EAASC,QAAQC,EAAIvE,OAAQwE,GAE1C,GAAI4C,IAASC,SAET,MAAM,IAAIrM,MAAM,oCAGpB,OAAOoM,KAAQvG,EAClB,EACDqE,wBAAAA,CAA0BX,EAAKC,GAC3B,GAAsB,eAAlBD,EAAIhH,KAAKnB,KACT,MAAM+I,YAAY,wCAEtB,MAAMmC,EAAK/C,EAAIhH,KAAKpC,KACdyC,EAAQyG,EAASC,QAAQC,EAAI/G,MAAOgH,GAE1C,OADAA,EAAK8C,GAAM1J,EACJ4G,EAAK8C,EAChB,GC9JJ,SAAS1K,EAAM2K,EAAKC,GAGhB,OAFAD,EAAMA,EAAI5G,SACN/D,KAAK4K,GACFD,CACX,CAOA,SAASE,EAASD,EAAMD,GAGpB,OAFAA,EAAMA,EAAI5G,SACN8G,QAAQD,GACLD,CACX,CAMA,MAAMG,UAAiB1M,MAInBnB,WAAAA,CAAa+D,GACT+J,MACI,8FAGJpO,KAAKqO,UAAW,EAChBrO,KAAKqE,MAAQA,EACbrE,KAAK4B,KAAO,UAChB,EAiFJ,SAAS0M,EAAUC,EAAMtO,EAAMO,EAAK4B,EAAUoM,GAE1C,KAAMxO,gBAAgBsO,GAClB,IACI,OAAO,IAAIA,EAASC,EAAMtO,EAAMO,EAAK4B,EAAUoM,EAClD,CAAC,MAAOxE,GACL,IAAKA,EAAEqE,SACH,MAAMrE,EAEV,OAAOA,EAAE3F,KACb,CAGgB,iBAATkK,IACPC,EAAoBpM,EACpBA,EAAW5B,EACXA,EAAMP,EACNA,EAAOsO,EACPA,EAAO,MAEX,MAAME,EAASF,GAAwB,iBAATA,EAwB9B,GAvBAA,EAAOA,GAAQ,CAAE,EACjBvO,KAAK0O,KAAOH,EAAKG,MAAQlO,EACzBR,KAAK2O,KAAOJ,EAAKI,MAAQ1O,EACzBD,KAAK4O,WAAaL,EAAKK,YAAc,QACrC5O,KAAK6O,QAAUN,EAAKM,UAAW,EAC/B7O,KAAK8O,MAAOrO,OAAO4M,OAAOkB,EAAM,SAAUA,EAAKO,KAC/C9O,KAAK+O,QAAUR,EAAKQ,SAAW,CAAE,EACjC/O,KAAKgP,UAAqB5F,IAAdmF,EAAKS,KAAqB,OAAST,EAAKS,KACpDhP,KAAKiP,sBAAqD,IAA1BV,EAAKU,kBAE/BV,EAAKU,iBACXjP,KAAKkP,OAASX,EAAKW,QAAU,KAC7BlP,KAAKmP,eAAiBZ,EAAKY,gBAAkB,KAC7CnP,KAAKoC,SAAWmM,EAAKnM,UAAYA,GAAY,KAC7CpC,KAAKwO,kBAAoBD,EAAKC,mBAC1BA,GACA,WACI,MAAM,IAAIjB,UACN,mFAGP,GAEkB,IAAnBgB,EAAKa,UAAqB,CAC1B,MAAM9H,EAAO,CACTqH,KAAOF,EAASF,EAAKI,KAAO1O,GAE3BwO,EAEM,SAAUF,IACjBjH,EAAKoH,KAAOH,EAAKG,MAFjBpH,EAAKoH,KAAOlO,EAIhB,MAAM6O,EAAMrP,KAAKsP,SAAShI,GAC1B,IAAK+H,GAAsB,iBAARA,EACf,MAAM,IAAIlB,EAASkB,GAEvB,OAAOA,CACX,CACJ,CAGAf,EAASiB,UAAUD,SAAW,SAC1BrP,EAAMyO,EAAMtM,EAAUoM,GAEtB,IAAIgB,EAAaxP,KAAKkP,OAClBO,EAAqBzP,KAAKmP,gBAC1BN,QAACA,EAAOC,KAAEA,GAAQ9O,KAUtB,GARAA,KAAK0P,eAAiB1P,KAAK4O,WAC3B5O,KAAK2P,SAAW3P,KAAKgP,KACrBhP,KAAK4P,YAAc5P,KAAK+O,QACxB3M,EAAWA,GAAYpC,KAAKoC,SAC5BpC,KAAK6P,sBAAwBrB,GAAqBxO,KAAKwO,kBAEvDE,EAAOA,GAAQ1O,KAAK0O,MACpBzO,EAAOA,GAAQD,KAAK2O,OACQ,iBAAT1O,IAAsB6H,MAAMC,QAAQ9H,GAAO,CAC1D,IAAKA,EAAK0O,MAAsB,KAAd1O,EAAK0O,KACnB,MAAM,IAAIpB,UACN,+FAIR,IAAM9M,OAAO4M,OAAOpN,EAAM,QACtB,MAAM,IAAIsN,UACN,iGAINmB,QAAQzO,GACV4O,EAAUpO,OAAO4M,OAAOpN,EAAM,WAAaA,EAAK4O,QAAUA,EAC1D7O,KAAK0P,eAAiBjP,OAAO4M,OAAOpN,EAAM,cACpCA,EAAK2O,WACL5O,KAAK0P,eACX1P,KAAK4P,YAAcnP,OAAO4M,OAAOpN,EAAM,WACjCA,EAAK8O,QACL/O,KAAK4P,YACXd,EAAOrO,OAAO4M,OAAOpN,EAAM,QAAUA,EAAK6O,KAAOA,EACjD9O,KAAK2P,SAAWlP,OAAO4M,OAAOpN,EAAM,QAC9BA,EAAK+O,KACLhP,KAAK2P,SACXvN,EAAW3B,OAAO4M,OAAOpN,EAAM,YAAcA,EAAKmC,SAAWA,EAC7DpC,KAAK6P,sBAAwBpP,OAAO4M,OAAOpN,EAAM,qBAC3CA,EAAKuO,kBACLxO,KAAK6P,sBACXL,EAAa/O,OAAO4M,OAAOpN,EAAM,UAAYA,EAAKiP,OAASM,EAC3DC,EAAqBhP,OAAO4M,OAAOpN,EAAM,kBACnCA,EAAKkP,eACLM,EACNxP,EAAOA,EAAK0O,IAChB,CAOA,GANAa,EAAaA,GAAc,KAC3BC,EAAqBA,GAAsB,KAEvC3H,MAAMC,QAAQ9H,KACdA,EAAOqO,EAASwB,aAAa7P,KAE3BA,GAAiB,KAATA,IAAiByO,EAC3B,OAGJ,MAAMqB,EAAWzB,EAAS0B,YAAY/P,GAClB,MAAhB8P,EAAS,IAAcA,EAASxR,OAAS,GACzCwR,EAASE,QAEbjQ,KAAKkQ,mBAAqB,KAC1B,MAAM1C,EAASxN,KACVmQ,OACGJ,EAAUrB,EAAM,CAAC,KAAMc,EAAYC,EAAoBrN,GAE1D6G,QAAO,SAAUmH,GACd,OAAOA,IAAOA,EAAGC,gBACrB,IAEJ,OAAK7C,EAAOjP,OAGPuQ,GAA0B,IAAlBtB,EAAOjP,QAAiBiP,EAAO,GAAG8C,WAGxC9C,EAAO+C,QAAO,CAACC,EAAMJ,KACxB,MAAMK,EAAYzQ,KAAK0Q,oBAAoBN,GAM3C,OALIvB,GAAW/G,MAAMC,QAAQ0I,GACzBD,EAAOA,EAAKG,OAAOF,GAEnBD,EAAKnN,KAAKoN,GAEPD,CAAI,GACZ,IAVQxQ,KAAK0Q,oBAAoBlD,EAAO,IAHhCsB,EAAO,QAAK1F,CAc3B,EAIAkF,EAASiB,UAAUmB,oBAAsB,SAAUN,GAC/C,MAAMxB,EAAa5O,KAAK0P,eACxB,OAAQd,GACR,IAAK,MAAO,CACR,MAAMD,EAAO7G,MAAMC,QAAQqI,EAAGzB,MACxByB,EAAGzB,KACHL,EAAS0B,YAAYI,EAAGzB,MAK9B,OAJAyB,EAAGQ,QAAUtC,EAASuC,UAAUlC,GAChCyB,EAAGzB,KAA0B,iBAAZyB,EAAGzB,KACdyB,EAAGzB,KACHL,EAASwB,aAAaM,EAAGzB,MACxByB,CACX,CAAE,IAAK,QAAS,IAAK,SAAU,IAAK,iBAChC,OAAOA,EAAGxB,GACd,IAAK,OACD,OAAON,EAASwB,aAAaM,EAAGxB,IACpC,IAAK,UACD,OAAON,EAASuC,UAAUT,EAAGzB,MACjC,QACI,MAAM,IAAIpB,UAAU,uBAE5B,EAEAe,EAASiB,UAAUuB,gBAAkB,SAAUC,EAAY3O,EAAUS,GACjE,GAAIT,EAAU,CACV,MAAM4O,EAAkBhR,KAAK0Q,oBAAoBK,GACjDA,EAAWpC,KAAkC,iBAApBoC,EAAWpC,KAC9BoC,EAAWpC,KACXL,EAASwB,aAAaiB,EAAWpC,MAEvCvM,EAAS4O,EAAiBnO,EAAMkO,EACpC,CACJ,EAcAzC,EAASiB,UAAUY,OAAS,SACxBlQ,EAAMsK,EAAKoE,EAAMO,EAAQ+B,EAAgB7O,EAAUkO,EACnDY,GAIA,IAAIC,EACJ,IAAKlR,EAAK1B,OASN,OARA4S,EAAS,CACLxC,OACAtK,MAAOkG,EACP2E,SACAC,eAAgB8B,EAChBX,cAEJtQ,KAAK8Q,gBAAgBK,EAAQ/O,EAAU,SAChC+O,EAGX,MAAMC,EAAMnR,EAAK,GAAIoR,EAAIpR,EAAKmH,MAAM,GAI9BiI,EAAM,GAMZ,SAASiC,EAAQC,GACTzJ,MAAMC,QAAQwJ,GAIdA,EAAMvJ,SAASwJ,IACXnC,EAAIhM,KAAKmO,EAAE,IAGfnC,EAAIhM,KAAKkO,EAEjB,CACA,IAAoB,iBAARH,GAAoBF,IAAoB3G,GAChD9J,OAAO4M,OAAO9C,EAAK6G,GAEnBE,EAAOtR,KAAKmQ,OAAOkB,EAAG9G,EAAI6G,GAAM/N,EAAKsL,EAAMyC,GAAM7G,EAAK6G,EAAKhP,EACvDkO,SAED,GAAY,MAARc,EACPpR,KAAKyR,MAAMlH,GAAMlB,IACbiI,EAAOtR,KAAKmQ,OACRkB,EAAG9G,EAAIlB,GAAIhG,EAAKsL,EAAMtF,GAAIkB,EAAKlB,EAAGjH,GAAU,GAAM,GACpD,SAEH,GAAY,OAARgP,EAEPE,EACItR,KAAKmQ,OAAOkB,EAAG9G,EAAKoE,EAAMO,EAAQ+B,EAAgB7O,EAC9CkO,IAERtQ,KAAKyR,MAAMlH,GAAMlB,IAGS,iBAAXkB,EAAIlB,IAGXiI,EAAOtR,KAAKmQ,OACRlQ,EAAKmH,QAASmD,EAAIlB,GAAIhG,EAAKsL,EAAMtF,GAAIkB,EAAKlB,EAAGjH,GAAU,GAE/D,QAID,IAAY,MAARgP,EAGP,OADApR,KAAKkQ,oBAAqB,EACnB,CACHvB,KAAMA,EAAKvH,MAAM,GAAI,GACrBnH,KAAMoR,EACNhB,kBAAkB,GAEnB,GAAY,MAARe,EAQP,OAPAD,EAAS,CACLxC,KAAMtL,EAAKsL,EAAMyC,GACjB/M,MAAO4M,EACP/B,SACAC,eAAgB,MAEpBnP,KAAK8Q,gBAAgBK,EAAQ/O,EAAU,YAChC+O,EACJ,GAAY,MAARC,EACPE,EAAOtR,KAAKmQ,OAAOkB,EAAG9G,EAAKoE,EAAM,KAAM,KAAMvM,EAAUkO,SACpD,GAAK,4BAA6B/G,KAAK6H,GAC1CE,EACItR,KAAK0R,OAAON,EAAKC,EAAG9G,EAAKoE,EAAMO,EAAQ+B,EAAgB7O,SAExD,GAA0B,IAAtBgP,EAAIO,QAAQ,MAAa,CAChC,IAAsB,IAAlB3R,KAAK2P,SACL,MAAM,IAAIlO,MAAM,oDAEpB,MAAMmQ,EAAUR,EAAIS,QAAQ,iBAAkB,MAExCC,EAAU,6CAA8CC,KAAKH,GAC/DE,EAGA9R,KAAKyR,MAAMlH,GAAMlB,IACb,MAAM2I,EAAQ,CAACF,EAAO,IAChBG,EAASH,EAAO,GAChBvH,EAAIlB,GAAGyI,EAAO,IACdvH,EAAIlB,GACYrJ,KAAKmQ,OAAO6B,EAAOC,EAAQtD,EAC7CO,EAAQ+B,EAAgB7O,GAAU,GACpB7D,OAAS,GACvB+S,EAAOtR,KAAKmQ,OAAOkB,EAAG9G,EAAIlB,GAAIhG,EAAKsL,EAAMtF,GAAIkB,EACzClB,EAAGjH,GAAU,GACrB,IAGJpC,KAAKyR,MAAMlH,GAAMlB,IACTrJ,KAAKkS,MAAMN,EAASrH,EAAIlB,GAAIA,EAAGsF,EAAMO,EACrC+B,IACAK,EAAOtR,KAAKmQ,OAAOkB,EAAG9G,EAAIlB,GAAIhG,EAAKsL,EAAMtF,GAAIkB,EAAKlB,EAC9CjH,GAAU,GAClB,GAGX,MAAM,GAAe,MAAXgP,EAAI,GAAY,CACvB,IAAsB,IAAlBpR,KAAK2P,SACL,MAAM,IAAIlO,MAAM,mDAKpB6P,EAAOtR,KAAKmQ,OAAOjC,EACflO,KAAKkS,MACDd,EAAK7G,EAAKoE,EAAKwD,IAAI,GACnBxD,EAAKvH,MAAM,GAAI,GAAI8H,EAAQ+B,GAE/BI,GACD9G,EAAKoE,EAAMO,EAAQ+B,EAAgB7O,EAAUkO,GACnD,MAAM,GAAe,MAAXc,EAAI,GAAY,CACvB,IAAIgB,GAAU,EACd,MAAMC,EAAYjB,EAAIhK,MAAM,GAAI,GAChC,OAAQiL,GACR,IAAK,SACI9H,GAAS,CAAC,SAAU,YAAYpB,gBAAgBoB,KACjD6H,GAAU,GAEd,MACJ,IAAK,UAAW,IAAK,SAAU,IAAK,YAAa,IAAK,kBACvC7H,IAAQ8H,IACfD,GAAU,GAEd,MACJ,IAAK,WACGE,OAAOC,SAAShI,IAAUA,EAAM,IAChC6H,GAAU,GAEd,MACJ,IAAK,SACGE,OAAOC,SAAShI,KAChB6H,GAAU,GAEd,MACJ,IAAK,YACkB,iBAAR7H,GAAqB+H,OAAOC,SAAShI,KAC5C6H,GAAU,GAEd,MACJ,IAAK,SACG7H,UAAcA,IAAQ8H,IACtBD,GAAU,GAEd,MACJ,IAAK,QACGtK,MAAMC,QAAQwC,KACd6H,GAAU,GAEd,MACJ,IAAK,QACDA,EAAUpS,KAAK6P,sBACXtF,EAAKoE,EAAMO,EAAQ+B,GAEvB,MACJ,IAAK,OACW,OAAR1G,IACA6H,GAAU,GAEd,MAEJ,QACI,MAAM,IAAI7E,UAAU,sBAAwB8E,GAEhD,GAAID,EAGA,OAFAjB,EAAS,CAACxC,OAAMtK,MAAOkG,EAAK2E,SAAQC,eAAgB8B,GACpDjR,KAAK8Q,gBAAgBK,EAAQ/O,EAAU,SAChC+O,CAGd,MAAM,GAAe,MAAXC,EAAI,IAAc7G,GAAO9J,OAAO4M,OAAO9C,EAAK6G,EAAIhK,MAAM,IAAK,CAClE,MAAMoL,EAAUpB,EAAIhK,MAAM,GAC1BkK,EAAOtR,KAAKmQ,OACRkB,EAAG9G,EAAIiI,GAAUnP,EAAKsL,EAAM6D,GAAUjI,EAAKiI,EAASpQ,EACpDkO,GAAY,GAEnB,MAAM,GAAIc,EAAIjI,SAAS,KAAM,CAC1B,MAAMsJ,EAAQrB,EAAIsB,MAAM,KACxB,IAAK,MAAMC,KAAQF,EACfnB,EAAOtR,KAAKmQ,OACRjC,EAAQyE,EAAMtB,GAAI9G,EAAKoE,EAAMO,EAAQ+B,EAAgB7O,GACrD,GAIZ,MACK8O,GAAmB3G,GAAO9J,OAAO4M,OAAO9C,EAAK6G,IAE9CE,EACItR,KAAKmQ,OAAOkB,EAAG9G,EAAI6G,GAAM/N,EAAKsL,EAAMyC,GAAM7G,EAAK6G,EAAKhP,EAChDkO,GAAY,GAExB,CAKA,GAAItQ,KAAKkQ,mBACL,IAAK,IAAIsB,EAAI,EAAGA,EAAInC,EAAI9Q,OAAQiT,IAAK,CACjC,MAAMoB,EAAOvD,EAAImC,GACjB,GAAIoB,GAAQA,EAAKvC,iBAAkB,CAC/B,MAAMwC,EAAM7S,KAAKmQ,OACbyC,EAAK3S,KAAMsK,EAAKqI,EAAKjE,KAAMO,EAAQ+B,EAAgB7O,EACnDkO,GAEJ,GAAIxI,MAAMC,QAAQ8K,GAAM,CACpBxD,EAAImC,GAAKqB,EAAI,GACb,MAAMC,EAAKD,EAAItU,OACf,IAAK,IAAIwU,EAAK,EAAGA,EAAKD,EAAIC,IAGtBvB,IACAnC,EAAI2D,OAAOxB,EAAG,EAAGqB,EAAIE,GAE7B,MACI1D,EAAImC,GAAKqB,CAEjB,CACJ,CAEJ,OAAOxD,CACX,EAEAf,EAASiB,UAAUkC,MAAQ,SAAUlH,EAAK0I,GACtC,GAAInL,MAAMC,QAAQwC,GAAM,CACpB,MAAM2I,EAAI3I,EAAIhM,OACd,IAAK,IAAI2F,EAAI,EAAGA,EAAIgP,EAAGhP,IACnB+O,EAAE/O,EAET,MAAUqG,GAAsB,iBAARA,GACrB9J,OAAOC,KAAK6J,GAAKvC,SAASqB,IACtB4J,EAAE5J,EAAE,GAGhB,EAEAiF,EAASiB,UAAUmC,OAAS,SACxBN,EAAKnR,EAAMsK,EAAKoE,EAAMO,EAAQ+B,EAAgB7O,GAE9C,IAAK0F,MAAMC,QAAQwC,GACf,OAEJ,MAAM4I,EAAM5I,EAAIhM,OAAQkU,EAAQrB,EAAIsB,MAAM,KACtCU,EAAQX,EAAM,IAAMH,OAAOe,SAASZ,EAAM,KAAQ,EACtD,IAAIvL,EAASuL,EAAM,IAAMH,OAAOe,SAASZ,EAAM,KAAQ,EACnDa,EAAOb,EAAM,IAAMH,OAAOe,SAASZ,EAAM,KAAQU,EACrDjM,EAASA,EAAQ,EAAK7I,KAAKC,IAAI,EAAG4I,EAAQiM,GAAO9U,KAAKkV,IAAIJ,EAAKjM,GAC/DoM,EAAOA,EAAM,EAAKjV,KAAKC,IAAI,EAAGgV,EAAMH,GAAO9U,KAAKkV,IAAIJ,EAAKG,GACzD,MAAMjE,EAAM,GACZ,IAAK,IAAInL,EAAIgD,EAAOhD,EAAIoP,EAAKpP,GAAKkP,EAAM,CACxBpT,KAAKmQ,OACbjC,EAAQhK,EAAGjE,GAAOsK,EAAKoE,EAAMO,EAAQ+B,EAAgB7O,GAAU,GAO/D4F,SAASwJ,IACTnC,EAAIhM,KAAKmO,EAAE,GAEnB,CACA,OAAOnC,CACX,EAEAf,EAASiB,UAAU2C,MAAQ,SACvB9R,EAAMoT,EAAIC,EAAQ9E,EAAMO,EAAQ+B,GAEhCjR,KAAK4P,YAAY8D,kBAAoBzC,EACrCjR,KAAK4P,YAAY+D,UAAYzE,EAC7BlP,KAAK4P,YAAYgE,YAAcH,EAC/BzT,KAAK4P,YAAYiE,QAAU7T,KAAK0O,KAChC1O,KAAK4P,YAAYkE,KAAON,EAExB,MAAMO,EAAe3T,EAAK+I,SAAS,SAC/B4K,IACA/T,KAAK4P,YAAYoE,QAAU1F,EAASwB,aAAanB,EAAKgC,OAAO,CAAC8C,MAGlE,MAAMQ,EAAiBjU,KAAK2P,SAAW,UAAYvP,EACnD,IAAKkO,EAAS4F,MAAMD,GAAiB,CACjC,IAAIE,EAAS/T,EACRgU,WAAW,kBAAmB,qBAC9BA,WAAW,UAAW,aACtBA,WAAW,YAAa,eACxBA,WAAW,QAAS,WACpBA,WAAW,eAAgB,UAIhC,GAHIL,IACAI,EAASA,EAAOC,WAAW,QAAS,YAGlB,SAAlBpU,KAAK2P,WACa,IAAlB3P,KAAK2P,eACavG,IAAlBpJ,KAAK2P,SAELrB,EAAS4F,MAAMD,GAAkB,IAAIjU,KAAKqU,OAAOC,OAAOH,QACrD,GAAsB,WAAlBnU,KAAK2P,SACZrB,EAAS4F,MAAMD,GAAkB,IAAIjU,KAAKuU,GAAGD,OAAOH,QACjD,GACsB,mBAAlBnU,KAAK2P,UACZ3P,KAAK2P,SAASJ,WACd9O,OAAO4M,OAAOrN,KAAK2P,SAASJ,UAAW,mBACzC,CACE,MAAMiF,EAAWxU,KAAK2P,SACtBrB,EAAS4F,MAAMD,GAAkB,IAAIO,EAASL,EACjD,KAAM,IAA6B,mBAAlBnU,KAAK2P,SAKnB,MAAM,IAAIpC,UAAU,4BAA4BvN,KAAK2P,aAJrDrB,EAAS4F,MAAMD,GAAkB,CAC7BQ,gBAAkBzS,GAAYhC,KAAK2P,SAASwE,EAAQnS,GAI5D,CACJ,CAEA,IACI,OAAOsM,EAAS4F,MAAMD,GAAgBQ,gBAAgBzU,KAAK4P,YAC9D,CAAC,MAAO5F,GACL,GAAIhK,KAAKiP,iBACL,OAAO,EAEX,MAAM,IAAIxN,MAAM,aAAeuI,EAAEzI,QAAU,KAAOnB,EACtD,CACJ,EAKAkO,EAAS4F,MAAQ,CAAE,EAMnB5F,EAASwB,aAAe,SAAU4E,GAC9B,MAAMrD,EAAIqD,EAASxB,EAAI7B,EAAE9S,OACzB,IAAIoW,EAAI,IACR,IAAK,IAAIzQ,EAAI,EAAGA,EAAIgP,EAAGhP,IACb,qBAAsBqF,KAAK8H,EAAEnN,MAC/ByQ,GAAM,aAAcpL,KAAK8H,EAAEnN,IAAO,IAAMmN,EAAEnN,GAAK,IAAQ,KAAOmN,EAAEnN,GAAK,MAG7E,OAAOyQ,CACX,EAMArG,EAASuC,UAAY,SAAUD,GAC3B,MAAMS,EAAIT,EAASsC,EAAI7B,EAAE9S,OACzB,IAAIoW,EAAI,GACR,IAAK,IAAIzQ,EAAI,EAAGA,EAAIgP,EAAGhP,IACb,qBAAsBqF,KAAK8H,EAAEnN,MAC/ByQ,GAAK,IAAMtD,EAAEnN,GAAGjG,WACXmW,WAAW,IAAK,MAChBA,WAAW,IAAK,OAG7B,OAAOO,CACX,EAMArG,EAAS0B,YAAc,SAAU/P,GAC7B,MAAMiU,MAACA,GAAS5F,EAChB,GAAI4F,EAAMjU,GACN,OAAOiU,EAAMjU,GAAM0Q,SAEvB,MAAMiE,EAAO,GAoCP7E,EAnCa9P,EAEdmU,WACG,uGACA,QAIHA,WAAW,kCAAkC,SAAUS,EAAIC,GACxD,MAAO,MAAQF,EAAKvR,KAAKyR,GAAM,GAAK,GACvC,IAEAV,WAAW,2BAA2B,SAAUS,EAAI3L,GACjD,MAAO,KAAOA,EACTkL,WAAW,IAAK,OAChBA,WAAW,IAAK,UACjB,IACP,IAEAA,WAAW,IAAK,OAEhBA,WAAW,oCAAqC,KAEhDA,WAAW,MAAO,KAElBA,WAAW,SAAU,KAErBA,WAAW,uBAAuB,SAAUS,EAAIE,GAC7C,MAAO,IAAMA,EAAIrC,MAAM,IAAIsC,KAAK,KAAO,GAC1C,IAEAZ,WAAW,WAAY,QAEvBA,WAAW,eAAgB,IAEJ1B,MAAM,KAAK/R,KAAI,SAAUsU,GACjD,MAAMC,EAAQD,EAAIC,MAAM,WACxB,OAAQA,GAAUA,EAAM,GAAWN,EAAKM,EAAM,IAAjBD,CACjC,IAEA,OADAf,EAAMjU,GAAQ8P,EACPmE,EAAMjU,GAAM0Q,QACvB,EAEArC,EAASiB,UAAU8E,OAAS,CACxBC,ODllBJ,MAIIhU,WAAAA,CAAaL,GACTD,KAAKI,KAAOH,EACZD,KAAKgL,IAAM7C,EAAKnI,KAAKI,KACzB,CAOAqU,eAAAA,CAAiBzS,GAEb,MAAMmT,EAAS1U,OAAOwH,OAAOxH,OAAO2U,OAAO,MAAOpT,GAClD,OAAO8I,EAASC,QAAQ/K,KAAKgL,IAAKmK,EACtC,IE3GJ7G,EAASiB,UAAUgF,GAAK,CACpBD,OA3DJ,MAIIhU,WAAAA,CAAaL,GACTD,KAAKI,KAAOH,CAChB,CAOAwU,eAAAA,CAAiBzS,GACb,IAAI/B,EAAOD,KAAKI,KAChB,MAAMM,EAAOD,OAAOC,KAAKsB,GACnBqT,EAAQ,IA/BK,SAAUC,EAAQC,EAAQC,GACjD,MAAMC,EAAKH,EAAO/W,OAClB,IAAK,IAAI2F,EAAI,EAAGA,EAAIuR,EAAIvR,IAEhBsR,EADSF,EAAOpR,KAIhBqR,EAAOlS,KAAKiS,EAAOtC,OAAO9O,IAAK,GAAG,GAG9C,CAsBQwR,CAAmBhV,EAAM2U,GAAQM,GACE,mBAAjB3T,EAAQ2T,KAE1B,MAAMrL,EAAS5J,EAAKC,KAAKiV,GACd5T,EAAQ4T,KAWnB3V,EARmBoV,EAAM9E,QAAO,CAACsF,EAAGhI,KAChC,IAAIiI,EAAU9T,EAAQ6L,GAAM5P,WAI5B,MAHM,YAAasL,KAAKuM,KACpBA,EAAU,YAAcA,GAErB,OAASjI,EAAO,IAAMiI,EAAU,IAAMD,CAAC,GAC/C,IAEiB5V,EAGd,sBAAuBsJ,KAAKtJ,IAAUS,EAAKyI,SAAS,eACtDlJ,EAAO,6BAA+BA,GAM1CA,EAAOA,EAAK4R,QAAQ,SAAU,IAG9B,MAAMkE,EAAmB9V,EAAK+V,YAAY,KACpC5V,GACoB,IAAtB2V,EACM9V,EAAKmH,MAAM,EAAG2O,EAAmB,GACjC,WACA9V,EAAKmH,MAAM2O,EAAmB,GAC9B,WAAa9V,EAGvB,OAAO,IAAI6N,YAAYpN,EAAMN,EAAtB,IAA+BkK,EAC1C","x_google_ignoreList":[0,1,2]}
\ No newline at end of file
+{"version":3,"file":"index-browser-umd.min.cjs","sources":["../node_modules/.pnpm/jsep@1.4.0/node_modules/jsep/dist/jsep.js","../node_modules/.pnpm/@jsep-plugin+regex@1.0.4_jsep@1.4.0/node_modules/@jsep-plugin/regex/dist/index.js","../node_modules/.pnpm/@jsep-plugin+assignment@1.3.0_jsep@1.4.0/node_modules/@jsep-plugin/assignment/dist/index.js","../src/Safe-Script.js","../src/jsonpath.js","../src/jsonpath-browser.js"],"sourcesContent":["/**\n * @implements {IHooks}\n */\nclass Hooks {\n\t/**\n\t * @callback HookCallback\n\t * @this {*|Jsep} this\n\t * @param {Jsep} env\n\t * @returns: void\n\t */\n\t/**\n\t * Adds the given callback to the list of callbacks for the given hook.\n\t *\n\t * The callback will be invoked when the hook it is registered for is run.\n\t *\n\t * One callback function can be registered to multiple hooks and the same hook multiple times.\n\t *\n\t * @param {string|object} name The name of the hook, or an object of callbacks keyed by name\n\t * @param {HookCallback|boolean} callback The callback function which is given environment variables.\n\t * @param {?boolean} [first=false] Will add the hook to the top of the list (defaults to the bottom)\n\t * @public\n\t */\n\tadd(name, callback, first) {\n\t\tif (typeof arguments[0] != 'string') {\n\t\t\t// Multiple hook callbacks, keyed by name\n\t\t\tfor (let name in arguments[0]) {\n\t\t\t\tthis.add(name, arguments[0][name], arguments[1]);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\t(Array.isArray(name) ? name : [name]).forEach(function (name) {\n\t\t\t\tthis[name] = this[name] || [];\n\n\t\t\t\tif (callback) {\n\t\t\t\t\tthis[name][first ? 'unshift' : 'push'](callback);\n\t\t\t\t}\n\t\t\t}, this);\n\t\t}\n\t}\n\n\t/**\n\t * Runs a hook invoking all registered callbacks with the given environment variables.\n\t *\n\t * Callbacks will be invoked synchronously and in the order in which they were registered.\n\t *\n\t * @param {string} name The name of the hook.\n\t * @param {Object} env The environment variables of the hook passed to all callbacks registered.\n\t * @public\n\t */\n\trun(name, env) {\n\t\tthis[name] = this[name] || [];\n\t\tthis[name].forEach(function (callback) {\n\t\t\tcallback.call(env && env.context ? env.context : env, env);\n\t\t});\n\t}\n}\n\n/**\n * @implements {IPlugins}\n */\nclass Plugins {\n\tconstructor(jsep) {\n\t\tthis.jsep = jsep;\n\t\tthis.registered = {};\n\t}\n\n\t/**\n\t * @callback PluginSetup\n\t * @this {Jsep} jsep\n\t * @returns: void\n\t */\n\t/**\n\t * Adds the given plugin(s) to the registry\n\t *\n\t * @param {object} plugins\n\t * @param {string} plugins.name The name of the plugin\n\t * @param {PluginSetup} plugins.init The init function\n\t * @public\n\t */\n\tregister(...plugins) {\n\t\tplugins.forEach((plugin) => {\n\t\t\tif (typeof plugin !== 'object' || !plugin.name || !plugin.init) {\n\t\t\t\tthrow new Error('Invalid JSEP plugin format');\n\t\t\t}\n\t\t\tif (this.registered[plugin.name]) {\n\t\t\t\t// already registered. Ignore.\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tplugin.init(this.jsep);\n\t\t\tthis.registered[plugin.name] = plugin;\n\t\t});\n\t}\n}\n\n// JavaScript Expression Parser (JSEP) 1.4.0\n\nclass Jsep {\n\t/**\n\t * @returns {string}\n\t */\n\tstatic get version() {\n\t\t// To be filled in by the template\n\t\treturn '1.4.0';\n\t}\n\n\t/**\n\t * @returns {string}\n\t */\n\tstatic toString() {\n\t\treturn 'JavaScript Expression Parser (JSEP) v' + Jsep.version;\n\t};\n\n\t// ==================== CONFIG ================================\n\t/**\n\t * @method addUnaryOp\n\t * @param {string} op_name The name of the unary op to add\n\t * @returns {Jsep}\n\t */\n\tstatic addUnaryOp(op_name) {\n\t\tJsep.max_unop_len = Math.max(op_name.length, Jsep.max_unop_len);\n\t\tJsep.unary_ops[op_name] = 1;\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method jsep.addBinaryOp\n\t * @param {string} op_name The name of the binary op to add\n\t * @param {number} precedence The precedence of the binary op (can be a float). Higher number = higher precedence\n\t * @param {boolean} [isRightAssociative=false] whether operator is right-associative\n\t * @returns {Jsep}\n\t */\n\tstatic addBinaryOp(op_name, precedence, isRightAssociative) {\n\t\tJsep.max_binop_len = Math.max(op_name.length, Jsep.max_binop_len);\n\t\tJsep.binary_ops[op_name] = precedence;\n\t\tif (isRightAssociative) {\n\t\t\tJsep.right_associative.add(op_name);\n\t\t}\n\t\telse {\n\t\t\tJsep.right_associative.delete(op_name);\n\t\t}\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method addIdentifierChar\n\t * @param {string} char The additional character to treat as a valid part of an identifier\n\t * @returns {Jsep}\n\t */\n\tstatic addIdentifierChar(char) {\n\t\tJsep.additional_identifier_chars.add(char);\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method addLiteral\n\t * @param {string} literal_name The name of the literal to add\n\t * @param {*} literal_value The value of the literal\n\t * @returns {Jsep}\n\t */\n\tstatic addLiteral(literal_name, literal_value) {\n\t\tJsep.literals[literal_name] = literal_value;\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method removeUnaryOp\n\t * @param {string} op_name The name of the unary op to remove\n\t * @returns {Jsep}\n\t */\n\tstatic removeUnaryOp(op_name) {\n\t\tdelete Jsep.unary_ops[op_name];\n\t\tif (op_name.length === Jsep.max_unop_len) {\n\t\t\tJsep.max_unop_len = Jsep.getMaxKeyLen(Jsep.unary_ops);\n\t\t}\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method removeAllUnaryOps\n\t * @returns {Jsep}\n\t */\n\tstatic removeAllUnaryOps() {\n\t\tJsep.unary_ops = {};\n\t\tJsep.max_unop_len = 0;\n\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method removeIdentifierChar\n\t * @param {string} char The additional character to stop treating as a valid part of an identifier\n\t * @returns {Jsep}\n\t */\n\tstatic removeIdentifierChar(char) {\n\t\tJsep.additional_identifier_chars.delete(char);\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method removeBinaryOp\n\t * @param {string} op_name The name of the binary op to remove\n\t * @returns {Jsep}\n\t */\n\tstatic removeBinaryOp(op_name) {\n\t\tdelete Jsep.binary_ops[op_name];\n\n\t\tif (op_name.length === Jsep.max_binop_len) {\n\t\t\tJsep.max_binop_len = Jsep.getMaxKeyLen(Jsep.binary_ops);\n\t\t}\n\t\tJsep.right_associative.delete(op_name);\n\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method removeAllBinaryOps\n\t * @returns {Jsep}\n\t */\n\tstatic removeAllBinaryOps() {\n\t\tJsep.binary_ops = {};\n\t\tJsep.max_binop_len = 0;\n\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method removeLiteral\n\t * @param {string} literal_name The name of the literal to remove\n\t * @returns {Jsep}\n\t */\n\tstatic removeLiteral(literal_name) {\n\t\tdelete Jsep.literals[literal_name];\n\t\treturn Jsep;\n\t}\n\n\t/**\n\t * @method removeAllLiterals\n\t * @returns {Jsep}\n\t */\n\tstatic removeAllLiterals() {\n\t\tJsep.literals = {};\n\n\t\treturn Jsep;\n\t}\n\t// ==================== END CONFIG ============================\n\n\n\t/**\n\t * @returns {string}\n\t */\n\tget char() {\n\t\treturn this.expr.charAt(this.index);\n\t}\n\n\t/**\n\t * @returns {number}\n\t */\n\tget code() {\n\t\treturn this.expr.charCodeAt(this.index);\n\t};\n\n\n\t/**\n\t * @param {string} expr a string with the passed in express\n\t * @returns Jsep\n\t */\n\tconstructor(expr) {\n\t\t// `index` stores the character number we are currently at\n\t\t// All of the gobbles below will modify `index` as we move along\n\t\tthis.expr = expr;\n\t\tthis.index = 0;\n\t}\n\n\t/**\n\t * static top-level parser\n\t * @returns {jsep.Expression}\n\t */\n\tstatic parse(expr) {\n\t\treturn (new Jsep(expr)).parse();\n\t}\n\n\t/**\n\t * Get the longest key length of any object\n\t * @param {object} obj\n\t * @returns {number}\n\t */\n\tstatic getMaxKeyLen(obj) {\n\t\treturn Math.max(0, ...Object.keys(obj).map(k => k.length));\n\t}\n\n\t/**\n\t * `ch` is a character code in the next three functions\n\t * @param {number} ch\n\t * @returns {boolean}\n\t */\n\tstatic isDecimalDigit(ch) {\n\t\treturn (ch >= 48 && ch <= 57); // 0...9\n\t}\n\n\t/**\n\t * Returns the precedence of a binary operator or `0` if it isn't a binary operator. Can be float.\n\t * @param {string} op_val\n\t * @returns {number}\n\t */\n\tstatic binaryPrecedence(op_val) {\n\t\treturn Jsep.binary_ops[op_val] || 0;\n\t}\n\n\t/**\n\t * Looks for start of identifier\n\t * @param {number} ch\n\t * @returns {boolean}\n\t */\n\tstatic isIdentifierStart(ch) {\n\t\treturn (ch >= 65 && ch <= 90) || // A...Z\n\t\t\t(ch >= 97 && ch <= 122) || // a...z\n\t\t\t(ch >= 128 && !Jsep.binary_ops[String.fromCharCode(ch)]) || // any non-ASCII that is not an operator\n\t\t\t(Jsep.additional_identifier_chars.has(String.fromCharCode(ch))); // additional characters\n\t}\n\n\t/**\n\t * @param {number} ch\n\t * @returns {boolean}\n\t */\n\tstatic isIdentifierPart(ch) {\n\t\treturn Jsep.isIdentifierStart(ch) || Jsep.isDecimalDigit(ch);\n\t}\n\n\t/**\n\t * throw error at index of the expression\n\t * @param {string} message\n\t * @throws\n\t */\n\tthrowError(message) {\n\t\tconst error = new Error(message + ' at character ' + this.index);\n\t\terror.index = this.index;\n\t\terror.description = message;\n\t\tthrow error;\n\t}\n\n\t/**\n\t * Run a given hook\n\t * @param {string} name\n\t * @param {jsep.Expression|false} [node]\n\t * @returns {?jsep.Expression}\n\t */\n\trunHook(name, node) {\n\t\tif (Jsep.hooks[name]) {\n\t\t\tconst env = { context: this, node };\n\t\t\tJsep.hooks.run(name, env);\n\t\t\treturn env.node;\n\t\t}\n\t\treturn node;\n\t}\n\n\t/**\n\t * Runs a given hook until one returns a node\n\t * @param {string} name\n\t * @returns {?jsep.Expression}\n\t */\n\tsearchHook(name) {\n\t\tif (Jsep.hooks[name]) {\n\t\t\tconst env = { context: this };\n\t\t\tJsep.hooks[name].find(function (callback) {\n\t\t\t\tcallback.call(env.context, env);\n\t\t\t\treturn env.node;\n\t\t\t});\n\t\t\treturn env.node;\n\t\t}\n\t}\n\n\t/**\n\t * Push `index` up to the next non-space character\n\t */\n\tgobbleSpaces() {\n\t\tlet ch = this.code;\n\t\t// Whitespace\n\t\twhile (ch === Jsep.SPACE_CODE\n\t\t|| ch === Jsep.TAB_CODE\n\t\t|| ch === Jsep.LF_CODE\n\t\t|| ch === Jsep.CR_CODE) {\n\t\t\tch = this.expr.charCodeAt(++this.index);\n\t\t}\n\t\tthis.runHook('gobble-spaces');\n\t}\n\n\t/**\n\t * Top-level method to parse all expressions and returns compound or single node\n\t * @returns {jsep.Expression}\n\t */\n\tparse() {\n\t\tthis.runHook('before-all');\n\t\tconst nodes = this.gobbleExpressions();\n\n\t\t// If there's only one expression just try returning the expression\n\t\tconst node = nodes.length === 1\n\t\t ? nodes[0]\n\t\t\t: {\n\t\t\t\ttype: Jsep.COMPOUND,\n\t\t\t\tbody: nodes\n\t\t\t};\n\t\treturn this.runHook('after-all', node);\n\t}\n\n\t/**\n\t * top-level parser (but can be reused within as well)\n\t * @param {number} [untilICode]\n\t * @returns {jsep.Expression[]}\n\t */\n\tgobbleExpressions(untilICode) {\n\t\tlet nodes = [], ch_i, node;\n\n\t\twhile (this.index < this.expr.length) {\n\t\t\tch_i = this.code;\n\n\t\t\t// Expressions can be separated by semicolons, commas, or just inferred without any\n\t\t\t// separators\n\t\t\tif (ch_i === Jsep.SEMCOL_CODE || ch_i === Jsep.COMMA_CODE) {\n\t\t\t\tthis.index++; // ignore separators\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Try to gobble each expression individually\n\t\t\t\tif (node = this.gobbleExpression()) {\n\t\t\t\t\tnodes.push(node);\n\t\t\t\t\t// If we weren't able to find a binary expression and are out of room, then\n\t\t\t\t\t// the expression passed in probably has too much\n\t\t\t\t}\n\t\t\t\telse if (this.index < this.expr.length) {\n\t\t\t\t\tif (ch_i === untilICode) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tthis.throwError('Unexpected \"' + this.char + '\"');\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn nodes;\n\t}\n\n\t/**\n\t * The main parsing function.\n\t * @returns {?jsep.Expression}\n\t */\n\tgobbleExpression() {\n\t\tconst node = this.searchHook('gobble-expression') || this.gobbleBinaryExpression();\n\t\tthis.gobbleSpaces();\n\n\t\treturn this.runHook('after-expression', node);\n\t}\n\n\t/**\n\t * Search for the operation portion of the string (e.g. `+`, `===`)\n\t * Start by taking the longest possible binary operations (3 characters: `===`, `!==`, `>>>`)\n\t * and move down from 3 to 2 to 1 character until a matching binary operation is found\n\t * then, return that binary operation\n\t * @returns {string|boolean}\n\t */\n\tgobbleBinaryOp() {\n\t\tthis.gobbleSpaces();\n\t\tlet to_check = this.expr.substr(this.index, Jsep.max_binop_len);\n\t\tlet tc_len = to_check.length;\n\n\t\twhile (tc_len > 0) {\n\t\t\t// Don't accept a binary op when it is an identifier.\n\t\t\t// Binary ops that start with a identifier-valid character must be followed\n\t\t\t// by a non identifier-part valid character\n\t\t\tif (Jsep.binary_ops.hasOwnProperty(to_check) && (\n\t\t\t\t!Jsep.isIdentifierStart(this.code) ||\n\t\t\t\t(this.index + to_check.length < this.expr.length && !Jsep.isIdentifierPart(this.expr.charCodeAt(this.index + to_check.length)))\n\t\t\t)) {\n\t\t\t\tthis.index += tc_len;\n\t\t\t\treturn to_check;\n\t\t\t}\n\t\t\tto_check = to_check.substr(0, --tc_len);\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * This function is responsible for gobbling an individual expression,\n\t * e.g. `1`, `1+2`, `a+(b*2)-Math.sqrt(2)`\n\t * @returns {?jsep.BinaryExpression}\n\t */\n\tgobbleBinaryExpression() {\n\t\tlet node, biop, prec, stack, biop_info, left, right, i, cur_biop;\n\n\t\t// First, try to get the leftmost thing\n\t\t// Then, check to see if there's a binary operator operating on that leftmost thing\n\t\t// Don't gobbleBinaryOp without a left-hand-side\n\t\tleft = this.gobbleToken();\n\t\tif (!left) {\n\t\t\treturn left;\n\t\t}\n\t\tbiop = this.gobbleBinaryOp();\n\n\t\t// If there wasn't a binary operator, just return the leftmost node\n\t\tif (!biop) {\n\t\t\treturn left;\n\t\t}\n\n\t\t// Otherwise, we need to start a stack to properly place the binary operations in their\n\t\t// precedence structure\n\t\tbiop_info = { value: biop, prec: Jsep.binaryPrecedence(biop), right_a: Jsep.right_associative.has(biop) };\n\n\t\tright = this.gobbleToken();\n\n\t\tif (!right) {\n\t\t\tthis.throwError(\"Expected expression after \" + biop);\n\t\t}\n\n\t\tstack = [left, biop_info, right];\n\n\t\t// Properly deal with precedence using [recursive descent](http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm)\n\t\twhile ((biop = this.gobbleBinaryOp())) {\n\t\t\tprec = Jsep.binaryPrecedence(biop);\n\n\t\t\tif (prec === 0) {\n\t\t\t\tthis.index -= biop.length;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tbiop_info = { value: biop, prec, right_a: Jsep.right_associative.has(biop) };\n\n\t\t\tcur_biop = biop;\n\n\t\t\t// Reduce: make a binary expression from the three topmost entries.\n\t\t\tconst comparePrev = prev => biop_info.right_a && prev.right_a\n\t\t\t\t? prec > prev.prec\n\t\t\t\t: prec <= prev.prec;\n\t\t\twhile ((stack.length > 2) && comparePrev(stack[stack.length - 2])) {\n\t\t\t\tright = stack.pop();\n\t\t\t\tbiop = stack.pop().value;\n\t\t\t\tleft = stack.pop();\n\t\t\t\tnode = {\n\t\t\t\t\ttype: Jsep.BINARY_EXP,\n\t\t\t\t\toperator: biop,\n\t\t\t\t\tleft,\n\t\t\t\t\tright\n\t\t\t\t};\n\t\t\t\tstack.push(node);\n\t\t\t}\n\n\t\t\tnode = this.gobbleToken();\n\n\t\t\tif (!node) {\n\t\t\t\tthis.throwError(\"Expected expression after \" + cur_biop);\n\t\t\t}\n\n\t\t\tstack.push(biop_info, node);\n\t\t}\n\n\t\ti = stack.length - 1;\n\t\tnode = stack[i];\n\n\t\twhile (i > 1) {\n\t\t\tnode = {\n\t\t\t\ttype: Jsep.BINARY_EXP,\n\t\t\t\toperator: stack[i - 1].value,\n\t\t\t\tleft: stack[i - 2],\n\t\t\t\tright: node\n\t\t\t};\n\t\t\ti -= 2;\n\t\t}\n\n\t\treturn node;\n\t}\n\n\t/**\n\t * An individual part of a binary expression:\n\t * e.g. `foo.bar(baz)`, `1`, `\"abc\"`, `(a % 2)` (because it's in parenthesis)\n\t * @returns {boolean|jsep.Expression}\n\t */\n\tgobbleToken() {\n\t\tlet ch, to_check, tc_len, node;\n\n\t\tthis.gobbleSpaces();\n\t\tnode = this.searchHook('gobble-token');\n\t\tif (node) {\n\t\t\treturn this.runHook('after-token', node);\n\t\t}\n\n\t\tch = this.code;\n\n\t\tif (Jsep.isDecimalDigit(ch) || ch === Jsep.PERIOD_CODE) {\n\t\t\t// Char code 46 is a dot `.` which can start off a numeric literal\n\t\t\treturn this.gobbleNumericLiteral();\n\t\t}\n\n\t\tif (ch === Jsep.SQUOTE_CODE || ch === Jsep.DQUOTE_CODE) {\n\t\t\t// Single or double quotes\n\t\t\tnode = this.gobbleStringLiteral();\n\t\t}\n\t\telse if (ch === Jsep.OBRACK_CODE) {\n\t\t\tnode = this.gobbleArray();\n\t\t}\n\t\telse {\n\t\t\tto_check = this.expr.substr(this.index, Jsep.max_unop_len);\n\t\t\ttc_len = to_check.length;\n\n\t\t\twhile (tc_len > 0) {\n\t\t\t\t// Don't accept an unary op when it is an identifier.\n\t\t\t\t// Unary ops that start with a identifier-valid character must be followed\n\t\t\t\t// by a non identifier-part valid character\n\t\t\t\tif (Jsep.unary_ops.hasOwnProperty(to_check) && (\n\t\t\t\t\t!Jsep.isIdentifierStart(this.code) ||\n\t\t\t\t\t(this.index + to_check.length < this.expr.length && !Jsep.isIdentifierPart(this.expr.charCodeAt(this.index + to_check.length)))\n\t\t\t\t)) {\n\t\t\t\t\tthis.index += tc_len;\n\t\t\t\t\tconst argument = this.gobbleToken();\n\t\t\t\t\tif (!argument) {\n\t\t\t\t\t\tthis.throwError('missing unaryOp argument');\n\t\t\t\t\t}\n\t\t\t\t\treturn this.runHook('after-token', {\n\t\t\t\t\t\ttype: Jsep.UNARY_EXP,\n\t\t\t\t\t\toperator: to_check,\n\t\t\t\t\t\targument,\n\t\t\t\t\t\tprefix: true\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tto_check = to_check.substr(0, --tc_len);\n\t\t\t}\n\n\t\t\tif (Jsep.isIdentifierStart(ch)) {\n\t\t\t\tnode = this.gobbleIdentifier();\n\t\t\t\tif (Jsep.literals.hasOwnProperty(node.name)) {\n\t\t\t\t\tnode = {\n\t\t\t\t\t\ttype: Jsep.LITERAL,\n\t\t\t\t\t\tvalue: Jsep.literals[node.name],\n\t\t\t\t\t\traw: node.name,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\telse if (node.name === Jsep.this_str) {\n\t\t\t\t\tnode = { type: Jsep.THIS_EXP };\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (ch === Jsep.OPAREN_CODE) { // open parenthesis\n\t\t\t\tnode = this.gobbleGroup();\n\t\t\t}\n\t\t}\n\n\t\tif (!node) {\n\t\t\treturn this.runHook('after-token', false);\n\t\t}\n\n\t\tnode = this.gobbleTokenProperty(node);\n\t\treturn this.runHook('after-token', node);\n\t}\n\n\t/**\n\t * Gobble properties of of identifiers/strings/arrays/groups.\n\t * e.g. `foo`, `bar.baz`, `foo['bar'].baz`\n\t * It also gobbles function calls:\n\t * e.g. `Math.acos(obj.angle)`\n\t * @param {jsep.Expression} node\n\t * @returns {jsep.Expression}\n\t */\n\tgobbleTokenProperty(node) {\n\t\tthis.gobbleSpaces();\n\n\t\tlet ch = this.code;\n\t\twhile (ch === Jsep.PERIOD_CODE || ch === Jsep.OBRACK_CODE || ch === Jsep.OPAREN_CODE || ch === Jsep.QUMARK_CODE) {\n\t\t\tlet optional;\n\t\t\tif (ch === Jsep.QUMARK_CODE) {\n\t\t\t\tif (this.expr.charCodeAt(this.index + 1) !== Jsep.PERIOD_CODE) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\toptional = true;\n\t\t\t\tthis.index += 2;\n\t\t\t\tthis.gobbleSpaces();\n\t\t\t\tch = this.code;\n\t\t\t}\n\t\t\tthis.index++;\n\n\t\t\tif (ch === Jsep.OBRACK_CODE) {\n\t\t\t\tnode = {\n\t\t\t\t\ttype: Jsep.MEMBER_EXP,\n\t\t\t\t\tcomputed: true,\n\t\t\t\t\tobject: node,\n\t\t\t\t\tproperty: this.gobbleExpression()\n\t\t\t\t};\n\t\t\t\tif (!node.property) {\n\t\t\t\t\tthis.throwError('Unexpected \"' + this.char + '\"');\n\t\t\t\t}\n\t\t\t\tthis.gobbleSpaces();\n\t\t\t\tch = this.code;\n\t\t\t\tif (ch !== Jsep.CBRACK_CODE) {\n\t\t\t\t\tthis.throwError('Unclosed [');\n\t\t\t\t}\n\t\t\t\tthis.index++;\n\t\t\t}\n\t\t\telse if (ch === Jsep.OPAREN_CODE) {\n\t\t\t\t// A function call is being made; gobble all the arguments\n\t\t\t\tnode = {\n\t\t\t\t\ttype: Jsep.CALL_EXP,\n\t\t\t\t\t'arguments': this.gobbleArguments(Jsep.CPAREN_CODE),\n\t\t\t\t\tcallee: node\n\t\t\t\t};\n\t\t\t}\n\t\t\telse if (ch === Jsep.PERIOD_CODE || optional) {\n\t\t\t\tif (optional) {\n\t\t\t\t\tthis.index--;\n\t\t\t\t}\n\t\t\t\tthis.gobbleSpaces();\n\t\t\t\tnode = {\n\t\t\t\t\ttype: Jsep.MEMBER_EXP,\n\t\t\t\t\tcomputed: false,\n\t\t\t\t\tobject: node,\n\t\t\t\t\tproperty: this.gobbleIdentifier(),\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (optional) {\n\t\t\t\tnode.optional = true;\n\t\t\t} // else leave undefined for compatibility with esprima\n\n\t\t\tthis.gobbleSpaces();\n\t\t\tch = this.code;\n\t\t}\n\n\t\treturn node;\n\t}\n\n\t/**\n\t * Parse simple numeric literals: `12`, `3.4`, `.5`. Do this by using a string to\n\t * keep track of everything in the numeric literal and then calling `parseFloat` on that string\n\t * @returns {jsep.Literal}\n\t */\n\tgobbleNumericLiteral() {\n\t\tlet number = '', ch, chCode;\n\n\t\twhile (Jsep.isDecimalDigit(this.code)) {\n\t\t\tnumber += this.expr.charAt(this.index++);\n\t\t}\n\n\t\tif (this.code === Jsep.PERIOD_CODE) { // can start with a decimal marker\n\t\t\tnumber += this.expr.charAt(this.index++);\n\n\t\t\twhile (Jsep.isDecimalDigit(this.code)) {\n\t\t\t\tnumber += this.expr.charAt(this.index++);\n\t\t\t}\n\t\t}\n\n\t\tch = this.char;\n\n\t\tif (ch === 'e' || ch === 'E') { // exponent marker\n\t\t\tnumber += this.expr.charAt(this.index++);\n\t\t\tch = this.char;\n\n\t\t\tif (ch === '+' || ch === '-') { // exponent sign\n\t\t\t\tnumber += this.expr.charAt(this.index++);\n\t\t\t}\n\n\t\t\twhile (Jsep.isDecimalDigit(this.code)) { // exponent itself\n\t\t\t\tnumber += this.expr.charAt(this.index++);\n\t\t\t}\n\n\t\t\tif (!Jsep.isDecimalDigit(this.expr.charCodeAt(this.index - 1)) ) {\n\t\t\t\tthis.throwError('Expected exponent (' + number + this.char + ')');\n\t\t\t}\n\t\t}\n\n\t\tchCode = this.code;\n\n\t\t// Check to make sure this isn't a variable name that start with a number (123abc)\n\t\tif (Jsep.isIdentifierStart(chCode)) {\n\t\t\tthis.throwError('Variable names cannot start with a number (' +\n\t\t\t\tnumber + this.char + ')');\n\t\t}\n\t\telse if (chCode === Jsep.PERIOD_CODE || (number.length === 1 && number.charCodeAt(0) === Jsep.PERIOD_CODE)) {\n\t\t\tthis.throwError('Unexpected period');\n\t\t}\n\n\t\treturn {\n\t\t\ttype: Jsep.LITERAL,\n\t\t\tvalue: parseFloat(number),\n\t\t\traw: number\n\t\t};\n\t}\n\n\t/**\n\t * Parses a string literal, staring with single or double quotes with basic support for escape codes\n\t * e.g. `\"hello world\"`, `'this is\\nJSEP'`\n\t * @returns {jsep.Literal}\n\t */\n\tgobbleStringLiteral() {\n\t\tlet str = '';\n\t\tconst startIndex = this.index;\n\t\tconst quote = this.expr.charAt(this.index++);\n\t\tlet closed = false;\n\n\t\twhile (this.index < this.expr.length) {\n\t\t\tlet ch = this.expr.charAt(this.index++);\n\n\t\t\tif (ch === quote) {\n\t\t\t\tclosed = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\telse if (ch === '\\\\') {\n\t\t\t\t// Check for all of the common escape codes\n\t\t\t\tch = this.expr.charAt(this.index++);\n\n\t\t\t\tswitch (ch) {\n\t\t\t\t\tcase 'n': str += '\\n'; break;\n\t\t\t\t\tcase 'r': str += '\\r'; break;\n\t\t\t\t\tcase 't': str += '\\t'; break;\n\t\t\t\t\tcase 'b': str += '\\b'; break;\n\t\t\t\t\tcase 'f': str += '\\f'; break;\n\t\t\t\t\tcase 'v': str += '\\x0B'; break;\n\t\t\t\t\tdefault : str += ch;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tstr += ch;\n\t\t\t}\n\t\t}\n\n\t\tif (!closed) {\n\t\t\tthis.throwError('Unclosed quote after \"' + str + '\"');\n\t\t}\n\n\t\treturn {\n\t\t\ttype: Jsep.LITERAL,\n\t\t\tvalue: str,\n\t\t\traw: this.expr.substring(startIndex, this.index),\n\t\t};\n\t}\n\n\t/**\n\t * Gobbles only identifiers\n\t * e.g.: `foo`, `_value`, `$x1`\n\t * Also, this function checks if that identifier is a literal:\n\t * (e.g. `true`, `false`, `null`) or `this`\n\t * @returns {jsep.Identifier}\n\t */\n\tgobbleIdentifier() {\n\t\tlet ch = this.code, start = this.index;\n\n\t\tif (Jsep.isIdentifierStart(ch)) {\n\t\t\tthis.index++;\n\t\t}\n\t\telse {\n\t\t\tthis.throwError('Unexpected ' + this.char);\n\t\t}\n\n\t\twhile (this.index < this.expr.length) {\n\t\t\tch = this.code;\n\n\t\t\tif (Jsep.isIdentifierPart(ch)) {\n\t\t\t\tthis.index++;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\ttype: Jsep.IDENTIFIER,\n\t\t\tname: this.expr.slice(start, this.index),\n\t\t};\n\t}\n\n\t/**\n\t * Gobbles a list of arguments within the context of a function call\n\t * or array literal. This function also assumes that the opening character\n\t * `(` or `[` has already been gobbled, and gobbles expressions and commas\n\t * until the terminator character `)` or `]` is encountered.\n\t * e.g. `foo(bar, baz)`, `my_func()`, or `[bar, baz]`\n\t * @param {number} termination\n\t * @returns {jsep.Expression[]}\n\t */\n\tgobbleArguments(termination) {\n\t\tconst args = [];\n\t\tlet closed = false;\n\t\tlet separator_count = 0;\n\n\t\twhile (this.index < this.expr.length) {\n\t\t\tthis.gobbleSpaces();\n\t\t\tlet ch_i = this.code;\n\n\t\t\tif (ch_i === termination) { // done parsing\n\t\t\t\tclosed = true;\n\t\t\t\tthis.index++;\n\n\t\t\t\tif (termination === Jsep.CPAREN_CODE && separator_count && separator_count >= args.length){\n\t\t\t\t\tthis.throwError('Unexpected token ' + String.fromCharCode(termination));\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\telse if (ch_i === Jsep.COMMA_CODE) { // between expressions\n\t\t\t\tthis.index++;\n\t\t\t\tseparator_count++;\n\n\t\t\t\tif (separator_count !== args.length) { // missing argument\n\t\t\t\t\tif (termination === Jsep.CPAREN_CODE) {\n\t\t\t\t\t\tthis.throwError('Unexpected token ,');\n\t\t\t\t\t}\n\t\t\t\t\telse if (termination === Jsep.CBRACK_CODE) {\n\t\t\t\t\t\tfor (let arg = args.length; arg < separator_count; arg++) {\n\t\t\t\t\t\t\targs.push(null);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (args.length !== separator_count && separator_count !== 0) {\n\t\t\t\t// NOTE: `&& separator_count !== 0` allows for either all commas, or all spaces as arguments\n\t\t\t\tthis.throwError('Expected comma');\n\t\t\t}\n\t\t\telse {\n\t\t\t\tconst node = this.gobbleExpression();\n\n\t\t\t\tif (!node || node.type === Jsep.COMPOUND) {\n\t\t\t\t\tthis.throwError('Expected comma');\n\t\t\t\t}\n\n\t\t\t\targs.push(node);\n\t\t\t}\n\t\t}\n\n\t\tif (!closed) {\n\t\t\tthis.throwError('Expected ' + String.fromCharCode(termination));\n\t\t}\n\n\t\treturn args;\n\t}\n\n\t/**\n\t * Responsible for parsing a group of things within parentheses `()`\n\t * that have no identifier in front (so not a function call)\n\t * This function assumes that it needs to gobble the opening parenthesis\n\t * and then tries to gobble everything within that parenthesis, assuming\n\t * that the next thing it should see is the close parenthesis. If not,\n\t * then the expression probably doesn't have a `)`\n\t * @returns {boolean|jsep.Expression}\n\t */\n\tgobbleGroup() {\n\t\tthis.index++;\n\t\tlet nodes = this.gobbleExpressions(Jsep.CPAREN_CODE);\n\t\tif (this.code === Jsep.CPAREN_CODE) {\n\t\t\tthis.index++;\n\t\t\tif (nodes.length === 1) {\n\t\t\t\treturn nodes[0];\n\t\t\t}\n\t\t\telse if (!nodes.length) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn {\n\t\t\t\t\ttype: Jsep.SEQUENCE_EXP,\n\t\t\t\t\texpressions: nodes,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tthis.throwError('Unclosed (');\n\t\t}\n\t}\n\n\t/**\n\t * Responsible for parsing Array literals `[1, 2, 3]`\n\t * This function assumes that it needs to gobble the opening bracket\n\t * and then tries to gobble the expressions as arguments.\n\t * @returns {jsep.ArrayExpression}\n\t */\n\tgobbleArray() {\n\t\tthis.index++;\n\n\t\treturn {\n\t\t\ttype: Jsep.ARRAY_EXP,\n\t\t\telements: this.gobbleArguments(Jsep.CBRACK_CODE)\n\t\t};\n\t}\n}\n\n// Static fields:\nconst hooks = new Hooks();\nObject.assign(Jsep, {\n\thooks,\n\tplugins: new Plugins(Jsep),\n\n\t// Node Types\n\t// ----------\n\t// This is the full set of types that any JSEP node can be.\n\t// Store them here to save space when minified\n\tCOMPOUND: 'Compound',\n\tSEQUENCE_EXP: 'SequenceExpression',\n\tIDENTIFIER: 'Identifier',\n\tMEMBER_EXP: 'MemberExpression',\n\tLITERAL: 'Literal',\n\tTHIS_EXP: 'ThisExpression',\n\tCALL_EXP: 'CallExpression',\n\tUNARY_EXP: 'UnaryExpression',\n\tBINARY_EXP: 'BinaryExpression',\n\tARRAY_EXP: 'ArrayExpression',\n\n\tTAB_CODE: 9,\n\tLF_CODE: 10,\n\tCR_CODE: 13,\n\tSPACE_CODE: 32,\n\tPERIOD_CODE: 46, // '.'\n\tCOMMA_CODE: 44, // ','\n\tSQUOTE_CODE: 39, // single quote\n\tDQUOTE_CODE: 34, // double quotes\n\tOPAREN_CODE: 40, // (\n\tCPAREN_CODE: 41, // )\n\tOBRACK_CODE: 91, // [\n\tCBRACK_CODE: 93, // ]\n\tQUMARK_CODE: 63, // ?\n\tSEMCOL_CODE: 59, // ;\n\tCOLON_CODE: 58, // :\n\n\n\t// Operations\n\t// ----------\n\t// Use a quickly-accessible map to store all of the unary operators\n\t// Values are set to `1` (it really doesn't matter)\n\tunary_ops: {\n\t\t'-': 1,\n\t\t'!': 1,\n\t\t'~': 1,\n\t\t'+': 1\n\t},\n\n\t// Also use a map for the binary operations but set their values to their\n\t// binary precedence for quick reference (higher number = higher precedence)\n\t// see [Order of operations](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence)\n\tbinary_ops: {\n\t\t'||': 1, '??': 1,\n\t\t'&&': 2, '|': 3, '^': 4, '&': 5,\n\t\t'==': 6, '!=': 6, '===': 6, '!==': 6,\n\t\t'<': 7, '>': 7, '<=': 7, '>=': 7,\n\t\t'<<': 8, '>>': 8, '>>>': 8,\n\t\t'+': 9, '-': 9,\n\t\t'*': 10, '/': 10, '%': 10,\n\t\t'**': 11,\n\t},\n\n\t// sets specific binary_ops as right-associative\n\tright_associative: new Set(['**']),\n\n\t// Additional valid identifier chars, apart from a-z, A-Z and 0-9 (except on the starting char)\n\tadditional_identifier_chars: new Set(['$', '_']),\n\n\t// Literals\n\t// ----------\n\t// Store the values to return for the various literals we may encounter\n\tliterals: {\n\t\t'true': true,\n\t\t'false': false,\n\t\t'null': null\n\t},\n\n\t// Except for `this`, which is special. This could be changed to something like `'self'` as well\n\tthis_str: 'this',\n});\nJsep.max_unop_len = Jsep.getMaxKeyLen(Jsep.unary_ops);\nJsep.max_binop_len = Jsep.getMaxKeyLen(Jsep.binary_ops);\n\n// Backward Compatibility:\nconst jsep = expr => (new Jsep(expr)).parse();\nconst stdClassProps = Object.getOwnPropertyNames(class Test{});\nObject.getOwnPropertyNames(Jsep)\n\t.filter(prop => !stdClassProps.includes(prop) && jsep[prop] === undefined)\n\t.forEach((m) => {\n\t\tjsep[m] = Jsep[m];\n\t});\njsep.Jsep = Jsep; // allows for const { Jsep } = require('jsep');\n\nconst CONDITIONAL_EXP = 'ConditionalExpression';\n\nvar ternary = {\n\tname: 'ternary',\n\n\tinit(jsep) {\n\t\t// Ternary expression: test ? consequent : alternate\n\t\tjsep.hooks.add('after-expression', function gobbleTernary(env) {\n\t\t\tif (env.node && this.code === jsep.QUMARK_CODE) {\n\t\t\t\tthis.index++;\n\t\t\t\tconst test = env.node;\n\t\t\t\tconst consequent = this.gobbleExpression();\n\n\t\t\t\tif (!consequent) {\n\t\t\t\t\tthis.throwError('Expected expression');\n\t\t\t\t}\n\n\t\t\t\tthis.gobbleSpaces();\n\n\t\t\t\tif (this.code === jsep.COLON_CODE) {\n\t\t\t\t\tthis.index++;\n\t\t\t\t\tconst alternate = this.gobbleExpression();\n\n\t\t\t\t\tif (!alternate) {\n\t\t\t\t\t\tthis.throwError('Expected expression');\n\t\t\t\t\t}\n\t\t\t\t\tenv.node = {\n\t\t\t\t\t\ttype: CONDITIONAL_EXP,\n\t\t\t\t\t\ttest,\n\t\t\t\t\t\tconsequent,\n\t\t\t\t\t\talternate,\n\t\t\t\t\t};\n\n\t\t\t\t\t// check for operators of higher priority than ternary (i.e. assignment)\n\t\t\t\t\t// jsep sets || at 1, and assignment at 0.9, and conditional should be between them\n\t\t\t\t\tif (test.operator && jsep.binary_ops[test.operator] <= 0.9) {\n\t\t\t\t\t\tlet newTest = test;\n\t\t\t\t\t\twhile (newTest.right.operator && jsep.binary_ops[newTest.right.operator] <= 0.9) {\n\t\t\t\t\t\t\tnewTest = newTest.right;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tenv.node.test = newTest.right;\n\t\t\t\t\t\tnewTest.right = env.node;\n\t\t\t\t\t\tenv.node = test;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tthis.throwError('Expected :');\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n};\n\n// Add default plugins:\n\njsep.plugins.register(ternary);\n\nexport { Jsep, jsep as default };\n","const FSLASH_CODE = 47; // '/'\nconst BSLASH_CODE = 92; // '\\\\'\n\nvar index = {\n\tname: 'regex',\n\n\tinit(jsep) {\n\t\t// Regex literal: /abc123/ig\n\t\tjsep.hooks.add('gobble-token', function gobbleRegexLiteral(env) {\n\t\t\tif (this.code === FSLASH_CODE) {\n\t\t\t\tconst patternIndex = ++this.index;\n\n\t\t\t\tlet inCharSet = false;\n\t\t\t\twhile (this.index < this.expr.length) {\n\t\t\t\t\tif (this.code === FSLASH_CODE && !inCharSet) {\n\t\t\t\t\t\tconst pattern = this.expr.slice(patternIndex, this.index);\n\n\t\t\t\t\t\tlet flags = '';\n\t\t\t\t\t\twhile (++this.index < this.expr.length) {\n\t\t\t\t\t\t\tconst code = this.code;\n\t\t\t\t\t\t\tif ((code >= 97 && code <= 122) // a...z\n\t\t\t\t\t\t\t\t|| (code >= 65 && code <= 90) // A...Z\n\t\t\t\t\t\t\t\t|| (code >= 48 && code <= 57)) { // 0-9\n\t\t\t\t\t\t\t\tflags += this.char;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tlet value;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tvalue = new RegExp(pattern, flags);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcatch (e) {\n\t\t\t\t\t\t\tthis.throwError(e.message);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tenv.node = {\n\t\t\t\t\t\t\ttype: jsep.LITERAL,\n\t\t\t\t\t\t\tvalue,\n\t\t\t\t\t\t\traw: this.expr.slice(patternIndex - 1, this.index),\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\t// allow . [] and () after regex: /regex/.test(a)\n\t\t\t\t\t\tenv.node = this.gobbleTokenProperty(env.node);\n\t\t\t\t\t\treturn env.node;\n\t\t\t\t\t}\n\t\t\t\t\tif (this.code === jsep.OBRACK_CODE) {\n\t\t\t\t\t\tinCharSet = true;\n\t\t\t\t\t}\n\t\t\t\t\telse if (inCharSet && this.code === jsep.CBRACK_CODE) {\n\t\t\t\t\t\tinCharSet = false;\n\t\t\t\t\t}\n\t\t\t\t\tthis.index += this.code === BSLASH_CODE ? 2 : 1;\n\t\t\t\t}\n\t\t\t\tthis.throwError('Unclosed Regex');\n\t\t\t}\n\t\t});\n\t},\n};\n\nexport { index as default };\n","const PLUS_CODE = 43; // +\nconst MINUS_CODE = 45; // -\n\nconst plugin = {\n\tname: 'assignment',\n\n\tassignmentOperators: new Set([\n\t\t'=',\n\t\t'*=',\n\t\t'**=',\n\t\t'/=',\n\t\t'%=',\n\t\t'+=',\n\t\t'-=',\n\t\t'<<=',\n\t\t'>>=',\n\t\t'>>>=',\n\t\t'&=',\n\t\t'^=',\n\t\t'|=',\n\t\t'||=',\n\t\t'&&=',\n\t\t'??=',\n\t]),\n\tupdateOperators: [PLUS_CODE, MINUS_CODE],\n\tassignmentPrecedence: 0.9,\n\n\tinit(jsep) {\n\t\tconst updateNodeTypes = [jsep.IDENTIFIER, jsep.MEMBER_EXP];\n\t\tplugin.assignmentOperators.forEach(op => jsep.addBinaryOp(op, plugin.assignmentPrecedence, true));\n\n\t\tjsep.hooks.add('gobble-token', function gobbleUpdatePrefix(env) {\n\t\t\tconst code = this.code;\n\t\t\tif (plugin.updateOperators.some(c => c === code && c === this.expr.charCodeAt(this.index + 1))) {\n\t\t\t\tthis.index += 2;\n\t\t\t\tenv.node = {\n\t\t\t\t\ttype: 'UpdateExpression',\n\t\t\t\t\toperator: code === PLUS_CODE ? '++' : '--',\n\t\t\t\t\targument: this.gobbleTokenProperty(this.gobbleIdentifier()),\n\t\t\t\t\tprefix: true,\n\t\t\t\t};\n\t\t\t\tif (!env.node.argument || !updateNodeTypes.includes(env.node.argument.type)) {\n\t\t\t\t\tthis.throwError(`Unexpected ${env.node.operator}`);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tjsep.hooks.add('after-token', function gobbleUpdatePostfix(env) {\n\t\t\tif (env.node) {\n\t\t\t\tconst code = this.code;\n\t\t\t\tif (plugin.updateOperators.some(c => c === code && c === this.expr.charCodeAt(this.index + 1))) {\n\t\t\t\t\tif (!updateNodeTypes.includes(env.node.type)) {\n\t\t\t\t\t\tthis.throwError(`Unexpected ${env.node.operator}`);\n\t\t\t\t\t}\n\t\t\t\t\tthis.index += 2;\n\t\t\t\t\tenv.node = {\n\t\t\t\t\t\ttype: 'UpdateExpression',\n\t\t\t\t\t\toperator: code === PLUS_CODE ? '++' : '--',\n\t\t\t\t\t\targument: env.node,\n\t\t\t\t\t\tprefix: false,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tjsep.hooks.add('after-expression', function gobbleAssignment(env) {\n\t\t\tif (env.node) {\n\t\t\t\t// Note: Binaries can be chained in a single expression to respect\n\t\t\t\t// operator precedence (i.e. a = b = 1 + 2 + 3)\n\t\t\t\t// Update all binary assignment nodes in the tree\n\t\t\t\tupdateBinariesToAssignments(env.node);\n\t\t\t}\n\t\t});\n\n\t\tfunction updateBinariesToAssignments(node) {\n\t\t\tif (plugin.assignmentOperators.has(node.operator)) {\n\t\t\t\tnode.type = 'AssignmentExpression';\n\t\t\t\tupdateBinariesToAssignments(node.left);\n\t\t\t\tupdateBinariesToAssignments(node.right);\n\t\t\t}\n\t\t\telse if (!node.operator) {\n\t\t\t\tObject.values(node).forEach((val) => {\n\t\t\t\t\tif (val && typeof val === 'object') {\n\t\t\t\t\t\tupdateBinariesToAssignments(val);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t},\n};\n\nexport { plugin as default };\n","/* eslint-disable no-bitwise -- Convenient */\nimport jsep from 'jsep';\nimport jsepRegex from '@jsep-plugin/regex';\nimport jsepAssignment from '@jsep-plugin/assignment';\n\n// register plugins\njsep.plugins.register(jsepRegex, jsepAssignment);\njsep.addUnaryOp('typeof');\njsep.addUnaryOp('void');\njsep.addLiteral('null', null);\njsep.addLiteral('undefined', undefined);\n\nconst BLOCKED_PROTO_PROPERTIES = new Set([\n 'constructor',\n '__proto__',\n '__defineGetter__',\n '__defineSetter__',\n '__lookupGetter__',\n '__lookupSetter__'\n]);\n\nconst SafeEval = {\n /**\n * @param {jsep.Expression} ast\n * @param {Record} subs\n */\n evalAst (ast, subs) {\n switch (ast.type) {\n case 'BinaryExpression':\n case 'LogicalExpression':\n return SafeEval.evalBinaryExpression(ast, subs);\n case 'Compound':\n return SafeEval.evalCompound(ast, subs);\n case 'ConditionalExpression':\n return SafeEval.evalConditionalExpression(ast, subs);\n case 'Identifier':\n return SafeEval.evalIdentifier(ast, subs);\n case 'Literal':\n return SafeEval.evalLiteral(ast, subs);\n case 'MemberExpression':\n return SafeEval.evalMemberExpression(ast, subs);\n case 'UnaryExpression':\n return SafeEval.evalUnaryExpression(ast, subs);\n case 'ArrayExpression':\n return SafeEval.evalArrayExpression(ast, subs);\n case 'CallExpression':\n return SafeEval.evalCallExpression(ast, subs);\n case 'AssignmentExpression':\n return SafeEval.evalAssignmentExpression(ast, subs);\n default:\n throw SyntaxError('Unexpected expression', ast);\n }\n },\n evalBinaryExpression (ast, subs) {\n const result = {\n '||': (a, b) => a || b(),\n '&&': (a, b) => a && b(),\n '|': (a, b) => a | b(),\n '^': (a, b) => a ^ b(),\n '&': (a, b) => a & b(),\n // eslint-disable-next-line eqeqeq -- API\n '==': (a, b) => a == b(),\n // eslint-disable-next-line eqeqeq -- API\n '!=': (a, b) => a != b(),\n '===': (a, b) => a === b(),\n '!==': (a, b) => a !== b(),\n '<': (a, b) => a < b(),\n '>': (a, b) => a > b(),\n '<=': (a, b) => a <= b(),\n '>=': (a, b) => a >= b(),\n '<<': (a, b) => a << b(),\n '>>': (a, b) => a >> b(),\n '>>>': (a, b) => a >>> b(),\n '+': (a, b) => a + b(),\n '-': (a, b) => a - b(),\n '*': (a, b) => a * b(),\n '/': (a, b) => a / b(),\n '%': (a, b) => a % b()\n }[ast.operator](\n SafeEval.evalAst(ast.left, subs),\n () => SafeEval.evalAst(ast.right, subs)\n );\n return result;\n },\n evalCompound (ast, subs) {\n let last;\n for (let i = 0; i < ast.body.length; i++) {\n if (\n ast.body[i].type === 'Identifier' &&\n ['var', 'let', 'const'].includes(ast.body[i].name) &&\n ast.body[i + 1] &&\n ast.body[i + 1].type === 'AssignmentExpression'\n ) {\n // var x=2; is detected as\n // [{Identifier var}, {AssignmentExpression x=2}]\n // eslint-disable-next-line @stylistic/max-len -- Long\n // eslint-disable-next-line sonarjs/updated-loop-counter -- Convenient\n i += 1;\n }\n const expr = ast.body[i];\n last = SafeEval.evalAst(expr, subs);\n }\n return last;\n },\n evalConditionalExpression (ast, subs) {\n if (SafeEval.evalAst(ast.test, subs)) {\n return SafeEval.evalAst(ast.consequent, subs);\n }\n return SafeEval.evalAst(ast.alternate, subs);\n },\n evalIdentifier (ast, subs) {\n if (Object.hasOwn(subs, ast.name)) {\n return subs[ast.name];\n }\n throw ReferenceError(`${ast.name} is not defined`);\n },\n evalLiteral (ast) {\n return ast.value;\n },\n evalMemberExpression (ast, subs) {\n const prop = String(\n // NOTE: `String(value)` throws error when\n // value has overwritten the toString method to return non-string\n // i.e. `value = {toString: () => []}`\n ast.computed\n ? SafeEval.evalAst(ast.property) // `object[property]`\n : ast.property.name // `object.property` property is Identifier\n );\n const obj = SafeEval.evalAst(ast.object, subs);\n if (obj === undefined || obj === null) {\n throw TypeError(\n `Cannot read properties of ${obj} (reading '${prop}')`\n );\n }\n if (!Object.hasOwn(obj, prop) && BLOCKED_PROTO_PROPERTIES.has(prop)) {\n throw TypeError(\n `Cannot read properties of ${obj} (reading '${prop}')`\n );\n }\n const result = obj[prop];\n if (typeof result === 'function') {\n return result.bind(obj); // arrow functions aren't affected by bind.\n }\n return result;\n },\n evalUnaryExpression (ast, subs) {\n const result = {\n '-': (a) => -SafeEval.evalAst(a, subs),\n '!': (a) => !SafeEval.evalAst(a, subs),\n '~': (a) => ~SafeEval.evalAst(a, subs),\n // eslint-disable-next-line no-implicit-coercion -- API\n '+': (a) => +SafeEval.evalAst(a, subs),\n typeof: (a) => typeof SafeEval.evalAst(a, subs),\n // eslint-disable-next-line no-void, sonarjs/void-use -- feature\n void: (a) => void SafeEval.evalAst(a, subs)\n }[ast.operator](ast.argument);\n return result;\n },\n evalArrayExpression (ast, subs) {\n return ast.elements.map((el) => SafeEval.evalAst(el, subs));\n },\n evalCallExpression (ast, subs) {\n const args = ast.arguments.map((arg) => SafeEval.evalAst(arg, subs));\n const func = SafeEval.evalAst(ast.callee, subs);\n /* c8 ignore start */\n if (func === Function) {\n // unreachable since BLOCKED_PROTO_PROPERTIES includes 'constructor'\n throw new Error('Function constructor is disabled');\n }\n /* c8 ignore end */\n return func(...args);\n },\n evalAssignmentExpression (ast, subs) {\n if (ast.left.type !== 'Identifier') {\n throw SyntaxError('Invalid left-hand side in assignment');\n }\n const id = ast.left.name;\n const value = SafeEval.evalAst(ast.right, subs);\n subs[id] = value;\n return subs[id];\n }\n};\n\n/**\n * A replacement for NodeJS' VM.Script which is also {@link https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP | Content Security Policy} friendly.\n */\nclass SafeScript {\n /**\n * @param {string} expr Expression to evaluate\n */\n constructor (expr) {\n this.code = expr;\n this.ast = jsep(this.code);\n }\n\n /**\n * @param {object} context Object whose items will be added\n * to evaluation\n * @returns {EvaluatedResult} Result of evaluated code\n */\n runInNewContext (context) {\n // `Object.create(null)` creates a prototypeless object\n const keyMap = Object.assign(Object.create(null), context);\n return SafeEval.evalAst(this.ast, keyMap);\n }\n}\n\nexport {SafeScript};\n","/* eslint-disable camelcase -- Convenient for escaping */\n\nimport {SafeScript} from './Safe-Script.js';\n\n/**\n * @typedef {null|boolean|number|string|object|GenericArray} JSONObject\n */\n\n/**\n * @typedef {any} AnyItem\n */\n\n/**\n * @typedef {any} AnyResult\n */\n\n/**\n * Copies array and then pushes item into it.\n * @param {GenericArray} arr Array to copy and into which to push\n * @param {AnyItem} item Array item to add (to end)\n * @returns {GenericArray} Copy of the original array\n */\nfunction push (arr, item) {\n arr = arr.slice();\n arr.push(item);\n return arr;\n}\n/**\n * Copies array and then unshifts item into it.\n * @param {AnyItem} item Array item to add (to beginning)\n * @param {GenericArray} arr Array to copy and into which to unshift\n * @returns {GenericArray} Copy of the original array\n */\nfunction unshift (item, arr) {\n arr = arr.slice();\n arr.unshift(item);\n return arr;\n}\n\n/**\n * Caught when JSONPath is used without `new` but rethrown if with `new`\n * @extends Error\n */\nclass NewError extends Error {\n /**\n * @param {AnyResult} value The evaluated scalar value\n */\n constructor (value) {\n super(\n 'JSONPath should not be called with \"new\" (it prevents return ' +\n 'of (unwrapped) scalar values)'\n );\n this.avoidNew = true;\n this.value = value;\n this.name = 'NewError';\n }\n}\n\n/**\n* @typedef {object} ReturnObject\n* @property {string} path\n* @property {JSONObject} value\n* @property {object|GenericArray} parent\n* @property {string} parentProperty\n*/\n\n/**\n* @callback JSONPathCallback\n* @param {string|object} preferredOutput\n* @param {\"value\"|\"property\"} type\n* @param {ReturnObject} fullRetObj\n* @returns {void}\n*/\n\n/**\n* @callback OtherTypeCallback\n* @param {JSONObject} val\n* @param {string} path\n* @param {object|GenericArray} parent\n* @param {string} parentPropName\n* @returns {boolean}\n*/\n\n/**\n * @typedef {any} ContextItem\n */\n\n/**\n * @typedef {any} EvaluatedResult\n */\n\n/**\n* @callback EvalCallback\n* @param {string} code\n* @param {ContextItem} context\n* @returns {EvaluatedResult}\n*/\n\n/**\n * @typedef {typeof SafeScript} EvalClass\n */\n\n/**\n * @typedef {object} JSONPathOptions\n * @property {JSON} json\n * @property {string|string[]} path\n * @property {\"value\"|\"path\"|\"pointer\"|\"parent\"|\"parentProperty\"|\n * \"all\"} [resultType=\"value\"]\n * @property {boolean} [flatten=false]\n * @property {boolean} [wrap=true]\n * @property {object} [sandbox={}]\n * @property {EvalCallback|EvalClass|'safe'|'native'|\n * boolean} [eval = 'safe']\n * @property {object|GenericArray|null} [parent=null]\n * @property {string|null} [parentProperty=null]\n * @property {JSONPathCallback} [callback]\n * @property {OtherTypeCallback} [otherTypeCallback] Defaults to\n * function which throws on encountering `@other`\n * @property {boolean} [autostart=true]\n */\n\n/**\n * @param {string|JSONPathOptions} opts If a string, will be treated as `expr`\n * @param {string} [expr] JSON path to evaluate\n * @param {JSON} [obj] JSON object to evaluate against\n * @param {JSONPathCallback} [callback] Passed 3 arguments: 1) desired payload\n * per `resultType`, 2) `\"value\"|\"property\"`, 3) Full returned object with\n * all payloads\n * @param {OtherTypeCallback} [otherTypeCallback] If `@other()` is at the end\n * of one's query, this will be invoked with the value of the item, its\n * path, its parent, and its parent's property name, and it should return\n * a boolean indicating whether the supplied value belongs to the \"other\"\n * type or not (or it may handle transformations and return `false`).\n * @returns {JSONPath}\n * @class\n */\nfunction JSONPath (opts, expr, obj, callback, otherTypeCallback) {\n // eslint-disable-next-line no-restricted-syntax -- Allow for pseudo-class\n if (!(this instanceof JSONPath)) {\n try {\n return new JSONPath(opts, expr, obj, callback, otherTypeCallback);\n } catch (e) {\n if (!e.avoidNew) {\n throw e;\n }\n return e.value;\n }\n }\n\n if (typeof opts === 'string') {\n otherTypeCallback = callback;\n callback = obj;\n obj = expr;\n expr = opts;\n opts = null;\n }\n const optObj = opts && typeof opts === 'object';\n opts = opts || {};\n this.json = opts.json || obj;\n this.path = opts.path || expr;\n this.resultType = opts.resultType || 'value';\n this.flatten = opts.flatten || false;\n this.wrap = Object.hasOwn(opts, 'wrap') ? opts.wrap : true;\n this.sandbox = opts.sandbox || {};\n this.eval = opts.eval === undefined ? 'safe' : opts.eval;\n this.ignoreEvalErrors = (typeof opts.ignoreEvalErrors === 'undefined')\n ? false\n : opts.ignoreEvalErrors;\n this.parent = opts.parent || null;\n this.parentProperty = opts.parentProperty || null;\n this.callback = opts.callback || callback || null;\n this.otherTypeCallback = opts.otherTypeCallback ||\n otherTypeCallback ||\n function () {\n throw new TypeError(\n 'You must supply an otherTypeCallback callback option ' +\n 'with the @other() operator.'\n );\n };\n\n if (opts.autostart !== false) {\n const args = {\n path: (optObj ? opts.path : expr)\n };\n if (!optObj) {\n args.json = obj;\n } else if ('json' in opts) {\n args.json = opts.json;\n }\n const ret = this.evaluate(args);\n if (!ret || typeof ret !== 'object') {\n throw new NewError(ret);\n }\n return ret;\n }\n}\n\n// PUBLIC METHODS\nJSONPath.prototype.evaluate = function (\n expr, json, callback, otherTypeCallback\n) {\n let currParent = this.parent,\n currParentProperty = this.parentProperty;\n let {flatten, wrap} = this;\n\n this.currResultType = this.resultType;\n this.currEval = this.eval;\n this.currSandbox = this.sandbox;\n callback = callback || this.callback;\n this.currOtherTypeCallback = otherTypeCallback || this.otherTypeCallback;\n\n json = json || this.json;\n expr = expr || this.path;\n if (expr && typeof expr === 'object' && !Array.isArray(expr)) {\n if (!expr.path && expr.path !== '') {\n throw new TypeError(\n 'You must supply a \"path\" property when providing an object ' +\n 'argument to JSONPath.evaluate().'\n );\n }\n if (!(Object.hasOwn(expr, 'json'))) {\n throw new TypeError(\n 'You must supply a \"json\" property when providing an object ' +\n 'argument to JSONPath.evaluate().'\n );\n }\n ({json} = expr);\n flatten = Object.hasOwn(expr, 'flatten') ? expr.flatten : flatten;\n this.currResultType = Object.hasOwn(expr, 'resultType')\n ? expr.resultType\n : this.currResultType;\n this.currSandbox = Object.hasOwn(expr, 'sandbox')\n ? expr.sandbox\n : this.currSandbox;\n wrap = Object.hasOwn(expr, 'wrap') ? expr.wrap : wrap;\n this.currEval = Object.hasOwn(expr, 'eval')\n ? expr.eval\n : this.currEval;\n callback = Object.hasOwn(expr, 'callback') ? expr.callback : callback;\n this.currOtherTypeCallback = Object.hasOwn(expr, 'otherTypeCallback')\n ? expr.otherTypeCallback\n : this.currOtherTypeCallback;\n currParent = Object.hasOwn(expr, 'parent') ? expr.parent : currParent;\n currParentProperty = Object.hasOwn(expr, 'parentProperty')\n ? expr.parentProperty\n : currParentProperty;\n expr = expr.path;\n }\n currParent = currParent || null;\n currParentProperty = currParentProperty || null;\n\n if (Array.isArray(expr)) {\n expr = JSONPath.toPathString(expr);\n }\n if ((!expr && expr !== '') || !json) {\n return undefined;\n }\n\n const exprList = JSONPath.toPathParts(expr);\n if (exprList[0] && exprList[0].type === 'root' && exprList.length > 1) {\n exprList.shift();\n }\n this._hasParentSelector = null;\n this._json = json; // Store root for parent selector navigation\n const result = this\n ._trace(\n exprList, json, ['$'], currParent, currParentProperty, callback\n )\n .filter(function (ea) {\n return ea && !ea.isParentSelector;\n });\n\n if (!result.length) {\n return wrap ? [] : undefined;\n }\n if (!wrap && result.length === 1 && !result[0].hasArrExpr) {\n return this._getPreferredOutput(result[0]);\n }\n return result.reduce((rslt, ea) => {\n const valOrPath = this._getPreferredOutput(ea);\n if (flatten && Array.isArray(valOrPath)) {\n rslt = rslt.concat(valOrPath);\n } else {\n rslt.push(valOrPath);\n }\n return rslt;\n }, []);\n};\n\n// PRIVATE METHODS\n\nJSONPath.prototype._getPreferredOutput = function (ea) {\n const resultType = this.currResultType;\n switch (resultType) {\n case 'all': {\n const path = Array.isArray(ea.path)\n ? ea.path\n : JSONPath.toPathParts(ea.path);\n ea.pointer = JSONPath.toPointer(path);\n ea.path = typeof ea.path === 'string'\n ? ea.path\n : JSONPath.toPathString(ea.path);\n return ea;\n } case 'value': case 'parent': case 'parentProperty':\n return ea[resultType];\n case 'path':\n return JSONPath.toPathString(ea[resultType]);\n case 'pointer':\n return JSONPath.toPointer(ea.path);\n default:\n throw new TypeError('Unknown result type');\n }\n};\n\nJSONPath.prototype._handleCallback = function (fullRetObj, callback, type) {\n if (callback) {\n const preferredOutput = this._getPreferredOutput(fullRetObj);\n fullRetObj.path = typeof fullRetObj.path === 'string'\n ? fullRetObj.path\n : JSONPath.toPathString(fullRetObj.path);\n // eslint-disable-next-line n/callback-return -- No need to return\n callback(preferredOutput, type, fullRetObj);\n }\n};\n\n/**\n *\n * @param {string} expr\n * @param {JSONObject} val\n * @param {string} path\n * @param {object|GenericArray} parent\n * @param {string} parentPropName\n * @param {JSONPathCallback} callback\n * @param {boolean} hasArrExpr\n * @param {boolean} literalPriority\n * @returns {ReturnObject|ReturnObject[]}\n */\nJSONPath.prototype._trace = function (\n expr, val, path, parent, parentPropName, callback, hasArrExpr,\n literalPriority\n) {\n // No expr to follow? return path and value as the result of\n // this trace branch\n let retObj;\n if (!expr.length) {\n retObj = {\n path,\n value: val,\n parent,\n parentProperty: parentPropName,\n hasArrExpr\n };\n this._handleCallback(retObj, callback, 'value');\n return [retObj];\n }\n\n const token = expr[0], x = expr.slice(1);\n\n // We need to gather the return value of recursive trace calls in order to\n // do the parent sel computation.\n const ret = [];\n /**\n *\n * @param {ReturnObject|ReturnObject[]} elems\n * @returns {void}\n */\n function addRet (elems) {\n if (Array.isArray(elems)) {\n // This was causing excessive stack size in Node (with or\n // without Babel) against our performance test:\n // `ret.push(...elems);`\n elems.forEach((t) => {\n ret.push(t);\n });\n } else {\n ret.push(elems);\n }\n }\n\n // Fast path for primitive tokens (strings and numbers)\n if (typeof token === 'string') {\n // Simple property access\n if (val && Object.hasOwn(val, token)) {\n addRet(this._trace(\n x, val[token], push(path, token), val, token, callback, hasArrExpr\n ));\n }\n } else if (typeof token === 'number') {\n // Simple numeric index access\n if (Array.isArray(val) && token >= 0 && token < val.length) {\n addRet(this._trace(\n x, val[token], push(path, token), val, token, callback, hasArrExpr\n ));\n }\n } else if (token && typeof token === 'object' && token.type) {\n // Handle complex token objects\n switch (token.type) {\n case 'root': // $\n addRet(this._trace(x, val, path, null, null, callback, hasArrExpr));\n break;\n\n case 'property': {\n const propName = token.value;\n // Check if property exists (escaped flag just means it's not wildcard)\n if (val && Object.hasOwn(val, propName)) {\n addRet(this._trace(\n x, val[propName], push(path, propName), val, propName, callback,\n hasArrExpr, true\n ));\n }\n break;\n }\n\n case 'wildcard': // *\n this._walk(val, (m) => {\n addRet(this._trace(\n x, val[m], push(path, m), val, m, callback, true, true\n ));\n });\n break;\n\n case 'descent': // ..\n // Check remaining expression with val's immediate children\n addRet(\n this._trace(x, val, path, parent, parentPropName, callback,\n hasArrExpr)\n );\n this._walk(val, (m) => {\n // We don't join m and x here because we only want parents,\n // not scalar values\n if (typeof val[m] === 'object') {\n // Keep going with recursive descent on val's\n // object children\n addRet(this._trace(\n expr.slice(), val[m], push(path, m), val, m, callback, true\n ));\n }\n });\n break;\n\n case 'parent': // ^\n // This is not a final endpoint, so we do not invoke the callback here\n // Only allow parent selector if we're not already at root\n if (path.length > 1) {\n this._hasParentSelector = true;\n ret.push({\n path: path.slice(0, -1),\n expr: x,\n isParentSelector: true\n });\n }\n break;\n\n case 'propertyName': // ~\n retObj = {\n path: push(path, '~'),\n value: parentPropName,\n parent,\n parentProperty: null\n };\n this._handleCallback(retObj, callback, 'property');\n ret.push(retObj);\n break;\n\n case 'index': {\n const idx = token.value;\n if ((Array.isArray(val) && idx >= 0 && idx < val.length) ||\n (val && Object.hasOwn(val, idx))) {\n addRet(this._trace(\n x, val[idx], push(path, idx), val, idx, callback,\n hasArrExpr, true\n ));\n }\n break;\n }\n\n case 'slice':\n addRet(\n this._slice(token, x, val, path, parent, parentPropName, callback)\n );\n break;\n\n case 'filter': {\n if (this.currEval === false) {\n throw new Error('Eval [?(expr)] prevented in JSONPath expression.');\n }\n\n // Quick check: Does this filter have nested paths?\n const hasNesting = token.expression.includes('[?(');\n\n if (!hasNesting) {\n // Fast path: No nesting, skip extraction\n this._walk(val, (m) => {\n if (this._eval(token.expression, val[m], m, path,\n parent, parentPropName)) {\n addRet(this._trace(x, val[m], push(path, m), val, m,\n callback, true));\n }\n });\n } else {\n // Slow path: Extract and handle nested filters\n const {expression: modifiedExpr, nestedPaths} =\n this._extractNestedFilters(token.expression);\n\n // Check if expression is JUST a nested path (no other JavaScript)\n // If so, we need to check array length for truthiness\n const isSingleNestedPath = nestedPaths.length === 1 &&\n modifiedExpr.trim() === '_$_jp0';\n\n // Evaluate filter for each item\n this._walk(val, (m) => {\n // Evaluate nested paths in context of current item\n const nestedResults = {};\n for (const [i, nestedPath] of nestedPaths.entries()) {\n // Convert @ to $ for parsing (@ means current value)\n const pathForParsing = nestedPath.replace(/^@/u, '$');\n try {\n const nestedTokens = JSONPath.toPathParts(pathForParsing);\n // Evaluate nested path on current item\n const nestedResult = this._trace(\n nestedTokens,\n val[m],\n push(path, m),\n val,\n m,\n null, // no callback for nested evaluation\n true\n );\n // Extract values from result objects\n nestedResults[`_$_jp${i}`] =\n nestedResult.map((r) => r.value);\n } catch (e) {\n // If nested evaluation fails, treat as no matches\n nestedResults[`_$_jp${i}`] = [];\n }\n }\n\n // Add nested results to sandbox temporarily\n const originalSandbox = {...this.currSandbox};\n Object.assign(this.currSandbox, nestedResults);\n\n try {\n // For single nested path, check if array has elements\n // (empty arrays are truthy in JS but should be falsy in filter)\n const matches = isSingleNestedPath\n ? nestedResults._$_jp0.length > 0\n : this._eval(modifiedExpr, val[m], m, path,\n parent, parentPropName);\n\n if (matches) {\n addRet(this._trace(x, val[m], push(path, m), val, m,\n callback, true));\n }\n } finally {\n // Restore original sandbox (remove nested result placeholders)\n this.currSandbox = originalSandbox;\n }\n });\n }\n break;\n }\n\n case 'dynamic': {\n if (this.currEval === false) {\n throw new Error('Eval [(expr)] prevented in JSONPath expression.');\n }\n // As this will resolve to a property name (but we don't know it\n // yet), property and parent information is relative to the\n // parent of the property to which this expression will resolve\n addRet(this._trace(unshift(\n this._eval(\n token.expression, val, path.at(-1),\n path.slice(0, -1), parent, parentPropName\n ),\n x\n ), val, path, parent, parentPropName, callback, hasArrExpr));\n break;\n }\n\n case 'typeOperator': {\n let addType = false;\n const {valueType} = token;\n switch (valueType) {\n case 'scalar':\n if (!val || !(['object', 'function'].includes(typeof val))) {\n addType = true;\n }\n break;\n case 'boolean': case 'string': case 'undefined': case 'function':\n if (typeof val === valueType) {\n addType = true;\n }\n break;\n case 'integer':\n if (Number.isFinite(val) && !(val % 1)) {\n addType = true;\n }\n break;\n case 'number':\n if (Number.isFinite(val)) {\n addType = true;\n }\n break;\n case 'nonFinite':\n if (typeof val === 'number' && !Number.isFinite(val)) {\n addType = true;\n }\n break;\n case 'object':\n if (val && typeof val === valueType) {\n addType = true;\n }\n break;\n case 'array':\n if (Array.isArray(val)) {\n addType = true;\n }\n break;\n case 'other':\n addType = this.currOtherTypeCallback(\n val, path, parent, parentPropName\n );\n break;\n case 'null':\n if (val === null) {\n addType = true;\n }\n break;\n /* c8 ignore next 2 */\n default:\n throw new TypeError('Unknown value type ' + valueType);\n }\n if (addType) {\n retObj = {\n path, value: val, parent, parentProperty: parentPropName\n };\n this._handleCallback(retObj, callback, 'value');\n ret.push(retObj);\n }\n break;\n }\n\n case 'multiProperty': {\n const parts = token.properties;\n const escapedFlags = token.escaped || [];\n for (const [i, part] of parts.entries()) {\n // Check if part is a number (multi-index) or string (multi-property)\n let partToken;\n if (typeof part === 'number') {\n partToken = {type: 'index', value: part};\n } else {\n const isEscaped = escapedFlags[i] || false;\n partToken = {\n type: 'property',\n value: part,\n escaped: isEscaped\n };\n }\n addRet(this._trace(\n unshift(partToken, x), val, path, parent, parentPropName,\n callback, true\n ));\n }\n break;\n }\n }\n } else if ((typeof token !== 'string' || literalPriority) && val &&\n Object.hasOwn(val, token)\n ) { // simple case--directly follow property (for object tokens or with literalPriority)\n addRet(this._trace(x, val[token], push(path, token), val, token, callback,\n hasArrExpr));\n }\n // Note: Legacy string token handling removed - now handled by fast path above\n\n // We check the resulting values for parent selections. For parent\n // selections we discard the value object and continue the trace with the\n // current val object\n if (this._hasParentSelector) {\n for (let t = 0; t < ret.length; t++) {\n const rett = ret[t];\n if (rett && rett.isParentSelector) {\n // Navigate from root to the parent path to get correct parent context\n // rett.path is the path with last element removed (e.g., ['$', 'children'])\n let resultVal = this._json;\n let resultParent = null;\n let resultParentProp = null;\n\n // Navigate from root following the path\n // Start at index 1 to skip '$'\n for (let i = 1; i < rett.path.length; i++) {\n resultParent = resultVal;\n resultParentProp = rett.path[i];\n resultVal = resultVal[rett.path[i]];\n }\n\n const tmp = this._trace(\n rett.expr, resultVal, rett.path, resultParent,\n resultParentProp, callback, hasArrExpr\n );\n if (Array.isArray(tmp)) {\n ret[t] = tmp[0];\n const tl = tmp.length;\n for (let tt = 1; tt < tl; tt++) {\n // eslint-disable-next-line @stylistic/max-len -- Long\n // eslint-disable-next-line sonarjs/updated-loop-counter -- Convenient\n t++;\n ret.splice(t, 0, tmp[tt]);\n }\n } else {\n ret[t] = tmp;\n }\n }\n }\n }\n return ret;\n};\n\nJSONPath.prototype._walk = function (val, f) {\n if (Array.isArray(val)) {\n const n = val.length;\n for (let i = 0; i < n; i++) {\n f(i);\n }\n } else if (val && typeof val === 'object') {\n Object.keys(val).forEach((m) => {\n f(m);\n });\n }\n};\n\n/**\n * Extract nested JSONPath expressions from a filter expression.\n * @param {string} expr - Filter expression (e.g., \"@.children[?(@.price<10)]\")\n * @returns {{expression: string, nestedPaths: string[]}} Modified expression and extracted paths\n */\nJSONPath.prototype._extractNestedFilters = function (expr) {\n // Check cache first\n const cache = JSONPath.filterExtractionCache;\n if (cache[expr]) {\n // Return shallow clone to prevent mutation\n return {\n expression: cache[expr].expression,\n nestedPaths: [...cache[expr].nestedPaths]\n };\n }\n\n const nestedPaths = [];\n let result = expr;\n let placeholderCount = 0;\n\n // We need to find patterns like @.path[?(...)] or @[?(...)], etc.\n // Use a stack-based approach to handle nested brackets properly\n\n /**\n * Find the next JSONPath expression starting with @.\n * @param {string} str - String to search\n * @param {number} startPos - Position to start searching\n * @returns {{start: number, end: number, path: string} | null}\n */\n function findNextNestedPath (str, startPos) {\n let i = startPos;\n\n // Find next @ that's not in a string or regex literal\n while (i < str.length) {\n const ch = str[i];\n\n // Skip string literals\n if (ch === '\"' || ch === \"'\") {\n const quote = ch;\n i++;\n while (i < str.length) {\n if (str[i] === '\\\\' && i + 1 < str.length) {\n i += 2; // Skip escaped character\n } else if (str[i] === quote) {\n i++;\n break;\n } else {\n i++;\n }\n }\n continue;\n }\n\n // Skip regex literals (simplified detection)\n if (ch === '/' && i > 0) {\n // Check if this might be a regex (not division)\n // Look back for operators that could precede a regex\n const prevNonSpace = str.slice(0, i).trimEnd().slice(-1);\n if ('=([{,;:!&|?'.includes(prevNonSpace) || i === startPos) {\n i++;\n while (i < str.length) {\n if (str[i] === '\\\\' && i + 1 < str.length) {\n i += 2;\n } else if (str[i] === '/') {\n i++;\n // Skip regex flags\n while (i < str.length && (/[gimsuvy]/u).test(str[i])) {\n i++;\n }\n break;\n } else {\n i++;\n }\n }\n continue;\n }\n }\n\n // Found @ - check if it's followed by JSONPath syntax\n if (ch === '@') {\n const pathStart = i;\n i++; // Move past @\n\n // Check if there's path syntax after @\n // Could be: @.prop, @[, @.., @@\n if (i >= str.length) {\n return null;\n }\n\n let hasPathSyntax = false;\n let path = '@';\n\n // Parse the JSONPath expression\n while (i < str.length) {\n const c = str[i];\n\n // Path components\n if (c === '.' || c === '[' || c === '*' ||\n c === '^' || c === '~') {\n hasPathSyntax = true;\n path += c;\n i++;\n\n // Handle bracket notation with bracket matching\n if (c === '[') {\n let depth = 1;\n /* eslint-disable unicorn/prefer-switch --\n Complex bracket matching with nested quotes */\n while (i < str.length && depth > 0) {\n if (str[i] === '\\\\' && i + 1 < str.length) {\n path += str[i] + str[i + 1];\n i += 2;\n } else if (str[i] === '\"' || str[i] === \"'\") {\n // Handle quoted strings in brackets\n const q = str[i];\n path += str[i];\n i++;\n while (i < str.length && str[i] !== q) {\n if (str[i] === '\\\\' && i + 1 < str.length) {\n path += str[i] + str[i + 1];\n i += 2;\n } else {\n path += str[i];\n i++;\n }\n }\n if (i < str.length) {\n path += str[i];\n i++;\n }\n } else if (str[i] === '[') {\n depth++;\n path += str[i];\n i++;\n } else if (str[i] === ']') {\n depth--;\n path += str[i];\n i++;\n } else {\n path += str[i];\n i++;\n }\n }\n /* eslint-enable unicorn/prefer-switch --\n Re-enable after bracket matching section */\n }\n } else if ((/[\\w$]/u).test(c)) {\n // Property name characters\n hasPathSyntax = true;\n path += c;\n i++;\n } else {\n // End of path\n break;\n }\n }\n\n // Check if this path contains a filter (has [?(...)])\n // Only extract paths that have filters to avoid unnecessary evaluation\n if (hasPathSyntax && path.includes('[?')) {\n return {\n start: pathStart,\n end: i,\n path\n };\n }\n\n // No filter found, continue searching\n continue;\n }\n\n i++;\n }\n\n return null;\n }\n\n // Extract all nested paths\n let searchPos = 0;\n const replacements = [];\n\n while (searchPos < result.length) {\n const found = findNextNestedPath(result, searchPos);\n if (!found) {\n break;\n }\n\n // Store the replacement to be made\n replacements.push({\n start: found.start,\n end: found.end,\n path: found.path,\n placeholder: `_$_jp${placeholderCount}`\n });\n\n nestedPaths.push(found.path);\n placeholderCount++;\n searchPos = found.end;\n }\n\n // Apply replacements in reverse order to maintain positions\n for (let i = replacements.length - 1; i >= 0; i--) {\n const {start, end, placeholder} = replacements[i];\n result = result.slice(0, start) + placeholder + result.slice(end);\n }\n\n // Cache the result\n const extractionResult = {\n expression: result,\n nestedPaths\n };\n cache[expr] = extractionResult;\n\n return {\n expression: result,\n nestedPaths: [...nestedPaths]\n };\n};\n\nJSONPath.prototype._slice = function (\n token, expr, val, path, parent, parentPropName, callback\n) {\n if (!Array.isArray(val)) {\n return undefined;\n }\n const len = val.length;\n let start = token.start === null ? 0 : token.start;\n let end = token.end === null ? len : token.end;\n const step = token.step === null ? 1 : token.step;\n\n start = (start < 0) ? Math.max(0, start + len) : Math.min(len, start);\n end = (end < 0) ? Math.max(0, end + len) : Math.min(len, end);\n const ret = [];\n for (let i = start; i < end; i += step) {\n const tmp = this._trace(\n unshift(i, expr), val, path, parent, parentPropName, callback, true\n );\n // Should only be possible to be an array here since first part of\n // ``unshift(i, expr)` passed in above would not be empty, nor `~`,\n // nor begin with `@` (as could return objects)\n // This was causing excessive stack size in Node (with or\n // without Babel) against our performance test: `ret.push(...tmp);`\n tmp.forEach((t) => {\n ret.push(t);\n });\n }\n return ret;\n};\n\nJSONPath.prototype._eval = function (\n code, _v, _vname, path, parent, parentPropName\n) {\n this.currSandbox._$_parentProperty = parentPropName;\n this.currSandbox._$_parent = parent;\n this.currSandbox._$_property = _vname;\n this.currSandbox._$_root = this.json;\n this.currSandbox._$_v = _v;\n\n const containsPath = code.includes('@path');\n if (containsPath) {\n this.currSandbox._$_path = JSONPath.toPathString(path.concat([_vname]));\n }\n\n const scriptCacheKey = this.currEval + 'Script:' + code;\n if (!JSONPath.cache[scriptCacheKey]) {\n let script = code\n .replaceAll('@parentProperty', '_$_parentProperty')\n .replaceAll('@parent', '_$_parent')\n .replaceAll('@property', '_$_property')\n .replaceAll('@root', '_$_root')\n .replaceAll(/@([.\\s)[])/gu, '_$_v$1');\n if (containsPath) {\n script = script.replaceAll('@path', '_$_path');\n }\n if (\n this.currEval === 'safe' ||\n this.currEval === true ||\n this.currEval === undefined\n ) {\n JSONPath.cache[scriptCacheKey] = new this.safeVm.Script(script);\n } else if (this.currEval === 'native') {\n JSONPath.cache[scriptCacheKey] = new this.vm.Script(script);\n } else if (\n typeof this.currEval === 'function' &&\n this.currEval.prototype &&\n Object.hasOwn(this.currEval.prototype, 'runInNewContext')\n ) {\n const CurrEval = this.currEval;\n JSONPath.cache[scriptCacheKey] = new CurrEval(script);\n } else if (typeof this.currEval === 'function') {\n JSONPath.cache[scriptCacheKey] = {\n runInNewContext: (context) => this.currEval(script, context)\n };\n } else {\n throw new TypeError(`Unknown \"eval\" property \"${this.currEval}\"`);\n }\n }\n\n try {\n return JSONPath.cache[scriptCacheKey].runInNewContext(this.currSandbox);\n } catch (e) {\n if (this.ignoreEvalErrors) {\n return false;\n }\n throw new Error('jsonPath: ' + e.message + ': ' + code);\n }\n};\n\n// PUBLIC CLASS PROPERTIES AND METHODS\n\n// Could store the cache object itself\nJSONPath.cache = {};\nJSONPath.pathPartsCache = {};\nJSONPath.filterExtractionCache = {};\n\n/**\n * @param {string[]|object[]} pathArr Array to convert\n * @returns {string} The path string\n */\nJSONPath.toPathString = function (pathArr) {\n const x = pathArr, n = x.length;\n let p = '$';\n for (let i = 1; i < n; i++) {\n const item = x[i];\n\n // Handle both old string format and new token format\n if (typeof item === 'number') {\n // Array index\n p += '[' + item + ']';\n } else if (typeof item === 'string') {\n // Legacy path\n if (!(/^(~|\\^|@.*?\\(\\))$/u).test(item)) {\n p += (/^[0-9*]+$/u).test(item) ? ('[' + item + ']') : (\"['\" + item + \"']\");\n }\n } else if (item && typeof item === 'object') {\n // New token format\n switch (item.type) {\n case 'property':\n p += \"['\" + item.value + \"']\";\n break;\n case 'index':\n p += '[' + item.value + ']';\n break;\n case 'wildcard':\n p += '[*]';\n break;\n case 'slice':\n p += '[' + item.raw + ']';\n break;\n case 'filter':\n p += '[?(' + item.expression + ')]';\n break;\n case 'dynamic':\n p += '[(' + item.expression + ')]';\n break;\n case 'typeOperator':\n p += '@' + item.valueType + '()';\n break;\n case 'multiProperty':\n p += \"['\" + item.properties.join(\"','\") + \"']\";\n break;\n // Special operators don't add to path string\n case 'root':\n case 'descent':\n case 'parent':\n case 'propertyName':\n break;\n }\n }\n }\n return p;\n};\n\n/**\n * Converts path array to JSON Pointer format.\n * Handles both legacy string arrays and new token objects.\n * @param {string[]|object[]} pointer - Path array\n * @returns {string} JSON Pointer\n */\nJSONPath.toPointer = function (pointer) {\n const x = pointer, n = x.length;\n let p = '';\n for (let i = 1; i < n; i++) {\n const item = x[i];\n let value;\n\n // Handle different formats\n if (typeof item === 'number') {\n value = String(item);\n } else if (typeof item === 'string') {\n // Legacy string format or special operators\n if ((/^(~|\\^|@.*?\\(\\))$/u).test(item)) {\n continue; // Skip special operators\n }\n value = item;\n } else if (item && typeof item === 'object') {\n // New token format\n switch (item.type) {\n case 'property': {\n const {value: propValue} = item;\n value = propValue;\n break;\n }\n case 'index': {\n const {value: indexValue} = item;\n value = String(indexValue);\n break;\n }\n // Skip special operators\n case 'root':\n case 'wildcard':\n case 'descent':\n case 'parent':\n case 'propertyName':\n case 'filter':\n case 'dynamic':\n case 'slice':\n case 'typeOperator':\n case 'multiProperty':\n continue;\n default:\n continue;\n }\n } else {\n continue;\n }\n\n // Escape ~ and / per JSON Pointer spec\n p += '/' + value\n .replaceAll('~', '~0')\n .replaceAll('/', '~1');\n }\n return p;\n};\n\n\n/**\n * Parse a JSONPath expression into structured tokens.\n * @param {string} expr - JSONPath expression\n * @returns {Array} Array of tokens\n */\n/**\n * Parses a JSONPath expression into structured token objects.\n * @param {string} expr - JSONPath expression to parse\n * @returns {object[]} Array of token objects\n */\nJSONPath.toPathParts = function (expr) {\n const cache = JSONPath.pathPartsCache;\n if (cache[expr]) {\n // Shallow clone array, shallow clone object tokens\n // (tokens are simple objects with no nested objects)\n return cache[expr].map((token) => (\n typeof token === 'object' && token !== null ? {...token} : token\n ));\n }\n\n const tokens = [];\n let i = 0;\n\n // Handle empty path - treat as empty property access\n if (expr === '') {\n // Hybrid token: empty property is a string\n tokens.push('');\n cache[expr] = tokens;\n return cache[expr].map((token) => (\n typeof token === 'object' && token !== null ? {...token} : token\n ));\n }\n\n /**\n * Extract balanced content between delimiters.\n * @param {number} start - Starting position\n * @param {string} open - Opening delimiter\n * @param {string} close - Closing delimiter\n * @throws {SyntaxError} If delimiters are unbalanced\n * @returns {{content: string, end: number}} Extracted content and end position\n */\n function extractBalanced (start, open, close) {\n let depth = 1;\n let j = start;\n while (j < expr.length && depth > 0) {\n if (expr[j] === open) {\n depth++;\n } else if (expr[j] === close) {\n depth--;\n }\n j++;\n }\n if (depth !== 0) {\n throw new SyntaxError(\n `Unbalanced ${open}${close} in expression at position ${start}`\n );\n }\n return {content: expr.slice(start, j - 1), end: j};\n }\n\n /**\n * Extract quoted string.\n * @param {number} start - Starting position (after quote)\n * @param {string} quote - Quote character\n * @throws {SyntaxError} If string is unterminated\n * @returns {{content: string, end: number, escaped: boolean}} Extracted content, end position, and whether it's backtick-escaped\n */\n function extractQuoted (start, quote) {\n let j = start;\n let content = '';\n let escaped = false;\n\n while (j < expr.length) {\n if (expr[j] === '\\\\' && j + 1 < expr.length) {\n // Handle backslash escape sequences\n content += expr[j + 1];\n j += 2;\n } else if (expr[j] === '`' && j + 1 < expr.length) {\n // Handle backtick escape - backtick escapes next char\n content += expr[j + 1];\n escaped = true;\n j += 2;\n } else if (expr[j] === quote) {\n return {content, end: j + 1, escaped};\n } else {\n content += expr[j];\n j++;\n }\n }\n throw new SyntaxError(`Unterminated string at position ${start - 1}`);\n }\n\n /**\n * Handle dot notation (.property or ..descendant).\n * @throws {SyntaxError} If malformed\n * @returns {void}\n */\n function handleDotNotation () {\n if (i + 1 < expr.length && expr[i + 1] === '.') {\n // Descendant (..)\n tokens.push({type: 'descent'});\n i += 2;\n } else {\n // Skip the dot and parse property name\n i++;\n if (i >= expr.length) {\n throw new SyntaxError('Unexpected end after dot at position ' + (i - 1));\n }\n\n // Check what follows the dot\n switch (expr[i]) {\n case '*':\n tokens.push({type: 'wildcard'});\n i++;\n break;\n case '`':\n // Backtick escapes the next character\n i++; // Skip backtick\n if (i >= expr.length) {\n throw new SyntaxError(\n 'Unexpected end after backtick at position ' + (i - 1)\n );\n }\n // The escaped character becomes the property name\n tokens.push({\n type: 'property',\n value: expr[i],\n escaped: true\n });\n i++;\n break;\n case '[':\n // Dot followed by bracket: interpret as descent\n // e.g., $.[?(...)] becomes $ .. [?(...)]\n tokens.push({type: 'descent'});\n break;\n default: {\n // Regular property name (until next special char)\n let propName = '';\n while (i < expr.length && !(/[.[\\]^~@*]/u).test(expr[i])) {\n propName += expr[i];\n i++;\n }\n if (propName) {\n // Hybrid token: use string for unescaped properties\n tokens.push(propName);\n }\n }\n }\n }\n }\n\n /**\n * Handle bracket notation [...].\n * @throws {SyntaxError} If malformed\n * @returns {void}\n */\n function handleBracketNotation () {\n i++; // Skip [\n if (i >= expr.length) {\n throw new SyntaxError('Unexpected end after [ at position ' + (i - 1));\n }\n\n // Skip whitespace\n while (i < expr.length && (/\\s/u).test(expr[i])) {\n i++;\n }\n\n const ch = expr[i];\n\n // Wildcard [*]\n if (ch === '*') {\n i++;\n // Skip whitespace and closing bracket\n while (i < expr.length && (/\\s/u).test(expr[i])) {\n i++;\n }\n if (expr[i] !== ']') {\n throw new SyntaxError('Expected ] after * at position ' + i);\n }\n i++;\n tokens.push({type: 'wildcard'});\n return;\n }\n\n // Filter [?(expression)]\n if (ch === '?') {\n if (i + 1 >= expr.length || expr[i + 1] !== '(') {\n throw new SyntaxError(\n 'Expected ( after ? at position ' + i\n );\n }\n i += 2; // Skip ?(\n const result = extractBalanced(i, '(', ')');\n const {content: expression} = result;\n i = result.end;\n\n // Skip whitespace and closing bracket\n while (i < expr.length && (/\\s/u).test(expr[i])) {\n i++;\n }\n if (expr[i] !== ']') {\n throw new SyntaxError(\n 'Expected ] after filter at position ' + i\n );\n }\n i++;\n tokens.push({type: 'filter', expression});\n return;\n }\n\n // Dynamic [(expression)]\n if (ch === '(') {\n i++; // Skip (\n const result = extractBalanced(i, '(', ')');\n const {content: expression} = result;\n i = result.end;\n\n // Skip whitespace and closing bracket\n while (i < expr.length && (/\\s/u).test(expr[i])) {\n i++;\n }\n if (expr[i] !== ']') {\n throw new SyntaxError(\n 'Expected ] after dynamic expression at position ' + i\n );\n }\n i++;\n tokens.push({type: 'dynamic', expression});\n return;\n }\n\n // Quoted property ['name'] or [\"name\"]\n if (ch === \"'\" || ch === '\"') {\n const quote = ch;\n i++; // Skip opening quote\n const result = extractQuoted(i, quote);\n const {content, escaped} = result;\n i = result.end;\n\n // Skip whitespace\n while (i < expr.length && (/\\s/u).test(expr[i])) {\n i++;\n }\n\n // Check for comma (multi-property)\n if (expr[i] === ',') {\n const properties = [content];\n const escapedFlags = [escaped];\n while (expr[i] === ',') {\n i++; // Skip comma\n // Skip whitespace\n while (i < expr.length && (/\\s/u).test(expr[i])) {\n i++;\n }\n if (expr[i] !== \"'\" && expr[i] !== '\"') {\n throw new SyntaxError(\n 'Expected quoted property after comma at position ' + i\n );\n }\n const q = expr[i];\n i++;\n const r = extractQuoted(i, q);\n properties.push(r.content);\n escapedFlags.push(r.escaped);\n i = r.end;\n // Skip whitespace\n while (i < expr.length && (/\\s/u).test(expr[i])) {\n i++;\n }\n }\n if (expr[i] !== ']') {\n throw new SyntaxError(\n 'Expected ] after multi-property at position ' + i\n );\n }\n i++;\n tokens.push({\n type: 'multiProperty',\n properties,\n escaped: escapedFlags\n });\n return;\n }\n\n if (expr[i] !== ']') {\n throw new SyntaxError(\n 'Expected ] after quoted property at position ' + i\n );\n }\n i++;\n // Check if quoted property is wildcard\n if (content === '*' && !escaped) {\n tokens.push({type: 'wildcard'});\n } else if (escaped) {\n // Keep object for escaped properties (metadata needed)\n tokens.push({type: 'property', value: content, escaped: true});\n } else {\n // Hybrid token: use string for unescaped properties\n tokens.push(content);\n }\n return;\n }\n\n // Number (index, slice, or multi-index)\n if ((/[-\\d]/u).test(ch) || ch === ':') {\n let numStr = '';\n while (i < expr.length && (/[-\\d:]/u).test(expr[i])) {\n numStr += expr[i];\n i++;\n }\n\n // Skip whitespace\n while (i < expr.length && (/\\s/u).test(expr[i])) {\n i++;\n }\n\n // Check for comma (multi-index like [0,1,2])\n if (expr[i] === ',') {\n const indices = [Number.parseInt(numStr)];\n while (expr[i] === ',') {\n i++; // Skip comma\n // Skip whitespace\n while (i < expr.length && (/\\s/u).test(expr[i])) {\n i++;\n }\n // Read next number\n let nextNum = '';\n while (i < expr.length && (/[-\\d]/u).test(expr[i])) {\n nextNum += expr[i];\n i++;\n }\n indices.push(Number.parseInt(nextNum));\n // Skip whitespace\n while (i < expr.length && (/\\s/u).test(expr[i])) {\n i++;\n }\n }\n if (expr[i] !== ']') {\n throw new SyntaxError(\n 'Expected ] after multi-index at position ' + i\n );\n }\n i++;\n // Create multiProperty token with numeric properties\n tokens.push({type: 'multiProperty', properties: indices});\n return;\n }\n\n if (expr[i] !== ']') {\n throw new SyntaxError(\n 'Expected ] after number at position ' + i\n );\n }\n i++;\n\n // Check if it's a slice (contains :)\n if (numStr.includes(':')) {\n const parts = numStr.split(':');\n const start = parts[0] === ''\n ? null\n : Number.parseInt(parts[0]);\n const end = parts[1] === ''\n ? null\n : Number.parseInt(parts[1]);\n const step = parts.length > 2 && parts[2] !== ''\n ? Number.parseInt(parts[2])\n : null;\n tokens.push({type: 'slice', start, end, step, raw: numStr});\n } else {\n // Simple index - Hybrid token: use number directly\n const index = Number.parseInt(numStr);\n tokens.push(index);\n }\n return;\n }\n\n // Unquoted property (identifier)\n // In brackets, unquoted properties can have backtick escapes\n let propName = '';\n let escaped = false;\n while (i < expr.length && expr[i] !== ']' && expr[i] !== ',' &&\n !(/\\s/u).test(expr[i])) {\n if (expr[i] === '`' && i + 1 < expr.length &&\n expr[i + 1] !== ']' && expr[i + 1] !== ',') {\n // Backtick escapes next character\n propName += expr[i + 1];\n escaped = true;\n i += 2;\n } else {\n propName += expr[i];\n i++;\n }\n }\n\n // Skip whitespace\n while (i < expr.length && (/\\s/u).test(expr[i])) {\n i++;\n }\n\n // Check for comma (multi-property with unquoted names)\n if (expr[i] === ',') {\n const properties = [propName];\n const escapedFlags = [escaped];\n while (expr[i] === ',') {\n i++; // Skip comma\n // Skip whitespace\n while (i < expr.length && (/\\s/u).test(expr[i])) {\n i++;\n }\n let prop = '';\n let propEscaped = false;\n while (i < expr.length && expr[i] !== ']' && expr[i] !== ',' &&\n !(/\\s/u).test(expr[i])) {\n if (expr[i] === '`' && i + 1 < expr.length &&\n expr[i + 1] !== ']' && expr[i + 1] !== ',') {\n // Backtick escapes next character\n prop += expr[i + 1];\n propEscaped = true;\n i += 2;\n } else {\n prop += expr[i];\n i++;\n }\n }\n if (!prop) {\n throw new SyntaxError(\n 'Expected property name after comma at position ' + i\n );\n }\n properties.push(prop);\n escapedFlags.push(propEscaped);\n // Skip whitespace\n while (i < expr.length && (/\\s/u).test(expr[i])) {\n i++;\n }\n }\n if (expr[i] !== ']') {\n throw new SyntaxError(\n 'Expected ] after multi-property at position ' + i\n );\n }\n i++;\n tokens.push({\n type: 'multiProperty',\n properties,\n escaped: escapedFlags\n });\n return;\n }\n\n if (expr[i] !== ']') {\n throw new SyntaxError(\n 'Expected ] after property at position ' + i\n );\n }\n i++;\n if (propName) {\n if (escaped) {\n // Keep object for escaped properties\n tokens.push({type: 'property', value: propName, escaped: true});\n } else {\n // Hybrid token: use string for unescaped properties\n tokens.push(propName);\n }\n }\n }\n\n /**\n * Handle type operator `@type()`.\n * @throws {SyntaxError} If malformed\n * @returns {void}\n */\n function handleTypeOperator () {\n i++; // Skip @\n let typeName = '';\n while (i < expr.length && (/[a-z]/ui).test(expr[i])) {\n typeName += expr[i];\n i++;\n }\n if (i + 1 >= expr.length || expr[i] !== '(' || expr[i + 1] !== ')') {\n throw new SyntaxError(\n 'Expected () after @' + typeName + ' at position ' + i\n );\n }\n i += 2; // Skip ()\n tokens.push({type: 'typeOperator', valueType: typeName});\n }\n\n // If path doesn't start with $, [, or other special char, add implicit root\n if (expr.length > 0 && !['$', '[', '.', '^', '~', '@'].includes(expr[0])) {\n tokens.push({type: 'root'});\n // Prepend with a dot to make it valid for our parser\n expr = '.' + expr;\n }\n\n // Main parsing loop\n while (i < expr.length) {\n const ch = expr[i];\n\n switch (ch) {\n case '$':\n tokens.push({type: 'root'});\n i++;\n break;\n case '.':\n handleDotNotation();\n break;\n case '[':\n handleBracketNotation();\n break;\n case '*':\n // Wildcard (can appear after .. without a dot)\n tokens.push({type: 'wildcard'});\n i++;\n break;\n case '^':\n // If parent selector comes right after root (or at start),\n // add implicit empty string property\n // This handles cases like \"^\" or \"$^\" which should be \"['']^\"\n if (tokens.length === 0 ||\n (tokens.length === 1 && tokens[0].type === 'root')) {\n // Hybrid token: empty property is a string\n tokens.push('');\n }\n tokens.push({type: 'parent'});\n i++;\n break;\n case '~':\n tokens.push({type: 'propertyName'});\n i++;\n break;\n case '@':\n // Check if this is a type operator like @boolean()\n // Type operators have the pattern: @identifier()\n if ((/^@[a-z]+\\(\\)/ui).test(expr.slice(i))) {\n handleTypeOperator();\n } else {\n // Treat @ as part of a property name\n let propName = '';\n while (i < expr.length && (/[\\w$@\\\\]/u).test(expr[i])) {\n propName += expr[i];\n i++;\n }\n if (propName) {\n // Hybrid token: use string for unescaped properties\n tokens.push(propName);\n }\n }\n break;\n case ' ':\n case '\\t':\n case '\\n':\n case '\\r':\n // Skip whitespace\n i++;\n break;\n default:\n // Try to parse as identifier (property name)\n if ((/[\\w$]/u).test(ch)) {\n let propName = '';\n while (i < expr.length && (/[\\w$]/u).test(expr[i])) {\n propName += expr[i];\n i++;\n }\n // Hybrid token: use string for unescaped properties\n tokens.push(propName);\n } else {\n throw new SyntaxError(\n `Unexpected character '${ch}' at position ${i}`\n );\n }\n }\n }\n\n cache[expr] = tokens;\n return tokens.map((token) => (\n typeof token === 'object' && token !== null ? {...token} : token\n ));\n};\n\nJSONPath.prototype.safeVm = {\n Script: SafeScript\n};\n\nexport {JSONPath};\n","import {JSONPath} from './jsonpath.js';\n\n/**\n * @typedef {any} ContextItem\n */\n\n/**\n * @typedef {any} EvaluatedResult\n */\n\n/**\n * @callback ConditionCallback\n * @param {ContextItem} item\n * @returns {boolean}\n */\n\n/**\n * Copy items out of one array into another.\n * @param {GenericArray} source Array with items to copy\n * @param {GenericArray} target Array to which to copy\n * @param {ConditionCallback} conditionCb Callback passed the current item;\n * will move item if evaluates to `true`\n * @returns {void}\n */\nconst moveToAnotherArray = function (source, target, conditionCb) {\n const il = source.length;\n for (let i = 0; i < il; i++) {\n const item = source[i];\n if (conditionCb(item)) {\n // eslint-disable-next-line @stylistic/max-len -- Long\n // eslint-disable-next-line sonarjs/updated-loop-counter -- Convenient\n target.push(source.splice(i--, 1)[0]);\n }\n }\n};\n\n/**\n * In-browser replacement for NodeJS' VM.Script.\n */\nclass Script {\n /**\n * @param {string} expr Expression to evaluate\n */\n constructor (expr) {\n this.code = expr;\n }\n\n /**\n * @param {object} context Object whose items will be added\n * to evaluation\n * @returns {EvaluatedResult} Result of evaluated code\n */\n runInNewContext (context) {\n let expr = this.code;\n const keys = Object.keys(context);\n const funcs = [];\n moveToAnotherArray(keys, funcs, (key) => {\n return typeof context[key] === 'function';\n });\n const values = keys.map((vr) => {\n return context[vr];\n });\n\n const funcString = funcs.reduce((s, func) => {\n let fString = context[func].toString();\n if (!(/function/u).test(fString)) {\n fString = 'function ' + fString;\n }\n return 'var ' + func + '=' + fString + ';' + s;\n }, '');\n\n expr = funcString + expr;\n\n // Mitigate http://perfectionkills.com/global-eval-what-are-the-options/#new_function\n if (!(/(['\"])use strict\\1/u).test(expr) && !keys.includes('arguments')) {\n expr = 'var arguments = undefined;' + expr;\n }\n\n // Remove last semi so `return` will be inserted before\n // the previous one instead, allowing for the return\n // of a bare ending expression\n expr = expr.replace(/;\\s*$/u, '');\n\n // Insert `return`\n const lastStatementEnd = expr.lastIndexOf(';');\n const code =\n lastStatementEnd !== -1\n ? expr.slice(0, lastStatementEnd + 1) +\n ' return ' +\n expr.slice(lastStatementEnd + 1)\n : ' return ' + expr;\n\n // eslint-disable-next-line no-new-func -- User's choice\n return new Function(...keys, code)(...values);\n }\n}\n\nJSONPath.prototype.vm = {\n Script\n};\n\nexport {JSONPath};\n"],"names":["Jsep","version","toString","addUnaryOp","op_name","max_unop_len","Math","max","length","unary_ops","addBinaryOp","precedence","isRightAssociative","max_binop_len","binary_ops","right_associative","add","delete","addIdentifierChar","char","additional_identifier_chars","addLiteral","literal_name","literal_value","literals","removeUnaryOp","getMaxKeyLen","removeAllUnaryOps","removeIdentifierChar","removeBinaryOp","removeAllBinaryOps","removeLiteral","removeAllLiterals","this","expr","charAt","index","code","charCodeAt","constructor","parse","obj","Object","keys","map","k","isDecimalDigit","ch","binaryPrecedence","op_val","isIdentifierStart","String","fromCharCode","has","isIdentifierPart","throwError","message","error","Error","description","runHook","name","node","hooks","env","context","run","searchHook","find","callback","call","gobbleSpaces","SPACE_CODE","TAB_CODE","LF_CODE","CR_CODE","nodes","gobbleExpressions","type","COMPOUND","body","untilICode","ch_i","SEMCOL_CODE","COMMA_CODE","gobbleExpression","push","gobbleBinaryExpression","gobbleBinaryOp","to_check","substr","tc_len","hasOwnProperty","biop","prec","stack","biop_info","left","right","i","cur_biop","gobbleToken","value","right_a","comparePrev","prev","pop","BINARY_EXP","operator","PERIOD_CODE","gobbleNumericLiteral","SQUOTE_CODE","DQUOTE_CODE","gobbleStringLiteral","OBRACK_CODE","gobbleArray","argument","UNARY_EXP","prefix","gobbleIdentifier","LITERAL","raw","this_str","THIS_EXP","OPAREN_CODE","gobbleGroup","gobbleTokenProperty","QUMARK_CODE","optional","MEMBER_EXP","computed","object","property","CBRACK_CODE","CALL_EXP","arguments","gobbleArguments","CPAREN_CODE","callee","chCode","number","parseFloat","str","startIndex","quote","closed","substring","start","IDENTIFIER","slice","termination","args","separator_count","arg","SEQUENCE_EXP","expressions","ARRAY_EXP","elements","first","Array","isArray","forEach","assign","plugins","jsep","registered","register","plugin","init","COLON_CODE","Set","true","false","null","stdClassProps","getOwnPropertyNames","filter","prop","includes","undefined","m","ternary","test","consequent","alternate","newTest","patternIndex","inCharSet","pattern","flags","RegExp","e","assignmentOperators","updateOperators","assignmentPrecedence","updateNodeTypes","updateBinariesToAssignments","values","val","op","some","c","jsepRegex","jsepAssignment","BLOCKED_PROTO_PROPERTIES","SafeEval","evalAst","ast","subs","evalBinaryExpression","evalCompound","evalConditionalExpression","evalIdentifier","evalLiteral","evalMemberExpression","evalUnaryExpression","evalArrayExpression","evalCallExpression","evalAssignmentExpression","SyntaxError","||","a","b","&&","|","^","&","==","!=","===","!==","<",">","<=",">=","<<",">>",">>>","+","-","*","/","%","last","hasOwn","ReferenceError","TypeError","result","bind","typeof","void","el","func","Function","id","arr","item","unshift","NewError","super","avoidNew","JSONPath","opts","otherTypeCallback","optObj","json","path","resultType","flatten","wrap","sandbox","eval","ignoreEvalErrors","parent","parentProperty","autostart","ret","evaluate","prototype","currParent","currParentProperty","currResultType","currEval","currSandbox","currOtherTypeCallback","toPathString","exprList","toPathParts","shift","_hasParentSelector","_json","_trace","ea","isParentSelector","hasArrExpr","reduce","rslt","valOrPath","_getPreferredOutput","concat","pointer","toPointer","_handleCallback","fullRetObj","preferredOutput","parentPropName","literalPriority","retObj","token","x","addRet","elems","t","propName","_walk","idx","_slice","expression","modifiedExpr","nestedPaths","_extractNestedFilters","isSingleNestedPath","trim","nestedResults","nestedPath","entries","pathForParsing","replace","nestedTokens","nestedResult","r","originalSandbox","_$_jp0","_eval","at","addType","valueType","Number","isFinite","parts","properties","escapedFlags","escaped","part","partToken","rett","resultVal","resultParent","resultParentProp","tmp","tl","tt","splice","f","n","cache","filterExtractionCache","placeholderCount","findNextNestedPath","startPos","prevNonSpace","trimEnd","pathStart","hasPathSyntax","depth","q","end","searchPos","replacements","found","placeholder","extractionResult","len","step","min","_v","_vname","_$_parentProperty","_$_parent","_$_property","_$_root","_$_v","containsPath","_$_path","scriptCacheKey","script","replaceAll","safeVm","Script","vm","CurrEval","runInNewContext","pathPartsCache","pathArr","p","join","propValue","indexValue","tokens","extractBalanced","open","close","j","content","extractQuoted","handleDotNotation","handleBracketNotation","numStr","indices","parseInt","nextNum","split","propEscaped","handleTypeOperator","typeName","keyMap","create","funcs","source","target","conditionCb","il","moveToAnotherArray","key","vr","s","fString","lastStatementEnd","lastIndexOf"],"mappings":"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","x_google_ignoreList":[0,1,2]}
\ No newline at end of file
diff --git a/dist/index-node-cjs.cjs b/dist/index-node-cjs.cjs
index 698a5c3..a3c0553 100644
--- a/dist/index-node-cjs.cjs
+++ b/dist/index-node-cjs.cjs
@@ -1609,11 +1609,12 @@ JSONPath.prototype.evaluate = function (expr, json, callback, otherTypeCallback)
if (!expr && expr !== '' || !json) {
return undefined;
}
- const exprList = JSONPath.toPathArray(expr);
- if (exprList[0] === '$' && exprList.length > 1) {
+ const exprList = JSONPath.toPathParts(expr);
+ if (exprList[0] && exprList[0].type === 'root' && exprList.length > 1) {
exprList.shift();
}
this._hasParentSelector = null;
+ this._json = json; // Store root for parent selector navigation
const result = this._trace(exprList, json, ['$'], currParent, currParentProperty, callback).filter(function (ea) {
return ea && !ea.isParentSelector;
});
@@ -1641,7 +1642,7 @@ JSONPath.prototype._getPreferredOutput = function (ea) {
switch (resultType) {
case 'all':
{
- const path = Array.isArray(ea.path) ? ea.path : JSONPath.toPathArray(ea.path);
+ const path = Array.isArray(ea.path) ? ea.path : JSONPath.toPathParts(ea.path);
ea.pointer = JSONPath.toPointer(path);
ea.path = typeof ea.path === 'string' ? ea.path : JSONPath.toPathString(ea.path);
return ea;
@@ -1692,9 +1693,9 @@ JSONPath.prototype._trace = function (expr, val, path, parent, parentPropName, c
hasArrExpr
};
this._handleCallback(retObj, callback, 'value');
- return retObj;
+ return [retObj];
}
- const loc = expr[0],
+ const token = expr[0],
x = expr.slice(1);
// We need to gather the return value of recursive trace calls in order to
@@ -1717,168 +1718,266 @@ JSONPath.prototype._trace = function (expr, val, path, parent, parentPropName, c
ret.push(elems);
}
}
- if ((typeof loc !== 'string' || literalPriority) && val && Object.hasOwn(val, loc)) {
- // simple case--directly follow property
- addRet(this._trace(x, val[loc], push(path, loc), val, loc, callback, hasArrExpr));
- // eslint-disable-next-line unicorn/prefer-switch -- Part of larger `if`
- } else if (loc === '*') {
- // all child properties
- this._walk(val, m => {
- addRet(this._trace(x, val[m], push(path, m), val, m, callback, true, true));
- });
- } else if (loc === '..') {
- // all descendent parent properties
- // Check remaining expression with val's immediate children
- addRet(this._trace(x, val, path, parent, parentPropName, callback, hasArrExpr));
- this._walk(val, m => {
- // We don't join m and x here because we only want parents,
- // not scalar values
- if (typeof val[m] === 'object') {
- // Keep going with recursive descent on val's
- // object children
- addRet(this._trace(expr.slice(), val[m], push(path, m), val, m, callback, true));
- }
- });
- // The parent sel computation is handled in the frame above using the
- // ancestor object of val
- } else if (loc === '^') {
- // This is not a final endpoint, so we do not invoke the callback here
- this._hasParentSelector = true;
- return {
- path: path.slice(0, -1),
- expr: x,
- isParentSelector: true
- };
- } else if (loc === '~') {
- // property name
- retObj = {
- path: push(path, loc),
- value: parentPropName,
- parent,
- parentProperty: null
- };
- this._handleCallback(retObj, callback, 'property');
- return retObj;
- } else if (loc === '$') {
- // root only
- addRet(this._trace(x, val, path, null, null, callback, hasArrExpr));
- } else if (/^(-?\d*):(-?\d*):?(\d*)$/u.test(loc)) {
- // [start:end:step] Python slice syntax
- addRet(this._slice(loc, x, val, path, parent, parentPropName, callback));
- } else if (loc.indexOf('?(') === 0) {
- // [?(expr)] (filtering)
- if (this.currEval === false) {
- throw new Error('Eval [?(expr)] prevented in JSONPath expression.');
- }
- const safeLoc = loc.replace(/^\?\((.*?)\)$/u, '$1');
- // check for a nested filter expression
- const nested = /@.?([^?]*)[['](\??\(.*?\))(?!.\)\])[\]']/gu.exec(safeLoc);
- if (nested) {
- // find if there are matches in the nested expression
- // add them to the result set if there is at least one match
- this._walk(val, m => {
- const npath = [nested[2]];
- const nvalue = nested[1] ? val[m][nested[1]] : val[m];
- const filterResults = this._trace(npath, nvalue, path, parent, parentPropName, callback, true);
- if (filterResults.length > 0) {
- addRet(this._trace(x, val[m], push(path, m), val, m, callback, true));
- }
- });
- } else {
- this._walk(val, m => {
- if (this._eval(safeLoc, val[m], m, path, parent, parentPropName)) {
- addRet(this._trace(x, val[m], push(path, m), val, m, callback, true));
- }
- });
+
+ // Fast path for primitive tokens (strings and numbers)
+ if (typeof token === 'string') {
+ // Simple property access
+ if (val && Object.hasOwn(val, token)) {
+ addRet(this._trace(x, val[token], push(path, token), val, token, callback, hasArrExpr));
}
- } else if (loc[0] === '(') {
- // [(expr)] (dynamic property/index)
- if (this.currEval === false) {
- throw new Error('Eval [(expr)] prevented in JSONPath expression.');
- }
- // As this will resolve to a property name (but we don't know it
- // yet), property and parent information is relative to the
- // parent of the property to which this expression will resolve
- addRet(this._trace(unshift(this._eval(loc, val, path.at(-1), path.slice(0, -1), parent, parentPropName), x), val, path, parent, parentPropName, callback, hasArrExpr));
- } else if (loc[0] === '@') {
- // value type: @boolean(), etc.
- let addType = false;
- const valueType = loc.slice(1, -2);
- switch (valueType) {
- case 'scalar':
- if (!val || !['object', 'function'].includes(typeof val)) {
- addType = true;
- }
+ } else if (typeof token === 'number') {
+ // Simple numeric index access
+ if (Array.isArray(val) && token >= 0 && token < val.length) {
+ addRet(this._trace(x, val[token], push(path, token), val, token, callback, hasArrExpr));
+ }
+ } else if (token && typeof token === 'object' && token.type) {
+ // Handle complex token objects
+ switch (token.type) {
+ case 'root':
+ // $
+ addRet(this._trace(x, val, path, null, null, callback, hasArrExpr));
break;
- case 'boolean':
- case 'string':
- case 'undefined':
- case 'function':
- if (typeof val === valueType) {
- addType = true;
+ case 'property':
+ {
+ const propName = token.value;
+ // Check if property exists (escaped flag just means it's not wildcard)
+ if (val && Object.hasOwn(val, propName)) {
+ addRet(this._trace(x, val[propName], push(path, propName), val, propName, callback, hasArrExpr, true));
+ }
+ break;
}
+ case 'wildcard':
+ // *
+ this._walk(val, m => {
+ addRet(this._trace(x, val[m], push(path, m), val, m, callback, true, true));
+ });
break;
- case 'integer':
- if (Number.isFinite(val) && !(val % 1)) {
- addType = true;
- }
+ case 'descent':
+ // ..
+ // Check remaining expression with val's immediate children
+ addRet(this._trace(x, val, path, parent, parentPropName, callback, hasArrExpr));
+ this._walk(val, m => {
+ // We don't join m and x here because we only want parents,
+ // not scalar values
+ if (typeof val[m] === 'object') {
+ // Keep going with recursive descent on val's
+ // object children
+ addRet(this._trace(expr.slice(), val[m], push(path, m), val, m, callback, true));
+ }
+ });
break;
- case 'number':
- if (Number.isFinite(val)) {
- addType = true;
+ case 'parent':
+ // ^
+ // This is not a final endpoint, so we do not invoke the callback here
+ // Only allow parent selector if we're not already at root
+ if (path.length > 1) {
+ this._hasParentSelector = true;
+ ret.push({
+ path: path.slice(0, -1),
+ expr: x,
+ isParentSelector: true
+ });
}
break;
- case 'nonFinite':
- if (typeof val === 'number' && !Number.isFinite(val)) {
- addType = true;
- }
+ case 'propertyName':
+ // ~
+ retObj = {
+ path: push(path, '~'),
+ value: parentPropName,
+ parent,
+ parentProperty: null
+ };
+ this._handleCallback(retObj, callback, 'property');
+ ret.push(retObj);
break;
- case 'object':
- if (val && typeof val === valueType) {
- addType = true;
+ case 'index':
+ {
+ const idx = token.value;
+ if (Array.isArray(val) && idx >= 0 && idx < val.length || val && Object.hasOwn(val, idx)) {
+ addRet(this._trace(x, val[idx], push(path, idx), val, idx, callback, hasArrExpr, true));
+ }
+ break;
}
+ case 'slice':
+ addRet(this._slice(token, x, val, path, parent, parentPropName, callback));
break;
- case 'array':
- if (Array.isArray(val)) {
- addType = true;
+ case 'filter':
+ {
+ if (this.currEval === false) {
+ throw new Error('Eval [?(expr)] prevented in JSONPath expression.');
+ }
+
+ // Quick check: Does this filter have nested paths?
+ const hasNesting = token.expression.includes('[?(');
+ if (!hasNesting) {
+ // Fast path: No nesting, skip extraction
+ this._walk(val, m => {
+ if (this._eval(token.expression, val[m], m, path, parent, parentPropName)) {
+ addRet(this._trace(x, val[m], push(path, m), val, m, callback, true));
+ }
+ });
+ } else {
+ // Slow path: Extract and handle nested filters
+ const {
+ expression: modifiedExpr,
+ nestedPaths
+ } = this._extractNestedFilters(token.expression);
+
+ // Check if expression is JUST a nested path (no other JavaScript)
+ // If so, we need to check array length for truthiness
+ const isSingleNestedPath = nestedPaths.length === 1 && modifiedExpr.trim() === '_$_jp0';
+
+ // Evaluate filter for each item
+ this._walk(val, m => {
+ // Evaluate nested paths in context of current item
+ const nestedResults = {};
+ for (const [i, nestedPath] of nestedPaths.entries()) {
+ // Convert @ to $ for parsing (@ means current value)
+ const pathForParsing = nestedPath.replace(/^@/u, '$');
+ try {
+ const nestedTokens = JSONPath.toPathParts(pathForParsing);
+ // Evaluate nested path on current item
+ const nestedResult = this._trace(nestedTokens, val[m], push(path, m), val, m, null,
+ // no callback for nested evaluation
+ true);
+ // Extract values from result objects
+ nestedResults[`_$_jp${i}`] = nestedResult.map(r => r.value);
+ } catch (e) {
+ // If nested evaluation fails, treat as no matches
+ nestedResults[`_$_jp${i}`] = [];
+ }
+ }
+
+ // Add nested results to sandbox temporarily
+ const originalSandbox = {
+ ...this.currSandbox
+ };
+ Object.assign(this.currSandbox, nestedResults);
+ try {
+ // For single nested path, check if array has elements
+ // (empty arrays are truthy in JS but should be falsy in filter)
+ const matches = isSingleNestedPath ? nestedResults._$_jp0.length > 0 : this._eval(modifiedExpr, val[m], m, path, parent, parentPropName);
+ if (matches) {
+ addRet(this._trace(x, val[m], push(path, m), val, m, callback, true));
+ }
+ } finally {
+ // Restore original sandbox (remove nested result placeholders)
+ this.currSandbox = originalSandbox;
+ }
+ });
+ }
+ break;
}
- break;
- case 'other':
- addType = this.currOtherTypeCallback(val, path, parent, parentPropName);
- break;
- case 'null':
- if (val === null) {
- addType = true;
+ case 'dynamic':
+ {
+ if (this.currEval === false) {
+ throw new Error('Eval [(expr)] prevented in JSONPath expression.');
+ }
+ // As this will resolve to a property name (but we don't know it
+ // yet), property and parent information is relative to the
+ // parent of the property to which this expression will resolve
+ addRet(this._trace(unshift(this._eval(token.expression, val, path.at(-1), path.slice(0, -1), parent, parentPropName), x), val, path, parent, parentPropName, callback, hasArrExpr));
+ break;
+ }
+ case 'typeOperator':
+ {
+ let addType = false;
+ const {
+ valueType
+ } = token;
+ switch (valueType) {
+ case 'scalar':
+ if (!val || !['object', 'function'].includes(typeof val)) {
+ addType = true;
+ }
+ break;
+ case 'boolean':
+ case 'string':
+ case 'undefined':
+ case 'function':
+ if (typeof val === valueType) {
+ addType = true;
+ }
+ break;
+ case 'integer':
+ if (Number.isFinite(val) && !(val % 1)) {
+ addType = true;
+ }
+ break;
+ case 'number':
+ if (Number.isFinite(val)) {
+ addType = true;
+ }
+ break;
+ case 'nonFinite':
+ if (typeof val === 'number' && !Number.isFinite(val)) {
+ addType = true;
+ }
+ break;
+ case 'object':
+ if (val && typeof val === valueType) {
+ addType = true;
+ }
+ break;
+ case 'array':
+ if (Array.isArray(val)) {
+ addType = true;
+ }
+ break;
+ case 'other':
+ addType = this.currOtherTypeCallback(val, path, parent, parentPropName);
+ break;
+ case 'null':
+ if (val === null) {
+ addType = true;
+ }
+ break;
+ /* c8 ignore next 2 */
+ default:
+ throw new TypeError('Unknown value type ' + valueType);
+ }
+ if (addType) {
+ retObj = {
+ path,
+ value: val,
+ parent,
+ parentProperty: parentPropName
+ };
+ this._handleCallback(retObj, callback, 'value');
+ ret.push(retObj);
+ }
+ break;
+ }
+ case 'multiProperty':
+ {
+ const parts = token.properties;
+ const escapedFlags = token.escaped || [];
+ for (const [i, part] of parts.entries()) {
+ // Check if part is a number (multi-index) or string (multi-property)
+ let partToken;
+ if (typeof part === 'number') {
+ partToken = {
+ type: 'index',
+ value: part
+ };
+ } else {
+ const isEscaped = escapedFlags[i] || false;
+ partToken = {
+ type: 'property',
+ value: part,
+ escaped: isEscaped
+ };
+ }
+ addRet(this._trace(unshift(partToken, x), val, path, parent, parentPropName, callback, true));
+ }
+ break;
}
- break;
- /* c8 ignore next 2 */
- default:
- throw new TypeError('Unknown value type ' + valueType);
- }
- if (addType) {
- retObj = {
- path,
- value: val,
- parent,
- parentProperty: parentPropName
- };
- this._handleCallback(retObj, callback, 'value');
- return retObj;
- }
- // `-escaped property
- } else if (loc[0] === '`' && val && Object.hasOwn(val, loc.slice(1))) {
- const locProp = loc.slice(1);
- addRet(this._trace(x, val[locProp], push(path, locProp), val, locProp, callback, hasArrExpr, true));
- } else if (loc.includes(',')) {
- // [name1,name2,...]
- const parts = loc.split(',');
- for (const part of parts) {
- addRet(this._trace(unshift(part, x), val, path, parent, parentPropName, callback, true));
}
- // simple case--directly follow property
- } else if (!literalPriority && val && Object.hasOwn(val, loc)) {
- addRet(this._trace(x, val[loc], push(path, loc), val, loc, callback, hasArrExpr, true));
+ } else if ((typeof token !== 'string' || literalPriority) && val && Object.hasOwn(val, token)) {
+ // simple case--directly follow property (for object tokens or with literalPriority)
+ addRet(this._trace(x, val[token], push(path, token), val, token, callback, hasArrExpr));
}
+ // Note: Legacy string token handling removed - now handled by fast path above
// We check the resulting values for parent selections. For parent
// selections we discard the value object and continue the trace with the
@@ -1887,7 +1986,20 @@ JSONPath.prototype._trace = function (expr, val, path, parent, parentPropName, c
for (let t = 0; t < ret.length; t++) {
const rett = ret[t];
if (rett && rett.isParentSelector) {
- const tmp = this._trace(rett.expr, val, rett.path, parent, parentPropName, callback, hasArrExpr);
+ // Navigate from root to the parent path to get correct parent context
+ // rett.path is the path with last element removed (e.g., ['$', 'children'])
+ let resultVal = this._json;
+ let resultParent = null;
+ let resultParentProp = null;
+
+ // Navigate from root following the path
+ // Start at index 1 to skip '$'
+ for (let i = 1; i < rett.path.length; i++) {
+ resultParent = resultVal;
+ resultParentProp = rett.path[i];
+ resultVal = resultVal[rett.path[i]];
+ }
+ const tmp = this._trace(rett.expr, resultVal, rett.path, resultParent, resultParentProp, callback, hasArrExpr);
if (Array.isArray(tmp)) {
ret[t] = tmp[0];
const tl = tmp.length;
@@ -1917,15 +2029,229 @@ JSONPath.prototype._walk = function (val, f) {
});
}
};
-JSONPath.prototype._slice = function (loc, expr, val, path, parent, parentPropName, callback) {
+
+/**
+ * Extract nested JSONPath expressions from a filter expression.
+ * @param {string} expr - Filter expression (e.g., "@.children[?(@.price<10)]")
+ * @returns {{expression: string, nestedPaths: string[]}} Modified expression and extracted paths
+ */
+JSONPath.prototype._extractNestedFilters = function (expr) {
+ // Check cache first
+ const cache = JSONPath.filterExtractionCache;
+ if (cache[expr]) {
+ // Return shallow clone to prevent mutation
+ return {
+ expression: cache[expr].expression,
+ nestedPaths: [...cache[expr].nestedPaths]
+ };
+ }
+ const nestedPaths = [];
+ let result = expr;
+ let placeholderCount = 0;
+
+ // We need to find patterns like @.path[?(...)] or @[?(...)], etc.
+ // Use a stack-based approach to handle nested brackets properly
+
+ /**
+ * Find the next JSONPath expression starting with @.
+ * @param {string} str - String to search
+ * @param {number} startPos - Position to start searching
+ * @returns {{start: number, end: number, path: string} | null}
+ */
+ function findNextNestedPath(str, startPos) {
+ let i = startPos;
+
+ // Find next @ that's not in a string or regex literal
+ while (i < str.length) {
+ const ch = str[i];
+
+ // Skip string literals
+ if (ch === '"' || ch === "'") {
+ const quote = ch;
+ i++;
+ while (i < str.length) {
+ if (str[i] === '\\' && i + 1 < str.length) {
+ i += 2; // Skip escaped character
+ } else if (str[i] === quote) {
+ i++;
+ break;
+ } else {
+ i++;
+ }
+ }
+ continue;
+ }
+
+ // Skip regex literals (simplified detection)
+ if (ch === '/' && i > 0) {
+ // Check if this might be a regex (not division)
+ // Look back for operators that could precede a regex
+ const prevNonSpace = str.slice(0, i).trimEnd().slice(-1);
+ if ('=([{,;:!&|?'.includes(prevNonSpace) || i === startPos) {
+ i++;
+ while (i < str.length) {
+ if (str[i] === '\\' && i + 1 < str.length) {
+ i += 2;
+ } else if (str[i] === '/') {
+ i++;
+ // Skip regex flags
+ while (i < str.length && /[gimsuvy]/u.test(str[i])) {
+ i++;
+ }
+ break;
+ } else {
+ i++;
+ }
+ }
+ continue;
+ }
+ }
+
+ // Found @ - check if it's followed by JSONPath syntax
+ if (ch === '@') {
+ const pathStart = i;
+ i++; // Move past @
+
+ // Check if there's path syntax after @
+ // Could be: @.prop, @[, @.., @@
+ if (i >= str.length) {
+ return null;
+ }
+ let hasPathSyntax = false;
+ let path = '@';
+
+ // Parse the JSONPath expression
+ while (i < str.length) {
+ const c = str[i];
+
+ // Path components
+ if (c === '.' || c === '[' || c === '*' || c === '^' || c === '~') {
+ hasPathSyntax = true;
+ path += c;
+ i++;
+
+ // Handle bracket notation with bracket matching
+ if (c === '[') {
+ let depth = 1;
+ /* eslint-disable unicorn/prefer-switch --
+ Complex bracket matching with nested quotes */
+ while (i < str.length && depth > 0) {
+ if (str[i] === '\\' && i + 1 < str.length) {
+ path += str[i] + str[i + 1];
+ i += 2;
+ } else if (str[i] === '"' || str[i] === "'") {
+ // Handle quoted strings in brackets
+ const q = str[i];
+ path += str[i];
+ i++;
+ while (i < str.length && str[i] !== q) {
+ if (str[i] === '\\' && i + 1 < str.length) {
+ path += str[i] + str[i + 1];
+ i += 2;
+ } else {
+ path += str[i];
+ i++;
+ }
+ }
+ if (i < str.length) {
+ path += str[i];
+ i++;
+ }
+ } else if (str[i] === '[') {
+ depth++;
+ path += str[i];
+ i++;
+ } else if (str[i] === ']') {
+ depth--;
+ path += str[i];
+ i++;
+ } else {
+ path += str[i];
+ i++;
+ }
+ }
+ /* eslint-enable unicorn/prefer-switch --
+ Re-enable after bracket matching section */
+ }
+ } else if (/[\w$]/u.test(c)) {
+ // Property name characters
+ hasPathSyntax = true;
+ path += c;
+ i++;
+ } else {
+ // End of path
+ break;
+ }
+ }
+
+ // Check if this path contains a filter (has [?(...)])
+ // Only extract paths that have filters to avoid unnecessary evaluation
+ if (hasPathSyntax && path.includes('[?')) {
+ return {
+ start: pathStart,
+ end: i,
+ path
+ };
+ }
+
+ // No filter found, continue searching
+ continue;
+ }
+ i++;
+ }
+ return null;
+ }
+
+ // Extract all nested paths
+ let searchPos = 0;
+ const replacements = [];
+ while (searchPos < result.length) {
+ const found = findNextNestedPath(result, searchPos);
+ if (!found) {
+ break;
+ }
+
+ // Store the replacement to be made
+ replacements.push({
+ start: found.start,
+ end: found.end,
+ path: found.path,
+ placeholder: `_$_jp${placeholderCount}`
+ });
+ nestedPaths.push(found.path);
+ placeholderCount++;
+ searchPos = found.end;
+ }
+
+ // Apply replacements in reverse order to maintain positions
+ for (let i = replacements.length - 1; i >= 0; i--) {
+ const {
+ start,
+ end,
+ placeholder
+ } = replacements[i];
+ result = result.slice(0, start) + placeholder + result.slice(end);
+ }
+
+ // Cache the result
+ const extractionResult = {
+ expression: result,
+ nestedPaths
+ };
+ cache[expr] = extractionResult;
+ return {
+ expression: result,
+ nestedPaths: [...nestedPaths]
+ };
+};
+JSONPath.prototype._slice = function (token, expr, val, path, parent, parentPropName, callback) {
if (!Array.isArray(val)) {
return undefined;
}
- const len = val.length,
- parts = loc.split(':'),
- step = parts[2] && Number.parseInt(parts[2]) || 1;
- let start = parts[0] && Number.parseInt(parts[0]) || 0,
- end = parts[1] && Number.parseInt(parts[1]) || len;
+ const len = val.length;
+ let start = token.start === null ? 0 : token.start;
+ let end = token.end === null ? len : token.end;
+ const step = token.step === null ? 1 : token.step;
start = start < 0 ? Math.max(0, start + len) : Math.min(len, start);
end = end < 0 ? Math.max(0, end + len) : Math.min(len, end);
const ret = [];
@@ -1987,9 +2313,11 @@ JSONPath.prototype._eval = function (code, _v, _vname, path, parent, parentPropN
// Could store the cache object itself
JSONPath.cache = {};
+JSONPath.pathPartsCache = {};
+JSONPath.filterExtractionCache = {};
/**
- * @param {string[]} pathArr Array to convert
+ * @param {string[]|object[]} pathArr Array to convert
* @returns {string} The path string
*/
JSONPath.toPathString = function (pathArr) {
@@ -1997,15 +2325,54 @@ JSONPath.toPathString = function (pathArr) {
n = x.length;
let p = '$';
for (let i = 1; i < n; i++) {
- if (!/^(~|\^|@.*?\(\))$/u.test(x[i])) {
- p += /^[0-9*]+$/u.test(x[i]) ? '[' + x[i] + ']' : "['" + x[i] + "']";
+ const item = x[i];
+
+ // Handle both old string format and new token format
+ if (typeof item === 'number') {
+ // Array index
+ p += '[' + item + ']';
+ } else if (typeof item === 'string') {
+ // Legacy path
+ if (!/^(~|\^|@.*?\(\))$/u.test(item)) {
+ p += /^[0-9*]+$/u.test(item) ? '[' + item + ']' : "['" + item + "']";
+ }
+ } else if (item && typeof item === 'object') {
+ // New token format
+ switch (item.type) {
+ case 'property':
+ p += "['" + item.value + "']";
+ break;
+ case 'index':
+ p += '[' + item.value + ']';
+ break;
+ case 'wildcard':
+ p += '[*]';
+ break;
+ case 'slice':
+ p += '[' + item.raw + ']';
+ break;
+ case 'filter':
+ p += '[?(' + item.expression + ')]';
+ break;
+ case 'dynamic':
+ p += '[(' + item.expression + ')]';
+ break;
+ case 'typeOperator':
+ p += '@' + item.valueType + '()';
+ break;
+ case 'multiProperty':
+ p += "['" + item.properties.join("','") + "']";
+ break;
+ }
}
}
return p;
};
/**
- * @param {string} pointer JSON Path
+ * Converts path array to JSON Pointer format.
+ * Handles both legacy string arrays and new token objects.
+ * @param {string[]|object[]} pointer - Path array
* @returns {string} JSON Pointer
*/
JSONPath.toPointer = function (pointer) {
@@ -2013,59 +2380,653 @@ JSONPath.toPointer = function (pointer) {
n = x.length;
let p = '';
for (let i = 1; i < n; i++) {
- if (!/^(~|\^|@.*?\(\))$/u.test(x[i])) {
- p += '/' + x[i].toString().replaceAll('~', '~0').replaceAll('/', '~1');
+ const item = x[i];
+ let value;
+
+ // Handle different formats
+ if (typeof item === 'number') {
+ value = String(item);
+ } else if (typeof item === 'string') {
+ // Legacy string format or special operators
+ if (/^(~|\^|@.*?\(\))$/u.test(item)) {
+ continue; // Skip special operators
+ }
+ value = item;
+ } else if (item && typeof item === 'object') {
+ // New token format
+ switch (item.type) {
+ case 'property':
+ {
+ const {
+ value: propValue
+ } = item;
+ value = propValue;
+ break;
+ }
+ case 'index':
+ {
+ const {
+ value: indexValue
+ } = item;
+ value = String(indexValue);
+ break;
+ }
+ // Skip special operators
+ case 'root':
+ case 'wildcard':
+ case 'descent':
+ case 'parent':
+ case 'propertyName':
+ case 'filter':
+ case 'dynamic':
+ case 'slice':
+ case 'typeOperator':
+ case 'multiProperty':
+ continue;
+ default:
+ continue;
+ }
+ } else {
+ continue;
}
+
+ // Escape ~ and / per JSON Pointer spec
+ p += '/' + value.replaceAll('~', '~0').replaceAll('/', '~1');
}
return p;
};
/**
- * @param {string} expr Expression to convert
- * @returns {string[]}
+ * Parse a JSONPath expression into structured tokens.
+ * @param {string} expr - JSONPath expression
+ * @returns {Array} Array of tokens
*/
-JSONPath.toPathArray = function (expr) {
- const {
- cache
- } = JSONPath;
+/**
+ * Parses a JSONPath expression into structured token objects.
+ * @param {string} expr - JSONPath expression to parse
+ * @returns {object[]} Array of token objects
+ */
+JSONPath.toPathParts = function (expr) {
+ const cache = JSONPath.pathPartsCache;
if (cache[expr]) {
- return cache[expr].concat();
- }
- const subx = [];
- const normalized = expr
- // Properties
- .replaceAll(/@(?:null|boolean|number|string|integer|undefined|nonFinite|scalar|array|object|function|other)\(\)/gu, ';$&;')
- // Parenthetical evaluations (filtering and otherwise), directly
- // within brackets or single quotes
- .replaceAll(/[['](\??\(.*?\))[\]'](?!.\])/gu, function ($0, $1) {
- return '[#' + (subx.push($1) - 1) + ']';
- })
- // Escape periods and tildes within properties
- .replaceAll(/\[['"]([^'\]]*)['"]\]/gu, function ($0, prop) {
- return "['" + prop.replaceAll('.', '%@%').replaceAll('~', '%%@@%%') + "']";
- })
- // Properties operator
- .replaceAll('~', ';~;')
- // Split by property boundaries
- .replaceAll(/['"]?\.['"]?(?![^[]*\])|\[['"]?/gu, ';')
- // Reinsert periods within properties
- .replaceAll('%@%', '.')
- // Reinsert tildes within properties
- .replaceAll('%%@@%%', '~')
- // Parent
- .replaceAll(/(?:;)?(\^+)(?:;)?/gu, function ($0, ups) {
- return ';' + ups.split('').join(';') + ';';
- })
- // Descendents
- .replaceAll(/;;;|;;/gu, ';..;')
- // Remove trailing
- .replaceAll(/;$|'?\]|'$/gu, '');
- const exprList = normalized.split(';').map(function (exp) {
- const match = exp.match(/#(\d+)/u);
- return !match || !match[1] ? exp : subx[match[1]];
- });
- cache[expr] = exprList;
- return cache[expr].concat();
+ // Shallow clone array, shallow clone object tokens
+ // (tokens are simple objects with no nested objects)
+ return cache[expr].map(token => typeof token === 'object' && token !== null ? {
+ ...token
+ } : token);
+ }
+ const tokens = [];
+ let i = 0;
+
+ // Handle empty path - treat as empty property access
+ if (expr === '') {
+ // Hybrid token: empty property is a string
+ tokens.push('');
+ cache[expr] = tokens;
+ return cache[expr].map(token => typeof token === 'object' && token !== null ? {
+ ...token
+ } : token);
+ }
+
+ /**
+ * Extract balanced content between delimiters.
+ * @param {number} start - Starting position
+ * @param {string} open - Opening delimiter
+ * @param {string} close - Closing delimiter
+ * @throws {SyntaxError} If delimiters are unbalanced
+ * @returns {{content: string, end: number}} Extracted content and end position
+ */
+ function extractBalanced(start, open, close) {
+ let depth = 1;
+ let j = start;
+ while (j < expr.length && depth > 0) {
+ if (expr[j] === open) {
+ depth++;
+ } else if (expr[j] === close) {
+ depth--;
+ }
+ j++;
+ }
+ if (depth !== 0) {
+ throw new SyntaxError(`Unbalanced ${open}${close} in expression at position ${start}`);
+ }
+ return {
+ content: expr.slice(start, j - 1),
+ end: j
+ };
+ }
+
+ /**
+ * Extract quoted string.
+ * @param {number} start - Starting position (after quote)
+ * @param {string} quote - Quote character
+ * @throws {SyntaxError} If string is unterminated
+ * @returns {{content: string, end: number, escaped: boolean}} Extracted content, end position, and whether it's backtick-escaped
+ */
+ function extractQuoted(start, quote) {
+ let j = start;
+ let content = '';
+ let escaped = false;
+ while (j < expr.length) {
+ if (expr[j] === '\\' && j + 1 < expr.length) {
+ // Handle backslash escape sequences
+ content += expr[j + 1];
+ j += 2;
+ } else if (expr[j] === '`' && j + 1 < expr.length) {
+ // Handle backtick escape - backtick escapes next char
+ content += expr[j + 1];
+ escaped = true;
+ j += 2;
+ } else if (expr[j] === quote) {
+ return {
+ content,
+ end: j + 1,
+ escaped
+ };
+ } else {
+ content += expr[j];
+ j++;
+ }
+ }
+ throw new SyntaxError(`Unterminated string at position ${start - 1}`);
+ }
+
+ /**
+ * Handle dot notation (.property or ..descendant).
+ * @throws {SyntaxError} If malformed
+ * @returns {void}
+ */
+ function handleDotNotation() {
+ if (i + 1 < expr.length && expr[i + 1] === '.') {
+ // Descendant (..)
+ tokens.push({
+ type: 'descent'
+ });
+ i += 2;
+ } else {
+ // Skip the dot and parse property name
+ i++;
+ if (i >= expr.length) {
+ throw new SyntaxError('Unexpected end after dot at position ' + (i - 1));
+ }
+
+ // Check what follows the dot
+ switch (expr[i]) {
+ case '*':
+ tokens.push({
+ type: 'wildcard'
+ });
+ i++;
+ break;
+ case '`':
+ // Backtick escapes the next character
+ i++; // Skip backtick
+ if (i >= expr.length) {
+ throw new SyntaxError('Unexpected end after backtick at position ' + (i - 1));
+ }
+ // The escaped character becomes the property name
+ tokens.push({
+ type: 'property',
+ value: expr[i],
+ escaped: true
+ });
+ i++;
+ break;
+ case '[':
+ // Dot followed by bracket: interpret as descent
+ // e.g., $.[?(...)] becomes $ .. [?(...)]
+ tokens.push({
+ type: 'descent'
+ });
+ break;
+ default:
+ {
+ // Regular property name (until next special char)
+ let propName = '';
+ while (i < expr.length && !/[.[\]^~@*]/u.test(expr[i])) {
+ propName += expr[i];
+ i++;
+ }
+ if (propName) {
+ // Hybrid token: use string for unescaped properties
+ tokens.push(propName);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Handle bracket notation [...].
+ * @throws {SyntaxError} If malformed
+ * @returns {void}
+ */
+ function handleBracketNotation() {
+ i++; // Skip [
+ if (i >= expr.length) {
+ throw new SyntaxError('Unexpected end after [ at position ' + (i - 1));
+ }
+
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ const ch = expr[i];
+
+ // Wildcard [*]
+ if (ch === '*') {
+ i++;
+ // Skip whitespace and closing bracket
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after * at position ' + i);
+ }
+ i++;
+ tokens.push({
+ type: 'wildcard'
+ });
+ return;
+ }
+
+ // Filter [?(expression)]
+ if (ch === '?') {
+ if (i + 1 >= expr.length || expr[i + 1] !== '(') {
+ throw new SyntaxError('Expected ( after ? at position ' + i);
+ }
+ i += 2; // Skip ?(
+ const result = extractBalanced(i, '(', ')');
+ const {
+ content: expression
+ } = result;
+ i = result.end;
+
+ // Skip whitespace and closing bracket
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after filter at position ' + i);
+ }
+ i++;
+ tokens.push({
+ type: 'filter',
+ expression
+ });
+ return;
+ }
+
+ // Dynamic [(expression)]
+ if (ch === '(') {
+ i++; // Skip (
+ const result = extractBalanced(i, '(', ')');
+ const {
+ content: expression
+ } = result;
+ i = result.end;
+
+ // Skip whitespace and closing bracket
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after dynamic expression at position ' + i);
+ }
+ i++;
+ tokens.push({
+ type: 'dynamic',
+ expression
+ });
+ return;
+ }
+
+ // Quoted property ['name'] or ["name"]
+ if (ch === "'" || ch === '"') {
+ const quote = ch;
+ i++; // Skip opening quote
+ const result = extractQuoted(i, quote);
+ const {
+ content,
+ escaped
+ } = result;
+ i = result.end;
+
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+
+ // Check for comma (multi-property)
+ if (expr[i] === ',') {
+ const properties = [content];
+ const escapedFlags = [escaped];
+ while (expr[i] === ',') {
+ i++; // Skip comma
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ if (expr[i] !== "'" && expr[i] !== '"') {
+ throw new SyntaxError('Expected quoted property after comma at position ' + i);
+ }
+ const q = expr[i];
+ i++;
+ const r = extractQuoted(i, q);
+ properties.push(r.content);
+ escapedFlags.push(r.escaped);
+ i = r.end;
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after multi-property at position ' + i);
+ }
+ i++;
+ tokens.push({
+ type: 'multiProperty',
+ properties,
+ escaped: escapedFlags
+ });
+ return;
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after quoted property at position ' + i);
+ }
+ i++;
+ // Check if quoted property is wildcard
+ if (content === '*' && !escaped) {
+ tokens.push({
+ type: 'wildcard'
+ });
+ } else if (escaped) {
+ // Keep object for escaped properties (metadata needed)
+ tokens.push({
+ type: 'property',
+ value: content,
+ escaped: true
+ });
+ } else {
+ // Hybrid token: use string for unescaped properties
+ tokens.push(content);
+ }
+ return;
+ }
+
+ // Number (index, slice, or multi-index)
+ if (/[-\d]/u.test(ch) || ch === ':') {
+ let numStr = '';
+ while (i < expr.length && /[-\d:]/u.test(expr[i])) {
+ numStr += expr[i];
+ i++;
+ }
+
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+
+ // Check for comma (multi-index like [0,1,2])
+ if (expr[i] === ',') {
+ const indices = [Number.parseInt(numStr)];
+ while (expr[i] === ',') {
+ i++; // Skip comma
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ // Read next number
+ let nextNum = '';
+ while (i < expr.length && /[-\d]/u.test(expr[i])) {
+ nextNum += expr[i];
+ i++;
+ }
+ indices.push(Number.parseInt(nextNum));
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after multi-index at position ' + i);
+ }
+ i++;
+ // Create multiProperty token with numeric properties
+ tokens.push({
+ type: 'multiProperty',
+ properties: indices
+ });
+ return;
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after number at position ' + i);
+ }
+ i++;
+
+ // Check if it's a slice (contains :)
+ if (numStr.includes(':')) {
+ const parts = numStr.split(':');
+ const start = parts[0] === '' ? null : Number.parseInt(parts[0]);
+ const end = parts[1] === '' ? null : Number.parseInt(parts[1]);
+ const step = parts.length > 2 && parts[2] !== '' ? Number.parseInt(parts[2]) : null;
+ tokens.push({
+ type: 'slice',
+ start,
+ end,
+ step,
+ raw: numStr
+ });
+ } else {
+ // Simple index - Hybrid token: use number directly
+ const index = Number.parseInt(numStr);
+ tokens.push(index);
+ }
+ return;
+ }
+
+ // Unquoted property (identifier)
+ // In brackets, unquoted properties can have backtick escapes
+ let propName = '';
+ let escaped = false;
+ while (i < expr.length && expr[i] !== ']' && expr[i] !== ',' && !/\s/u.test(expr[i])) {
+ if (expr[i] === '`' && i + 1 < expr.length && expr[i + 1] !== ']' && expr[i + 1] !== ',') {
+ // Backtick escapes next character
+ propName += expr[i + 1];
+ escaped = true;
+ i += 2;
+ } else {
+ propName += expr[i];
+ i++;
+ }
+ }
+
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+
+ // Check for comma (multi-property with unquoted names)
+ if (expr[i] === ',') {
+ const properties = [propName];
+ const escapedFlags = [escaped];
+ while (expr[i] === ',') {
+ i++; // Skip comma
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ let prop = '';
+ let propEscaped = false;
+ while (i < expr.length && expr[i] !== ']' && expr[i] !== ',' && !/\s/u.test(expr[i])) {
+ if (expr[i] === '`' && i + 1 < expr.length && expr[i + 1] !== ']' && expr[i + 1] !== ',') {
+ // Backtick escapes next character
+ prop += expr[i + 1];
+ propEscaped = true;
+ i += 2;
+ } else {
+ prop += expr[i];
+ i++;
+ }
+ }
+ if (!prop) {
+ throw new SyntaxError('Expected property name after comma at position ' + i);
+ }
+ properties.push(prop);
+ escapedFlags.push(propEscaped);
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after multi-property at position ' + i);
+ }
+ i++;
+ tokens.push({
+ type: 'multiProperty',
+ properties,
+ escaped: escapedFlags
+ });
+ return;
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after property at position ' + i);
+ }
+ i++;
+ if (propName) {
+ if (escaped) {
+ // Keep object for escaped properties
+ tokens.push({
+ type: 'property',
+ value: propName,
+ escaped: true
+ });
+ } else {
+ // Hybrid token: use string for unescaped properties
+ tokens.push(propName);
+ }
+ }
+ }
+
+ /**
+ * Handle type operator `@type()`.
+ * @throws {SyntaxError} If malformed
+ * @returns {void}
+ */
+ function handleTypeOperator() {
+ i++; // Skip @
+ let typeName = '';
+ while (i < expr.length && /[a-z]/ui.test(expr[i])) {
+ typeName += expr[i];
+ i++;
+ }
+ if (i + 1 >= expr.length || expr[i] !== '(' || expr[i + 1] !== ')') {
+ throw new SyntaxError('Expected () after @' + typeName + ' at position ' + i);
+ }
+ i += 2; // Skip ()
+ tokens.push({
+ type: 'typeOperator',
+ valueType: typeName
+ });
+ }
+
+ // If path doesn't start with $, [, or other special char, add implicit root
+ if (expr.length > 0 && !['$', '[', '.', '^', '~', '@'].includes(expr[0])) {
+ tokens.push({
+ type: 'root'
+ });
+ // Prepend with a dot to make it valid for our parser
+ expr = '.' + expr;
+ }
+
+ // Main parsing loop
+ while (i < expr.length) {
+ const ch = expr[i];
+ switch (ch) {
+ case '$':
+ tokens.push({
+ type: 'root'
+ });
+ i++;
+ break;
+ case '.':
+ handleDotNotation();
+ break;
+ case '[':
+ handleBracketNotation();
+ break;
+ case '*':
+ // Wildcard (can appear after .. without a dot)
+ tokens.push({
+ type: 'wildcard'
+ });
+ i++;
+ break;
+ case '^':
+ // If parent selector comes right after root (or at start),
+ // add implicit empty string property
+ // This handles cases like "^" or "$^" which should be "['']^"
+ if (tokens.length === 0 || tokens.length === 1 && tokens[0].type === 'root') {
+ // Hybrid token: empty property is a string
+ tokens.push('');
+ }
+ tokens.push({
+ type: 'parent'
+ });
+ i++;
+ break;
+ case '~':
+ tokens.push({
+ type: 'propertyName'
+ });
+ i++;
+ break;
+ case '@':
+ // Check if this is a type operator like @boolean()
+ // Type operators have the pattern: @identifier()
+ if (/^@[a-z]+\(\)/ui.test(expr.slice(i))) {
+ handleTypeOperator();
+ } else {
+ // Treat @ as part of a property name
+ let propName = '';
+ while (i < expr.length && /[\w$@\\]/u.test(expr[i])) {
+ propName += expr[i];
+ i++;
+ }
+ if (propName) {
+ // Hybrid token: use string for unescaped properties
+ tokens.push(propName);
+ }
+ }
+ break;
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ // Skip whitespace
+ i++;
+ break;
+ default:
+ // Try to parse as identifier (property name)
+ if (/[\w$]/u.test(ch)) {
+ let propName = '';
+ while (i < expr.length && /[\w$]/u.test(expr[i])) {
+ propName += expr[i];
+ i++;
+ }
+ // Hybrid token: use string for unescaped properties
+ tokens.push(propName);
+ } else {
+ throw new SyntaxError(`Unexpected character '${ch}' at position ${i}`);
+ }
+ }
+ }
+ cache[expr] = tokens;
+ return tokens.map(token => typeof token === 'object' && token !== null ? {
+ ...token
+ } : token);
};
JSONPath.prototype.safeVm = {
Script: SafeScript
diff --git a/dist/index-node-esm.js b/dist/index-node-esm.js
index 53c30b6..461f227 100644
--- a/dist/index-node-esm.js
+++ b/dist/index-node-esm.js
@@ -1607,11 +1607,12 @@ JSONPath.prototype.evaluate = function (expr, json, callback, otherTypeCallback)
if (!expr && expr !== '' || !json) {
return undefined;
}
- const exprList = JSONPath.toPathArray(expr);
- if (exprList[0] === '$' && exprList.length > 1) {
+ const exprList = JSONPath.toPathParts(expr);
+ if (exprList[0] && exprList[0].type === 'root' && exprList.length > 1) {
exprList.shift();
}
this._hasParentSelector = null;
+ this._json = json; // Store root for parent selector navigation
const result = this._trace(exprList, json, ['$'], currParent, currParentProperty, callback).filter(function (ea) {
return ea && !ea.isParentSelector;
});
@@ -1639,7 +1640,7 @@ JSONPath.prototype._getPreferredOutput = function (ea) {
switch (resultType) {
case 'all':
{
- const path = Array.isArray(ea.path) ? ea.path : JSONPath.toPathArray(ea.path);
+ const path = Array.isArray(ea.path) ? ea.path : JSONPath.toPathParts(ea.path);
ea.pointer = JSONPath.toPointer(path);
ea.path = typeof ea.path === 'string' ? ea.path : JSONPath.toPathString(ea.path);
return ea;
@@ -1690,9 +1691,9 @@ JSONPath.prototype._trace = function (expr, val, path, parent, parentPropName, c
hasArrExpr
};
this._handleCallback(retObj, callback, 'value');
- return retObj;
+ return [retObj];
}
- const loc = expr[0],
+ const token = expr[0],
x = expr.slice(1);
// We need to gather the return value of recursive trace calls in order to
@@ -1715,168 +1716,266 @@ JSONPath.prototype._trace = function (expr, val, path, parent, parentPropName, c
ret.push(elems);
}
}
- if ((typeof loc !== 'string' || literalPriority) && val && Object.hasOwn(val, loc)) {
- // simple case--directly follow property
- addRet(this._trace(x, val[loc], push(path, loc), val, loc, callback, hasArrExpr));
- // eslint-disable-next-line unicorn/prefer-switch -- Part of larger `if`
- } else if (loc === '*') {
- // all child properties
- this._walk(val, m => {
- addRet(this._trace(x, val[m], push(path, m), val, m, callback, true, true));
- });
- } else if (loc === '..') {
- // all descendent parent properties
- // Check remaining expression with val's immediate children
- addRet(this._trace(x, val, path, parent, parentPropName, callback, hasArrExpr));
- this._walk(val, m => {
- // We don't join m and x here because we only want parents,
- // not scalar values
- if (typeof val[m] === 'object') {
- // Keep going with recursive descent on val's
- // object children
- addRet(this._trace(expr.slice(), val[m], push(path, m), val, m, callback, true));
- }
- });
- // The parent sel computation is handled in the frame above using the
- // ancestor object of val
- } else if (loc === '^') {
- // This is not a final endpoint, so we do not invoke the callback here
- this._hasParentSelector = true;
- return {
- path: path.slice(0, -1),
- expr: x,
- isParentSelector: true
- };
- } else if (loc === '~') {
- // property name
- retObj = {
- path: push(path, loc),
- value: parentPropName,
- parent,
- parentProperty: null
- };
- this._handleCallback(retObj, callback, 'property');
- return retObj;
- } else if (loc === '$') {
- // root only
- addRet(this._trace(x, val, path, null, null, callback, hasArrExpr));
- } else if (/^(-?\d*):(-?\d*):?(\d*)$/u.test(loc)) {
- // [start:end:step] Python slice syntax
- addRet(this._slice(loc, x, val, path, parent, parentPropName, callback));
- } else if (loc.indexOf('?(') === 0) {
- // [?(expr)] (filtering)
- if (this.currEval === false) {
- throw new Error('Eval [?(expr)] prevented in JSONPath expression.');
- }
- const safeLoc = loc.replace(/^\?\((.*?)\)$/u, '$1');
- // check for a nested filter expression
- const nested = /@.?([^?]*)[['](\??\(.*?\))(?!.\)\])[\]']/gu.exec(safeLoc);
- if (nested) {
- // find if there are matches in the nested expression
- // add them to the result set if there is at least one match
- this._walk(val, m => {
- const npath = [nested[2]];
- const nvalue = nested[1] ? val[m][nested[1]] : val[m];
- const filterResults = this._trace(npath, nvalue, path, parent, parentPropName, callback, true);
- if (filterResults.length > 0) {
- addRet(this._trace(x, val[m], push(path, m), val, m, callback, true));
- }
- });
- } else {
- this._walk(val, m => {
- if (this._eval(safeLoc, val[m], m, path, parent, parentPropName)) {
- addRet(this._trace(x, val[m], push(path, m), val, m, callback, true));
- }
- });
+
+ // Fast path for primitive tokens (strings and numbers)
+ if (typeof token === 'string') {
+ // Simple property access
+ if (val && Object.hasOwn(val, token)) {
+ addRet(this._trace(x, val[token], push(path, token), val, token, callback, hasArrExpr));
}
- } else if (loc[0] === '(') {
- // [(expr)] (dynamic property/index)
- if (this.currEval === false) {
- throw new Error('Eval [(expr)] prevented in JSONPath expression.');
- }
- // As this will resolve to a property name (but we don't know it
- // yet), property and parent information is relative to the
- // parent of the property to which this expression will resolve
- addRet(this._trace(unshift(this._eval(loc, val, path.at(-1), path.slice(0, -1), parent, parentPropName), x), val, path, parent, parentPropName, callback, hasArrExpr));
- } else if (loc[0] === '@') {
- // value type: @boolean(), etc.
- let addType = false;
- const valueType = loc.slice(1, -2);
- switch (valueType) {
- case 'scalar':
- if (!val || !['object', 'function'].includes(typeof val)) {
- addType = true;
- }
+ } else if (typeof token === 'number') {
+ // Simple numeric index access
+ if (Array.isArray(val) && token >= 0 && token < val.length) {
+ addRet(this._trace(x, val[token], push(path, token), val, token, callback, hasArrExpr));
+ }
+ } else if (token && typeof token === 'object' && token.type) {
+ // Handle complex token objects
+ switch (token.type) {
+ case 'root':
+ // $
+ addRet(this._trace(x, val, path, null, null, callback, hasArrExpr));
break;
- case 'boolean':
- case 'string':
- case 'undefined':
- case 'function':
- if (typeof val === valueType) {
- addType = true;
+ case 'property':
+ {
+ const propName = token.value;
+ // Check if property exists (escaped flag just means it's not wildcard)
+ if (val && Object.hasOwn(val, propName)) {
+ addRet(this._trace(x, val[propName], push(path, propName), val, propName, callback, hasArrExpr, true));
+ }
+ break;
}
+ case 'wildcard':
+ // *
+ this._walk(val, m => {
+ addRet(this._trace(x, val[m], push(path, m), val, m, callback, true, true));
+ });
break;
- case 'integer':
- if (Number.isFinite(val) && !(val % 1)) {
- addType = true;
- }
+ case 'descent':
+ // ..
+ // Check remaining expression with val's immediate children
+ addRet(this._trace(x, val, path, parent, parentPropName, callback, hasArrExpr));
+ this._walk(val, m => {
+ // We don't join m and x here because we only want parents,
+ // not scalar values
+ if (typeof val[m] === 'object') {
+ // Keep going with recursive descent on val's
+ // object children
+ addRet(this._trace(expr.slice(), val[m], push(path, m), val, m, callback, true));
+ }
+ });
break;
- case 'number':
- if (Number.isFinite(val)) {
- addType = true;
+ case 'parent':
+ // ^
+ // This is not a final endpoint, so we do not invoke the callback here
+ // Only allow parent selector if we're not already at root
+ if (path.length > 1) {
+ this._hasParentSelector = true;
+ ret.push({
+ path: path.slice(0, -1),
+ expr: x,
+ isParentSelector: true
+ });
}
break;
- case 'nonFinite':
- if (typeof val === 'number' && !Number.isFinite(val)) {
- addType = true;
- }
+ case 'propertyName':
+ // ~
+ retObj = {
+ path: push(path, '~'),
+ value: parentPropName,
+ parent,
+ parentProperty: null
+ };
+ this._handleCallback(retObj, callback, 'property');
+ ret.push(retObj);
break;
- case 'object':
- if (val && typeof val === valueType) {
- addType = true;
+ case 'index':
+ {
+ const idx = token.value;
+ if (Array.isArray(val) && idx >= 0 && idx < val.length || val && Object.hasOwn(val, idx)) {
+ addRet(this._trace(x, val[idx], push(path, idx), val, idx, callback, hasArrExpr, true));
+ }
+ break;
}
+ case 'slice':
+ addRet(this._slice(token, x, val, path, parent, parentPropName, callback));
break;
- case 'array':
- if (Array.isArray(val)) {
- addType = true;
+ case 'filter':
+ {
+ if (this.currEval === false) {
+ throw new Error('Eval [?(expr)] prevented in JSONPath expression.');
+ }
+
+ // Quick check: Does this filter have nested paths?
+ const hasNesting = token.expression.includes('[?(');
+ if (!hasNesting) {
+ // Fast path: No nesting, skip extraction
+ this._walk(val, m => {
+ if (this._eval(token.expression, val[m], m, path, parent, parentPropName)) {
+ addRet(this._trace(x, val[m], push(path, m), val, m, callback, true));
+ }
+ });
+ } else {
+ // Slow path: Extract and handle nested filters
+ const {
+ expression: modifiedExpr,
+ nestedPaths
+ } = this._extractNestedFilters(token.expression);
+
+ // Check if expression is JUST a nested path (no other JavaScript)
+ // If so, we need to check array length for truthiness
+ const isSingleNestedPath = nestedPaths.length === 1 && modifiedExpr.trim() === '_$_jp0';
+
+ // Evaluate filter for each item
+ this._walk(val, m => {
+ // Evaluate nested paths in context of current item
+ const nestedResults = {};
+ for (const [i, nestedPath] of nestedPaths.entries()) {
+ // Convert @ to $ for parsing (@ means current value)
+ const pathForParsing = nestedPath.replace(/^@/u, '$');
+ try {
+ const nestedTokens = JSONPath.toPathParts(pathForParsing);
+ // Evaluate nested path on current item
+ const nestedResult = this._trace(nestedTokens, val[m], push(path, m), val, m, null,
+ // no callback for nested evaluation
+ true);
+ // Extract values from result objects
+ nestedResults[`_$_jp${i}`] = nestedResult.map(r => r.value);
+ } catch (e) {
+ // If nested evaluation fails, treat as no matches
+ nestedResults[`_$_jp${i}`] = [];
+ }
+ }
+
+ // Add nested results to sandbox temporarily
+ const originalSandbox = {
+ ...this.currSandbox
+ };
+ Object.assign(this.currSandbox, nestedResults);
+ try {
+ // For single nested path, check if array has elements
+ // (empty arrays are truthy in JS but should be falsy in filter)
+ const matches = isSingleNestedPath ? nestedResults._$_jp0.length > 0 : this._eval(modifiedExpr, val[m], m, path, parent, parentPropName);
+ if (matches) {
+ addRet(this._trace(x, val[m], push(path, m), val, m, callback, true));
+ }
+ } finally {
+ // Restore original sandbox (remove nested result placeholders)
+ this.currSandbox = originalSandbox;
+ }
+ });
+ }
+ break;
}
- break;
- case 'other':
- addType = this.currOtherTypeCallback(val, path, parent, parentPropName);
- break;
- case 'null':
- if (val === null) {
- addType = true;
+ case 'dynamic':
+ {
+ if (this.currEval === false) {
+ throw new Error('Eval [(expr)] prevented in JSONPath expression.');
+ }
+ // As this will resolve to a property name (but we don't know it
+ // yet), property and parent information is relative to the
+ // parent of the property to which this expression will resolve
+ addRet(this._trace(unshift(this._eval(token.expression, val, path.at(-1), path.slice(0, -1), parent, parentPropName), x), val, path, parent, parentPropName, callback, hasArrExpr));
+ break;
+ }
+ case 'typeOperator':
+ {
+ let addType = false;
+ const {
+ valueType
+ } = token;
+ switch (valueType) {
+ case 'scalar':
+ if (!val || !['object', 'function'].includes(typeof val)) {
+ addType = true;
+ }
+ break;
+ case 'boolean':
+ case 'string':
+ case 'undefined':
+ case 'function':
+ if (typeof val === valueType) {
+ addType = true;
+ }
+ break;
+ case 'integer':
+ if (Number.isFinite(val) && !(val % 1)) {
+ addType = true;
+ }
+ break;
+ case 'number':
+ if (Number.isFinite(val)) {
+ addType = true;
+ }
+ break;
+ case 'nonFinite':
+ if (typeof val === 'number' && !Number.isFinite(val)) {
+ addType = true;
+ }
+ break;
+ case 'object':
+ if (val && typeof val === valueType) {
+ addType = true;
+ }
+ break;
+ case 'array':
+ if (Array.isArray(val)) {
+ addType = true;
+ }
+ break;
+ case 'other':
+ addType = this.currOtherTypeCallback(val, path, parent, parentPropName);
+ break;
+ case 'null':
+ if (val === null) {
+ addType = true;
+ }
+ break;
+ /* c8 ignore next 2 */
+ default:
+ throw new TypeError('Unknown value type ' + valueType);
+ }
+ if (addType) {
+ retObj = {
+ path,
+ value: val,
+ parent,
+ parentProperty: parentPropName
+ };
+ this._handleCallback(retObj, callback, 'value');
+ ret.push(retObj);
+ }
+ break;
+ }
+ case 'multiProperty':
+ {
+ const parts = token.properties;
+ const escapedFlags = token.escaped || [];
+ for (const [i, part] of parts.entries()) {
+ // Check if part is a number (multi-index) or string (multi-property)
+ let partToken;
+ if (typeof part === 'number') {
+ partToken = {
+ type: 'index',
+ value: part
+ };
+ } else {
+ const isEscaped = escapedFlags[i] || false;
+ partToken = {
+ type: 'property',
+ value: part,
+ escaped: isEscaped
+ };
+ }
+ addRet(this._trace(unshift(partToken, x), val, path, parent, parentPropName, callback, true));
+ }
+ break;
}
- break;
- /* c8 ignore next 2 */
- default:
- throw new TypeError('Unknown value type ' + valueType);
- }
- if (addType) {
- retObj = {
- path,
- value: val,
- parent,
- parentProperty: parentPropName
- };
- this._handleCallback(retObj, callback, 'value');
- return retObj;
- }
- // `-escaped property
- } else if (loc[0] === '`' && val && Object.hasOwn(val, loc.slice(1))) {
- const locProp = loc.slice(1);
- addRet(this._trace(x, val[locProp], push(path, locProp), val, locProp, callback, hasArrExpr, true));
- } else if (loc.includes(',')) {
- // [name1,name2,...]
- const parts = loc.split(',');
- for (const part of parts) {
- addRet(this._trace(unshift(part, x), val, path, parent, parentPropName, callback, true));
}
- // simple case--directly follow property
- } else if (!literalPriority && val && Object.hasOwn(val, loc)) {
- addRet(this._trace(x, val[loc], push(path, loc), val, loc, callback, hasArrExpr, true));
+ } else if ((typeof token !== 'string' || literalPriority) && val && Object.hasOwn(val, token)) {
+ // simple case--directly follow property (for object tokens or with literalPriority)
+ addRet(this._trace(x, val[token], push(path, token), val, token, callback, hasArrExpr));
}
+ // Note: Legacy string token handling removed - now handled by fast path above
// We check the resulting values for parent selections. For parent
// selections we discard the value object and continue the trace with the
@@ -1885,7 +1984,20 @@ JSONPath.prototype._trace = function (expr, val, path, parent, parentPropName, c
for (let t = 0; t < ret.length; t++) {
const rett = ret[t];
if (rett && rett.isParentSelector) {
- const tmp = this._trace(rett.expr, val, rett.path, parent, parentPropName, callback, hasArrExpr);
+ // Navigate from root to the parent path to get correct parent context
+ // rett.path is the path with last element removed (e.g., ['$', 'children'])
+ let resultVal = this._json;
+ let resultParent = null;
+ let resultParentProp = null;
+
+ // Navigate from root following the path
+ // Start at index 1 to skip '$'
+ for (let i = 1; i < rett.path.length; i++) {
+ resultParent = resultVal;
+ resultParentProp = rett.path[i];
+ resultVal = resultVal[rett.path[i]];
+ }
+ const tmp = this._trace(rett.expr, resultVal, rett.path, resultParent, resultParentProp, callback, hasArrExpr);
if (Array.isArray(tmp)) {
ret[t] = tmp[0];
const tl = tmp.length;
@@ -1915,15 +2027,229 @@ JSONPath.prototype._walk = function (val, f) {
});
}
};
-JSONPath.prototype._slice = function (loc, expr, val, path, parent, parentPropName, callback) {
+
+/**
+ * Extract nested JSONPath expressions from a filter expression.
+ * @param {string} expr - Filter expression (e.g., "@.children[?(@.price<10)]")
+ * @returns {{expression: string, nestedPaths: string[]}} Modified expression and extracted paths
+ */
+JSONPath.prototype._extractNestedFilters = function (expr) {
+ // Check cache first
+ const cache = JSONPath.filterExtractionCache;
+ if (cache[expr]) {
+ // Return shallow clone to prevent mutation
+ return {
+ expression: cache[expr].expression,
+ nestedPaths: [...cache[expr].nestedPaths]
+ };
+ }
+ const nestedPaths = [];
+ let result = expr;
+ let placeholderCount = 0;
+
+ // We need to find patterns like @.path[?(...)] or @[?(...)], etc.
+ // Use a stack-based approach to handle nested brackets properly
+
+ /**
+ * Find the next JSONPath expression starting with @.
+ * @param {string} str - String to search
+ * @param {number} startPos - Position to start searching
+ * @returns {{start: number, end: number, path: string} | null}
+ */
+ function findNextNestedPath(str, startPos) {
+ let i = startPos;
+
+ // Find next @ that's not in a string or regex literal
+ while (i < str.length) {
+ const ch = str[i];
+
+ // Skip string literals
+ if (ch === '"' || ch === "'") {
+ const quote = ch;
+ i++;
+ while (i < str.length) {
+ if (str[i] === '\\' && i + 1 < str.length) {
+ i += 2; // Skip escaped character
+ } else if (str[i] === quote) {
+ i++;
+ break;
+ } else {
+ i++;
+ }
+ }
+ continue;
+ }
+
+ // Skip regex literals (simplified detection)
+ if (ch === '/' && i > 0) {
+ // Check if this might be a regex (not division)
+ // Look back for operators that could precede a regex
+ const prevNonSpace = str.slice(0, i).trimEnd().slice(-1);
+ if ('=([{,;:!&|?'.includes(prevNonSpace) || i === startPos) {
+ i++;
+ while (i < str.length) {
+ if (str[i] === '\\' && i + 1 < str.length) {
+ i += 2;
+ } else if (str[i] === '/') {
+ i++;
+ // Skip regex flags
+ while (i < str.length && /[gimsuvy]/u.test(str[i])) {
+ i++;
+ }
+ break;
+ } else {
+ i++;
+ }
+ }
+ continue;
+ }
+ }
+
+ // Found @ - check if it's followed by JSONPath syntax
+ if (ch === '@') {
+ const pathStart = i;
+ i++; // Move past @
+
+ // Check if there's path syntax after @
+ // Could be: @.prop, @[, @.., @@
+ if (i >= str.length) {
+ return null;
+ }
+ let hasPathSyntax = false;
+ let path = '@';
+
+ // Parse the JSONPath expression
+ while (i < str.length) {
+ const c = str[i];
+
+ // Path components
+ if (c === '.' || c === '[' || c === '*' || c === '^' || c === '~') {
+ hasPathSyntax = true;
+ path += c;
+ i++;
+
+ // Handle bracket notation with bracket matching
+ if (c === '[') {
+ let depth = 1;
+ /* eslint-disable unicorn/prefer-switch --
+ Complex bracket matching with nested quotes */
+ while (i < str.length && depth > 0) {
+ if (str[i] === '\\' && i + 1 < str.length) {
+ path += str[i] + str[i + 1];
+ i += 2;
+ } else if (str[i] === '"' || str[i] === "'") {
+ // Handle quoted strings in brackets
+ const q = str[i];
+ path += str[i];
+ i++;
+ while (i < str.length && str[i] !== q) {
+ if (str[i] === '\\' && i + 1 < str.length) {
+ path += str[i] + str[i + 1];
+ i += 2;
+ } else {
+ path += str[i];
+ i++;
+ }
+ }
+ if (i < str.length) {
+ path += str[i];
+ i++;
+ }
+ } else if (str[i] === '[') {
+ depth++;
+ path += str[i];
+ i++;
+ } else if (str[i] === ']') {
+ depth--;
+ path += str[i];
+ i++;
+ } else {
+ path += str[i];
+ i++;
+ }
+ }
+ /* eslint-enable unicorn/prefer-switch --
+ Re-enable after bracket matching section */
+ }
+ } else if (/[\w$]/u.test(c)) {
+ // Property name characters
+ hasPathSyntax = true;
+ path += c;
+ i++;
+ } else {
+ // End of path
+ break;
+ }
+ }
+
+ // Check if this path contains a filter (has [?(...)])
+ // Only extract paths that have filters to avoid unnecessary evaluation
+ if (hasPathSyntax && path.includes('[?')) {
+ return {
+ start: pathStart,
+ end: i,
+ path
+ };
+ }
+
+ // No filter found, continue searching
+ continue;
+ }
+ i++;
+ }
+ return null;
+ }
+
+ // Extract all nested paths
+ let searchPos = 0;
+ const replacements = [];
+ while (searchPos < result.length) {
+ const found = findNextNestedPath(result, searchPos);
+ if (!found) {
+ break;
+ }
+
+ // Store the replacement to be made
+ replacements.push({
+ start: found.start,
+ end: found.end,
+ path: found.path,
+ placeholder: `_$_jp${placeholderCount}`
+ });
+ nestedPaths.push(found.path);
+ placeholderCount++;
+ searchPos = found.end;
+ }
+
+ // Apply replacements in reverse order to maintain positions
+ for (let i = replacements.length - 1; i >= 0; i--) {
+ const {
+ start,
+ end,
+ placeholder
+ } = replacements[i];
+ result = result.slice(0, start) + placeholder + result.slice(end);
+ }
+
+ // Cache the result
+ const extractionResult = {
+ expression: result,
+ nestedPaths
+ };
+ cache[expr] = extractionResult;
+ return {
+ expression: result,
+ nestedPaths: [...nestedPaths]
+ };
+};
+JSONPath.prototype._slice = function (token, expr, val, path, parent, parentPropName, callback) {
if (!Array.isArray(val)) {
return undefined;
}
- const len = val.length,
- parts = loc.split(':'),
- step = parts[2] && Number.parseInt(parts[2]) || 1;
- let start = parts[0] && Number.parseInt(parts[0]) || 0,
- end = parts[1] && Number.parseInt(parts[1]) || len;
+ const len = val.length;
+ let start = token.start === null ? 0 : token.start;
+ let end = token.end === null ? len : token.end;
+ const step = token.step === null ? 1 : token.step;
start = start < 0 ? Math.max(0, start + len) : Math.min(len, start);
end = end < 0 ? Math.max(0, end + len) : Math.min(len, end);
const ret = [];
@@ -1985,9 +2311,11 @@ JSONPath.prototype._eval = function (code, _v, _vname, path, parent, parentPropN
// Could store the cache object itself
JSONPath.cache = {};
+JSONPath.pathPartsCache = {};
+JSONPath.filterExtractionCache = {};
/**
- * @param {string[]} pathArr Array to convert
+ * @param {string[]|object[]} pathArr Array to convert
* @returns {string} The path string
*/
JSONPath.toPathString = function (pathArr) {
@@ -1995,15 +2323,54 @@ JSONPath.toPathString = function (pathArr) {
n = x.length;
let p = '$';
for (let i = 1; i < n; i++) {
- if (!/^(~|\^|@.*?\(\))$/u.test(x[i])) {
- p += /^[0-9*]+$/u.test(x[i]) ? '[' + x[i] + ']' : "['" + x[i] + "']";
+ const item = x[i];
+
+ // Handle both old string format and new token format
+ if (typeof item === 'number') {
+ // Array index
+ p += '[' + item + ']';
+ } else if (typeof item === 'string') {
+ // Legacy path
+ if (!/^(~|\^|@.*?\(\))$/u.test(item)) {
+ p += /^[0-9*]+$/u.test(item) ? '[' + item + ']' : "['" + item + "']";
+ }
+ } else if (item && typeof item === 'object') {
+ // New token format
+ switch (item.type) {
+ case 'property':
+ p += "['" + item.value + "']";
+ break;
+ case 'index':
+ p += '[' + item.value + ']';
+ break;
+ case 'wildcard':
+ p += '[*]';
+ break;
+ case 'slice':
+ p += '[' + item.raw + ']';
+ break;
+ case 'filter':
+ p += '[?(' + item.expression + ')]';
+ break;
+ case 'dynamic':
+ p += '[(' + item.expression + ')]';
+ break;
+ case 'typeOperator':
+ p += '@' + item.valueType + '()';
+ break;
+ case 'multiProperty':
+ p += "['" + item.properties.join("','") + "']";
+ break;
+ }
}
}
return p;
};
/**
- * @param {string} pointer JSON Path
+ * Converts path array to JSON Pointer format.
+ * Handles both legacy string arrays and new token objects.
+ * @param {string[]|object[]} pointer - Path array
* @returns {string} JSON Pointer
*/
JSONPath.toPointer = function (pointer) {
@@ -2011,59 +2378,653 @@ JSONPath.toPointer = function (pointer) {
n = x.length;
let p = '';
for (let i = 1; i < n; i++) {
- if (!/^(~|\^|@.*?\(\))$/u.test(x[i])) {
- p += '/' + x[i].toString().replaceAll('~', '~0').replaceAll('/', '~1');
+ const item = x[i];
+ let value;
+
+ // Handle different formats
+ if (typeof item === 'number') {
+ value = String(item);
+ } else if (typeof item === 'string') {
+ // Legacy string format or special operators
+ if (/^(~|\^|@.*?\(\))$/u.test(item)) {
+ continue; // Skip special operators
+ }
+ value = item;
+ } else if (item && typeof item === 'object') {
+ // New token format
+ switch (item.type) {
+ case 'property':
+ {
+ const {
+ value: propValue
+ } = item;
+ value = propValue;
+ break;
+ }
+ case 'index':
+ {
+ const {
+ value: indexValue
+ } = item;
+ value = String(indexValue);
+ break;
+ }
+ // Skip special operators
+ case 'root':
+ case 'wildcard':
+ case 'descent':
+ case 'parent':
+ case 'propertyName':
+ case 'filter':
+ case 'dynamic':
+ case 'slice':
+ case 'typeOperator':
+ case 'multiProperty':
+ continue;
+ default:
+ continue;
+ }
+ } else {
+ continue;
}
+
+ // Escape ~ and / per JSON Pointer spec
+ p += '/' + value.replaceAll('~', '~0').replaceAll('/', '~1');
}
return p;
};
/**
- * @param {string} expr Expression to convert
- * @returns {string[]}
+ * Parse a JSONPath expression into structured tokens.
+ * @param {string} expr - JSONPath expression
+ * @returns {Array} Array of tokens
*/
-JSONPath.toPathArray = function (expr) {
- const {
- cache
- } = JSONPath;
+/**
+ * Parses a JSONPath expression into structured token objects.
+ * @param {string} expr - JSONPath expression to parse
+ * @returns {object[]} Array of token objects
+ */
+JSONPath.toPathParts = function (expr) {
+ const cache = JSONPath.pathPartsCache;
if (cache[expr]) {
- return cache[expr].concat();
- }
- const subx = [];
- const normalized = expr
- // Properties
- .replaceAll(/@(?:null|boolean|number|string|integer|undefined|nonFinite|scalar|array|object|function|other)\(\)/gu, ';$&;')
- // Parenthetical evaluations (filtering and otherwise), directly
- // within brackets or single quotes
- .replaceAll(/[['](\??\(.*?\))[\]'](?!.\])/gu, function ($0, $1) {
- return '[#' + (subx.push($1) - 1) + ']';
- })
- // Escape periods and tildes within properties
- .replaceAll(/\[['"]([^'\]]*)['"]\]/gu, function ($0, prop) {
- return "['" + prop.replaceAll('.', '%@%').replaceAll('~', '%%@@%%') + "']";
- })
- // Properties operator
- .replaceAll('~', ';~;')
- // Split by property boundaries
- .replaceAll(/['"]?\.['"]?(?![^[]*\])|\[['"]?/gu, ';')
- // Reinsert periods within properties
- .replaceAll('%@%', '.')
- // Reinsert tildes within properties
- .replaceAll('%%@@%%', '~')
- // Parent
- .replaceAll(/(?:;)?(\^+)(?:;)?/gu, function ($0, ups) {
- return ';' + ups.split('').join(';') + ';';
- })
- // Descendents
- .replaceAll(/;;;|;;/gu, ';..;')
- // Remove trailing
- .replaceAll(/;$|'?\]|'$/gu, '');
- const exprList = normalized.split(';').map(function (exp) {
- const match = exp.match(/#(\d+)/u);
- return !match || !match[1] ? exp : subx[match[1]];
- });
- cache[expr] = exprList;
- return cache[expr].concat();
+ // Shallow clone array, shallow clone object tokens
+ // (tokens are simple objects with no nested objects)
+ return cache[expr].map(token => typeof token === 'object' && token !== null ? {
+ ...token
+ } : token);
+ }
+ const tokens = [];
+ let i = 0;
+
+ // Handle empty path - treat as empty property access
+ if (expr === '') {
+ // Hybrid token: empty property is a string
+ tokens.push('');
+ cache[expr] = tokens;
+ return cache[expr].map(token => typeof token === 'object' && token !== null ? {
+ ...token
+ } : token);
+ }
+
+ /**
+ * Extract balanced content between delimiters.
+ * @param {number} start - Starting position
+ * @param {string} open - Opening delimiter
+ * @param {string} close - Closing delimiter
+ * @throws {SyntaxError} If delimiters are unbalanced
+ * @returns {{content: string, end: number}} Extracted content and end position
+ */
+ function extractBalanced(start, open, close) {
+ let depth = 1;
+ let j = start;
+ while (j < expr.length && depth > 0) {
+ if (expr[j] === open) {
+ depth++;
+ } else if (expr[j] === close) {
+ depth--;
+ }
+ j++;
+ }
+ if (depth !== 0) {
+ throw new SyntaxError(`Unbalanced ${open}${close} in expression at position ${start}`);
+ }
+ return {
+ content: expr.slice(start, j - 1),
+ end: j
+ };
+ }
+
+ /**
+ * Extract quoted string.
+ * @param {number} start - Starting position (after quote)
+ * @param {string} quote - Quote character
+ * @throws {SyntaxError} If string is unterminated
+ * @returns {{content: string, end: number, escaped: boolean}} Extracted content, end position, and whether it's backtick-escaped
+ */
+ function extractQuoted(start, quote) {
+ let j = start;
+ let content = '';
+ let escaped = false;
+ while (j < expr.length) {
+ if (expr[j] === '\\' && j + 1 < expr.length) {
+ // Handle backslash escape sequences
+ content += expr[j + 1];
+ j += 2;
+ } else if (expr[j] === '`' && j + 1 < expr.length) {
+ // Handle backtick escape - backtick escapes next char
+ content += expr[j + 1];
+ escaped = true;
+ j += 2;
+ } else if (expr[j] === quote) {
+ return {
+ content,
+ end: j + 1,
+ escaped
+ };
+ } else {
+ content += expr[j];
+ j++;
+ }
+ }
+ throw new SyntaxError(`Unterminated string at position ${start - 1}`);
+ }
+
+ /**
+ * Handle dot notation (.property or ..descendant).
+ * @throws {SyntaxError} If malformed
+ * @returns {void}
+ */
+ function handleDotNotation() {
+ if (i + 1 < expr.length && expr[i + 1] === '.') {
+ // Descendant (..)
+ tokens.push({
+ type: 'descent'
+ });
+ i += 2;
+ } else {
+ // Skip the dot and parse property name
+ i++;
+ if (i >= expr.length) {
+ throw new SyntaxError('Unexpected end after dot at position ' + (i - 1));
+ }
+
+ // Check what follows the dot
+ switch (expr[i]) {
+ case '*':
+ tokens.push({
+ type: 'wildcard'
+ });
+ i++;
+ break;
+ case '`':
+ // Backtick escapes the next character
+ i++; // Skip backtick
+ if (i >= expr.length) {
+ throw new SyntaxError('Unexpected end after backtick at position ' + (i - 1));
+ }
+ // The escaped character becomes the property name
+ tokens.push({
+ type: 'property',
+ value: expr[i],
+ escaped: true
+ });
+ i++;
+ break;
+ case '[':
+ // Dot followed by bracket: interpret as descent
+ // e.g., $.[?(...)] becomes $ .. [?(...)]
+ tokens.push({
+ type: 'descent'
+ });
+ break;
+ default:
+ {
+ // Regular property name (until next special char)
+ let propName = '';
+ while (i < expr.length && !/[.[\]^~@*]/u.test(expr[i])) {
+ propName += expr[i];
+ i++;
+ }
+ if (propName) {
+ // Hybrid token: use string for unescaped properties
+ tokens.push(propName);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Handle bracket notation [...].
+ * @throws {SyntaxError} If malformed
+ * @returns {void}
+ */
+ function handleBracketNotation() {
+ i++; // Skip [
+ if (i >= expr.length) {
+ throw new SyntaxError('Unexpected end after [ at position ' + (i - 1));
+ }
+
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ const ch = expr[i];
+
+ // Wildcard [*]
+ if (ch === '*') {
+ i++;
+ // Skip whitespace and closing bracket
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after * at position ' + i);
+ }
+ i++;
+ tokens.push({
+ type: 'wildcard'
+ });
+ return;
+ }
+
+ // Filter [?(expression)]
+ if (ch === '?') {
+ if (i + 1 >= expr.length || expr[i + 1] !== '(') {
+ throw new SyntaxError('Expected ( after ? at position ' + i);
+ }
+ i += 2; // Skip ?(
+ const result = extractBalanced(i, '(', ')');
+ const {
+ content: expression
+ } = result;
+ i = result.end;
+
+ // Skip whitespace and closing bracket
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after filter at position ' + i);
+ }
+ i++;
+ tokens.push({
+ type: 'filter',
+ expression
+ });
+ return;
+ }
+
+ // Dynamic [(expression)]
+ if (ch === '(') {
+ i++; // Skip (
+ const result = extractBalanced(i, '(', ')');
+ const {
+ content: expression
+ } = result;
+ i = result.end;
+
+ // Skip whitespace and closing bracket
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after dynamic expression at position ' + i);
+ }
+ i++;
+ tokens.push({
+ type: 'dynamic',
+ expression
+ });
+ return;
+ }
+
+ // Quoted property ['name'] or ["name"]
+ if (ch === "'" || ch === '"') {
+ const quote = ch;
+ i++; // Skip opening quote
+ const result = extractQuoted(i, quote);
+ const {
+ content,
+ escaped
+ } = result;
+ i = result.end;
+
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+
+ // Check for comma (multi-property)
+ if (expr[i] === ',') {
+ const properties = [content];
+ const escapedFlags = [escaped];
+ while (expr[i] === ',') {
+ i++; // Skip comma
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ if (expr[i] !== "'" && expr[i] !== '"') {
+ throw new SyntaxError('Expected quoted property after comma at position ' + i);
+ }
+ const q = expr[i];
+ i++;
+ const r = extractQuoted(i, q);
+ properties.push(r.content);
+ escapedFlags.push(r.escaped);
+ i = r.end;
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after multi-property at position ' + i);
+ }
+ i++;
+ tokens.push({
+ type: 'multiProperty',
+ properties,
+ escaped: escapedFlags
+ });
+ return;
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after quoted property at position ' + i);
+ }
+ i++;
+ // Check if quoted property is wildcard
+ if (content === '*' && !escaped) {
+ tokens.push({
+ type: 'wildcard'
+ });
+ } else if (escaped) {
+ // Keep object for escaped properties (metadata needed)
+ tokens.push({
+ type: 'property',
+ value: content,
+ escaped: true
+ });
+ } else {
+ // Hybrid token: use string for unescaped properties
+ tokens.push(content);
+ }
+ return;
+ }
+
+ // Number (index, slice, or multi-index)
+ if (/[-\d]/u.test(ch) || ch === ':') {
+ let numStr = '';
+ while (i < expr.length && /[-\d:]/u.test(expr[i])) {
+ numStr += expr[i];
+ i++;
+ }
+
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+
+ // Check for comma (multi-index like [0,1,2])
+ if (expr[i] === ',') {
+ const indices = [Number.parseInt(numStr)];
+ while (expr[i] === ',') {
+ i++; // Skip comma
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ // Read next number
+ let nextNum = '';
+ while (i < expr.length && /[-\d]/u.test(expr[i])) {
+ nextNum += expr[i];
+ i++;
+ }
+ indices.push(Number.parseInt(nextNum));
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after multi-index at position ' + i);
+ }
+ i++;
+ // Create multiProperty token with numeric properties
+ tokens.push({
+ type: 'multiProperty',
+ properties: indices
+ });
+ return;
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after number at position ' + i);
+ }
+ i++;
+
+ // Check if it's a slice (contains :)
+ if (numStr.includes(':')) {
+ const parts = numStr.split(':');
+ const start = parts[0] === '' ? null : Number.parseInt(parts[0]);
+ const end = parts[1] === '' ? null : Number.parseInt(parts[1]);
+ const step = parts.length > 2 && parts[2] !== '' ? Number.parseInt(parts[2]) : null;
+ tokens.push({
+ type: 'slice',
+ start,
+ end,
+ step,
+ raw: numStr
+ });
+ } else {
+ // Simple index - Hybrid token: use number directly
+ const index = Number.parseInt(numStr);
+ tokens.push(index);
+ }
+ return;
+ }
+
+ // Unquoted property (identifier)
+ // In brackets, unquoted properties can have backtick escapes
+ let propName = '';
+ let escaped = false;
+ while (i < expr.length && expr[i] !== ']' && expr[i] !== ',' && !/\s/u.test(expr[i])) {
+ if (expr[i] === '`' && i + 1 < expr.length && expr[i + 1] !== ']' && expr[i + 1] !== ',') {
+ // Backtick escapes next character
+ propName += expr[i + 1];
+ escaped = true;
+ i += 2;
+ } else {
+ propName += expr[i];
+ i++;
+ }
+ }
+
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+
+ // Check for comma (multi-property with unquoted names)
+ if (expr[i] === ',') {
+ const properties = [propName];
+ const escapedFlags = [escaped];
+ while (expr[i] === ',') {
+ i++; // Skip comma
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ let prop = '';
+ let propEscaped = false;
+ while (i < expr.length && expr[i] !== ']' && expr[i] !== ',' && !/\s/u.test(expr[i])) {
+ if (expr[i] === '`' && i + 1 < expr.length && expr[i + 1] !== ']' && expr[i + 1] !== ',') {
+ // Backtick escapes next character
+ prop += expr[i + 1];
+ propEscaped = true;
+ i += 2;
+ } else {
+ prop += expr[i];
+ i++;
+ }
+ }
+ if (!prop) {
+ throw new SyntaxError('Expected property name after comma at position ' + i);
+ }
+ properties.push(prop);
+ escapedFlags.push(propEscaped);
+ // Skip whitespace
+ while (i < expr.length && /\s/u.test(expr[i])) {
+ i++;
+ }
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after multi-property at position ' + i);
+ }
+ i++;
+ tokens.push({
+ type: 'multiProperty',
+ properties,
+ escaped: escapedFlags
+ });
+ return;
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after property at position ' + i);
+ }
+ i++;
+ if (propName) {
+ if (escaped) {
+ // Keep object for escaped properties
+ tokens.push({
+ type: 'property',
+ value: propName,
+ escaped: true
+ });
+ } else {
+ // Hybrid token: use string for unescaped properties
+ tokens.push(propName);
+ }
+ }
+ }
+
+ /**
+ * Handle type operator `@type()`.
+ * @throws {SyntaxError} If malformed
+ * @returns {void}
+ */
+ function handleTypeOperator() {
+ i++; // Skip @
+ let typeName = '';
+ while (i < expr.length && /[a-z]/ui.test(expr[i])) {
+ typeName += expr[i];
+ i++;
+ }
+ if (i + 1 >= expr.length || expr[i] !== '(' || expr[i + 1] !== ')') {
+ throw new SyntaxError('Expected () after @' + typeName + ' at position ' + i);
+ }
+ i += 2; // Skip ()
+ tokens.push({
+ type: 'typeOperator',
+ valueType: typeName
+ });
+ }
+
+ // If path doesn't start with $, [, or other special char, add implicit root
+ if (expr.length > 0 && !['$', '[', '.', '^', '~', '@'].includes(expr[0])) {
+ tokens.push({
+ type: 'root'
+ });
+ // Prepend with a dot to make it valid for our parser
+ expr = '.' + expr;
+ }
+
+ // Main parsing loop
+ while (i < expr.length) {
+ const ch = expr[i];
+ switch (ch) {
+ case '$':
+ tokens.push({
+ type: 'root'
+ });
+ i++;
+ break;
+ case '.':
+ handleDotNotation();
+ break;
+ case '[':
+ handleBracketNotation();
+ break;
+ case '*':
+ // Wildcard (can appear after .. without a dot)
+ tokens.push({
+ type: 'wildcard'
+ });
+ i++;
+ break;
+ case '^':
+ // If parent selector comes right after root (or at start),
+ // add implicit empty string property
+ // This handles cases like "^" or "$^" which should be "['']^"
+ if (tokens.length === 0 || tokens.length === 1 && tokens[0].type === 'root') {
+ // Hybrid token: empty property is a string
+ tokens.push('');
+ }
+ tokens.push({
+ type: 'parent'
+ });
+ i++;
+ break;
+ case '~':
+ tokens.push({
+ type: 'propertyName'
+ });
+ i++;
+ break;
+ case '@':
+ // Check if this is a type operator like @boolean()
+ // Type operators have the pattern: @identifier()
+ if (/^@[a-z]+\(\)/ui.test(expr.slice(i))) {
+ handleTypeOperator();
+ } else {
+ // Treat @ as part of a property name
+ let propName = '';
+ while (i < expr.length && /[\w$@\\]/u.test(expr[i])) {
+ propName += expr[i];
+ i++;
+ }
+ if (propName) {
+ // Hybrid token: use string for unescaped properties
+ tokens.push(propName);
+ }
+ }
+ break;
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ // Skip whitespace
+ i++;
+ break;
+ default:
+ // Try to parse as identifier (property name)
+ if (/[\w$]/u.test(ch)) {
+ let propName = '';
+ while (i < expr.length && /[\w$]/u.test(expr[i])) {
+ propName += expr[i];
+ i++;
+ }
+ // Hybrid token: use string for unescaped properties
+ tokens.push(propName);
+ } else {
+ throw new SyntaxError(`Unexpected character '${ch}' at position ${i}`);
+ }
+ }
+ }
+ cache[expr] = tokens;
+ return tokens.map(token => typeof token === 'object' && token !== null ? {
+ ...token
+ } : token);
};
JSONPath.prototype.safeVm = {
Script: SafeScript
diff --git a/src/jsonpath.d.ts b/src/jsonpath.d.ts
index 6c3ab7b..53edd26 100644
--- a/src/jsonpath.d.ts
+++ b/src/jsonpath.d.ts
@@ -8,6 +8,20 @@ declare module 'jsonpath-plus' {
type JSONPathOtherTypeCallback = (...args: any[]) => void
+ type PathToken =
+ | { type: 'root' }
+ | { type: 'wildcard' }
+ | { type: 'descent' }
+ | { type: 'parent' }
+ | { type: 'propertyName' }
+ | { type: 'property'; value: string; escaped: boolean }
+ | { type: 'index'; value: number }
+ | { type: 'slice'; start: number | null; end: number | null; step: number | null; raw: string }
+ | { type: 'filter'; expression: string }
+ | { type: 'dynamic'; expression: string }
+ | { type: 'typeOperator'; valueType: string }
+ | { type: 'multiProperty'; properties: string[] }
+
class EvalClass {
constructor(code: string);
runInNewContext(context: object): any;
@@ -180,10 +194,10 @@ declare module 'jsonpath-plus' {
/**
* Accepts a normalized or unnormalized path as string and
- * converts to an array: for example,
- * `['$', 'aProperty', 'anotherProperty']`.
+ * converts to an array of structured tokens with metadata.
+ * For example: `[{type: 'root'}, {type: 'property', value: 'aProperty', escaped: false}]`.
*/
- toPathArray(path: string): string[]
+ toPathParts(path: string): PathToken[]
/**
* Accepts a path array and converts to a normalized path string.
@@ -192,7 +206,7 @@ declare module 'jsonpath-plus' {
* The JSONPath terminal constructions `~` and `^` and type operators
* like `@string()` are silently stripped.
*/
- toPathString(path: string[]): string
+ toPathString(path: (string | PathToken)[]): string
/**
* Accepts a path array and converts to a JSON Pointer.
diff --git a/src/jsonpath.js b/src/jsonpath.js
index 15be426..166186c 100644
--- a/src/jsonpath.js
+++ b/src/jsonpath.js
@@ -256,11 +256,12 @@ JSONPath.prototype.evaluate = function (
return undefined;
}
- const exprList = JSONPath.toPathArray(expr);
- if (exprList[0] === '$' && exprList.length > 1) {
+ const exprList = JSONPath.toPathParts(expr);
+ if (exprList[0] && exprList[0].type === 'root' && exprList.length > 1) {
exprList.shift();
}
this._hasParentSelector = null;
+ this._json = json; // Store root for parent selector navigation
const result = this
._trace(
exprList, json, ['$'], currParent, currParentProperty, callback
@@ -294,7 +295,7 @@ JSONPath.prototype._getPreferredOutput = function (ea) {
case 'all': {
const path = Array.isArray(ea.path)
? ea.path
- : JSONPath.toPathArray(ea.path);
+ : JSONPath.toPathParts(ea.path);
ea.pointer = JSONPath.toPointer(path);
ea.path = typeof ea.path === 'string'
? ea.path
@@ -350,10 +351,10 @@ JSONPath.prototype._trace = function (
hasArrExpr
};
this._handleCallback(retObj, callback, 'value');
- return retObj;
+ return [retObj];
}
- const loc = expr[0], x = expr.slice(1);
+ const token = expr[0], x = expr.slice(1);
// We need to gather the return value of recursive trace calls in order to
// do the parent sel computation.
@@ -375,187 +376,301 @@ JSONPath.prototype._trace = function (
ret.push(elems);
}
}
- if ((typeof loc !== 'string' || literalPriority) && val &&
- Object.hasOwn(val, loc)
- ) { // simple case--directly follow property
- addRet(this._trace(x, val[loc], push(path, loc), val, loc, callback,
- hasArrExpr));
- // eslint-disable-next-line unicorn/prefer-switch -- Part of larger `if`
- } else if (loc === '*') { // all child properties
- this._walk(val, (m) => {
+
+ // Fast path for primitive tokens (strings and numbers)
+ if (typeof token === 'string') {
+ // Simple property access
+ if (val && Object.hasOwn(val, token)) {
addRet(this._trace(
- x, val[m], push(path, m), val, m, callback, true, true
+ x, val[token], push(path, token), val, token, callback, hasArrExpr
));
- });
- } else if (loc === '..') { // all descendent parent properties
- // Check remaining expression with val's immediate children
- addRet(
- this._trace(x, val, path, parent, parentPropName, callback,
- hasArrExpr)
- );
- this._walk(val, (m) => {
- // We don't join m and x here because we only want parents,
- // not scalar values
- if (typeof val[m] === 'object') {
- // Keep going with recursive descent on val's
- // object children
+ }
+ } else if (typeof token === 'number') {
+ // Simple numeric index access
+ if (Array.isArray(val) && token >= 0 && token < val.length) {
+ addRet(this._trace(
+ x, val[token], push(path, token), val, token, callback, hasArrExpr
+ ));
+ }
+ } else if (token && typeof token === 'object' && token.type) {
+ // Handle complex token objects
+ switch (token.type) {
+ case 'root': // $
+ addRet(this._trace(x, val, path, null, null, callback, hasArrExpr));
+ break;
+
+ case 'property': {
+ const propName = token.value;
+ // Check if property exists (escaped flag just means it's not wildcard)
+ if (val && Object.hasOwn(val, propName)) {
addRet(this._trace(
- expr.slice(), val[m], push(path, m), val, m, callback, true
+ x, val[propName], push(path, propName), val, propName, callback,
+ hasArrExpr, true
));
}
- });
- // The parent sel computation is handled in the frame above using the
- // ancestor object of val
- } else if (loc === '^') {
- // This is not a final endpoint, so we do not invoke the callback here
- this._hasParentSelector = true;
- return {
- path: path.slice(0, -1),
- expr: x,
- isParentSelector: true
- };
- } else if (loc === '~') { // property name
- retObj = {
- path: push(path, loc),
- value: parentPropName,
- parent,
- parentProperty: null
- };
- this._handleCallback(retObj, callback, 'property');
- return retObj;
- } else if (loc === '$') { // root only
- addRet(this._trace(x, val, path, null, null, callback, hasArrExpr));
- } else if ((/^(-?\d*):(-?\d*):?(\d*)$/u).test(loc)) { // [start:end:step] Python slice syntax
- addRet(
- this._slice(loc, x, val, path, parent, parentPropName, callback)
- );
- } else if (loc.indexOf('?(') === 0) { // [?(expr)] (filtering)
- if (this.currEval === false) {
- throw new Error('Eval [?(expr)] prevented in JSONPath expression.');
- }
- const safeLoc = loc.replace(/^\?\((.*?)\)$/u, '$1');
- // check for a nested filter expression
- const nested = (/@.?([^?]*)[['](\??\(.*?\))(?!.\)\])[\]']/gu).exec(safeLoc);
- if (nested) {
- // find if there are matches in the nested expression
- // add them to the result set if there is at least one match
+ break;
+ }
+
+ case 'wildcard': // *
this._walk(val, (m) => {
- const npath = [nested[2]];
- const nvalue = nested[1]
- ? val[m][nested[1]]
- : val[m];
- const filterResults = this._trace(npath, nvalue, path,
- parent, parentPropName, callback, true);
- if (filterResults.length > 0) {
- addRet(this._trace(x, val[m], push(path, m), val,
- m, callback, true));
- }
+ addRet(this._trace(
+ x, val[m], push(path, m), val, m, callback, true, true
+ ));
});
- } else {
+ break;
+
+ case 'descent': // ..
+ // Check remaining expression with val's immediate children
+ addRet(
+ this._trace(x, val, path, parent, parentPropName, callback,
+ hasArrExpr)
+ );
this._walk(val, (m) => {
- if (this._eval(safeLoc, val[m], m, path, parent,
- parentPropName)) {
- addRet(this._trace(x, val[m], push(path, m), val, m,
- callback, true));
+ // We don't join m and x here because we only want parents,
+ // not scalar values
+ if (typeof val[m] === 'object') {
+ // Keep going with recursive descent on val's
+ // object children
+ addRet(this._trace(
+ expr.slice(), val[m], push(path, m), val, m, callback, true
+ ));
}
});
- }
- } else if (loc[0] === '(') { // [(expr)] (dynamic property/index)
- if (this.currEval === false) {
- throw new Error('Eval [(expr)] prevented in JSONPath expression.');
- }
- // As this will resolve to a property name (but we don't know it
- // yet), property and parent information is relative to the
- // parent of the property to which this expression will resolve
- addRet(this._trace(unshift(
- this._eval(
- loc, val, path.at(-1),
- path.slice(0, -1), parent, parentPropName
- ),
- x
- ), val, path, parent, parentPropName, callback, hasArrExpr));
- } else if (loc[0] === '@') { // value type: @boolean(), etc.
- let addType = false;
- const valueType = loc.slice(1, -2);
- switch (valueType) {
- case 'scalar':
- if (!val || !(['object', 'function'].includes(typeof val))) {
- addType = true;
- }
break;
- case 'boolean': case 'string': case 'undefined': case 'function':
- if (typeof val === valueType) {
- addType = true;
+
+ case 'parent': // ^
+ // This is not a final endpoint, so we do not invoke the callback here
+ // Only allow parent selector if we're not already at root
+ if (path.length > 1) {
+ this._hasParentSelector = true;
+ ret.push({
+ path: path.slice(0, -1),
+ expr: x,
+ isParentSelector: true
+ });
}
break;
- case 'integer':
- if (Number.isFinite(val) && !(val % 1)) {
- addType = true;
- }
+
+ case 'propertyName': // ~
+ retObj = {
+ path: push(path, '~'),
+ value: parentPropName,
+ parent,
+ parentProperty: null
+ };
+ this._handleCallback(retObj, callback, 'property');
+ ret.push(retObj);
break;
- case 'number':
- if (Number.isFinite(val)) {
- addType = true;
+
+ case 'index': {
+ const idx = token.value;
+ if ((Array.isArray(val) && idx >= 0 && idx < val.length) ||
+ (val && Object.hasOwn(val, idx))) {
+ addRet(this._trace(
+ x, val[idx], push(path, idx), val, idx, callback,
+ hasArrExpr, true
+ ));
}
break;
- case 'nonFinite':
- if (typeof val === 'number' && !Number.isFinite(val)) {
- addType = true;
- }
+ }
+
+ case 'slice':
+ addRet(
+ this._slice(token, x, val, path, parent, parentPropName, callback)
+ );
break;
- case 'object':
- if (val && typeof val === valueType) {
- addType = true;
+
+ case 'filter': {
+ if (this.currEval === false) {
+ throw new Error('Eval [?(expr)] prevented in JSONPath expression.');
+ }
+
+ // Quick check: Does this filter have nested paths?
+ const hasNesting = token.expression.includes('[?(');
+
+ if (!hasNesting) {
+ // Fast path: No nesting, skip extraction
+ this._walk(val, (m) => {
+ if (this._eval(token.expression, val[m], m, path,
+ parent, parentPropName)) {
+ addRet(this._trace(x, val[m], push(path, m), val, m,
+ callback, true));
+ }
+ });
+ } else {
+ // Slow path: Extract and handle nested filters
+ const {expression: modifiedExpr, nestedPaths} =
+ this._extractNestedFilters(token.expression);
+
+ // Check if expression is JUST a nested path (no other JavaScript)
+ // If so, we need to check array length for truthiness
+ const isSingleNestedPath = nestedPaths.length === 1 &&
+ modifiedExpr.trim() === '_$_jp0';
+
+ // Evaluate filter for each item
+ this._walk(val, (m) => {
+ // Evaluate nested paths in context of current item
+ const nestedResults = {};
+ for (const [i, nestedPath] of nestedPaths.entries()) {
+ // Convert @ to $ for parsing (@ means current value)
+ const pathForParsing = nestedPath.replace(/^@/u, '$');
+ try {
+ const nestedTokens = JSONPath.toPathParts(pathForParsing);
+ // Evaluate nested path on current item
+ const nestedResult = this._trace(
+ nestedTokens,
+ val[m],
+ push(path, m),
+ val,
+ m,
+ null, // no callback for nested evaluation
+ true
+ );
+ // Extract values from result objects
+ nestedResults[`_$_jp${i}`] =
+ nestedResult.map((r) => r.value);
+ } catch (e) {
+ // If nested evaluation fails, treat as no matches
+ nestedResults[`_$_jp${i}`] = [];
+ }
+ }
+
+ // Add nested results to sandbox temporarily
+ const originalSandbox = {...this.currSandbox};
+ Object.assign(this.currSandbox, nestedResults);
+
+ try {
+ // For single nested path, check if array has elements
+ // (empty arrays are truthy in JS but should be falsy in filter)
+ const matches = isSingleNestedPath
+ ? nestedResults._$_jp0.length > 0
+ : this._eval(modifiedExpr, val[m], m, path,
+ parent, parentPropName);
+
+ if (matches) {
+ addRet(this._trace(x, val[m], push(path, m), val, m,
+ callback, true));
+ }
+ } finally {
+ // Restore original sandbox (remove nested result placeholders)
+ this.currSandbox = originalSandbox;
+ }
+ });
}
break;
- case 'array':
- if (Array.isArray(val)) {
- addType = true;
+ }
+
+ case 'dynamic': {
+ if (this.currEval === false) {
+ throw new Error('Eval [(expr)] prevented in JSONPath expression.');
}
+ // As this will resolve to a property name (but we don't know it
+ // yet), property and parent information is relative to the
+ // parent of the property to which this expression will resolve
+ addRet(this._trace(unshift(
+ this._eval(
+ token.expression, val, path.at(-1),
+ path.slice(0, -1), parent, parentPropName
+ ),
+ x
+ ), val, path, parent, parentPropName, callback, hasArrExpr));
break;
- case 'other':
- addType = this.currOtherTypeCallback(
- val, path, parent, parentPropName
- );
+ }
+
+ case 'typeOperator': {
+ let addType = false;
+ const {valueType} = token;
+ switch (valueType) {
+ case 'scalar':
+ if (!val || !(['object', 'function'].includes(typeof val))) {
+ addType = true;
+ }
+ break;
+ case 'boolean': case 'string': case 'undefined': case 'function':
+ if (typeof val === valueType) {
+ addType = true;
+ }
+ break;
+ case 'integer':
+ if (Number.isFinite(val) && !(val % 1)) {
+ addType = true;
+ }
+ break;
+ case 'number':
+ if (Number.isFinite(val)) {
+ addType = true;
+ }
+ break;
+ case 'nonFinite':
+ if (typeof val === 'number' && !Number.isFinite(val)) {
+ addType = true;
+ }
+ break;
+ case 'object':
+ if (val && typeof val === valueType) {
+ addType = true;
+ }
+ break;
+ case 'array':
+ if (Array.isArray(val)) {
+ addType = true;
+ }
+ break;
+ case 'other':
+ addType = this.currOtherTypeCallback(
+ val, path, parent, parentPropName
+ );
+ break;
+ case 'null':
+ if (val === null) {
+ addType = true;
+ }
+ break;
+ /* c8 ignore next 2 */
+ default:
+ throw new TypeError('Unknown value type ' + valueType);
+ }
+ if (addType) {
+ retObj = {
+ path, value: val, parent, parentProperty: parentPropName
+ };
+ this._handleCallback(retObj, callback, 'value');
+ ret.push(retObj);
+ }
break;
- case 'null':
- if (val === null) {
- addType = true;
+ }
+
+ case 'multiProperty': {
+ const parts = token.properties;
+ const escapedFlags = token.escaped || [];
+ for (const [i, part] of parts.entries()) {
+ // Check if part is a number (multi-index) or string (multi-property)
+ let partToken;
+ if (typeof part === 'number') {
+ partToken = {type: 'index', value: part};
+ } else {
+ const isEscaped = escapedFlags[i] || false;
+ partToken = {
+ type: 'property',
+ value: part,
+ escaped: isEscaped
+ };
+ }
+ addRet(this._trace(
+ unshift(partToken, x), val, path, parent, parentPropName,
+ callback, true
+ ));
}
break;
- /* c8 ignore next 2 */
- default:
- throw new TypeError('Unknown value type ' + valueType);
- }
- if (addType) {
- retObj = {path, value: val, parent, parentProperty: parentPropName};
- this._handleCallback(retObj, callback, 'value');
- return retObj;
- }
- // `-escaped property
- } else if (loc[0] === '`' && val && Object.hasOwn(val, loc.slice(1))) {
- const locProp = loc.slice(1);
- addRet(this._trace(
- x, val[locProp], push(path, locProp), val, locProp, callback,
- hasArrExpr, true
- ));
- } else if (loc.includes(',')) { // [name1,name2,...]
- const parts = loc.split(',');
- for (const part of parts) {
- addRet(this._trace(
- unshift(part, x), val, path, parent, parentPropName, callback,
- true
- ));
}
- // simple case--directly follow property
- } else if (
- !literalPriority && val && Object.hasOwn(val, loc)
- ) {
- addRet(
- this._trace(x, val[loc], push(path, loc), val, loc, callback,
- hasArrExpr, true)
- );
+ }
+ } else if ((typeof token !== 'string' || literalPriority) && val &&
+ Object.hasOwn(val, token)
+ ) { // simple case--directly follow property (for object tokens or with literalPriority)
+ addRet(this._trace(x, val[token], push(path, token), val, token, callback,
+ hasArrExpr));
}
+ // Note: Legacy string token handling removed - now handled by fast path above
// We check the resulting values for parent selections. For parent
// selections we discard the value object and continue the trace with the
@@ -564,9 +679,23 @@ JSONPath.prototype._trace = function (
for (let t = 0; t < ret.length; t++) {
const rett = ret[t];
if (rett && rett.isParentSelector) {
+ // Navigate from root to the parent path to get correct parent context
+ // rett.path is the path with last element removed (e.g., ['$', 'children'])
+ let resultVal = this._json;
+ let resultParent = null;
+ let resultParentProp = null;
+
+ // Navigate from root following the path
+ // Start at index 1 to skip '$'
+ for (let i = 1; i < rett.path.length; i++) {
+ resultParent = resultVal;
+ resultParentProp = rett.path[i];
+ resultVal = resultVal[rett.path[i]];
+ }
+
const tmp = this._trace(
- rett.expr, val, rett.path, parent, parentPropName, callback,
- hasArrExpr
+ rett.expr, resultVal, rett.path, resultParent,
+ resultParentProp, callback, hasArrExpr
);
if (Array.isArray(tmp)) {
ret[t] = tmp[0];
@@ -599,16 +728,236 @@ JSONPath.prototype._walk = function (val, f) {
}
};
+/**
+ * Extract nested JSONPath expressions from a filter expression.
+ * @param {string} expr - Filter expression (e.g., "@.children[?(@.price<10)]")
+ * @returns {{expression: string, nestedPaths: string[]}} Modified expression and extracted paths
+ */
+JSONPath.prototype._extractNestedFilters = function (expr) {
+ // Check cache first
+ const cache = JSONPath.filterExtractionCache;
+ if (cache[expr]) {
+ // Return shallow clone to prevent mutation
+ return {
+ expression: cache[expr].expression,
+ nestedPaths: [...cache[expr].nestedPaths]
+ };
+ }
+
+ const nestedPaths = [];
+ let result = expr;
+ let placeholderCount = 0;
+
+ // We need to find patterns like @.path[?(...)] or @[?(...)], etc.
+ // Use a stack-based approach to handle nested brackets properly
+
+ /**
+ * Find the next JSONPath expression starting with @.
+ * @param {string} str - String to search
+ * @param {number} startPos - Position to start searching
+ * @returns {{start: number, end: number, path: string} | null}
+ */
+ function findNextNestedPath (str, startPos) {
+ let i = startPos;
+
+ // Find next @ that's not in a string or regex literal
+ while (i < str.length) {
+ const ch = str[i];
+
+ // Skip string literals
+ if (ch === '"' || ch === "'") {
+ const quote = ch;
+ i++;
+ while (i < str.length) {
+ if (str[i] === '\\' && i + 1 < str.length) {
+ i += 2; // Skip escaped character
+ } else if (str[i] === quote) {
+ i++;
+ break;
+ } else {
+ i++;
+ }
+ }
+ continue;
+ }
+
+ // Skip regex literals (simplified detection)
+ if (ch === '/' && i > 0) {
+ // Check if this might be a regex (not division)
+ // Look back for operators that could precede a regex
+ const prevNonSpace = str.slice(0, i).trimEnd().slice(-1);
+ if ('=([{,;:!&|?'.includes(prevNonSpace) || i === startPos) {
+ i++;
+ while (i < str.length) {
+ if (str[i] === '\\' && i + 1 < str.length) {
+ i += 2;
+ } else if (str[i] === '/') {
+ i++;
+ // Skip regex flags
+ while (i < str.length && (/[gimsuvy]/u).test(str[i])) {
+ i++;
+ }
+ break;
+ } else {
+ i++;
+ }
+ }
+ continue;
+ }
+ }
+
+ // Found @ - check if it's followed by JSONPath syntax
+ if (ch === '@') {
+ const pathStart = i;
+ i++; // Move past @
+
+ // Check if there's path syntax after @
+ // Could be: @.prop, @[, @.., @@
+ if (i >= str.length) {
+ return null;
+ }
+
+ let hasPathSyntax = false;
+ let path = '@';
+
+ // Parse the JSONPath expression
+ while (i < str.length) {
+ const c = str[i];
+
+ // Path components
+ if (c === '.' || c === '[' || c === '*' ||
+ c === '^' || c === '~') {
+ hasPathSyntax = true;
+ path += c;
+ i++;
+
+ // Handle bracket notation with bracket matching
+ if (c === '[') {
+ let depth = 1;
+ /* eslint-disable unicorn/prefer-switch --
+ Complex bracket matching with nested quotes */
+ while (i < str.length && depth > 0) {
+ if (str[i] === '\\' && i + 1 < str.length) {
+ path += str[i] + str[i + 1];
+ i += 2;
+ } else if (str[i] === '"' || str[i] === "'") {
+ // Handle quoted strings in brackets
+ const q = str[i];
+ path += str[i];
+ i++;
+ while (i < str.length && str[i] !== q) {
+ if (str[i] === '\\' && i + 1 < str.length) {
+ path += str[i] + str[i + 1];
+ i += 2;
+ } else {
+ path += str[i];
+ i++;
+ }
+ }
+ if (i < str.length) {
+ path += str[i];
+ i++;
+ }
+ } else if (str[i] === '[') {
+ depth++;
+ path += str[i];
+ i++;
+ } else if (str[i] === ']') {
+ depth--;
+ path += str[i];
+ i++;
+ } else {
+ path += str[i];
+ i++;
+ }
+ }
+ /* eslint-enable unicorn/prefer-switch --
+ Re-enable after bracket matching section */
+ }
+ } else if ((/[\w$]/u).test(c)) {
+ // Property name characters
+ hasPathSyntax = true;
+ path += c;
+ i++;
+ } else {
+ // End of path
+ break;
+ }
+ }
+
+ // Check if this path contains a filter (has [?(...)])
+ // Only extract paths that have filters to avoid unnecessary evaluation
+ if (hasPathSyntax && path.includes('[?')) {
+ return {
+ start: pathStart,
+ end: i,
+ path
+ };
+ }
+
+ // No filter found, continue searching
+ continue;
+ }
+
+ i++;
+ }
+
+ return null;
+ }
+
+ // Extract all nested paths
+ let searchPos = 0;
+ const replacements = [];
+
+ while (searchPos < result.length) {
+ const found = findNextNestedPath(result, searchPos);
+ if (!found) {
+ break;
+ }
+
+ // Store the replacement to be made
+ replacements.push({
+ start: found.start,
+ end: found.end,
+ path: found.path,
+ placeholder: `_$_jp${placeholderCount}`
+ });
+
+ nestedPaths.push(found.path);
+ placeholderCount++;
+ searchPos = found.end;
+ }
+
+ // Apply replacements in reverse order to maintain positions
+ for (let i = replacements.length - 1; i >= 0; i--) {
+ const {start, end, placeholder} = replacements[i];
+ result = result.slice(0, start) + placeholder + result.slice(end);
+ }
+
+ // Cache the result
+ const extractionResult = {
+ expression: result,
+ nestedPaths
+ };
+ cache[expr] = extractionResult;
+
+ return {
+ expression: result,
+ nestedPaths: [...nestedPaths]
+ };
+};
+
JSONPath.prototype._slice = function (
- loc, expr, val, path, parent, parentPropName, callback
+ token, expr, val, path, parent, parentPropName, callback
) {
if (!Array.isArray(val)) {
return undefined;
}
- const len = val.length, parts = loc.split(':'),
- step = (parts[2] && Number.parseInt(parts[2])) || 1;
- let start = (parts[0] && Number.parseInt(parts[0])) || 0,
- end = (parts[1] && Number.parseInt(parts[1])) || len;
+ const len = val.length;
+ let start = token.start === null ? 0 : token.start;
+ let end = token.end === null ? len : token.end;
+ const step = token.step === null ? 1 : token.step;
+
start = (start < 0) ? Math.max(0, start + len) : Math.min(len, start);
end = (end < 0) ? Math.max(0, end + len) : Math.min(len, end);
const ret = [];
@@ -691,90 +1040,709 @@ JSONPath.prototype._eval = function (
// Could store the cache object itself
JSONPath.cache = {};
+JSONPath.pathPartsCache = {};
+JSONPath.filterExtractionCache = {};
/**
- * @param {string[]} pathArr Array to convert
+ * @param {string[]|object[]} pathArr Array to convert
* @returns {string} The path string
*/
JSONPath.toPathString = function (pathArr) {
const x = pathArr, n = x.length;
let p = '$';
for (let i = 1; i < n; i++) {
- if (!(/^(~|\^|@.*?\(\))$/u).test(x[i])) {
- p += (/^[0-9*]+$/u).test(x[i]) ? ('[' + x[i] + ']') : ("['" + x[i] + "']");
+ const item = x[i];
+
+ // Handle both old string format and new token format
+ if (typeof item === 'number') {
+ // Array index
+ p += '[' + item + ']';
+ } else if (typeof item === 'string') {
+ // Legacy path
+ if (!(/^(~|\^|@.*?\(\))$/u).test(item)) {
+ p += (/^[0-9*]+$/u).test(item) ? ('[' + item + ']') : ("['" + item + "']");
+ }
+ } else if (item && typeof item === 'object') {
+ // New token format
+ switch (item.type) {
+ case 'property':
+ p += "['" + item.value + "']";
+ break;
+ case 'index':
+ p += '[' + item.value + ']';
+ break;
+ case 'wildcard':
+ p += '[*]';
+ break;
+ case 'slice':
+ p += '[' + item.raw + ']';
+ break;
+ case 'filter':
+ p += '[?(' + item.expression + ')]';
+ break;
+ case 'dynamic':
+ p += '[(' + item.expression + ')]';
+ break;
+ case 'typeOperator':
+ p += '@' + item.valueType + '()';
+ break;
+ case 'multiProperty':
+ p += "['" + item.properties.join("','") + "']";
+ break;
+ // Special operators don't add to path string
+ case 'root':
+ case 'descent':
+ case 'parent':
+ case 'propertyName':
+ break;
+ }
}
}
return p;
};
/**
- * @param {string} pointer JSON Path
+ * Converts path array to JSON Pointer format.
+ * Handles both legacy string arrays and new token objects.
+ * @param {string[]|object[]} pointer - Path array
* @returns {string} JSON Pointer
*/
JSONPath.toPointer = function (pointer) {
const x = pointer, n = x.length;
let p = '';
for (let i = 1; i < n; i++) {
- if (!(/^(~|\^|@.*?\(\))$/u).test(x[i])) {
- p += '/' + x[i].toString()
- .replaceAll('~', '~0')
- .replaceAll('/', '~1');
+ const item = x[i];
+ let value;
+
+ // Handle different formats
+ if (typeof item === 'number') {
+ value = String(item);
+ } else if (typeof item === 'string') {
+ // Legacy string format or special operators
+ if ((/^(~|\^|@.*?\(\))$/u).test(item)) {
+ continue; // Skip special operators
+ }
+ value = item;
+ } else if (item && typeof item === 'object') {
+ // New token format
+ switch (item.type) {
+ case 'property': {
+ const {value: propValue} = item;
+ value = propValue;
+ break;
+ }
+ case 'index': {
+ const {value: indexValue} = item;
+ value = String(indexValue);
+ break;
+ }
+ // Skip special operators
+ case 'root':
+ case 'wildcard':
+ case 'descent':
+ case 'parent':
+ case 'propertyName':
+ case 'filter':
+ case 'dynamic':
+ case 'slice':
+ case 'typeOperator':
+ case 'multiProperty':
+ continue;
+ default:
+ continue;
+ }
+ } else {
+ continue;
}
+
+ // Escape ~ and / per JSON Pointer spec
+ p += '/' + value
+ .replaceAll('~', '~0')
+ .replaceAll('/', '~1');
}
return p;
};
+
+/**
+ * Parse a JSONPath expression into structured tokens.
+ * @param {string} expr - JSONPath expression
+ * @returns {Array} Array of tokens
+ */
/**
- * @param {string} expr Expression to convert
- * @returns {string[]}
+ * Parses a JSONPath expression into structured token objects.
+ * @param {string} expr - JSONPath expression to parse
+ * @returns {object[]} Array of token objects
*/
-JSONPath.toPathArray = function (expr) {
- const {cache} = JSONPath;
+JSONPath.toPathParts = function (expr) {
+ const cache = JSONPath.pathPartsCache;
if (cache[expr]) {
- return cache[expr].concat();
- }
- const subx = [];
- const normalized = expr
- // Properties
- .replaceAll(
- /@(?:null|boolean|number|string|integer|undefined|nonFinite|scalar|array|object|function|other)\(\)/gu,
- ';$&;'
- )
- // Parenthetical evaluations (filtering and otherwise), directly
- // within brackets or single quotes
- .replaceAll(/[['](\??\(.*?\))[\]'](?!.\])/gu, function ($0, $1) {
- return '[#' + (subx.push($1) - 1) + ']';
- })
- // Escape periods and tildes within properties
- .replaceAll(/\[['"]([^'\]]*)['"]\]/gu, function ($0, prop) {
- return "['" + prop
- .replaceAll('.', '%@%')
- .replaceAll('~', '%%@@%%') +
- "']";
- })
- // Properties operator
- .replaceAll('~', ';~;')
- // Split by property boundaries
- .replaceAll(/['"]?\.['"]?(?![^[]*\])|\[['"]?/gu, ';')
- // Reinsert periods within properties
- .replaceAll('%@%', '.')
- // Reinsert tildes within properties
- .replaceAll('%%@@%%', '~')
- // Parent
- .replaceAll(/(?:;)?(\^+)(?:;)?/gu, function ($0, ups) {
- return ';' + ups.split('').join(';') + ';';
- })
- // Descendents
- .replaceAll(/;;;|;;/gu, ';..;')
- // Remove trailing
- .replaceAll(/;$|'?\]|'$/gu, '');
-
- const exprList = normalized.split(';').map(function (exp) {
- const match = exp.match(/#(\d+)/u);
- return !match || !match[1] ? exp : subx[match[1]];
- });
- cache[expr] = exprList;
- return cache[expr].concat();
+ // Shallow clone array, shallow clone object tokens
+ // (tokens are simple objects with no nested objects)
+ return cache[expr].map((token) => (
+ typeof token === 'object' && token !== null ? {...token} : token
+ ));
+ }
+
+ const tokens = [];
+ let i = 0;
+
+ // Handle empty path - treat as empty property access
+ if (expr === '') {
+ // Hybrid token: empty property is a string
+ tokens.push('');
+ cache[expr] = tokens;
+ return cache[expr].map((token) => (
+ typeof token === 'object' && token !== null ? {...token} : token
+ ));
+ }
+
+ /**
+ * Extract balanced content between delimiters.
+ * @param {number} start - Starting position
+ * @param {string} open - Opening delimiter
+ * @param {string} close - Closing delimiter
+ * @throws {SyntaxError} If delimiters are unbalanced
+ * @returns {{content: string, end: number}} Extracted content and end position
+ */
+ function extractBalanced (start, open, close) {
+ let depth = 1;
+ let j = start;
+ while (j < expr.length && depth > 0) {
+ if (expr[j] === open) {
+ depth++;
+ } else if (expr[j] === close) {
+ depth--;
+ }
+ j++;
+ }
+ if (depth !== 0) {
+ throw new SyntaxError(
+ `Unbalanced ${open}${close} in expression at position ${start}`
+ );
+ }
+ return {content: expr.slice(start, j - 1), end: j};
+ }
+
+ /**
+ * Extract quoted string.
+ * @param {number} start - Starting position (after quote)
+ * @param {string} quote - Quote character
+ * @throws {SyntaxError} If string is unterminated
+ * @returns {{content: string, end: number, escaped: boolean}} Extracted content, end position, and whether it's backtick-escaped
+ */
+ function extractQuoted (start, quote) {
+ let j = start;
+ let content = '';
+ let escaped = false;
+
+ while (j < expr.length) {
+ if (expr[j] === '\\' && j + 1 < expr.length) {
+ // Handle backslash escape sequences
+ content += expr[j + 1];
+ j += 2;
+ } else if (expr[j] === '`' && j + 1 < expr.length) {
+ // Handle backtick escape - backtick escapes next char
+ content += expr[j + 1];
+ escaped = true;
+ j += 2;
+ } else if (expr[j] === quote) {
+ return {content, end: j + 1, escaped};
+ } else {
+ content += expr[j];
+ j++;
+ }
+ }
+ throw new SyntaxError(`Unterminated string at position ${start - 1}`);
+ }
+
+ /**
+ * Handle dot notation (.property or ..descendant).
+ * @throws {SyntaxError} If malformed
+ * @returns {void}
+ */
+ function handleDotNotation () {
+ if (i + 1 < expr.length && expr[i + 1] === '.') {
+ // Descendant (..)
+ tokens.push({type: 'descent'});
+ i += 2;
+ } else {
+ // Skip the dot and parse property name
+ i++;
+ if (i >= expr.length) {
+ throw new SyntaxError('Unexpected end after dot at position ' + (i - 1));
+ }
+
+ // Check what follows the dot
+ switch (expr[i]) {
+ case '*':
+ tokens.push({type: 'wildcard'});
+ i++;
+ break;
+ case '`':
+ // Backtick escapes the next character
+ i++; // Skip backtick
+ if (i >= expr.length) {
+ throw new SyntaxError(
+ 'Unexpected end after backtick at position ' + (i - 1)
+ );
+ }
+ // The escaped character becomes the property name
+ tokens.push({
+ type: 'property',
+ value: expr[i],
+ escaped: true
+ });
+ i++;
+ break;
+ case '[':
+ // Dot followed by bracket: interpret as descent
+ // e.g., $.[?(...)] becomes $ .. [?(...)]
+ tokens.push({type: 'descent'});
+ break;
+ default: {
+ // Regular property name (until next special char)
+ let propName = '';
+ while (i < expr.length && !(/[.[\]^~@*]/u).test(expr[i])) {
+ propName += expr[i];
+ i++;
+ }
+ if (propName) {
+ // Hybrid token: use string for unescaped properties
+ tokens.push(propName);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Handle bracket notation [...].
+ * @throws {SyntaxError} If malformed
+ * @returns {void}
+ */
+ function handleBracketNotation () {
+ i++; // Skip [
+ if (i >= expr.length) {
+ throw new SyntaxError('Unexpected end after [ at position ' + (i - 1));
+ }
+
+ // Skip whitespace
+ while (i < expr.length && (/\s/u).test(expr[i])) {
+ i++;
+ }
+
+ const ch = expr[i];
+
+ // Wildcard [*]
+ if (ch === '*') {
+ i++;
+ // Skip whitespace and closing bracket
+ while (i < expr.length && (/\s/u).test(expr[i])) {
+ i++;
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError('Expected ] after * at position ' + i);
+ }
+ i++;
+ tokens.push({type: 'wildcard'});
+ return;
+ }
+
+ // Filter [?(expression)]
+ if (ch === '?') {
+ if (i + 1 >= expr.length || expr[i + 1] !== '(') {
+ throw new SyntaxError(
+ 'Expected ( after ? at position ' + i
+ );
+ }
+ i += 2; // Skip ?(
+ const result = extractBalanced(i, '(', ')');
+ const {content: expression} = result;
+ i = result.end;
+
+ // Skip whitespace and closing bracket
+ while (i < expr.length && (/\s/u).test(expr[i])) {
+ i++;
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError(
+ 'Expected ] after filter at position ' + i
+ );
+ }
+ i++;
+ tokens.push({type: 'filter', expression});
+ return;
+ }
+
+ // Dynamic [(expression)]
+ if (ch === '(') {
+ i++; // Skip (
+ const result = extractBalanced(i, '(', ')');
+ const {content: expression} = result;
+ i = result.end;
+
+ // Skip whitespace and closing bracket
+ while (i < expr.length && (/\s/u).test(expr[i])) {
+ i++;
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError(
+ 'Expected ] after dynamic expression at position ' + i
+ );
+ }
+ i++;
+ tokens.push({type: 'dynamic', expression});
+ return;
+ }
+
+ // Quoted property ['name'] or ["name"]
+ if (ch === "'" || ch === '"') {
+ const quote = ch;
+ i++; // Skip opening quote
+ const result = extractQuoted(i, quote);
+ const {content, escaped} = result;
+ i = result.end;
+
+ // Skip whitespace
+ while (i < expr.length && (/\s/u).test(expr[i])) {
+ i++;
+ }
+
+ // Check for comma (multi-property)
+ if (expr[i] === ',') {
+ const properties = [content];
+ const escapedFlags = [escaped];
+ while (expr[i] === ',') {
+ i++; // Skip comma
+ // Skip whitespace
+ while (i < expr.length && (/\s/u).test(expr[i])) {
+ i++;
+ }
+ if (expr[i] !== "'" && expr[i] !== '"') {
+ throw new SyntaxError(
+ 'Expected quoted property after comma at position ' + i
+ );
+ }
+ const q = expr[i];
+ i++;
+ const r = extractQuoted(i, q);
+ properties.push(r.content);
+ escapedFlags.push(r.escaped);
+ i = r.end;
+ // Skip whitespace
+ while (i < expr.length && (/\s/u).test(expr[i])) {
+ i++;
+ }
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError(
+ 'Expected ] after multi-property at position ' + i
+ );
+ }
+ i++;
+ tokens.push({
+ type: 'multiProperty',
+ properties,
+ escaped: escapedFlags
+ });
+ return;
+ }
+
+ if (expr[i] !== ']') {
+ throw new SyntaxError(
+ 'Expected ] after quoted property at position ' + i
+ );
+ }
+ i++;
+ // Check if quoted property is wildcard
+ if (content === '*' && !escaped) {
+ tokens.push({type: 'wildcard'});
+ } else if (escaped) {
+ // Keep object for escaped properties (metadata needed)
+ tokens.push({type: 'property', value: content, escaped: true});
+ } else {
+ // Hybrid token: use string for unescaped properties
+ tokens.push(content);
+ }
+ return;
+ }
+
+ // Number (index, slice, or multi-index)
+ if ((/[-\d]/u).test(ch) || ch === ':') {
+ let numStr = '';
+ while (i < expr.length && (/[-\d:]/u).test(expr[i])) {
+ numStr += expr[i];
+ i++;
+ }
+
+ // Skip whitespace
+ while (i < expr.length && (/\s/u).test(expr[i])) {
+ i++;
+ }
+
+ // Check for comma (multi-index like [0,1,2])
+ if (expr[i] === ',') {
+ const indices = [Number.parseInt(numStr)];
+ while (expr[i] === ',') {
+ i++; // Skip comma
+ // Skip whitespace
+ while (i < expr.length && (/\s/u).test(expr[i])) {
+ i++;
+ }
+ // Read next number
+ let nextNum = '';
+ while (i < expr.length && (/[-\d]/u).test(expr[i])) {
+ nextNum += expr[i];
+ i++;
+ }
+ indices.push(Number.parseInt(nextNum));
+ // Skip whitespace
+ while (i < expr.length && (/\s/u).test(expr[i])) {
+ i++;
+ }
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError(
+ 'Expected ] after multi-index at position ' + i
+ );
+ }
+ i++;
+ // Create multiProperty token with numeric properties
+ tokens.push({type: 'multiProperty', properties: indices});
+ return;
+ }
+
+ if (expr[i] !== ']') {
+ throw new SyntaxError(
+ 'Expected ] after number at position ' + i
+ );
+ }
+ i++;
+
+ // Check if it's a slice (contains :)
+ if (numStr.includes(':')) {
+ const parts = numStr.split(':');
+ const start = parts[0] === ''
+ ? null
+ : Number.parseInt(parts[0]);
+ const end = parts[1] === ''
+ ? null
+ : Number.parseInt(parts[1]);
+ const step = parts.length > 2 && parts[2] !== ''
+ ? Number.parseInt(parts[2])
+ : null;
+ tokens.push({type: 'slice', start, end, step, raw: numStr});
+ } else {
+ // Simple index - Hybrid token: use number directly
+ const index = Number.parseInt(numStr);
+ tokens.push(index);
+ }
+ return;
+ }
+
+ // Unquoted property (identifier)
+ // In brackets, unquoted properties can have backtick escapes
+ let propName = '';
+ let escaped = false;
+ while (i < expr.length && expr[i] !== ']' && expr[i] !== ',' &&
+ !(/\s/u).test(expr[i])) {
+ if (expr[i] === '`' && i + 1 < expr.length &&
+ expr[i + 1] !== ']' && expr[i + 1] !== ',') {
+ // Backtick escapes next character
+ propName += expr[i + 1];
+ escaped = true;
+ i += 2;
+ } else {
+ propName += expr[i];
+ i++;
+ }
+ }
+
+ // Skip whitespace
+ while (i < expr.length && (/\s/u).test(expr[i])) {
+ i++;
+ }
+
+ // Check for comma (multi-property with unquoted names)
+ if (expr[i] === ',') {
+ const properties = [propName];
+ const escapedFlags = [escaped];
+ while (expr[i] === ',') {
+ i++; // Skip comma
+ // Skip whitespace
+ while (i < expr.length && (/\s/u).test(expr[i])) {
+ i++;
+ }
+ let prop = '';
+ let propEscaped = false;
+ while (i < expr.length && expr[i] !== ']' && expr[i] !== ',' &&
+ !(/\s/u).test(expr[i])) {
+ if (expr[i] === '`' && i + 1 < expr.length &&
+ expr[i + 1] !== ']' && expr[i + 1] !== ',') {
+ // Backtick escapes next character
+ prop += expr[i + 1];
+ propEscaped = true;
+ i += 2;
+ } else {
+ prop += expr[i];
+ i++;
+ }
+ }
+ if (!prop) {
+ throw new SyntaxError(
+ 'Expected property name after comma at position ' + i
+ );
+ }
+ properties.push(prop);
+ escapedFlags.push(propEscaped);
+ // Skip whitespace
+ while (i < expr.length && (/\s/u).test(expr[i])) {
+ i++;
+ }
+ }
+ if (expr[i] !== ']') {
+ throw new SyntaxError(
+ 'Expected ] after multi-property at position ' + i
+ );
+ }
+ i++;
+ tokens.push({
+ type: 'multiProperty',
+ properties,
+ escaped: escapedFlags
+ });
+ return;
+ }
+
+ if (expr[i] !== ']') {
+ throw new SyntaxError(
+ 'Expected ] after property at position ' + i
+ );
+ }
+ i++;
+ if (propName) {
+ if (escaped) {
+ // Keep object for escaped properties
+ tokens.push({type: 'property', value: propName, escaped: true});
+ } else {
+ // Hybrid token: use string for unescaped properties
+ tokens.push(propName);
+ }
+ }
+ }
+
+ /**
+ * Handle type operator `@type()`.
+ * @throws {SyntaxError} If malformed
+ * @returns {void}
+ */
+ function handleTypeOperator () {
+ i++; // Skip @
+ let typeName = '';
+ while (i < expr.length && (/[a-z]/ui).test(expr[i])) {
+ typeName += expr[i];
+ i++;
+ }
+ if (i + 1 >= expr.length || expr[i] !== '(' || expr[i + 1] !== ')') {
+ throw new SyntaxError(
+ 'Expected () after @' + typeName + ' at position ' + i
+ );
+ }
+ i += 2; // Skip ()
+ tokens.push({type: 'typeOperator', valueType: typeName});
+ }
+
+ // If path doesn't start with $, [, or other special char, add implicit root
+ if (expr.length > 0 && !['$', '[', '.', '^', '~', '@'].includes(expr[0])) {
+ tokens.push({type: 'root'});
+ // Prepend with a dot to make it valid for our parser
+ expr = '.' + expr;
+ }
+
+ // Main parsing loop
+ while (i < expr.length) {
+ const ch = expr[i];
+
+ switch (ch) {
+ case '$':
+ tokens.push({type: 'root'});
+ i++;
+ break;
+ case '.':
+ handleDotNotation();
+ break;
+ case '[':
+ handleBracketNotation();
+ break;
+ case '*':
+ // Wildcard (can appear after .. without a dot)
+ tokens.push({type: 'wildcard'});
+ i++;
+ break;
+ case '^':
+ // If parent selector comes right after root (or at start),
+ // add implicit empty string property
+ // This handles cases like "^" or "$^" which should be "['']^"
+ if (tokens.length === 0 ||
+ (tokens.length === 1 && tokens[0].type === 'root')) {
+ // Hybrid token: empty property is a string
+ tokens.push('');
+ }
+ tokens.push({type: 'parent'});
+ i++;
+ break;
+ case '~':
+ tokens.push({type: 'propertyName'});
+ i++;
+ break;
+ case '@':
+ // Check if this is a type operator like @boolean()
+ // Type operators have the pattern: @identifier()
+ if ((/^@[a-z]+\(\)/ui).test(expr.slice(i))) {
+ handleTypeOperator();
+ } else {
+ // Treat @ as part of a property name
+ let propName = '';
+ while (i < expr.length && (/[\w$@\\]/u).test(expr[i])) {
+ propName += expr[i];
+ i++;
+ }
+ if (propName) {
+ // Hybrid token: use string for unescaped properties
+ tokens.push(propName);
+ }
+ }
+ break;
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ // Skip whitespace
+ i++;
+ break;
+ default:
+ // Try to parse as identifier (property name)
+ if ((/[\w$]/u).test(ch)) {
+ let propName = '';
+ while (i < expr.length && (/[\w$]/u).test(expr[i])) {
+ propName += expr[i];
+ i++;
+ }
+ // Hybrid token: use string for unescaped properties
+ tokens.push(propName);
+ } else {
+ throw new SyntaxError(
+ `Unexpected character '${ch}' at position ${i}`
+ );
+ }
+ }
+ }
+
+ cache[expr] = tokens;
+ return tokens.map((token) => (
+ typeof token === 'object' && token !== null ? {...token} : token
+ ));
};
JSONPath.prototype.safeVm = {
diff --git a/test/index.html b/test/index.html
index 87aacf4..95c1554 100644
--- a/test/index.html
+++ b/test/index.html
@@ -15,7 +15,7 @@ JSONPath Tests