Skip to content

Commit

Permalink
Back off from inlining type aliases when the aliased name is shadowed…
Browse files Browse the repository at this point in the history
… by a local var.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=258461498
  • Loading branch information
tjgq committed Jul 17, 2019
1 parent a96aaaf commit 3cc33fe
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 5 deletions.
20 changes: 15 additions & 5 deletions src/com/google/javascript/jscomp/InlineAliases.java
Expand Up @@ -16,6 +16,7 @@

package com.google.javascript.jscomp;

import com.google.common.base.Preconditions;
import com.google.javascript.jscomp.NodeTraversal.ExternsSkippingCallback;
import com.google.javascript.rhino.JSDocInfo;
import com.google.javascript.rhino.JSDocInfo.Visibility;
Expand Down Expand Up @@ -132,19 +133,21 @@ public void visit(NodeTraversal t, Node n, Node parent) {
case NAME:
case GETPROP:
if (n.isQualifiedName() && aliases.containsKey(n.getQualifiedName())) {
String leftmostName = NodeUtil.getRootOfQualifiedName(n).getString();
Var v = t.getScope().getVar(leftmostName);
if (v != null && v.isLocal()) {
// Shadow of alias. Don't rewrite
if (isLeftmostNameLocal(t, n)) {
// The alias is shadowed by a local variable. Don't rewrite.
return;
}
if (NodeUtil.isNameDeclOrSimpleAssignLhs(n, parent)) {
// Alias definition. Don't rewrite
// The node defines an alias. Don't rewrite.
return;
}

Node newNode =
astFactory.createQName(t.getScope(), resolveAlias(n.getQualifiedName(), n));
if (isLeftmostNameLocal(t, newNode)) {
// The aliased name is shadowed by a local variable. Don't rewrite.
return;
}

// If n is get_prop like "obj.foo" then newNode should use only location of foo, not
// obj.foo.
Expand All @@ -163,6 +166,13 @@ public void visit(NodeTraversal t, Node n, Node parent) {
}
}

private boolean isLeftmostNameLocal(NodeTraversal t, Node n) {
Preconditions.checkState(n.isQualifiedName());
String leftmostName = NodeUtil.getRootOfQualifiedName(n).getString();
Var v = t.getScope().getVar(leftmostName);
return v != null && v.isLocal();
}

/**
* Use the alias table to look up the resolved name of the given alias. If the result is also an
* alias repeat until the real name is resolved.
Expand Down
34 changes: 34 additions & 0 deletions test/com/google/javascript/jscomp/InlineAliasesTest.java
Expand Up @@ -618,4 +618,38 @@ public void testDoInlineEscapedConstructorProperty() {
"use(Foobar);",
"alert(Foobar.foo);")));
}

@Test
public void testForwardedExport() {
testSame(
lines(
"const proto = {};",
"/** @const */",
"proto.google = {};",
"/** @const */",
"proto.google.type = {};",
"proto.google.type.Date = class {};",
"const alias = proto;",
"function f() {",
" const d = new alias.google.type.Date();",
" const proto = 0;",
"}"));
}

@Test
public void testForwardedExportNested() {
testSame(
lines(
"const proto = {};",
"/** @const */",
"proto.google = {};",
"/** @const */",
"proto.google.type = {};",
"proto.google.type.Date = class {};",
"const alias = proto.google;",
"function f() {",
" const d = new alias.type.Date();",
" const proto = 0;",
"}"));
}
}

0 comments on commit 3cc33fe

Please sign in to comment.