/** * Test for one of the bugs causing issue 8284. JsObfuscateNamer was used to assign obfuscated * names to deduped functions and as a result it might have modified the other names that had been * assigned invalidating the irrevocable decision made by the deduper. */ public void testRerunNamerError() throws Exception { JsProgram program = new JsProgram(); // Reference to a in _.b is to the top level scope a function where the one in _.c is to the // local a definition. // // After deduping _.b and _.c the identifier a in the deduped function points to the top level // scope a function and runing a namer afterwards makes the deduping invalid. // CAVEAT: The two functions that have {return a;} as their bodies are not actually duplicates // but we use them to model functions that refer to names at different scopes. Because this // optimization only runs on JsFunctions that come from Java source this situation does not // happen. String js = "var c; function a(){return f1;}; function f1() {_.b = function() {return a;} }; " + "function f2() { var a = null; _.c = function() {return a;} };f1();f2();_.b();_.c();"; List<JsStatement> input = JsParser.parse(SourceOrigin.UNKNOWN, program.getScope(), new StringReader(js)); program.getGlobalBlock().getStatements().addAll(input); // Mark all functions as if they were translated from Java sources. setAllFromJava(program); // Get the JsNames for the top level a and the f2() scoped a. JsName topScope_a = program.getScope().findExistingName("a"); JsName f2_a = null; for (JsScope scope : program.getScope().getChildren()) { if (scope.toString().startsWith("function f2->")) { f2_a = scope.findExistingName("a"); } } assertTrue(topScope_a != f2_a); optimize(program, JsSymbolResolver.class, JsDuplicateFunctionRemoverProxy.class); // collect values assigned to some identifiers. final Map<String, JsName> assignments = AssignmentGatherer.exec(program); // If the function have been dedupped then there is a constraint that the different JsNames // they referred to are obfuscated to the same id. // Hence if _.c and _.b are collapsed the top scope name "a" and the one in f2() need to remain // the same. assertTrue( assignments.get("_.b") != assignments.get("_.c") || topScope_a.getShortIdent().equals(f2_a.getShortIdent())); }
private static void addPropertyToObject( SourceInfo sourceInfo, JsName propertyName, long propertyValue, JsObjectLiteral objectLiteral) { JsExpression label = propertyName.makeRef(sourceInfo); JsExpression value = new JsNumberLiteral(sourceInfo, propertyValue); objectLiteral.addProperty(sourceInfo, label, value); }
private Node transform(JsNameRef x) { Node n; JsName name = x.getName(); boolean isExternal = name == null || !name.isObfuscatable(); if (x.getQualifier() != null) { n = IR.getprop(transform(x.getQualifier()), transformNameAsString(x.getShortIdent(), x)); if (isExternal) { this.externalProperties.add(x.getShortIdent()); } } else { n = transformName(x.getShortIdent(), x); if (isExternal) { this.externalVars.add(x.getShortIdent()); } else if (name.getEnclosing() == program.getScope()) { this.globalVars.add(x.getShortIdent()); } } applyOriginalName(n, x); return applySourceInfo(n, x); }
@Override protected void visit(JsScope scope) { // Visit children. for (JsScope child : scope.getChildren()) { visit(child); } // Visit all my idents. for (JsName name : scope.getAllNames()) { if (!referenced.contains(name)) { // Don't allocate idents for non-referenced names. continue; } if (!name.isObfuscatable()) { // Unobfuscatable names become themselves. name.setShortIdent(name.getIdent()); continue; } String fullIdent = name.getIdent(); // Fixes package-info.java classes. fullIdent = fullIdent.replace("-", "_"); if (!isLegal(fullIdent)) { String checkIdent; for (int i = 0; true; ++i) { checkIdent = fullIdent + "_" + i; if (isLegal(checkIdent)) { break; } } name.setShortIdent(checkIdent); } else { // set each name's short ident to its full ident name.setShortIdent(fullIdent); } } }
/** * Verifies the JavaScript function corresponding to <code>test.EntryPoint.onModuleLoad</code>. */ private static void checkOnModuleLoad(JsProgram program, String expectedJavascript) { JsName onModuleLoad = program.getScope().findExistingName("test_EntryPoint_onModuleLoad__V"); assertNotNull(onModuleLoad); assert onModuleLoad.getStaticRef() instanceof JsFunction; assertEquals(expectedJavascript, serializeJs(onModuleLoad.getStaticRef())); }
private Node transformName(JsName name) { Node n = IR.name(getName(name)); return applySourceInfo(n, name.getStaticRef()); }
private Node transformLabel(JsName label) { Node n = IR.labelName(getName(label)); return applySourceInfo(n, label.getStaticRef()); }
private String getName(JsName name) { return name.getShortIdent(); }