Skip to content

Commit 9f64bb1

Browse files
lauraharkercopybara-github
authored andcommitted
Make generator transpilation compatible with @closureUnaware transpilation
Note: this CL is expected to increase code size for projects targeting ECMASCRIPT5, as generator_engine.js now exports more properties for use in non-property-renaming-safe code. PiperOrigin-RevId: 853290695
1 parent ca89f69 commit 9f64bb1

File tree

5 files changed

+205
-134
lines changed

5 files changed

+205
-134
lines changed

src/com/google/javascript/jscomp/Es6RewriteGenerators.java

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ public void transpile() {
327327

328328
// $jscomp.asyncExecutePromiseGeneratorFunction
329329
Node callTarget = generatorFunction.getPrevious();
330-
checkState(callTarget.isGetProp());
330+
checkState(callTarget.isGetProp() || callTarget.isName(), callTarget);
331331

332332
// Use original async function as a hoist block for local generator variables:
333333
// generator function -> call -> return -> async function body
@@ -1272,47 +1272,53 @@ public void finalizeTransformation(Node generatorBody) {
12721272
optimizeCaseIds();
12731273

12741274
// If number of cases is small we render them without using "switch"
1275-
// switch ($context.nextAddress) {
1275+
// switch ($context.getNextAddress()) {
12761276
// case 1: a();
12771277
// case 2: b();
12781278
// case 3: c();
12791279
// }
12801280
// are rendered as:
1281-
// if ($context.nextAddress == 1) a();
1282-
// if ($context.nextAddress != 3) b();
1281+
// if ($context.getNextAddress() == 1) a();
1282+
// if ($context.getNextAddress() != 3) b();
12831283
// c();
12841284
if (allCases.size() == 2 || allCases.size() == 3) {
12851285
generatorBody.addChildToBack(
12861286
astFactory
12871287
.createIf(
12881288
astFactory.createEq(
1289-
getContextField(generatorBody, "nextAddress"),
1289+
callContextMethod(
1290+
generatorBody,
1291+
"getNextAddress",
1292+
type(JSTypeNative.NUMBER_TYPE, StandardColors.NUMBER)),
12901293
astFactory.createNumber(1)),
12911294
allCases.remove(0).caseBlock)
12921295
.srcrefTreeIfMissing(generatorBody));
12931296
}
12941297

12951298
// If number of cases is small we render them without using "switch"
1296-
// switch ($context.nextAddress) {
1299+
// switch ($context.getNextAddress()) {
12971300
// case 1: a();
12981301
// case 2: b();
12991302
// }
13001303
// are rendered as:
1301-
// if ($context.nextAddress == 1) a();
1304+
// if ($context.getNextAddress() == 1) a();
13021305
// b();
13031306
if (allCases.size() == 2) {
13041307
generatorBody.addChildToBack(
13051308
astFactory
13061309
.createIf(
13071310
astFactory.createNe(
1308-
getContextField(generatorBody, "nextAddress"),
1311+
callContextMethod(
1312+
generatorBody,
1313+
"getNextAddress",
1314+
type(JSTypeNative.NUMBER_TYPE, StandardColors.NUMBER)),
13091315
astFactory.createNumber(allCases.get(1).id)),
13101316
allCases.remove(0).caseBlock)
13111317
.srcrefTreeIfMissing(generatorBody));
13121318
}
13131319

13141320
// If number of cases is small we render them without using "switch"
1315-
// switch ($context.nextAddress) {
1321+
// switch ($context.getNextAddress()) {
13161322
// case 1: a();
13171323
// }
13181324
// are rendered as:
@@ -1323,9 +1329,14 @@ public void finalizeTransformation(Node generatorBody) {
13231329
return;
13241330
}
13251331

1326-
// switch ($jscomp$generator$context.nextAddress) {}
1332+
// switch ($jscomp$generator$context.getNextAddress()) {}
13271333
Node switchNode =
1328-
IR.switchNode(getContextField(generatorBody, "nextAddress")).srcref(generatorBody);
1334+
IR.switchNode(
1335+
callContextMethod(
1336+
generatorBody,
1337+
"getNextAddress",
1338+
type(JSTypeNative.NUMBER_TYPE, StandardColors.NUMBER)))
1339+
.srcref(generatorBody);
13291340
generatorBody.addChildToBack(switchNode);
13301341
Node switchBody = switchNode.getSecondChild().srcref(generatorBody);
13311342

@@ -1578,7 +1589,7 @@ Node returnExpression(Node sourceNode, @Nullable Node expression) {
15781589

15791590
/** Instructs a state machine program to consume a yield result after yielding. */
15801591
Node yieldResult(Node sourceNode) {
1581-
return getContextField(sourceNode, "yieldResult");
1592+
return callContextMethod(sourceNode, "getYieldResult", type(StandardColors.UNKNOWN));
15821593
}
15831594

15841595
/** Adds references to catch and finally blocks to the transpilation context. */

src/com/google/javascript/jscomp/js/es6/generator_engine.js

Lines changed: 80 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
* return $jscomp.generator.createGenerator(
5656
* es3Definition,
5757
* function (context$) {
58-
* switch (context$.nextAddress) {
58+
* switch (context$.nextAddress_) {
5959
* case 1: // execution always starts with 1
6060
* currentValue = start;
6161
* yieldCount = 0;
@@ -154,18 +154,18 @@ $jscomp.generator.Context = function() {
154154
* The value that will be sent to the program as the result of suspended
155155
* yield expression.
156156
*
157-
* @type {?}
157+
* @private {?}
158158
*/
159-
this.yieldResult = undefined;
159+
this.yieldResult_ = undefined;
160160

161161
/**
162162
* The next address where the state machine execution should be resumed.
163163
*
164164
* <p>Program execution starts at 1 and ends at 0.
165165
*
166-
* @type {number}
166+
* @private {number}
167167
*/
168-
this.nextAddress = 1;
168+
this.nextAddress_ = 1;
169169

170170
/**
171171
* The address that should be executed once an exception is thrown.
@@ -257,7 +257,7 @@ $jscomp.generator.Context.prototype.stop_ = function() {
257257
* @return {void}
258258
*/
259259
$jscomp.generator.Context.prototype.jumpToErrorHandler_ = function() {
260-
this.nextAddress = this.catchAddress_ || this.finallyAddress_;
260+
this.nextAddress_ = this.catchAddress_ || this.finallyAddress_;
261261
};
262262

263263
/**
@@ -270,7 +270,7 @@ $jscomp.generator.Context.prototype.jumpToErrorHandler_ = function() {
270270
* @suppress {reportUnknownTypes}
271271
*/
272272
$jscomp.generator.Context.prototype.next_ = function(value) {
273-
this.yieldResult = value;
273+
this.yieldResult_ = value;
274274
};
275275

276276
/**
@@ -287,6 +287,34 @@ $jscomp.generator.Context.prototype.throw_ = function(e) {
287287
this.jumpToErrorHandler_();
288288
};
289289

290+
/** Public methods */
291+
292+
/**
293+
* Returns the next address in the state machine.
294+
*
295+
* @final
296+
* @return {number}
297+
*/
298+
$jscomp.generator.Context.prototype.getNextAddress = function() {
299+
return this.nextAddress_;
300+
};
301+
302+
$jscomp.generator.Context.prototype['getNextAddress'] =
303+
$jscomp.generator.Context.prototype.getNextAddress;
304+
305+
/**
306+
* Returns the value that was set by the last yield expression.
307+
*
308+
* @final
309+
* @return {number}
310+
*/
311+
$jscomp.generator.Context.prototype.getYieldResult = function() {
312+
return this.yieldResult_;
313+
};
314+
315+
$jscomp.generator.Context.prototype['getYieldResult'] =
316+
$jscomp.generator.Context.prototype.getYieldResult;
317+
290318
/**
291319
* Returns a value as the result of generator function.
292320
*
@@ -297,9 +325,12 @@ $jscomp.generator.Context.prototype.throw_ = function(e) {
297325
*/
298326
$jscomp.generator.Context.prototype.return = function(value) {
299327
this.abruptCompletion_ = {return: /** @type {VALUE} */ (value)};
300-
this.nextAddress = this.finallyAddress_;
328+
this.nextAddress_ = this.finallyAddress_;
301329
};
302330

331+
$jscomp.generator.Context.prototype['return'] =
332+
$jscomp.generator.Context.prototype.return;
333+
303334
/**
304335
* Changes the context so the program execution will continue from the given
305336
* state after executing nessesary pending finally blocks first.
@@ -311,8 +342,10 @@ $jscomp.generator.Context.prototype.return = function(value) {
311342
$jscomp.generator.Context.prototype.jumpThroughFinallyBlocks = function(
312343
nextAddress) {
313344
this.abruptCompletion_ = {jumpTo: nextAddress};
314-
this.nextAddress = this.finallyAddress_;
345+
this.nextAddress_ = this.finallyAddress_;
315346
};
347+
$jscomp.generator.Context.prototype['jumpThroughFinallyBlocks'] =
348+
$jscomp.generator.Context.prototype.jumpThroughFinallyBlocks;
316349

317350
/**
318351
* Pauses the state machine program assosiated with generator function to yield
@@ -326,9 +359,11 @@ $jscomp.generator.Context.prototype.jumpThroughFinallyBlocks = function(
326359
* @suppress {reportUnknownTypes}
327360
*/
328361
$jscomp.generator.Context.prototype.yield = function(value, resumeAddress) {
329-
this.nextAddress = resumeAddress;
362+
this.nextAddress_ = resumeAddress;
330363
return {value: value};
331364
};
365+
$jscomp.generator.Context.prototype['yield'] =
366+
$jscomp.generator.Context.prototype.yield;
332367

333368
/**
334369
* Causes the state machine program to yield all values from an iterator.
@@ -349,13 +384,15 @@ $jscomp.generator.Context.prototype.yieldAll = function(
349384
if (result.done) {
350385
// If `someGenerator` in `x = yield *someGenerator` completes immediately,
351386
// x is the return value of that generator.
352-
this.yieldResult = result.value;
353-
this.nextAddress = resumeAddress;
387+
this.yieldResult_ = result.value;
388+
this.nextAddress_ = resumeAddress;
354389
return;
355390
}
356391
this.yieldAllIterator_ = iterator;
357392
return this.yield(result.value, resumeAddress);
358393
};
394+
$jscomp.generator.Context.prototype['yieldAll'] =
395+
$jscomp.generator.Context.prototype.yieldAll;
359396

360397
/**
361398
* Changes the context so the program execution will continue from the given
@@ -366,8 +403,10 @@ $jscomp.generator.Context.prototype.yieldAll = function(
366403
* @return {void}
367404
*/
368405
$jscomp.generator.Context.prototype.jumpTo = function(nextAddress) {
369-
this.nextAddress = nextAddress;
406+
this.nextAddress_ = nextAddress;
370407
};
408+
$jscomp.generator.Context.prototype['jumpTo'] =
409+
$jscomp.generator.Context.prototype.jumpTo;
371410

372411
/**
373412
* Changes the context so the program execution ends.
@@ -376,8 +415,10 @@ $jscomp.generator.Context.prototype.jumpTo = function(nextAddress) {
376415
* @return {void}
377416
*/
378417
$jscomp.generator.Context.prototype.jumpToEnd = function() {
379-
this.nextAddress = 0;
418+
this.nextAddress_ = 0;
380419
};
420+
$jscomp.generator.Context.prototype['jumpToEnd'] =
421+
$jscomp.generator.Context.prototype.jumpToEnd;
381422

382423
/**
383424
* Sets catch / finally handlers.
@@ -395,6 +436,8 @@ $jscomp.generator.Context.prototype.setCatchFinallyBlocks = function(
395436
this.finallyAddress_ = finallyAddress;
396437
}
397438
};
439+
$jscomp.generator.Context.prototype['setCatchFinallyBlocks'] =
440+
$jscomp.generator.Context.prototype.setCatchFinallyBlocks;
398441

399442
/**
400443
* Sets finally handler.
@@ -408,6 +451,8 @@ $jscomp.generator.Context.prototype.setFinallyBlock = function(finallyAddress) {
408451
this.catchAddress_ = 0;
409452
this.finallyAddress_ = finallyAddress || 0;
410453
};
454+
$jscomp.generator.Context.prototype['setFinallyBlock'] =
455+
$jscomp.generator.Context.prototype.setFinallyBlock;
411456

412457
/**
413458
* Sets a catch handler and jumps to the next address.
@@ -420,9 +465,11 @@ $jscomp.generator.Context.prototype.setFinallyBlock = function(finallyAddress) {
420465
*/
421466
$jscomp.generator.Context.prototype.leaveTryBlock = function(
422467
nextAddress, catchAddress) {
423-
this.nextAddress = nextAddress;
468+
this.nextAddress_ = nextAddress;
424469
this.catchAddress_ = catchAddress || 0;
425470
};
471+
$jscomp.generator.Context.prototype['leaveTryBlock'] =
472+
$jscomp.generator.Context.prototype.leaveTryBlock;
426473

427474
/**
428475
* Initializes exception variable in the beginning of catch block.
@@ -442,6 +489,8 @@ $jscomp.generator.Context.prototype.enterCatchBlock = function(
442489
this.abruptCompletion_ = null;
443490
return exception;
444491
};
492+
$jscomp.generator.Context.prototype['enterCatchBlock'] =
493+
$jscomp.generator.Context.prototype.enterCatchBlock;
445494

446495
/**
447496
* Saves the current throw context which will be restored at the end of finally
@@ -466,6 +515,8 @@ $jscomp.generator.Context.prototype.enterFinallyBlock = function(
466515
this.catchAddress_ = nextCatchAddress || 0;
467516
this.finallyAddress_ = nextFinallyAddress || 0;
468517
};
518+
$jscomp.generator.Context.prototype['enterFinallyBlock'] =
519+
$jscomp.generator.Context.prototype.enterFinallyBlock;
469520

470521
/**
471522
* Figures out whether the program execution should continue normally, or jump
@@ -572,15 +623,17 @@ $jscomp.generator.Context.prototype.leaveFinallyBlock = function(
572623
// }
573624
if (abruptCompletion.jumpTo != undefined &&
574625
this.finallyAddress_ < abruptCompletion.jumpTo) {
575-
this.nextAddress = abruptCompletion.jumpTo;
626+
this.nextAddress_ = abruptCompletion.jumpTo;
576627
this.abruptCompletion_ = null;
577628
} else {
578-
this.nextAddress = this.finallyAddress_;
629+
this.nextAddress_ = this.finallyAddress_;
579630
}
580631
} else {
581-
this.nextAddress = nextAddress;
632+
this.nextAddress_ = nextAddress;
582633
}
583634
};
635+
$jscomp.generator.Context.prototype['leaveFinallyBlock'] =
636+
$jscomp.generator.Context.prototype.leaveFinallyBlock;
584637

585638
/**
586639
* Is used in transpilation of `for in` statements.
@@ -602,6 +655,11 @@ $jscomp.generator.Context.prototype.leaveFinallyBlock = function(
602655
$jscomp.generator.Context.prototype.forIn = function(object) {
603656
return new $jscomp.generator.Context.PropertyIterator(object);
604657
};
658+
$jscomp.generator.Context.prototype['forIn'] =
659+
$jscomp.generator.Context.prototype.forIn;
660+
661+
662+
/** End public methods */
605663

606664
/**
607665
* @constructor
@@ -650,6 +708,8 @@ $jscomp.generator.Context.PropertyIterator.prototype.getNext = function() {
650708
}
651709
return null;
652710
};
711+
$jscomp.generator.Context.PropertyIterator.prototype['getNext'] =
712+
$jscomp.generator.Context.PropertyIterator.prototype.getNext;
653713

654714
/**
655715
* Engine handling execution of a state machine associated with the generator
@@ -790,15 +850,15 @@ $jscomp.generator.Engine_.prototype.yieldAllStep_ = function(
790850
* @suppress {reportUnknownTypes, strictMissingProperties}
791851
*/
792852
$jscomp.generator.Engine_.prototype.nextStep_ = function() {
793-
while (this.context_.nextAddress) {
853+
while (this.context_.nextAddress_) {
794854
try {
795855
/** @const */ var yieldValue = this.program_(this.context_);
796856
if (yieldValue) {
797857
this.context_.stop_();
798858
return {value: yieldValue.value, done: false};
799859
}
800860
} catch (e) {
801-
this.context_.yieldResult = undefined;
861+
this.context_.yieldResult_ = undefined;
802862
this.context_.throw_(e);
803863
}
804864
}

0 commit comments

Comments
 (0)