1
+ export const PLUS_CODE = 43 ; // +
2
+ export const MINUS_CODE = 45 ; // -
3
+
4
+ const plugin = {
5
+ name : 'assignment' ,
6
+
7
+ assignmentOperators : new Set ( [
8
+ '=' ,
9
+ '*=' ,
10
+ '**=' ,
11
+ '/=' ,
12
+ '%=' ,
13
+ '+=' ,
14
+ '-=' ,
15
+ '<<=' ,
16
+ '>>=' ,
17
+ '>>>=' ,
18
+ '&=' ,
19
+ '^=' ,
20
+ '|=' ,
21
+ ] ) ,
22
+ updateOperators : [ PLUS_CODE , MINUS_CODE ] ,
23
+ assignmentPrecedence : 0.9 ,
24
+
25
+ init ( jsep ) {
26
+ const updateNodeTypes = [ jsep . IDENTIFIER , jsep . MEMBER_EXP ] ;
27
+ plugin . assignmentOperators . forEach ( op => jsep . addBinaryOp ( op , plugin . assignmentPrecedence , true ) ) ;
28
+
29
+ jsep . hooks . add ( 'gobble-token' , function gobbleUpdatePrefix ( env ) {
30
+ const code = this . code ;
31
+ if ( plugin . updateOperators . some ( c => c === code && c === this . expr . charCodeAt ( this . index + 1 ) ) ) {
32
+ this . index += 2 ;
33
+ env . node = {
34
+ type : 'UpdateExpression' ,
35
+ operator : code === PLUS_CODE ? '++' : '--' ,
36
+ argument : this . gobbleTokenProperty ( this . gobbleIdentifier ( ) ) ,
37
+ prefix : true ,
38
+ } ;
39
+ if ( ! env . node . argument || ! updateNodeTypes . includes ( env . node . argument . type ) ) {
40
+ this . throwError ( `Unexpected ${ env . node . operator } ` ) ;
41
+ }
42
+ }
43
+ } ) ;
44
+
45
+ jsep . hooks . add ( 'after-token' , function gobbleUpdatePostfix ( env ) {
46
+ if ( env . node ) {
47
+ const code = this . code ;
48
+ if ( plugin . updateOperators . some ( c => c === code && c === this . expr . charCodeAt ( this . index + 1 ) ) ) {
49
+ if ( ! updateNodeTypes . includes ( env . node . type ) ) {
50
+ this . throwError ( `Unexpected ${ env . node . operator } ` ) ;
51
+ }
52
+ this . index += 2 ;
53
+ env . node = {
54
+ type : 'UpdateExpression' ,
55
+ operator : code === PLUS_CODE ? '++' : '--' ,
56
+ argument : env . node ,
57
+ prefix : false ,
58
+ } ;
59
+ }
60
+ }
61
+ } ) ;
62
+
63
+ jsep . hooks . add ( 'after-expression' , function gobbleAssignment ( env ) {
64
+ if ( env . node ) {
65
+ // Note: Binaries can be chained in a single expression to respect
66
+ // operator precedence (i.e. a = b = 1 + 2 + 3)
67
+ // Update all binary assignment nodes in the tree
68
+ updateBinariesToAssignments ( env . node ) ;
69
+ }
70
+ } ) ;
71
+
72
+ function updateBinariesToAssignments ( node ) {
73
+ if ( plugin . assignmentOperators . has ( node . operator ) ) {
74
+ node . type = 'AssignmentExpression' ;
75
+ updateBinariesToAssignments ( node . left ) ;
76
+ updateBinariesToAssignments ( node . right ) ;
77
+ }
78
+ else if ( ! node . operator ) {
79
+ Object . values ( node ) . forEach ( ( val ) => {
80
+ if ( val && typeof val === 'object' ) {
81
+ updateBinariesToAssignments ( val ) ;
82
+ }
83
+ } ) ;
84
+ }
85
+ }
86
+ } ,
87
+ } ;
88
+ export default plugin ;
0 commit comments