json-p3 1.3.2 → 1.3.4
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.
- package/dist/json-p3.cjs.js +184 -10
- package/dist/json-p3.esm.js +184 -10
- package/dist/json-p3.iife.js +184 -10
- package/dist/json-p3.iife.min.js +1 -1
- package/dist/json-p3.iife.min.js.map +1 -1
- package/dist/path/parse.d.ts +27 -1
- package/dist/path/token.d.ts +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
package/dist/json-p3.cjs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* json-p3 version 1.3.
|
|
2
|
+
* json-p3 version 1.3.4
|
|
3
3
|
* https://github.com/jg-rp/json-p3
|
|
4
4
|
*
|
|
5
5
|
* MIT License
|
|
@@ -2552,6 +2552,12 @@ class TokenStream {
|
|
|
2552
2552
|
throw new JSONPathSyntaxError(`expected token '${kind}', found '${peeked.kind}'`, peeked);
|
|
2553
2553
|
}
|
|
2554
2554
|
}
|
|
2555
|
+
expectPeekNot(kind, message) {
|
|
2556
|
+
const peeked = this.peek;
|
|
2557
|
+
if (peeked.kind === kind) {
|
|
2558
|
+
throw new JSONPathSyntaxError(message, peeked);
|
|
2559
|
+
}
|
|
2560
|
+
}
|
|
2555
2561
|
}
|
|
2556
2562
|
|
|
2557
2563
|
/** A lexer that accepts additional, non-standard tokens. */
|
|
@@ -2559,7 +2565,7 @@ class TokenStream {
|
|
|
2559
2565
|
|
|
2560
2566
|
// These regular expressions are to be used with Lexer.acceptMatchRun(),
|
|
2561
2567
|
// which expects the sticky flag to be set.
|
|
2562
|
-
const exponentPattern = /
|
|
2568
|
+
const exponentPattern = /[eE][+-]?\d+/y;
|
|
2563
2569
|
const functionNamePattern = /[a-z][a-z_0-9]*/y;
|
|
2564
2570
|
const indexPattern = /-?\d+/y;
|
|
2565
2571
|
const intPattern = /-?[0-9]+/y;
|
|
@@ -4002,7 +4008,7 @@ class Parser {
|
|
|
4002
4008
|
switch (stream.current.kind) {
|
|
4003
4009
|
case TokenKind.SINGLE_QUOTE_STRING:
|
|
4004
4010
|
case TokenKind.DOUBLE_QUOTE_STRING:
|
|
4005
|
-
items.push(new NameSelector(this.environment, stream.current, this.decodeString(stream.current
|
|
4011
|
+
items.push(new NameSelector(this.environment, stream.current, this.decodeString(stream.current), false));
|
|
4006
4012
|
break;
|
|
4007
4013
|
case TokenKind.FILTER:
|
|
4008
4014
|
items.push(this.parseFilter(stream));
|
|
@@ -4022,7 +4028,7 @@ class Parser {
|
|
|
4022
4028
|
break;
|
|
4023
4029
|
case TokenKind.KEY_SINGLE_QUOTE_STRING:
|
|
4024
4030
|
case TokenKind.KEY_DOUBLE_QUOTE_STRING:
|
|
4025
|
-
items.push(new KeySelector(this.environment, stream.current, this.decodeString(stream.current
|
|
4031
|
+
items.push(new KeySelector(this.environment, stream.current, this.decodeString(stream.current), false));
|
|
4026
4032
|
break;
|
|
4027
4033
|
case TokenKind.KEYS_FILTER:
|
|
4028
4034
|
items.push(this.parseFilter(stream, true));
|
|
@@ -4038,6 +4044,7 @@ class Parser {
|
|
|
4038
4044
|
if (stream.peek.kind !== TokenKind.RBRACKET) {
|
|
4039
4045
|
stream.expectPeek(TokenKind.COMMA);
|
|
4040
4046
|
stream.next();
|
|
4047
|
+
stream.expectPeekNot(TokenKind.RBRACKET, "unexpected trailing comma");
|
|
4041
4048
|
}
|
|
4042
4049
|
stream.next();
|
|
4043
4050
|
}
|
|
@@ -4056,6 +4063,7 @@ class Parser {
|
|
|
4056
4063
|
throw new JSONPathTypeError(`result of ${expr.name}() must be compared`, expr.token);
|
|
4057
4064
|
}
|
|
4058
4065
|
}
|
|
4066
|
+
this.throwForLiteral(expr);
|
|
4059
4067
|
return keys ? new KeysFilterSelector(this.environment, tok, new LogicalExpression(tok, expr)) : new FilterSelector(this.environment, tok, new LogicalExpression(tok, expr));
|
|
4060
4068
|
}
|
|
4061
4069
|
parseBoolean(stream) {
|
|
@@ -4069,7 +4077,15 @@ class Parser {
|
|
|
4069
4077
|
return new StringLiteral(stream.current, this.decodeString(stream.current));
|
|
4070
4078
|
}
|
|
4071
4079
|
parseNumber(stream) {
|
|
4072
|
-
|
|
4080
|
+
const value = stream.current.value;
|
|
4081
|
+
if (value.startsWith("0") && value.length > 1) {
|
|
4082
|
+
throw new JSONPathSyntaxError(`invalid number literal '${value}'`, stream.current);
|
|
4083
|
+
}
|
|
4084
|
+
const num = Number(stream.current.value);
|
|
4085
|
+
if (isNaN(num)) {
|
|
4086
|
+
throw new JSONPathSyntaxError(`invalid number literal '${value}'`, stream.current);
|
|
4087
|
+
}
|
|
4088
|
+
return new NumberLiteral(stream.current, num);
|
|
4073
4089
|
}
|
|
4074
4090
|
parsePrefixExpression(stream) {
|
|
4075
4091
|
stream.expect(TokenKind.NOT);
|
|
@@ -4087,6 +4103,9 @@ class Parser {
|
|
|
4087
4103
|
if (COMPARISON_OPERATORS.has(operator)) {
|
|
4088
4104
|
this.throwForNonComparable(left);
|
|
4089
4105
|
this.throwForNonComparable(right);
|
|
4106
|
+
} else {
|
|
4107
|
+
this.throwForLiteral(left);
|
|
4108
|
+
this.throwForLiteral(right);
|
|
4090
4109
|
}
|
|
4091
4110
|
return new InfixExpression(tok, left, operator, right);
|
|
4092
4111
|
}
|
|
@@ -4177,11 +4196,155 @@ class Parser {
|
|
|
4177
4196
|
return left;
|
|
4178
4197
|
}
|
|
4179
4198
|
decodeString(token) {
|
|
4180
|
-
|
|
4199
|
+
return this.unescapeString(token.kind === TokenKind.SINGLE_QUOTE_STRING ? token.value.replaceAll('"', '\\"').replaceAll("\\'", "'") : token.value, token);
|
|
4200
|
+
}
|
|
4201
|
+
unescapeString(value, token) {
|
|
4202
|
+
const rv = [];
|
|
4203
|
+
const length = value.length;
|
|
4204
|
+
let index = 0;
|
|
4205
|
+
let codepoint;
|
|
4206
|
+
while (index < length) {
|
|
4207
|
+
const ch = value[index];
|
|
4208
|
+
if (ch === "\\") {
|
|
4209
|
+
// Handle escape sequences
|
|
4210
|
+
index += 1; // Move past '\'
|
|
4211
|
+
|
|
4212
|
+
switch (value[index]) {
|
|
4213
|
+
case '"':
|
|
4214
|
+
rv.push('"');
|
|
4215
|
+
break;
|
|
4216
|
+
case "\\":
|
|
4217
|
+
rv.push("\\");
|
|
4218
|
+
break;
|
|
4219
|
+
case "/":
|
|
4220
|
+
rv.push("/");
|
|
4221
|
+
break;
|
|
4222
|
+
case "b":
|
|
4223
|
+
rv.push("\x08");
|
|
4224
|
+
break;
|
|
4225
|
+
case "f":
|
|
4226
|
+
rv.push("\x0C");
|
|
4227
|
+
break;
|
|
4228
|
+
case "n":
|
|
4229
|
+
rv.push("\n");
|
|
4230
|
+
break;
|
|
4231
|
+
case "r":
|
|
4232
|
+
rv.push("\r");
|
|
4233
|
+
break;
|
|
4234
|
+
case "t":
|
|
4235
|
+
rv.push("\t");
|
|
4236
|
+
break;
|
|
4237
|
+
case "u":
|
|
4238
|
+
[codepoint, index] = this.decodeHexChar(value, index, token);
|
|
4239
|
+
rv.push(this.stringFromCodePoint(codepoint, token));
|
|
4240
|
+
break;
|
|
4241
|
+
default:
|
|
4242
|
+
// TODO: This is unreachable. The lexer will catch unknown escape sequences.
|
|
4243
|
+
throw new JSONPathSyntaxError(`unknown escape sequence at index ${token.index + index - 1}`, token);
|
|
4244
|
+
}
|
|
4245
|
+
} else {
|
|
4246
|
+
this.stringFromCodePoint(ch.codePointAt(0), token);
|
|
4247
|
+
rv.push(ch);
|
|
4248
|
+
}
|
|
4249
|
+
index += 1;
|
|
4250
|
+
}
|
|
4251
|
+
return rv.join("");
|
|
4252
|
+
}
|
|
4253
|
+
|
|
4254
|
+
/**
|
|
4255
|
+
* Decode a `\uXXXX` or `\uXXXX\uXXXX` escape sequence from _value_ at _index_.
|
|
4256
|
+
*
|
|
4257
|
+
* @param value - A string value containing the sequence to decode.
|
|
4258
|
+
* @param index - The start index of an escape sequence in _value_.
|
|
4259
|
+
* @param token - The token for the string value.
|
|
4260
|
+
* @returns - A codepoint, new index tuple.
|
|
4261
|
+
*/
|
|
4262
|
+
decodeHexChar(value, index, token) {
|
|
4263
|
+
const length = value.length;
|
|
4264
|
+
if (index + 4 >= length) {
|
|
4265
|
+
throw new JSONPathSyntaxError(`incomplete escape sequence at index ${token.index + index - 1}`, token);
|
|
4266
|
+
}
|
|
4267
|
+
index += 1; // Move past 'u'
|
|
4268
|
+
let codepoint = this.parseHexDigits(value.slice(index, index + 4), token);
|
|
4269
|
+
if (isLowSurrogate(codepoint)) {
|
|
4270
|
+
throw new JSONPathSyntaxError(`unexpected low surrogate codepoint at index ${token.index + index - 2}`, token);
|
|
4271
|
+
}
|
|
4272
|
+
if (isHighSurrogate(codepoint)) {
|
|
4273
|
+
// Expect a surrogate pair.
|
|
4274
|
+
if (!(index + 9 < length && value[index + 4] === "\\" && value[index + 5] === "u")) {
|
|
4275
|
+
throw new JSONPathSyntaxError(`incomplete escape sequence at index ${token.index + index - 2}`, token);
|
|
4276
|
+
}
|
|
4277
|
+
const lowSurrogate = this.parseHexDigits(value.slice(index + 6, index + 10), token);
|
|
4278
|
+
if (!isLowSurrogate(lowSurrogate)) {
|
|
4279
|
+
throw new JSONPathSyntaxError(`unexpected codepoint at index ${token.index + index + 4}`, token);
|
|
4280
|
+
}
|
|
4281
|
+
codepoint = 0x10000 + ((codepoint & 0x03ff) << 10 | lowSurrogate & 0x03ff);
|
|
4282
|
+
return [codepoint, index + 9];
|
|
4283
|
+
}
|
|
4284
|
+
return [codepoint, index + 3];
|
|
4285
|
+
}
|
|
4286
|
+
|
|
4287
|
+
/**
|
|
4288
|
+
* Parse a hexadecimal string as an integer.
|
|
4289
|
+
*
|
|
4290
|
+
* @param digits - Hexadecimal digit string.
|
|
4291
|
+
* @param token - The token for the string value.
|
|
4292
|
+
* @returns - The number representation of _digits_.
|
|
4293
|
+
*
|
|
4294
|
+
* Note that we're not using `parseInt(digits, 16)` because it accepts `+`
|
|
4295
|
+
* and `-` and things we don't allow.
|
|
4296
|
+
*/
|
|
4297
|
+
parseHexDigits(digits, token) {
|
|
4298
|
+
const encoder = new TextEncoder();
|
|
4299
|
+
let codepoint = 0;
|
|
4300
|
+
for (const digit of encoder.encode(digits)) {
|
|
4301
|
+
codepoint <<= 4;
|
|
4302
|
+
switch (digit) {
|
|
4303
|
+
case 48:
|
|
4304
|
+
case 49:
|
|
4305
|
+
case 50:
|
|
4306
|
+
case 51:
|
|
4307
|
+
case 52:
|
|
4308
|
+
case 53:
|
|
4309
|
+
case 54:
|
|
4310
|
+
case 55:
|
|
4311
|
+
case 56:
|
|
4312
|
+
case 57:
|
|
4313
|
+
codepoint |= digit - 48; // '0'
|
|
4314
|
+
break;
|
|
4315
|
+
case 97:
|
|
4316
|
+
case 98:
|
|
4317
|
+
case 99:
|
|
4318
|
+
case 100:
|
|
4319
|
+
case 101:
|
|
4320
|
+
case 102:
|
|
4321
|
+
codepoint |= digit - 97 + 10; // 'a'
|
|
4322
|
+
break;
|
|
4323
|
+
case 65:
|
|
4324
|
+
case 66:
|
|
4325
|
+
case 67:
|
|
4326
|
+
case 68:
|
|
4327
|
+
case 69:
|
|
4328
|
+
case 70:
|
|
4329
|
+
codepoint |= digit - 65 + 10; // 'A'
|
|
4330
|
+
break;
|
|
4331
|
+
default:
|
|
4332
|
+
throw new JSONPathSyntaxError("invalid \\uXXXX escape sequence", token);
|
|
4333
|
+
}
|
|
4334
|
+
}
|
|
4335
|
+
return codepoint;
|
|
4336
|
+
}
|
|
4337
|
+
|
|
4338
|
+
/** Check the codepoint is valid and return its string representation. */
|
|
4339
|
+
stringFromCodePoint(codepoint, token) {
|
|
4340
|
+
if (codepoint === undefined || codepoint <= 0x1f) {
|
|
4341
|
+
throw new JSONPathSyntaxError(`invalid character`, token);
|
|
4342
|
+
}
|
|
4181
4343
|
try {
|
|
4182
|
-
return
|
|
4344
|
+
return String.fromCodePoint(codepoint);
|
|
4183
4345
|
} catch {
|
|
4184
|
-
|
|
4346
|
+
// This should not be reachable.
|
|
4347
|
+
throw new JSONPathSyntaxError("invalid escape sequence", token);
|
|
4185
4348
|
}
|
|
4186
4349
|
}
|
|
4187
4350
|
throwForNonComparable(expr) {
|
|
@@ -4195,6 +4358,17 @@ class Parser {
|
|
|
4195
4358
|
}
|
|
4196
4359
|
}
|
|
4197
4360
|
}
|
|
4361
|
+
throwForLiteral(expr) {
|
|
4362
|
+
if (expr instanceof FilterExpressionLiteral) {
|
|
4363
|
+
throw new JSONPathSyntaxError(`filter expression literals (${expr.toString()}) must be compared`, expr.token);
|
|
4364
|
+
}
|
|
4365
|
+
}
|
|
4366
|
+
}
|
|
4367
|
+
function isHighSurrogate(codepoint) {
|
|
4368
|
+
return codepoint >= 0xd800 && codepoint <= 0xdbff;
|
|
4369
|
+
}
|
|
4370
|
+
function isLowSurrogate(codepoint) {
|
|
4371
|
+
return codepoint >= 0xdc00 && codepoint <= 0xdfff;
|
|
4198
4372
|
}
|
|
4199
4373
|
|
|
4200
4374
|
/**
|
|
@@ -4253,7 +4427,7 @@ class JSONPathEnvironment {
|
|
|
4253
4427
|
let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
4254
4428
|
this.strict = options.strict ?? true;
|
|
4255
4429
|
this.maxIntIndex = options.maxIntIndex ?? Math.pow(2, 53) - 1;
|
|
4256
|
-
this.minIntIndex = options.maxIntIndex ?? -Math.pow(2, 53)
|
|
4430
|
+
this.minIntIndex = options.maxIntIndex ?? -Math.pow(2, 53) + 1;
|
|
4257
4431
|
this.maxRecursionDepth = options.maxRecursionDepth ?? 50;
|
|
4258
4432
|
this.nondeterministic = options.nondeterministic ?? false;
|
|
4259
4433
|
this.keysPattern = options.keysPattern ?? /~/y;
|
|
@@ -4977,7 +5151,7 @@ var index = /*#__PURE__*/Object.freeze({
|
|
|
4977
5151
|
apply: apply
|
|
4978
5152
|
});
|
|
4979
5153
|
|
|
4980
|
-
const version = "1.3.
|
|
5154
|
+
const version = "1.3.4";
|
|
4981
5155
|
|
|
4982
5156
|
exports.DEFAULT_ENVIRONMENT = DEFAULT_ENVIRONMENT;
|
|
4983
5157
|
exports.FunctionExpressionType = FunctionExpressionType;
|
package/dist/json-p3.esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* json-p3 version 1.3.
|
|
2
|
+
* json-p3 version 1.3.4
|
|
3
3
|
* https://github.com/jg-rp/json-p3
|
|
4
4
|
*
|
|
5
5
|
* MIT License
|
|
@@ -2550,6 +2550,12 @@ class TokenStream {
|
|
|
2550
2550
|
throw new JSONPathSyntaxError(`expected token '${kind}', found '${peeked.kind}'`, peeked);
|
|
2551
2551
|
}
|
|
2552
2552
|
}
|
|
2553
|
+
expectPeekNot(kind, message) {
|
|
2554
|
+
const peeked = this.peek;
|
|
2555
|
+
if (peeked.kind === kind) {
|
|
2556
|
+
throw new JSONPathSyntaxError(message, peeked);
|
|
2557
|
+
}
|
|
2558
|
+
}
|
|
2553
2559
|
}
|
|
2554
2560
|
|
|
2555
2561
|
/** A lexer that accepts additional, non-standard tokens. */
|
|
@@ -2557,7 +2563,7 @@ class TokenStream {
|
|
|
2557
2563
|
|
|
2558
2564
|
// These regular expressions are to be used with Lexer.acceptMatchRun(),
|
|
2559
2565
|
// which expects the sticky flag to be set.
|
|
2560
|
-
const exponentPattern = /
|
|
2566
|
+
const exponentPattern = /[eE][+-]?\d+/y;
|
|
2561
2567
|
const functionNamePattern = /[a-z][a-z_0-9]*/y;
|
|
2562
2568
|
const indexPattern = /-?\d+/y;
|
|
2563
2569
|
const intPattern = /-?[0-9]+/y;
|
|
@@ -4000,7 +4006,7 @@ class Parser {
|
|
|
4000
4006
|
switch (stream.current.kind) {
|
|
4001
4007
|
case TokenKind.SINGLE_QUOTE_STRING:
|
|
4002
4008
|
case TokenKind.DOUBLE_QUOTE_STRING:
|
|
4003
|
-
items.push(new NameSelector(this.environment, stream.current, this.decodeString(stream.current
|
|
4009
|
+
items.push(new NameSelector(this.environment, stream.current, this.decodeString(stream.current), false));
|
|
4004
4010
|
break;
|
|
4005
4011
|
case TokenKind.FILTER:
|
|
4006
4012
|
items.push(this.parseFilter(stream));
|
|
@@ -4020,7 +4026,7 @@ class Parser {
|
|
|
4020
4026
|
break;
|
|
4021
4027
|
case TokenKind.KEY_SINGLE_QUOTE_STRING:
|
|
4022
4028
|
case TokenKind.KEY_DOUBLE_QUOTE_STRING:
|
|
4023
|
-
items.push(new KeySelector(this.environment, stream.current, this.decodeString(stream.current
|
|
4029
|
+
items.push(new KeySelector(this.environment, stream.current, this.decodeString(stream.current), false));
|
|
4024
4030
|
break;
|
|
4025
4031
|
case TokenKind.KEYS_FILTER:
|
|
4026
4032
|
items.push(this.parseFilter(stream, true));
|
|
@@ -4036,6 +4042,7 @@ class Parser {
|
|
|
4036
4042
|
if (stream.peek.kind !== TokenKind.RBRACKET) {
|
|
4037
4043
|
stream.expectPeek(TokenKind.COMMA);
|
|
4038
4044
|
stream.next();
|
|
4045
|
+
stream.expectPeekNot(TokenKind.RBRACKET, "unexpected trailing comma");
|
|
4039
4046
|
}
|
|
4040
4047
|
stream.next();
|
|
4041
4048
|
}
|
|
@@ -4054,6 +4061,7 @@ class Parser {
|
|
|
4054
4061
|
throw new JSONPathTypeError(`result of ${expr.name}() must be compared`, expr.token);
|
|
4055
4062
|
}
|
|
4056
4063
|
}
|
|
4064
|
+
this.throwForLiteral(expr);
|
|
4057
4065
|
return keys ? new KeysFilterSelector(this.environment, tok, new LogicalExpression(tok, expr)) : new FilterSelector(this.environment, tok, new LogicalExpression(tok, expr));
|
|
4058
4066
|
}
|
|
4059
4067
|
parseBoolean(stream) {
|
|
@@ -4067,7 +4075,15 @@ class Parser {
|
|
|
4067
4075
|
return new StringLiteral(stream.current, this.decodeString(stream.current));
|
|
4068
4076
|
}
|
|
4069
4077
|
parseNumber(stream) {
|
|
4070
|
-
|
|
4078
|
+
const value = stream.current.value;
|
|
4079
|
+
if (value.startsWith("0") && value.length > 1) {
|
|
4080
|
+
throw new JSONPathSyntaxError(`invalid number literal '${value}'`, stream.current);
|
|
4081
|
+
}
|
|
4082
|
+
const num = Number(stream.current.value);
|
|
4083
|
+
if (isNaN(num)) {
|
|
4084
|
+
throw new JSONPathSyntaxError(`invalid number literal '${value}'`, stream.current);
|
|
4085
|
+
}
|
|
4086
|
+
return new NumberLiteral(stream.current, num);
|
|
4071
4087
|
}
|
|
4072
4088
|
parsePrefixExpression(stream) {
|
|
4073
4089
|
stream.expect(TokenKind.NOT);
|
|
@@ -4085,6 +4101,9 @@ class Parser {
|
|
|
4085
4101
|
if (COMPARISON_OPERATORS.has(operator)) {
|
|
4086
4102
|
this.throwForNonComparable(left);
|
|
4087
4103
|
this.throwForNonComparable(right);
|
|
4104
|
+
} else {
|
|
4105
|
+
this.throwForLiteral(left);
|
|
4106
|
+
this.throwForLiteral(right);
|
|
4088
4107
|
}
|
|
4089
4108
|
return new InfixExpression(tok, left, operator, right);
|
|
4090
4109
|
}
|
|
@@ -4175,11 +4194,155 @@ class Parser {
|
|
|
4175
4194
|
return left;
|
|
4176
4195
|
}
|
|
4177
4196
|
decodeString(token) {
|
|
4178
|
-
|
|
4197
|
+
return this.unescapeString(token.kind === TokenKind.SINGLE_QUOTE_STRING ? token.value.replaceAll('"', '\\"').replaceAll("\\'", "'") : token.value, token);
|
|
4198
|
+
}
|
|
4199
|
+
unescapeString(value, token) {
|
|
4200
|
+
const rv = [];
|
|
4201
|
+
const length = value.length;
|
|
4202
|
+
let index = 0;
|
|
4203
|
+
let codepoint;
|
|
4204
|
+
while (index < length) {
|
|
4205
|
+
const ch = value[index];
|
|
4206
|
+
if (ch === "\\") {
|
|
4207
|
+
// Handle escape sequences
|
|
4208
|
+
index += 1; // Move past '\'
|
|
4209
|
+
|
|
4210
|
+
switch (value[index]) {
|
|
4211
|
+
case '"':
|
|
4212
|
+
rv.push('"');
|
|
4213
|
+
break;
|
|
4214
|
+
case "\\":
|
|
4215
|
+
rv.push("\\");
|
|
4216
|
+
break;
|
|
4217
|
+
case "/":
|
|
4218
|
+
rv.push("/");
|
|
4219
|
+
break;
|
|
4220
|
+
case "b":
|
|
4221
|
+
rv.push("\x08");
|
|
4222
|
+
break;
|
|
4223
|
+
case "f":
|
|
4224
|
+
rv.push("\x0C");
|
|
4225
|
+
break;
|
|
4226
|
+
case "n":
|
|
4227
|
+
rv.push("\n");
|
|
4228
|
+
break;
|
|
4229
|
+
case "r":
|
|
4230
|
+
rv.push("\r");
|
|
4231
|
+
break;
|
|
4232
|
+
case "t":
|
|
4233
|
+
rv.push("\t");
|
|
4234
|
+
break;
|
|
4235
|
+
case "u":
|
|
4236
|
+
[codepoint, index] = this.decodeHexChar(value, index, token);
|
|
4237
|
+
rv.push(this.stringFromCodePoint(codepoint, token));
|
|
4238
|
+
break;
|
|
4239
|
+
default:
|
|
4240
|
+
// TODO: This is unreachable. The lexer will catch unknown escape sequences.
|
|
4241
|
+
throw new JSONPathSyntaxError(`unknown escape sequence at index ${token.index + index - 1}`, token);
|
|
4242
|
+
}
|
|
4243
|
+
} else {
|
|
4244
|
+
this.stringFromCodePoint(ch.codePointAt(0), token);
|
|
4245
|
+
rv.push(ch);
|
|
4246
|
+
}
|
|
4247
|
+
index += 1;
|
|
4248
|
+
}
|
|
4249
|
+
return rv.join("");
|
|
4250
|
+
}
|
|
4251
|
+
|
|
4252
|
+
/**
|
|
4253
|
+
* Decode a `\uXXXX` or `\uXXXX\uXXXX` escape sequence from _value_ at _index_.
|
|
4254
|
+
*
|
|
4255
|
+
* @param value - A string value containing the sequence to decode.
|
|
4256
|
+
* @param index - The start index of an escape sequence in _value_.
|
|
4257
|
+
* @param token - The token for the string value.
|
|
4258
|
+
* @returns - A codepoint, new index tuple.
|
|
4259
|
+
*/
|
|
4260
|
+
decodeHexChar(value, index, token) {
|
|
4261
|
+
const length = value.length;
|
|
4262
|
+
if (index + 4 >= length) {
|
|
4263
|
+
throw new JSONPathSyntaxError(`incomplete escape sequence at index ${token.index + index - 1}`, token);
|
|
4264
|
+
}
|
|
4265
|
+
index += 1; // Move past 'u'
|
|
4266
|
+
let codepoint = this.parseHexDigits(value.slice(index, index + 4), token);
|
|
4267
|
+
if (isLowSurrogate(codepoint)) {
|
|
4268
|
+
throw new JSONPathSyntaxError(`unexpected low surrogate codepoint at index ${token.index + index - 2}`, token);
|
|
4269
|
+
}
|
|
4270
|
+
if (isHighSurrogate(codepoint)) {
|
|
4271
|
+
// Expect a surrogate pair.
|
|
4272
|
+
if (!(index + 9 < length && value[index + 4] === "\\" && value[index + 5] === "u")) {
|
|
4273
|
+
throw new JSONPathSyntaxError(`incomplete escape sequence at index ${token.index + index - 2}`, token);
|
|
4274
|
+
}
|
|
4275
|
+
const lowSurrogate = this.parseHexDigits(value.slice(index + 6, index + 10), token);
|
|
4276
|
+
if (!isLowSurrogate(lowSurrogate)) {
|
|
4277
|
+
throw new JSONPathSyntaxError(`unexpected codepoint at index ${token.index + index + 4}`, token);
|
|
4278
|
+
}
|
|
4279
|
+
codepoint = 0x10000 + ((codepoint & 0x03ff) << 10 | lowSurrogate & 0x03ff);
|
|
4280
|
+
return [codepoint, index + 9];
|
|
4281
|
+
}
|
|
4282
|
+
return [codepoint, index + 3];
|
|
4283
|
+
}
|
|
4284
|
+
|
|
4285
|
+
/**
|
|
4286
|
+
* Parse a hexadecimal string as an integer.
|
|
4287
|
+
*
|
|
4288
|
+
* @param digits - Hexadecimal digit string.
|
|
4289
|
+
* @param token - The token for the string value.
|
|
4290
|
+
* @returns - The number representation of _digits_.
|
|
4291
|
+
*
|
|
4292
|
+
* Note that we're not using `parseInt(digits, 16)` because it accepts `+`
|
|
4293
|
+
* and `-` and things we don't allow.
|
|
4294
|
+
*/
|
|
4295
|
+
parseHexDigits(digits, token) {
|
|
4296
|
+
const encoder = new TextEncoder();
|
|
4297
|
+
let codepoint = 0;
|
|
4298
|
+
for (const digit of encoder.encode(digits)) {
|
|
4299
|
+
codepoint <<= 4;
|
|
4300
|
+
switch (digit) {
|
|
4301
|
+
case 48:
|
|
4302
|
+
case 49:
|
|
4303
|
+
case 50:
|
|
4304
|
+
case 51:
|
|
4305
|
+
case 52:
|
|
4306
|
+
case 53:
|
|
4307
|
+
case 54:
|
|
4308
|
+
case 55:
|
|
4309
|
+
case 56:
|
|
4310
|
+
case 57:
|
|
4311
|
+
codepoint |= digit - 48; // '0'
|
|
4312
|
+
break;
|
|
4313
|
+
case 97:
|
|
4314
|
+
case 98:
|
|
4315
|
+
case 99:
|
|
4316
|
+
case 100:
|
|
4317
|
+
case 101:
|
|
4318
|
+
case 102:
|
|
4319
|
+
codepoint |= digit - 97 + 10; // 'a'
|
|
4320
|
+
break;
|
|
4321
|
+
case 65:
|
|
4322
|
+
case 66:
|
|
4323
|
+
case 67:
|
|
4324
|
+
case 68:
|
|
4325
|
+
case 69:
|
|
4326
|
+
case 70:
|
|
4327
|
+
codepoint |= digit - 65 + 10; // 'A'
|
|
4328
|
+
break;
|
|
4329
|
+
default:
|
|
4330
|
+
throw new JSONPathSyntaxError("invalid \\uXXXX escape sequence", token);
|
|
4331
|
+
}
|
|
4332
|
+
}
|
|
4333
|
+
return codepoint;
|
|
4334
|
+
}
|
|
4335
|
+
|
|
4336
|
+
/** Check the codepoint is valid and return its string representation. */
|
|
4337
|
+
stringFromCodePoint(codepoint, token) {
|
|
4338
|
+
if (codepoint === undefined || codepoint <= 0x1f) {
|
|
4339
|
+
throw new JSONPathSyntaxError(`invalid character`, token);
|
|
4340
|
+
}
|
|
4179
4341
|
try {
|
|
4180
|
-
return
|
|
4342
|
+
return String.fromCodePoint(codepoint);
|
|
4181
4343
|
} catch {
|
|
4182
|
-
|
|
4344
|
+
// This should not be reachable.
|
|
4345
|
+
throw new JSONPathSyntaxError("invalid escape sequence", token);
|
|
4183
4346
|
}
|
|
4184
4347
|
}
|
|
4185
4348
|
throwForNonComparable(expr) {
|
|
@@ -4193,6 +4356,17 @@ class Parser {
|
|
|
4193
4356
|
}
|
|
4194
4357
|
}
|
|
4195
4358
|
}
|
|
4359
|
+
throwForLiteral(expr) {
|
|
4360
|
+
if (expr instanceof FilterExpressionLiteral) {
|
|
4361
|
+
throw new JSONPathSyntaxError(`filter expression literals (${expr.toString()}) must be compared`, expr.token);
|
|
4362
|
+
}
|
|
4363
|
+
}
|
|
4364
|
+
}
|
|
4365
|
+
function isHighSurrogate(codepoint) {
|
|
4366
|
+
return codepoint >= 0xd800 && codepoint <= 0xdbff;
|
|
4367
|
+
}
|
|
4368
|
+
function isLowSurrogate(codepoint) {
|
|
4369
|
+
return codepoint >= 0xdc00 && codepoint <= 0xdfff;
|
|
4196
4370
|
}
|
|
4197
4371
|
|
|
4198
4372
|
/**
|
|
@@ -4251,7 +4425,7 @@ class JSONPathEnvironment {
|
|
|
4251
4425
|
let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
4252
4426
|
this.strict = options.strict ?? true;
|
|
4253
4427
|
this.maxIntIndex = options.maxIntIndex ?? Math.pow(2, 53) - 1;
|
|
4254
|
-
this.minIntIndex = options.maxIntIndex ?? -Math.pow(2, 53)
|
|
4428
|
+
this.minIntIndex = options.maxIntIndex ?? -Math.pow(2, 53) + 1;
|
|
4255
4429
|
this.maxRecursionDepth = options.maxRecursionDepth ?? 50;
|
|
4256
4430
|
this.nondeterministic = options.nondeterministic ?? false;
|
|
4257
4431
|
this.keysPattern = options.keysPattern ?? /~/y;
|
|
@@ -4975,6 +5149,6 @@ var index = /*#__PURE__*/Object.freeze({
|
|
|
4975
5149
|
apply: apply
|
|
4976
5150
|
});
|
|
4977
5151
|
|
|
4978
|
-
const version = "1.3.
|
|
5152
|
+
const version = "1.3.4";
|
|
4979
5153
|
|
|
4980
5154
|
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 };
|