Stephen Haberman has submitted this change and it was merged.

Change subject: Fix non-final field initializers running before the super cstr.
......................................................................


Fix non-final field initializers running before the super cstr.

Previously, any field with an initializer would get assigned at
the top-level scope, before any cstrs had run.

However, this does not match the JVM behavior, which is that final fields behave
this way, but non-field fields have their type's default value assigned when
super cstrs run, and then only later in their cstr are assigned to the initializer.

Bug: issue 380
Change-Id: I4c8ed0cd718a2188b33cc290fec6071c89be7918
---
M dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
M user/test/com/google/gwt/dev/jjs/test/CompilerTest.java
A user/test/com/google/gwt/dev/jjs/test/FieldInitOrderBase.java
A user/test/com/google/gwt/dev/jjs/test/FieldInitOrderChild.java
4 files changed, 113 insertions(+), 10 deletions(-)

Approvals:
  Roberto Lublinerman: Looks good to me, approved
  Leeroy Jenkins: Verified



diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
index c0e1423..240f6a0 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
@@ -857,10 +857,13 @@
       JsNameRef localRef = (JsNameRef) pop(); // localRef

       JVariable target = x.getVariableRef().getTarget();
- if (target instanceof JField && ((JField) target).getLiteralInitializer() != null) {
-        // Will initialize at top scope; no need to double-initialize.
-        push(null);
-        return;
+      if (target instanceof JField) {
+        JField field = (JField) target;
+ if (field.getLiteralInitializer() != null && (field.isStatic() || field.isFinal())) {
+          // Will initialize at top scope; no need to double-initialize.
+          push(null);
+          return;
+        }
       }

       JsBinaryOperation binOp =
@@ -890,15 +893,15 @@
     @Override
     public void endVisit(JField x, Context ctx) {
       // if we need an initial value, create an assignment
-      if (x.getLiteralInitializer() != null) {
+ if (x.getLiteralInitializer() != null && (x.isFinal() || x.isStatic())) {
         // setup the constant value
         accept(x.getLiteralInitializer());
- } else if (!x.hasInitializer() && x.getEnclosingType() != program.getTypeJavaLangObject()) {
-        // setup a default value
-        accept(x.getType().getDefaultValue());
-      } else {
-        // the variable is setup during clinit, no need to initialize here
+      } else if (x.getEnclosingType() == program.getTypeJavaLangObject()) {
+        // Special fields whose initialization is done somewhere else.
         push(null);
+      } else {
+        // setup the default value, see Issue 380
+        accept(x.getType().getDefaultValue());
       }
       JsExpression rhs = (JsExpression) pop();
       JsName name = names.get(x);
diff --git a/user/test/com/google/gwt/dev/jjs/test/CompilerTest.java b/user/test/com/google/gwt/dev/jjs/test/CompilerTest.java
index 4107144..812c6bb 100644
--- a/user/test/com/google/gwt/dev/jjs/test/CompilerTest.java
+++ b/user/test/com/google/gwt/dev/jjs/test/CompilerTest.java
@@ -787,6 +787,14 @@
     assertEquals(1, x);
   }

+ /** Ensure that only final fields are initializers when cstrs run, see issue 380. */
+  public void testFieldInitializationOrder() {
+    ArrayList<String> seenValues = new ArrayList<String>();
+    new FieldInitOrderChild(seenValues);
+ assertEquals("i1=1,i2=0,i3=null,i4=null,i5=1,i6=1,i7=1", seenValues.get(0));
+    assertEquals("i1=1,i2=1,i3=1,i4=2,i5=1,i6=2,i7=2", seenValues.get(1));
+  }
+
   public void testForStatement() {
     {
       int i;
diff --git a/user/test/com/google/gwt/dev/jjs/test/FieldInitOrderBase.java b/user/test/com/google/gwt/dev/jjs/test/FieldInitOrderBase.java
new file mode 100644
index 0000000..de1146b
--- /dev/null
+++ b/user/test/com/google/gwt/dev/jjs/test/FieldInitOrderBase.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dev.jjs.test;
+
+import java.util.ArrayList;
+
+/**
+ * A superclass that invokes a method in its cstr, so that subclasses can see their state before
+ * their own cstr has run.
+ *
+ * See {@link CompilerTest#testFieldInitializationOrder()}.
+ */
+class FieldInitOrderBase {
+  FieldInitOrderBase(ArrayList<String> seenValues, int x) {
+    method(seenValues, x);
+  }
+
+  void method(ArrayList<String> seenValues, int x) {
+  }
+}
\ No newline at end of file
diff --git a/user/test/com/google/gwt/dev/jjs/test/FieldInitOrderChild.java b/user/test/com/google/gwt/dev/jjs/test/FieldInitOrderChild.java
new file mode 100644
index 0000000..dc00759
--- /dev/null
+++ b/user/test/com/google/gwt/dev/jjs/test/FieldInitOrderChild.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dev.jjs.test;
+
+import java.util.ArrayList;
+
+/**
+ * A subclass that overrides {@link #method(ArrayList, int)} to see what the values of its own + * fields are from within the superclass's cstr (before our own cstr has run).
+ *
+ * See {@link CompilerTest#testFieldInitializationOrder()}.
+ */
+class FieldInitOrderChild extends FieldInitOrderBase {
+
+  private final int i1 = 1;
+  private int i2 = 1;
+  private Integer i3 = new Integer(1);
+  private Integer i4;
+  private final static int i5 = 1;
+  private static int i6 = 1;
+  private static Integer i7 = new Integer(1);
+
+  FieldInitOrderChild(ArrayList<String> seenValues) {
+ // the superclass calls method(), which will record the pre-cstr value of our fields
+    super(seenValues, 2);
+    recordValues(seenValues);
+  }
+
+  // invoked by the super classes before our cstr has run
+  @Override
+  void method(ArrayList<String> seenValues, int x) {
+    recordValues(seenValues);
+    // i1 is final
+    i2 = x;
+    i3 = new Integer(x);
+    i4 = new Integer(x);
+    // i5 is final
+    i6 = 2;
+    i7 = new Integer(x);
+  }
+
+  private void recordValues(ArrayList<String> seenValues) {
+ seenValues.add("i1=" + i1 + ",i2=" + i2 + ",i3=" + i3 + ",i4=" + i4 + ",i5=" + i5 + ",i6=" + i6
+        + ",i7=" + i7);
+  }
+}
\ No newline at end of file

--
To view, visit https://gwt-review.googlesource.com/3030
To unsubscribe, visit https://gwt-review.googlesource.com/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I4c8ed0cd718a2188b33cc290fec6071c89be7918
Gerrit-PatchSet: 8
Gerrit-Project: gwt
Gerrit-Branch: master
Gerrit-Owner: Stephen Haberman <[email protected]>
Gerrit-Reviewer: Leeroy Jenkins <[email protected]>
Gerrit-Reviewer: Matthew Dempsky <[email protected]>
Gerrit-Reviewer: Ray Cromwell <[email protected]>
Gerrit-Reviewer: Roberto Lublinerman <[email protected]>
Gerrit-Reviewer: Stephen Haberman <[email protected]>

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors
--- You received this message because you are subscribed to the Google Groups "GWT Contributors" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to