99 * @description JSON query and transformation language
1010 */
1111
12- var regeneratorRuntime = require ( "regenerator-runtime" ) ;
12+ // istanbul ignore else
13+ if ( typeof module !== 'undefined' ) {
14+ var regeneratorRuntime = require ( "regenerator-runtime" ) ;
15+ }
1316
1417/**
1518 * jsonata
@@ -2542,7 +2545,12 @@ var jsonata = (function() {
25422545 return comp === 1 ;
25432546 } ;
25442547
2545- result = yield * functionSort ( lhs , comparator ) ;
2548+ var focus = {
2549+ environment : environment ,
2550+ input : input
2551+ } ;
2552+ // the `focus` is passed in as the `this` for the invoked function
2553+ result = yield * functionSort . apply ( focus , [ lhs , comparator ] ) ;
25462554
25472555 return result ;
25482556 }
@@ -2572,7 +2580,7 @@ var jsonata = (function() {
25722580 position : expr . position
25732581 } ;
25742582 }
2575- var result = yield * apply ( cloneFunction , [ obj ] , null ) ;
2583+ var result = yield * apply ( cloneFunction , [ obj ] , null , environment ) ;
25762584 var matches = yield * evaluate ( expr . pattern , result , environment ) ;
25772585 if ( typeof matches !== 'undefined' ) {
25782586 if ( ! Array . isArray ( matches ) ) {
@@ -2666,9 +2674,9 @@ var jsonata = (function() {
26662674 // this is function chaining (func1 ~> func2)
26672675 // λ($f, $g) { λ($x){ $g($f($x)) } }
26682676 var chain = yield * evaluate ( chainAST , null , environment ) ;
2669- result = yield * apply ( chain , [ lhs , func ] , null ) ;
2677+ result = yield * apply ( chain , [ lhs , func ] , null , environment ) ;
26702678 } else {
2671- result = yield * apply ( func , [ lhs ] , null ) ;
2679+ result = yield * apply ( func , [ lhs ] , null , environment ) ;
26722680 }
26732681
26742682 }
@@ -2713,7 +2721,6 @@ var jsonata = (function() {
27132721 * @param {Object } expr - JSONata expression
27142722 * @param {Object } input - Input data to evaluate against
27152723 * @param {Object } environment - Environment
2716- * @param {Object } [applyto] - LHS of ~> operator
27172724 * @returns {* } Evaluated input data
27182725 */
27192726 function * evaluateFunction ( expr , input , environment ) {
@@ -2742,7 +2749,7 @@ var jsonata = (function() {
27422749 }
27432750 // apply the procedure
27442751 try {
2745- result = yield * apply ( proc , evaluatedArgs , input ) ;
2752+ result = yield * apply ( proc , evaluatedArgs , input , environment ) ;
27462753 } catch ( err ) {
27472754 // add the position field to the error
27482755 err . position = expr . position ;
@@ -2757,12 +2764,13 @@ var jsonata = (function() {
27572764 * Apply procedure or function
27582765 * @param {Object } proc - Procedure
27592766 * @param {Array } args - Arguments
2760- * @param {Object } self - Self
2767+ * @param {Object } input - input
2768+ * @param {Object } environment - environment
27612769 * @returns {* } Result of procedure
27622770 */
2763- function * apply ( proc , args , self ) {
2771+ function * apply ( proc , args , input , environment ) {
27642772 var result ;
2765- result = yield * applyInner ( proc , args , self ) ;
2773+ result = yield * applyInner ( proc , args , input , environment ) ;
27662774 while ( isLambda ( result ) && result . thunk === true ) {
27672775 // trampoline loop - this gets invoked as a result of tail-call optimization
27682776 // the function returned a tail-call thunk
@@ -2773,7 +2781,7 @@ var jsonata = (function() {
27732781 evaluatedArgs . push ( yield * evaluate ( result . body . arguments [ ii ] , result . input , result . environment ) ) ;
27742782 }
27752783
2776- result = yield * applyInner ( next , evaluatedArgs , self ) ;
2784+ result = yield * applyInner ( next , evaluatedArgs , input , environment ) ;
27772785 }
27782786 return result ;
27792787 }
@@ -2782,26 +2790,37 @@ var jsonata = (function() {
27822790 * Apply procedure or function
27832791 * @param {Object } proc - Procedure
27842792 * @param {Array } args - Arguments
2785- * @param {Object } self - Self
2793+ * @param {Object } input - input
2794+ * @param {Object } environment - environment
27862795 * @returns {* } Result of procedure
27872796 */
2788- function * applyInner ( proc , args , self ) {
2797+ function * applyInner ( proc , args , input , environment ) {
27892798 var result ;
27902799 var validatedArgs = args ;
27912800 if ( proc ) {
2792- validatedArgs = validateArguments ( proc . signature , args , self ) ;
2801+ validatedArgs = validateArguments ( proc . signature , args , input ) ;
27932802 }
2803+
27942804 if ( isLambda ( proc ) ) {
27952805 result = yield * applyProcedure ( proc , validatedArgs ) ;
27962806 } else if ( proc && proc . _jsonata_function === true ) {
2797- result = proc . implementation . apply ( self , validatedArgs ) ;
2807+ var focus = {
2808+ environment : environment ,
2809+ input : input
2810+ } ;
2811+ // the `focus` is passed in as the `this` for the invoked function
2812+ result = proc . implementation . apply ( focus , validatedArgs ) ;
27982813 // `proc.implementation` might be a generator function
27992814 // and `result` might be a generator - if so, yield
28002815 if ( isIterable ( result ) ) {
28012816 result = yield * result ;
28022817 }
28032818 } else if ( typeof proc === 'function' ) {
2804- result = proc . apply ( self , validatedArgs ) ;
2819+ // typically these are functions that are returned by the invocation of plugin functions
2820+ // the `input` is being passed in as the `this` for the invoked function
2821+ // this is so that functions that return objects containing functions can chain
2822+ // e.g. $func().next().next()
2823+ result = proc . apply ( input , validatedArgs ) ;
28052824 /* istanbul ignore next */
28062825 if ( isIterable ( result ) ) {
28072826 result = yield * result ;
@@ -2987,7 +3006,10 @@ var jsonata = (function() {
29873006 return env . lookup ( sigArg . trim ( ) ) ;
29883007 } ) ;
29893008
2990- var result = proc . apply ( null , args ) ;
3009+ var focus = {
3010+ environment : env
3011+ } ;
3012+ var result = proc . apply ( focus , args ) ;
29913013 if ( isIterable ( result ) ) {
29923014 result = yield * result ;
29933015 }
@@ -3384,6 +3406,8 @@ var jsonata = (function() {
33843406 return undefined ;
33853407 }
33863408
3409+ var environment = this . environment ;
3410+
33873411 // pattern cannot be an empty string
33883412 if ( pattern === '' ) {
33893413 throw {
@@ -3478,7 +3502,7 @@ var jsonata = (function() {
34783502 if ( typeof matches !== 'undefined' ) {
34793503 while ( typeof matches !== 'undefined' && ( typeof limit === 'undefined' || count < limit ) ) {
34803504 result += str . substring ( position , matches . start ) ;
3481- var replacedWith = yield * apply ( replacer , [ matches ] , null ) ;
3505+ var replacedWith = yield * apply ( replacer , [ matches ] , null , environment ) ;
34823506 // check replacedWith is a string
34833507 if ( typeof replacedWith === 'string' ) {
34843508 result += replacedWith ;
@@ -4310,7 +4334,7 @@ var jsonata = (function() {
43104334 func_args . push ( arr ) ;
43114335 }
43124336 // invoke func
4313- var res = yield * apply ( func , func_args , null ) ;
4337+ var res = yield * apply ( func , func_args , null , this . environment ) ;
43144338 if ( typeof res !== 'undefined' ) {
43154339 result . push ( res ) ;
43164340 }
@@ -4338,7 +4362,7 @@ var jsonata = (function() {
43384362 for ( var i = 0 ; i < arr . length ; i ++ ) {
43394363 var entry = arr [ i ] ;
43404364 // invoke func
4341- var res = yield * apply ( func , [ entry , i , arr ] , null ) ;
4365+ var res = yield * apply ( func , [ entry , i , arr ] , null , this . environment ) ;
43424366 if ( functionBoolean ( res ) ) {
43434367 result . push ( entry ) ;
43444368 }
@@ -4403,7 +4427,7 @@ var jsonata = (function() {
44034427 }
44044428
44054429 while ( index < sequence . length ) {
4406- result = yield * apply ( func , [ result , sequence [ index ] ] , null ) ;
4430+ result = yield * apply ( func , [ result , sequence [ index ] ] , null , this . environment ) ;
44074431 index ++ ;
44084432 }
44094433
@@ -4572,7 +4596,7 @@ var jsonata = (function() {
45724596 for ( var key in obj ) {
45734597 var func_args = [ obj [ key ] , key ] ;
45744598 // invoke func
4575- result . push ( yield * apply ( func , func_args , null ) ) ;
4599+ result . push ( yield * apply ( func , func_args , null , this . environment ) ) ;
45764600 }
45774601
45784602 return result ;
@@ -4591,6 +4615,8 @@ var jsonata = (function() {
45914615 return undefined ;
45924616 }
45934617
4618+ var environment = this . environment ;
4619+
45944620 if ( arr . length <= 1 ) {
45954621 return arr ;
45964622 }
@@ -4614,7 +4640,7 @@ var jsonata = (function() {
46144640 comp = comparator ;
46154641 } else {
46164642 comp = function * ( a , b ) {
4617- return yield * apply ( comparator , [ a , b ] , null ) ;
4643+ return yield * apply ( comparator , [ a , b ] , null , environment ) ;
46184644 } ;
46194645 }
46204646
@@ -4699,7 +4725,7 @@ var jsonata = (function() {
46994725 for ( var item in arg ) {
47004726 var entry = arg [ item ] ;
47014727 // invoke func
4702- var res = yield * apply ( func , [ entry , item , arg ] , null ) ;
4728+ var res = yield * apply ( func , [ entry , item , arg ] , null , this . environment ) ;
47034729 if ( functionBoolean ( res ) ) {
47044730 result [ item ] = entry ;
47054731 }
@@ -4713,6 +4739,49 @@ var jsonata = (function() {
47134739 return result ;
47144740 }
47154741
4742+ /**
4743+ * parses and evaluates the supplied expression
4744+ * @param {string } expr - expression to evaluate
4745+ * @returns {* } - result of evaluating the expression
4746+ */
4747+ function * functionEval ( expr , focus ) {
4748+ // undefined inputs always return undefined
4749+ if ( typeof expr === 'undefined' ) {
4750+ return undefined ;
4751+ }
4752+ var input = this . input ;
4753+ if ( typeof focus !== 'undefined' ) {
4754+ input = focus ;
4755+ }
4756+
4757+ try {
4758+ var ast = parser ( expr , false ) ;
4759+ } catch ( err ) {
4760+ // error parsing the expression passed to $eval
4761+ populateMessage ( err ) ;
4762+ throw {
4763+ stack : ( new Error ( ) ) . stack ,
4764+ code : "D3120" ,
4765+ value : err . message ,
4766+ error : err
4767+ } ;
4768+ }
4769+ try {
4770+ var result = yield * evaluate ( ast , input , this . environment ) ;
4771+ } catch ( err ) {
4772+ // error evaluating the expression passed to $eval
4773+ populateMessage ( err ) ;
4774+ throw {
4775+ stack : ( new Error ( ) ) . stack ,
4776+ code : "D3121" ,
4777+ value :err . message ,
4778+ error : err
4779+ } ;
4780+ }
4781+
4782+ return result ;
4783+ }
4784+
47164785 // Regular expression to match an ISO 8601 formatted timestamp
47174786 var iso8601regex = new RegExp ( '^\\d{4}(-[01]\\d)*(-[0-3]\\d)*(T[0-2]\\d:[0-5]\\d:[0-5]\\d)*(\\.\\d+)?([+-][0-2]\\d:?[0-5]\\d|Z)?$' ) ;
47184787
@@ -4839,6 +4908,7 @@ var jsonata = (function() {
48394908 staticFrame . bind ( 'shuffle' , defineFunction ( functionShuffle , '<a:a>' ) ) ;
48404909 staticFrame . bind ( 'base64encode' , defineFunction ( functionBase64encode , '<s-:s>' ) ) ;
48414910 staticFrame . bind ( 'base64decode' , defineFunction ( functionBase64decode , '<s-:s>' ) ) ;
4911+ staticFrame . bind ( 'eval' , defineFunction ( functionEval , '<s-x?:x>' ) ) ;
48424912 staticFrame . bind ( 'toMillis' , defineFunction ( functionToMillis , '<s-:n>' ) ) ;
48434913 staticFrame . bind ( 'fromMillis' , defineFunction ( functionFromMillis , '<n-:s>' ) ) ;
48444914 staticFrame . bind ( 'clone' , defineFunction ( functionClone , '<(oa)-:o>' ) ) ;
@@ -4934,7 +5004,9 @@ var jsonata = (function() {
49345004 "D3092" : "A sub-picture that contains a 'percent' or 'per-mille' character must not contain a character treated as an 'exponent-separator'" ,
49355005 "D3093" : "The exponent part of the sub-picture must comprise only of one or more characters that are members of the 'decimal digit family'" ,
49365006 "D3100" : "The radix of the formatBase function must be between 2 and 36. It was given {{value}}" ,
4937- "D3110" : "The argument of the toMillis function must be an ISO 8601 formatted timestamp. Given {{value}}"
5007+ "D3110" : "The argument of the toMillis function must be an ISO 8601 formatted timestamp. Given {{value}}" ,
5008+ "D3120" : "Syntax error in expression passed to function eval: {{value}}" ,
5009+ "D3121" : "Dynamic error evaluating the expression passed to function eval: {{value}}"
49385010 } ;
49395011
49405012 /**
0 commit comments