@@ -89,10 +89,16 @@ public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
89
89
classStack .push (new ClassRecord (n , classNameNode .getQualifiedName (), classInsertionPoint ));
90
90
break ;
91
91
case COMPUTED_FIELD_DEF :
92
+ if (NodeUtil .canBeSideEffected (n .getFirstChild ())) {
93
+ t .report (
94
+ n ,
95
+ TranspilationUtil .CANNOT_CONVERT_YET ,
96
+ "Class contains computed field with possible side effects" );
97
+ return false ;
98
+ }
92
99
checkState (!classStack .isEmpty ());
93
- t .report (n , TranspilationUtil .CANNOT_CONVERT_YET , "Computed fields" );
94
- classStack .peek ().cannotConvert = true ;
95
- return false ;
100
+ classStack .peek ().enterField (n );
101
+ break ;
96
102
case MEMBER_FIELD_DEF :
97
103
checkState (!classStack .isEmpty ());
98
104
classStack .peek ().enterField (n );
@@ -145,12 +151,14 @@ public void visit(NodeTraversal t, Node n, Node parent) {
145
151
case CLASS :
146
152
visitClass (t );
147
153
return ;
154
+ case COMPUTED_FIELD_DEF :
148
155
case MEMBER_FIELD_DEF :
149
156
classStack .peek ().exitField ();
150
157
return ;
151
158
case THIS :
152
159
Node rootNode = t .getClosestScopeRootNodeBindingThisOrSuper ();
153
- if (rootNode .isMemberFieldDef () && rootNode .isStaticMember ()) {
160
+ if (rootNode .isStaticMember ()
161
+ && (rootNode .isMemberFieldDef () || rootNode .isComputedFieldDef ())) {
154
162
Node className = rootNode .getGrandparent ().getFirstChild ().cloneNode ();
155
163
n .replaceWith (className );
156
164
t .reportCodeChange (className );
@@ -195,7 +203,8 @@ private void rewriteInstanceMembers(NodeTraversal t, ClassRecord record) {
195
203
196
204
while (!instanceMembers .isEmpty ()) {
197
205
Node instanceMember = instanceMembers .pop ();
198
- checkState (instanceMember .isMemberFieldDef ());
206
+ checkState (
207
+ instanceMember .isMemberFieldDef () || instanceMember .isComputedFieldDef (), instanceMember );
199
208
200
209
for (Node nameInRhs : record .referencedNamesByMember .get (instanceMember )) {
201
210
String name = nameInRhs .getString ();
@@ -209,8 +218,10 @@ private void rewriteInstanceMembers(NodeTraversal t, ClassRecord record) {
209
218
}
210
219
211
220
Node thisNode = astFactory .createThisForEs6ClassMember (instanceMember );
212
-
213
- Node transpiledNode = convNonCompFieldToGetProp (thisNode , instanceMember .detach ());
221
+ Node transpiledNode =
222
+ instanceMember .isMemberFieldDef ()
223
+ ? convNonCompFieldToGetProp (thisNode , instanceMember .detach ())
224
+ : convCompFieldToGetElem (thisNode , instanceMember .detach ());
214
225
if (insertionPoint == ctorBlock ) { // insert the field at the beginning of the block, no super
215
226
ctorBlock .addChildToFront (transpiledNode );
216
227
} else {
@@ -244,6 +255,9 @@ private void rewriteStaticMembers(NodeTraversal t, ClassRecord record) {
244
255
case MEMBER_FIELD_DEF :
245
256
transpiledNode = convNonCompFieldToGetProp (nameToUse , staticMember .detach ());
246
257
break ;
258
+ case COMPUTED_FIELD_DEF :
259
+ transpiledNode = convCompFieldToGetElem (nameToUse , staticMember .detach ());
260
+ break ;
247
261
default :
248
262
throw new IllegalStateException (String .valueOf (staticMember ));
249
263
}
@@ -272,6 +286,24 @@ private Node convNonCompFieldToGetProp(Node receiver, Node noncomputedField) {
272
286
return result ;
273
287
}
274
288
289
+ /**
290
+ * Creates a node that represents receiver[key] = value; where the key and value comes from the
291
+ * computed field
292
+ */
293
+ private Node convCompFieldToGetElem (Node receiver , Node computedField ) {
294
+ checkArgument (computedField .isComputedFieldDef (), computedField );
295
+ checkArgument (computedField .getParent () == null , computedField );
296
+ checkArgument (receiver .getParent () == null , receiver );
297
+ Node getElem = astFactory .createGetElem (receiver , computedField .getFirstChild ().detach ());
298
+ Node fieldValue = computedField .getLastChild ();
299
+ Node result =
300
+ (fieldValue != null )
301
+ ? astFactory .createAssignStatement (getElem , fieldValue .detach ())
302
+ : astFactory .exprResult (getElem );
303
+ result .srcrefTreeIfMissing (computedField );
304
+ return result ;
305
+ }
306
+
275
307
/**
276
308
* Finds the location in the constructor to put the transpiled instance fields
277
309
*
@@ -378,7 +410,8 @@ void potentiallyRecordNameInRhs(Node nameNode) {
378
410
if (currentMember == null ) {
379
411
return ;
380
412
}
381
- checkState (currentMember .isMemberFieldDef ());
413
+ checkState (
414
+ currentMember .isMemberFieldDef () || currentMember .isComputedFieldDef (), currentMember );
382
415
referencedNamesByMember .put (currentMember , nameNode );
383
416
}
384
417
0 commit comments