@zaly/agent 0.0.4 → 0.0.6
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/{agent-GDLdDc2w.mjs → agent-DirSoZjM.mjs} +8 -9
- package/dist/agent-DirSoZjM.mjs.map +1 -0
- package/dist/{bash-QNMTQ1PD.mjs → bash-COgq4W7U.mjs} +2 -2
- package/dist/{bash-QNMTQ1PD.mjs.map → bash-COgq4W7U.mjs.map} +1 -1
- package/dist/compactions-3AjPqjeZ.mjs.map +1 -1
- package/dist/{fetch-D8cmmA3E.mjs → fetch-DXuxAg_t.mjs} +3 -3
- package/dist/{fetch-D8cmmA3E.mjs.map → fetch-DXuxAg_t.mjs.map} +1 -1
- package/dist/{grep-B2Ax7ewy.mjs → grep-B4GF0svc.mjs} +2 -2
- package/dist/{grep-B2Ax7ewy.mjs.map → grep-B4GF0svc.mjs.map} +1 -1
- package/dist/index-node-esm-DAnl9SaE.mjs +2114 -0
- package/dist/index-node-esm-DAnl9SaE.mjs.map +1 -0
- package/dist/index.d.mts +47 -42
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +28 -22
- package/dist/index.mjs.map +1 -1
- package/dist/{jsonl-Dw_VBp46.mjs → jsonl-CvgEOakL.mjs} +2 -2
- package/dist/jsonl-CvgEOakL.mjs.map +1 -0
- package/dist/{manager-D-lWBTHG.mjs → manager-DHBfEtge.mjs} +12 -2
- package/dist/manager-DHBfEtge.mjs.map +1 -0
- package/dist/masker-Bv9KjkDF.mjs.map +1 -1
- package/dist/notify-DpG_m9iP.mjs.map +1 -1
- package/dist/{registry-CFmR5G3J.mjs → registry-Bao6L4Ue.mjs} +399 -73
- package/dist/registry-Bao6L4Ue.mjs.map +1 -0
- package/dist/session/claude.d.mts +2 -3
- package/dist/session/claude.d.mts.map +1 -1
- package/dist/session/claude.mjs +1 -1
- package/dist/{session-CUUdWFC5.mjs → session-B1lXSWhT.mjs} +4 -4
- package/dist/session-B1lXSWhT.mjs.map +1 -0
- package/dist/session.d.mts +8 -8
- package/dist/session.d.mts.map +1 -1
- package/dist/session.mjs +3 -3
- package/dist/{subagent-baqzjRMc.mjs → subagent-Zz-MQHk2.mjs} +3 -3
- package/dist/{subagent-baqzjRMc.mjs.map → subagent-Zz-MQHk2.mjs.map} +1 -1
- package/dist/swarm-BJ3gQA1Z.mjs.map +1 -1
- package/dist/{tasks-D8rARHZ1.mjs → tasks-BA-PCeGa.mjs} +4 -3
- package/dist/{tasks-D8rARHZ1.mjs.map → tasks-BA-PCeGa.mjs.map} +1 -1
- package/dist/{tasks-WmC270X2.mjs → tasks-WdRAHsOL.mjs} +5 -4
- package/dist/tasks-WdRAHsOL.mjs.map +1 -0
- package/dist/{tools-DW1dbcCz.mjs → tools-CZvBFp-v.mjs} +144 -38
- package/dist/tools-CZvBFp-v.mjs.map +1 -0
- package/dist/truncate-BSMXgiXj.mjs.map +1 -1
- package/dist/{uuid-ByXP5SO5.mjs → uuid-CAdJg4l8.mjs} +2 -2
- package/dist/{uuid-ByXP5SO5.mjs.map → uuid-CAdJg4l8.mjs.map} +1 -1
- package/package.json +12 -12
- package/dist/agent-GDLdDc2w.mjs.map +0 -1
- package/dist/index-node-esm-D6YQRKEz.mjs +0 -1537
- package/dist/index-node-esm-D6YQRKEz.mjs.map +0 -1
- package/dist/jsonl-Dw_VBp46.mjs.map +0 -1
- package/dist/manager-D-lWBTHG.mjs.map +0 -1
- package/dist/registry-CFmR5G3J.mjs.map +0 -1
- package/dist/session-CUUdWFC5.mjs.map +0 -1
- package/dist/tasks-WmC270X2.mjs.map +0 -1
- package/dist/tools-DW1dbcCz.mjs.map +0 -1
|
@@ -0,0 +1,2114 @@
|
|
|
1
|
+
import vm from "node:vm";
|
|
2
|
+
//#region ../../node_modules/.bun/jsonpath-plus@11.2.0/node_modules/jsonpath-plus/dist/index-node-esm.js
|
|
3
|
+
/**
|
|
4
|
+
* @implements {IHooks}
|
|
5
|
+
*/
|
|
6
|
+
var Hooks = class {
|
|
7
|
+
/**
|
|
8
|
+
* @callback HookCallback
|
|
9
|
+
* @this {*|Jsep} this
|
|
10
|
+
* @param {Jsep} env
|
|
11
|
+
* @returns: void
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Adds the given callback to the list of callbacks for the given hook.
|
|
15
|
+
*
|
|
16
|
+
* The callback will be invoked when the hook it is registered for is run.
|
|
17
|
+
*
|
|
18
|
+
* One callback function can be registered to multiple hooks and the same hook multiple times.
|
|
19
|
+
*
|
|
20
|
+
* @param {string|object} name The name of the hook, or an object of callbacks keyed by name
|
|
21
|
+
* @param {HookCallback|boolean} callback The callback function which is given environment variables.
|
|
22
|
+
* @param {?boolean} [first=false] Will add the hook to the top of the list (defaults to the bottom)
|
|
23
|
+
* @public
|
|
24
|
+
*/
|
|
25
|
+
add(name, callback, first) {
|
|
26
|
+
if (typeof arguments[0] != "string") for (let name in arguments[0]) this.add(name, arguments[0][name], arguments[1]);
|
|
27
|
+
else (Array.isArray(name) ? name : [name]).forEach(function(name) {
|
|
28
|
+
this[name] = this[name] || [];
|
|
29
|
+
if (callback) this[name][first ? "unshift" : "push"](callback);
|
|
30
|
+
}, this);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Runs a hook invoking all registered callbacks with the given environment variables.
|
|
34
|
+
*
|
|
35
|
+
* Callbacks will be invoked synchronously and in the order in which they were registered.
|
|
36
|
+
*
|
|
37
|
+
* @param {string} name The name of the hook.
|
|
38
|
+
* @param {Object<string, any>} env The environment variables of the hook passed to all callbacks registered.
|
|
39
|
+
* @public
|
|
40
|
+
*/
|
|
41
|
+
run(name, env) {
|
|
42
|
+
this[name] = this[name] || [];
|
|
43
|
+
this[name].forEach(function(callback) {
|
|
44
|
+
callback.call(env && env.context ? env.context : env, env);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* @implements {IPlugins}
|
|
50
|
+
*/
|
|
51
|
+
var Plugins = class {
|
|
52
|
+
constructor(jsep) {
|
|
53
|
+
this.jsep = jsep;
|
|
54
|
+
this.registered = {};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* @callback PluginSetup
|
|
58
|
+
* @this {Jsep} jsep
|
|
59
|
+
* @returns: void
|
|
60
|
+
*/
|
|
61
|
+
/**
|
|
62
|
+
* Adds the given plugin(s) to the registry
|
|
63
|
+
*
|
|
64
|
+
* @param {object} plugins
|
|
65
|
+
* @param {string} plugins.name The name of the plugin
|
|
66
|
+
* @param {PluginSetup} plugins.init The init function
|
|
67
|
+
* @public
|
|
68
|
+
*/
|
|
69
|
+
register(...plugins) {
|
|
70
|
+
plugins.forEach((plugin) => {
|
|
71
|
+
if (typeof plugin !== "object" || !plugin.name || !plugin.init) throw new Error("Invalid JSEP plugin format");
|
|
72
|
+
if (this.registered[plugin.name]) return;
|
|
73
|
+
plugin.init(this.jsep);
|
|
74
|
+
this.registered[plugin.name] = plugin;
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
var Jsep = class Jsep {
|
|
79
|
+
/**
|
|
80
|
+
* @returns {string}
|
|
81
|
+
*/
|
|
82
|
+
static get version() {
|
|
83
|
+
return "1.4.0";
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* @returns {string}
|
|
87
|
+
*/
|
|
88
|
+
static toString() {
|
|
89
|
+
return "JavaScript Expression Parser (JSEP) v" + Jsep.version;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* @method addUnaryOp
|
|
93
|
+
* @param {string} op_name The name of the unary op to add
|
|
94
|
+
* @returns {Jsep}
|
|
95
|
+
*/
|
|
96
|
+
static addUnaryOp(op_name) {
|
|
97
|
+
Jsep.max_unop_len = Math.max(op_name.length, Jsep.max_unop_len);
|
|
98
|
+
Jsep.unary_ops[op_name] = 1;
|
|
99
|
+
return Jsep;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* @method jsep.addBinaryOp
|
|
103
|
+
* @param {string} op_name The name of the binary op to add
|
|
104
|
+
* @param {number} precedence The precedence of the binary op (can be a float). Higher number = higher precedence
|
|
105
|
+
* @param {boolean} [isRightAssociative=false] whether operator is right-associative
|
|
106
|
+
* @returns {Jsep}
|
|
107
|
+
*/
|
|
108
|
+
static addBinaryOp(op_name, precedence, isRightAssociative) {
|
|
109
|
+
Jsep.max_binop_len = Math.max(op_name.length, Jsep.max_binop_len);
|
|
110
|
+
Jsep.binary_ops[op_name] = precedence;
|
|
111
|
+
if (isRightAssociative) Jsep.right_associative.add(op_name);
|
|
112
|
+
else Jsep.right_associative.delete(op_name);
|
|
113
|
+
return Jsep;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* @method addIdentifierChar
|
|
117
|
+
* @param {string} char The additional character to treat as a valid part of an identifier
|
|
118
|
+
* @returns {Jsep}
|
|
119
|
+
*/
|
|
120
|
+
static addIdentifierChar(char) {
|
|
121
|
+
Jsep.additional_identifier_chars.add(char);
|
|
122
|
+
return Jsep;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* @method addLiteral
|
|
126
|
+
* @param {string} literal_name The name of the literal to add
|
|
127
|
+
* @param {*} literal_value The value of the literal
|
|
128
|
+
* @returns {Jsep}
|
|
129
|
+
*/
|
|
130
|
+
static addLiteral(literal_name, literal_value) {
|
|
131
|
+
Jsep.literals[literal_name] = literal_value;
|
|
132
|
+
return Jsep;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* @method removeUnaryOp
|
|
136
|
+
* @param {string} op_name The name of the unary op to remove
|
|
137
|
+
* @returns {Jsep}
|
|
138
|
+
*/
|
|
139
|
+
static removeUnaryOp(op_name) {
|
|
140
|
+
delete Jsep.unary_ops[op_name];
|
|
141
|
+
if (op_name.length === Jsep.max_unop_len) Jsep.max_unop_len = Jsep.getMaxKeyLen(Jsep.unary_ops);
|
|
142
|
+
return Jsep;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* @method removeAllUnaryOps
|
|
146
|
+
* @returns {Jsep}
|
|
147
|
+
*/
|
|
148
|
+
static removeAllUnaryOps() {
|
|
149
|
+
Jsep.unary_ops = {};
|
|
150
|
+
Jsep.max_unop_len = 0;
|
|
151
|
+
return Jsep;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* @method removeIdentifierChar
|
|
155
|
+
* @param {string} char The additional character to stop treating as a valid part of an identifier
|
|
156
|
+
* @returns {Jsep}
|
|
157
|
+
*/
|
|
158
|
+
static removeIdentifierChar(char) {
|
|
159
|
+
Jsep.additional_identifier_chars.delete(char);
|
|
160
|
+
return Jsep;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* @method removeBinaryOp
|
|
164
|
+
* @param {string} op_name The name of the binary op to remove
|
|
165
|
+
* @returns {Jsep}
|
|
166
|
+
*/
|
|
167
|
+
static removeBinaryOp(op_name) {
|
|
168
|
+
delete Jsep.binary_ops[op_name];
|
|
169
|
+
if (op_name.length === Jsep.max_binop_len) Jsep.max_binop_len = Jsep.getMaxKeyLen(Jsep.binary_ops);
|
|
170
|
+
Jsep.right_associative.delete(op_name);
|
|
171
|
+
return Jsep;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* @method removeAllBinaryOps
|
|
175
|
+
* @returns {Jsep}
|
|
176
|
+
*/
|
|
177
|
+
static removeAllBinaryOps() {
|
|
178
|
+
Jsep.binary_ops = {};
|
|
179
|
+
Jsep.max_binop_len = 0;
|
|
180
|
+
return Jsep;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* @method removeLiteral
|
|
184
|
+
* @param {string} literal_name The name of the literal to remove
|
|
185
|
+
* @returns {Jsep}
|
|
186
|
+
*/
|
|
187
|
+
static removeLiteral(literal_name) {
|
|
188
|
+
delete Jsep.literals[literal_name];
|
|
189
|
+
return Jsep;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* @method removeAllLiterals
|
|
193
|
+
* @returns {Jsep}
|
|
194
|
+
*/
|
|
195
|
+
static removeAllLiterals() {
|
|
196
|
+
Jsep.literals = {};
|
|
197
|
+
return Jsep;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* @returns {string}
|
|
201
|
+
*/
|
|
202
|
+
get char() {
|
|
203
|
+
return this.expr.charAt(this.index);
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* @returns {number}
|
|
207
|
+
*/
|
|
208
|
+
get code() {
|
|
209
|
+
return this.expr.charCodeAt(this.index);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* @param {string} expr a string with the passed in express
|
|
213
|
+
* @returns Jsep
|
|
214
|
+
*/
|
|
215
|
+
constructor(expr) {
|
|
216
|
+
this.expr = expr;
|
|
217
|
+
this.index = 0;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* static top-level parser
|
|
221
|
+
* @returns {jsep.Expression}
|
|
222
|
+
*/
|
|
223
|
+
static parse(expr) {
|
|
224
|
+
return new Jsep(expr).parse();
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Get the longest key length of any object
|
|
228
|
+
* @param {object} obj
|
|
229
|
+
* @returns {number}
|
|
230
|
+
*/
|
|
231
|
+
static getMaxKeyLen(obj) {
|
|
232
|
+
return Math.max(0, ...Object.keys(obj).map((k) => k.length));
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* `ch` is a character code in the next three functions
|
|
236
|
+
* @param {number} ch
|
|
237
|
+
* @returns {boolean}
|
|
238
|
+
*/
|
|
239
|
+
static isDecimalDigit(ch) {
|
|
240
|
+
return ch >= 48 && ch <= 57;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Returns the precedence of a binary operator or `0` if it isn't a binary operator. Can be float.
|
|
244
|
+
* @param {string} op_val
|
|
245
|
+
* @returns {number}
|
|
246
|
+
*/
|
|
247
|
+
static binaryPrecedence(op_val) {
|
|
248
|
+
return Jsep.binary_ops[op_val] || 0;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Looks for start of identifier
|
|
252
|
+
* @param {number} ch
|
|
253
|
+
* @returns {boolean}
|
|
254
|
+
*/
|
|
255
|
+
static isIdentifierStart(ch) {
|
|
256
|
+
return ch >= 65 && ch <= 90 || ch >= 97 && ch <= 122 || ch >= 128 && !Jsep.binary_ops[String.fromCharCode(ch)] || Jsep.additional_identifier_chars.has(String.fromCharCode(ch));
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* @param {number} ch
|
|
260
|
+
* @returns {boolean}
|
|
261
|
+
*/
|
|
262
|
+
static isIdentifierPart(ch) {
|
|
263
|
+
return Jsep.isIdentifierStart(ch) || Jsep.isDecimalDigit(ch);
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* throw error at index of the expression
|
|
267
|
+
* @param {string} message
|
|
268
|
+
* @throws
|
|
269
|
+
*/
|
|
270
|
+
throwError(message) {
|
|
271
|
+
const error = /* @__PURE__ */ new Error(message + " at character " + this.index);
|
|
272
|
+
error.index = this.index;
|
|
273
|
+
error.description = message;
|
|
274
|
+
throw error;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Run a given hook
|
|
278
|
+
* @param {string} name
|
|
279
|
+
* @param {jsep.Expression|false} [node]
|
|
280
|
+
* @returns {?jsep.Expression}
|
|
281
|
+
*/
|
|
282
|
+
runHook(name, node) {
|
|
283
|
+
if (Jsep.hooks[name]) {
|
|
284
|
+
const env = {
|
|
285
|
+
context: this,
|
|
286
|
+
node
|
|
287
|
+
};
|
|
288
|
+
Jsep.hooks.run(name, env);
|
|
289
|
+
return env.node;
|
|
290
|
+
}
|
|
291
|
+
return node;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Runs a given hook until one returns a node
|
|
295
|
+
* @param {string} name
|
|
296
|
+
* @returns {?jsep.Expression}
|
|
297
|
+
*/
|
|
298
|
+
searchHook(name) {
|
|
299
|
+
if (Jsep.hooks[name]) {
|
|
300
|
+
const env = { context: this };
|
|
301
|
+
Jsep.hooks[name].find(function(callback) {
|
|
302
|
+
callback.call(env.context, env);
|
|
303
|
+
return env.node;
|
|
304
|
+
});
|
|
305
|
+
return env.node;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Push `index` up to the next non-space character
|
|
310
|
+
*/
|
|
311
|
+
gobbleSpaces() {
|
|
312
|
+
let ch = this.code;
|
|
313
|
+
while (ch === Jsep.SPACE_CODE || ch === Jsep.TAB_CODE || ch === Jsep.LF_CODE || ch === Jsep.CR_CODE) ch = this.expr.charCodeAt(++this.index);
|
|
314
|
+
this.runHook("gobble-spaces");
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Top-level method to parse all expressions and returns compound or single node
|
|
318
|
+
* @returns {jsep.Expression}
|
|
319
|
+
*/
|
|
320
|
+
parse() {
|
|
321
|
+
this.runHook("before-all");
|
|
322
|
+
const nodes = this.gobbleExpressions();
|
|
323
|
+
const node = nodes.length === 1 ? nodes[0] : {
|
|
324
|
+
type: Jsep.COMPOUND,
|
|
325
|
+
body: nodes
|
|
326
|
+
};
|
|
327
|
+
return this.runHook("after-all", node);
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* top-level parser (but can be reused within as well)
|
|
331
|
+
* @param {number} [untilICode]
|
|
332
|
+
* @returns {jsep.Expression[]}
|
|
333
|
+
*/
|
|
334
|
+
gobbleExpressions(untilICode) {
|
|
335
|
+
let nodes = [], ch_i, node;
|
|
336
|
+
while (this.index < this.expr.length) {
|
|
337
|
+
ch_i = this.code;
|
|
338
|
+
if (ch_i === Jsep.SEMCOL_CODE || ch_i === Jsep.COMMA_CODE) this.index++;
|
|
339
|
+
else if (node = this.gobbleExpression()) nodes.push(node);
|
|
340
|
+
else if (this.index < this.expr.length) {
|
|
341
|
+
if (ch_i === untilICode) break;
|
|
342
|
+
this.throwError("Unexpected \"" + this.char + "\"");
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
return nodes;
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* The main parsing function.
|
|
349
|
+
* @returns {?jsep.Expression}
|
|
350
|
+
*/
|
|
351
|
+
gobbleExpression() {
|
|
352
|
+
const node = this.searchHook("gobble-expression") || this.gobbleBinaryExpression();
|
|
353
|
+
this.gobbleSpaces();
|
|
354
|
+
return this.runHook("after-expression", node);
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Search for the operation portion of the string (e.g. `+`, `===`)
|
|
358
|
+
* Start by taking the longest possible binary operations (3 characters: `===`, `!==`, `>>>`)
|
|
359
|
+
* and move down from 3 to 2 to 1 character until a matching binary operation is found
|
|
360
|
+
* then, return that binary operation
|
|
361
|
+
* @returns {string|boolean}
|
|
362
|
+
*/
|
|
363
|
+
gobbleBinaryOp() {
|
|
364
|
+
this.gobbleSpaces();
|
|
365
|
+
let to_check = this.expr.substr(this.index, Jsep.max_binop_len);
|
|
366
|
+
let tc_len = to_check.length;
|
|
367
|
+
while (tc_len > 0) {
|
|
368
|
+
if (Jsep.binary_ops.hasOwnProperty(to_check) && (!Jsep.isIdentifierStart(this.code) || this.index + to_check.length < this.expr.length && !Jsep.isIdentifierPart(this.expr.charCodeAt(this.index + to_check.length)))) {
|
|
369
|
+
this.index += tc_len;
|
|
370
|
+
return to_check;
|
|
371
|
+
}
|
|
372
|
+
to_check = to_check.substr(0, --tc_len);
|
|
373
|
+
}
|
|
374
|
+
return false;
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* This function is responsible for gobbling an individual expression,
|
|
378
|
+
* e.g. `1`, `1+2`, `a+(b*2)-Math.sqrt(2)`
|
|
379
|
+
* @returns {?jsep.BinaryExpression}
|
|
380
|
+
*/
|
|
381
|
+
gobbleBinaryExpression() {
|
|
382
|
+
let node, biop, prec, stack, biop_info, left, right, i, cur_biop;
|
|
383
|
+
left = this.gobbleToken();
|
|
384
|
+
if (!left) return left;
|
|
385
|
+
biop = this.gobbleBinaryOp();
|
|
386
|
+
if (!biop) return left;
|
|
387
|
+
biop_info = {
|
|
388
|
+
value: biop,
|
|
389
|
+
prec: Jsep.binaryPrecedence(biop),
|
|
390
|
+
right_a: Jsep.right_associative.has(biop)
|
|
391
|
+
};
|
|
392
|
+
right = this.gobbleToken();
|
|
393
|
+
if (!right) this.throwError("Expected expression after " + biop);
|
|
394
|
+
stack = [
|
|
395
|
+
left,
|
|
396
|
+
biop_info,
|
|
397
|
+
right
|
|
398
|
+
];
|
|
399
|
+
while (biop = this.gobbleBinaryOp()) {
|
|
400
|
+
prec = Jsep.binaryPrecedence(biop);
|
|
401
|
+
if (prec === 0) {
|
|
402
|
+
this.index -= biop.length;
|
|
403
|
+
break;
|
|
404
|
+
}
|
|
405
|
+
biop_info = {
|
|
406
|
+
value: biop,
|
|
407
|
+
prec,
|
|
408
|
+
right_a: Jsep.right_associative.has(biop)
|
|
409
|
+
};
|
|
410
|
+
cur_biop = biop;
|
|
411
|
+
const comparePrev = (prev) => biop_info.right_a && prev.right_a ? prec > prev.prec : prec <= prev.prec;
|
|
412
|
+
while (stack.length > 2 && comparePrev(stack[stack.length - 2])) {
|
|
413
|
+
right = stack.pop();
|
|
414
|
+
biop = stack.pop().value;
|
|
415
|
+
left = stack.pop();
|
|
416
|
+
node = {
|
|
417
|
+
type: Jsep.BINARY_EXP,
|
|
418
|
+
operator: biop,
|
|
419
|
+
left,
|
|
420
|
+
right
|
|
421
|
+
};
|
|
422
|
+
stack.push(node);
|
|
423
|
+
}
|
|
424
|
+
node = this.gobbleToken();
|
|
425
|
+
if (!node) this.throwError("Expected expression after " + cur_biop);
|
|
426
|
+
stack.push(biop_info, node);
|
|
427
|
+
}
|
|
428
|
+
i = stack.length - 1;
|
|
429
|
+
node = stack[i];
|
|
430
|
+
while (i > 1) {
|
|
431
|
+
node = {
|
|
432
|
+
type: Jsep.BINARY_EXP,
|
|
433
|
+
operator: stack[i - 1].value,
|
|
434
|
+
left: stack[i - 2],
|
|
435
|
+
right: node
|
|
436
|
+
};
|
|
437
|
+
i -= 2;
|
|
438
|
+
}
|
|
439
|
+
return node;
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* An individual part of a binary expression:
|
|
443
|
+
* e.g. `foo.bar(baz)`, `1`, `"abc"`, `(a % 2)` (because it's in parenthesis)
|
|
444
|
+
* @returns {boolean|jsep.Expression}
|
|
445
|
+
*/
|
|
446
|
+
gobbleToken() {
|
|
447
|
+
let ch, to_check, tc_len, node;
|
|
448
|
+
this.gobbleSpaces();
|
|
449
|
+
node = this.searchHook("gobble-token");
|
|
450
|
+
if (node) return this.runHook("after-token", node);
|
|
451
|
+
ch = this.code;
|
|
452
|
+
if (Jsep.isDecimalDigit(ch) || ch === Jsep.PERIOD_CODE) return this.gobbleNumericLiteral();
|
|
453
|
+
if (ch === Jsep.SQUOTE_CODE || ch === Jsep.DQUOTE_CODE) node = this.gobbleStringLiteral();
|
|
454
|
+
else if (ch === Jsep.OBRACK_CODE) node = this.gobbleArray();
|
|
455
|
+
else {
|
|
456
|
+
to_check = this.expr.substr(this.index, Jsep.max_unop_len);
|
|
457
|
+
tc_len = to_check.length;
|
|
458
|
+
while (tc_len > 0) {
|
|
459
|
+
if (Jsep.unary_ops.hasOwnProperty(to_check) && (!Jsep.isIdentifierStart(this.code) || this.index + to_check.length < this.expr.length && !Jsep.isIdentifierPart(this.expr.charCodeAt(this.index + to_check.length)))) {
|
|
460
|
+
this.index += tc_len;
|
|
461
|
+
const argument = this.gobbleToken();
|
|
462
|
+
if (!argument) this.throwError("missing unaryOp argument");
|
|
463
|
+
return this.runHook("after-token", {
|
|
464
|
+
type: Jsep.UNARY_EXP,
|
|
465
|
+
operator: to_check,
|
|
466
|
+
argument,
|
|
467
|
+
prefix: true
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
to_check = to_check.substr(0, --tc_len);
|
|
471
|
+
}
|
|
472
|
+
if (Jsep.isIdentifierStart(ch)) {
|
|
473
|
+
node = this.gobbleIdentifier();
|
|
474
|
+
if (Jsep.literals.hasOwnProperty(node.name)) node = {
|
|
475
|
+
type: Jsep.LITERAL,
|
|
476
|
+
value: Jsep.literals[node.name],
|
|
477
|
+
raw: node.name
|
|
478
|
+
};
|
|
479
|
+
else if (node.name === Jsep.this_str) node = { type: Jsep.THIS_EXP };
|
|
480
|
+
} else if (ch === Jsep.OPAREN_CODE) node = this.gobbleGroup();
|
|
481
|
+
}
|
|
482
|
+
if (!node) return this.runHook("after-token", false);
|
|
483
|
+
node = this.gobbleTokenProperty(node);
|
|
484
|
+
return this.runHook("after-token", node);
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Gobble properties of of identifiers/strings/arrays/groups.
|
|
488
|
+
* e.g. `foo`, `bar.baz`, `foo['bar'].baz`
|
|
489
|
+
* It also gobbles function calls:
|
|
490
|
+
* e.g. `Math.acos(obj.angle)`
|
|
491
|
+
* @param {jsep.Expression} node
|
|
492
|
+
* @returns {jsep.Expression}
|
|
493
|
+
*/
|
|
494
|
+
gobbleTokenProperty(node) {
|
|
495
|
+
this.gobbleSpaces();
|
|
496
|
+
let ch = this.code;
|
|
497
|
+
while (ch === Jsep.PERIOD_CODE || ch === Jsep.OBRACK_CODE || ch === Jsep.OPAREN_CODE || ch === Jsep.QUMARK_CODE) {
|
|
498
|
+
let optional;
|
|
499
|
+
if (ch === Jsep.QUMARK_CODE) {
|
|
500
|
+
if (this.expr.charCodeAt(this.index + 1) !== Jsep.PERIOD_CODE) break;
|
|
501
|
+
optional = true;
|
|
502
|
+
this.index += 2;
|
|
503
|
+
this.gobbleSpaces();
|
|
504
|
+
ch = this.code;
|
|
505
|
+
}
|
|
506
|
+
this.index++;
|
|
507
|
+
if (ch === Jsep.OBRACK_CODE) {
|
|
508
|
+
node = {
|
|
509
|
+
type: Jsep.MEMBER_EXP,
|
|
510
|
+
computed: true,
|
|
511
|
+
object: node,
|
|
512
|
+
property: this.gobbleExpression()
|
|
513
|
+
};
|
|
514
|
+
if (!node.property) this.throwError("Unexpected \"" + this.char + "\"");
|
|
515
|
+
this.gobbleSpaces();
|
|
516
|
+
ch = this.code;
|
|
517
|
+
if (ch !== Jsep.CBRACK_CODE) this.throwError("Unclosed [");
|
|
518
|
+
this.index++;
|
|
519
|
+
} else if (ch === Jsep.OPAREN_CODE) node = {
|
|
520
|
+
type: Jsep.CALL_EXP,
|
|
521
|
+
"arguments": this.gobbleArguments(Jsep.CPAREN_CODE),
|
|
522
|
+
callee: node
|
|
523
|
+
};
|
|
524
|
+
else if (ch === Jsep.PERIOD_CODE || optional) {
|
|
525
|
+
if (optional) this.index--;
|
|
526
|
+
this.gobbleSpaces();
|
|
527
|
+
node = {
|
|
528
|
+
type: Jsep.MEMBER_EXP,
|
|
529
|
+
computed: false,
|
|
530
|
+
object: node,
|
|
531
|
+
property: this.gobbleIdentifier()
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
if (optional) node.optional = true;
|
|
535
|
+
this.gobbleSpaces();
|
|
536
|
+
ch = this.code;
|
|
537
|
+
}
|
|
538
|
+
return node;
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* Parse simple numeric literals: `12`, `3.4`, `.5`. Do this by using a string to
|
|
542
|
+
* keep track of everything in the numeric literal and then calling `parseFloat` on that string
|
|
543
|
+
* @returns {jsep.Literal}
|
|
544
|
+
*/
|
|
545
|
+
gobbleNumericLiteral() {
|
|
546
|
+
let number = "", ch, chCode;
|
|
547
|
+
while (Jsep.isDecimalDigit(this.code)) number += this.expr.charAt(this.index++);
|
|
548
|
+
if (this.code === Jsep.PERIOD_CODE) {
|
|
549
|
+
number += this.expr.charAt(this.index++);
|
|
550
|
+
while (Jsep.isDecimalDigit(this.code)) number += this.expr.charAt(this.index++);
|
|
551
|
+
}
|
|
552
|
+
ch = this.char;
|
|
553
|
+
if (ch === "e" || ch === "E") {
|
|
554
|
+
number += this.expr.charAt(this.index++);
|
|
555
|
+
ch = this.char;
|
|
556
|
+
if (ch === "+" || ch === "-") number += this.expr.charAt(this.index++);
|
|
557
|
+
while (Jsep.isDecimalDigit(this.code)) number += this.expr.charAt(this.index++);
|
|
558
|
+
if (!Jsep.isDecimalDigit(this.expr.charCodeAt(this.index - 1))) this.throwError("Expected exponent (" + number + this.char + ")");
|
|
559
|
+
}
|
|
560
|
+
chCode = this.code;
|
|
561
|
+
if (Jsep.isIdentifierStart(chCode)) this.throwError("Variable names cannot start with a number (" + number + this.char + ")");
|
|
562
|
+
else if (chCode === Jsep.PERIOD_CODE || number.length === 1 && number.charCodeAt(0) === Jsep.PERIOD_CODE) this.throwError("Unexpected period");
|
|
563
|
+
return {
|
|
564
|
+
type: Jsep.LITERAL,
|
|
565
|
+
value: parseFloat(number),
|
|
566
|
+
raw: number
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* Parses a string literal, staring with single or double quotes with basic support for escape codes
|
|
571
|
+
* e.g. `"hello world"`, `'this is\nJSEP'`
|
|
572
|
+
* @returns {jsep.Literal}
|
|
573
|
+
*/
|
|
574
|
+
gobbleStringLiteral() {
|
|
575
|
+
let str = "";
|
|
576
|
+
const startIndex = this.index;
|
|
577
|
+
const quote = this.expr.charAt(this.index++);
|
|
578
|
+
let closed = false;
|
|
579
|
+
while (this.index < this.expr.length) {
|
|
580
|
+
let ch = this.expr.charAt(this.index++);
|
|
581
|
+
if (ch === quote) {
|
|
582
|
+
closed = true;
|
|
583
|
+
break;
|
|
584
|
+
} else if (ch === "\\") {
|
|
585
|
+
ch = this.expr.charAt(this.index++);
|
|
586
|
+
switch (ch) {
|
|
587
|
+
case "n":
|
|
588
|
+
str += "\n";
|
|
589
|
+
break;
|
|
590
|
+
case "r":
|
|
591
|
+
str += "\r";
|
|
592
|
+
break;
|
|
593
|
+
case "t":
|
|
594
|
+
str += " ";
|
|
595
|
+
break;
|
|
596
|
+
case "b":
|
|
597
|
+
str += "\b";
|
|
598
|
+
break;
|
|
599
|
+
case "f":
|
|
600
|
+
str += "\f";
|
|
601
|
+
break;
|
|
602
|
+
case "v":
|
|
603
|
+
str += "\v";
|
|
604
|
+
break;
|
|
605
|
+
default: str += ch;
|
|
606
|
+
}
|
|
607
|
+
} else str += ch;
|
|
608
|
+
}
|
|
609
|
+
if (!closed) this.throwError("Unclosed quote after \"" + str + "\"");
|
|
610
|
+
return {
|
|
611
|
+
type: Jsep.LITERAL,
|
|
612
|
+
value: str,
|
|
613
|
+
raw: this.expr.substring(startIndex, this.index)
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Gobbles only identifiers
|
|
618
|
+
* e.g.: `foo`, `_value`, `$x1`
|
|
619
|
+
* Also, this function checks if that identifier is a literal:
|
|
620
|
+
* (e.g. `true`, `false`, `null`) or `this`
|
|
621
|
+
* @returns {jsep.Identifier}
|
|
622
|
+
*/
|
|
623
|
+
gobbleIdentifier() {
|
|
624
|
+
let ch = this.code, start = this.index;
|
|
625
|
+
if (Jsep.isIdentifierStart(ch)) this.index++;
|
|
626
|
+
else this.throwError("Unexpected " + this.char);
|
|
627
|
+
while (this.index < this.expr.length) {
|
|
628
|
+
ch = this.code;
|
|
629
|
+
if (Jsep.isIdentifierPart(ch)) this.index++;
|
|
630
|
+
else break;
|
|
631
|
+
}
|
|
632
|
+
return {
|
|
633
|
+
type: Jsep.IDENTIFIER,
|
|
634
|
+
name: this.expr.slice(start, this.index)
|
|
635
|
+
};
|
|
636
|
+
}
|
|
637
|
+
/**
|
|
638
|
+
* Gobbles a list of arguments within the context of a function call
|
|
639
|
+
* or array literal. This function also assumes that the opening character
|
|
640
|
+
* `(` or `[` has already been gobbled, and gobbles expressions and commas
|
|
641
|
+
* until the terminator character `)` or `]` is encountered.
|
|
642
|
+
* e.g. `foo(bar, baz)`, `my_func()`, or `[bar, baz]`
|
|
643
|
+
* @param {number} termination
|
|
644
|
+
* @returns {jsep.Expression[]}
|
|
645
|
+
*/
|
|
646
|
+
gobbleArguments(termination) {
|
|
647
|
+
const args = [];
|
|
648
|
+
let closed = false;
|
|
649
|
+
let separator_count = 0;
|
|
650
|
+
while (this.index < this.expr.length) {
|
|
651
|
+
this.gobbleSpaces();
|
|
652
|
+
let ch_i = this.code;
|
|
653
|
+
if (ch_i === termination) {
|
|
654
|
+
closed = true;
|
|
655
|
+
this.index++;
|
|
656
|
+
if (termination === Jsep.CPAREN_CODE && separator_count && separator_count >= args.length) this.throwError("Unexpected token " + String.fromCharCode(termination));
|
|
657
|
+
break;
|
|
658
|
+
} else if (ch_i === Jsep.COMMA_CODE) {
|
|
659
|
+
this.index++;
|
|
660
|
+
separator_count++;
|
|
661
|
+
if (separator_count !== args.length) {
|
|
662
|
+
if (termination === Jsep.CPAREN_CODE) this.throwError("Unexpected token ,");
|
|
663
|
+
else if (termination === Jsep.CBRACK_CODE) for (let arg = args.length; arg < separator_count; arg++) args.push(null);
|
|
664
|
+
}
|
|
665
|
+
} else if (args.length !== separator_count && separator_count !== 0) this.throwError("Expected comma");
|
|
666
|
+
else {
|
|
667
|
+
const node = this.gobbleExpression();
|
|
668
|
+
if (!node || node.type === Jsep.COMPOUND) this.throwError("Expected comma");
|
|
669
|
+
args.push(node);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
if (!closed) this.throwError("Expected " + String.fromCharCode(termination));
|
|
673
|
+
return args;
|
|
674
|
+
}
|
|
675
|
+
/**
|
|
676
|
+
* Responsible for parsing a group of things within parentheses `()`
|
|
677
|
+
* that have no identifier in front (so not a function call)
|
|
678
|
+
* This function assumes that it needs to gobble the opening parenthesis
|
|
679
|
+
* and then tries to gobble everything within that parenthesis, assuming
|
|
680
|
+
* that the next thing it should see is the close parenthesis. If not,
|
|
681
|
+
* then the expression probably doesn't have a `)`
|
|
682
|
+
* @returns {boolean|jsep.Expression}
|
|
683
|
+
*/
|
|
684
|
+
gobbleGroup() {
|
|
685
|
+
this.index++;
|
|
686
|
+
let nodes = this.gobbleExpressions(Jsep.CPAREN_CODE);
|
|
687
|
+
if (this.code === Jsep.CPAREN_CODE) {
|
|
688
|
+
this.index++;
|
|
689
|
+
if (nodes.length === 1) return nodes[0];
|
|
690
|
+
else if (!nodes.length) return false;
|
|
691
|
+
else return {
|
|
692
|
+
type: Jsep.SEQUENCE_EXP,
|
|
693
|
+
expressions: nodes
|
|
694
|
+
};
|
|
695
|
+
} else this.throwError("Unclosed (");
|
|
696
|
+
}
|
|
697
|
+
/**
|
|
698
|
+
* Responsible for parsing Array literals `[1, 2, 3]`
|
|
699
|
+
* This function assumes that it needs to gobble the opening bracket
|
|
700
|
+
* and then tries to gobble the expressions as arguments.
|
|
701
|
+
* @returns {jsep.ArrayExpression}
|
|
702
|
+
*/
|
|
703
|
+
gobbleArray() {
|
|
704
|
+
this.index++;
|
|
705
|
+
return {
|
|
706
|
+
type: Jsep.ARRAY_EXP,
|
|
707
|
+
elements: this.gobbleArguments(Jsep.CBRACK_CODE)
|
|
708
|
+
};
|
|
709
|
+
}
|
|
710
|
+
};
|
|
711
|
+
const hooks = new Hooks();
|
|
712
|
+
Object.assign(Jsep, {
|
|
713
|
+
hooks,
|
|
714
|
+
plugins: new Plugins(Jsep),
|
|
715
|
+
COMPOUND: "Compound",
|
|
716
|
+
SEQUENCE_EXP: "SequenceExpression",
|
|
717
|
+
IDENTIFIER: "Identifier",
|
|
718
|
+
MEMBER_EXP: "MemberExpression",
|
|
719
|
+
LITERAL: "Literal",
|
|
720
|
+
THIS_EXP: "ThisExpression",
|
|
721
|
+
CALL_EXP: "CallExpression",
|
|
722
|
+
UNARY_EXP: "UnaryExpression",
|
|
723
|
+
BINARY_EXP: "BinaryExpression",
|
|
724
|
+
ARRAY_EXP: "ArrayExpression",
|
|
725
|
+
TAB_CODE: 9,
|
|
726
|
+
LF_CODE: 10,
|
|
727
|
+
CR_CODE: 13,
|
|
728
|
+
SPACE_CODE: 32,
|
|
729
|
+
PERIOD_CODE: 46,
|
|
730
|
+
COMMA_CODE: 44,
|
|
731
|
+
SQUOTE_CODE: 39,
|
|
732
|
+
DQUOTE_CODE: 34,
|
|
733
|
+
OPAREN_CODE: 40,
|
|
734
|
+
CPAREN_CODE: 41,
|
|
735
|
+
OBRACK_CODE: 91,
|
|
736
|
+
CBRACK_CODE: 93,
|
|
737
|
+
QUMARK_CODE: 63,
|
|
738
|
+
SEMCOL_CODE: 59,
|
|
739
|
+
COLON_CODE: 58,
|
|
740
|
+
unary_ops: {
|
|
741
|
+
"-": 1,
|
|
742
|
+
"!": 1,
|
|
743
|
+
"~": 1,
|
|
744
|
+
"+": 1
|
|
745
|
+
},
|
|
746
|
+
binary_ops: {
|
|
747
|
+
"||": 1,
|
|
748
|
+
"??": 1,
|
|
749
|
+
"&&": 2,
|
|
750
|
+
"|": 3,
|
|
751
|
+
"^": 4,
|
|
752
|
+
"&": 5,
|
|
753
|
+
"==": 6,
|
|
754
|
+
"!=": 6,
|
|
755
|
+
"===": 6,
|
|
756
|
+
"!==": 6,
|
|
757
|
+
"<": 7,
|
|
758
|
+
">": 7,
|
|
759
|
+
"<=": 7,
|
|
760
|
+
">=": 7,
|
|
761
|
+
"<<": 8,
|
|
762
|
+
">>": 8,
|
|
763
|
+
">>>": 8,
|
|
764
|
+
"+": 9,
|
|
765
|
+
"-": 9,
|
|
766
|
+
"*": 10,
|
|
767
|
+
"/": 10,
|
|
768
|
+
"%": 10,
|
|
769
|
+
"**": 11
|
|
770
|
+
},
|
|
771
|
+
right_associative: /* @__PURE__ */ new Set(["**"]),
|
|
772
|
+
additional_identifier_chars: /* @__PURE__ */ new Set(["$", "_"]),
|
|
773
|
+
literals: {
|
|
774
|
+
"true": true,
|
|
775
|
+
"false": false,
|
|
776
|
+
"null": null
|
|
777
|
+
},
|
|
778
|
+
this_str: "this"
|
|
779
|
+
});
|
|
780
|
+
Jsep.max_unop_len = Jsep.getMaxKeyLen(Jsep.unary_ops);
|
|
781
|
+
Jsep.max_binop_len = Jsep.getMaxKeyLen(Jsep.binary_ops);
|
|
782
|
+
const jsep = (expr) => new Jsep(expr).parse();
|
|
783
|
+
const stdClassProps = Object.getOwnPropertyNames(class Test {});
|
|
784
|
+
Object.getOwnPropertyNames(Jsep).filter((prop) => !stdClassProps.includes(prop) && jsep[prop] === void 0).forEach((m) => {
|
|
785
|
+
jsep[m] = Jsep[m];
|
|
786
|
+
});
|
|
787
|
+
jsep.Jsep = Jsep;
|
|
788
|
+
const CONDITIONAL_EXP = "ConditionalExpression";
|
|
789
|
+
jsep.plugins.register({
|
|
790
|
+
name: "ternary",
|
|
791
|
+
init(jsep) {
|
|
792
|
+
jsep.hooks.add("after-expression", function gobbleTernary(env) {
|
|
793
|
+
if (env.node && this.code === jsep.QUMARK_CODE) {
|
|
794
|
+
this.index++;
|
|
795
|
+
const test = env.node;
|
|
796
|
+
const consequent = this.gobbleExpression();
|
|
797
|
+
if (!consequent) this.throwError("Expected expression");
|
|
798
|
+
this.gobbleSpaces();
|
|
799
|
+
if (this.code === jsep.COLON_CODE) {
|
|
800
|
+
this.index++;
|
|
801
|
+
const alternate = this.gobbleExpression();
|
|
802
|
+
if (!alternate) this.throwError("Expected expression");
|
|
803
|
+
env.node = {
|
|
804
|
+
type: CONDITIONAL_EXP,
|
|
805
|
+
test,
|
|
806
|
+
consequent,
|
|
807
|
+
alternate
|
|
808
|
+
};
|
|
809
|
+
if (test.operator && jsep.binary_ops[test.operator] <= .9) {
|
|
810
|
+
let newTest = test;
|
|
811
|
+
while (newTest.right.operator && jsep.binary_ops[newTest.right.operator] <= .9) newTest = newTest.right;
|
|
812
|
+
env.node.test = newTest.right;
|
|
813
|
+
newTest.right = env.node;
|
|
814
|
+
env.node = test;
|
|
815
|
+
}
|
|
816
|
+
} else this.throwError("Expected :");
|
|
817
|
+
}
|
|
818
|
+
});
|
|
819
|
+
}
|
|
820
|
+
});
|
|
821
|
+
const FSLASH_CODE = 47;
|
|
822
|
+
const BSLASH_CODE = 92;
|
|
823
|
+
var index = {
|
|
824
|
+
name: "regex",
|
|
825
|
+
init(jsep) {
|
|
826
|
+
jsep.hooks.add("gobble-token", function gobbleRegexLiteral(env) {
|
|
827
|
+
if (this.code === FSLASH_CODE) {
|
|
828
|
+
const patternIndex = ++this.index;
|
|
829
|
+
let inCharSet = false;
|
|
830
|
+
while (this.index < this.expr.length) {
|
|
831
|
+
if (this.code === FSLASH_CODE && !inCharSet) {
|
|
832
|
+
const pattern = this.expr.slice(patternIndex, this.index);
|
|
833
|
+
let flags = "";
|
|
834
|
+
while (++this.index < this.expr.length) {
|
|
835
|
+
const code = this.code;
|
|
836
|
+
if (code >= 97 && code <= 122 || code >= 65 && code <= 90 || code >= 48 && code <= 57) flags += this.char;
|
|
837
|
+
else break;
|
|
838
|
+
}
|
|
839
|
+
let value;
|
|
840
|
+
try {
|
|
841
|
+
value = new RegExp(pattern, flags);
|
|
842
|
+
} catch (e) {
|
|
843
|
+
this.throwError(e.message);
|
|
844
|
+
}
|
|
845
|
+
env.node = {
|
|
846
|
+
type: jsep.LITERAL,
|
|
847
|
+
value,
|
|
848
|
+
raw: this.expr.slice(patternIndex - 1, this.index)
|
|
849
|
+
};
|
|
850
|
+
env.node = this.gobbleTokenProperty(env.node);
|
|
851
|
+
return env.node;
|
|
852
|
+
}
|
|
853
|
+
if (this.code === jsep.OBRACK_CODE) inCharSet = true;
|
|
854
|
+
else if (inCharSet && this.code === jsep.CBRACK_CODE) inCharSet = false;
|
|
855
|
+
this.index += this.code === BSLASH_CODE ? 2 : 1;
|
|
856
|
+
}
|
|
857
|
+
this.throwError("Unclosed Regex");
|
|
858
|
+
}
|
|
859
|
+
});
|
|
860
|
+
}
|
|
861
|
+
};
|
|
862
|
+
const PLUS_CODE = 43;
|
|
863
|
+
const plugin = {
|
|
864
|
+
name: "assignment",
|
|
865
|
+
assignmentOperators: /* @__PURE__ */ new Set([
|
|
866
|
+
"=",
|
|
867
|
+
"*=",
|
|
868
|
+
"**=",
|
|
869
|
+
"/=",
|
|
870
|
+
"%=",
|
|
871
|
+
"+=",
|
|
872
|
+
"-=",
|
|
873
|
+
"<<=",
|
|
874
|
+
">>=",
|
|
875
|
+
">>>=",
|
|
876
|
+
"&=",
|
|
877
|
+
"^=",
|
|
878
|
+
"|=",
|
|
879
|
+
"||=",
|
|
880
|
+
"&&=",
|
|
881
|
+
"??="
|
|
882
|
+
]),
|
|
883
|
+
updateOperators: [PLUS_CODE, 45],
|
|
884
|
+
assignmentPrecedence: .9,
|
|
885
|
+
init(jsep) {
|
|
886
|
+
const updateNodeTypes = [jsep.IDENTIFIER, jsep.MEMBER_EXP];
|
|
887
|
+
plugin.assignmentOperators.forEach((op) => jsep.addBinaryOp(op, plugin.assignmentPrecedence, true));
|
|
888
|
+
jsep.hooks.add("gobble-token", function gobbleUpdatePrefix(env) {
|
|
889
|
+
const code = this.code;
|
|
890
|
+
if (plugin.updateOperators.some((c) => c === code && c === this.expr.charCodeAt(this.index + 1))) {
|
|
891
|
+
this.index += 2;
|
|
892
|
+
env.node = {
|
|
893
|
+
type: "UpdateExpression",
|
|
894
|
+
operator: code === PLUS_CODE ? "++" : "--",
|
|
895
|
+
argument: this.gobbleTokenProperty(this.gobbleIdentifier()),
|
|
896
|
+
prefix: true
|
|
897
|
+
};
|
|
898
|
+
if (!env.node.argument || !updateNodeTypes.includes(env.node.argument.type)) this.throwError(`Unexpected ${env.node.operator}`);
|
|
899
|
+
}
|
|
900
|
+
});
|
|
901
|
+
jsep.hooks.add("after-token", function gobbleUpdatePostfix(env) {
|
|
902
|
+
if (env.node) {
|
|
903
|
+
const code = this.code;
|
|
904
|
+
if (plugin.updateOperators.some((c) => c === code && c === this.expr.charCodeAt(this.index + 1))) {
|
|
905
|
+
if (!updateNodeTypes.includes(env.node.type)) this.throwError(`Unexpected ${env.node.operator}`);
|
|
906
|
+
this.index += 2;
|
|
907
|
+
env.node = {
|
|
908
|
+
type: "UpdateExpression",
|
|
909
|
+
operator: code === PLUS_CODE ? "++" : "--",
|
|
910
|
+
argument: env.node,
|
|
911
|
+
prefix: false
|
|
912
|
+
};
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
});
|
|
916
|
+
jsep.hooks.add("after-expression", function gobbleAssignment(env) {
|
|
917
|
+
if (env.node) updateBinariesToAssignments(env.node);
|
|
918
|
+
});
|
|
919
|
+
function updateBinariesToAssignments(node) {
|
|
920
|
+
if (plugin.assignmentOperators.has(node.operator)) {
|
|
921
|
+
node.type = "AssignmentExpression";
|
|
922
|
+
updateBinariesToAssignments(node.left);
|
|
923
|
+
updateBinariesToAssignments(node.right);
|
|
924
|
+
} else if (!node.operator) Object.values(node).forEach((val) => {
|
|
925
|
+
if (val && typeof val === "object") updateBinariesToAssignments(val);
|
|
926
|
+
});
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
};
|
|
930
|
+
/**
|
|
931
|
+
* @import {EvaluatedResult, UnknownResult} from './jsonpath.js';
|
|
932
|
+
*/
|
|
933
|
+
/**
|
|
934
|
+
* @typedef {any} AssignmentExpression
|
|
935
|
+
*/
|
|
936
|
+
/**
|
|
937
|
+
* @typedef {any} Substitution
|
|
938
|
+
*/
|
|
939
|
+
/**
|
|
940
|
+
* @typedef {any} AnyParameter
|
|
941
|
+
*/
|
|
942
|
+
/**
|
|
943
|
+
* @typedef {Record<string, Substitution>} Substitutions
|
|
944
|
+
*/
|
|
945
|
+
jsep.plugins.register(index, plugin);
|
|
946
|
+
jsep.addUnaryOp("typeof");
|
|
947
|
+
jsep.addUnaryOp("void");
|
|
948
|
+
jsep.addLiteral("null", null);
|
|
949
|
+
jsep.addLiteral("undefined", void 0);
|
|
950
|
+
const BLOCKED_PROTO_PROPERTIES = /* @__PURE__ */ new Set([
|
|
951
|
+
"constructor",
|
|
952
|
+
"__proto__",
|
|
953
|
+
"__defineGetter__",
|
|
954
|
+
"__defineSetter__",
|
|
955
|
+
"__lookupGetter__",
|
|
956
|
+
"__lookupSetter__"
|
|
957
|
+
]);
|
|
958
|
+
/** @type {WeakSet<object>} */
|
|
959
|
+
const BLOCKED_FUNCTIONS = new WeakSet([
|
|
960
|
+
Function,
|
|
961
|
+
function* () {}.constructor,
|
|
962
|
+
async function() {}.constructor,
|
|
963
|
+
async function* () {}.constructor,
|
|
964
|
+
Function.prototype.call,
|
|
965
|
+
Function.prototype.apply,
|
|
966
|
+
Function.prototype.bind,
|
|
967
|
+
Reflect.apply,
|
|
968
|
+
Reflect.construct,
|
|
969
|
+
...[...BLOCKED_PROTO_PROPERTIES].map((name) => Reflect.get(Object.prototype, name)).filter((value) => typeof value === "function")
|
|
970
|
+
]);
|
|
971
|
+
/**
|
|
972
|
+
* @param {UnknownResult} value
|
|
973
|
+
* @returns {boolean}
|
|
974
|
+
*/
|
|
975
|
+
const isBlockedFunction = (value) => {
|
|
976
|
+
return typeof value === "function" && BLOCKED_FUNCTIONS.has(value);
|
|
977
|
+
};
|
|
978
|
+
/**
|
|
979
|
+
* Guarded `obj[prop]`, applying the same restrictions as a MemberExpression.
|
|
980
|
+
* @param {UnknownResult} obj
|
|
981
|
+
* @param {string} prop
|
|
982
|
+
* @returns {UnknownResult}
|
|
983
|
+
*/
|
|
984
|
+
const getSafeProperty = (obj, prop) => {
|
|
985
|
+
if (obj === void 0 || obj === null) throw new TypeError(`Cannot read properties of ${obj} (reading '${prop}')`);
|
|
986
|
+
if (!Object.hasOwn(obj, prop) && BLOCKED_PROTO_PROPERTIES.has(prop)) throw new TypeError(`Cannot read properties of ${obj} (reading '${prop}')`);
|
|
987
|
+
const result = obj[prop];
|
|
988
|
+
if (isBlockedFunction(result)) throw new TypeError("Function constructor is disabled");
|
|
989
|
+
return result;
|
|
990
|
+
};
|
|
991
|
+
/**
|
|
992
|
+
* @typedef {Record<
|
|
993
|
+
* string,
|
|
994
|
+
* (a: AnyParameter, b: AnyParameter) => UnknownResult
|
|
995
|
+
* >} OperatorTable
|
|
996
|
+
*/
|
|
997
|
+
const BINOPS = Object.assign(
|
|
998
|
+
Object.create(null),
|
|
999
|
+
/** @type {OperatorTable} */
|
|
1000
|
+
{
|
|
1001
|
+
"||": (a, b) => a || b(),
|
|
1002
|
+
"&&": (a, b) => a && b(),
|
|
1003
|
+
"|": (a, b) => a | b(),
|
|
1004
|
+
"^": (a, b) => a ^ b(),
|
|
1005
|
+
"&": (a, b) => a & b(),
|
|
1006
|
+
"==": (a, b) => a == b(),
|
|
1007
|
+
"!=": (a, b) => a != b(),
|
|
1008
|
+
"===": (a, b) => a === b(),
|
|
1009
|
+
"!==": (a, b) => a !== b(),
|
|
1010
|
+
"<": (a, b) => a < b(),
|
|
1011
|
+
">": (a, b) => a > b(),
|
|
1012
|
+
"<=": (a, b) => a <= b(),
|
|
1013
|
+
">=": (a, b) => a >= b(),
|
|
1014
|
+
"<<": (a, b) => a << b(),
|
|
1015
|
+
">>": (a, b) => a >> b(),
|
|
1016
|
+
">>>": (a, b) => a >>> b(),
|
|
1017
|
+
"+": (a, b) => a + b(),
|
|
1018
|
+
"-": (a, b) => a - b(),
|
|
1019
|
+
"*": (a, b) => a * b(),
|
|
1020
|
+
"/": (a, b) => a / b(),
|
|
1021
|
+
"%": (a, b) => a % b()
|
|
1022
|
+
}
|
|
1023
|
+
);
|
|
1024
|
+
/**
|
|
1025
|
+
* @typedef {{
|
|
1026
|
+
* [key: string]: (a: AnyParameter) => UnknownResult
|
|
1027
|
+
* }} UnaryOperatorTable
|
|
1028
|
+
*/
|
|
1029
|
+
const UNOPS = Object.assign(
|
|
1030
|
+
Object.create(null),
|
|
1031
|
+
/** @type {UnaryOperatorTable} */
|
|
1032
|
+
{
|
|
1033
|
+
"-": (a) => -a,
|
|
1034
|
+
"!": (a) => !a,
|
|
1035
|
+
"~": (a) => ~a,
|
|
1036
|
+
"+": (a) => +a,
|
|
1037
|
+
typeof: (a) => typeof a,
|
|
1038
|
+
void: () => void 0
|
|
1039
|
+
}
|
|
1040
|
+
);
|
|
1041
|
+
const SafeEval = {
|
|
1042
|
+
/**
|
|
1043
|
+
* @param {jsep.Expression} ast
|
|
1044
|
+
* @param {Substitutions} subs
|
|
1045
|
+
* @returns {UnknownResult}
|
|
1046
|
+
*/
|
|
1047
|
+
evalAst(ast, subs) {
|
|
1048
|
+
switch (ast.type) {
|
|
1049
|
+
case "BinaryExpression":
|
|
1050
|
+
case "LogicalExpression": return SafeEval.evalBinaryExpression(
|
|
1051
|
+
/** @type {jsep.BinaryExpression} */
|
|
1052
|
+
ast,
|
|
1053
|
+
subs
|
|
1054
|
+
);
|
|
1055
|
+
case "Compound": return SafeEval.evalCompound(
|
|
1056
|
+
/** @type {jsep.Compound} */
|
|
1057
|
+
ast,
|
|
1058
|
+
subs
|
|
1059
|
+
);
|
|
1060
|
+
case "ConditionalExpression": return SafeEval.evalConditionalExpression(
|
|
1061
|
+
/** @type {jsep.ConditionalExpression} */
|
|
1062
|
+
ast,
|
|
1063
|
+
subs
|
|
1064
|
+
);
|
|
1065
|
+
case "Identifier": return SafeEval.evalIdentifier(
|
|
1066
|
+
/** @type {jsep.Identifier} */
|
|
1067
|
+
ast,
|
|
1068
|
+
subs
|
|
1069
|
+
);
|
|
1070
|
+
case "Literal": return SafeEval.evalLiteral(
|
|
1071
|
+
/** @type {jsep.Literal} */
|
|
1072
|
+
ast
|
|
1073
|
+
);
|
|
1074
|
+
case "MemberExpression": return SafeEval.evalMemberExpression(
|
|
1075
|
+
/** @type {jsep.MemberExpression} */
|
|
1076
|
+
ast,
|
|
1077
|
+
subs
|
|
1078
|
+
);
|
|
1079
|
+
case "UnaryExpression": return SafeEval.evalUnaryExpression(
|
|
1080
|
+
/** @type {jsep.UnaryExpression} */
|
|
1081
|
+
ast,
|
|
1082
|
+
subs
|
|
1083
|
+
);
|
|
1084
|
+
case "ArrayExpression": return SafeEval.evalArrayExpression(
|
|
1085
|
+
/** @type {jsep.ArrayExpression} */
|
|
1086
|
+
ast,
|
|
1087
|
+
subs
|
|
1088
|
+
);
|
|
1089
|
+
case "CallExpression": return SafeEval.evalCallExpression(
|
|
1090
|
+
/** @type {jsep.CallExpression} */
|
|
1091
|
+
ast,
|
|
1092
|
+
subs
|
|
1093
|
+
);
|
|
1094
|
+
case "AssignmentExpression": return SafeEval.evalAssignmentExpression(
|
|
1095
|
+
/** @type {AssignmentExpression} */
|
|
1096
|
+
ast,
|
|
1097
|
+
subs
|
|
1098
|
+
);
|
|
1099
|
+
default: throw new SyntaxError("Unexpected expression", { cause: ast });
|
|
1100
|
+
}
|
|
1101
|
+
},
|
|
1102
|
+
/**
|
|
1103
|
+
* @param {jsep.BinaryExpression} ast
|
|
1104
|
+
* @param {Substitutions} subs
|
|
1105
|
+
* @returns {UnknownResult}
|
|
1106
|
+
*/
|
|
1107
|
+
evalBinaryExpression(ast, subs) {
|
|
1108
|
+
/* c8 ignore next 3 -- Defensive guard for malformed ASTs */
|
|
1109
|
+
if (!Object.hasOwn(BINOPS, ast.operator)) throw new SyntaxError(`Unknown binary operator: ${ast.operator}`);
|
|
1110
|
+
return BINOPS[ast.operator](SafeEval.evalAst(ast.left, subs), () => SafeEval.evalAst(ast.right, subs));
|
|
1111
|
+
},
|
|
1112
|
+
/**
|
|
1113
|
+
* @param {jsep.Compound} ast
|
|
1114
|
+
* @param {Substitutions} subs
|
|
1115
|
+
* @returns {UnknownResult}
|
|
1116
|
+
*/
|
|
1117
|
+
evalCompound(ast, subs) {
|
|
1118
|
+
let last;
|
|
1119
|
+
for (let i = 0; i < ast.body.length; i++) {
|
|
1120
|
+
if (ast.body[i].type === "Identifier" && [
|
|
1121
|
+
"var",
|
|
1122
|
+
"let",
|
|
1123
|
+
"const"
|
|
1124
|
+
].includes(ast.body[i].name) && Object.hasOwn(ast.body, i + 1) && ast.body[i + 1].type === "AssignmentExpression") i += 1;
|
|
1125
|
+
const expr = ast.body[i];
|
|
1126
|
+
last = SafeEval.evalAst(expr, subs);
|
|
1127
|
+
}
|
|
1128
|
+
return last;
|
|
1129
|
+
},
|
|
1130
|
+
/**
|
|
1131
|
+
* @param {jsep.ConditionalExpression} ast
|
|
1132
|
+
* @param {Substitutions} subs
|
|
1133
|
+
* @returns {UnknownResult}
|
|
1134
|
+
*/
|
|
1135
|
+
evalConditionalExpression(ast, subs) {
|
|
1136
|
+
return SafeEval.evalAst(ast.test, subs) ? SafeEval.evalAst(ast.consequent, subs) : SafeEval.evalAst(ast.alternate, subs);
|
|
1137
|
+
},
|
|
1138
|
+
/**
|
|
1139
|
+
* @param {jsep.Identifier} ast
|
|
1140
|
+
* @param {Substitutions} subs
|
|
1141
|
+
* @returns {UnknownResult}
|
|
1142
|
+
*/
|
|
1143
|
+
evalIdentifier(ast, subs) {
|
|
1144
|
+
if (Object.hasOwn(subs, ast.name)) return subs[ast.name];
|
|
1145
|
+
throw new ReferenceError(`${ast.name} is not defined`);
|
|
1146
|
+
},
|
|
1147
|
+
/**
|
|
1148
|
+
* @param {jsep.Literal} ast
|
|
1149
|
+
* @returns {UnknownResult}
|
|
1150
|
+
*/
|
|
1151
|
+
evalLiteral(ast) {
|
|
1152
|
+
return ast.value;
|
|
1153
|
+
},
|
|
1154
|
+
/**
|
|
1155
|
+
* @param {jsep.MemberExpression} ast
|
|
1156
|
+
* @param {Substitutions} subs
|
|
1157
|
+
* @returns {UnknownResult}
|
|
1158
|
+
*/
|
|
1159
|
+
evalMemberExpression(ast, subs) {
|
|
1160
|
+
const prop = String(ast.computed ? SafeEval.evalAst(ast.property, subs) : ast.property.name);
|
|
1161
|
+
const obj = SafeEval.evalAst(ast.object, subs);
|
|
1162
|
+
const result = getSafeProperty(obj, prop);
|
|
1163
|
+
if (typeof result === "function") return result.bind(obj);
|
|
1164
|
+
return result;
|
|
1165
|
+
},
|
|
1166
|
+
/**
|
|
1167
|
+
* @param {jsep.UnaryExpression} ast
|
|
1168
|
+
* @param {Substitutions} subs
|
|
1169
|
+
* @returns {UnknownResult}
|
|
1170
|
+
*/
|
|
1171
|
+
evalUnaryExpression(ast, subs) {
|
|
1172
|
+
/* c8 ignore next 3 -- Defensive guard for malformed ASTs */
|
|
1173
|
+
if (!Object.hasOwn(UNOPS, ast.operator)) throw new SyntaxError(`Unknown unary operator: ${ast.operator}`);
|
|
1174
|
+
const operand = SafeEval.evalAst(ast.argument, subs);
|
|
1175
|
+
return UNOPS[ast.operator](operand);
|
|
1176
|
+
},
|
|
1177
|
+
/**
|
|
1178
|
+
* @param {jsep.ArrayExpression} ast
|
|
1179
|
+
* @param {Substitutions} subs
|
|
1180
|
+
* @returns {UnknownResult}
|
|
1181
|
+
*/
|
|
1182
|
+
evalArrayExpression(ast, subs) {
|
|
1183
|
+
return ast.elements.map((el) => SafeEval.evalAst(el, subs));
|
|
1184
|
+
},
|
|
1185
|
+
/**
|
|
1186
|
+
* @param {jsep.CallExpression} ast
|
|
1187
|
+
* @param {Substitutions} subs
|
|
1188
|
+
* @returns {UnknownResult}
|
|
1189
|
+
*/
|
|
1190
|
+
evalCallExpression(ast, subs) {
|
|
1191
|
+
const args = ast.arguments.map((arg) => SafeEval.evalAst(arg, subs));
|
|
1192
|
+
const func = SafeEval.evalAst(ast.callee, subs);
|
|
1193
|
+
if (isBlockedFunction(func) || args.some((arg) => isBlockedFunction(arg))) throw new Error("Function constructor is disabled");
|
|
1194
|
+
return func(...args);
|
|
1195
|
+
},
|
|
1196
|
+
/**
|
|
1197
|
+
* @param {AssignmentExpression} ast
|
|
1198
|
+
* @param {Substitutions} subs
|
|
1199
|
+
* @returns {UnknownResult}
|
|
1200
|
+
*/
|
|
1201
|
+
evalAssignmentExpression(ast, subs) {
|
|
1202
|
+
if (ast.left.type !== "Identifier") throw new SyntaxError("Invalid left-hand side in assignment");
|
|
1203
|
+
const id = ast.left.name;
|
|
1204
|
+
subs[id] = SafeEval.evalAst(ast.right, subs);
|
|
1205
|
+
return subs[id];
|
|
1206
|
+
}
|
|
1207
|
+
};
|
|
1208
|
+
/**
|
|
1209
|
+
* A replacement for NodeJS' VM.Script which is also {@link https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP | Content Security Policy} friendly.
|
|
1210
|
+
*/
|
|
1211
|
+
var SafeScript = class {
|
|
1212
|
+
/**
|
|
1213
|
+
* @param {string} expr Expression to evaluate
|
|
1214
|
+
*/
|
|
1215
|
+
constructor(expr) {
|
|
1216
|
+
this.code = expr;
|
|
1217
|
+
this.ast = jsep(this.code);
|
|
1218
|
+
}
|
|
1219
|
+
/**
|
|
1220
|
+
* @param {object} context Object whose items will be added
|
|
1221
|
+
* to evaluation
|
|
1222
|
+
* @returns {EvaluatedResult} Result of evaluated code
|
|
1223
|
+
*/
|
|
1224
|
+
runInNewContext(context) {
|
|
1225
|
+
const keyMap = Object.assign(Object.create(null), context);
|
|
1226
|
+
return SafeEval.evalAst(
|
|
1227
|
+
/** @type {jsep.Expression} */
|
|
1228
|
+
this.ast,
|
|
1229
|
+
keyMap
|
|
1230
|
+
);
|
|
1231
|
+
}
|
|
1232
|
+
};
|
|
1233
|
+
/**
|
|
1234
|
+
* @param {unknown} val
|
|
1235
|
+
*/
|
|
1236
|
+
const toStringTag = (val) => {
|
|
1237
|
+
return Object.prototype.toString.call(val).slice(8, -1);
|
|
1238
|
+
};
|
|
1239
|
+
const scriptCache = /* @__PURE__ */ new Map();
|
|
1240
|
+
const pathCache = /* @__PURE__ */ new Map();
|
|
1241
|
+
/**
|
|
1242
|
+
* @typedef {any} AnyInput
|
|
1243
|
+
*/
|
|
1244
|
+
/**
|
|
1245
|
+
* @typedef {((...args: any[]) => any)} SandboxCallback
|
|
1246
|
+
*/
|
|
1247
|
+
/**
|
|
1248
|
+
* @typedef {any|SandboxCallback} SandboxPropertyValue
|
|
1249
|
+
*/
|
|
1250
|
+
/**
|
|
1251
|
+
* @typedef {(string|number)[]} ExpressionArray
|
|
1252
|
+
*/
|
|
1253
|
+
/**
|
|
1254
|
+
* @typedef {"scalar"|"boolean"|"string"|"undefined"
|
|
1255
|
+
* |"function"|"integer"|"number"|"nonFinite"|"object"
|
|
1256
|
+
* |"array"|"other"|"null"|"symbol"|"Promise"|"BigInt"
|
|
1257
|
+
* |"jsonReference"} ValueType
|
|
1258
|
+
*/
|
|
1259
|
+
/**
|
|
1260
|
+
* @typedef {unknown} ParentValue
|
|
1261
|
+
*/
|
|
1262
|
+
/**
|
|
1263
|
+
* @typedef {unknown} UnknownResult
|
|
1264
|
+
*/
|
|
1265
|
+
/**
|
|
1266
|
+
* @typedef {string|number|null} ParentProperty
|
|
1267
|
+
*/
|
|
1268
|
+
/**
|
|
1269
|
+
* @typedef {ReturnObject|string|number|boolean|null|unknown[]
|
|
1270
|
+
* |Record<string, unknown>} PreferredOutput
|
|
1271
|
+
*/
|
|
1272
|
+
/**
|
|
1273
|
+
* Copies array and then pushes item into it.
|
|
1274
|
+
* @param {ExpressionArray} arr Array to copy and into which to push
|
|
1275
|
+
* @param {string|number} item Array item to add (to end)
|
|
1276
|
+
* @returns {ExpressionArray} Copy of the original array
|
|
1277
|
+
*/
|
|
1278
|
+
function push(arr, item) {
|
|
1279
|
+
arr = arr.slice();
|
|
1280
|
+
arr.push(item);
|
|
1281
|
+
return arr;
|
|
1282
|
+
}
|
|
1283
|
+
/**
|
|
1284
|
+
* Copies array and then unshifts item into it.
|
|
1285
|
+
* @param {string|number} item Array item to add (to beginning)
|
|
1286
|
+
* @param {ExpressionArray} arr Array to copy and into which to unshift
|
|
1287
|
+
* @returns {ExpressionArray} Copy of the original array
|
|
1288
|
+
*/
|
|
1289
|
+
function unshift(item, arr) {
|
|
1290
|
+
arr = arr.slice();
|
|
1291
|
+
arr.unshift(item);
|
|
1292
|
+
return arr;
|
|
1293
|
+
}
|
|
1294
|
+
/**
|
|
1295
|
+
* @typedef {object} ReturnObject
|
|
1296
|
+
* @property {ExpressionArray|string} path
|
|
1297
|
+
* @property {unknown} value
|
|
1298
|
+
* @property {ParentValue} parent
|
|
1299
|
+
* @property {ParentProperty} parentProperty
|
|
1300
|
+
* @property {boolean} [isParentSelector]
|
|
1301
|
+
* @property {boolean} [hasArrExpr]
|
|
1302
|
+
* @property {ExpressionArray} [expr]
|
|
1303
|
+
* @property {string} [pointer]
|
|
1304
|
+
*/
|
|
1305
|
+
/**
|
|
1306
|
+
* @callback JSONPathCallback
|
|
1307
|
+
* @param {any} preferredOutput Using `any` type instead of `PreferredOutput` so
|
|
1308
|
+
* that user can supply flexible type
|
|
1309
|
+
* @param {"value"|"property"} type
|
|
1310
|
+
* @param {ReturnObject} fullRetObj
|
|
1311
|
+
* @returns {void}
|
|
1312
|
+
*/
|
|
1313
|
+
/**
|
|
1314
|
+
* @callback OtherTypeCallback
|
|
1315
|
+
* @param {unknown} val
|
|
1316
|
+
* @param {ExpressionArray} path
|
|
1317
|
+
* @param {ParentValue} parent
|
|
1318
|
+
* @param {string|number|null} parentPropName
|
|
1319
|
+
* @param {string} arg
|
|
1320
|
+
* @returns {boolean|null}
|
|
1321
|
+
*/
|
|
1322
|
+
/**
|
|
1323
|
+
* @typedef {any} ContextItem
|
|
1324
|
+
*/
|
|
1325
|
+
/**
|
|
1326
|
+
* @typedef {any} EvaluatedResult
|
|
1327
|
+
*/
|
|
1328
|
+
/**
|
|
1329
|
+
* @callback EvalCallback
|
|
1330
|
+
* @param {string} code
|
|
1331
|
+
* @param {ContextItem} context
|
|
1332
|
+
* @returns {EvaluatedResult}
|
|
1333
|
+
*/
|
|
1334
|
+
/**
|
|
1335
|
+
* @typedef {new (expr: string) => {
|
|
1336
|
+
* runInNewContext: (context: object) => EvaluatedResult
|
|
1337
|
+
* }} ScriptConstructor
|
|
1338
|
+
*/
|
|
1339
|
+
/**
|
|
1340
|
+
* @typedef {ScriptConstructor} EvalClass
|
|
1341
|
+
*/
|
|
1342
|
+
/**
|
|
1343
|
+
* @typedef {"value"|"path"|"pointer"|"parent"|"parentProperty"
|
|
1344
|
+
* |"all"} ResultType
|
|
1345
|
+
*/
|
|
1346
|
+
/**
|
|
1347
|
+
* @typedef {EvalCallback|EvalClass|'safe'|'native'|boolean} EvalValue
|
|
1348
|
+
*/
|
|
1349
|
+
/**
|
|
1350
|
+
* @typedef {string|string[]} PathType
|
|
1351
|
+
*/
|
|
1352
|
+
/**
|
|
1353
|
+
* @typedef {{Script: ScriptConstructor}} SafeScriptType
|
|
1354
|
+
*/
|
|
1355
|
+
/**
|
|
1356
|
+
* @typedef {{Script: ScriptConstructor}} ScriptType
|
|
1357
|
+
*/
|
|
1358
|
+
/**
|
|
1359
|
+
* @typedef {{
|
|
1360
|
+
* _$_path?: string,
|
|
1361
|
+
* _$_parentProperty?: ParentProperty,
|
|
1362
|
+
* _$_parent?: ParentValue,
|
|
1363
|
+
* _$_property?: string|number,
|
|
1364
|
+
* _$_root?: AnyInput,
|
|
1365
|
+
* _$_v?: unknown,
|
|
1366
|
+
* [key: string]: SandboxPropertyValue
|
|
1367
|
+
* }} SandboxType
|
|
1368
|
+
*/
|
|
1369
|
+
/**
|
|
1370
|
+
* @typedef {object} JSONPathOptions
|
|
1371
|
+
* @property {AnyInput} [json]
|
|
1372
|
+
* @property {PathType} [path]
|
|
1373
|
+
* @property {ResultType} [resultType="value"]
|
|
1374
|
+
* @property {boolean} [flatten=false]
|
|
1375
|
+
* @property {boolean} [wrap=true]
|
|
1376
|
+
* @property {SandboxType} [sandbox={}]
|
|
1377
|
+
* @property {EvalValue} [eval='safe']
|
|
1378
|
+
* @property {any|null} [parent=null]
|
|
1379
|
+
* @property {ParentProperty} [parentProperty=null]
|
|
1380
|
+
* @property {JSONPathCallback} [callback]
|
|
1381
|
+
* @property {OtherTypeCallback} [otherTypeCallback] Defaults to
|
|
1382
|
+
* function which throws on encountering `@other`
|
|
1383
|
+
* @property {Record<string, OtherTypeCallback>} [customTypes] Map of
|
|
1384
|
+
* custom type operator names to their evaluation callbacks
|
|
1385
|
+
* @property {boolean} [autostart=true]
|
|
1386
|
+
* @property {boolean} [ignoreEvalErrors=false]
|
|
1387
|
+
*/
|
|
1388
|
+
/**
|
|
1389
|
+
* @overload
|
|
1390
|
+
* @param {string} opts JSON path to evaluate
|
|
1391
|
+
* @param {AnyInput} [expr] JSON object to evaluate against
|
|
1392
|
+
* @param {JSONPathCallback} [obj] Passed 3 arguments: 1) desired
|
|
1393
|
+
* payload per `resultType`, 2) `"value"|"property"`, 3) Full returned
|
|
1394
|
+
* object with all payloads
|
|
1395
|
+
* @param {OtherTypeCallback} [callback] If `@other()` is at the
|
|
1396
|
+
* end of one's query, this will be invoked with the value of the item,
|
|
1397
|
+
* its path, its parent, and its parent's property name, and it should
|
|
1398
|
+
* return a boolean indicating whether the supplied value belongs to the
|
|
1399
|
+
* "other" type or not (or it may handle transformations and return
|
|
1400
|
+
* `false`).
|
|
1401
|
+
* @param {undefined} [otherTypeCallback]
|
|
1402
|
+
* @returns {unknown} The string form always has `autostart` implicitly
|
|
1403
|
+
* `true`, so the result is the evaluated value, not a `JSONPathClass`
|
|
1404
|
+
*/
|
|
1405
|
+
/**
|
|
1406
|
+
* @overload
|
|
1407
|
+
* @param {JSONPathOptions & {autostart: false}} opts An options object
|
|
1408
|
+
* with `autostart` explicitly set to `false` defers evaluation and
|
|
1409
|
+
* returns the `JSONPathClass` instance instead
|
|
1410
|
+
* @returns {JSONPathClass}
|
|
1411
|
+
*/
|
|
1412
|
+
/**
|
|
1413
|
+
* @overload
|
|
1414
|
+
* @param {JSONPathOptions} opts If a string, will be treated as
|
|
1415
|
+
* `expr`
|
|
1416
|
+
* @returns {unknown}
|
|
1417
|
+
*/
|
|
1418
|
+
/**
|
|
1419
|
+
* @param {JSONPathOptions|string} opts If a string, will be treated as `expr`
|
|
1420
|
+
* @param {string|AnyInput} [expr] JSON path to evaluate
|
|
1421
|
+
* @param {AnyInput|JSONPathCallback} [obj] JSON object to evaluate against
|
|
1422
|
+
* @param {JSONPathCallback|OtherTypeCallback} [callback] Passed 3
|
|
1423
|
+
* arguments: 1) desired payload per `resultType`,
|
|
1424
|
+
* 2) `"value"|"property"`, 3) Full returned object with
|
|
1425
|
+
* all payloads
|
|
1426
|
+
* @param {OtherTypeCallback} [otherTypeCallback] If `@other()` is at the end
|
|
1427
|
+
* of one's query, this will be invoked with the value of the item, its
|
|
1428
|
+
* path, its parent, and its parent's property name, and it should return
|
|
1429
|
+
* a boolean indicating whether the supplied value belongs to the "other"
|
|
1430
|
+
* type or not (or it may handle transformations and return `false`).
|
|
1431
|
+
* @throws {Error}
|
|
1432
|
+
* @returns {unknown|JSONPathClass}
|
|
1433
|
+
*/
|
|
1434
|
+
function JSONPath(opts, expr, obj, callback, otherTypeCallback) {
|
|
1435
|
+
try {
|
|
1436
|
+
if (opts && typeof opts === "object") return new JSONPathClass(opts);
|
|
1437
|
+
return new JSONPathClass(
|
|
1438
|
+
opts,
|
|
1439
|
+
expr,
|
|
1440
|
+
/** @type {JSONPathCallback|undefined} */
|
|
1441
|
+
obj,
|
|
1442
|
+
/** @type {OtherTypeCallback|undefined} */
|
|
1443
|
+
callback,
|
|
1444
|
+
/** @type {undefined} */
|
|
1445
|
+
otherTypeCallback
|
|
1446
|
+
);
|
|
1447
|
+
} catch (e) {
|
|
1448
|
+
if (new.target) throw e;
|
|
1449
|
+
if (e && typeof e === "object" && "value" in e) return e.value;
|
|
1450
|
+
throw e;
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
/**
|
|
1454
|
+
*
|
|
1455
|
+
*/
|
|
1456
|
+
var JSONPathClass = class {
|
|
1457
|
+
/**
|
|
1458
|
+
* @overload
|
|
1459
|
+
* @param {string} opts JSON path to evaluate
|
|
1460
|
+
* @param {AnyInput} [expr] JSON object to evaluate against
|
|
1461
|
+
* @param {JSONPathCallback} [obj] Passed 3 arguments: 1) desired
|
|
1462
|
+
* payload per `resultType`, 2) `"value"|"property"`, 3) Full returned
|
|
1463
|
+
* object with all payloads
|
|
1464
|
+
* @param {OtherTypeCallback} [callback] If `@other()` is at the
|
|
1465
|
+
* end of one's query, this will be invoked with the value of the item,
|
|
1466
|
+
* its path, its parent, and its parent's property name, and it should
|
|
1467
|
+
* return a boolean indicating whether the supplied value belongs to the
|
|
1468
|
+
* "other" type or not (or it may handle transformations and return
|
|
1469
|
+
* `false`).
|
|
1470
|
+
* @param {undefined} [otherTypeCallback]
|
|
1471
|
+
*/
|
|
1472
|
+
/**
|
|
1473
|
+
* @overload
|
|
1474
|
+
* @param {JSONPathOptions} opts If a string, will be treated as
|
|
1475
|
+
* `expr`
|
|
1476
|
+
*/
|
|
1477
|
+
/**
|
|
1478
|
+
* @param {null|string|JSONPathOptions} opts If a string, will be treated as
|
|
1479
|
+
* `expr`
|
|
1480
|
+
* @param {string|AnyInput} [expr] JSON path to evaluate
|
|
1481
|
+
* @param {AnyInput|JSONPathCallback} [obj] JSON object to evaluate against
|
|
1482
|
+
* @param {JSONPathCallback|OtherTypeCallback} [callback] Passed 3
|
|
1483
|
+
* arguments: 1) desired payload per `resultType`,
|
|
1484
|
+
* 2) `"value"|"property"`, 3) Full returned
|
|
1485
|
+
* object with all payloads
|
|
1486
|
+
* @param {OtherTypeCallback} [otherTypeCallback] If `@other()` is at the
|
|
1487
|
+
* end of one's query, this will be invoked with the value of the item,
|
|
1488
|
+
* its path, its parent, and its parent's property name, and it should
|
|
1489
|
+
* return a boolean indicating whether the supplied value belongs to the
|
|
1490
|
+
* "other" type or not (or it may handle transformations and return
|
|
1491
|
+
* `false`).
|
|
1492
|
+
*/
|
|
1493
|
+
constructor(opts, expr, obj, callback, otherTypeCallback) {
|
|
1494
|
+
if (typeof opts === "string") {
|
|
1495
|
+
otherTypeCallback = callback;
|
|
1496
|
+
callback = obj;
|
|
1497
|
+
obj = expr;
|
|
1498
|
+
expr = opts;
|
|
1499
|
+
opts = null;
|
|
1500
|
+
}
|
|
1501
|
+
const optObj = opts && typeof opts === "object";
|
|
1502
|
+
opts ||= (/** @type {JSONPathOptions} */ {});
|
|
1503
|
+
/** @type {ResultType|undefined} */
|
|
1504
|
+
this.currResultType = void 0;
|
|
1505
|
+
/** @type {EvalValue|undefined} */
|
|
1506
|
+
this.currEval = void 0;
|
|
1507
|
+
/** @type {OtherTypeCallback|undefined} */
|
|
1508
|
+
this.currOtherTypeCallback = void 0;
|
|
1509
|
+
/** @type {Record<string, OtherTypeCallback>|undefined} */
|
|
1510
|
+
this.currCustomTypes = void 0;
|
|
1511
|
+
/** @type {SandboxType|undefined} */
|
|
1512
|
+
this.currSandbox = void 0;
|
|
1513
|
+
this._hasParentSelector = false;
|
|
1514
|
+
this.json = opts.json || obj;
|
|
1515
|
+
this.path = opts.path || expr;
|
|
1516
|
+
this.resultType = opts.resultType || "value";
|
|
1517
|
+
this.flatten = Object.hasOwn(opts, "flatten") && opts.flatten;
|
|
1518
|
+
this.wrap = !Object.hasOwn(opts, "wrap") || opts.wrap;
|
|
1519
|
+
this.sandbox = opts.sandbox || {};
|
|
1520
|
+
this.eval = opts.eval === void 0 ? "safe" : opts.eval;
|
|
1521
|
+
this.ignoreEvalErrors = typeof opts.ignoreEvalErrors !== "undefined" && opts.ignoreEvalErrors;
|
|
1522
|
+
this.parent = Object.hasOwn(opts, "parent") ? opts.parent : null;
|
|
1523
|
+
this.parentProperty = Object.hasOwn(opts, "parentProperty") ? opts.parentProperty : null;
|
|
1524
|
+
this.callback = opts.callback || callback || null;
|
|
1525
|
+
this.otherTypeCallback = opts.otherTypeCallback || otherTypeCallback || function() {
|
|
1526
|
+
throw new TypeError("You must supply an otherTypeCallback callback option with the @other() operator.");
|
|
1527
|
+
};
|
|
1528
|
+
this.customTypes = opts.customTypes || {};
|
|
1529
|
+
if (opts.autostart === false) return;
|
|
1530
|
+
const args = (/** @type {JSONPathOptions} */ { path: optObj ? opts.path : expr });
|
|
1531
|
+
if (!optObj && obj !== void 0) args.json = obj;
|
|
1532
|
+
else if ("json" in opts) args.json = opts.json;
|
|
1533
|
+
const ret = this.evaluate(args);
|
|
1534
|
+
if (!ret || typeof ret !== "object") {
|
|
1535
|
+
const err = /* @__PURE__ */ new Error("JSONPath should not be called with \"new\" (it prevents return of (unwrapped) scalar values)");
|
|
1536
|
+
err.value = ret;
|
|
1537
|
+
throw err;
|
|
1538
|
+
}
|
|
1539
|
+
return ret;
|
|
1540
|
+
}
|
|
1541
|
+
/**
|
|
1542
|
+
* @overload
|
|
1543
|
+
* @param {JSONPathOptions} [expr]
|
|
1544
|
+
* @returns {ReturnObject|ReturnObject[]|undefined|unknown}
|
|
1545
|
+
*/
|
|
1546
|
+
/**
|
|
1547
|
+
* @overload
|
|
1548
|
+
* @param {PathType|undefined} [expr]
|
|
1549
|
+
* @param {AnyInput} [json]
|
|
1550
|
+
* @param {JSONPathCallback|null} [callback]
|
|
1551
|
+
* @param {OtherTypeCallback} [otherTypeCallback]
|
|
1552
|
+
* @returns {ReturnObject|ReturnObject[]|undefined|unknown}
|
|
1553
|
+
*/
|
|
1554
|
+
/**
|
|
1555
|
+
* @param {PathType|JSONPathOptions|undefined} [expr]
|
|
1556
|
+
* @param {AnyInput} [json]
|
|
1557
|
+
* @param {JSONPathCallback|null} [callback]
|
|
1558
|
+
* @param {OtherTypeCallback} [otherTypeCallback]
|
|
1559
|
+
* @returns {ReturnObject|ReturnObject[]|undefined|unknown}
|
|
1560
|
+
*/
|
|
1561
|
+
evaluate(expr, json, callback, otherTypeCallback) {
|
|
1562
|
+
let currParent = this.parent, currParentProperty = this.parentProperty;
|
|
1563
|
+
let { flatten, wrap } = this;
|
|
1564
|
+
this.currResultType = this.resultType;
|
|
1565
|
+
this.currEval = this.eval;
|
|
1566
|
+
this.currSandbox = this.sandbox;
|
|
1567
|
+
callback ||= this.callback;
|
|
1568
|
+
this.currOtherTypeCallback = otherTypeCallback || this.otherTypeCallback;
|
|
1569
|
+
this.currCustomTypes = this.customTypes;
|
|
1570
|
+
if (expr && typeof expr === "object" && !Array.isArray(expr)) {
|
|
1571
|
+
const exprObj = expr;
|
|
1572
|
+
if (!exprObj.path && exprObj.path !== "") throw new TypeError("You must supply a \"path\" property when providing an object argument to JSONPath.evaluate().");
|
|
1573
|
+
if (!Object.hasOwn(exprObj, "json")) throw new TypeError("You must supply a \"json\" property when providing an object argument to JSONPath.evaluate().");
|
|
1574
|
+
({json} = exprObj);
|
|
1575
|
+
flatten = Object.hasOwn(exprObj, "flatten") ? exprObj.flatten : flatten;
|
|
1576
|
+
this.currResultType = Object.hasOwn(exprObj, "resultType") ? exprObj.resultType : this.currResultType;
|
|
1577
|
+
this.currSandbox = Object.hasOwn(exprObj, "sandbox") ? exprObj.sandbox : this.currSandbox;
|
|
1578
|
+
wrap = Object.hasOwn(exprObj, "wrap") ? exprObj.wrap : wrap;
|
|
1579
|
+
this.currEval = Object.hasOwn(exprObj, "eval") ? exprObj.eval : this.currEval;
|
|
1580
|
+
callback = Object.hasOwn(exprObj, "callback") ? exprObj.callback : callback;
|
|
1581
|
+
this.currOtherTypeCallback = Object.hasOwn(exprObj, "otherTypeCallback") ? exprObj.otherTypeCallback : this.currOtherTypeCallback;
|
|
1582
|
+
this.currCustomTypes = Object.hasOwn(exprObj, "customTypes") ? exprObj.customTypes : this.currCustomTypes;
|
|
1583
|
+
currParent = Object.hasOwn(exprObj, "parent") ? exprObj.parent : currParent;
|
|
1584
|
+
currParentProperty = Object.hasOwn(exprObj, "parentProperty") ? exprObj.parentProperty : currParentProperty;
|
|
1585
|
+
expr = exprObj.path;
|
|
1586
|
+
} else {
|
|
1587
|
+
json ||= this.json;
|
|
1588
|
+
expr ||= this.path;
|
|
1589
|
+
}
|
|
1590
|
+
currParent ||= null;
|
|
1591
|
+
currParentProperty ||= null;
|
|
1592
|
+
if (Array.isArray(expr)) expr = JSONPath.toPathString(expr);
|
|
1593
|
+
if (!json || !expr && expr !== "") return;
|
|
1594
|
+
const exprList = JSONPath.toPathArray(expr);
|
|
1595
|
+
if (exprList[0] === "$" && exprList.length > 1) exprList.shift();
|
|
1596
|
+
this._hasParentSelector = false;
|
|
1597
|
+
const traceResult = this._trace(exprList, json, ["$"], currParent, currParentProperty, callback ?? void 0, void 0);
|
|
1598
|
+
/* c8 ignore next 2 -- Unreachable: _trace returns array when hasArrExpr set */
|
|
1599
|
+
const result = (Array.isArray(traceResult) ? traceResult : [traceResult]).filter((ea) => {
|
|
1600
|
+
return ea && !ea.isParentSelector;
|
|
1601
|
+
});
|
|
1602
|
+
if (!result.length)
|
|
1603
|
+
/* c8 ignore next -- Unreachable: valid queries always produce results */
|
|
1604
|
+
return wrap ? [] : void 0;
|
|
1605
|
+
if (!wrap && result.length === 1 && !result[0].hasArrExpr) return this._getPreferredOutput(result[0]);
|
|
1606
|
+
return result.reduce((rslt, ea) => {
|
|
1607
|
+
const valOrPath = this._getPreferredOutput(ea);
|
|
1608
|
+
if (flatten && Array.isArray(valOrPath)) rslt = rslt.concat(valOrPath);
|
|
1609
|
+
else rslt.push(valOrPath);
|
|
1610
|
+
return rslt;
|
|
1611
|
+
}, []);
|
|
1612
|
+
}
|
|
1613
|
+
/**
|
|
1614
|
+
* @param {ReturnObject} ea
|
|
1615
|
+
* @returns {PreferredOutput}
|
|
1616
|
+
*/
|
|
1617
|
+
_getPreferredOutput(ea) {
|
|
1618
|
+
const resultType = this.currResultType;
|
|
1619
|
+
switch (resultType) {
|
|
1620
|
+
case "all": {
|
|
1621
|
+
const path = Array.isArray(ea.path) ? ea.path : JSONPath.toPathArray(ea.path);
|
|
1622
|
+
ea.pointer = JSONPath.toPointer(
|
|
1623
|
+
/** @type {string[]} */
|
|
1624
|
+
path
|
|
1625
|
+
);
|
|
1626
|
+
ea.path = typeof ea.path === "string" ? ea.path : JSONPath.toPathString(
|
|
1627
|
+
/** @type {string[]} */
|
|
1628
|
+
ea.path
|
|
1629
|
+
);
|
|
1630
|
+
return ea;
|
|
1631
|
+
}
|
|
1632
|
+
case "value":
|
|
1633
|
+
case "parent":
|
|
1634
|
+
case "parentProperty": return ea[resultType];
|
|
1635
|
+
case "path":
|
|
1636
|
+
if (typeof ea.path === "string") return ea.path;
|
|
1637
|
+
return JSONPath.toPathString(
|
|
1638
|
+
/** @type {string[]} */
|
|
1639
|
+
ea.path
|
|
1640
|
+
);
|
|
1641
|
+
case "pointer": {
|
|
1642
|
+
const pathArray = Array.isArray(ea.path) ? ea.path : JSONPath.toPathArray(ea.path);
|
|
1643
|
+
return JSONPath.toPointer(
|
|
1644
|
+
/** @type {string[]} */
|
|
1645
|
+
pathArray
|
|
1646
|
+
);
|
|
1647
|
+
}
|
|
1648
|
+
default: throw new TypeError("Unknown result type");
|
|
1649
|
+
}
|
|
1650
|
+
}
|
|
1651
|
+
/**
|
|
1652
|
+
* @param {ReturnObject} fullRetObj
|
|
1653
|
+
* @param {JSONPathCallback|undefined} callback
|
|
1654
|
+
* @param {"value"|"property"} type
|
|
1655
|
+
* @returns {void}
|
|
1656
|
+
*/
|
|
1657
|
+
_handleCallback(fullRetObj, callback, type) {
|
|
1658
|
+
if (!callback) return;
|
|
1659
|
+
const preferredOutput = this._getPreferredOutput(fullRetObj);
|
|
1660
|
+
if (Array.isArray(fullRetObj.path)) fullRetObj.path = JSONPath.toPathString(
|
|
1661
|
+
/** @type {string[]} */
|
|
1662
|
+
fullRetObj.path
|
|
1663
|
+
);
|
|
1664
|
+
callback(preferredOutput, type, fullRetObj);
|
|
1665
|
+
}
|
|
1666
|
+
/**
|
|
1667
|
+
*
|
|
1668
|
+
* @param {ExpressionArray} expr
|
|
1669
|
+
* @param {unknown} val
|
|
1670
|
+
* @param {ExpressionArray} path
|
|
1671
|
+
* @param {ParentValue} parent
|
|
1672
|
+
* @param {ParentProperty} parentPropName
|
|
1673
|
+
* @param {JSONPathCallback|undefined} callback
|
|
1674
|
+
* @param {boolean|undefined} hasArrExpr
|
|
1675
|
+
* @param {boolean} [literalPriority]
|
|
1676
|
+
* @returns {ReturnObject|ReturnObject[]}
|
|
1677
|
+
*/
|
|
1678
|
+
_trace(expr, val, path, parent, parentPropName, callback, hasArrExpr, literalPriority) {
|
|
1679
|
+
let retObj;
|
|
1680
|
+
if (!expr.length) {
|
|
1681
|
+
retObj = {
|
|
1682
|
+
path,
|
|
1683
|
+
value: val,
|
|
1684
|
+
parent,
|
|
1685
|
+
parentProperty: parentPropName,
|
|
1686
|
+
hasArrExpr
|
|
1687
|
+
};
|
|
1688
|
+
this._handleCallback(retObj, callback, "value");
|
|
1689
|
+
return retObj;
|
|
1690
|
+
}
|
|
1691
|
+
const loc = expr[0], x = expr.slice(1);
|
|
1692
|
+
/** @type {ReturnObject[]} */
|
|
1693
|
+
const ret = [];
|
|
1694
|
+
/**
|
|
1695
|
+
*
|
|
1696
|
+
* @param {ReturnObject|ReturnObject[]} elems
|
|
1697
|
+
* @returns {void}
|
|
1698
|
+
*/
|
|
1699
|
+
function addRet(elems) {
|
|
1700
|
+
if (Array.isArray(elems)) elems.forEach((t) => {
|
|
1701
|
+
ret.push(t);
|
|
1702
|
+
});
|
|
1703
|
+
else ret.push(elems);
|
|
1704
|
+
}
|
|
1705
|
+
if (val && (typeof loc !== "string" || literalPriority) && Object.hasOwn(
|
|
1706
|
+
val,
|
|
1707
|
+
/** @type {PropertyKey} */
|
|
1708
|
+
loc
|
|
1709
|
+
)) {
|
|
1710
|
+
const valObj = val;
|
|
1711
|
+
addRet(this._trace(
|
|
1712
|
+
x,
|
|
1713
|
+
valObj[loc],
|
|
1714
|
+
push(path, loc),
|
|
1715
|
+
val,
|
|
1716
|
+
/** @type {string|number} */
|
|
1717
|
+
loc,
|
|
1718
|
+
callback,
|
|
1719
|
+
hasArrExpr
|
|
1720
|
+
));
|
|
1721
|
+
} else if (loc === "*") this._walk(val, (m) => {
|
|
1722
|
+
const valObj = val;
|
|
1723
|
+
addRet(this._trace(x, valObj[m], push(path, m), val, m, callback, true, true));
|
|
1724
|
+
});
|
|
1725
|
+
else if (loc === "..") {
|
|
1726
|
+
addRet(this._trace(x, val, path, parent, parentPropName, callback, hasArrExpr));
|
|
1727
|
+
this._walk(val, (m) => {
|
|
1728
|
+
const valObj = val;
|
|
1729
|
+
if (typeof valObj[m] === "object") addRet(this._trace(expr.slice(), valObj[m], push(path, m), val, m, callback, true));
|
|
1730
|
+
});
|
|
1731
|
+
} else if (loc === "^") {
|
|
1732
|
+
this._hasParentSelector = true;
|
|
1733
|
+
return (/** @type {ReturnObject} */ {
|
|
1734
|
+
path: path.slice(0, -1),
|
|
1735
|
+
expr: x,
|
|
1736
|
+
isParentSelector: true,
|
|
1737
|
+
value: void 0,
|
|
1738
|
+
parent: void 0,
|
|
1739
|
+
parentProperty: null
|
|
1740
|
+
});
|
|
1741
|
+
} else if (loc === "~") {
|
|
1742
|
+
retObj = {
|
|
1743
|
+
path: push(path, loc),
|
|
1744
|
+
value: parentPropName,
|
|
1745
|
+
parent,
|
|
1746
|
+
parentProperty: null
|
|
1747
|
+
};
|
|
1748
|
+
this._handleCallback(retObj, callback, "property");
|
|
1749
|
+
return retObj;
|
|
1750
|
+
} else if (loc === "$") addRet(this._trace(x, val, path, null, null, callback, hasArrExpr));
|
|
1751
|
+
else if (/^(-?\d*):(-?\d*):?(\d*)$/v.test(loc)) {
|
|
1752
|
+
const sliceResult = this._slice(loc, x, val, path, parent, parentPropName, callback);
|
|
1753
|
+
if (sliceResult) addRet(sliceResult);
|
|
1754
|
+
} else if (loc.indexOf("?(") === 0) {
|
|
1755
|
+
if (this.currEval === false) throw new Error("Eval [?(expr)] prevented in JSONPath expression.");
|
|
1756
|
+
const safeLoc = loc.replace(/^\?\((.*?)\)$/v, "$1");
|
|
1757
|
+
const nested = /@.?([^?]*)[\['](\??\(.*?\))(?!.\)\])[\]']/gv.exec(safeLoc);
|
|
1758
|
+
if (nested) this._walk(val, (m) => {
|
|
1759
|
+
const npath = [nested[2]];
|
|
1760
|
+
const valObj2 = val;
|
|
1761
|
+
const nvalue = nested[1] ? getSafeProperty(valObj2[m], nested[1]) : valObj2[m];
|
|
1762
|
+
const filterResults = this._trace(npath, nvalue, path, parent, parentPropName, callback, true);
|
|
1763
|
+
if ((Array.isArray(filterResults) ? filterResults : [filterResults]).length > 0) addRet(this._trace(x, valObj2[m], push(path, m), val, m, callback, true));
|
|
1764
|
+
});
|
|
1765
|
+
else {
|
|
1766
|
+
const valObj3 = val;
|
|
1767
|
+
this._walk(val, (m) => {
|
|
1768
|
+
if (this._eval(safeLoc, valObj3[m], m, path, parent, parentPropName)) addRet(this._trace(x, valObj3[m], push(path, m), val, m, callback, true));
|
|
1769
|
+
});
|
|
1770
|
+
}
|
|
1771
|
+
} else if (loc[0] === "(") {
|
|
1772
|
+
if (this.currEval === false) throw new Error("Eval [(expr)] prevented in JSONPath expression.");
|
|
1773
|
+
const evalResult = this._eval(
|
|
1774
|
+
/** @type {string} */
|
|
1775
|
+
loc,
|
|
1776
|
+
val,
|
|
1777
|
+
/** @type {string|number} */
|
|
1778
|
+
path.at(-1),
|
|
1779
|
+
path.slice(0, -1),
|
|
1780
|
+
parent,
|
|
1781
|
+
parentPropName
|
|
1782
|
+
);
|
|
1783
|
+
const exprToUse = evalResult !== void 0 ? evalResult : "";
|
|
1784
|
+
addRet(this._trace(unshift(exprToUse, x), val, path, parent, parentPropName, callback, hasArrExpr));
|
|
1785
|
+
} else if (loc[0] === "@") {
|
|
1786
|
+
let addType = false;
|
|
1787
|
+
const parenthIndex = loc.indexOf("(");
|
|
1788
|
+
const valueType = loc.slice(1, parenthIndex);
|
|
1789
|
+
const lastParenth = loc.lastIndexOf(")");
|
|
1790
|
+
const argRaw = loc.slice(parenthIndex + 1, lastParenth);
|
|
1791
|
+
const arg = argRaw ? JSON.parse(argRaw) : void 0;
|
|
1792
|
+
switch (valueType) {
|
|
1793
|
+
case "scalar":
|
|
1794
|
+
addType = !val || !["object", "function"].includes(typeof val);
|
|
1795
|
+
break;
|
|
1796
|
+
case "boolean":
|
|
1797
|
+
case "string":
|
|
1798
|
+
case "undefined":
|
|
1799
|
+
case "function":
|
|
1800
|
+
addType = typeof val === valueType;
|
|
1801
|
+
break;
|
|
1802
|
+
case "integer":
|
|
1803
|
+
addType = Number.isFinite(val) && !(val % 1);
|
|
1804
|
+
break;
|
|
1805
|
+
case "number":
|
|
1806
|
+
addType = Number.isFinite(val);
|
|
1807
|
+
break;
|
|
1808
|
+
case "nonFinite":
|
|
1809
|
+
addType = typeof val === "number" && !Number.isFinite(val);
|
|
1810
|
+
break;
|
|
1811
|
+
case "object":
|
|
1812
|
+
addType = Boolean(val) && typeof val === valueType;
|
|
1813
|
+
break;
|
|
1814
|
+
case "array":
|
|
1815
|
+
addType = Array.isArray(val);
|
|
1816
|
+
break;
|
|
1817
|
+
case "other":
|
|
1818
|
+
addType = this.currOtherTypeCallback(val, path, parent, parentPropName, arg) || false;
|
|
1819
|
+
break;
|
|
1820
|
+
case "null":
|
|
1821
|
+
addType = val === null;
|
|
1822
|
+
break;
|
|
1823
|
+
case "symbol":
|
|
1824
|
+
addType = typeof val === "symbol";
|
|
1825
|
+
break;
|
|
1826
|
+
case "BigInt":
|
|
1827
|
+
addType = typeof val === "bigint";
|
|
1828
|
+
break;
|
|
1829
|
+
case "Promise":
|
|
1830
|
+
addType = toStringTag(val) === "Promise";
|
|
1831
|
+
break;
|
|
1832
|
+
case "jsonReference":
|
|
1833
|
+
addType = Boolean(val) && typeof val === "object" && Object.hasOwn(
|
|
1834
|
+
/** @type {object} */
|
|
1835
|
+
val,
|
|
1836
|
+
"$ref"
|
|
1837
|
+
);
|
|
1838
|
+
break;
|
|
1839
|
+
default: if (this.currCustomTypes && Object.hasOwn(this.currCustomTypes, valueType)) addType = this.currCustomTypes[valueType](val, path, parent, parentPropName, arg) || false;
|
|
1840
|
+
else throw new TypeError("Unknown value type " + valueType);
|
|
1841
|
+
}
|
|
1842
|
+
if (addType) {
|
|
1843
|
+
retObj = {
|
|
1844
|
+
path,
|
|
1845
|
+
value: val,
|
|
1846
|
+
parent,
|
|
1847
|
+
parentProperty: parentPropName
|
|
1848
|
+
};
|
|
1849
|
+
this._handleCallback(retObj, callback, "value");
|
|
1850
|
+
return retObj;
|
|
1851
|
+
}
|
|
1852
|
+
} else if (val && loc[0] === "`" && Object.hasOwn(val, loc.slice(1))) {
|
|
1853
|
+
const locProp = loc.slice(1);
|
|
1854
|
+
const valObj = val;
|
|
1855
|
+
addRet(this._trace(x, valObj[locProp], push(path, locProp), val, locProp, callback, hasArrExpr, true));
|
|
1856
|
+
} else if (loc[0] === "'" || loc[0] === "\"") for (const [, single, double] of loc.matchAll(/'((?:\\.|[^'\\])*)'|"((?:\\.|[^"\\])*)"/gv)) {
|
|
1857
|
+
const prop = (single ?? double).replaceAll(/\\(['"\\])/gv, "$1");
|
|
1858
|
+
if (!val || !Object.hasOwn(val, prop)) continue;
|
|
1859
|
+
const valObj = val;
|
|
1860
|
+
addRet(this._trace(x, valObj[prop], push(path, prop), val, prop, callback, true));
|
|
1861
|
+
}
|
|
1862
|
+
else if (loc.includes(",")) {
|
|
1863
|
+
const parts = loc.split(",");
|
|
1864
|
+
for (const part of parts) addRet(this._trace(unshift(part, x), val, path, parent, parentPropName, callback, true));
|
|
1865
|
+
} else if (!literalPriority && val && Object.hasOwn(val, loc)) {
|
|
1866
|
+
const valObj = val;
|
|
1867
|
+
addRet(this._trace(x, valObj[loc], push(path, loc), val, loc, callback, hasArrExpr, true));
|
|
1868
|
+
}
|
|
1869
|
+
if (this._hasParentSelector) for (let t = 0; t < ret.length; t++) {
|
|
1870
|
+
const rett = ret[t];
|
|
1871
|
+
if (!rett || !rett.isParentSelector) continue;
|
|
1872
|
+
const exprToUse = rett.expr;
|
|
1873
|
+
const pathToUse = rett.path;
|
|
1874
|
+
const tmp = this._trace(exprToUse, val, pathToUse, parent, parentPropName, callback, hasArrExpr);
|
|
1875
|
+
if (Array.isArray(tmp)) {
|
|
1876
|
+
ret[t] = tmp[0];
|
|
1877
|
+
const tl = tmp.length;
|
|
1878
|
+
for (let tt = 1; tt < tl; tt++) {
|
|
1879
|
+
t++;
|
|
1880
|
+
ret.splice(t, 0, tmp[tt]);
|
|
1881
|
+
}
|
|
1882
|
+
} else ret[t] = tmp;
|
|
1883
|
+
}
|
|
1884
|
+
return ret;
|
|
1885
|
+
}
|
|
1886
|
+
/**
|
|
1887
|
+
* @param {unknown} val
|
|
1888
|
+
* @param {(prop: string|number) => void} f
|
|
1889
|
+
* @returns {void}
|
|
1890
|
+
*/
|
|
1891
|
+
_walk(val, f) {
|
|
1892
|
+
if (Array.isArray(val)) {
|
|
1893
|
+
const n = val.length;
|
|
1894
|
+
for (let i = 0; i < n; i++) f(i);
|
|
1895
|
+
} else if (val && typeof val === "object") Object.keys(val).forEach((m) => {
|
|
1896
|
+
f(m);
|
|
1897
|
+
});
|
|
1898
|
+
}
|
|
1899
|
+
/**
|
|
1900
|
+
* @param {string} loc
|
|
1901
|
+
* @param {ExpressionArray} expr
|
|
1902
|
+
* @param {unknown} val
|
|
1903
|
+
* @param {ExpressionArray} path
|
|
1904
|
+
* @param {ParentValue} parent
|
|
1905
|
+
* @param {ParentProperty} parentPropName
|
|
1906
|
+
* @param {JSONPathCallback|undefined} callback
|
|
1907
|
+
* @returns {ReturnObject[]|undefined}
|
|
1908
|
+
*/
|
|
1909
|
+
_slice(loc, expr, val, path, parent, parentPropName, callback) {
|
|
1910
|
+
if (!Array.isArray(val)) return;
|
|
1911
|
+
const len = val.length, parts = loc.split(":"), step = parts[2] && Number(parts[2]) || 1;
|
|
1912
|
+
let start = parts[0] && Number(parts[0]) || 0, end = parts[1] ? Number(parts[1]) : len;
|
|
1913
|
+
start = start < 0 ? Math.max(0, start + len) : Math.min(len, start);
|
|
1914
|
+
end = end < 0 ? Math.max(0, end + len) : Math.min(len, end);
|
|
1915
|
+
/** @type {ReturnObject[]} */
|
|
1916
|
+
const ret = [];
|
|
1917
|
+
for (let i = start; i < end; i += step) {
|
|
1918
|
+
const tmp = this._trace(unshift(i, expr), val, path, parent, parentPropName, callback, true);
|
|
1919
|
+
(Array.isArray(tmp) ? tmp : [tmp]).forEach((t) => {
|
|
1920
|
+
ret.push(t);
|
|
1921
|
+
});
|
|
1922
|
+
}
|
|
1923
|
+
return ret;
|
|
1924
|
+
}
|
|
1925
|
+
/**
|
|
1926
|
+
* @param {string} code
|
|
1927
|
+
* @param {unknown} _v
|
|
1928
|
+
* @param {string|number} _vname
|
|
1929
|
+
* @param {ExpressionArray} path
|
|
1930
|
+
* @param {ParentValue} parent
|
|
1931
|
+
* @param {ParentProperty} parentPropName
|
|
1932
|
+
* @returns {UnknownResult}
|
|
1933
|
+
*/
|
|
1934
|
+
_eval(code, _v, _vname, path, parent, parentPropName) {
|
|
1935
|
+
if (this.currSandbox) {
|
|
1936
|
+
this.currSandbox._$_parentProperty = parentPropName;
|
|
1937
|
+
this.currSandbox._$_parent = parent;
|
|
1938
|
+
this.currSandbox._$_property = _vname;
|
|
1939
|
+
this.currSandbox._$_root = this.json;
|
|
1940
|
+
this.currSandbox._$_v = _v;
|
|
1941
|
+
}
|
|
1942
|
+
const containsPath = code.includes("@path");
|
|
1943
|
+
if (containsPath) {
|
|
1944
|
+
/* c8 ignore next -- Unreachable: currSandbox set in evaluate() before _eval */
|
|
1945
|
+
const currSandbox = this.currSandbox ?? {};
|
|
1946
|
+
currSandbox._$_path = JSONPath.toPathString(
|
|
1947
|
+
/** @type {string[]} */
|
|
1948
|
+
path.concat([_vname])
|
|
1949
|
+
);
|
|
1950
|
+
}
|
|
1951
|
+
const scriptCacheKey = this.currEval + "Script:" + code;
|
|
1952
|
+
if (!scriptCache.has(scriptCacheKey)) {
|
|
1953
|
+
let script = code.replaceAll("@parentProperty", "_$_parentProperty").replaceAll("@parent", "_$_parent").replaceAll("@property", "_$_property").replaceAll("@root", "_$_root").replaceAll(/('(?:\\.|[^'\\])*'|"(?:\\.|[^"\\])*"|(?<=(?:^|[\(,=:\[!\|?\{\};+\-*%<>~^]|&)\s*)\/(?:\\.|\[(?:\\.|[^\]\\])*\]|[^\/\\\[])+\/[dgimsuvy]*)|@(?![\w$])/gv, (_, literal) => literal ?? "_$_v");
|
|
1954
|
+
if (containsPath) script = script.replaceAll("@path", "_$_path");
|
|
1955
|
+
const evalType = this.currEval;
|
|
1956
|
+
if ([
|
|
1957
|
+
"safe",
|
|
1958
|
+
true,
|
|
1959
|
+
void 0
|
|
1960
|
+
].includes(evalType)) scriptCache.set(scriptCacheKey, new this.safeVm.Script(script));
|
|
1961
|
+
else if (this.currEval === "native") scriptCache.set(scriptCacheKey, new this.vm.Script(script));
|
|
1962
|
+
else if (typeof this.currEval === "function" && this.currEval.prototype && Object.hasOwn(this.currEval.prototype, "runInNewContext")) {
|
|
1963
|
+
const CurrEval = this.currEval;
|
|
1964
|
+
scriptCache.set(scriptCacheKey, new CurrEval(script));
|
|
1965
|
+
} else if (typeof this.currEval === "function") {
|
|
1966
|
+
const evalFunc = this.currEval;
|
|
1967
|
+
scriptCache.set(scriptCacheKey, { runInNewContext: (context) => evalFunc(script, context) });
|
|
1968
|
+
} else throw new TypeError(`Unknown "eval" property "${this.currEval}"`);
|
|
1969
|
+
}
|
|
1970
|
+
try {
|
|
1971
|
+
/**
|
|
1972
|
+
* @typedef {{
|
|
1973
|
+
* runInNewContext: (
|
|
1974
|
+
* ctx: SandboxType|undefined
|
|
1975
|
+
* ) => EvaluatedResult
|
|
1976
|
+
* }} RunInNewContext
|
|
1977
|
+
*/
|
|
1978
|
+
return scriptCache.get(scriptCacheKey).runInNewContext(this.currSandbox);
|
|
1979
|
+
} catch (e) {
|
|
1980
|
+
if (this.ignoreEvalErrors) return false;
|
|
1981
|
+
throw new Error("jsonPath: " + e.message + ": " + code, { cause: e });
|
|
1982
|
+
}
|
|
1983
|
+
}
|
|
1984
|
+
};
|
|
1985
|
+
/** @type {{safeVm: SafeScriptType}} */
|
|
1986
|
+
JSONPathClass.prototype.safeVm = { Script: SafeScript };
|
|
1987
|
+
JSONPath.prototype = JSONPathClass.prototype;
|
|
1988
|
+
/**
|
|
1989
|
+
* Clears cached parsed paths and compiled scripts.
|
|
1990
|
+
* @returns {void}
|
|
1991
|
+
*/
|
|
1992
|
+
JSONPath.clearCache = function() {
|
|
1993
|
+
pathCache.clear();
|
|
1994
|
+
scriptCache.clear();
|
|
1995
|
+
};
|
|
1996
|
+
/**
|
|
1997
|
+
* @param {string[]} pathArr Array to convert
|
|
1998
|
+
* @returns {string} The path string
|
|
1999
|
+
*/
|
|
2000
|
+
JSONPath.toPathString = function(pathArr) {
|
|
2001
|
+
const x = pathArr, n = x.length;
|
|
2002
|
+
let p = "$";
|
|
2003
|
+
for (let i = 1; i < n; i++) if (!/^(~|\^|@.*?\(\))$/v.test(x[i])) p += /^[0-9*]+$/v.test(x[i]) ? "[" + x[i] + "]" : "['" + String(x[i]).replaceAll(/['\\]/gv, String.raw`\$&`) + "']";
|
|
2004
|
+
return p;
|
|
2005
|
+
};
|
|
2006
|
+
/**
|
|
2007
|
+
* @param {string[]} pointer JSON Path array
|
|
2008
|
+
* @returns {string} JSON Pointer
|
|
2009
|
+
*/
|
|
2010
|
+
JSONPath.toPointer = function(pointer) {
|
|
2011
|
+
const x = pointer, n = x.length;
|
|
2012
|
+
let p = "";
|
|
2013
|
+
for (let i = 1; i < n; i++) if (!/^(~|\^|@.*?\(\))$/v.test(x[i])) p += "/" + x[i].toString().replaceAll("~", "~0").replaceAll("/", "~1");
|
|
2014
|
+
return p;
|
|
2015
|
+
};
|
|
2016
|
+
/**
|
|
2017
|
+
* @param {string} expr Expression to convert
|
|
2018
|
+
* @returns {string[]}
|
|
2019
|
+
*/
|
|
2020
|
+
JSONPath.toPathArray = function(expr) {
|
|
2021
|
+
if (pathCache.has(expr)) return pathCache.get(expr).concat();
|
|
2022
|
+
/** @type {string[]} */
|
|
2023
|
+
const subx = [];
|
|
2024
|
+
const exprList = expr.replaceAll(/@[\w$\-]+\([^\)]*\)/gv, ";$&;").replaceAll(/[\['](\??\(.*?\))[\]'](?!.\])/gv, function($0, $1) {
|
|
2025
|
+
return "[#" + (subx.push($1) - 1) + "]";
|
|
2026
|
+
}).replaceAll(/\[\s*((?:'(?:\\.|[^'\\])*'|"(?:\\.|[^"\\])*")(?:\s*,\s*(?:'(?:\\.|[^'\\])*'|"(?:\\.|[^"\\])*"))*)\s*\]/gv, function($0, $1) {
|
|
2027
|
+
if (!/[,\\]/v.test($1)) return $0;
|
|
2028
|
+
return "[#" + (subx.push($1) - 1) + "]";
|
|
2029
|
+
}).replaceAll(/\[['"]([^'\]]*)['"]\]/gv, function($0, prop) {
|
|
2030
|
+
return "['" + prop.replaceAll(".", "%@%").replaceAll("~", "%%@@%%") + "']";
|
|
2031
|
+
}).replaceAll("~", ";~;").replaceAll(/['"]?\.['"]?(?![^\[]*\])|\[['"]?/gv, ";").replaceAll("%@%", ".").replaceAll("%%@@%%", "~").replaceAll(/(?:;)?(\^+)(?:;)?/gv, function($0, ups) {
|
|
2032
|
+
return ";" + ups.split("").join(";") + ";";
|
|
2033
|
+
}).replaceAll(/;;;|;;/gv, ";..;").replaceAll(/;$|'?\]|'$/gv, "").split(";").map(function(exp) {
|
|
2034
|
+
const match = exp.match(/#(\d+)/v);
|
|
2035
|
+
return !match || !match[1] ? exp : subx[Number(match[1])];
|
|
2036
|
+
});
|
|
2037
|
+
pathCache.set(expr, exprList);
|
|
2038
|
+
return pathCache.get(expr).concat();
|
|
2039
|
+
};
|
|
2040
|
+
/**
|
|
2041
|
+
* @typedef {import('./jsonpath.js').AnyInput} AnyInput
|
|
2042
|
+
*/
|
|
2043
|
+
/**
|
|
2044
|
+
* @typedef {import('./jsonpath.js').SandboxCallback} SandboxCallback
|
|
2045
|
+
*/
|
|
2046
|
+
/**
|
|
2047
|
+
* @typedef {import('./jsonpath.js').SandboxPropertyValue} SandboxPropertyValue
|
|
2048
|
+
*/
|
|
2049
|
+
/**
|
|
2050
|
+
* @typedef {import('./jsonpath.js').ExpressionArray} ExpressionArray
|
|
2051
|
+
*/
|
|
2052
|
+
/**
|
|
2053
|
+
* @typedef {import('./jsonpath.js').ValueType} ValueType
|
|
2054
|
+
*/
|
|
2055
|
+
/**
|
|
2056
|
+
* @typedef {import('./jsonpath.js').ParentValue} ParentValue
|
|
2057
|
+
*/
|
|
2058
|
+
/**
|
|
2059
|
+
* @typedef {import('./jsonpath.js').UnknownResult} UnknownResult
|
|
2060
|
+
*/
|
|
2061
|
+
/**
|
|
2062
|
+
* @typedef {import('./jsonpath.js').ParentProperty} ParentProperty
|
|
2063
|
+
*/
|
|
2064
|
+
/**
|
|
2065
|
+
* @typedef {import('./jsonpath.js').PreferredOutput} PreferredOutput
|
|
2066
|
+
*/
|
|
2067
|
+
/**
|
|
2068
|
+
* @typedef {import('./jsonpath.js').ReturnObject} ReturnObject
|
|
2069
|
+
*/
|
|
2070
|
+
/**
|
|
2071
|
+
* @typedef {import('./jsonpath.js').JSONPathCallback} JSONPathCallback
|
|
2072
|
+
*/
|
|
2073
|
+
/**
|
|
2074
|
+
* @typedef {import('./jsonpath.js').OtherTypeCallback} OtherTypeCallback
|
|
2075
|
+
*/
|
|
2076
|
+
/**
|
|
2077
|
+
* @typedef {import('./jsonpath.js').ContextItem} ContextItem
|
|
2078
|
+
*/
|
|
2079
|
+
/**
|
|
2080
|
+
* @typedef {import('./jsonpath.js').EvaluatedResult} EvaluatedResult
|
|
2081
|
+
*/
|
|
2082
|
+
/**
|
|
2083
|
+
* @typedef {import('./jsonpath.js').EvalCallback} EvalCallback
|
|
2084
|
+
*/
|
|
2085
|
+
/**
|
|
2086
|
+
* @typedef {import('./jsonpath.js').EvalClass} EvalClass
|
|
2087
|
+
*/
|
|
2088
|
+
/**
|
|
2089
|
+
* @typedef {import('./jsonpath.js').ResultType} ResultType
|
|
2090
|
+
*/
|
|
2091
|
+
/**
|
|
2092
|
+
* @typedef {import('./jsonpath.js').EvalValue} EvalValue
|
|
2093
|
+
*/
|
|
2094
|
+
/**
|
|
2095
|
+
* @typedef {import('./jsonpath.js').PathType} PathType
|
|
2096
|
+
*/
|
|
2097
|
+
/**
|
|
2098
|
+
* @typedef {import('./jsonpath.js').SafeScriptType} SafeScriptType
|
|
2099
|
+
*/
|
|
2100
|
+
/**
|
|
2101
|
+
* @typedef {import('./jsonpath.js').ScriptType} ScriptType
|
|
2102
|
+
*/
|
|
2103
|
+
/**
|
|
2104
|
+
* @typedef {import('./jsonpath.js').SandboxType} SandboxType
|
|
2105
|
+
*/
|
|
2106
|
+
/**
|
|
2107
|
+
* @typedef {import('./jsonpath.js').JSONPathOptions} JSONPathOptions
|
|
2108
|
+
*/
|
|
2109
|
+
/** @type {{vm: ScriptType}} */
|
|
2110
|
+
JSONPathClass.prototype.vm = vm;
|
|
2111
|
+
//#endregion
|
|
2112
|
+
export { JSONPath };
|
|
2113
|
+
|
|
2114
|
+
//# sourceMappingURL=index-node-esm-DAnl9SaE.mjs.map
|