11'use strict' ;
22
3+ const { default : getValue } = require ( 'get-value' ) ;
34const FunctionsSync = require ( './FunctionsSync' ) ;
45const Functions = require ( './Functions' ) ;
56const variables = require ( './variables' ) ;
@@ -57,11 +58,29 @@ class ExpressionSync {
5758 this . state . expressionDepth -- ;
5859 }
5960
61+ createContext ( context ) {
62+ if ( typeof context === 'function' ) {
63+ return context ;
64+ }
65+
66+ if ( utils . isPlainObject ( context ) ) {
67+ return { ...context } ;
68+ }
69+
70+ return context ;
71+ }
72+
6073 visit ( node , context , parent ) {
6174 this . incrementDepth ( ) ;
6275
6376 try {
64- Reflect . defineProperty ( node , 'parent' , { value : node . parent || parent } ) ;
77+ Reflect . defineProperty ( node , 'parent' , {
78+ configurable : true ,
79+ enumerable : false ,
80+ writable : true ,
81+ value : node . parent || parent
82+ } ) ;
83+
6584 const visitor = this . visitors [ node . type ] || this [ node . type ] ;
6685
6786 if ( typeof visitor !== 'function' ) {
@@ -70,13 +89,19 @@ class ExpressionSync {
7089 throw new TypeError ( message ) ;
7190 }
7291
73- const block = node . type === 'ArrayExpression' || node . type === 'ObjectExpression' ;
74- if ( block ) this . stack . push ( node ) ;
92+ // const block = node.type === 'ArrayExpression' || node.type === 'ObjectExpression';
93+ const ignore = [ 'Identifier' , 'BinaryExpression' ] ;
94+
95+ if ( ! ignore . includes ( node . type ) ) {
96+ this . stack . push ( node ) ;
97+ } else {
98+ //
99+ }
75100
76101 const value = visitor . call ( this , node , context , parent ) ;
77102 const resolve = v => {
78103 if ( v instanceof Promise ) return v . then ( v => resolve ( v ) ) ;
79- if ( block ) this . stack . pop ( ) ;
104+ if ( ! ignore . includes ( node . type ) ) this . stack . pop ( ) ;
80105 if ( this . state . fail ) return ;
81106 return v ;
82107 } ;
@@ -95,7 +120,7 @@ class ExpressionSync {
95120 return node . operator === '=' && node . right ?. operator === '~' && this . options . regexOperator !== false ;
96121 }
97122
98- assignment ( node ) {
123+ assignment ( node ) {
99124 switch ( node . operator ) {
100125 case '=' : // Assignment operator.
101126 case '*=' : // Multiplication assignment.
@@ -119,14 +144,38 @@ class ExpressionSync {
119144 }
120145 }
121146
122- postfix ( node , value ) {
147+ assignOperation ( operator , left , right ) {
148+ switch ( operator ) {
149+ case '=' : return right ;
150+ case '+=' : return left + right ;
151+ case '-=' : return left - right ;
152+ case '*=' : return left * right ;
153+ case '/=' : return left / right ;
154+ case '%=' : return left % right ;
155+ case '**=' : return left ** right ;
156+ case '<<=' : return left << right ;
157+ case '>>=' : return left >> right ;
158+ case '>>>=' : return left >>> right ;
159+ case '&=' : return left & right ;
160+ case '^=' : return left ^ right ;
161+ case '|=' : return left | right ;
162+ case '&&=' : return left && right ;
163+ case '||=' : return left || right ;
164+ case '??=' : return left ?? right ;
165+ default : {
166+ throw new SyntaxError ( `Assignment operator "${ operator } " is not supported` ) ;
167+ }
168+ }
169+ }
170+
171+ postfix ( node , value ) {
123172 switch ( node . operator ) {
124173 case '++' : return value + 1 ;
125174 case '--' : return value - 1 ;
126175 }
127176 }
128177
129- prefix ( node , value ) {
178+ prefix ( node , value ) {
130179 switch ( node . operator ) {
131180 case '++' : return value + 1 ;
132181 case '--' : return value - 1 ;
@@ -139,6 +188,12 @@ class ExpressionSync {
139188 const unset = obj => {
140189 if ( utils . isObject ( obj ) ) {
141190 Reflect . deleteProperty ( obj , node . property . name ) ;
191+
192+ const name = node . object . name ;
193+ if ( name && this . options . prefix && ! name . startsWith ( this . options . prefix ) ) {
194+ node . object . name = `${ this . options . prefix } .${ node . object . name } ` ;
195+ }
196+
142197 context [ node . object . name ] = obj ;
143198 return true ;
144199 }
@@ -196,7 +251,7 @@ class ExpressionSync {
196251 // Equality operators
197252 case '!==' : return left !== val ( ) ;
198253 case '===' : return left === val ( ) ;
199- case '!=' : return left != val ( ) ; /* eslint-disable-line eqeqeq */
254+ case '!=' : return left != val ( ) ; /* eslint-disable-line eqeqeq */
200255 case '==' : return left == val ( ) ; /* eslint-disable-line eqeqeq */
201256
202257 // Bitwise shift operators
@@ -300,7 +355,7 @@ class ExpressionSync {
300355 ConditionalExpression ( node , context ) {
301356 const { test, consequent, alternate } = node ;
302357 const truthy = this . visit ( test , context , node ) ;
303- return truthy ? this . visit ( consequent , context , node ) : this . visit ( alternate , context , node ) ;
358+ return this . visit ( truthy ? consequent : alternate , context , node ) ;
304359 }
305360
306361 Identifier ( node , context , parent ) {
@@ -314,8 +369,25 @@ class ExpressionSync {
314369 return ;
315370 }
316371
372+ if ( this . options . prefix && ! node . name . startsWith ( this . options . prefix ) ) {
373+ if ( ! this . insideFunction || ! this . functionParams ?. some ( p => p . name === node . name ) ) {
374+ node . name = `${ this . options . prefix } .${ node . name } ` ;
375+ }
376+ }
377+
317378 if ( context != null ) {
318- if ( context [ node . name ] !== undefined ) return context [ node . name ] ;
379+ if ( typeof context ?. lookup === 'function' ) {
380+ const value = context . lookup ( node . name ) ;
381+ if ( value !== undefined ) {
382+ return value ;
383+ }
384+ }
385+
386+ const value = context [ node . name ] ?? getValue ( context , node . name ) ;
387+ if ( value !== undefined ) {
388+ return value ;
389+ }
390+
319391 if ( hasOwnProperty . call ( context , node . name ) ) {
320392 return ;
321393 }
@@ -325,6 +397,7 @@ class ExpressionSync {
325397 if ( this . options . strict !== false ) {
326398 throw new ReferenceError ( `${ node . name } is undefined` ) ;
327399 }
400+
328401 this . state . fail = true ;
329402 return ExpressionSync . FAIL ;
330403 } ;
@@ -352,6 +425,11 @@ class ExpressionSync {
352425
353426 MemberExpression ( node , context , parent ) {
354427 const { computed, object, property, unset } = node ;
428+
429+ if ( object . name && this . options . prefix && ! object . name . startsWith ( this . options . prefix ) ) {
430+ object . name = `${ this . options . prefix } .${ object . name } ` ;
431+ }
432+
355433 const value = this . visit ( object , context , node ) ?? context [ object . name ] ;
356434 const data = computed ? context : value ;
357435
@@ -370,7 +448,7 @@ class ExpressionSync {
370448 prop = this . visit ( property , data , node ) ;
371449 }
372450
373- if ( prop == null && property . name && data ) {
451+ if ( prop === undefined && property . name && data ) {
374452 prop = data [ property . name ] ;
375453 }
376454
@@ -395,11 +473,14 @@ class ExpressionSync {
395473 if ( type === 'SpreadElement' ) {
396474 Object . assign ( object , this . visit ( property , context , node ) ) ;
397475 } else {
398- const name = property . computed
399- ? this . visit ( key , context , property )
400- : ( key . value || key . name ) ;
476+ const name = property . computed ? this . visit ( key , context , property ) : key . value || key . name ;
477+ const result = this . visit ( value , context , property ) ;
401478
402- object [ name ] = this . visit ( value , context , property ) ;
479+ if ( property . shorthand && this . options . prefix ) {
480+ property . shorthand = false ;
481+ }
482+
483+ object [ name ] = result ;
403484 }
404485 }
405486
@@ -457,9 +538,9 @@ class ExpressionSync {
457538
458539 ThisExpression ( node , context ) {
459540 if ( ! context ) throw new TypeError ( 'Cannot read property "this" of undefined' ) ;
460- if ( Reflect . has ( context , 'this' ) ) {
461- return context [ 'this' ] ;
462- }
541+
542+ const thisKey = this . options . prefix ? ` ${ this . options . prefix } .this` : 'this' ;
543+ return getValue ( context , thisKey ) ?? getValue ( context , 'this' ) ;
463544 }
464545
465546 UnaryExpression ( node , context ) {
@@ -486,12 +567,22 @@ class ExpressionSync {
486567
487568 const update = v => {
488569 const updated = node . prefix ? this . prefix ( node , v ) : this . postfix ( node , v ) ;
570+
571+ const name = node . argument . name ;
572+ if ( name && this . options . prefix && ! name . startsWith ( this . options . prefix ) ) {
573+ node . argument . name = `${ this . options . prefix } .${ node . argument . name } ` ;
574+ }
575+
489576 context [ node . argument . name ] = updated ;
490577 return updated ;
491578 } ;
492579
493580 return value instanceof Promise ? value . then ( obj => update ( obj ) ) : update ( value ) ;
494581 }
582+
583+ ExpressionStatement ( node , context ) {
584+ return this . visit ( node . expression , context , node ) ;
585+ }
495586}
496587
497588module . exports = ExpressionSync ;
0 commit comments