UNPKG

33.7 kBJavaScriptView Raw
1(function (global, factory) {
2 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3 typeof define === 'function' && define.amd ? define(['exports'], factory) :
4 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.JSONPath = {}));
5}(this, (function (exports) { 'use strict';
6
7 function _typeof(obj) {
8 "@babel/helpers - typeof";
9
10 if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
11 _typeof = function (obj) {
12 return typeof obj;
13 };
14 } else {
15 _typeof = function (obj) {
16 return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
17 };
18 }
19
20 return _typeof(obj);
21 }
22
23 function _classCallCheck(instance, Constructor) {
24 if (!(instance instanceof Constructor)) {
25 throw new TypeError("Cannot call a class as a function");
26 }
27 }
28
29 function _inherits(subClass, superClass) {
30 if (typeof superClass !== "function" && superClass !== null) {
31 throw new TypeError("Super expression must either be null or a function");
32 }
33
34 subClass.prototype = Object.create(superClass && superClass.prototype, {
35 constructor: {
36 value: subClass,
37 writable: true,
38 configurable: true
39 }
40 });
41 if (superClass) _setPrototypeOf(subClass, superClass);
42 }
43
44 function _getPrototypeOf(o) {
45 _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
46 return o.__proto__ || Object.getPrototypeOf(o);
47 };
48 return _getPrototypeOf(o);
49 }
50
51 function _setPrototypeOf(o, p) {
52 _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
53 o.__proto__ = p;
54 return o;
55 };
56
57 return _setPrototypeOf(o, p);
58 }
59
60 function _isNativeReflectConstruct() {
61 if (typeof Reflect === "undefined" || !Reflect.construct) return false;
62 if (Reflect.construct.sham) return false;
63 if (typeof Proxy === "function") return true;
64
65 try {
66 Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
67 return true;
68 } catch (e) {
69 return false;
70 }
71 }
72
73 function _construct(Parent, args, Class) {
74 if (_isNativeReflectConstruct()) {
75 _construct = Reflect.construct;
76 } else {
77 _construct = function _construct(Parent, args, Class) {
78 var a = [null];
79 a.push.apply(a, args);
80 var Constructor = Function.bind.apply(Parent, a);
81 var instance = new Constructor();
82 if (Class) _setPrototypeOf(instance, Class.prototype);
83 return instance;
84 };
85 }
86
87 return _construct.apply(null, arguments);
88 }
89
90 function _isNativeFunction(fn) {
91 return Function.toString.call(fn).indexOf("[native code]") !== -1;
92 }
93
94 function _wrapNativeSuper(Class) {
95 var _cache = typeof Map === "function" ? new Map() : undefined;
96
97 _wrapNativeSuper = function _wrapNativeSuper(Class) {
98 if (Class === null || !_isNativeFunction(Class)) return Class;
99
100 if (typeof Class !== "function") {
101 throw new TypeError("Super expression must either be null or a function");
102 }
103
104 if (typeof _cache !== "undefined") {
105 if (_cache.has(Class)) return _cache.get(Class);
106
107 _cache.set(Class, Wrapper);
108 }
109
110 function Wrapper() {
111 return _construct(Class, arguments, _getPrototypeOf(this).constructor);
112 }
113
114 Wrapper.prototype = Object.create(Class.prototype, {
115 constructor: {
116 value: Wrapper,
117 enumerable: false,
118 writable: true,
119 configurable: true
120 }
121 });
122 return _setPrototypeOf(Wrapper, Class);
123 };
124
125 return _wrapNativeSuper(Class);
126 }
127
128 function _assertThisInitialized(self) {
129 if (self === void 0) {
130 throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
131 }
132
133 return self;
134 }
135
136 function _possibleConstructorReturn(self, call) {
137 if (call && (typeof call === "object" || typeof call === "function")) {
138 return call;
139 }
140
141 return _assertThisInitialized(self);
142 }
143
144 function _createSuper(Derived) {
145 var hasNativeReflectConstruct = _isNativeReflectConstruct();
146
147 return function _createSuperInternal() {
148 var Super = _getPrototypeOf(Derived),
149 result;
150
151 if (hasNativeReflectConstruct) {
152 var NewTarget = _getPrototypeOf(this).constructor;
153
154 result = Reflect.construct(Super, arguments, NewTarget);
155 } else {
156 result = Super.apply(this, arguments);
157 }
158
159 return _possibleConstructorReturn(this, result);
160 };
161 }
162
163 function _toConsumableArray(arr) {
164 return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
165 }
166
167 function _arrayWithoutHoles(arr) {
168 if (Array.isArray(arr)) return _arrayLikeToArray(arr);
169 }
170
171 function _iterableToArray(iter) {
172 if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter);
173 }
174
175 function _unsupportedIterableToArray(o, minLen) {
176 if (!o) return;
177 if (typeof o === "string") return _arrayLikeToArray(o, minLen);
178 var n = Object.prototype.toString.call(o).slice(8, -1);
179 if (n === "Object" && o.constructor) n = o.constructor.name;
180 if (n === "Map" || n === "Set") return Array.from(o);
181 if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
182 }
183
184 function _arrayLikeToArray(arr, len) {
185 if (len == null || len > arr.length) len = arr.length;
186
187 for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
188
189 return arr2;
190 }
191
192 function _nonIterableSpread() {
193 throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
194 }
195
196 function _createForOfIteratorHelper(o, allowArrayLike) {
197 var it;
198
199 if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) {
200 if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
201 if (it) o = it;
202 var i = 0;
203
204 var F = function () {};
205
206 return {
207 s: F,
208 n: function () {
209 if (i >= o.length) return {
210 done: true
211 };
212 return {
213 done: false,
214 value: o[i++]
215 };
216 },
217 e: function (e) {
218 throw e;
219 },
220 f: F
221 };
222 }
223
224 throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
225 }
226
227 var normalCompletion = true,
228 didErr = false,
229 err;
230 return {
231 s: function () {
232 it = o[Symbol.iterator]();
233 },
234 n: function () {
235 var step = it.next();
236 normalCompletion = step.done;
237 return step;
238 },
239 e: function (e) {
240 didErr = true;
241 err = e;
242 },
243 f: function () {
244 try {
245 if (!normalCompletion && it.return != null) it.return();
246 } finally {
247 if (didErr) throw err;
248 }
249 }
250 };
251 }
252
253 var hasOwnProp = Object.prototype.hasOwnProperty;
254 /**
255 * @typedef {null|boolean|number|string|PlainObject|GenericArray} JSONObject
256 */
257
258 /**
259 * Copies array and then pushes item into it.
260 * @param {GenericArray} arr Array to copy and into which to push
261 * @param {any} item Array item to add (to end)
262 * @returns {GenericArray} Copy of the original array
263 */
264
265 function push(arr, item) {
266 arr = arr.slice();
267 arr.push(item);
268 return arr;
269 }
270 /**
271 * Copies array and then unshifts item into it.
272 * @param {any} item Array item to add (to beginning)
273 * @param {GenericArray} arr Array to copy and into which to unshift
274 * @returns {GenericArray} Copy of the original array
275 */
276
277
278 function unshift(item, arr) {
279 arr = arr.slice();
280 arr.unshift(item);
281 return arr;
282 }
283 /**
284 * Caught when JSONPath is used without `new` but rethrown if with `new`
285 * @extends Error
286 */
287
288
289 var NewError = /*#__PURE__*/function (_Error) {
290 _inherits(NewError, _Error);
291
292 var _super = _createSuper(NewError);
293
294 /**
295 * @param {any} value The evaluated scalar value
296 */
297 function NewError(value) {
298 var _this;
299
300 _classCallCheck(this, NewError);
301
302 _this = _super.call(this, 'JSONPath should not be called with "new" (it prevents return ' + 'of (unwrapped) scalar values)');
303 _this.avoidNew = true;
304 _this.value = value;
305 _this.name = 'NewError';
306 return _this;
307 }
308
309 return NewError;
310 }( /*#__PURE__*/_wrapNativeSuper(Error));
311 /**
312 * @typedef {PlainObject} ReturnObject
313 * @property {string} path
314 * @property {JSONObject} value
315 * @property {PlainObject|GenericArray} parent
316 * @property {string} parentProperty
317 */
318
319 /**
320 * @callback JSONPathCallback
321 * @param {string|PlainObject} preferredOutput
322 * @param {"value"|"property"} type
323 * @param {ReturnObject} fullRetObj
324 * @returns {void}
325 */
326
327 /**
328 * @callback OtherTypeCallback
329 * @param {JSONObject} val
330 * @param {string} path
331 * @param {PlainObject|GenericArray} parent
332 * @param {string} parentPropName
333 * @returns {boolean}
334 */
335
336 /* eslint-disable max-len -- Can make multiline type after https://github.com/syavorsky/comment-parser/issues/109 */
337
338 /**
339 * @typedef {PlainObject} JSONPathOptions
340 * @property {JSON} json
341 * @property {string|string[]} path
342 * @property {"value"|"path"|"pointer"|"parent"|"parentProperty"|"all"} [resultType="value"]
343 * @property {boolean} [flatten=false]
344 * @property {boolean} [wrap=true]
345 * @property {PlainObject} [sandbox={}]
346 * @property {boolean} [preventEval=false]
347 * @property {PlainObject|GenericArray|null} [parent=null]
348 * @property {string|null} [parentProperty=null]
349 * @property {JSONPathCallback} [callback]
350 * @property {OtherTypeCallback} [otherTypeCallback] Defaults to
351 * function which throws on encountering `@other`
352 * @property {boolean} [autostart=true]
353 */
354
355 /* eslint-enable max-len -- Can make multiline type after https://github.com/syavorsky/comment-parser/issues/109 */
356
357 /**
358 * @param {string|JSONPathOptions} opts If a string, will be treated as `expr`
359 * @param {string} [expr] JSON path to evaluate
360 * @param {JSON} [obj] JSON object to evaluate against
361 * @param {JSONPathCallback} [callback] Passed 3 arguments: 1) desired payload
362 * per `resultType`, 2) `"value"|"property"`, 3) Full returned object with
363 * all payloads
364 * @param {OtherTypeCallback} [otherTypeCallback] If `@other()` is at the end
365 * of one's query, this will be invoked with the value of the item, its
366 * path, its parent, and its parent's property name, and it should return
367 * a boolean indicating whether the supplied value belongs to the "other"
368 * type or not (or it may handle transformations and return `false`).
369 * @returns {JSONPath}
370 * @class
371 */
372
373
374 function JSONPath(opts, expr, obj, callback, otherTypeCallback) {
375 // eslint-disable-next-line no-restricted-syntax
376 if (!(this instanceof JSONPath)) {
377 try {
378 return new JSONPath(opts, expr, obj, callback, otherTypeCallback);
379 } catch (e) {
380 if (!e.avoidNew) {
381 throw e;
382 }
383
384 return e.value;
385 }
386 }
387
388 if (typeof opts === 'string') {
389 otherTypeCallback = callback;
390 callback = obj;
391 obj = expr;
392 expr = opts;
393 opts = null;
394 }
395
396 var optObj = opts && _typeof(opts) === 'object';
397 opts = opts || {};
398 this.json = opts.json || obj;
399 this.path = opts.path || expr;
400 this.resultType = opts.resultType || 'value';
401 this.flatten = opts.flatten || false;
402 this.wrap = hasOwnProp.call(opts, 'wrap') ? opts.wrap : true;
403 this.sandbox = opts.sandbox || {};
404 this.preventEval = opts.preventEval || false;
405 this.parent = opts.parent || null;
406 this.parentProperty = opts.parentProperty || null;
407 this.callback = opts.callback || callback || null;
408
409 this.otherTypeCallback = opts.otherTypeCallback || otherTypeCallback || function () {
410 throw new TypeError('You must supply an otherTypeCallback callback option ' + 'with the @other() operator.');
411 };
412
413 if (opts.autostart !== false) {
414 var args = {
415 path: optObj ? opts.path : expr
416 };
417
418 if (!optObj) {
419 args.json = obj;
420 } else if ('json' in opts) {
421 args.json = opts.json;
422 }
423
424 var ret = this.evaluate(args);
425
426 if (!ret || _typeof(ret) !== 'object') {
427 throw new NewError(ret);
428 }
429
430 return ret;
431 }
432 } // PUBLIC METHODS
433
434
435 JSONPath.prototype.evaluate = function (expr, json, callback, otherTypeCallback) {
436 var _this2 = this;
437
438 var currParent = this.parent,
439 currParentProperty = this.parentProperty;
440 var flatten = this.flatten,
441 wrap = this.wrap;
442 this.currResultType = this.resultType;
443 this.currPreventEval = this.preventEval;
444 this.currSandbox = this.sandbox;
445 callback = callback || this.callback;
446 this.currOtherTypeCallback = otherTypeCallback || this.otherTypeCallback;
447 json = json || this.json;
448 expr = expr || this.path;
449
450 if (expr && _typeof(expr) === 'object' && !Array.isArray(expr)) {
451 if (!expr.path && expr.path !== '') {
452 throw new TypeError('You must supply a "path" property when providing an object ' + 'argument to JSONPath.evaluate().');
453 }
454
455 if (!hasOwnProp.call(expr, 'json')) {
456 throw new TypeError('You must supply a "json" property when providing an object ' + 'argument to JSONPath.evaluate().');
457 }
458
459 var _expr = expr;
460 json = _expr.json;
461 flatten = hasOwnProp.call(expr, 'flatten') ? expr.flatten : flatten;
462 this.currResultType = hasOwnProp.call(expr, 'resultType') ? expr.resultType : this.currResultType;
463 this.currSandbox = hasOwnProp.call(expr, 'sandbox') ? expr.sandbox : this.currSandbox;
464 wrap = hasOwnProp.call(expr, 'wrap') ? expr.wrap : wrap;
465 this.currPreventEval = hasOwnProp.call(expr, 'preventEval') ? expr.preventEval : this.currPreventEval;
466 callback = hasOwnProp.call(expr, 'callback') ? expr.callback : callback;
467 this.currOtherTypeCallback = hasOwnProp.call(expr, 'otherTypeCallback') ? expr.otherTypeCallback : this.currOtherTypeCallback;
468 currParent = hasOwnProp.call(expr, 'parent') ? expr.parent : currParent;
469 currParentProperty = hasOwnProp.call(expr, 'parentProperty') ? expr.parentProperty : currParentProperty;
470 expr = expr.path;
471 }
472
473 currParent = currParent || null;
474 currParentProperty = currParentProperty || null;
475
476 if (Array.isArray(expr)) {
477 expr = JSONPath.toPathString(expr);
478 }
479
480 if (!expr && expr !== '' || !json) {
481 return undefined;
482 }
483
484 var exprList = JSONPath.toPathArray(expr);
485
486 if (exprList[0] === '$' && exprList.length > 1) {
487 exprList.shift();
488 }
489
490 this._hasParentSelector = null;
491
492 var result = this._trace(exprList, json, ['$'], currParent, currParentProperty, callback).filter(function (ea) {
493 return ea && !ea.isParentSelector;
494 });
495
496 if (!result.length) {
497 return wrap ? [] : undefined;
498 }
499
500 if (!wrap && result.length === 1 && !result[0].hasArrExpr) {
501 return this._getPreferredOutput(result[0]);
502 }
503
504 return result.reduce(function (rslt, ea) {
505 var valOrPath = _this2._getPreferredOutput(ea);
506
507 if (flatten && Array.isArray(valOrPath)) {
508 rslt = rslt.concat(valOrPath);
509 } else {
510 rslt.push(valOrPath);
511 }
512
513 return rslt;
514 }, []);
515 }; // PRIVATE METHODS
516
517
518 JSONPath.prototype._getPreferredOutput = function (ea) {
519 var resultType = this.currResultType;
520
521 switch (resultType) {
522 case 'all':
523 {
524 var path = Array.isArray(ea.path) ? ea.path : JSONPath.toPathArray(ea.path);
525 ea.pointer = JSONPath.toPointer(path);
526 ea.path = typeof ea.path === 'string' ? ea.path : JSONPath.toPathString(ea.path);
527 return ea;
528 }
529
530 case 'value':
531 case 'parent':
532 case 'parentProperty':
533 return ea[resultType];
534
535 case 'path':
536 return JSONPath.toPathString(ea[resultType]);
537
538 case 'pointer':
539 return JSONPath.toPointer(ea.path);
540
541 default:
542 throw new TypeError('Unknown result type');
543 }
544 };
545
546 JSONPath.prototype._handleCallback = function (fullRetObj, callback, type) {
547 if (callback) {
548 var preferredOutput = this._getPreferredOutput(fullRetObj);
549
550 fullRetObj.path = typeof fullRetObj.path === 'string' ? fullRetObj.path : JSONPath.toPathString(fullRetObj.path); // eslint-disable-next-line node/callback-return
551
552 callback(preferredOutput, type, fullRetObj);
553 }
554 };
555 /**
556 *
557 * @param {string} expr
558 * @param {JSONObject} val
559 * @param {string} path
560 * @param {PlainObject|GenericArray} parent
561 * @param {string} parentPropName
562 * @param {JSONPathCallback} callback
563 * @param {boolean} hasArrExpr
564 * @param {boolean} literalPriority
565 * @returns {ReturnObject|ReturnObject[]}
566 */
567
568
569 JSONPath.prototype._trace = function (expr, val, path, parent, parentPropName, callback, hasArrExpr, literalPriority) {
570 var _this3 = this;
571
572 // No expr to follow? return path and value as the result of
573 // this trace branch
574 var retObj;
575
576 if (!expr.length) {
577 retObj = {
578 path: path,
579 value: val,
580 parent: parent,
581 parentProperty: parentPropName,
582 hasArrExpr: hasArrExpr
583 };
584
585 this._handleCallback(retObj, callback, 'value');
586
587 return retObj;
588 }
589
590 var loc = expr[0],
591 x = expr.slice(1); // We need to gather the return value of recursive trace calls in order to
592 // do the parent sel computation.
593
594 var ret = [];
595 /**
596 *
597 * @param {ReturnObject|ReturnObject[]} elems
598 * @returns {void}
599 */
600
601 function addRet(elems) {
602 if (Array.isArray(elems)) {
603 // This was causing excessive stack size in Node (with or
604 // without Babel) against our performance test:
605 // `ret.push(...elems);`
606 elems.forEach(function (t) {
607 ret.push(t);
608 });
609 } else {
610 ret.push(elems);
611 }
612 }
613
614 if ((typeof loc !== 'string' || literalPriority) && val && hasOwnProp.call(val, loc)) {
615 // simple case--directly follow property
616 addRet(this._trace(x, val[loc], push(path, loc), val, loc, callback, hasArrExpr));
617 } else if (loc === '*') {
618 // all child properties
619 this._walk(loc, x, val, path, parent, parentPropName, callback, function (m, l, _x, v, p, par, pr, cb) {
620 addRet(_this3._trace(unshift(m, _x), v, p, par, pr, cb, true, true));
621 });
622 } else if (loc === '..') {
623 // all descendent parent properties
624 // Check remaining expression with val's immediate children
625 addRet(this._trace(x, val, path, parent, parentPropName, callback, hasArrExpr));
626
627 this._walk(loc, x, val, path, parent, parentPropName, callback, function (m, l, _x, v, p, par, pr, cb) {
628 // We don't join m and x here because we only want parents,
629 // not scalar values
630 if (_typeof(v[m]) === 'object') {
631 // Keep going with recursive descent on val's
632 // object children
633 addRet(_this3._trace(unshift(l, _x), v[m], push(p, m), v, m, cb, true));
634 }
635 }); // The parent sel computation is handled in the frame above using the
636 // ancestor object of val
637
638 } else if (loc === '^') {
639 // This is not a final endpoint, so we do not invoke the callback here
640 this._hasParentSelector = true;
641 return {
642 path: path.slice(0, -1),
643 expr: x,
644 isParentSelector: true
645 };
646 } else if (loc === '~') {
647 // property name
648 retObj = {
649 path: push(path, loc),
650 value: parentPropName,
651 parent: parent,
652 parentProperty: null
653 };
654
655 this._handleCallback(retObj, callback, 'property');
656
657 return retObj;
658 } else if (loc === '$') {
659 // root only
660 addRet(this._trace(x, val, path, null, null, callback, hasArrExpr));
661 } else if (/^(\x2D?[0-9]*):(\x2D?[0-9]*):?([0-9]*)$/.test(loc)) {
662 // [start:end:step] Python slice syntax
663 addRet(this._slice(loc, x, val, path, parent, parentPropName, callback));
664 } else if (loc.indexOf('?(') === 0) {
665 // [?(expr)] (filtering)
666 if (this.currPreventEval) {
667 throw new Error('Eval [?(expr)] prevented in JSONPath expression.');
668 }
669
670 this._walk(loc, x, val, path, parent, parentPropName, callback, function (m, l, _x, v, p, par, pr, cb) {
671 if (_this3._eval(l.replace(/^\?\(((?:[\0-\t\x0B\f\x0E-\u2027\u202A-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*?)\)$/, '$1'), v[m], m, p, par, pr)) {
672 addRet(_this3._trace(unshift(m, _x), v, p, par, pr, cb, true));
673 }
674 });
675 } else if (loc[0] === '(') {
676 // [(expr)] (dynamic property/index)
677 if (this.currPreventEval) {
678 throw new Error('Eval [(expr)] prevented in JSONPath expression.');
679 } // As this will resolve to a property name (but we don't know it
680 // yet), property and parent information is relative to the
681 // parent of the property to which this expression will resolve
682
683
684 addRet(this._trace(unshift(this._eval(loc, val, path[path.length - 1], path.slice(0, -1), parent, parentPropName), x), val, path, parent, parentPropName, callback, hasArrExpr));
685 } else if (loc[0] === '@') {
686 // value type: @boolean(), etc.
687 var addType = false;
688 var valueType = loc.slice(1, -2);
689
690 switch (valueType) {
691 case 'scalar':
692 if (!val || !['object', 'function'].includes(_typeof(val))) {
693 addType = true;
694 }
695
696 break;
697
698 case 'boolean':
699 case 'string':
700 case 'undefined':
701 case 'function':
702 // eslint-disable-next-line valid-typeof
703 if (_typeof(val) === valueType) {
704 addType = true;
705 }
706
707 break;
708
709 case 'integer':
710 if (Number.isFinite(val) && !(val % 1)) {
711 addType = true;
712 }
713
714 break;
715
716 case 'number':
717 if (Number.isFinite(val)) {
718 addType = true;
719 }
720
721 break;
722
723 case 'nonFinite':
724 if (typeof val === 'number' && !Number.isFinite(val)) {
725 addType = true;
726 }
727
728 break;
729
730 case 'object':
731 // eslint-disable-next-line valid-typeof
732 if (val && _typeof(val) === valueType) {
733 addType = true;
734 }
735
736 break;
737
738 case 'array':
739 if (Array.isArray(val)) {
740 addType = true;
741 }
742
743 break;
744
745 case 'other':
746 addType = this.currOtherTypeCallback(val, path, parent, parentPropName);
747 break;
748
749 case 'null':
750 if (val === null) {
751 addType = true;
752 }
753
754 break;
755
756 /* istanbul ignore next */
757
758 default:
759 throw new TypeError('Unknown value type ' + valueType);
760 }
761
762 if (addType) {
763 retObj = {
764 path: path,
765 value: val,
766 parent: parent,
767 parentProperty: parentPropName
768 };
769
770 this._handleCallback(retObj, callback, 'value');
771
772 return retObj;
773 } // `-escaped property
774
775 } else if (loc[0] === '`' && val && hasOwnProp.call(val, loc.slice(1))) {
776 var locProp = loc.slice(1);
777 addRet(this._trace(x, val[locProp], push(path, locProp), val, locProp, callback, hasArrExpr, true));
778 } else if (loc.includes(',')) {
779 // [name1,name2,...]
780 var parts = loc.split(',');
781
782 var _iterator = _createForOfIteratorHelper(parts),
783 _step;
784
785 try {
786 for (_iterator.s(); !(_step = _iterator.n()).done;) {
787 var part = _step.value;
788 addRet(this._trace(unshift(part, x), val, path, parent, parentPropName, callback, true));
789 } // simple case--directly follow property
790
791 } catch (err) {
792 _iterator.e(err);
793 } finally {
794 _iterator.f();
795 }
796 } else if (!literalPriority && val && hasOwnProp.call(val, loc)) {
797 addRet(this._trace(x, val[loc], push(path, loc), val, loc, callback, hasArrExpr, true));
798 } // We check the resulting values for parent selections. For parent
799 // selections we discard the value object and continue the trace with the
800 // current val object
801
802
803 if (this._hasParentSelector) {
804 for (var t = 0; t < ret.length; t++) {
805 var rett = ret[t];
806
807 if (rett && rett.isParentSelector) {
808 var tmp = this._trace(rett.expr, val, rett.path, parent, parentPropName, callback, hasArrExpr);
809
810 if (Array.isArray(tmp)) {
811 ret[t] = tmp[0];
812 var tl = tmp.length;
813
814 for (var tt = 1; tt < tl; tt++) {
815 t++;
816 ret.splice(t, 0, tmp[tt]);
817 }
818 } else {
819 ret[t] = tmp;
820 }
821 }
822 }
823 }
824
825 return ret;
826 };
827
828 JSONPath.prototype._walk = function (loc, expr, val, path, parent, parentPropName, callback, f) {
829 if (Array.isArray(val)) {
830 var n = val.length;
831
832 for (var i = 0; i < n; i++) {
833 f(i, loc, expr, val, path, parent, parentPropName, callback);
834 }
835 } else if (val && _typeof(val) === 'object') {
836 Object.keys(val).forEach(function (m) {
837 f(m, loc, expr, val, path, parent, parentPropName, callback);
838 });
839 }
840 };
841
842 JSONPath.prototype._slice = function (loc, expr, val, path, parent, parentPropName, callback) {
843 if (!Array.isArray(val)) {
844 return undefined;
845 }
846
847 var len = val.length,
848 parts = loc.split(':'),
849 step = parts[2] && Number.parseInt(parts[2]) || 1;
850 var start = parts[0] && Number.parseInt(parts[0]) || 0,
851 end = parts[1] && Number.parseInt(parts[1]) || len;
852 start = start < 0 ? Math.max(0, start + len) : Math.min(len, start);
853 end = end < 0 ? Math.max(0, end + len) : Math.min(len, end);
854 var ret = [];
855
856 for (var i = start; i < end; i += step) {
857 var tmp = this._trace(unshift(i, expr), val, path, parent, parentPropName, callback, true); // Should only be possible to be an array here since first part of
858 // ``unshift(i, expr)` passed in above would not be empty, nor `~`,
859 // nor begin with `@` (as could return objects)
860 // This was causing excessive stack size in Node (with or
861 // without Babel) against our performance test: `ret.push(...tmp);`
862
863
864 tmp.forEach(function (t) {
865 ret.push(t);
866 });
867 }
868
869 return ret;
870 };
871
872 JSONPath.prototype._eval = function (code, _v, _vname, path, parent, parentPropName) {
873 if (code.includes('@parentProperty')) {
874 this.currSandbox._$_parentProperty = parentPropName;
875 code = code.replace(/@parentProperty/g, '_$_parentProperty');
876 }
877
878 if (code.includes('@parent')) {
879 this.currSandbox._$_parent = parent;
880 code = code.replace(/@parent/g, '_$_parent');
881 }
882
883 if (code.includes('@property')) {
884 this.currSandbox._$_property = _vname;
885 code = code.replace(/@property/g, '_$_property');
886 }
887
888 if (code.includes('@path')) {
889 this.currSandbox._$_path = JSONPath.toPathString(path.concat([_vname]));
890 code = code.replace(/@path/g, '_$_path');
891 }
892
893 if (code.includes('@root')) {
894 this.currSandbox._$_root = this.json;
895 code = code.replace(/@root/g, '_$_root');
896 }
897
898 if (/@([\t-\r \)\.\[\xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF])/.test(code)) {
899 this.currSandbox._$_v = _v;
900 code = code.replace(/@([\t-\r \)\.\[\xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF])/g, '_$_v$1');
901 }
902
903 try {
904 return this.vm.runInNewContext(code, this.currSandbox);
905 } catch (e) {
906 // eslint-disable-next-line no-console
907 console.log(e);
908 throw new Error('jsonPath: ' + e.message + ': ' + code);
909 }
910 }; // PUBLIC CLASS PROPERTIES AND METHODS
911 // Could store the cache object itself
912
913
914 JSONPath.cache = {};
915 /**
916 * @param {string[]} pathArr Array to convert
917 * @returns {string} The path string
918 */
919
920 JSONPath.toPathString = function (pathArr) {
921 var x = pathArr,
922 n = x.length;
923 var p = '$';
924
925 for (var i = 1; i < n; i++) {
926 if (!/^(~|\^|@(?:[\0-\t\x0B\f\x0E-\u2027\u202A-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*?\(\))$/.test(x[i])) {
927 p += /^[\*0-9]+$/.test(x[i]) ? '[' + x[i] + ']' : "['" + x[i] + "']";
928 }
929 }
930
931 return p;
932 };
933 /**
934 * @param {string} pointer JSON Path
935 * @returns {string} JSON Pointer
936 */
937
938
939 JSONPath.toPointer = function (pointer) {
940 var x = pointer,
941 n = x.length;
942 var p = '';
943
944 for (var i = 1; i < n; i++) {
945 if (!/^(~|\^|@(?:[\0-\t\x0B\f\x0E-\u2027\u202A-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*?\(\))$/.test(x[i])) {
946 p += '/' + x[i].toString().replace(/~/g, '~0').replace(/\//g, '~1');
947 }
948 }
949
950 return p;
951 };
952 /**
953 * @param {string} expr Expression to convert
954 * @returns {string[]}
955 */
956
957
958 JSONPath.toPathArray = function (expr) {
959 var cache = JSONPath.cache;
960
961 if (cache[expr]) {
962 return cache[expr].concat();
963 }
964
965 var subx = [];
966 var normalized = expr // Properties
967 .replace(/@(?:null|boolean|number|string|integer|undefined|nonFinite|scalar|array|object|function|other)\(\)/g, ';$&;') // Parenthetical evaluations (filtering and otherwise), directly
968 // within brackets or single quotes
969 .replace(/['\[](\??\((?:[\0-\t\x0B\f\x0E-\u2027\u202A-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])*?\))['\]]/g, function ($0, $1) {
970 return '[#' + (subx.push($1) - 1) + ']';
971 }) // Escape periods and tildes within properties
972 .replace(/\['((?:(?!['\]])[\s\S])*)'\]/g, function ($0, prop) {
973 return "['" + prop.replace(/\./g, '%@%').replace(/~/g, '%%@@%%') + "']";
974 }) // Properties operator
975 .replace(/~/g, ';~;') // Split by property boundaries
976 .replace(/'?\.'?(?!(?:(?!\[)[\s\S])*\])|\['?/g, ';') // Reinsert periods within properties
977 .replace(/%@%/g, '.') // Reinsert tildes within properties
978 .replace(/%%@@%%/g, '~') // Parent
979 .replace(/(?:;)?(\^+)(?:;)?/g, function ($0, ups) {
980 return ';' + ups.split('').join(';') + ';';
981 }) // Descendents
982 .replace(/;;;|;;/g, ';..;') // Remove trailing
983 .replace(/;$|'?\]|'$/g, '');
984 var exprList = normalized.split(';').map(function (exp) {
985 var match = exp.match(/#([0-9]+)/);
986 return !match || !match[1] ? exp : subx[match[1]];
987 });
988 cache[expr] = exprList;
989 return cache[expr].concat();
990 };
991
992 /**
993 * @callback ConditionCallback
994 * @param {any} item
995 * @returns {boolean}
996 */
997
998 /**
999 * Copy items out of one array into another.
1000 * @param {GenericArray} source Array with items to copy
1001 * @param {GenericArray} target Array to which to copy
1002 * @param {ConditionCallback} conditionCb Callback passed the current item;
1003 * will move item if evaluates to `true`
1004 * @returns {void}
1005 */
1006
1007 var moveToAnotherArray = function moveToAnotherArray(source, target, conditionCb) {
1008 var il = source.length;
1009
1010 for (var i = 0; i < il; i++) {
1011 var item = source[i];
1012
1013 if (conditionCb(item)) {
1014 target.push(source.splice(i--, 1)[0]);
1015 }
1016 }
1017 };
1018
1019 JSONPath.prototype.vm = {
1020 /**
1021 * @param {string} expr Expression to evaluate
1022 * @param {PlainObject} context Object whose items will be added
1023 * to evaluation
1024 * @returns {any} Result of evaluated code
1025 */
1026 runInNewContext: function runInNewContext(expr, context) {
1027 var keys = Object.keys(context);
1028 var funcs = [];
1029 moveToAnotherArray(keys, funcs, function (key) {
1030 return typeof context[key] === 'function';
1031 });
1032 var values = keys.map(function (vr, i) {
1033 return context[vr];
1034 });
1035 var funcString = funcs.reduce(function (s, func) {
1036 var fString = context[func].toString();
1037
1038 if (!/function/.test(fString)) {
1039 fString = 'function ' + fString;
1040 }
1041
1042 return 'var ' + func + '=' + fString + ';' + s;
1043 }, '');
1044 expr = funcString + expr; // Mitigate http://perfectionkills.com/global-eval-what-are-the-options/#new_function
1045
1046 if (!/(["'])use strict\1/.test(expr) && !keys.includes('arguments')) {
1047 expr = 'var arguments = undefined;' + expr;
1048 } // Remove last semi so `return` will be inserted before
1049 // the previous one instead, allowing for the return
1050 // of a bare ending expression
1051
1052
1053 expr = expr.replace(/;[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]*$/, ''); // Insert `return`
1054
1055 var lastStatementEnd = expr.lastIndexOf(';');
1056 var code = lastStatementEnd > -1 ? expr.slice(0, lastStatementEnd + 1) + ' return ' + expr.slice(lastStatementEnd + 1) : ' return ' + expr; // eslint-disable-next-line no-new-func
1057
1058 return _construct(Function, _toConsumableArray(keys).concat([code])).apply(void 0, _toConsumableArray(values));
1059 }
1060 };
1061
1062 exports.JSONPath = JSONPath;
1063
1064 Object.defineProperty(exports, '__esModule', { value: true });
1065
1066})));