/*
* Copyright 2016 The Closure Compiler Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import static com.google.common.truth.Truth.assertThat;
import com.google.javascript.jscomp.CompilerOptions.LanguageMode;
public class RewriteAsyncFunctionsTest extends CompilerTestCase {
@Override
public void setUp() {
setAcceptedLanguage(LanguageMode.ECMASCRIPT_NEXT);
setLanguageOut(LanguageMode.ECMASCRIPT3);
runTypeCheckAfterProcessing = true;
}
@Override
protected CompilerPass getProcessor(Compiler compiler) {
return new RewriteAsyncFunctions(compiler);
}
// Don't let the compiler actually inject any code.
// It just makes the expected output hard to read and write.
@Override
protected Compiler createCompiler() {
return new NoninjectingCompiler();
}
@Override
NoninjectingCompiler getLastCompiler() {
return (NoninjectingCompiler) super.getLastCompiler();
}
public void testRequiredCodeInjected() {
test(
"async function foo() { return 1; }",
LINE_JOINER.join(
"function foo() {",
" function* $jscomp$async$generator() {",
" return 1;",
" }",
" return $jscomp.executeAsyncGenerator($jscomp$async$generator());",
"}"));
assertThat(getLastCompiler().injected).containsExactly("es6/execute_async_generator");
}
public void testAwaitReplacement() {
test(
"async function foo(promise) { return await promise; }",
LINE_JOINER.join(
"function foo(promise) {",
" function* $jscomp$async$generator() {",
" return yield promise;",
" }",
" return $jscomp.executeAsyncGenerator($jscomp$async$generator());",
"}"));
}
public void testArgumentsReplacement_topLevelCode() {
testSame("arguments;");
}
public void testArgumentsReplacement_normalFunction() {
testSame("function f(a, b, ...rest) { return arguments.length; }");
}
public void testArgumentsReplacement_asyncFunction() {
test(
"async function f(a, b, ...rest) { return arguments.length; }",
LINE_JOINER.join(
"function f(a, b, ...rest) {",
" let $jscomp$async$arguments = arguments;",
" function* $jscomp$async$generator() {",
" return $jscomp$async$arguments.length;", // arguments replaced
" }",
" return $jscomp.executeAsyncGenerator($jscomp$async$generator());",
"}"));
}
public void testArgumentsReplacement_asyncClosure() {
test(
LINE_JOINER.join(
"function outer() {",
" async function f() { return arguments.length; }",
" return f(arguments)",
"}"),
LINE_JOINER.join(
"function outer() {",
" function f() {",
" let $jscomp$async$arguments = arguments;",
" function* $jscomp$async$generator() {",
" return $jscomp$async$arguments.length;", // arguments replaced
" }",
" return $jscomp.executeAsyncGenerator($jscomp$async$generator());",
" }",
" return f(arguments)", // unchanged
"}"));
}
public void testArgumentsReplacement_normalClosureInAsync() {
test(
LINE_JOINER.join(
"async function a() {",
" function inner() {",
" return arguments.length;",
" }",
" return inner.apply(undefined, arguments);", // this should get replaced
"}"),
LINE_JOINER.join(
"function a() {",
" let $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());",
"}"));
}
public void testClassMethod() {
test(
"class A { async f() { return this.x; } }",
LINE_JOINER.join(
"class A {",
" f() {",
" let $jscomp$async$this = this;",
" function* $jscomp$async$generator() {",
" return $jscomp$async$this.x;", // this replaced
" }",
" return $jscomp.executeAsyncGenerator($jscomp$async$generator());",
" }",
"}"));
}
public void testArrowFunctionExpressionBody() {
test(
"let f = async () => 1;",
LINE_JOINER.join(
"let f = () => {",
" function* $jscomp$async$generator() {",
" return 1;",
" }",
" return $jscomp.executeAsyncGenerator($jscomp$async$generator());",
"}"));
}
}