8019585: Sometimes a var declaration using itself in its init wasn't declared as canBeUndefined, causing erroneous bytecode
Reviewed-by: sundar, attila
--- 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);
+}