Skip to content

Commit

Permalink
Check FOR_AWAIT_OF statements in many places we check for FOR_IN/FOR_…
Browse files Browse the repository at this point in the history
…OF statements.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=229834000
  • Loading branch information
johnplaisted authored and lauraharker committed Jan 18, 2019
1 parent 2139366 commit 5b99a85
Show file tree
Hide file tree
Showing 27 changed files with 335 additions and 41 deletions.
1 change: 1 addition & 0 deletions src/com/google/javascript/jscomp/BasicBlock.java
Expand Up @@ -55,6 +55,7 @@ final class BasicBlock implements Serializable {
|| pType == Token.WHILE
|| pType == Token.FOR
|| pType == Token.FOR_OF
|| pType == Token.FOR_AWAIT_OF
|| pType == Token.FOR_IN;
} else {
this.isLoop = false;
Expand Down
1 change: 1 addition & 0 deletions src/com/google/javascript/jscomp/CheckSuspiciousCode.java
Expand Up @@ -92,6 +92,7 @@ private void checkMissingSemicolon(NodeTraversal t, Node n) {
case FOR:
case FOR_IN:
case FOR_OF:
case FOR_AWAIT_OF:
reportIfWasEmpty(t, NodeUtil.getLoopCodeBlock(n));
break;
default:
Expand Down
1 change: 1 addition & 0 deletions src/com/google/javascript/jscomp/ControlFlowAnalysis.java
Expand Up @@ -994,6 +994,7 @@ static boolean isBreakStructure(Node n, boolean labeled) {
case FOR:
case FOR_IN:
case FOR_OF:
case FOR_AWAIT_OF:
case DO:
case WHILE:
case SWITCH:
Expand Down
Expand Up @@ -272,6 +272,7 @@ private static boolean isBlockBoundary(Node n, Node parent) {
case FOR:
case FOR_IN:
case FOR_OF:
case FOR_AWAIT_OF:
case TRY:
case WHILE:
case WITH:
Expand Down
Expand Up @@ -167,6 +167,7 @@ private void tryRemoveDeadAssignments(NodeTraversal t,
case FOR:
case FOR_IN:
case FOR_OF:
case FOR_AWAIT_OF:
if (n.isVanillaFor()) {
tryRemoveAssignment(t, NodeUtil.getConditionExpression(n), state, allVarsInFn);
}
Expand Down
1 change: 1 addition & 0 deletions src/com/google/javascript/jscomp/ExpressionDecomposer.java
Expand Up @@ -741,6 +741,7 @@ private static Node findExpressionRoot(Node subExpression) {
// fall through
case FOR_IN:
case FOR_OF:
case FOR_AWAIT_OF:
case DO:
case WHILE:
case SCRIPT:
Expand Down
Expand Up @@ -255,6 +255,7 @@ private void computeGenKill(Node n, BitSet gen, BitSet kill, boolean conditional
return;

case FOR_OF:
case FOR_AWAIT_OF:
case FOR_IN:
{
// for (x in y) {...}
Expand Down
Expand Up @@ -206,6 +206,7 @@ private void computeMayUse(Node n, Node cfgNode, ReachingUses output, boolean co

case FOR_IN:
case FOR_OF:
case FOR_AWAIT_OF:
// for(x in y) {...}
Node lhs = n.getFirstChild();
Node rhs = lhs.getNext();
Expand Down
1 change: 1 addition & 0 deletions src/com/google/javascript/jscomp/MinimizeExitPoints.java
Expand Up @@ -42,6 +42,7 @@ Node optimizeSubtree(Node n) {
case FOR:
case FOR_IN:
case FOR_OF:
case FOR_AWAIT_OF:
case WHILE:
tryMinimizeExits(NodeUtil.getLoopCodeBlock(n), Token.CONTINUE, null);
break;
Expand Down
Expand Up @@ -259,6 +259,7 @@ private void computeMustDef(

case FOR_IN:
case FOR_OF:
case FOR_AWAIT_OF:
// for(x in y) {...}
Node lhs = n.getFirstChild();
Node rhs = lhs.getNext();
Expand Down
2 changes: 2 additions & 0 deletions src/com/google/javascript/jscomp/Normalize.java
Expand Up @@ -590,6 +590,7 @@ private void normalizeLabels(Node n) {
case FOR:
case FOR_IN:
case FOR_OF:
case FOR_AWAIT_OF:
case WHILE:
case DO:
return;
Expand Down Expand Up @@ -627,6 +628,7 @@ private void extractForInitializer(
break;
case FOR_IN:
case FOR_OF:
case FOR_AWAIT_OF:
Node first = c.getFirstChild();
if (first.isVar()) {
Node lhs = first.getFirstChild();
Expand Down
1 change: 1 addition & 0 deletions src/com/google/javascript/jscomp/OptimizeCalls.java
Expand Up @@ -429,6 +429,7 @@ static boolean isAllowedReference(Node n) {
switch (parent.getToken()) {
case FOR_IN:
case FOR_OF:
case FOR_AWAIT_OF:
// inspecting the properties is allowed.
return parent.getSecondChild() == n;
case INSTANCEOF:
Expand Down
1 change: 1 addition & 0 deletions src/com/google/javascript/jscomp/Reference.java
Expand Up @@ -222,6 +222,7 @@ public boolean isLvalue() {
case FOR:
case FOR_IN:
case FOR_OF:
case FOR_AWAIT_OF:
return NodeUtil.isEnhancedFor(parent) && parent.getFirstChild() == nameNode;
case ARRAY_PATTERN:
case STRING_KEY:
Expand Down
Expand Up @@ -318,6 +318,7 @@ private static boolean isBlockBoundary(Node n, Node parent) {
case FOR:
case FOR_IN:
case FOR_OF:
case FOR_AWAIT_OF:
case TRY:
case WHILE:
case WITH:
Expand Down
1 change: 1 addition & 0 deletions src/com/google/javascript/jscomp/RemoveUnusedCode.java
Expand Up @@ -395,6 +395,7 @@ private void traverseNode(Node n, Scope scope) {

case FOR_IN:
case FOR_OF:
case FOR_AWAIT_OF:
traverseEnhancedFor(n, scope);
break;

Expand Down
3 changes: 2 additions & 1 deletion src/com/google/javascript/jscomp/VariableReferenceCheck.java
Expand Up @@ -81,7 +81,8 @@ class VariableReferenceCheck implements HotSwapCompilerPass {
// e.g. if (b) let x;
// This list omits Token.LABEL intentionally. It's handled differently in IRFactory.
private static final ImmutableSet<Token> BLOCKLESS_DECLARATION_FORBIDDEN_STATEMENTS =
Sets.immutableEnumSet(Token.IF, Token.FOR, Token.FOR_IN, Token.FOR_OF, Token.WHILE);
Sets.immutableEnumSet(
Token.IF, Token.FOR, Token.FOR_IN, Token.FOR_OF, Token.FOR_AWAIT_OF, Token.WHILE);

public VariableReferenceCheck(AbstractCompiler compiler) {
this(compiler, false);
Expand Down
Expand Up @@ -207,6 +207,7 @@ public boolean shouldTraverse(NodeTraversal t, Node n, Node parent) {
NodeUtil.deleteNode(n.getSecondChild(), t.getCompiler());
// fall-through
case FOR_OF:
case FOR_AWAIT_OF:
case FOR_IN:
NodeUtil.deleteNode(n.getSecondChild(), t.getCompiler());
Node initializer = n.removeFirstChild();
Expand Down Expand Up @@ -254,6 +255,7 @@ public void visit(NodeTraversal t, Node n, Node parent) {
case FOR:
case FOR_IN:
case FOR_OF:
case FOR_AWAIT_OF:
case IF:
case SWITCH:
if (n.getParent() != null) {
Expand Down
19 changes: 18 additions & 1 deletion test/com/google/javascript/jscomp/CheckSuspiciousCodeTest.java
Expand Up @@ -38,7 +38,7 @@ protected CompilerPass getProcessor(Compiler compiler) {
@Before
public void setUp() throws Exception {
super.setUp();
setAcceptedLanguage(LanguageMode.ECMASCRIPT_2017);
setAcceptedLanguage(LanguageMode.ECMASCRIPT_2018);
enableParseTypeInfo();
}

Expand Down Expand Up @@ -77,6 +77,10 @@ public void testSuspiciousSemi() {
testSame("var y = [1, 2, 3]; for(x of y) console.log(x);");
testWarning("var y = [1, 2, 3]; for(x of y); console.log(x);", e);
testSame("var y = [1, 2, 3]; for(x of y){} console.log(x);");

testSame("async () => { var y = [1, 2, 3]; for await (x of y) console.log(x); }");
testWarning("async () => { var y = [1, 2, 3]; for await (x of y); console.log(x); }", e);
testSame("async () => { var y = [1, 2, 3]; for await (x of y){} console.log(x); }");
}

@Test
Expand Down Expand Up @@ -107,6 +111,19 @@ public void testForOf() {
testSame("for (var x of null) console.log(x);");
}

@Test
public void testForAwaitOf() {
testSame("async () => { var y = [1, 2, 3]; for await (var x of y) console.log(x); }");
testSame("async () => { var y = [1, 2, 3]; for await (var x of 'test') console.log(x); }");
testSame("async () => { for await (var x of 123) console.log(x); }");
testSame("async () => { for await (var x of false) console.log(x); }");
testSame("async () => { for await (var x of true) console.log(x); }");
testSame("async () => { for await (var x of undefined) console.log(x); }");
testSame("async () => { for await (var x of NaN) console.log(x); }");
testSame("async () => { for await (var x of Infinity) console.log(x); }");
testSame("async () => { for await (var x of null) console.log(x); }");
}

private void testReportNaN(String js) {
testWarning(js, CheckSuspiciousCode.SUSPICIOUS_COMPARISON_WITH_NAN);
}
Expand Down
82 changes: 74 additions & 8 deletions test/com/google/javascript/jscomp/ControlFlowAnalysisTest.java
Expand Up @@ -18,6 +18,7 @@

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static com.google.javascript.jscomp.CompilerTestCase.lines;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Ordering;
Expand All @@ -30,6 +31,7 @@
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
Expand Down Expand Up @@ -1492,6 +1494,72 @@ public void testForAwaitOfOrder() throws IOException {
Token.RETURN));
}

@Test
public void testForAwaitOfOrderBreakAndContinue() throws IOException {
assertNodeOrder(
createCfg(
lines(
"async function f() {",
" outer: for await (let x of y) {",
" inner: for await (let z of x) {",
" if (z) break inner;",
" else continue outer;",
" }",
" }",
" return 0;",
"}")),
ImmutableList.of(
Token.SCRIPT,
Token.FUNCTION,
Token.BLOCK,
Token.NAME,
Token.FOR_AWAIT_OF,
Token.BLOCK,
Token.NAME,
Token.FOR_AWAIT_OF,
Token.BLOCK,
Token.IF,
Token.BLOCK,
Token.BREAK,
Token.BLOCK,
Token.CONTINUE,
Token.RETURN));
}

@Test
public void testForAwaitOfOrderBreakAndContinueAndYield() throws IOException {
assertNodeOrder(
createCfg(
lines(
"async function* f() {",
" outer: for await (let x of y) {",
" inner: for await (let z of x) {",
" if (z > 0) break inner;",
" else if (z < 0) continue outer;",
" yield z;",
" }",
" }",
"}")),
ImmutableList.of(
Token.SCRIPT,
Token.FUNCTION,
Token.BLOCK,
Token.NAME,
Token.FOR_AWAIT_OF,
Token.BLOCK,
Token.NAME,
Token.FOR_AWAIT_OF,
Token.BLOCK,
Token.IF,
Token.BLOCK,
Token.BREAK,
Token.BLOCK,
Token.IF,
Token.BLOCK,
Token.CONTINUE,
Token.EXPR_RESULT));
}

@Test
public void testBreakInFinally1() throws IOException {
String src =
Expand Down Expand Up @@ -1630,13 +1698,11 @@ private void assertNodeOrder(ControlFlowGraph<Node> cfg,
.that(implicitReturn)
.isNull();

assertWithMessage("Wrong number of CFG nodes")
.that(cfgNodes.size())
.isEqualTo(nodeTypes.size());
for (int i = 0; i < cfgNodes.size(); i++) {
Token expectedType = nodeTypes.get(i);
Token actualType = cfgNodes.get(i).getValue().getToken();
assertWithMessage("node type mismatch at " + i).that(actualType).isEqualTo(expectedType);
}
assertThat(
cfgNodes.stream()
.map(DiGraphNode::getValue)
.map(Node::getToken)
.collect(Collectors.toList()))
.isEqualTo(nodeTypes);
}
}
Expand Up @@ -16,6 +16,7 @@

package com.google.javascript.jscomp;

import com.google.javascript.jscomp.CompilerOptions.LanguageMode;
import com.google.javascript.rhino.Node;
import org.junit.Before;
import org.junit.Test;
Expand All @@ -40,6 +41,13 @@ public void setUp() throws Exception {
enableNormalize();
}

@Override
protected CompilerOptions getOptions() {
CompilerOptions options = super.getOptions();
options.setLanguageIn(LanguageMode.ECMASCRIPT_2018);
return options;
}

@Override
protected CompilerPass getProcessor(final Compiler compiler) {
return new CompilerPass() {
Expand Down Expand Up @@ -426,6 +434,16 @@ private void inFunction(String src, String expected) {
"function FUNC(param1, param2){" + expected + "}");
}

private void inAsyncFunction(String src) {
inAsyncFunction(src, src);
}

private void inAsyncFunction(String src, String expected) {
test(
"async function FUNC(param1, param2){" + src + "}",
"async function FUNC(param1, param2){" + expected + "}");
}

@Test
public void testBug8730257() {
inFunction(
Expand Down Expand Up @@ -708,6 +726,15 @@ public void testForOf() {
"var x, y, z; ({}); z = {}; for (y of z) {}");
}

@Test
public void testForAwaitOf() {
inAsyncFunction("var x = {}; for await (var y of x) { y() }");

inAsyncFunction(
"var x, y, z; x = {}; z = {}; for await (y of x = z) {}",
"var x, y, z; ({}); z = {}; for await (y of z) {}");
}

@Test
public void testTemplateStrings() {
inFunction("var name; name = 'Foo'; `Hello ${name}`");
Expand Down
10 changes: 9 additions & 1 deletion test/com/google/javascript/jscomp/ExpressionDecomposerTest.java
Expand Up @@ -300,6 +300,14 @@ public void testCannotExpose_expression9() {
"yield");
}

@Test
public void testCannotExpose_forAwaitOf() {
helperCanExposeExpression(
DecompositionType.UNDECOMPOSABLE,
"async function *f() { for await (let x of yield y) {} }",
"yield");
}

@Test
public void testCanExposeExpression10() {
helperCanExposeExpression(
Expand Down Expand Up @@ -1258,7 +1266,7 @@ private void checkTypeStringsEqualAsTree(Node rootExpected, Node rootActual) {
private Compiler getCompiler() {
Compiler compiler = new Compiler();
CompilerOptions options = new CompilerOptions();
options.setLanguage(LanguageMode.ECMASCRIPT_2015);
options.setLanguage(LanguageMode.ECMASCRIPT_2018);
options.setCodingConvention(new GoogleCodingConvention());
options.setAllowMethodCallDecomposing(allowMethodCallDecomposing);
compiler.initOptions(options);
Expand Down

0 comments on commit 5b99a85

Please sign in to comment.