| OLD | NEW |
| (Empty) |
| 1 // Copyright 2011 Google Inc. All Rights Reserved. | |
| 2 | |
| 3 package com.google.dart.compiler.backend.js.analysis; | |
| 4 | |
| 5 import com.google.common.collect.Maps; | |
| 6 | |
| 7 import junit.framework.TestCase; | |
| 8 | |
| 9 import org.mozilla.javascript.Parser; | |
| 10 import org.mozilla.javascript.ast.AstNode; | |
| 11 import org.mozilla.javascript.ast.AstRoot; | |
| 12 | |
| 13 import java.util.ArrayList; | |
| 14 import java.util.List; | |
| 15 import java.util.Map; | |
| 16 | |
| 17 | |
| 18 /** | |
| 19 * Tests that the dependency computer class reports dependencies correctly. | |
| 20 */ | |
| 21 public class DependencyComputerTest extends TestCase { | |
| 22 private Parser parser = new Parser(); | |
| 23 private Map<String, List<JavascriptElement>> namesToElements = Maps.newHashMap
(); | |
| 24 private List<AstNode> globals = new ArrayList<AstNode>(); | |
| 25 private TopLevelElementIndexer topLevelElementIndexer = new TopLevelElementInd
exer( | |
| 26 namesToElements, globals); | |
| 27 private DependencyComputer dependencyComputer = new DependencyComputer(namesTo
Elements); | |
| 28 | |
| 29 /** | |
| 30 * Tests that we don't add virtual dependencies for names that are shadowed by | |
| 31 * local variables. | |
| 32 */ | |
| 33 public void testLocalVariableShadowingOfMemberOfUninstantiatedClass() { | |
| 34 StringBuilder sb = new StringBuilder(); | |
| 35 sb.append("function A() {}\n"); | |
| 36 sb.append("A.prototype.foo = function() {}\n"); | |
| 37 sb.append("function B() {}\n"); | |
| 38 sb.append("B.prototype.foo = function() {}\n"); | |
| 39 sb.append("function execute() { var foo = 1; foo(); }"); | |
| 40 | |
| 41 AstRoot astRoot = parser.parse(sb.toString(), "", 1); | |
| 42 astRoot.visit(topLevelElementIndexer); | |
| 43 AstNode executeFunction = (AstNode) astRoot.getLastChild(); | |
| 44 List<JavascriptElement> computedDependencies = | |
| 45 dependencyComputer.computeDependencies(executeFunction); | |
| 46 assertNotNull(computedDependencies); | |
| 47 | |
| 48 /* | |
| 49 * The foo inside of execute method should lexically resolve to the local | |
| 50 * variable hence foo() does not introduce a dependency on A.prototype.foo | |
| 51 * or B.prototype.foo. | |
| 52 */ | |
| 53 assertEquals(0, computedDependencies.size()); | |
| 54 } | |
| 55 | |
| 56 /** | |
| 57 * Tests that we can find dependencies to methods added to the prototype chain
of native objects. | |
| 58 */ | |
| 59 public void testNativeDependencies() { | |
| 60 StringBuilder sb = new StringBuilder(); | |
| 61 sb.append("function A() {}\n"); | |
| 62 sb.append("A.prototype.foo = function() {}\n"); | |
| 63 sb.append("Array.prototype.foo = function() {}\n"); | |
| 64 sb.append("function execute() { Array.prototype.foo.call(); }"); | |
| 65 | |
| 66 AstRoot astRoot = parser.parse(sb.toString(), "", 1); | |
| 67 astRoot.visit(topLevelElementIndexer); | |
| 68 AstNode executeFunction = (AstNode) astRoot.getLastChild(); | |
| 69 List<JavascriptElement> computedDependencies = | |
| 70 dependencyComputer.computeDependencies(executeFunction); | |
| 71 assertNotNull(computedDependencies); | |
| 72 | |
| 73 /* | |
| 74 * The foo method is added to the native Array object's prototype directly,
ensure that we found | |
| 75 * it. | |
| 76 */ | |
| 77 assertEquals(1, computedDependencies.size()); | |
| 78 } | |
| 79 | |
| 80 /** | |
| 81 * Tests that we do add a virtual dependency to a member of an instantiated | |
| 82 * class even though its name is shadowed by a local variable. | |
| 83 */ | |
| 84 public void testLocalVariableShadowingOfMemberOfInstantiatedClass() { | |
| 85 StringBuilder sb = new StringBuilder(); | |
| 86 sb.append("function A() {}\n"); | |
| 87 sb.append("A.prototype.foo = function() {}\n"); | |
| 88 sb.append("function B() {}\n"); | |
| 89 sb.append("B.prototype.foo = function() {}\n"); | |
| 90 sb.append("function execute() { var foo = 1; new A(); this.foo(); }"); | |
| 91 | |
| 92 AstRoot astRoot = parser.parse(sb.toString(), "", 1); | |
| 93 astRoot.visit(topLevelElementIndexer); | |
| 94 AstNode executeFunction = (AstNode) astRoot.getLastChild(); | |
| 95 List<JavascriptElement> computedDependencies = | |
| 96 dependencyComputer.computeDependencies(executeFunction); | |
| 97 assertNotNull(computedDependencies); | |
| 98 | |
| 99 /* | |
| 100 * The foo inside of execute method should lexically resolve to the local | |
| 101 * variable foo, but this.foo() introduces a dependency on A.prototype.foo s
ince A is | |
| 102 * instantiated and foo is qualified. | |
| 103 */ | |
| 104 assertEquals(2, computedDependencies.size()); | |
| 105 } | |
| 106 | |
| 107 /** | |
| 108 * Tests that referencing a static method through only pulls in the static | |
| 109 * method and the enclosing function. | |
| 110 */ | |
| 111 public void testStaticReferencesToStaticMethods() { | |
| 112 StringBuilder sb = new StringBuilder(); | |
| 113 sb.append("function A() {}\n"); | |
| 114 sb.append("A.prototype.foo = function() {}\n"); | |
| 115 sb.append("function B() {}\n"); | |
| 116 sb.append("B.foo = function() {}\n"); | |
| 117 sb.append("function execute() { B.foo(); }"); | |
| 118 | |
| 119 AstRoot astRoot = parser.parse(sb.toString(), "", 1); | |
| 120 astRoot.visit(topLevelElementIndexer); | |
| 121 AstNode executeFunction = (AstNode) astRoot.getLastChild(); | |
| 122 List<JavascriptElement> computedDependencies = | |
| 123 dependencyComputer.computeDependencies(executeFunction); | |
| 124 assertNotNull(computedDependencies); | |
| 125 | |
| 126 // Computed dependencies should be B and B.foo | |
| 127 assertEquals(2, computedDependencies.size()); | |
| 128 List<JavascriptElement> list = new ArrayList<JavascriptElement>(namesToEleme
nts.get("B")); | |
| 129 list.addAll(namesToElements.get("B.foo")); | |
| 130 assertEquals(list, computedDependencies); | |
| 131 } | |
| 132 | |
| 133 /** | |
| 134 * Tests that referencing a virtual method through a static reference doesn't | |
| 135 * introduce a virtual reference to the method. | |
| 136 */ | |
| 137 public void testStaticReferencesToVirtualMethods() { | |
| 138 StringBuilder sb = new StringBuilder(); | |
| 139 sb.append("function A() {}\n"); | |
| 140 sb.append("A.prototype.foo = function() {}\n"); | |
| 141 sb.append("function execute() { A.prototype.foo.call(this); }"); | |
| 142 AstRoot astRoot = parser.parse(sb.toString(), "", 1); | |
| 143 astRoot.visit(topLevelElementIndexer); | |
| 144 AstNode executeFunction = (AstNode) astRoot.getLastChild(); | |
| 145 List<JavascriptElement> computedDependencies = | |
| 146 dependencyComputer.computeDependencies(executeFunction); | |
| 147 assertNotNull(computedDependencies); | |
| 148 assertEquals(1, computedDependencies.size()); | |
| 149 | |
| 150 // Static reference to A.prototype.foo | |
| 151 assertEquals(namesToElements.get("A.prototype.foo"), computedDependencies); | |
| 152 } | |
| 153 | |
| 154 /** | |
| 155 * Tests that referencing a virtual method only pulls in similarly named | |
| 156 * virtual methods on classes that have been instantiated.d | |
| 157 */ | |
| 158 public void testVirtualReferences() { | |
| 159 StringBuilder sb = new StringBuilder(); | |
| 160 sb.append("function A() {}\n"); | |
| 161 sb.append("A.prototype.foo = function() {}\n"); | |
| 162 sb.append("function B() {}\n"); | |
| 163 sb.append("B.prototype.foo = function() {}\n"); | |
| 164 sb.append("function execute() { new A(); foo(); }"); | |
| 165 | |
| 166 AstRoot astRoot = parser.parse(sb.toString(), "", 1); | |
| 167 astRoot.visit(topLevelElementIndexer); | |
| 168 AstNode executeFunction = (AstNode) astRoot.getLastChild(); | |
| 169 List<JavascriptElement> computedDependencies = | |
| 170 dependencyComputer.computeDependencies(executeFunction); | |
| 171 assertNotNull(computedDependencies); | |
| 172 | |
| 173 /* | |
| 174 * Expect a dependency on A and A.prototype.foo, B was not instantiated so | |
| 175 * B.prototype.foo does not qualify | |
| 176 */ | |
| 177 assertEquals(2, computedDependencies.size()); | |
| 178 List<JavascriptElement> list = new ArrayList<JavascriptElement>(namesToEleme
nts.get("A")); | |
| 179 list.addAll(namesToElements.get("A.prototype.foo")); | |
| 180 assertEquals(list, computedDependencies); | |
| 181 } | |
| 182 } | |
| OLD | NEW |