@@ -480,7 +480,7 @@ JSONPath.prototype.evaluate = function (expr, json, callback, otherTypeCallback)
480480 return wrap ? [ ] : undefined ;
481481 }
482482
483- if ( ! wrap && this . isSingularResult ( result , exprList ) ) {
483+ if ( ! wrap && result . length === 1 && ! result [ 0 ] . hasArrExpr ) {
484484 return this . _getPreferredOutput ( result [ 0 ] ) ;
485485 }
486486
@@ -522,52 +522,6 @@ JSONPath.prototype._getPreferredOutput = function (ea) {
522522 return JSONPath . toPointer ( ea . path ) ;
523523 }
524524} ;
525- /**
526- * Detect filter expressions.
527- * @param {string }loc
528- * @returns {boolean }
529- */
530-
531-
532- JSONPath . prototype . isFilterExpr = function ( loc ) {
533- return loc . indexOf ( '?(' ) === 0 ;
534- } ;
535- /**
536- * Detects operators in the expression list that require an array result.
537- * an array of results. If no such operator exists, the result
538- * will be treated as a singular value.
539- *
540- * For example, the following paths reference singular results:
541- * "store.book[0]" - specific book
542- * "store.bicycle.red" - single property of a single object
543- *
544- * Conversely, the following paths will always result in an array,
545- * because they can generate multiple results depending on the dataset:
546- * $.store.book[0][category,author] - category,author will return 2 values
547- * $..book - ".." will recurse through the store object
548- * $.store.book[1:2] - indicates a range within the array
549- * $.store.book[*] - wild card indicates multiple results
550- * $.store.book[?(@.isbn)] - filtering
551- */
552-
553- /**
554- * @param {PlainObject } result - json path result
555- * @param {array } exprList - array of json path expressions
556- * @returns {boolean }
557- */
558-
559-
560- JSONPath . prototype . isSingularResult = function ( result , exprList ) {
561- var _this2 = this ;
562-
563- return result . length === 1 && ! exprList . includes ( '*' ) && ! exprList . includes ( '..' ) && exprList . every ( function ( loc ) {
564- return ! _this2 . isFilterExpr ( loc ) ;
565- } ) && exprList . every ( function ( loc ) {
566- return ! loc . includes ( ',' ) ;
567- } ) && exprList . every ( function ( loc ) {
568- return ! loc . includes ( ':' ) ;
569- } ) ;
570- } ;
571525
572526JSONPath . prototype . _handleCallback = function ( fullRetObj , callback , type ) {
573527 if ( callback ) {
@@ -587,11 +541,12 @@ JSONPath.prototype._handleCallback = function (fullRetObj, callback, type) {
587541 * @param {string } parentPropName
588542 * @param {JSONPathCallback } callback
589543 * @param {boolean } literalPriority
544+ * @param {boolean } hasArrExpr
590545 * @returns {ReturnObject|ReturnObject[] }
591546 */
592547
593548
594- JSONPath . prototype . _trace = function ( expr , val , path , parent , parentPropName , callback , literalPriority ) {
549+ JSONPath . prototype . _trace = function ( expr , val , path , parent , parentPropName , callback , hasArrExpr , literalPriority ) {
595550 // No expr to follow? return path and value as the result of
596551 // this trace branch
597552 var retObj ;
@@ -602,7 +557,8 @@ JSONPath.prototype._trace = function (expr, val, path, parent, parentPropName, c
602557 path : path ,
603558 value : val ,
604559 parent : parent ,
605- parentProperty : parentPropName
560+ parentProperty : parentPropName ,
561+ hasArrExpr : hasArrExpr
606562 } ;
607563
608564 this . _handleCallback ( retObj , callback , 'value' ) ;
@@ -636,24 +592,24 @@ JSONPath.prototype._trace = function (expr, val, path, parent, parentPropName, c
636592
637593 if ( ( typeof loc !== 'string' || literalPriority ) && val && hasOwnProp . call ( val , loc ) ) {
638594 // simple case--directly follow property
639- addRet ( this . _trace ( x , val [ loc ] , push ( path , loc ) , val , loc , callback ) ) ;
595+ addRet ( this . _trace ( x , val [ loc ] , push ( path , loc ) , val , loc , callback , hasArrExpr ) ) ;
640596 } else if ( loc === '*' ) {
641597 // all child properties
642598 this . _walk ( loc , x , val , path , parent , parentPropName , callback , function ( m , l , _x , v , p , par , pr , cb ) {
643- addRet ( that . _trace ( unshift ( m , _x ) , v , p , par , pr , cb , true ) ) ;
599+ addRet ( that . _trace ( unshift ( m , _x ) , v , p , par , pr , cb , true , true ) ) ;
644600 } ) ;
645601 } else if ( loc === '..' ) {
646602 // all descendent parent properties
647603 // Check remaining expression with val's immediate children
648- addRet ( this . _trace ( x , val , path , parent , parentPropName , callback ) ) ;
604+ addRet ( this . _trace ( x , val , path , parent , parentPropName , callback , hasArrExpr ) ) ;
649605
650606 this . _walk ( loc , x , val , path , parent , parentPropName , callback , function ( m , l , _x , v , p , par , pr , cb ) {
651607 // We don't join m and x here because we only want parents,
652608 // not scalar values
653609 if ( _typeof ( v [ m ] ) === 'object' ) {
654610 // Keep going with recursive descent on val's
655611 // object children
656- addRet ( that . _trace ( unshift ( l , _x ) , v [ m ] , push ( p , m ) , v , m , cb ) ) ;
612+ addRet ( that . _trace ( unshift ( l , _x ) , v [ m ] , push ( p , m ) , v , m , cb , true ) ) ;
657613 }
658614 } ) ; // The parent sel computation is handled in the frame above using the
659615 // ancestor object of val
@@ -680,19 +636,19 @@ JSONPath.prototype._trace = function (expr, val, path, parent, parentPropName, c
680636 return retObj ;
681637 } else if ( loc === '$' ) {
682638 // root only
683- addRet ( this . _trace ( x , val , path , null , null , callback ) ) ;
639+ addRet ( this . _trace ( x , val , path , null , null , callback , hasArrExpr ) ) ;
684640 } else if ( / ^ ( \x2D ? [ 0 - 9 ] * ) : ( \x2D ? [ 0 - 9 ] * ) : ? ( [ 0 - 9 ] * ) $ / . test ( loc ) ) {
685641 // [start:end:step] Python slice syntax
686642 addRet ( this . _slice ( loc , x , val , path , parent , parentPropName , callback ) ) ;
687- } else if ( this . isFilterExpr ( loc ) ) {
643+ } else if ( loc . indexOf ( '?(' ) === 0 ) {
688644 // [?(expr)] (filtering)
689645 if ( this . currPreventEval ) {
690646 throw new Error ( 'Eval [?(expr)] prevented in JSONPath expression.' ) ;
691647 }
692648
693649 this . _walk ( loc , x , val , path , parent , parentPropName , callback , function ( m , l , _x , v , p , par , pr , cb ) {
694650 if ( that . _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 ) ) {
695- addRet ( that . _trace ( unshift ( m , _x ) , v , p , par , pr , cb ) ) ;
651+ addRet ( that . _trace ( unshift ( m , _x ) , v , p , par , pr , cb , true ) ) ;
696652 }
697653 } ) ;
698654 } else if ( loc [ 0 ] === '(' ) {
@@ -704,7 +660,7 @@ JSONPath.prototype._trace = function (expr, val, path, parent, parentPropName, c
704660 // parent of the property to which this expression will resolve
705661
706662
707- addRet ( this . _trace ( unshift ( this . _eval ( loc , val , path [ path . length - 1 ] , path . slice ( 0 , - 1 ) , parent , parentPropName ) , x ) , val , path , parent , parentPropName , callback ) ) ;
663+ 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 ) ) ;
708664 } else if ( loc [ 0 ] === '@' ) {
709665 // value type: @boolean (), etc.
710666 var addType = false ;
@@ -796,7 +752,7 @@ JSONPath.prototype._trace = function (expr, val, path, parent, parentPropName, c
796752
797753 } else if ( loc [ 0 ] === '`' && val && hasOwnProp . call ( val , loc . slice ( 1 ) ) ) {
798754 var locProp = loc . slice ( 1 ) ;
799- addRet ( this . _trace ( x , val [ locProp ] , push ( path , locProp ) , val , locProp , callback , true ) ) ;
755+ addRet ( this . _trace ( x , val [ locProp ] , push ( path , locProp ) , val , locProp , callback , hasArrExpr , true ) ) ;
800756 } else if ( loc . includes ( ',' ) ) {
801757 // [name1,name2,...]
802758 var parts = loc . split ( ',' ) ;
@@ -807,7 +763,7 @@ JSONPath.prototype._trace = function (expr, val, path, parent, parentPropName, c
807763 try {
808764 for ( var _iterator = parts [ Symbol . iterator ] ( ) , _step ; ! ( _iteratorNormalCompletion = ( _step = _iterator . next ( ) ) . done ) ; _iteratorNormalCompletion = true ) {
809765 var part = _step . value ;
810- addRet ( this . _trace ( unshift ( part , x ) , val , path , parent , parentPropName , callback ) ) ;
766+ addRet ( this . _trace ( unshift ( part , x ) , val , path , parent , parentPropName , callback , true ) ) ;
811767 } // simple case--directly follow property
812768
813769 } catch ( err ) {
@@ -825,7 +781,7 @@ JSONPath.prototype._trace = function (expr, val, path, parent, parentPropName, c
825781 }
826782 }
827783 } else if ( ! literalPriority && val && hasOwnProp . call ( val , loc ) ) {
828- addRet ( this . _trace ( x , val [ loc ] , push ( path , loc ) , val , loc , callback , true ) ) ;
784+ addRet ( this . _trace ( x , val [ loc ] , push ( path , loc ) , val , loc , callback , hasArrExpr , true ) ) ;
829785 } // We check the resulting values for parent selections. For parent
830786 // selections we discard the value object and continue the trace with the
831787 // current val object
@@ -836,7 +792,7 @@ JSONPath.prototype._trace = function (expr, val, path, parent, parentPropName, c
836792 var rett = ret [ t ] ;
837793
838794 if ( rett . isParentSelector ) {
839- var tmp = that . _trace ( rett . expr , val , rett . path , parent , parentPropName , callback ) ;
795+ var tmp = that . _trace ( rett . expr , val , rett . path , parent , parentPropName , callback , hasArrExpr ) ;
840796
841797 if ( Array . isArray ( tmp ) ) {
842798 ret [ t ] = tmp [ 0 ] ;
@@ -887,7 +843,7 @@ JSONPath.prototype._slice = function (loc, expr, val, path, parent, parentPropNa
887843 var ret = [ ] ;
888844
889845 for ( var i = start ; i < end ; i += step ) {
890- var tmp = this . _trace ( unshift ( i , expr ) , val , path , parent , parentPropName , callback ) ;
846+ var tmp = this . _trace ( unshift ( i , expr ) , val , path , parent , parentPropName , callback , true ) ;
891847
892848 if ( Array . isArray ( tmp ) ) {
893849 // This was causing excessive stack size in Node (with or
0 commit comments