json-p3 1.1.1 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  /*
2
- * json-p3 version 1.1.1
2
+ * json-p3 version 1.2.1
3
3
  * https://github.com/jg-rp/json-p3
4
4
  *
5
5
  * MIT License
@@ -1183,6 +1183,8 @@ var json_p3 = (function (exports) {
1183
1183
  TokenKind["GE"] = "TOKEN_GE";
1184
1184
  TokenKind["GT"] = "TOKEN_GT";
1185
1185
  TokenKind["INDEX"] = "TOKEN_INDEX";
1186
+ TokenKind["KEY"] = "TOKEN_KEY";
1187
+ TokenKind["KEYS"] = "TOKEN_KEYS";
1186
1188
  TokenKind["LBRACKET"] = "TOKEN_LBRACKET";
1187
1189
  TokenKind["LE"] = "TOKEN_LE";
1188
1190
  TokenKind["LG"] = "TOKEN_LG";
@@ -1252,6 +1254,9 @@ var json_p3 = (function (exports) {
1252
1254
  }
1253
1255
  }
1254
1256
 
1257
+ /** A lexer that accepts additional, non-standard tokens. */
1258
+
1259
+
1255
1260
  // These regular expressions are to be used with Lexer.acceptMatchRun(),
1256
1261
  // which expects the sticky flag to be set.
1257
1262
  const exponentPattern = /e[+-]?\d+/y;
@@ -1291,7 +1296,8 @@ var json_p3 = (function (exports) {
1291
1296
  /**
1292
1297
  * @param path - A JSONPath query.
1293
1298
  */
1294
- constructor(path) {
1299
+ constructor(environment, path) {
1300
+ this.environment = environment;
1295
1301
  this.path = path;
1296
1302
  }
1297
1303
  get pos() {
@@ -1391,8 +1397,8 @@ var json_p3 = (function (exports) {
1391
1397
  * @returns A two-tuple containing a lexer for _path_ and an array to populate
1392
1398
  * with tokens.
1393
1399
  */
1394
- function lex(path) {
1395
- const lexer = new Lexer(path);
1400
+ function lex(environment, path) {
1401
+ const lexer = new Lexer(environment, path);
1396
1402
  return [lexer, lexer.tokens];
1397
1403
  }
1398
1404
 
@@ -1401,8 +1407,8 @@ var json_p3 = (function (exports) {
1401
1407
  * @param path - A JSONPath query.
1402
1408
  * @returns Tokens to be parsed by the parser.
1403
1409
  */
1404
- function tokenize(path) {
1405
- const [lexer, tokens] = lex(path);
1410
+ function tokenize(environment, path) {
1411
+ const [lexer, tokens] = lex(environment, path);
1406
1412
  lexer.run();
1407
1413
  if (tokens.length && tokens[tokens.length - 1].kind === TokenKind.ERROR) {
1408
1414
  throw new JSONPathSyntaxError(tokens[tokens.length - 1].value, tokens[tokens.length - 1]);
@@ -1455,6 +1461,16 @@ var json_p3 = (function (exports) {
1455
1461
  * @returns -
1456
1462
  */
1457
1463
  function lexDescendantSelection(l) {
1464
+ if (l.acceptMatchRun(namePattern)) {
1465
+ // Shorthand name
1466
+ l.emit(TokenKind.NAME);
1467
+ return lexSegment;
1468
+ }
1469
+ if (!l.environment.strict && l.acceptMatchRun(l.environment.keysPattern)) {
1470
+ // Non-standard keys selector
1471
+ l.emit(TokenKind.KEYS);
1472
+ return lexSegment;
1473
+ }
1458
1474
  const ch = l.next();
1459
1475
  switch (ch) {
1460
1476
  case "":
@@ -1468,13 +1484,8 @@ var json_p3 = (function (exports) {
1468
1484
  return lexInsideBracketedSelection;
1469
1485
  default:
1470
1486
  l.backup();
1471
- if (l.acceptMatchRun(namePattern)) {
1472
- l.emit(TokenKind.NAME);
1473
- return lexSegment;
1474
- } else {
1475
- l.error(`unexpected descendent selection token '${ch}'`);
1476
- return null;
1477
- }
1487
+ l.error(`unexpected descendent selection token '${ch}'`);
1488
+ return null;
1478
1489
  }
1479
1490
  }
1480
1491
  function lexDotSelector(l) {
@@ -1483,23 +1494,34 @@ var json_p3 = (function (exports) {
1483
1494
  l.error("unexpected whitespace after dot");
1484
1495
  return null;
1485
1496
  }
1486
- const ch = l.next();
1487
- if (ch === "*") {
1488
- l.emit(TokenKind.WILD);
1497
+ if (!l.environment.strict && l.acceptMatchRun(l.environment.keysPattern)) {
1498
+ l.emit(TokenKind.KEYS);
1489
1499
  return lexSegment;
1490
1500
  }
1491
- l.backup();
1492
1501
  if (l.acceptMatchRun(namePattern)) {
1493
1502
  l.emit(TokenKind.NAME);
1494
1503
  return lexSegment;
1495
- } else {
1496
- l.error(`unexpected shorthand selector '${ch}'`);
1497
- return null;
1498
1504
  }
1505
+ const ch = l.next();
1506
+ if (ch === "*") {
1507
+ l.emit(TokenKind.WILD);
1508
+ return lexSegment;
1509
+ }
1510
+ l.backup();
1511
+ l.error(`unexpected shorthand selector '${ch}'`);
1512
+ return null;
1499
1513
  }
1500
1514
  function lexInsideBracketedSelection(l) {
1501
1515
  for (;;) {
1502
1516
  l.ignoreWhitespace();
1517
+ if (l.acceptMatchRun(indexPattern)) {
1518
+ l.emit(TokenKind.INDEX);
1519
+ continue;
1520
+ }
1521
+ if (!l.environment.strict && l.acceptMatchRun(l.environment.keysPattern)) {
1522
+ l.emit(TokenKind.KEYS);
1523
+ continue;
1524
+ }
1503
1525
  const ch = l.next();
1504
1526
  switch (ch) {
1505
1527
  case "]":
@@ -1528,10 +1550,6 @@ var json_p3 = (function (exports) {
1528
1550
  return lexDoubleQuoteStringInsideBracketSelection;
1529
1551
  default:
1530
1552
  l.backup();
1531
- if (l.acceptMatchRun(indexPattern)) {
1532
- l.emit(TokenKind.INDEX);
1533
- continue;
1534
- }
1535
1553
  l.error(`unexpected token '${ch}' in bracketed selection`);
1536
1554
  return null;
1537
1555
  }
@@ -1545,6 +1563,8 @@ var json_p3 = (function (exports) {
1545
1563
  const ch = l.next();
1546
1564
  switch (ch) {
1547
1565
  case "":
1566
+ l.error("unclosed bracketed selection");
1567
+ return null;
1548
1568
  case "]":
1549
1569
  l.filterLevel -= 1;
1550
1570
  if (l.parenStack.length === 1) {
@@ -1586,6 +1606,9 @@ var json_p3 = (function (exports) {
1586
1606
  case "@":
1587
1607
  l.emit(TokenKind.CURRENT);
1588
1608
  return lexSegment;
1609
+ case "#":
1610
+ l.emit(TokenKind.KEY);
1611
+ return lexSegment;
1589
1612
  case ".":
1590
1613
  l.backup();
1591
1614
  return lexSegment;
@@ -1764,7 +1787,7 @@ var json_p3 = (function (exports) {
1764
1787
  resolve(nodes) {
1765
1788
  const rv = [];
1766
1789
  for (const node of nodes) {
1767
- if (hasStringKey(node.value, this.name)) {
1790
+ if (!isArray(node.value) && hasStringKey(node.value, this.name)) {
1768
1791
  rv.push(new JSONPathNode(node.value[this.name], node.location.concat(this.name), node.root));
1769
1792
  }
1770
1793
  }
@@ -1772,7 +1795,7 @@ var json_p3 = (function (exports) {
1772
1795
  }
1773
1796
  *lazyResolve(nodes) {
1774
1797
  for (const node of nodes) {
1775
- if (hasStringKey(node.value, this.name)) {
1798
+ if (!isArray(node.value) && hasStringKey(node.value, this.name)) {
1776
1799
  yield new JSONPathNode(node.value[this.name], node.location.concat(this.name), node.root);
1777
1800
  }
1778
1801
  }
@@ -1848,7 +1871,7 @@ var json_p3 = (function (exports) {
1848
1871
  *lazyResolve(nodes) {
1849
1872
  for (const node of nodes) {
1850
1873
  if (!isArray(node.value)) continue;
1851
- for (const [i, value] of this.slice(node.value, this.start, this.stop, this.step)) {
1874
+ for (const [i, value] of this.lazySlice(node.value, this.start, this.stop, this.step)) {
1852
1875
  yield new JSONPathNode(value, node.location.concat(i), node.root);
1853
1876
  }
1854
1877
  }
@@ -1911,6 +1934,45 @@ var json_p3 = (function (exports) {
1911
1934
  }
1912
1935
  return slicedArray;
1913
1936
  }
1937
+
1938
+ // eslint-disable-next-line sonarjs/cognitive-complexity
1939
+ *lazySlice(arr, start, stop, step) {
1940
+ if (!arr.length) return;
1941
+
1942
+ // Handle negative and undefined start values
1943
+ if (start === undefined || start === null) {
1944
+ start = step && step < 0 ? arr.length - 1 : 0;
1945
+ } else if (start < 0) {
1946
+ start = Math.max(arr.length + start, 0);
1947
+ } else {
1948
+ start = Math.min(start, arr.length - 1);
1949
+ }
1950
+
1951
+ // Handle negative and undefined stop values
1952
+ if (stop === undefined || stop === null) {
1953
+ stop = step && step < 0 ? -1 : arr.length;
1954
+ } else if (stop < 0) {
1955
+ stop = Math.max(arr.length + stop, -1);
1956
+ } else {
1957
+ stop = Math.min(stop, arr.length);
1958
+ }
1959
+
1960
+ // Perform the slice
1961
+ if (step === undefined) {
1962
+ // Default to a step of 1
1963
+ for (let i = start; i < stop; i += 1) {
1964
+ yield [i, arr[i]];
1965
+ }
1966
+ } else if (step > 0) {
1967
+ for (let i = start; i < stop; i += step) {
1968
+ yield [i, arr[i]];
1969
+ }
1970
+ } else if (step < 0) {
1971
+ for (let i = start; i > stop; i += step) {
1972
+ yield [i, arr[i]];
1973
+ }
1974
+ }
1975
+ }
1914
1976
  }
1915
1977
  class WildcardSelector extends JSONPathSelector {
1916
1978
  constructor(environment, token) {
@@ -1963,10 +2025,18 @@ var json_p3 = (function (exports) {
1963
2025
  }
1964
2026
  resolve(nodes) {
1965
2027
  const rv = [];
1966
- for (const node of nodes) {
1967
- rv.push(node);
1968
- for (const _node of this.visit(node)) {
1969
- rv.push(_node);
2028
+ if (this.environment.nondeterministic) {
2029
+ for (const root of nodes) {
2030
+ for (const node of this.nondeterministicVisitor(root)) {
2031
+ rv.push(node);
2032
+ }
2033
+ }
2034
+ } else {
2035
+ for (const node of nodes) {
2036
+ rv.push(node);
2037
+ for (const _node of this.visitor(node)) {
2038
+ rv.push(_node);
2039
+ }
1970
2040
  }
1971
2041
  }
1972
2042
  return this.selector.resolve(rv);
@@ -2021,7 +2091,7 @@ var json_p3 = (function (exports) {
2021
2091
  toString() {
2022
2092
  return `..${this.selector.toString()}`;
2023
2093
  }
2024
- visit(node) {
2094
+ visitor(node) {
2025
2095
  let depth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
2026
2096
  if (depth >= this.environment.maxRecursionDepth) {
2027
2097
  throw new JSONPathRecursionLimitError("recursion limit reached", this.token);
@@ -2032,7 +2102,7 @@ var json_p3 = (function (exports) {
2032
2102
  for (let i = 0; i < node.value.length; i++) {
2033
2103
  const _node = new JSONPathNode(node.value[i], node.location.concat(i), node.root);
2034
2104
  rv.push(_node);
2035
- for (const __node of this.visit(_node, depth + 1)) {
2105
+ for (const __node of this.visitor(_node, depth + 1)) {
2036
2106
  rv.push(__node);
2037
2107
  }
2038
2108
  }
@@ -2040,13 +2110,52 @@ var json_p3 = (function (exports) {
2040
2110
  for (const [key, value] of this.environment.entries(node.value)) {
2041
2111
  const _node = new JSONPathNode(value, node.location.concat(key), node.root);
2042
2112
  rv.push(_node);
2043
- for (const __node of this.visit(_node, depth + 1)) {
2113
+ for (const __node of this.visitor(_node, depth + 1)) {
2044
2114
  rv.push(__node);
2045
2115
  }
2046
2116
  }
2047
2117
  }
2048
2118
  return rv;
2049
2119
  }
2120
+ nondeterministicVisitor(root) {
2121
+ let depth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
2122
+ const rv = [root];
2123
+ let queue = this.nondeterministicChildren(root).map(node => [node, depth]);
2124
+ while (queue.length) {
2125
+ const [node, _depth] = queue.shift();
2126
+ rv.push(node);
2127
+ if (_depth >= this.environment.maxRecursionDepth) {
2128
+ throw new JSONPathRecursionLimitError("recursion limit reached", this.token);
2129
+ }
2130
+
2131
+ // Visit child nodes now or queue them for later?
2132
+ const visitChildren = Math.random() < 0.5;
2133
+ for (const child of this.nondeterministicChildren(node)) {
2134
+ if (visitChildren) {
2135
+ rv.push(child);
2136
+ const grandchildren = this.nondeterministicChildren(child).map(n => [n, _depth + 2]);
2137
+ queue = interleave(queue, grandchildren);
2138
+ } else {
2139
+ queue.push([child, _depth + 1]);
2140
+ }
2141
+ }
2142
+ }
2143
+ return rv;
2144
+ }
2145
+ nondeterministicChildren(node) {
2146
+ const _rv = [];
2147
+ if (node.value instanceof String) return _rv;
2148
+ if (isArray(node.value)) {
2149
+ for (let i = 0; i < node.value.length; i++) {
2150
+ _rv.push(new JSONPathNode(node.value[i], node.location.concat(i), node.root));
2151
+ }
2152
+ } else if (isObject(node.value)) {
2153
+ for (const [key, value] of this.environment.entries(node.value)) {
2154
+ _rv.push(new JSONPathNode(value, node.location.concat(key), node.root));
2155
+ }
2156
+ }
2157
+ return _rv;
2158
+ }
2050
2159
  }
2051
2160
  class FilterSelector extends JSONPathSelector {
2052
2161
  constructor(environment, token, expression) {
@@ -2067,7 +2176,8 @@ var json_p3 = (function (exports) {
2067
2176
  const filterContext = {
2068
2177
  environment: this.environment,
2069
2178
  currentValue: value,
2070
- rootValue: node.root
2179
+ rootValue: node.root,
2180
+ currentKey: i
2071
2181
  };
2072
2182
  if (this.expression.evaluate(filterContext)) {
2073
2183
  rv.push(new JSONPathNode(value, node.location.concat(i), node.root));
@@ -2078,7 +2188,8 @@ var json_p3 = (function (exports) {
2078
2188
  const filterContext = {
2079
2189
  environment: this.environment,
2080
2190
  currentValue: value,
2081
- rootValue: node.root
2191
+ rootValue: node.root,
2192
+ currentKey: key
2082
2193
  };
2083
2194
  if (this.expression.evaluate(filterContext)) {
2084
2195
  rv.push(new JSONPathNode(value, node.location.concat(key), node.root));
@@ -2100,7 +2211,8 @@ var json_p3 = (function (exports) {
2100
2211
  environment: this.environment,
2101
2212
  currentValue: value,
2102
2213
  rootValue: node.root,
2103
- lazy: true
2214
+ lazy: true,
2215
+ currentKey: i
2104
2216
  };
2105
2217
  if (this.expression.evaluate(filterContext)) {
2106
2218
  yield new JSONPathNode(value, node.location.concat(i), node.root);
@@ -2112,7 +2224,8 @@ var json_p3 = (function (exports) {
2112
2224
  environment: this.environment,
2113
2225
  currentValue: value,
2114
2226
  rootValue: node.root,
2115
- lazy: true
2227
+ lazy: true,
2228
+ currentKey: key
2116
2229
  };
2117
2230
  if (this.expression.evaluate(filterContext)) {
2118
2231
  yield new JSONPathNode(value, node.location.concat(key), node.root);
@@ -2155,6 +2268,41 @@ var json_p3 = (function (exports) {
2155
2268
  }
2156
2269
  }
2157
2270
 
2271
+ /**
2272
+ * Randomly interleave elements from two arrays while maintaining relative
2273
+ * order of each input array.
2274
+ *
2275
+ * If _arrayA_ is empty, _arrayB_ is returned, and vice versa.
2276
+ */
2277
+ function interleave(arrayA, arrayB) {
2278
+ if (arrayA.length === 0) {
2279
+ return arrayB;
2280
+ }
2281
+ if (arrayB.length === 0) {
2282
+ return arrayA;
2283
+ }
2284
+
2285
+ // An array of iterators
2286
+ const iterators = [];
2287
+ const itA = arrayA[Symbol.iterator]();
2288
+ const itB = arrayB[Symbol.iterator]();
2289
+ for (let i = 0; i < arrayA.length; i++) {
2290
+ iterators.push(itA);
2291
+ }
2292
+ for (let i = 0; i < arrayB.length; i++) {
2293
+ iterators.push(itB);
2294
+ }
2295
+ shuffle(iterators);
2296
+ return iterators.map(it => it.next().value);
2297
+ }
2298
+ function shuffle(entries) {
2299
+ for (let i = entries.length - 1; i > 0; i--) {
2300
+ const j = Math.floor(Math.random() * (i + 1));
2301
+ [entries[i], entries[j]] = [entries[j], entries[i]];
2302
+ }
2303
+ return entries;
2304
+ }
2305
+
2158
2306
  var selectors = /*#__PURE__*/Object.freeze({
2159
2307
  __proto__: null,
2160
2308
  BracketedSelection: BracketedSelection,
@@ -2238,6 +2386,57 @@ var json_p3 = (function (exports) {
2238
2386
  }
2239
2387
  }
2240
2388
 
2389
+ class CurrentKey extends FilterExpression {
2390
+ evaluate(context) {
2391
+ return context.currentKey ?? Nothing;
2392
+ }
2393
+ toString() {
2394
+ return "#";
2395
+ }
2396
+ }
2397
+
2398
+ /**
2399
+ * Object property name selector or array index selector.
2400
+ */
2401
+ class KeysSelector extends JSONPathSelector {
2402
+ constructor(environment, token) {
2403
+ let shorthand = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
2404
+ super(environment, token);
2405
+ this.environment = environment;
2406
+ this.token = token;
2407
+ this.shorthand = shorthand;
2408
+ }
2409
+ resolve(nodes) {
2410
+ const rv = [];
2411
+ for (const node of nodes) {
2412
+ if (node.value instanceof String || isArray(node.value)) continue;
2413
+ if (isObject(node.value)) {
2414
+ let i = 0;
2415
+ for (const [key, _] of this.environment.entries(node.value)) {
2416
+ rv.push(new JSONPathNode(key, node.location.concat("[~]", `[${i}]`), node.root));
2417
+ i++;
2418
+ }
2419
+ }
2420
+ }
2421
+ return rv;
2422
+ }
2423
+ *lazyResolve(nodes) {
2424
+ for (const node of nodes) {
2425
+ if (node.value instanceof String || isArray(node.value)) continue;
2426
+ if (isObject(node.value)) {
2427
+ let i = 0;
2428
+ for (const [key, _] of this.environment.entries(node.value)) {
2429
+ yield new JSONPathNode(key, node.location.concat("[~]", `[${i}]`), node.root);
2430
+ i++;
2431
+ }
2432
+ }
2433
+ }
2434
+ }
2435
+ toString() {
2436
+ return this.shorthand ? "[~]" : "~";
2437
+ }
2438
+ }
2439
+
2241
2440
  const PRECEDENCE_LOWEST = 1;
2242
2441
  const PRECEDENCE_LOGICAL_OR = 4;
2243
2442
  const PRECEDENCE_LOGICAL_AND = 5;
@@ -2253,7 +2452,7 @@ var json_p3 = (function (exports) {
2253
2452
  class Parser {
2254
2453
  constructor(environment) {
2255
2454
  this.environment = environment;
2256
- this.tokenMap = new Map([[TokenKind.FALSE, this.parseBoolean], [TokenKind.NUMBER, this.parseNumber], [TokenKind.LPAREN, this.parseGroupedExpression], [TokenKind.NOT, this.parsePrefixExpression], [TokenKind.NULL, this.parseNull], [TokenKind.ROOT, this.parseRootQuery], [TokenKind.CURRENT, this.parseRelativeQuery], [TokenKind.SINGLE_QUOTE_STRING, this.parseString], [TokenKind.DOUBLE_QUOTE_STRING, this.parseString], [TokenKind.TRUE, this.parseBoolean], [TokenKind.FUNCTION, this.parseFunction]]);
2455
+ this.tokenMap = new Map([[TokenKind.FALSE, this.parseBoolean], [TokenKind.NUMBER, this.parseNumber], [TokenKind.LPAREN, this.parseGroupedExpression], [TokenKind.NOT, this.parsePrefixExpression], [TokenKind.NULL, this.parseNull], [TokenKind.ROOT, this.parseRootQuery], [TokenKind.CURRENT, this.parseRelativeQuery], [TokenKind.SINGLE_QUOTE_STRING, this.parseString], [TokenKind.DOUBLE_QUOTE_STRING, this.parseString], [TokenKind.TRUE, this.parseBoolean], [TokenKind.FUNCTION, this.parseFunction], [TokenKind.KEY, this.parseCurrentKey], [TokenKind.KEY, this.parseCurrentKey]]);
2257
2456
  }
2258
2457
  parse(stream) {
2259
2458
  if (stream.current.kind === TokenKind.ROOT) stream.next();
@@ -2285,6 +2484,8 @@ var json_p3 = (function (exports) {
2285
2484
  return new NameSelector(this.environment, stream.current, stream.current.value, true);
2286
2485
  case TokenKind.WILD:
2287
2486
  return new WildcardSelector(this.environment, stream.current, true);
2487
+ case TokenKind.KEYS:
2488
+ return new KeysSelector(this.environment, stream.current, true);
2288
2489
  case TokenKind.DDOT:
2289
2490
  {
2290
2491
  const segmentToken = stream.current;
@@ -2378,6 +2579,9 @@ var json_p3 = (function (exports) {
2378
2579
  case TokenKind.WILD:
2379
2580
  items.push(new WildcardSelector(this.environment, stream.current));
2380
2581
  break;
2582
+ case TokenKind.KEYS:
2583
+ items.push(new KeysSelector(this.environment, stream.current));
2584
+ break;
2381
2585
  case TokenKind.EOF:
2382
2586
  throw new JSONPathSyntaxError("unexpected end of query", stream.current);
2383
2587
  default:
@@ -2438,13 +2642,20 @@ var json_p3 = (function (exports) {
2438
2642
  return new InfixExpression(tok, left, operator, right);
2439
2643
  }
2440
2644
  parseGroupedExpression(stream) {
2441
- stream.next();
2645
+ if (stream.peek.kind === TokenKind.RPAREN) {
2646
+ throw new JSONPathSyntaxError(`empty paren expression`, stream.current);
2647
+ }
2648
+ stream.next(); // eat open paren
2649
+
2442
2650
  let expr = this.parseFilterExpression(stream);
2443
2651
  stream.next();
2444
2652
  while (stream.current.kind !== TokenKind.RPAREN) {
2445
2653
  if (stream.current.kind === TokenKind.EOF) {
2446
2654
  throw new JSONPathSyntaxError("unbalanced parentheses", stream.current);
2447
2655
  }
2656
+ if (!BINARY_OPERATORS.has(stream.current.kind)) {
2657
+ throw new JSONPathSyntaxError(`expected an expression, found '${stream.current.value}'`, stream.current);
2658
+ }
2448
2659
  expr = this.parseInfixExpression(stream, expr);
2449
2660
  }
2450
2661
  stream.expect(TokenKind.RPAREN);
@@ -2458,6 +2669,9 @@ var json_p3 = (function (exports) {
2458
2669
  const tok = stream.next();
2459
2670
  return new RelativeQuery(tok, new JSONPath(this.environment, this.parsePath(stream, true)));
2460
2671
  }
2672
+ parseCurrentKey(stream) {
2673
+ return new CurrentKey(stream.current);
2674
+ }
2461
2675
  parseFunction(stream) {
2462
2676
  const args = [];
2463
2677
  const tok = stream.next();
@@ -2497,7 +2711,7 @@ var json_p3 = (function (exports) {
2497
2711
  msg = "end of expression";
2498
2712
  break;
2499
2713
  default:
2500
- msg = `'${stream.current.value}`;
2714
+ msg = `'${stream.current.value}'`;
2501
2715
  }
2502
2716
  throw new JSONPathSyntaxError(`unexpected ${msg}`, stream.current);
2503
2717
  }
@@ -2574,6 +2788,10 @@ var json_p3 = (function (exports) {
2574
2788
  * If `true`, enable nondeterministic ordering when iterating JSON object data.
2575
2789
  */
2576
2790
 
2791
+ /**
2792
+ * The pattern to use for the non-standard _keys selector_.
2793
+ */
2794
+
2577
2795
  /**
2578
2796
  * A map of function names to objects implementing the {@link FilterFunction}
2579
2797
  * interface. You are free to set or delete custom filter functions directly.
@@ -2589,6 +2807,7 @@ var json_p3 = (function (exports) {
2589
2807
  this.minIntIndex = options.maxIntIndex ?? -Math.pow(2, 53) - 1;
2590
2808
  this.maxRecursionDepth = options.maxRecursionDepth ?? 50;
2591
2809
  this.nondeterministic = options.nondeterministic ?? false;
2810
+ this.keysPattern = options.keysPattern ?? /~/y;
2592
2811
  this.parser = new Parser(this);
2593
2812
  this.setupFilterFunctions();
2594
2813
  }
@@ -2598,7 +2817,7 @@ var json_p3 = (function (exports) {
2598
2817
  * @returns A new {@link JSONPath} object, bound to this environment.
2599
2818
  */
2600
2819
  compile(path) {
2601
- return new JSONPath(this, this.parser.parse(new TokenStream(tokenize(path))));
2820
+ return new JSONPath(this, this.parser.parse(new TokenStream(tokenize(this, path))));
2602
2821
  }
2603
2822
 
2604
2823
  /**
@@ -2680,7 +2899,7 @@ var json_p3 = (function (exports) {
2680
2899
  for (const [typ, arg, idx] of func.argTypes.map((t, i) => [t, args[i], i])) {
2681
2900
  switch (typ) {
2682
2901
  case FunctionExpressionType.ValueType:
2683
- if (!(arg instanceof FilterExpressionLiteral || arg instanceof JSONPathQuery && arg.path.singularQuery() || arg instanceof FunctionExtension && this.functionRegister.get(arg.name)?.returnType === FunctionExpressionType.ValueType)) {
2902
+ if (!(arg instanceof FilterExpressionLiteral || arg instanceof CurrentKey || arg instanceof JSONPathQuery && arg.path.singularQuery() || arg instanceof FunctionExtension && this.functionRegister.get(arg.name)?.returnType === FunctionExpressionType.ValueType)) {
2684
2903
  throw new JSONPathTypeError(`${token.value}() argument ${idx} must be of ValueType`, arg.token);
2685
2904
  }
2686
2905
  break;
@@ -3308,7 +3527,7 @@ var json_p3 = (function (exports) {
3308
3527
  apply: apply
3309
3528
  });
3310
3529
 
3311
- const version = "1.1.1";
3530
+ const version = "1.2.1";
3312
3531
 
3313
3532
  exports.DEFAULT_ENVIRONMENT = DEFAULT_ENVIRONMENT;
3314
3533
  exports.FunctionExpressionType = FunctionExpressionType;