8019585: Sometimes a var declaration using itself in its init wasn't declared as canBeUndefined, causing erroneous bytecode
Reviewed-by: sundar, attila
This commit is contained in:
parent
92bcfea39a
commit
62fb002570
nashorn
src/jdk/nashorn
api/scripting
internal
codegen
objects
ArrayBufferView.javaGlobal.javaNativeError.javaNativeFloat32Array.javaNativeFloat64Array.javaNativeFunction.javaNativeInt16Array.javaNativeInt32Array.javaNativeInt8Array.javaNativeJava.javaNativeObject.javaNativeRegExp.javaNativeUint16Array.javaNativeUint32Array.javaNativeUint8Array.javaNativeUint8ClampedArray.javaScriptFunctionImpl.java
runtime/arrays
test/script/basic
@ -146,7 +146,7 @@ public abstract class NashornException extends RuntimeException {
|
||||
* @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 abstract class NashornException extends RuntimeException {
|
||||
*/
|
||||
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());
|
||||
|
@ -54,6 +54,7 @@ import java.util.HashSet;
|
||||
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 @@ final class Attr extends NodeOperatorVisitor<LexicalContext> {
|
||||
@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 @@ final class Attr extends NodeOperatorVisitor<LexicalContext> {
|
||||
}
|
||||
return varNode.setName((IdentNode)ident.setSymbol(lc, symbol));
|
||||
}
|
||||
|
||||
return varNode;
|
||||
}
|
||||
});
|
||||
|
@ -1847,7 +1847,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
|
||||
// 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));
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,7 @@ import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
|
||||
abstract class ArrayBufferView extends ScriptObject {
|
||||
|
||||
// initialized by nasgen
|
||||
@SuppressWarnings("unused")
|
||||
private static PropertyMap $nasgenmap$;
|
||||
|
||||
ArrayBufferView(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
|
||||
|
@ -382,6 +382,7 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
|
||||
private final Context context;
|
||||
|
||||
// initialized by nasgen
|
||||
@SuppressWarnings("unused")
|
||||
private static PropertyMap $nasgenmap$;
|
||||
|
||||
/**
|
||||
|
@ -119,6 +119,7 @@ public final class NativeError extends ScriptObject {
|
||||
* 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 @@ public final class NativeError extends ScriptObject {
|
||||
final Object exception = ECMAException.getException(sobj);
|
||||
if (exception instanceof Throwable) {
|
||||
return getScriptStackString(sobj, (Throwable)exception);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,6 +48,7 @@ public final class NativeFloat32Array extends ArrayBufferView {
|
||||
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) {
|
||||
|
@ -48,6 +48,7 @@ public final class NativeFloat64Array extends ArrayBufferView {
|
||||
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) {
|
||||
|
@ -29,6 +29,7 @@ import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
|
||||
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 @@ import jdk.nashorn.internal.runtime.Source;
|
||||
public final class NativeFunction {
|
||||
|
||||
// initialized by nasgen
|
||||
@SuppressWarnings("unused")
|
||||
private static PropertyMap $nasgenmap$;
|
||||
|
||||
// do *not* create me!
|
||||
|
@ -42,6 +42,7 @@ import jdk.nashorn.internal.runtime.arrays.ArrayData;
|
||||
public final class NativeInt16Array extends ArrayBufferView {
|
||||
|
||||
// initialized by nasgen
|
||||
@SuppressWarnings("unused")
|
||||
private static PropertyMap $nasgenmap$;
|
||||
|
||||
/**
|
||||
|
@ -47,6 +47,7 @@ public final class NativeInt32Array extends ArrayBufferView {
|
||||
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) {
|
||||
|
@ -47,6 +47,7 @@ public final class NativeInt8Array extends ArrayBufferView {
|
||||
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) {
|
||||
|
@ -32,6 +32,7 @@ import java.lang.reflect.Array;
|
||||
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 @@ import jdk.nashorn.internal.runtime.linker.JavaAdapterFactory;
|
||||
public final class NativeJava {
|
||||
|
||||
// initialized by nasgen
|
||||
@SuppressWarnings("unused")
|
||||
private static PropertyMap $nasgenmap$;
|
||||
|
||||
private NativeJava() {
|
||||
|
@ -27,7 +27,6 @@ package jdk.nashorn.internal.objects;
|
||||
|
||||
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 @@ public final class NativeObject {
|
||||
private static final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
|
||||
|
||||
// initialized by nasgen
|
||||
@SuppressWarnings("unused")
|
||||
private static PropertyMap $nasgenmap$;
|
||||
|
||||
private NativeObject() {
|
||||
|
@ -68,6 +68,7 @@ public final class NativeRegExp extends ScriptObject {
|
||||
private Global globalObject;
|
||||
|
||||
// initialized by nasgen
|
||||
@SuppressWarnings("unused")
|
||||
private static PropertyMap $nasgenmap$;
|
||||
|
||||
NativeRegExp(final String input, final String flagString) {
|
||||
|
@ -47,6 +47,7 @@ public final class NativeUint16Array extends ArrayBufferView {
|
||||
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) {
|
||||
|
@ -48,6 +48,7 @@ public final class NativeUint32Array extends ArrayBufferView {
|
||||
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) {
|
||||
|
@ -47,6 +47,7 @@ public final class NativeUint8Array extends ArrayBufferView {
|
||||
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) {
|
||||
|
@ -48,6 +48,7 @@ public final class NativeUint8ClampedArray extends ArrayBufferView {
|
||||
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) {
|
||||
|
@ -149,12 +149,13 @@ public class ScriptFunctionImpl extends ScriptFunction {
|
||||
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!
|
||||
|
@ -146,7 +146,7 @@ final class ObjectArrayData extends ArrayData {
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
|
34
nashorn/test/script/basic/JDK-8019585.js
Normal file
34
nashorn/test/script/basic/JDK-8019585.js
Normal file
@ -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);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user