22 MIT License http://www.opensource.org/licenses/mit-license.php
33 Author Tobias Koppers @sokra
44*/
5- var esprima = require ( "esprima " ) ;
5+ var acorn = require ( "acorn " ) ;
66var Tapable = require ( "tapable" ) ;
77var BasicEvaluatedExpression = require ( "./BasicEvaluatedExpression" ) ;
88
@@ -39,28 +39,34 @@ Parser.prototype.initializeEvaluating = function() {
3939 return new BasicEvaluatedExpression ( ) . setRegExp ( expr . value ) . setRange ( expr . range ) ;
4040 } ) ;
4141 this . plugin ( "evaluate LogicalExpression" , function ( expr ) {
42+ var left ;
43+ var leftAsBool ;
44+ var right ;
4245 if ( expr . operator === "&&" ) {
43- var left = this . evaluateExpression ( expr . left ) ;
44- var leftAsBool = left && left . asBool ( ) ;
46+ left = this . evaluateExpression ( expr . left ) ;
47+ leftAsBool = left && left . asBool ( ) ;
4548 if ( leftAsBool === false ) return left . setRange ( expr . range ) ;
4649 if ( leftAsBool !== true ) return ;
47- var right = this . evaluateExpression ( expr . right ) ;
50+ right = this . evaluateExpression ( expr . right ) ;
4851 return right . setRange ( expr . range ) ;
4952 } else if ( expr . operator === "||" ) {
50- var left = this . evaluateExpression ( expr . left ) ;
51- var leftAsBool = left && left . asBool ( ) ;
53+ left = this . evaluateExpression ( expr . left ) ;
54+ leftAsBool = left && left . asBool ( ) ;
5255 if ( leftAsBool === true ) return left . setRange ( expr . range ) ;
5356 if ( leftAsBool !== false ) return ;
54- var right = this . evaluateExpression ( expr . right ) ;
57+ right = this . evaluateExpression ( expr . right ) ;
5558 return right . setRange ( expr . range ) ;
5659 }
5760 } ) ;
5861 this . plugin ( "evaluate BinaryExpression" , function ( expr ) {
62+ var left ;
63+ var right ;
64+ var res ;
5965 if ( expr . operator === "+" ) {
60- var left = this . evaluateExpression ( expr . left ) ;
61- var right = this . evaluateExpression ( expr . right ) ;
66+ left = this . evaluateExpression ( expr . left ) ;
67+ right = this . evaluateExpression ( expr . right ) ;
6268 if ( ! left || ! right ) return ;
63- var res = new BasicEvaluatedExpression ( ) ;
69+ res = new BasicEvaluatedExpression ( ) ;
6470 if ( left . isString ( ) ) {
6571 if ( right . isString ( ) ) {
6672 res . setString ( left . string + right . string ) ;
@@ -112,37 +118,37 @@ Parser.prototype.initializeEvaluating = function() {
112118 res . setRange ( expr . range ) ;
113119 return res ;
114120 } else if ( expr . operator === "-" ) {
115- var left = this . evaluateExpression ( expr . left ) ;
116- var right = this . evaluateExpression ( expr . right ) ;
121+ left = this . evaluateExpression ( expr . left ) ;
122+ right = this . evaluateExpression ( expr . right ) ;
117123 if ( ! left || ! right ) return ;
118124 if ( ! left . isNumber ( ) || ! right . isNumber ( ) ) return ;
119- var res = new BasicEvaluatedExpression ( ) ;
125+ res = new BasicEvaluatedExpression ( ) ;
120126 res . setNumber ( left . number - right . number ) ;
121127 res . setRange ( expr . range ) ;
122128 return res ;
123129 } else if ( expr . operator === "*" ) {
124- var left = this . evaluateExpression ( expr . left ) ;
125- var right = this . evaluateExpression ( expr . right ) ;
130+ left = this . evaluateExpression ( expr . left ) ;
131+ right = this . evaluateExpression ( expr . right ) ;
126132 if ( ! left || ! right ) return ;
127133 if ( ! left . isNumber ( ) || ! right . isNumber ( ) ) return ;
128- var res = new BasicEvaluatedExpression ( ) ;
134+ res = new BasicEvaluatedExpression ( ) ;
129135 res . setNumber ( left . number * right . number ) ;
130136 res . setRange ( expr . range ) ;
131137 return res ;
132138 } else if ( expr . operator === "/" ) {
133- var left = this . evaluateExpression ( expr . left ) ;
134- var right = this . evaluateExpression ( expr . right ) ;
139+ left = this . evaluateExpression ( expr . left ) ;
140+ right = this . evaluateExpression ( expr . right ) ;
135141 if ( ! left || ! right ) return ;
136142 if ( ! left . isNumber ( ) || ! right . isNumber ( ) ) return ;
137- var res = new BasicEvaluatedExpression ( ) ;
143+ res = new BasicEvaluatedExpression ( ) ;
138144 res . setNumber ( left . number / right . number ) ;
139145 res . setRange ( expr . range ) ;
140146 return res ;
141147 } else if ( expr . operator === "==" || expr . operator === "===" ) {
142- var left = this . evaluateExpression ( expr . left ) ;
143- var right = this . evaluateExpression ( expr . right ) ;
148+ left = this . evaluateExpression ( expr . left ) ;
149+ right = this . evaluateExpression ( expr . right ) ;
144150 if ( ! left || ! right ) return ;
145- var res = new BasicEvaluatedExpression ( ) ;
151+ res = new BasicEvaluatedExpression ( ) ;
146152 res . setRange ( expr . range ) ;
147153 if ( left . isString ( ) && right . isString ( ) ) {
148154 return res . setBoolean ( left . string === right . string ) ;
@@ -152,10 +158,10 @@ Parser.prototype.initializeEvaluating = function() {
152158 return res . setBoolean ( left . bool === right . bool ) ;
153159 }
154160 } else if ( expr . operator === "!=" || expr . operator === "!==" ) {
155- var left = this . evaluateExpression ( expr . left ) ;
156- var right = this . evaluateExpression ( expr . right ) ;
161+ left = this . evaluateExpression ( expr . left ) ;
162+ right = this . evaluateExpression ( expr . right ) ;
157163 if ( ! left || ! right ) return ;
158- var res = new BasicEvaluatedExpression ( ) ;
164+ res = new BasicEvaluatedExpression ( ) ;
159165 res . setRange ( expr . range ) ;
160166 if ( left . isString ( ) && right . isString ( ) ) {
161167 return res . setBoolean ( left . string !== right . string ) ;
@@ -168,10 +174,11 @@ Parser.prototype.initializeEvaluating = function() {
168174 } ) ;
169175 this . plugin ( "evaluate UnaryExpression" , function ( expr ) {
170176 if ( expr . operator === "typeof" ) {
177+ var res ;
171178 if ( expr . argument . type === "Identifier" ) {
172179 var name = this . scope . renames [ "$" + expr . argument . name ] || expr . argument . name ;
173180 if ( this . scope . definitions . indexOf ( name ) === - 1 ) {
174- var res = this . applyPluginsBailResult ( "evaluate typeof " + name , expr ) ;
181+ res = this . applyPluginsBailResult ( "evaluate typeof " + name , expr ) ;
175182 if ( res !== undefined ) return res ;
176183 }
177184 }
@@ -186,7 +193,7 @@ Parser.prototype.initializeEvaluating = function() {
186193 exprName . unshift ( this . scope . renames [ "$" + expression . name ] || expression . name ) ;
187194 if ( this . scope . definitions . indexOf ( name ) === - 1 ) {
188195 exprName = exprName . join ( "." ) ;
189- var res = this . applyPluginsBailResult ( "evaluate typeof " + exprName , expr ) ;
196+ res = this . applyPluginsBailResult ( "evaluate typeof " + exprName , expr ) ;
190197 if ( res !== undefined ) return res ;
191198 }
192199 }
@@ -267,15 +274,16 @@ Parser.prototype.initializeEvaluating = function() {
267274 [ "substr" , "substring" ] . forEach ( function ( fn ) {
268275 this . plugin ( "evaluate CallExpression ." + fn , function ( expr , param ) {
269276 if ( ! param . isString ( ) ) return ;
277+ var arg1 ;
270278 var result , str = param . string ;
271279 switch ( expr . arguments . length ) {
272280 case 1 :
273- var arg1 = this . evaluateExpression ( expr . arguments [ 0 ] ) ;
281+ arg1 = this . evaluateExpression ( expr . arguments [ 0 ] ) ;
274282 if ( ! arg1 . isNumber ( ) ) return ;
275283 result = str [ fn ] ( arg1 . number ) ;
276284 break ;
277285 case 2 :
278- var arg1 = this . evaluateExpression ( expr . arguments [ 0 ] ) ;
286+ arg1 = this . evaluateExpression ( expr . arguments [ 0 ] ) ;
279287 var arg2 = this . evaluateExpression ( expr . arguments [ 1 ] ) ;
280288 if ( ! arg1 . isNumber ( ) ) return ;
281289 if ( ! arg2 . isNumber ( ) ) return ;
@@ -302,11 +310,12 @@ Parser.prototype.initializeEvaluating = function() {
302310 this . plugin ( "evaluate ConditionalExpression" , function ( expr ) {
303311 var condition = this . evaluateExpression ( expr . test ) ;
304312 var conditionValue = condition . asBool ( ) ;
313+ var res ;
305314 if ( conditionValue === undefined ) {
306315 var consequent = this . evaluateExpression ( expr . consequent ) ;
307316 var alternate = this . evaluateExpression ( expr . alternate ) ;
308317 if ( ! consequent || ! alternate ) return ;
309- var res = new BasicEvaluatedExpression ( ) ;
318+ res = new BasicEvaluatedExpression ( ) ;
310319 if ( consequent . isConditional ( ) )
311320 res . setOptions ( consequent . options ) ;
312321 else
@@ -316,7 +325,7 @@ Parser.prototype.initializeEvaluating = function() {
316325 else
317326 res . addOptions ( [ alternate ] ) ;
318327 } else {
319- var res = this . evaluateExpression ( conditionValue ? expr . consequent : expr . alternate ) ;
328+ res = this . evaluateExpression ( conditionValue ? expr . consequent : expr . alternate ) ;
320329 }
321330 res . setRange ( expr . range ) ;
322331 return res ;
@@ -339,6 +348,24 @@ Parser.prototype.getRenameIdentifier = function getRenameIdentifier(expr) {
339348 return ;
340349} ;
341350
351+ Parser . prototype . walkClass = function walkClass ( classy ) {
352+ if ( classy . superClass )
353+ this . walkExpression ( classy . superClass ) ;
354+ if ( classy . body && classy . body . type === "ClassBody" ) {
355+ classy . body . body . forEach ( function ( methodDefinition ) {
356+ if ( methodDefinition . type === "MethodDefinition" )
357+ this . walkMethodDefinition ( methodDefinition ) ;
358+ } , this ) ;
359+ }
360+ } ;
361+
362+ Parser . prototype . walkMethodDefinition = function walkMethodDefinition ( methodDefinition ) {
363+ if ( methodDefinition . computed && methodDefinition . key )
364+ this . walkExpression ( methodDefinition . key ) ;
365+ if ( methodDefinition . value )
366+ this . walkExpression ( methodDefinition . value ) ;
367+ } ;
368+
342369Parser . prototype . walkStatements = function walkStatements ( statements ) {
343370 statements . forEach ( function ( statement ) {
344371 this . walkStatement ( statement ) ;
@@ -405,7 +432,8 @@ Parser.prototype.walkTryStatement = function walkTryStatement(statement) {
405432 this . walkStatement ( statement . block ) ;
406433 this . scope . inTry = false ;
407434 }
408- this . walkCatchClauses ( statement . handlers ) ;
435+ if ( statement . handler )
436+ this . walkCatchClause ( statement . handler ) ;
409437 if ( statement . finalizer )
410438 this . walkStatement ( statement . finalizer ) ;
411439} ;
@@ -439,6 +467,15 @@ Parser.prototype.walkForInStatement = function walkForInStatement(statement) {
439467 this . walkStatement ( statement . body ) ;
440468} ;
441469
470+ Parser . prototype . walkForOfStatement = function walkForOfStatement ( statement ) {
471+ if ( statement . left . type === "VariableDeclaration" )
472+ this . walkStatement ( statement . left ) ;
473+ else
474+ this . walkExpression ( statement . left ) ;
475+ this . walkExpression ( statement . right ) ;
476+ this . walkStatement ( statement . body ) ;
477+ } ;
478+
442479// Declarations
443480Parser . prototype . walkFunctionDeclaration = function walkFunctionDeclaration ( statement ) {
444481 this . scope . renames [ "$" + statement . id . name ] = undefined ;
@@ -456,6 +493,10 @@ Parser.prototype.walkVariableDeclaration = function walkVariableDeclaration(stat
456493 this . walkVariableDeclarators ( statement . declarations ) ;
457494} ;
458495
496+ Parser . prototype . walkClassDeclaration = function walkClassDeclaration ( statement ) {
497+ this . walkClass ( statement ) ;
498+ } ;
499+
459500Parser . prototype . walkSwitchCases = function walkSwitchCases ( switchCases ) {
460501 switchCases . forEach ( function ( switchCase ) {
461502 if ( switchCase . test )
@@ -464,14 +505,12 @@ Parser.prototype.walkSwitchCases = function walkSwitchCases(switchCases) {
464505 } , this ) ;
465506} ;
466507
467- Parser . prototype . walkCatchClauses = function walkCatchClauses ( catchClauses ) {
468- catchClauses . forEach ( function ( catchClause ) {
469- if ( catchClause . guard )
470- this . walkExpression ( catchClause . guard ) ;
471- this . inScope ( [ catchClause . param ] , function ( ) {
472- this . walkStatement ( catchClause . body ) ;
473- } . bind ( this ) ) ;
474- } , this ) ;
508+ Parser . prototype . walkCatchClause = function walkCatchClause ( catchClause ) {
509+ if ( catchClause . guard )
510+ this . walkExpression ( catchClause . guard ) ;
511+ this . inScope ( [ catchClause . param ] , function ( ) {
512+ this . walkStatement ( catchClause . body ) ;
513+ } . bind ( this ) ) ;
475514} ;
476515
477516Parser . prototype . walkVariableDeclarators = function walkVariableDeclarators ( declarators ) {
@@ -518,8 +557,15 @@ Parser.prototype.walkArrayExpression = function walkArrayExpression(expression)
518557 this . walkExpressions ( expression . elements ) ;
519558} ;
520559
560+ Parser . prototype . walkSpreadElement = function walkSpreadElement ( expression ) {
561+ if ( expression . argument )
562+ this . walkExpression ( expression . argument ) ;
563+ } ;
564+
521565Parser . prototype . walkObjectExpression = function walkObjectExpression ( expression ) {
522566 expression . properties . forEach ( function ( prop ) {
567+ if ( prop . computed )
568+ this . walkExpression ( prop . key )
523569 this . walkExpression ( prop . value ) ;
524570 } , this ) ;
525571} ;
@@ -533,6 +579,15 @@ Parser.prototype.walkFunctionExpression = function walkFunctionExpression(expres
533579 } . bind ( this ) ) ;
534580} ;
535581
582+ Parser . prototype . walkArrowFunctionExpression = function walkArrowFunctionExpression ( expression ) {
583+ this . inScope ( expression . params , function ( ) {
584+ if ( expression . body . type === "BlockStatement" )
585+ this . walkStatement ( expression . body ) ;
586+ else
587+ this . walkExpression ( expression . body ) ;
588+ } . bind ( this ) ) ;
589+ } ;
590+
536591Parser . prototype . walkSequenceExpression = function walkSequenceExpression ( expression ) {
537592 if ( expression . expressions )
538593 this . walkExpressions ( expression . expressions ) ;
@@ -612,6 +667,27 @@ Parser.prototype.walkNewExpression = function walkNewExpression(expression) {
612667 this . walkExpressions ( expression . arguments ) ;
613668} ;
614669
670+ Parser . prototype . walkYieldExpression = function walkYieldExpression ( expression ) {
671+ if ( expression . argument )
672+ this . walkExpression ( expression . argument ) ;
673+ } ;
674+
675+ Parser . prototype . walkTemplateLiteral = function walkTemplateLiteral ( expression ) {
676+ if ( expression . expressions )
677+ this . walkExpressions ( expression . expressions ) ;
678+ } ;
679+
680+ Parser . prototype . walkTaggedTemplateExpression = function walkTaggedTemplateExpression ( expression ) {
681+ if ( expression . tag )
682+ this . walkExpression ( expression . tag ) ;
683+ if ( expression . quasi && expression . quasi . expressions )
684+ this . walkExpressions ( expression . quasi . expressions ) ;
685+ } ;
686+
687+ Parser . prototype . walkClassExpression = function walkClassExpression ( expression ) {
688+ this . walkClass ( expression ) ;
689+ } ;
690+
615691Parser . prototype . walkCallExpression = function walkCallExpression ( expression ) {
616692 function walkIIFE ( functionExpression , args ) {
617693 var params = functionExpression . params ;
@@ -798,12 +874,38 @@ Parser.prototype.parseCalculatedString = function parseCalculatedString(expressi
798874 } ;
799875} ) ;
800876
877+ var POSSIBLE_AST_OPTIONS = [ {
878+ ranges : true ,
879+ locations : true ,
880+ ecmaVersion : 6 ,
881+ sourceType : "module"
882+ } , {
883+ ranges : true ,
884+ locations : true ,
885+ ecmaVersion : 6 ,
886+ sourceType : "script"
887+ } ]
888+
801889Parser . prototype . parse = function parse ( source , initialState ) {
802- var ast = esprima . parse ( source , {
803- range : true ,
804- loc : true ,
805- raw : true
806- } ) ;
890+ var ast ;
891+ for ( var i = 0 ; i < POSSIBLE_AST_OPTIONS . length ; i ++ ) {
892+ if ( ! ast ) {
893+ try {
894+ ast = acorn . parse ( source , POSSIBLE_AST_OPTIONS [ i ] ) ;
895+ } catch ( e ) {
896+ // ignore the error
897+ }
898+ }
899+ }
900+ if ( ! ast ) {
901+ // for the error
902+ ast = acorn . parse ( source , {
903+ ranges : true ,
904+ locations : true ,
905+ ecmaVersion : 6 ,
906+ sourceType : "module"
907+ } ) ;
908+ }
807909 if ( ! ast || typeof ast !== "object" )
808910 throw new Error ( "Source couldn't be parsed" ) ;
809911 var oldScope = this . scope ;
@@ -822,10 +924,11 @@ Parser.prototype.parse = function parse(source, initialState) {
822924} ;
823925
824926Parser . prototype . evaluate = function evaluate ( source ) {
825- var ast = esprima . parse ( "(" + source + ")" , {
826- range : true ,
827- loc : true ,
828- raw : true
927+ var ast = acorn . parse ( "(" + source + ")" , {
928+ ranges : true ,
929+ locations : true ,
930+ ecmaVersion : 6 ,
931+ sourceType : "module"
829932 } ) ;
830933 if ( ! ast || typeof ast !== "object" || ast . type !== "Program" )
831934 throw new Error ( "evaluate: Source couldn't be parsed" ) ;
0 commit comments