Skip to content

Commit

Permalink
RemoveUnusedCode: remove compound assignment to unused this properties
Browse files Browse the repository at this point in the history
This feature is only enabled for tests for now.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=179706963
  • Loading branch information
brad4d authored and Tyler Breisacher committed Dec 21, 2017
1 parent a11f2bd commit c3efb69
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 13 deletions.
34 changes: 34 additions & 0 deletions src/com/google/javascript/jscomp/RemoveUnusedCode.java
Expand Up @@ -292,6 +292,21 @@ private void traverseNode(Node n, Scope scope) {
traverseAssign(n, scope);
break;

case ASSIGN_BITOR:
case ASSIGN_BITXOR:
case ASSIGN_BITAND:
case ASSIGN_LSH:
case ASSIGN_RSH:
case ASSIGN_URSH:
case ASSIGN_ADD:
case ASSIGN_SUB:
case ASSIGN_MUL:
case ASSIGN_EXPONENT:
case ASSIGN_DIV:
case ASSIGN_MOD:
traverseCompoundAssign(n, scope);
break;

case CALL:
traverseCall(n, scope);
break;
Expand Down Expand Up @@ -385,6 +400,25 @@ private void traverseNode(Node n, Scope scope) {
}
}

private void traverseCompoundAssign(Node compoundAssignNode, Scope scope) {
// We'll allow removal of compound assignment to a this property as long as the result of the
// assignment is unused.
// e.g. `this.x += 3;`
Node targetNode = compoundAssignNode.getFirstChild();
Node valueNode = compoundAssignNode.getLastChild();
if (targetNode.isGetProp()
&& targetNode.getFirstChild().isThis()
&& !NodeUtil.isExpressionResultUsed(compoundAssignNode)) {
RemovableBuilder builder = new RemovableBuilder().setIsThisNamedPropertyAssignment(true);
traverseRemovableAssignValue(valueNode, builder, scope);
considerForIndependentRemoval(
builder.buildNamedPropertyAssign(compoundAssignNode, targetNode.getLastChild()));
} else {
traverseNode(targetNode, scope);
traverseNode(valueNode, scope);
}
}

private VarInfo traverseNameNode(Node n, Scope scope) {
return traverseVar(getVarForNameNode(n, scope));
}
Expand Down
Expand Up @@ -141,25 +141,22 @@ public void testExport() {
testSame("function f() { this.ext = 2; } window['export'] = this.ext;");
}


// TODO(b/66971163): make this pass
public void disabledTestAssignOp1() {
public void testAssignOp1() {
// Properties defined using a compound assignment can be removed if the
// result of the assignment expression is not immediately used.
test("this.x += 2", "2");
test("this.x += 2", "");
testSame("const x = (this.x += 2)");
testSame("this.x += 2; const x = this.x;");
// But, of course, a later use prevents its removal.
testSame("this.x += 2; let x = {}; x.x;");
}

// TODO(b/66971163): make this pass
public void disabledTestAssignOp2() {
public void testAssignOp2() {
// Properties defined using a compound assignment can be removed if the
// result of the assignment expression is not immediately used.
test("this.a += 2, f()", "2, f()");
test("x = (this.a += 2, f())", "x = (2, f())");
testSame("x = (f(), this.a += 2)");
test("this.a += 2, alert(1)", "0, alert(1)");
test("const x = (this.a += 2, alert(1))", "const x = (0, alert(1))");
testSame("const x = (alert(1), this.a += 2)");
}

// TODO(b/66971163): make this pass
Expand Down Expand Up @@ -214,15 +211,17 @@ public void testJSCompiler_renameProperty() {
public void testForIn() {
// This is the basic assumption that this pass makes:
// it can remove properties even when the object is used in a FOR-IN loop
test("let x = {}; this.y = 1;for (var a in x) { alert(x[a]) }",
"let x = {}; for (var a in x) { alert(x[a]) }");
test(
"let x = {}; this.y = 1;for (var a in x) { alert(x[a]) }",
"let x = {}; for (var a in x) { alert(x[a]) }");
}

public void testObjectKeys() {
// This is the basic assumption that this pass makes:
// it can remove properties even when the object are referenced
test("this.y = 1;alert(Object.keys(this))",
" alert(Object.keys(this))");
test(
"this.y = 1;alert(Object.keys(this))", // preserve format
" alert(Object.keys(this))");
}

public void testObjectReflection1() {
Expand Down

0 comments on commit c3efb69

Please sign in to comment.