/** * Test for one of the bugs causing issue 8284. JsObfuscateNamer was reassigning the same names * across different fragments. */ public void testDuplicateNamesWithCodeSplitterError() 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. String fragment0js = "_.a=function (){return _.a;}; _.b=function (){return _.a}; _.a();_.b();"; String fragment1js = "_.c=function (){return _.c;}; _.d=function (){return _.c}; _.c();_.d();"; List<JsStatement> fragment0 = JsParser.parse(SourceOrigin.UNKNOWN, program.getScope(), new StringReader(fragment0js)); List<JsStatement> fragment1 = JsParser.parse(SourceOrigin.UNKNOWN, program.getScope(), new StringReader(fragment1js)); program.setFragmentCount(2); program.getFragmentBlock(0).getStatements().addAll(fragment0); program.getFragmentBlock(1).getStatements().addAll(fragment1); // Mark all functions as if they were translated from Java sources. setAllFromJava(program); optimize(program, JsSymbolResolver.class, JsDuplicateFunctionRemoverProxy.class); // There should be two distinct dedupped functions here. MockNameGenerator tempFreshNameGenerator = new MockNameGenerator(); String firstName = tempFreshNameGenerator.getFreshName(); String secondName = tempFreshNameGenerator.getFreshName(); assertNotNull(program.getScope().findExistingName(secondName)); }
/** * 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 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); }
public void testVirtualRemoveDuplicates() throws Exception { JsProgram program = new JsProgram(); String js = "_.method1=function(){};_.method2=function(){};_.method1();_.method2();"; 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); String firstName = new MockNameGenerator().getFreshName(); assertEquals( "_.method1=" + firstName + ";_.method2=" + firstName + ";_.method1();_.method2();function " + firstName + "(){}\n", optimize(program, JsSymbolResolver.class, JsDuplicateFunctionRemoverProxy.class)); }
/** * 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())); }
protected final void execImpl() { reset(); visit(program.getScope()); reset(); visit(program.getObjectScope()); }