@@ -5,122 +5,50 @@ import Signal from '../signal';
5
5
import Environment from '../environment' ;
6
6
import { slice } from '../tool' ;
7
7
8
+ export function VariableDeclaration ( env : Environment < ESTree . VariableDeclaration > ) {
9
+ for ( const declarator of env . node . declarations ) {
10
+ const v = declarator . init ? env . evaluate ( declarator . init ) : undefined ;
11
+ declarePatternValue ( { node : declarator . id , v, env, scope : env . scope , kind : env . node . kind } ) ;
12
+ }
13
+ }
14
+
8
15
export function ObjectExpression ( env : Environment < ESTree . ObjectExpression > ) {
9
16
const obj : { [ key : string ] : any } = { } ;
10
17
11
- for ( const property of env . node . properties ) {
18
+ for ( const prop of env . node . properties ) {
12
19
let key : string ;
13
- if ( ! property . computed ) {
14
- if ( property . key . type === 'Literal' ) {
15
- key = property . key . value as string ;
16
- } else if ( property . key . type === 'Identifier' ) {
17
- key = property . key . name ;
20
+ if ( ! prop . computed ) {
21
+ if ( prop . key . type === 'Identifier' ) {
22
+ key = prop . key . name ;
18
23
} else {
19
- throw new Error ( `evil-eval: [ObjectExpression] Unsupported property key type " ${ property . key . type } "` ) ;
24
+ key = ( < ESTree . Literal > prop . key ) . value as string ;
20
25
}
26
+
21
27
} else {
22
- if ( property . key . type === 'Identifier' ) {
23
- const value = env . scope . get ( property . key . name ) ;
28
+ if ( prop . key . type === 'Identifier' ) {
29
+ const value = env . scope . get ( prop . key . name ) ;
24
30
key = value . v ;
25
31
} else {
26
- key = env . evaluate ( property . key ) ;
32
+ key = env . evaluate ( prop . key ) ;
27
33
}
28
34
}
29
35
30
- const value = env . evaluate ( property . value ) ;
31
- if ( property . kind === 'init' ) {
36
+ const value = env . evaluate ( prop . value ) ;
37
+ if ( prop . kind === 'init' ) {
32
38
obj [ key ] = value ;
33
- } else if ( property . kind === 'get' ) {
39
+ } else if ( prop . kind === 'get' ) {
34
40
Object . defineProperty ( obj , key , { get : value } ) ;
35
- } else if ( property . kind === 'set' ) {
41
+ } else if ( prop . kind === 'set' ) {
36
42
Object . defineProperty ( obj , key , { set : value } ) ;
37
43
} else {
38
- throw new Error ( `evil-eval: [ObjectExpression] Unsupported property kind "${ property . kind } "` ) ;
44
+ throw new Error ( `evil-eval: [ObjectExpression] Unsupported property kind "${ prop . kind } "` ) ;
39
45
}
40
46
}
41
47
42
48
return obj ;
43
49
}
44
50
45
- interface AssignPatternValueOptions < T > {
46
- node : T ;
47
- v : any ;
48
- env : Environment < ESTree . Node > ;
49
- scope : Scope ;
50
- kind ?: 'var' | 'let' | 'const' ;
51
- }
52
-
53
- function assignPatternValue ( options : AssignPatternValueOptions < ESTree . Pattern > ) {
54
- if ( options . node . type === 'ObjectPattern' ) {
55
- assignObjectPatternValue ( < AssignPatternValueOptions < ESTree . ObjectPattern > > options ) ;
56
- } else if ( options . node . type === 'ArrayPattern' ) {
57
- assignArrayPatternValue ( < AssignPatternValueOptions < ESTree . ArrayPattern > > options ) ;
58
- } else {
59
- throw new Error ( `evil-eval` ) ;
60
- }
61
- }
62
- function assignObjectPatternValue ( { node, v : vObj , env, scope, kind } : AssignPatternValueOptions < ESTree . ObjectPattern > ) {
63
- for ( const prop of node . properties ) {
64
- let key : string ;
65
- if ( ! prop . computed ) {
66
- if ( prop . key . type === 'Literal' ) {
67
- key = prop . key . value as string ;
68
- } else {
69
- key = ( < ESTree . Identifier > prop . key ) . name ;
70
- }
71
- } else {
72
- key = env . evaluate ( prop . key ) ;
73
- }
74
-
75
- const v = vObj [ key ] ;
76
-
77
- if ( prop . value . type === 'Identifier' ) {
78
- if ( v === null || v === undefined ) {
79
- throw new TypeError ( `Cannot destructure property \`${ key } \` of 'undefined' or 'null'.` )
80
- }
81
- if ( kind ) {
82
- scope . declare ( prop . value . name , v , kind ) ;
83
- } else {
84
- const value = scope . get ( prop . value . name , true ) ;
85
- value . v = v ;
86
- }
87
- } else {
88
- assignPatternValue ( { node : prop . value , v, env, scope, kind } ) ;
89
- }
90
- }
91
- }
92
-
93
- function assignArrayPatternValue ( { node, v : vArr , env, scope, kind } : AssignPatternValueOptions < ESTree . ArrayPattern > ) {
94
- for ( let i = 0 , l = node . elements . length ; i < l ; i ++ ) {
95
- const element = node . elements [ i ] ;
96
-
97
- let v = vArr [ i ] ;
98
- if ( element . type === 'Identifier' ) {
99
- if ( v === undefined ) {
100
- throw new TypeError ( `Cannot read property 'Symbol(Symbol.iterator)' of undefined` ) ;
101
- } else if ( v === null ) {
102
- throw new TypeError ( `Cannot read property 'Symbol(Symbol.iterator)' of object` ) ;
103
- }
104
- if ( kind ) {
105
- scope . declare ( element . name , v , kind ) ;
106
- } else {
107
- const value = scope . get ( element . name , true ) ;
108
- value . v = v ;
109
- }
110
- } else if ( element . type === 'RestElement' ) {
111
- const name = ( < ESTree . Identifier > element . argument ) . name ;
112
- v = slice . call ( vArr , i ) ;
113
- if ( kind ) {
114
- scope . declare ( name , v , kind ) ;
115
- } else {
116
- const value = scope . get ( name , true ) ;
117
- value . v = v ;
118
- }
119
- } else {
120
- assignPatternValue ( { node : element , v, env, scope, kind } ) ;
121
- }
122
- }
123
- }
51
+ // -- es2015 new feature --
124
52
125
53
export function ForOfStatement ( env : Environment < ESTree . ForOfStatement > ) {
126
54
const { left, right, body } = env . node ;
@@ -133,23 +61,14 @@ export function ForOfStatement(env: Environment<ESTree.ForOfStatement>) {
133
61
}
134
62
135
63
const id = left . declarations [ 0 ] . id ;
136
- if ( id . type === 'Identifier' ) {
137
- // for (let it of list);
138
- scope . declare ( id . name , v , left . kind ) ;
139
- } else {
140
- // for (let { id } of list);
141
- assignPatternValue ( { node : id , v, env, scope, kind : left . kind } ) ;
142
- }
64
+ // for (let it of list);
65
+ // for (let { id } of list);
66
+ declarePatternValue ( { node : id , v, env, scope, kind : left . kind } ) ;
143
67
144
68
} else {
145
- if ( left . type === 'Identifier' ) {
146
- // for (if of list);
147
- const value = scope . get ( left . name , true ) ;
148
- value . v = v ;
149
- } else {
150
- // for ({ id } of list);
151
- assignPatternValue ( { node : left , v, env, scope } ) ;
152
- }
69
+ // for (it of list);
70
+ // for ({ id } of list);
71
+ declarePatternValue ( { node : left , v, env, scope } ) ;
153
72
}
154
73
155
74
const signal : Signal = env . evaluate ( body , { scope } ) ;
@@ -260,3 +179,93 @@ export function ExportDefaultDeclaration(env: Environment<ESTree.ExportDefaultDe
260
179
export function ExportAllDeclaration ( env : Environment < ESTree . ExportAllDeclaration > ) {
261
180
throw new Error ( `evil-eval: "${ env . node . type } " not implemented` ) ;
262
181
}
182
+
183
+ // -- private --
184
+
185
+ interface DeclarePatternValueOptions < T > {
186
+ node : T ;
187
+ v : any ;
188
+ env : Environment < ESTree . Node > ;
189
+ scope : Scope ;
190
+ kind ?: 'var' | 'let' | 'const' ;
191
+ }
192
+
193
+ function declarePatternValue ( options : DeclarePatternValueOptions < ESTree . Pattern > ) {
194
+ if ( options . node . type === 'Identifier' ) {
195
+ if ( options . kind ) {
196
+ options . scope . declare ( options . node . name , options . v , options . kind ) ;
197
+ } else {
198
+ const value = options . scope . get ( options . node . name , true ) ;
199
+ value . v = options . v ;
200
+ }
201
+ } else if ( options . node . type === 'ObjectPattern' ) {
202
+ declareObjectPatternValue ( < DeclarePatternValueOptions < ESTree . ObjectPattern > > options ) ;
203
+ } else if ( options . node . type === 'ArrayPattern' ) {
204
+ declareArrayPatternValue ( < DeclarePatternValueOptions < ESTree . ArrayPattern > > options ) ;
205
+ } else {
206
+ throw new Error ( `evil-eval: Not support to declare pattern value of node type "${ options . node . type } "` ) ;
207
+ }
208
+ }
209
+
210
+ function declareObjectPatternValue ( { node, v : vObj , env, scope, kind } : DeclarePatternValueOptions < ESTree . ObjectPattern > ) {
211
+ for ( const prop of node . properties ) {
212
+ let key : string ;
213
+ if ( ! prop . computed ) {
214
+ if ( prop . key . type === 'Identifier' ) {
215
+ key = prop . key . name ;
216
+ } else {
217
+ key = ( < ESTree . Literal > prop . key ) . value as string ;
218
+ }
219
+ } else {
220
+ key = env . evaluate ( prop . key ) ;
221
+ }
222
+
223
+ const v = vObj [ key ] ;
224
+
225
+ if ( prop . value . type === 'Identifier' ) {
226
+ if ( v === null || v === undefined ) {
227
+ throw new TypeError ( `Cannot destructure property \`${ key } \` of 'undefined' or 'null'.` )
228
+ }
229
+ if ( kind ) {
230
+ scope . declare ( prop . value . name , v , kind ) ;
231
+ } else {
232
+ const value = scope . get ( prop . value . name , true ) ;
233
+ value . v = v ;
234
+ }
235
+ } else {
236
+ declarePatternValue ( { node : prop . value , v, env, scope, kind } ) ;
237
+ }
238
+ }
239
+ }
240
+
241
+ function declareArrayPatternValue ( { node, v : vArr , env, scope, kind } : DeclarePatternValueOptions < ESTree . ArrayPattern > ) {
242
+ for ( let i = 0 , l = node . elements . length ; i < l ; i ++ ) {
243
+ const element = node . elements [ i ] ;
244
+
245
+ let v = vArr [ i ] ;
246
+ if ( element . type === 'Identifier' ) {
247
+ if ( v === undefined ) {
248
+ throw new TypeError ( `Cannot read property 'Symbol(Symbol.iterator)' of undefined` ) ;
249
+ } else if ( v === null ) {
250
+ throw new TypeError ( `Cannot read property 'Symbol(Symbol.iterator)' of object` ) ;
251
+ }
252
+ if ( kind ) {
253
+ scope . declare ( element . name , v , kind ) ;
254
+ } else {
255
+ const value = scope . get ( element . name , true ) ;
256
+ value . v = v ;
257
+ }
258
+ } else if ( element . type === 'RestElement' ) {
259
+ const name = ( < ESTree . Identifier > element . argument ) . name ;
260
+ v = slice . call ( vArr , i ) ;
261
+ if ( kind ) {
262
+ scope . declare ( name , v , kind ) ;
263
+ } else {
264
+ const value = scope . get ( name , true ) ;
265
+ value . v = v ;
266
+ }
267
+ } else {
268
+ declarePatternValue ( { node : element , v, env, scope, kind } ) ;
269
+ }
270
+ }
271
+ }
0 commit comments