json-p3 1.3.3 → 1.3.5

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.3.3
2
+ * json-p3 version 1.3.5
3
3
  * https://github.com/jg-rp/json-p3
4
4
  *
5
5
  * MIT License
@@ -1040,16 +1040,16 @@ var expression = /*#__PURE__*/Object.freeze({
1040
1040
  });
1041
1041
 
1042
1042
  class Count {
1043
- argTypes = [FunctionExpressionType.NodesType];
1044
- returnType = FunctionExpressionType.ValueType;
1043
+ argTypes = (() => [FunctionExpressionType.NodesType])();
1044
+ returnType = (() => FunctionExpressionType.ValueType)();
1045
1045
  call(nodes) {
1046
1046
  return nodes.length;
1047
1047
  }
1048
1048
  }
1049
1049
 
1050
1050
  class Length {
1051
- argTypes = [FunctionExpressionType.ValueType];
1052
- returnType = FunctionExpressionType.ValueType;
1051
+ argTypes = (() => [FunctionExpressionType.ValueType])();
1052
+ returnType = (() => FunctionExpressionType.ValueType)();
1053
1053
  call(value) {
1054
1054
  if (isArray(value) || isString(value)) return value.length;
1055
1055
  if (isObject(value)) return Object.keys(value).length;
@@ -1083,7 +1083,10 @@ class LRUCache extends Map {
1083
1083
  if (this.has(key)) {
1084
1084
  this.delete(key);
1085
1085
  } else if (this.size >= this.maxSize) {
1086
- this.delete(this.first());
1086
+ const first = this.first();
1087
+ if (first !== undefined) {
1088
+ this.delete(first);
1089
+ }
1087
1090
  }
1088
1091
  return super.set(key, value);
1089
1092
  }
@@ -2342,8 +2345,8 @@ var check_1 = {
2342
2345
  var check$1 = check_1.check;
2343
2346
 
2344
2347
  class Match {
2345
- argTypes = [FunctionExpressionType.ValueType, FunctionExpressionType.ValueType];
2346
- returnType = FunctionExpressionType.LogicalType;
2348
+ argTypes = (() => [FunctionExpressionType.ValueType, FunctionExpressionType.ValueType])();
2349
+ returnType = (() => FunctionExpressionType.LogicalType)();
2347
2350
  #cache;
2348
2351
  constructor() {
2349
2352
  let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
@@ -2400,8 +2403,8 @@ class Match {
2400
2403
  }
2401
2404
 
2402
2405
  class Search {
2403
- argTypes = [FunctionExpressionType.ValueType, FunctionExpressionType.ValueType];
2404
- returnType = FunctionExpressionType.LogicalType;
2406
+ argTypes = (() => [FunctionExpressionType.ValueType, FunctionExpressionType.ValueType])();
2407
+ returnType = (() => FunctionExpressionType.LogicalType)();
2405
2408
  #cache;
2406
2409
  constructor() {
2407
2410
  let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
@@ -2449,8 +2452,8 @@ class Search {
2449
2452
  }
2450
2453
 
2451
2454
  class Value {
2452
- argTypes = [FunctionExpressionType.NodesType];
2453
- returnType = FunctionExpressionType.ValueType;
2455
+ argTypes = (() => [FunctionExpressionType.NodesType])();
2456
+ returnType = (() => FunctionExpressionType.ValueType)();
2454
2457
  call(nodes) {
2455
2458
  if (nodes.length === 1) return nodes.nodes[0].value;
2456
2459
  return Nothing;
@@ -2550,6 +2553,12 @@ class TokenStream {
2550
2553
  throw new JSONPathSyntaxError(`expected token '${kind}', found '${peeked.kind}'`, peeked);
2551
2554
  }
2552
2555
  }
2556
+ expectPeekNot(kind, message) {
2557
+ const peeked = this.peek;
2558
+ if (peeked.kind === kind) {
2559
+ throw new JSONPathSyntaxError(message, peeked);
2560
+ }
2561
+ }
2553
2562
  }
2554
2563
 
2555
2564
  /** A lexer that accepts additional, non-standard tokens. */
@@ -2557,7 +2566,7 @@ class TokenStream {
2557
2566
 
2558
2567
  // These regular expressions are to be used with Lexer.acceptMatchRun(),
2559
2568
  // which expects the sticky flag to be set.
2560
- const exponentPattern = /e[+-]?\d+/y;
2569
+ const exponentPattern = /[eE][+-]?\d+/y;
2561
2570
  const functionNamePattern = /[a-z][a-z_0-9]*/y;
2562
2571
  const indexPattern = /-?\d+/y;
2563
2572
  const intPattern = /-?[0-9]+/y;
@@ -4000,7 +4009,7 @@ class Parser {
4000
4009
  switch (stream.current.kind) {
4001
4010
  case TokenKind.SINGLE_QUOTE_STRING:
4002
4011
  case TokenKind.DOUBLE_QUOTE_STRING:
4003
- items.push(new NameSelector(this.environment, stream.current, this.decodeString(stream.current, true), false));
4012
+ items.push(new NameSelector(this.environment, stream.current, this.decodeString(stream.current), false));
4004
4013
  break;
4005
4014
  case TokenKind.FILTER:
4006
4015
  items.push(this.parseFilter(stream));
@@ -4020,7 +4029,7 @@ class Parser {
4020
4029
  break;
4021
4030
  case TokenKind.KEY_SINGLE_QUOTE_STRING:
4022
4031
  case TokenKind.KEY_DOUBLE_QUOTE_STRING:
4023
- items.push(new KeySelector(this.environment, stream.current, this.decodeString(stream.current, true), false));
4032
+ items.push(new KeySelector(this.environment, stream.current, this.decodeString(stream.current), false));
4024
4033
  break;
4025
4034
  case TokenKind.KEYS_FILTER:
4026
4035
  items.push(this.parseFilter(stream, true));
@@ -4036,6 +4045,7 @@ class Parser {
4036
4045
  if (stream.peek.kind !== TokenKind.RBRACKET) {
4037
4046
  stream.expectPeek(TokenKind.COMMA);
4038
4047
  stream.next();
4048
+ stream.expectPeekNot(TokenKind.RBRACKET, "unexpected trailing comma");
4039
4049
  }
4040
4050
  stream.next();
4041
4051
  }
@@ -4068,7 +4078,15 @@ class Parser {
4068
4078
  return new StringLiteral(stream.current, this.decodeString(stream.current));
4069
4079
  }
4070
4080
  parseNumber(stream) {
4071
- return new NumberLiteral(stream.current, Number(stream.current.value));
4081
+ const value = stream.current.value;
4082
+ if (value.startsWith("0") && value.length > 1) {
4083
+ throw new JSONPathSyntaxError(`invalid number literal '${value}'`, stream.current);
4084
+ }
4085
+ const num = Number(stream.current.value);
4086
+ if (isNaN(num)) {
4087
+ throw new JSONPathSyntaxError(`invalid number literal '${value}'`, stream.current);
4088
+ }
4089
+ return new NumberLiteral(stream.current, num);
4072
4090
  }
4073
4091
  parsePrefixExpression(stream) {
4074
4092
  stream.expect(TokenKind.NOT);
@@ -4179,11 +4197,155 @@ class Parser {
4179
4197
  return left;
4180
4198
  }
4181
4199
  decodeString(token) {
4182
- let isName = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
4200
+ return this.unescapeString(token.kind === TokenKind.SINGLE_QUOTE_STRING ? token.value.replaceAll('"', '\\"').replaceAll("\\'", "'") : token.value, token);
4201
+ }
4202
+ unescapeString(value, token) {
4203
+ const rv = [];
4204
+ const length = value.length;
4205
+ let index = 0;
4206
+ let codepoint;
4207
+ while (index < length) {
4208
+ const ch = value[index];
4209
+ if (ch === "\\") {
4210
+ // Handle escape sequences
4211
+ index += 1; // Move past '\'
4212
+
4213
+ switch (value[index]) {
4214
+ case '"':
4215
+ rv.push('"');
4216
+ break;
4217
+ case "\\":
4218
+ rv.push("\\");
4219
+ break;
4220
+ case "/":
4221
+ rv.push("/");
4222
+ break;
4223
+ case "b":
4224
+ rv.push("\x08");
4225
+ break;
4226
+ case "f":
4227
+ rv.push("\x0C");
4228
+ break;
4229
+ case "n":
4230
+ rv.push("\n");
4231
+ break;
4232
+ case "r":
4233
+ rv.push("\r");
4234
+ break;
4235
+ case "t":
4236
+ rv.push("\t");
4237
+ break;
4238
+ case "u":
4239
+ [codepoint, index] = this.decodeHexChar(value, index, token);
4240
+ rv.push(this.stringFromCodePoint(codepoint, token));
4241
+ break;
4242
+ default:
4243
+ // TODO: This is unreachable. The lexer will catch unknown escape sequences.
4244
+ throw new JSONPathSyntaxError(`unknown escape sequence at index ${token.index + index - 1}`, token);
4245
+ }
4246
+ } else {
4247
+ this.stringFromCodePoint(ch.codePointAt(0), token);
4248
+ rv.push(ch);
4249
+ }
4250
+ index += 1;
4251
+ }
4252
+ return rv.join("");
4253
+ }
4254
+
4255
+ /**
4256
+ * Decode a `\uXXXX` or `\uXXXX\uXXXX` escape sequence from _value_ at _index_.
4257
+ *
4258
+ * @param value - A string value containing the sequence to decode.
4259
+ * @param index - The start index of an escape sequence in _value_.
4260
+ * @param token - The token for the string value.
4261
+ * @returns - A codepoint, new index tuple.
4262
+ */
4263
+ decodeHexChar(value, index, token) {
4264
+ const length = value.length;
4265
+ if (index + 4 >= length) {
4266
+ throw new JSONPathSyntaxError(`incomplete escape sequence at index ${token.index + index - 1}`, token);
4267
+ }
4268
+ index += 1; // Move past 'u'
4269
+ let codepoint = this.parseHexDigits(value.slice(index, index + 4), token);
4270
+ if (isLowSurrogate(codepoint)) {
4271
+ throw new JSONPathSyntaxError(`unexpected low surrogate codepoint at index ${token.index + index - 2}`, token);
4272
+ }
4273
+ if (isHighSurrogate(codepoint)) {
4274
+ // Expect a surrogate pair.
4275
+ if (!(index + 9 < length && value[index + 4] === "\\" && value[index + 5] === "u")) {
4276
+ throw new JSONPathSyntaxError(`incomplete escape sequence at index ${token.index + index - 2}`, token);
4277
+ }
4278
+ const lowSurrogate = this.parseHexDigits(value.slice(index + 6, index + 10), token);
4279
+ if (!isLowSurrogate(lowSurrogate)) {
4280
+ throw new JSONPathSyntaxError(`unexpected codepoint at index ${token.index + index + 4}`, token);
4281
+ }
4282
+ codepoint = 0x10000 + ((codepoint & 0x03ff) << 10 | lowSurrogate & 0x03ff);
4283
+ return [codepoint, index + 9];
4284
+ }
4285
+ return [codepoint, index + 3];
4286
+ }
4287
+
4288
+ /**
4289
+ * Parse a hexadecimal string as an integer.
4290
+ *
4291
+ * @param digits - Hexadecimal digit string.
4292
+ * @param token - The token for the string value.
4293
+ * @returns - The number representation of _digits_.
4294
+ *
4295
+ * Note that we're not using `parseInt(digits, 16)` because it accepts `+`
4296
+ * and `-` and things we don't allow.
4297
+ */
4298
+ parseHexDigits(digits, token) {
4299
+ const encoder = new TextEncoder();
4300
+ let codepoint = 0;
4301
+ for (const digit of encoder.encode(digits)) {
4302
+ codepoint <<= 4;
4303
+ switch (digit) {
4304
+ case 48:
4305
+ case 49:
4306
+ case 50:
4307
+ case 51:
4308
+ case 52:
4309
+ case 53:
4310
+ case 54:
4311
+ case 55:
4312
+ case 56:
4313
+ case 57:
4314
+ codepoint |= digit - 48; // '0'
4315
+ break;
4316
+ case 97:
4317
+ case 98:
4318
+ case 99:
4319
+ case 100:
4320
+ case 101:
4321
+ case 102:
4322
+ codepoint |= digit - 97 + 10; // 'a'
4323
+ break;
4324
+ case 65:
4325
+ case 66:
4326
+ case 67:
4327
+ case 68:
4328
+ case 69:
4329
+ case 70:
4330
+ codepoint |= digit - 65 + 10; // 'A'
4331
+ break;
4332
+ default:
4333
+ throw new JSONPathSyntaxError("invalid \\uXXXX escape sequence", token);
4334
+ }
4335
+ }
4336
+ return codepoint;
4337
+ }
4338
+
4339
+ /** Check the codepoint is valid and return its string representation. */
4340
+ stringFromCodePoint(codepoint, token) {
4341
+ if (codepoint === undefined || codepoint <= 0x1f) {
4342
+ throw new JSONPathSyntaxError(`invalid character`, token);
4343
+ }
4183
4344
  try {
4184
- return JSON.parse(token.kind === TokenKind.SINGLE_QUOTE_STRING ? `"${token.value.replaceAll('"', '\\"').replaceAll("\\'", "'")}"` : `"${token.value}"`);
4345
+ return String.fromCodePoint(codepoint);
4185
4346
  } catch {
4186
- throw new JSONPathSyntaxError(`invalid ${isName ? "name selector" : "string literal"} '${token.value}'`, token);
4347
+ // This should not be reachable.
4348
+ throw new JSONPathSyntaxError("invalid escape sequence", token);
4187
4349
  }
4188
4350
  }
4189
4351
  throwForNonComparable(expr) {
@@ -4203,6 +4365,12 @@ class Parser {
4203
4365
  }
4204
4366
  }
4205
4367
  }
4368
+ function isHighSurrogate(codepoint) {
4369
+ return codepoint >= 0xd800 && codepoint <= 0xdbff;
4370
+ }
4371
+ function isLowSurrogate(codepoint) {
4372
+ return codepoint >= 0xdc00 && codepoint <= 0xdfff;
4373
+ }
4206
4374
 
4207
4375
  /**
4208
4376
  * JSONPath environment options. The defaults are in compliance with JSONPath
@@ -4252,7 +4420,7 @@ class JSONPathEnvironment {
4252
4420
  * A map of function names to objects implementing the {@link FilterFunction}
4253
4421
  * interface. You are free to set or delete custom filter functions directly.
4254
4422
  */
4255
- functionRegister = new Map();
4423
+ functionRegister = (() => new Map())();
4256
4424
  /**
4257
4425
  * @param options - Environment configuration options.
4258
4426
  */
@@ -4260,7 +4428,7 @@ class JSONPathEnvironment {
4260
4428
  let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
4261
4429
  this.strict = options.strict ?? true;
4262
4430
  this.maxIntIndex = options.maxIntIndex ?? Math.pow(2, 53) - 1;
4263
- this.minIntIndex = options.maxIntIndex ?? -Math.pow(2, 53) - 1;
4431
+ this.minIntIndex = options.maxIntIndex ?? -Math.pow(2, 53) + 1;
4264
4432
  this.maxRecursionDepth = options.maxRecursionDepth ?? 50;
4265
4433
  this.nondeterministic = options.nondeterministic ?? false;
4266
4434
  this.keysPattern = options.keysPattern ?? /~/y;
@@ -4695,7 +4863,11 @@ class OpMove {
4695
4863
  throw new JSONPatchError(`unexpected operation on 'undefined' (${this.name}:${index})`);
4696
4864
  }
4697
4865
  if (isArray(destParent)) {
4698
- destParent.splice(Number(destTarget), 0, sourceObj);
4866
+ if (destTarget === "-") {
4867
+ destParent.push(sourceObj);
4868
+ } else {
4869
+ destParent.splice(Number(destTarget), 0, sourceObj);
4870
+ }
4699
4871
  } else if (isObject(destParent)) {
4700
4872
  destParent[destTarget] = sourceObj;
4701
4873
  } else {
@@ -4737,11 +4909,15 @@ class OpCopy {
4737
4909
  throw new JSONPatchError(`unexpected operation on 'undefined' (${this.name}:${index})`);
4738
4910
  }
4739
4911
  if (isArray(destParent)) {
4740
- destParent.splice(Number(destTarget), 0, this.deepCopy(sourceObj));
4912
+ if (destTarget === "-") {
4913
+ destParent.push(this.deepCopy(sourceObj));
4914
+ } else {
4915
+ destParent.splice(Number(destTarget), 0, this.deepCopy(sourceObj));
4916
+ }
4741
4917
  } else if (isObject(destParent)) {
4742
4918
  destParent[destTarget] = this.deepCopy(sourceObj);
4743
4919
  } else {
4744
- throw new JSONPatchError(`unexpected operation on '${typeof parent}' (${this.name}:${index})`);
4920
+ throw new JSONPatchError(`unexpected operation on '${typeof destParent}' (${this.name}:${index})`);
4745
4921
  }
4746
4922
  return value;
4747
4923
  }
@@ -4984,6 +5160,6 @@ var index = /*#__PURE__*/Object.freeze({
4984
5160
  apply: apply
4985
5161
  });
4986
5162
 
4987
- const version = "1.3.3";
5163
+ const version = "1.3.5";
4988
5164
 
4989
5165
  export { DEFAULT_ENVIRONMENT, FunctionExpressionType, JSONPatch, JSONPatchError, JSONPatchTestFailure, JSONPath, JSONPathEnvironment, JSONPathError, JSONPathIndexError, JSONPathLexerError, JSONPathNode, JSONPathNodeList, JSONPathRecursionLimitError, JSONPathSyntaxError, JSONPathTypeError, JSONPointer, Nothing, RelativeJSONPointer, Token, TokenKind, UNDEFINED, apply, compile, index as jsonpatch, index$1 as jsonpath, index$3 as jsonpointer, lazyQuery, query, resolve, version };