2
2
MIT License http://www.opensource.org/licenses/mit-license.php
3
3
Author Tobias Koppers @sokra
4
4
*/
5
- var esprima = require ( "esprima " ) ;
5
+ var acorn = require ( "acorn " ) ;
6
6
var Tapable = require ( "tapable" ) ;
7
7
var BasicEvaluatedExpression = require ( "./BasicEvaluatedExpression" ) ;
8
8
@@ -39,28 +39,34 @@ Parser.prototype.initializeEvaluating = function() {
39
39
return new BasicEvaluatedExpression ( ) . setRegExp ( expr . value ) . setRange ( expr . range ) ;
40
40
} ) ;
41
41
this . plugin ( "evaluate LogicalExpression" , function ( expr ) {
42
+ var left ;
43
+ var leftAsBool ;
44
+ var right ;
42
45
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 ( ) ;
45
48
if ( leftAsBool === false ) return left . setRange ( expr . range ) ;
46
49
if ( leftAsBool !== true ) return ;
47
- var right = this . evaluateExpression ( expr . right ) ;
50
+ right = this . evaluateExpression ( expr . right ) ;
48
51
return right . setRange ( expr . range ) ;
49
52
} 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 ( ) ;
52
55
if ( leftAsBool === true ) return left . setRange ( expr . range ) ;
53
56
if ( leftAsBool !== false ) return ;
54
- var right = this . evaluateExpression ( expr . right ) ;
57
+ right = this . evaluateExpression ( expr . right ) ;
55
58
return right . setRange ( expr . range ) ;
56
59
}
57
60
} ) ;
58
61
this . plugin ( "evaluate BinaryExpression" , function ( expr ) {
62
+ var left ;
63
+ var right ;
64
+ var res ;
59
65
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 ) ;
62
68
if ( ! left || ! right ) return ;
63
- var res = new BasicEvaluatedExpression ( ) ;
69
+ res = new BasicEvaluatedExpression ( ) ;
64
70
if ( left . isString ( ) ) {
65
71
if ( right . isString ( ) ) {
66
72
res . setString ( left . string + right . string ) ;
@@ -112,37 +118,37 @@ Parser.prototype.initializeEvaluating = function() {
112
118
res . setRange ( expr . range ) ;
113
119
return res ;
114
120
} 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 ) ;
117
123
if ( ! left || ! right ) return ;
118
124
if ( ! left . isNumber ( ) || ! right . isNumber ( ) ) return ;
119
- var res = new BasicEvaluatedExpression ( ) ;
125
+ res = new BasicEvaluatedExpression ( ) ;
120
126
res . setNumber ( left . number - right . number ) ;
121
127
res . setRange ( expr . range ) ;
122
128
return res ;
123
129
} 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 ) ;
126
132
if ( ! left || ! right ) return ;
127
133
if ( ! left . isNumber ( ) || ! right . isNumber ( ) ) return ;
128
- var res = new BasicEvaluatedExpression ( ) ;
134
+ res = new BasicEvaluatedExpression ( ) ;
129
135
res . setNumber ( left . number * right . number ) ;
130
136
res . setRange ( expr . range ) ;
131
137
return res ;
132
138
} 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 ) ;
135
141
if ( ! left || ! right ) return ;
136
142
if ( ! left . isNumber ( ) || ! right . isNumber ( ) ) return ;
137
- var res = new BasicEvaluatedExpression ( ) ;
143
+ res = new BasicEvaluatedExpression ( ) ;
138
144
res . setNumber ( left . number / right . number ) ;
139
145
res . setRange ( expr . range ) ;
140
146
return res ;
141
147
} 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 ) ;
144
150
if ( ! left || ! right ) return ;
145
- var res = new BasicEvaluatedExpression ( ) ;
151
+ res = new BasicEvaluatedExpression ( ) ;
146
152
res . setRange ( expr . range ) ;
147
153
if ( left . isString ( ) && right . isString ( ) ) {
148
154
return res . setBoolean ( left . string === right . string ) ;
@@ -152,10 +158,10 @@ Parser.prototype.initializeEvaluating = function() {
152
158
return res . setBoolean ( left . bool === right . bool ) ;
153
159
}
154
160
} 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 ) ;
157
163
if ( ! left || ! right ) return ;
158
- var res = new BasicEvaluatedExpression ( ) ;
164
+ res = new BasicEvaluatedExpression ( ) ;
159
165
res . setRange ( expr . range ) ;
160
166
if ( left . isString ( ) && right . isString ( ) ) {
161
167
return res . setBoolean ( left . string !== right . string ) ;
@@ -168,10 +174,11 @@ Parser.prototype.initializeEvaluating = function() {
168
174
} ) ;
169
175
this . plugin ( "evaluate UnaryExpression" , function ( expr ) {
170
176
if ( expr . operator === "typeof" ) {
177
+ var res ;
171
178
if ( expr . argument . type === "Identifier" ) {
172
179
var name = this . scope . renames [ "$" + expr . argument . name ] || expr . argument . name ;
173
180
if ( this . scope . definitions . indexOf ( name ) === - 1 ) {
174
- var res = this . applyPluginsBailResult ( "evaluate typeof " + name , expr ) ;
181
+ res = this . applyPluginsBailResult ( "evaluate typeof " + name , expr ) ;
175
182
if ( res !== undefined ) return res ;
176
183
}
177
184
}
@@ -186,7 +193,7 @@ Parser.prototype.initializeEvaluating = function() {
186
193
exprName . unshift ( this . scope . renames [ "$" + expression . name ] || expression . name ) ;
187
194
if ( this . scope . definitions . indexOf ( name ) === - 1 ) {
188
195
exprName = exprName . join ( "." ) ;
189
- var res = this . applyPluginsBailResult ( "evaluate typeof " + exprName , expr ) ;
196
+ res = this . applyPluginsBailResult ( "evaluate typeof " + exprName , expr ) ;
190
197
if ( res !== undefined ) return res ;
191
198
}
192
199
}
@@ -267,15 +274,16 @@ Parser.prototype.initializeEvaluating = function() {
267
274
[ "substr" , "substring" ] . forEach ( function ( fn ) {
268
275
this . plugin ( "evaluate CallExpression ." + fn , function ( expr , param ) {
269
276
if ( ! param . isString ( ) ) return ;
277
+ var arg1 ;
270
278
var result , str = param . string ;
271
279
switch ( expr . arguments . length ) {
272
280
case 1 :
273
- var arg1 = this . evaluateExpression ( expr . arguments [ 0 ] ) ;
281
+ arg1 = this . evaluateExpression ( expr . arguments [ 0 ] ) ;
274
282
if ( ! arg1 . isNumber ( ) ) return ;
275
283
result = str [ fn ] ( arg1 . number ) ;
276
284
break ;
277
285
case 2 :
278
- var arg1 = this . evaluateExpression ( expr . arguments [ 0 ] ) ;
286
+ arg1 = this . evaluateExpression ( expr . arguments [ 0 ] ) ;
279
287
var arg2 = this . evaluateExpression ( expr . arguments [ 1 ] ) ;
280
288
if ( ! arg1 . isNumber ( ) ) return ;
281
289
if ( ! arg2 . isNumber ( ) ) return ;
@@ -302,11 +310,12 @@ Parser.prototype.initializeEvaluating = function() {
302
310
this . plugin ( "evaluate ConditionalExpression" , function ( expr ) {
303
311
var condition = this . evaluateExpression ( expr . test ) ;
304
312
var conditionValue = condition . asBool ( ) ;
313
+ var res ;
305
314
if ( conditionValue === undefined ) {
306
315
var consequent = this . evaluateExpression ( expr . consequent ) ;
307
316
var alternate = this . evaluateExpression ( expr . alternate ) ;
308
317
if ( ! consequent || ! alternate ) return ;
309
- var res = new BasicEvaluatedExpression ( ) ;
318
+ res = new BasicEvaluatedExpression ( ) ;
310
319
if ( consequent . isConditional ( ) )
311
320
res . setOptions ( consequent . options ) ;
312
321
else
@@ -316,7 +325,7 @@ Parser.prototype.initializeEvaluating = function() {
316
325
else
317
326
res . addOptions ( [ alternate ] ) ;
318
327
} else {
319
- var res = this . evaluateExpression ( conditionValue ? expr . consequent : expr . alternate ) ;
328
+ res = this . evaluateExpression ( conditionValue ? expr . consequent : expr . alternate ) ;
320
329
}
321
330
res . setRange ( expr . range ) ;
322
331
return res ;
@@ -339,6 +348,24 @@ Parser.prototype.getRenameIdentifier = function getRenameIdentifier(expr) {
339
348
return ;
340
349
} ;
341
350
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
+
342
369
Parser . prototype . walkStatements = function walkStatements ( statements ) {
343
370
statements . forEach ( function ( statement ) {
344
371
this . walkStatement ( statement ) ;
@@ -405,7 +432,8 @@ Parser.prototype.walkTryStatement = function walkTryStatement(statement) {
405
432
this . walkStatement ( statement . block ) ;
406
433
this . scope . inTry = false ;
407
434
}
408
- this . walkCatchClauses ( statement . handlers ) ;
435
+ if ( statement . handler )
436
+ this . walkCatchClause ( statement . handler ) ;
409
437
if ( statement . finalizer )
410
438
this . walkStatement ( statement . finalizer ) ;
411
439
} ;
@@ -439,6 +467,15 @@ Parser.prototype.walkForInStatement = function walkForInStatement(statement) {
439
467
this . walkStatement ( statement . body ) ;
440
468
} ;
441
469
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
+
442
479
// Declarations
443
480
Parser . prototype . walkFunctionDeclaration = function walkFunctionDeclaration ( statement ) {
444
481
this . scope . renames [ "$" + statement . id . name ] = undefined ;
@@ -456,6 +493,10 @@ Parser.prototype.walkVariableDeclaration = function walkVariableDeclaration(stat
456
493
this . walkVariableDeclarators ( statement . declarations ) ;
457
494
} ;
458
495
496
+ Parser . prototype . walkClassDeclaration = function walkClassDeclaration ( statement ) {
497
+ this . walkClass ( statement ) ;
498
+ } ;
499
+
459
500
Parser . prototype . walkSwitchCases = function walkSwitchCases ( switchCases ) {
460
501
switchCases . forEach ( function ( switchCase ) {
461
502
if ( switchCase . test )
@@ -464,14 +505,12 @@ Parser.prototype.walkSwitchCases = function walkSwitchCases(switchCases) {
464
505
} , this ) ;
465
506
} ;
466
507
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 ) ) ;
475
514
} ;
476
515
477
516
Parser . prototype . walkVariableDeclarators = function walkVariableDeclarators ( declarators ) {
@@ -518,8 +557,15 @@ Parser.prototype.walkArrayExpression = function walkArrayExpression(expression)
518
557
this . walkExpressions ( expression . elements ) ;
519
558
} ;
520
559
560
+ Parser . prototype . walkSpreadElement = function walkSpreadElement ( expression ) {
561
+ if ( expression . argument )
562
+ this . walkExpression ( expression . argument ) ;
563
+ } ;
564
+
521
565
Parser . prototype . walkObjectExpression = function walkObjectExpression ( expression ) {
522
566
expression . properties . forEach ( function ( prop ) {
567
+ if ( prop . computed )
568
+ this . walkExpression ( prop . key )
523
569
this . walkExpression ( prop . value ) ;
524
570
} , this ) ;
525
571
} ;
@@ -533,6 +579,15 @@ Parser.prototype.walkFunctionExpression = function walkFunctionExpression(expres
533
579
} . bind ( this ) ) ;
534
580
} ;
535
581
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
+
536
591
Parser . prototype . walkSequenceExpression = function walkSequenceExpression ( expression ) {
537
592
if ( expression . expressions )
538
593
this . walkExpressions ( expression . expressions ) ;
@@ -612,6 +667,27 @@ Parser.prototype.walkNewExpression = function walkNewExpression(expression) {
612
667
this . walkExpressions ( expression . arguments ) ;
613
668
} ;
614
669
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
+
615
691
Parser . prototype . walkCallExpression = function walkCallExpression ( expression ) {
616
692
function walkIIFE ( functionExpression , args ) {
617
693
var params = functionExpression . params ;
@@ -798,12 +874,38 @@ Parser.prototype.parseCalculatedString = function parseCalculatedString(expressi
798
874
} ;
799
875
} ) ;
800
876
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
+
801
889
Parser . 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
+ }
807
909
if ( ! ast || typeof ast !== "object" )
808
910
throw new Error ( "Source couldn't be parsed" ) ;
809
911
var oldScope = this . scope ;
@@ -822,10 +924,11 @@ Parser.prototype.parse = function parse(source, initialState) {
822
924
} ;
823
925
824
926
Parser . 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"
829
932
} ) ;
830
933
if ( ! ast || typeof ast !== "object" || ast . type !== "Program" )
831
934
throw new Error ( "evaluate: Source couldn't be parsed" ) ;
0 commit comments