Emit correct code for @JsMethod varargs when arguments is shadowed.
Change-Id: I532157dadc2b017888025bedebb9000f2810f1ab
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/NameClashesFixer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/NameClashesFixer.java
index ca63dfe37..359b938 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/NameClashesFixer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/NameClashesFixer.java
@@ -18,11 +18,16 @@
import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JBlock;
import com.google.gwt.dev.jjs.ast.JFieldRef;
+import com.google.gwt.dev.jjs.ast.JLocal;
+import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodBody;
+import com.google.gwt.dev.jjs.ast.JModVisitor;
+import com.google.gwt.dev.jjs.ast.JParameter;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JVariable;
import com.google.gwt.dev.jjs.ast.JVariableRef;
import com.google.gwt.dev.jjs.ast.JVisitor;
+import com.google.gwt.thirdparty.guava.common.collect.ImmutableSet;
import com.google.gwt.thirdparty.guava.common.collect.LinkedHashMultimap;
import com.google.gwt.thirdparty.guava.common.collect.Maps;
import com.google.gwt.thirdparty.guava.common.collect.Multimap;
@@ -222,8 +227,42 @@
}
public static void exec(JProgram program) {
+ // Rename variables that should not be shadowed.
+ new JModVisitor() {
+ @Override
+ public boolean visit(JMethod method, Context ctx) {
+ return !method.isJsniMethod() && method.isJsMethodVarargs();
+ }
+
+ @Override
+ public void endVisit(JLocal variable, Context ctx) {
+ maybeRename(variable);
+ }
+
+ @Override
+ public void endVisit(JParameter parameter, Context ctx) {
+ maybeRename(parameter);
+ }
+ }.accept(program);
+
+ // Resolve clashes.
new FixNameClashesVisitor().accept(program);
}
+
+ private static Set<String> unshadowableNames = ImmutableSet.of("arguments");
+
+ private static void maybeRename(JVariable variable) {
+ // In normal scenarios local variables from our Java programs will shadow existing JavaScript
+ // variables. The only exception is the implicit "arguments" variable which should not be
+ // shadowed.
+ // There is no need to care about collisions here as the JVariable object is what defines a
+ // variable, not its name; FixNameClashesVisitor, run immediately after, will ensure that names
+ // do not clash.
+ if (unshadowableNames.contains(variable.getName())) {
+ variable.setName("_" + variable.getName());
+ }
+ }
+
private NameClashesFixer() {
}
}
diff --git a/user/test/com/google/gwt/dev/jjs/test/CompilerMiscRegressionTest.java b/user/test/com/google/gwt/dev/jjs/test/CompilerMiscRegressionTest.java
index 26ca07c..d9897a6 100644
--- a/user/test/com/google/gwt/dev/jjs/test/CompilerMiscRegressionTest.java
+++ b/user/test/com/google/gwt/dev/jjs/test/CompilerMiscRegressionTest.java
@@ -30,11 +30,13 @@
import com.google.gwt.junit.client.GWTTestCase;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javaemul.internal.annotations.DoNotInline;
+import jsinterop.annotations.JsMethod;
import jsinterop.annotations.JsPackage;
import jsinterop.annotations.JsProperty;
import jsinterop.annotations.JsType;
@@ -369,4 +371,34 @@
final AbstractNativeType o = createAbstractNativeType("Hello");
assertEquals("Hello", o.getTextContent());
}
+
+ @JsMethod
+ private static List<String> singletonFrom(int i, String... arguments) {
+ // Make the second parameter varargs and pass it as a whole to trigger the arguments copying
+ // preamble.
+ return Arrays.asList(arguments).subList(i,i + 1);
+ }
+
+ @JsMethod
+ private static List<String> argumentsParameterClasher(int arguments, String... others) {
+ // Make the second parameter varargs and pass it as a whole to trigger the arguments copying
+ // preamble.
+ return Arrays.asList(others).subList(0, arguments);
+ }
+
+ @JsMethod
+ private static List<String> argumentsVariableClasher(int i, String... others) {
+ // Make the second parameter varargs and pass it as a whole to trigger the arguments copying
+ // preamble.
+ {
+ int arguments = 3;
+ }
+ return Arrays.asList(others).subList(0, i);
+ }
+
+ public void testVarargsNamedArguments() {
+ assertEquals("GoodBye", singletonFrom(1, "Hello", "GoodBye").get(0));
+ assertEquals("Hello", argumentsParameterClasher(1, "Hello", "GoodBye").get(0));
+ assertEquals("Hello", argumentsVariableClasher(1, "Hello", "GoodBye").get(0));
+ }
}