8019585: Sometimes a var declaration using itself in its init wasn't declared as canBeUndefined, causing erroneous bytecode
authorlagergren
Wed, 03 Jul 2013 13:03:36 +0200
changeset 18842 3c3be808b593
parent 18841 9bbc4b8832b2
child 18843 eea6d1b8263e
8019585: Sometimes a var declaration using itself in its init wasn't declared as canBeUndefined, causing erroneous bytecode Reviewed-by: sundar, attila
nashorn/src/jdk/nashorn/api/scripting/NashornException.java
nashorn/src/jdk/nashorn/internal/codegen/Attr.java
nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java
nashorn/src/jdk/nashorn/internal/objects/ArrayBufferView.java
nashorn/src/jdk/nashorn/internal/objects/Global.java
nashorn/src/jdk/nashorn/internal/objects/NativeError.java
nashorn/src/jdk/nashorn/internal/objects/NativeFloat32Array.java
nashorn/src/jdk/nashorn/internal/objects/NativeFloat64Array.java
nashorn/src/jdk/nashorn/internal/objects/NativeFunction.java
nashorn/src/jdk/nashorn/internal/objects/NativeInt16Array.java
nashorn/src/jdk/nashorn/internal/objects/NativeInt32Array.java
nashorn/src/jdk/nashorn/internal/objects/NativeInt8Array.java
nashorn/src/jdk/nashorn/internal/objects/NativeJava.java
nashorn/src/jdk/nashorn/internal/objects/NativeObject.java
nashorn/src/jdk/nashorn/internal/objects/NativeRegExp.java
nashorn/src/jdk/nashorn/internal/objects/NativeUint16Array.java
nashorn/src/jdk/nashorn/internal/objects/NativeUint32Array.java
nashorn/src/jdk/nashorn/internal/objects/NativeUint8Array.java
nashorn/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java
nashorn/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java
nashorn/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java
nashorn/test/script/basic/JDK-8019585.js
--- a/nashorn/src/jdk/nashorn/api/scripting/NashornException.java	Wed Jul 03 12:39:28 2013 +0200
+++ b/nashorn/src/jdk/nashorn/api/scripting/NashornException.java	Wed Jul 03 13:03:36 2013 +0200
@@ -146,7 +146,7 @@
      * @return array of javascript stack frames
      */
     public static StackTraceElement[] getScriptFrames(final Throwable exception) {
-        final StackTraceElement[] frames = ((Throwable)exception).getStackTrace();
+        final StackTraceElement[] frames = exception.getStackTrace();
         final List<StackTraceElement> filtered = new ArrayList<>();
         for (final StackTraceElement st : frames) {
             if (ECMAErrors.isScriptFrame(st)) {
@@ -170,7 +170,7 @@
      */
     public static String getScriptStackString(final Throwable exception) {
         final StringBuilder buf = new StringBuilder();
-        final StackTraceElement[] frames = getScriptFrames((Throwable)exception);
+        final StackTraceElement[] frames = getScriptFrames(exception);
         for (final StackTraceElement st : frames) {
             buf.append("\tat ");
             buf.append(st.getMethodName());
--- a/nashorn/src/jdk/nashorn/internal/codegen/Attr.java	Wed Jul 03 12:39:28 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Attr.java	Wed Jul 03 13:03:36 2013 +0200
@@ -54,6 +54,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
+
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.AccessNode;
 import jdk.nashorn.internal.ir.BinaryNode;
@@ -234,10 +235,25 @@
             @Override
             public boolean enterVarNode(final VarNode varNode) {
                 final String name = varNode.getName().getName();
-                //if this is used the var node symbol needs to be tagged as can be undefined
+                //if this is used before the var node, the var node symbol needs to be tagged as can be undefined
                 if (uses.contains(name)) {
                     canBeUndefined.add(name);
                 }
+
+                // all uses of the declared varnode inside the var node are potentially undefined
+                // however this is a bit conservative as e.g. var x = 17; var x = 1 + x; does work
+                if (!varNode.isFunctionDeclaration() && varNode.getInit() != null) {
+                    varNode.getInit().accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+                       @Override
+                       public boolean enterIdentNode(final IdentNode identNode) {
+                           if (name.equals(identNode.getName())) {
+                              canBeUndefined.add(name);
+                           }
+                           return false;
+                       }
+                    });
+                }
+
                 return true;
             }
 
@@ -257,6 +273,7 @@
                     }
                     return varNode.setName((IdentNode)ident.setSymbol(lc, symbol));
                 }
+
                 return varNode;
             }
         });
--- a/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Wed Jul 03 12:39:28 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java	Wed Jul 03 13:03:36 2013 +0200
@@ -1847,7 +1847,7 @@
             // If expression not int see if we can convert, if not use deflt to trigger default.
             if (!type.isInteger()) {
                 method.load(deflt);
-                final Class exprClass = type.getTypeClass();
+                final Class<?> exprClass = type.getTypeClass();
                 method.invoke(staticCallNoLookup(ScriptRuntime.class, "switchTagAsInt", int.class, exprClass.isPrimitive()? exprClass : Object.class, int.class));
             }
 
--- a/nashorn/src/jdk/nashorn/internal/objects/ArrayBufferView.java	Wed Jul 03 12:39:28 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/ArrayBufferView.java	Wed Jul 03 13:03:36 2013 +0200
@@ -40,6 +40,7 @@
 abstract class ArrayBufferView extends ScriptObject {
 
     // initialized by nasgen
+    @SuppressWarnings("unused")
     private static PropertyMap $nasgenmap$;
 
     ArrayBufferView(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
--- a/nashorn/src/jdk/nashorn/internal/objects/Global.java	Wed Jul 03 12:39:28 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/Global.java	Wed Jul 03 13:03:36 2013 +0200
@@ -382,6 +382,7 @@
     private final Context context;
 
     // initialized by nasgen
+    @SuppressWarnings("unused")
     private static PropertyMap $nasgenmap$;
 
     /**
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeError.java	Wed Jul 03 12:39:28 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeError.java	Wed Jul 03 13:03:36 2013 +0200
@@ -119,6 +119,7 @@
      * Nashorn extension: Error.captureStackTrace. Capture stack trace at the point of call into the Error object provided.
      *
      * @param self self reference
+     * @param errorObj the error object
      * @return undefined
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
@@ -286,9 +287,9 @@
         final Object exception = ECMAException.getException(sobj);
         if (exception instanceof Throwable) {
             return getScriptStackString(sobj, (Throwable)exception);
-        } else {
-            return "";
         }
+
+        return "";
     }
 
     /**
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeFloat32Array.java	Wed Jul 03 12:39:28 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeFloat32Array.java	Wed Jul 03 13:03:36 2013 +0200
@@ -48,6 +48,7 @@
     public static final int BYTES_PER_ELEMENT = 4;
 
     // initialized by nasgen
+    @SuppressWarnings("unused")
     private static PropertyMap $nasgenmap$;
 
     private static final Factory FACTORY = new Factory(BYTES_PER_ELEMENT) {
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeFloat64Array.java	Wed Jul 03 12:39:28 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeFloat64Array.java	Wed Jul 03 13:03:36 2013 +0200
@@ -48,6 +48,7 @@
     public static final int BYTES_PER_ELEMENT = 8;
 
     // initialized by nasgen
+    @SuppressWarnings("unused")
     private static PropertyMap $nasgenmap$;
 
     private static final Factory FACTORY = new Factory(BYTES_PER_ELEMENT) {
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeFunction.java	Wed Jul 03 12:39:28 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeFunction.java	Wed Jul 03 13:03:36 2013 +0200
@@ -29,6 +29,7 @@
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 
 import java.util.List;
+
 import jdk.nashorn.api.scripting.ScriptObjectMirror;
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Constructor;
@@ -55,6 +56,7 @@
 public final class NativeFunction {
 
     // initialized by nasgen
+    @SuppressWarnings("unused")
     private static PropertyMap $nasgenmap$;
 
     // do *not* create me!
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeInt16Array.java	Wed Jul 03 12:39:28 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeInt16Array.java	Wed Jul 03 13:03:36 2013 +0200
@@ -42,6 +42,7 @@
 public final class NativeInt16Array extends ArrayBufferView {
 
     // initialized by nasgen
+    @SuppressWarnings("unused")
     private static PropertyMap $nasgenmap$;
 
     /**
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeInt32Array.java	Wed Jul 03 12:39:28 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeInt32Array.java	Wed Jul 03 13:03:36 2013 +0200
@@ -47,6 +47,7 @@
     public static final int BYTES_PER_ELEMENT = 4;
 
     // initialized by nasgen
+    @SuppressWarnings("unused")
     private static PropertyMap $nasgenmap$;
 
     private static final Factory FACTORY = new Factory(BYTES_PER_ELEMENT) {
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeInt8Array.java	Wed Jul 03 12:39:28 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeInt8Array.java	Wed Jul 03 13:03:36 2013 +0200
@@ -47,6 +47,7 @@
     public static final int BYTES_PER_ELEMENT = 1;
 
     // initialized by nasgen
+    @SuppressWarnings("unused")
     private static PropertyMap $nasgenmap$;
 
     private static final Factory FACTORY = new Factory(BYTES_PER_ELEMENT) {
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeJava.java	Wed Jul 03 12:39:28 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeJava.java	Wed Jul 03 13:03:36 2013 +0200
@@ -32,6 +32,7 @@
 import java.util.Collection;
 import java.util.Deque;
 import java.util.List;
+
 import jdk.internal.dynalink.beans.StaticClass;
 import jdk.internal.dynalink.support.TypeUtilities;
 import jdk.nashorn.internal.objects.annotations.Attribute;
@@ -54,6 +55,7 @@
 public final class NativeJava {
 
     // initialized by nasgen
+    @SuppressWarnings("unused")
     private static PropertyMap $nasgenmap$;
 
     private NativeJava() {
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeObject.java	Wed Jul 03 12:39:28 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeObject.java	Wed Jul 03 13:03:36 2013 +0200
@@ -27,7 +27,6 @@
 
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
-
 import jdk.nashorn.api.scripting.ScriptObjectMirror;
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Constructor;
@@ -55,6 +54,7 @@
     private static final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
 
     // initialized by nasgen
+    @SuppressWarnings("unused")
     private static PropertyMap $nasgenmap$;
 
     private NativeObject() {
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeRegExp.java	Wed Jul 03 12:39:28 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeRegExp.java	Wed Jul 03 13:03:36 2013 +0200
@@ -68,6 +68,7 @@
     private Global globalObject;
 
     // initialized by nasgen
+    @SuppressWarnings("unused")
     private static PropertyMap $nasgenmap$;
 
     NativeRegExp(final String input, final String flagString) {
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeUint16Array.java	Wed Jul 03 12:39:28 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint16Array.java	Wed Jul 03 13:03:36 2013 +0200
@@ -47,6 +47,7 @@
     public static final int BYTES_PER_ELEMENT = 2;
 
     // initialized by nasgen
+    @SuppressWarnings("unused")
     private static PropertyMap $nasgenmap$;
 
     private static final Factory FACTORY = new Factory(BYTES_PER_ELEMENT) {
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeUint32Array.java	Wed Jul 03 12:39:28 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint32Array.java	Wed Jul 03 13:03:36 2013 +0200
@@ -48,6 +48,7 @@
     public static final int BYTES_PER_ELEMENT = 4;
 
     // initialized by nasgen
+    @SuppressWarnings("unused")
     private static PropertyMap $nasgenmap$;
 
     private static final Factory FACTORY = new Factory(BYTES_PER_ELEMENT) {
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeUint8Array.java	Wed Jul 03 12:39:28 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint8Array.java	Wed Jul 03 13:03:36 2013 +0200
@@ -47,6 +47,7 @@
     public static final int BYTES_PER_ELEMENT = 1;
 
     // initialized by nasgen
+    @SuppressWarnings("unused")
     private static PropertyMap $nasgenmap$;
 
     private static final Factory FACTORY = new Factory(BYTES_PER_ELEMENT) {
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java	Wed Jul 03 12:39:28 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java	Wed Jul 03 13:03:36 2013 +0200
@@ -48,6 +48,7 @@
     public static final int BYTES_PER_ELEMENT = 1;
 
     // initialized by nasgen
+    @SuppressWarnings("unused")
     private static PropertyMap $nasgenmap$;
 
     private static final Factory FACTORY = new Factory(BYTES_PER_ELEMENT) {
--- a/nashorn/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java	Wed Jul 03 12:39:28 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java	Wed Jul 03 13:03:36 2013 +0200
@@ -149,12 +149,13 @@
         return typeErrorThrower;
     }
 
-    private static PropertyMap createStrictModeMap(PropertyMap map) {
+    private static PropertyMap createStrictModeMap(final PropertyMap map) {
         final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE;
+        PropertyMap newMap = map;
         // Need to add properties directly to map since slots are assigned speculatively by newUserAccessors.
-        map = map.addProperty(map.newUserAccessors("arguments", flags));
-        map = map.addProperty(map.newUserAccessors("caller", flags));
-        return map;
+        newMap = newMap.addProperty(map.newUserAccessors("arguments", flags));
+        newMap = newMap.addProperty(map.newUserAccessors("caller", flags));
+        return newMap;
     }
 
     // Choose the map based on strict mode!
--- a/nashorn/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java	Wed Jul 03 12:39:28 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java	Wed Jul 03 13:03:36 2013 +0200
@@ -146,7 +146,7 @@
 
     @Override
     public ArrayData setEmpty(final long lo, final long hi) {
-        Arrays.fill(array, (int)Math.max(lo, 0L), (int)Math.min(hi, (long)Integer.MAX_VALUE), ScriptRuntime.EMPTY);
+        Arrays.fill(array, (int)Math.max(lo, 0L), (int)Math.min(hi, Integer.MAX_VALUE), ScriptRuntime.EMPTY);
         return this;
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8019585.js	Wed Jul 03 13:03:36 2013 +0200
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8019585 - use before def issues with vars using the declared var
+ * legal - but needs to set "a" as undefined
+ *
+ * @test
+ * @run
+ */
+
+function f() {
+    var a = b == 17 && (a = toto(b)) && toto2(a); 
+}