From bf3d1085aee4c23254b08f2c692ed2754d264a87 Mon Sep 17 00:00:00 2001 From: skill Date: Thu, 8 Mar 2018 06:17:08 -0800 Subject: [PATCH] Modify RewriteAsyncFunctions to generate less boilerplate code while transpiling async functions. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=188322314 --- .../jscomp/RewriteAsyncFunctions.java | 46 +++--- .../javascript/jscomp/IntegrationTest.java | 40 ++--- .../jscomp/RewriteAsyncFunctionsTest.java | 140 +++++++++--------- 3 files changed, 109 insertions(+), 117 deletions(-) diff --git a/src/com/google/javascript/jscomp/RewriteAsyncFunctions.java b/src/com/google/javascript/jscomp/RewriteAsyncFunctions.java index 29d4a7fd88e..32cf12f8774 100644 --- a/src/com/google/javascript/jscomp/RewriteAsyncFunctions.java +++ b/src/com/google/javascript/jscomp/RewriteAsyncFunctions.java @@ -41,20 +41,19 @@ * let $jscomp$async$this = this; * let $jscomp$async$arguments = arguments; * let $jscomp$async$super$get$x = () => super.x; - * function* $jscomp$async$generator() { - * // original body of foo() with: - * // - await (x) replaced with yield (x) - * // - arguments replaced with $jscomp$async$arguments - * // - this replaced with $jscomp$async$this - * // - super.x replaced with $jscomp$async$super$get$x() - * // - super.x(5) replaced with $jscomp$async$super$get$x().call($jscomp$async$this, 5) - * } - * return $jscomp.executeAsyncGenerator($jscomp$async$generator()); + * return $jscomp.asyncExecutePromiseGeneratorFunction( + * function* () { + * // original body of foo() with: + * // - await (x) replaced with yield (x) + * // - arguments replaced with $jscomp$async$arguments + * // - this replaced with $jscomp$async$this + * // - super.x replaced with $jscomp$async$super$get$x() + * // - super.x(5) replaced with $jscomp$async$super$get$x().call($jscomp$async$this, 5) + * }); * }} */ public final class RewriteAsyncFunctions implements NodeTraversal.Callback, HotSwapCompilerPass { - private static final String ASYNC_GENERATOR_NAME = "$jscomp$async$generator"; private static final String ASYNC_ARGUMENTS = "$jscomp$async$arguments"; private static final String ASYNC_THIS = "$jscomp$async$this"; private static final String ASYNC_SUPER_PROP_GETTER_PREFIX = "$jscomp$async$super$get$"; @@ -231,7 +230,7 @@ private void convertAsyncFunction(LexicalContext functionContext) { Node originalFunction = checkNotNull(functionContext.function); originalFunction.setIsAsyncFunction(false); Node originalBody = originalFunction.getLastChild(); - Node newBody = IR.block().useSourceInfoIfMissingFrom(originalBody); + Node newBody = IR.block(); originalFunction.replaceChild(originalBody, newBody); if (functionContext.mustAddAsyncThisVariable) { @@ -254,26 +253,19 @@ private void convertAsyncFunction(LexicalContext functionContext) { // Normalize arrow function short body to block body if (!originalBody.isNormalBlock()) { - originalBody = IR.block(IR.returnNode(originalBody)).useSourceInfoFromForTree(originalBody); + originalBody = IR.block(IR.returnNode(originalBody).useSourceInfoFrom(originalBody)) + .useSourceInfoFrom(originalBody); } // NOTE: visit() will already have made appropriate replacements in originalBody so it may // be used as the generator function body. - Node newFunctionName = IR.name(ASYNC_GENERATOR_NAME); - Node originalName = originalFunction.getFirstChild(); - // Use the source info from the function name. Without this line, we would use the source info - // from originalBody for the name node near the end of this method. - newFunctionName.useSourceInfoIfMissingFromForTree(originalName); - Node generatorFunction = IR.function(newFunctionName, IR.paramList(), originalBody); - compiler.reportChangeToChangeScope(generatorFunction); + Node generatorFunction = IR.function(IR.name(""), IR.paramList(), originalBody); generatorFunction.setIsGeneratorFunction(true); - // function* $jscomp$async$generator() { ... } - newBody.addChildToBack(generatorFunction); - - // return $jscomp.executeAsyncGenerator($jscomp$async$generator()); - Node executeAsyncGenerator = IR.getprop(IR.name("$jscomp"), IR.string("executeAsyncGenerator")); - newBody.addChildToBack( - IR.returnNode( - IR.call(executeAsyncGenerator, NodeUtil.newCallNode(IR.name(ASYNC_GENERATOR_NAME))))); + compiler.reportChangeToChangeScope(generatorFunction); + + // return $jscomp.asyncExecutePromiseGeneratorFunction(function* () { ... }); + newBody.addChildToBack(IR.returnNode(IR.call( + IR.getprop(IR.name("$jscomp"), IR.string("asyncExecutePromiseGeneratorFunction")), + generatorFunction))); newBody.useSourceInfoIfMissingFromForTree(originalBody); compiler.reportChangeToEnclosingScope(newBody); diff --git a/test/com/google/javascript/jscomp/IntegrationTest.java b/test/com/google/javascript/jscomp/IntegrationTest.java index ca1c98b1176..0885d583a72 100644 --- a/test/com/google/javascript/jscomp/IntegrationTest.java +++ b/test/com/google/javascript/jscomp/IntegrationTest.java @@ -5166,26 +5166,26 @@ public void testMethodDestructuringInTranspiledAsyncFunction() { " alert(i);", "};", "function foo() {", - " function $jscomp$async$generator() {", - " var JSCompiler_temp_const;", - " var JSCompiler_temp_const$jscomp$1;", - " return $jscomp.generator.createGenerator(", - " $jscomp$async$generator,", - " function ($jscomp$generator$context) {", - " do switch ($jscomp$generator$context.nextAddress) {", - " case 1:", - " JSCompiler_temp_const = A;", - " JSCompiler_temp_const$jscomp$1 = A$doSomething;", - " return $jscomp$generator$context.yield(3, 2);", - " case 2:", - " JSCompiler_temp_const$jscomp$1.call(", - " JSCompiler_temp_const,", - " $jscomp$generator$context.yieldResult);", - " $jscomp$generator$context.jumpToEnd();", - " } while (0);", - " });", - " }", - " return $jscomp.executeAsyncGenerator($jscomp$async$generator())", + " return $jscomp.asyncExecutePromiseGeneratorFunction(", + " function $jscomp$generator$function() {", + " var JSCompiler_temp_const;", + " var JSCompiler_temp_const$jscomp$1;", + " return $jscomp.generator.createGenerator(", + " $jscomp$generator$function,", + " function ($jscomp$generator$context) {", + " do switch ($jscomp$generator$context.nextAddress) {", + " case 1:", + " JSCompiler_temp_const = A;", + " JSCompiler_temp_const$jscomp$1 = A$doSomething;", + " return $jscomp$generator$context.yield(3, 2);", + " case 2:", + " JSCompiler_temp_const$jscomp$1.call(", + " JSCompiler_temp_const,", + " $jscomp$generator$context.yieldResult);", + " $jscomp$generator$context.jumpToEnd();", + " } while (0);", + " });", + " })", "}", "foo();")); } diff --git a/test/com/google/javascript/jscomp/RewriteAsyncFunctionsTest.java b/test/com/google/javascript/jscomp/RewriteAsyncFunctionsTest.java index e5e68265725..cdb082ddb7c 100644 --- a/test/com/google/javascript/jscomp/RewriteAsyncFunctionsTest.java +++ b/test/com/google/javascript/jscomp/RewriteAsyncFunctionsTest.java @@ -60,12 +60,12 @@ public void testInnerArrowFunctionUsingThis() { "class X {", " m() {", " const $jscomp$async$this = this;", - " function* $jscomp$async$generator() {", - " return new Promise((resolve, reject) => {", - " return $jscomp$async$this", - " });", - " }", - " return $jscomp.executeAsyncGenerator($jscomp$async$generator())", + " return $jscomp.asyncExecutePromiseGeneratorFunction(", + " function* () {", + " return new Promise((resolve, reject) => {", + " return $jscomp$async$this;", + " });", + " });", " }", "}")); } @@ -93,10 +93,10 @@ public void testInnerSuperCall() { " m() {", " const $jscomp$async$this = this;", " const $jscomp$async$super$get$m = () => super.m;", - " function* $jscomp$async$generator() {", - " return $jscomp$async$super$get$m().call($jscomp$async$this);", - " }", - " return $jscomp.executeAsyncGenerator($jscomp$async$generator())", + " return $jscomp.asyncExecutePromiseGeneratorFunction(", + " function* () {", + " return $jscomp$async$super$get$m().call($jscomp$async$this);", + " });", " }", "}")); } @@ -124,11 +124,11 @@ public void testInnerSuperReference() { "class X extends A {", " m() {", " const $jscomp$async$super$get$m = () => super.m;", - " function* $jscomp$async$generator() {", - " const tmp = $jscomp$async$super$get$m();", - " return tmp.call(null);", - " }", - " return $jscomp.executeAsyncGenerator($jscomp$async$generator())", + " return $jscomp.asyncExecutePromiseGeneratorFunction(", + " function* () {", + " const tmp = $jscomp$async$super$get$m();", + " return tmp.call(null);", + " });", " }", "}")); } @@ -146,10 +146,10 @@ public void testNestedArrowFunctionUsingThis() { " m() {", " return () => {", " const $jscomp$async$this = this;", - " function* $jscomp$async$generator() {", - " return () => $jscomp$async$this;", - " }", - " return $jscomp.executeAsyncGenerator($jscomp$async$generator())", + " return $jscomp.asyncExecutePromiseGeneratorFunction(", + " function* () {", + " return () => $jscomp$async$this;", + " })", " }", " }", "}")); @@ -169,12 +169,12 @@ public void testInnerArrowFunctionUsingArguments() { "class X {", " m() {", " const $jscomp$async$arguments = arguments;", - " function* $jscomp$async$generator() {", - " return new Promise((resolve,reject) => {", - " return $jscomp$async$arguments", - " });", - " }", - " return $jscomp.executeAsyncGenerator($jscomp$async$generator())", + " return $jscomp.asyncExecutePromiseGeneratorFunction(", + " function* () {", + " return new Promise((resolve, reject) => {", + " return $jscomp$async$arguments", + " });", + " });", " }", "}")); } @@ -184,10 +184,10 @@ public void testRequiredCodeInjected() { "async function foo() { return 1; }", lines( "function foo() {", - " function* $jscomp$async$generator() {", - " return 1;", - " }", - " return $jscomp.executeAsyncGenerator($jscomp$async$generator());", + " return $jscomp.asyncExecutePromiseGeneratorFunction(", + " function* () {", + " return 1;", + " });", "}")); assertThat(getLastCompiler().injected).containsExactly("es6/execute_async_generator"); } @@ -197,10 +197,10 @@ public void testAwaitReplacement() { "async function foo(promise) { return await promise; }", lines( "function foo(promise) {", - " function* $jscomp$async$generator() {", - " return yield promise;", - " }", - " return $jscomp.executeAsyncGenerator($jscomp$async$generator());", + " return $jscomp.asyncExecutePromiseGeneratorFunction(", + " function* () {", + " return yield promise;", + " });", "}")); } @@ -218,10 +218,10 @@ public void testArgumentsReplacement_asyncFunction() { lines( "function f(a, b, ...rest) {", " const $jscomp$async$arguments = arguments;", - " function* $jscomp$async$generator() {", - " return $jscomp$async$arguments.length;", // arguments replaced - " }", - " return $jscomp.executeAsyncGenerator($jscomp$async$generator());", + " return $jscomp.asyncExecutePromiseGeneratorFunction(", + " function* () {", + " return $jscomp$async$arguments.length;", // arguments replaced + " });", "}")); } @@ -236,10 +236,10 @@ public void testArgumentsReplacement_asyncClosure() { "function outer() {", " function f() {", " const $jscomp$async$arguments = arguments;", - " function* $jscomp$async$generator() {", - " return $jscomp$async$arguments.length;", // arguments replaced - " }", - " return $jscomp.executeAsyncGenerator($jscomp$async$generator());", + " return $jscomp.asyncExecutePromiseGeneratorFunction(", + " function* () {", + " return $jscomp$async$arguments.length;", // arguments replaced + " });", " }", " return f(arguments)", // unchanged "}")); @@ -257,13 +257,13 @@ public void testArgumentsReplacement_normalClosureInAsync() { lines( "function a() {", " const $jscomp$async$arguments = arguments;", - " function* $jscomp$async$generator() {", - " function inner() {", - " return arguments.length;", // unchanged - " }", - " return inner.apply(undefined, $jscomp$async$arguments);", // arguments replaced - " }", - " return $jscomp.executeAsyncGenerator($jscomp$async$generator());", + " return $jscomp.asyncExecutePromiseGeneratorFunction(", + " function* () {", + " function inner() {", + " return arguments.length;", // unchanged + " }", + " return inner.apply(undefined, $jscomp$async$arguments);", + " });", "}")); } @@ -274,10 +274,10 @@ public void testClassMethod() { "class A {", " f() {", " const $jscomp$async$this = this;", - " function* $jscomp$async$generator() {", - " return $jscomp$async$this.x;", // this replaced - " }", - " return $jscomp.executeAsyncGenerator($jscomp$async$generator());", + " return $jscomp.asyncExecutePromiseGeneratorFunction(", + " function *() {", + " return $jscomp$async$this.x;", // this replaced + " });", " }", "}")); } @@ -296,16 +296,16 @@ public void testAsyncClassMethodWithAsyncArrow() { " f() {", " const $jscomp$async$this = this;", " const $jscomp$async$arguments = arguments;", - " function *$jscomp$async$generator() {", - " let g = () => {", - " function *$jscomp$async$generator() {", - " console.log($jscomp$async$this, $jscomp$async$arguments);", - " }", - " return $jscomp.executeAsyncGenerator($jscomp$async$generator());", - " };", - " g();", - " }", - " return $jscomp.executeAsyncGenerator($jscomp$async$generator());", + " return $jscomp.asyncExecutePromiseGeneratorFunction(", + " function *() {", + " let g = () => {", + " return $jscomp.asyncExecutePromiseGeneratorFunction(", + " function *() {", + " console.log($jscomp$async$this, $jscomp$async$arguments);", + " });", + " };", + " g();", + " });", " }", "}")); } @@ -325,10 +325,10 @@ public void testNonAsyncClassMethodWithAsyncArrow() { " let g = () => {", " const $jscomp$async$this = this;", " const $jscomp$async$arguments = arguments;", - " function *$jscomp$async$generator() {", - " console.log($jscomp$async$this, $jscomp$async$arguments);", - " }", - " return $jscomp.executeAsyncGenerator($jscomp$async$generator());", + " return $jscomp.asyncExecutePromiseGeneratorFunction(", + " function *() {", + " console.log($jscomp$async$this, $jscomp$async$arguments);", + " });", " };", " g();", " }", @@ -340,10 +340,10 @@ public void testArrowFunctionExpressionBody() { "let f = async () => 1;", lines( "let f = () => {", - " function* $jscomp$async$generator() {", - " return 1;", - " }", - " return $jscomp.executeAsyncGenerator($jscomp$async$generator());", + " return $jscomp.asyncExecutePromiseGeneratorFunction(", + " function* () {", + " return 1;", + " });", "}")); } }