From 37278377bef0851e1247fff05074b113bf9bd273 Mon Sep 17 00:00:00 2001 From: hannesw Date: Fri, 7 Jun 2013 17:44:25 +0200 Subject: [PATCH] 8012291: NativeArray is inconsistent in using long for length and index in some places and int for the same in other places Reviewed-by: lagergren, jlaskey --- .../internal/codegen/FieldObjectCreator.java | 2 +- .../nashorn/internal/codegen/MapCreator.java | 2 +- .../internal/objects/ArrayBufferView.java | 13 +- .../internal/objects/NativeArguments.java | 91 ++++++----- .../nashorn/internal/objects/NativeArray.java | 24 ++- .../internal/objects/NativeString.java | 25 ++- .../internal/runtime/JSONFunctions.java | 8 +- .../internal/runtime/ScriptObject.java | 147 +++++++++--------- .../internal/runtime/arrays/ArrayIndex.java | 130 +++++----------- .../runtime/arrays/SparseArrayData.java | 8 +- .../runtime/resources/Messages.properties | 1 + test/examples/array-micro.js | 114 ++++++++++++++ test/script/basic/JDK-8012291.js | 48 ++++++ test/script/basic/JDK-8012291.js.EXPECTED | 5 + 14 files changed, 367 insertions(+), 251 deletions(-) create mode 100644 test/examples/array-micro.js create mode 100644 test/script/basic/JDK-8012291.js create mode 100644 test/script/basic/JDK-8012291.js.EXPECTED diff --git a/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java b/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java index 16ad2709..974b5ba8 100644 --- a/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java +++ b/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java @@ -126,7 +126,7 @@ public abstract class FieldObjectCreator extends ObjectCreator { final T value = valueIter.next(); if (symbol != null && value != null) { - final int index = ArrayIndex.getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); if (index < 0) { putField(method, key, symbol.getFieldIndex(), value); diff --git a/src/jdk/nashorn/internal/codegen/MapCreator.java b/src/jdk/nashorn/internal/codegen/MapCreator.java index 153e0367..609fac9b 100644 --- a/src/jdk/nashorn/internal/codegen/MapCreator.java +++ b/src/jdk/nashorn/internal/codegen/MapCreator.java @@ -79,7 +79,7 @@ public class MapCreator { final String key = keys[i]; final Symbol symbol = symbols[i]; - if (symbol != null && !ArrayIndex.isIndexKey(key)) { + if (symbol != null && !ArrayIndex.isIntArrayIndex(key)) { properties.add(new AccessorProperty(key, getPropertyFlags(symbol, hasArguments), structure, symbol.getFieldIndex())); } } diff --git a/src/jdk/nashorn/internal/objects/ArrayBufferView.java b/src/jdk/nashorn/internal/objects/ArrayBufferView.java index d85b31cb..2011daeb 100644 --- a/src/jdk/nashorn/internal/objects/ArrayBufferView.java +++ b/src/jdk/nashorn/internal/objects/ArrayBufferView.java @@ -33,6 +33,8 @@ import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; import jdk.nashorn.internal.runtime.arrays.ArrayData; +import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError; + @ScriptClass("ArrayBufferView") abstract class ArrayBufferView extends ScriptObject { @@ -305,11 +307,11 @@ abstract class ArrayBufferView extends ScriptObject { dst = factory.construct(length); } else if (arg0 instanceof NativeArray) { // Constructor(type[] array) - length = (int) (((NativeArray) arg0).getArray().length() & 0x7fff_ffff); + length = lengthToInt(((NativeArray) arg0).getArray().length()); dst = factory.construct(length); } else { // Constructor(unsigned long length) - length = JSType.toInt32(arg0); + length = lengthToInt(JSType.toInt64(arg0)); return factory.construct(length); } @@ -354,6 +356,13 @@ abstract class ArrayBufferView extends ScriptObject { } } + private static int lengthToInt(final long length) { + if (length > Integer.MAX_VALUE || length < 0) { + throw rangeError("inappropriate.array.buffer.length", JSType.toString(length)); + } + return (int) (length & Integer.MAX_VALUE); + } + protected static Object subarrayImpl(final Object self, final Object begin0, final Object end0) { final ArrayBufferView arrayView = ((ArrayBufferView)self); final int elementLength = arrayView.elementLength(); diff --git a/src/jdk/nashorn/internal/objects/NativeArguments.java b/src/jdk/nashorn/internal/objects/NativeArguments.java index efab674b..d92d7fb3 100644 --- a/src/jdk/nashorn/internal/objects/NativeArguments.java +++ b/src/jdk/nashorn/internal/objects/NativeArguments.java @@ -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 static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndexNoThrow; import static jdk.nashorn.internal.lookup.Lookup.MH; import java.lang.invoke.MethodHandle; @@ -132,103 +131,103 @@ public final class NativeArguments extends ScriptObject { @Override public int getInt(final Object key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return isMapped(index) ? namedArgs.getInt(index) : super.getInt(key); } @Override public int getInt(final double key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return isMapped(index) ? namedArgs.getInt(index) : super.getInt(key); } @Override public int getInt(final long key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return isMapped(index) ? namedArgs.getInt(index) : super.getInt(key); } @Override public int getInt(final int key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return isMapped(index) ? namedArgs.getInt(index) : super.getInt(key); } @Override public long getLong(final Object key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return isMapped(index) ? namedArgs.getLong(index) : super.getLong(key); } @Override public long getLong(final double key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return isMapped(index) ? namedArgs.getLong(index) : super.getLong(key); } @Override public long getLong(final long key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return isMapped(index) ? namedArgs.getLong(index) : super.getLong(key); } @Override public long getLong(final int key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return isMapped(index) ? namedArgs.getLong(index) : super.getLong(key); } @Override public double getDouble(final Object key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return isMapped(index) ? namedArgs.getDouble(index) : super.getDouble(key); } @Override public double getDouble(final double key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return isMapped(index) ? namedArgs.getDouble(index) : super.getDouble(key); } @Override public double getDouble(final long key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return isMapped(index) ? namedArgs.getDouble(index) : super.getDouble(key); } @Override public double getDouble(final int key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return isMapped(index) ? namedArgs.getDouble(index) : super.getDouble(key); } @Override public Object get(final Object key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return isMapped(index) ? namedArgs.getObject(index) : super.get(key); } @Override public Object get(final double key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return isMapped(index) ? namedArgs.getObject(index) : super.get(key); } @Override public Object get(final long key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return isMapped(index) ? namedArgs.getObject(index) : super.get(key); } @Override public Object get(final int key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return isMapped(index) ? namedArgs.getObject(index) : super.get(key); } @Override public void set(final Object key, final int value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); if (isMapped(index)) { namedArgs = namedArgs.set(index, value, strict); } else { @@ -238,7 +237,7 @@ public final class NativeArguments extends ScriptObject { @Override public void set(final Object key, final long value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); if (isMapped(index)) { namedArgs = namedArgs.set(index, value, strict); } else { @@ -248,7 +247,7 @@ public final class NativeArguments extends ScriptObject { @Override public void set(final Object key, final double value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); if (isMapped(index)) { namedArgs = namedArgs.set(index, value, strict); } else { @@ -258,7 +257,7 @@ public final class NativeArguments extends ScriptObject { @Override public void set(final Object key, final Object value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); if (isMapped(index)) { namedArgs = namedArgs.set(index, value, strict); } else { @@ -268,7 +267,7 @@ public final class NativeArguments extends ScriptObject { @Override public void set(final double key, final int value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); if (isMapped(index)) { namedArgs = namedArgs.set(index, value, strict); } else { @@ -278,7 +277,7 @@ public final class NativeArguments extends ScriptObject { @Override public void set(final double key, final long value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); if (isMapped(index)) { namedArgs = namedArgs.set(index, value, strict); } else { @@ -288,7 +287,7 @@ public final class NativeArguments extends ScriptObject { @Override public void set(final double key, final double value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); if (isMapped(index)) { namedArgs = namedArgs.set(index, value, strict); } else { @@ -298,7 +297,7 @@ public final class NativeArguments extends ScriptObject { @Override public void set(final double key, final Object value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); if (isMapped(index)) { namedArgs = namedArgs.set(index, value, strict); } else { @@ -308,7 +307,7 @@ public final class NativeArguments extends ScriptObject { @Override public void set(final long key, final int value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); if (isMapped(index)) { namedArgs = namedArgs.set(index, value, strict); } else { @@ -318,7 +317,7 @@ public final class NativeArguments extends ScriptObject { @Override public void set(final long key, final long value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); if (isMapped(index)) { namedArgs = namedArgs.set(index, value, strict); } else { @@ -328,7 +327,7 @@ public final class NativeArguments extends ScriptObject { @Override public void set(final long key, final double value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); if (isMapped(index)) { namedArgs = namedArgs.set(index, value, strict); } else { @@ -338,7 +337,7 @@ public final class NativeArguments extends ScriptObject { @Override public void set(final long key, final Object value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); if (isMapped(index)) { namedArgs = namedArgs.set(index, value, strict); } else { @@ -348,7 +347,7 @@ public final class NativeArguments extends ScriptObject { @Override public void set(final int key, final int value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); if (isMapped(index)) { namedArgs = namedArgs.set(index, value, strict); } else { @@ -358,7 +357,7 @@ public final class NativeArguments extends ScriptObject { @Override public void set(final int key, final long value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); if (isMapped(index)) { namedArgs = namedArgs.set(index, value, strict); } else { @@ -368,7 +367,7 @@ public final class NativeArguments extends ScriptObject { @Override public void set(final int key, final double value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); if (isMapped(index)) { namedArgs = namedArgs.set(index, value, strict); } else { @@ -378,7 +377,7 @@ public final class NativeArguments extends ScriptObject { @Override public void set(final int key, final Object value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); if (isMapped(index)) { namedArgs = namedArgs.set(index, value, strict); } else { @@ -388,55 +387,55 @@ public final class NativeArguments extends ScriptObject { @Override public boolean has(final Object key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return isMapped(index) || super.has(key); } @Override public boolean has(final double key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return isMapped(index) || super.has(key); } @Override public boolean has(final long key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return isMapped(index) || super.has(key); } @Override public boolean has(final int key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return isMapped(index) || super.has(key); } @Override public boolean hasOwnProperty(final Object key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return isMapped(index) || super.hasOwnProperty(key); } @Override public boolean hasOwnProperty(final int key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return isMapped(index) || super.hasOwnProperty(key); } @Override public boolean hasOwnProperty(final long key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return isMapped(index) || super.hasOwnProperty(key); } @Override public boolean hasOwnProperty(final double key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return isMapped(index) || super.hasOwnProperty(key); } @Override public boolean delete(final int key, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); final boolean success = super.delete(key, strict); if (success && namedArgs.has(index)) { setDeleted(index); @@ -446,7 +445,7 @@ public final class NativeArguments extends ScriptObject { @Override public boolean delete(final long key, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); final boolean success = super.delete(key, strict); if (success && namedArgs.has(index)) { setDeleted(index); @@ -456,7 +455,7 @@ public final class NativeArguments extends ScriptObject { @Override public boolean delete(final double key, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); final boolean success = super.delete(key, strict); if (success && namedArgs.has(index)) { setDeleted(index); @@ -466,7 +465,7 @@ public final class NativeArguments extends ScriptObject { @Override public boolean delete(final Object key, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); final boolean success = super.delete(key, strict); if (success && namedArgs.has(index)) { setDeleted(index); @@ -480,7 +479,7 @@ public final class NativeArguments extends ScriptObject { */ @Override public boolean defineOwnProperty(final String key, final Object propertyDesc, final boolean reject) { - final int index = ArrayIndex.getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); if (index >= 0) { final boolean allowed = super.defineOwnProperty(key, propertyDesc, false); if (!allowed) { diff --git a/src/jdk/nashorn/internal/objects/NativeArray.java b/src/jdk/nashorn/internal/objects/NativeArray.java index 9736376b..1898d4c8 100644 --- a/src/jdk/nashorn/internal/objects/NativeArray.java +++ b/src/jdk/nashorn/internal/objects/NativeArray.java @@ -228,7 +228,7 @@ public final class NativeArray extends ScriptObject { } // Step 4a - final int index = ArrayIndex.getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); if (ArrayIndex.isValidArrayIndex(index)) { final long longIndex = ArrayIndex.toLongIndex(index); // Step 4b @@ -770,7 +770,7 @@ public final class NativeArray extends ScriptObject { final NativeArray copy = new NativeArray(0); for (long n = 0; k < finale; n++, k++) { - copy.defineOwnProperty((int) n, sobj.get(k)); + copy.defineOwnProperty(ArrayIndex.getArrayIndex(n), sobj.get(k)); } return copy; @@ -835,28 +835,26 @@ public final class NativeArray extends ScriptObject { final ScriptObject sobj = (ScriptObject) self; final boolean strict = sobj.isStrictContext(); final long len = JSType.toUint32(sobj.getLength()); + ArrayData array = sobj.getArray(); if (len > 1) { // Get only non-missing elements. Missing elements go at the end // of the sorted array. So, just don't copy these to sort input. - final ArrayList src = new ArrayList<>(); - for (int i = 0; i < (int)len; i++) { - if (sobj.has(i)) { - src.add(sobj.get(i)); + for (long i = 0; i < len; i = array.nextIndex(i)) { + if (array.has((int) i)) { + src.add(array.getObject((int) i)); } } final Object[] sorted = sort(src.toArray(), comparefn); for (int i = 0; i < sorted.length; i++) { - sobj.set(i, sorted[i], strict); + array = array.set(i, sorted[i], strict); } // delete missing elements - which are at the end of sorted array - for (int j = sorted.length; j < (int)len; j++) { - sobj.delete(j, strict); - } + sobj.setArray(array.delete(sorted.length, len - 1)); } return sobj; @@ -906,7 +904,7 @@ public final class NativeArray extends ScriptObject { final long from = actualStart + k; if (sobj.has(from)) { - array.defineOwnProperty((int) k, sobj.get(from)); + array.defineOwnProperty(ArrayIndex.getArrayIndex(k), sobj.get(from)); } } @@ -1143,7 +1141,7 @@ public final class NativeArray extends ScriptObject { @Override protected boolean forEach(final Object val, final long i) throws Throwable { final Object r = MAP_CALLBACK_INVOKER.invokeExact(callbackfn, thisArg, val, i, self); - result.defineOwnProperty((int)index, r); + result.defineOwnProperty(ArrayIndex.getArrayIndex(index), r); return true; } @@ -1172,7 +1170,7 @@ public final class NativeArray extends ScriptObject { @Override protected boolean forEach(final Object val, final long i) throws Throwable { if ((boolean)FILTER_CALLBACK_INVOKER.invokeExact(callbackfn, thisArg, val, i, self)) { - result.defineOwnProperty((int)(to++), val); + result.defineOwnProperty(ArrayIndex.getArrayIndex(to++), val); } return true; } diff --git a/src/jdk/nashorn/internal/objects/NativeString.java b/src/jdk/nashorn/internal/objects/NativeString.java index df4aa1bf..fda265e6 100644 --- a/src/jdk/nashorn/internal/objects/NativeString.java +++ b/src/jdk/nashorn/internal/objects/NativeString.java @@ -29,7 +29,6 @@ import static jdk.nashorn.internal.lookup.Lookup.MH; import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; import static jdk.nashorn.internal.runtime.JSType.isRepresentableAsInt; import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; -import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndexNoThrow; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; @@ -156,7 +155,7 @@ public final class NativeString extends ScriptObject { @SuppressWarnings("unused") private static Object get(final Object self, final Object key) { final CharSequence cs = JSType.toCharSequence(self); - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); if (index >= 0 && index < cs.length()) { return String.valueOf(cs.charAt(index)); } @@ -191,7 +190,7 @@ public final class NativeString extends ScriptObject { // String characters can be accessed with array-like indexing.. @Override public Object get(final Object key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); if (index >= 0 && index < value.length()) { return String.valueOf(value.charAt(index)); } @@ -284,7 +283,7 @@ public final class NativeString extends ScriptObject { @Override public boolean has(final Object key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return isValid(index) || super.has(key); } @@ -295,19 +294,19 @@ public final class NativeString extends ScriptObject { @Override public boolean has(final long key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return isValid(index) || super.has(key); } @Override public boolean has(final double key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return isValid(index) || super.has(key); } @Override public boolean hasOwnProperty(final Object key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return isValid(index) || super.hasOwnProperty(key); } @@ -318,13 +317,13 @@ public final class NativeString extends ScriptObject { @Override public boolean hasOwnProperty(final long key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return isValid(index) || super.hasOwnProperty(key); } @Override public boolean hasOwnProperty(final double key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return isValid(index) || super.hasOwnProperty(key); } @@ -335,19 +334,19 @@ public final class NativeString extends ScriptObject { @Override public boolean delete(final long key, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return checkDeleteIndex(index, strict)? false : super.delete(key, strict); } @Override public boolean delete(final double key, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return checkDeleteIndex(index, strict)? false : super.delete(key, strict); } @Override public boolean delete(final Object key, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); return checkDeleteIndex(index, strict)? false : super.delete(key, strict); } @@ -364,7 +363,7 @@ public final class NativeString extends ScriptObject { @Override public Object getOwnPropertyDescriptor(final String key) { - final int index = ArrayIndex.getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); if (index >= 0 && index < value.length()) { final Global global = Global.instance(); return global.newDataDescriptor(String.valueOf(value.charAt(index)), false, true, false); diff --git a/src/jdk/nashorn/internal/runtime/JSONFunctions.java b/src/jdk/nashorn/internal/runtime/JSONFunctions.java index 33e6ef03..d371fbc0 100644 --- a/src/jdk/nashorn/internal/runtime/JSONFunctions.java +++ b/src/jdk/nashorn/internal/runtime/JSONFunctions.java @@ -25,9 +25,6 @@ package jdk.nashorn.internal.runtime; -import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndexNoThrow; -import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex; - import java.lang.invoke.MethodHandle; import java.util.Iterator; import jdk.nashorn.internal.ir.LiteralNode; @@ -37,6 +34,7 @@ import jdk.nashorn.internal.ir.PropertyNode; import jdk.nashorn.internal.ir.UnaryNode; import jdk.nashorn.internal.parser.JSONParser; import jdk.nashorn.internal.parser.TokenType; +import jdk.nashorn.internal.runtime.arrays.ArrayIndex; import jdk.nashorn.internal.runtime.linker.Bootstrap; /** @@ -188,8 +186,8 @@ public final class JSONFunctions { // add a new property if does not exist already, or else set old property private static void setPropertyValue(final ScriptObject sobj, final String name, final Object value, final boolean strict) { - final int index = getArrayIndexNoThrow(name); - if (isValidArrayIndex(index)) { + final int index = ArrayIndex.getArrayIndex(name); + if (ArrayIndex.isValidArrayIndex(index)) { // array index key sobj.defineOwnProperty(index, value); } else if (sobj.getMap().findProperty(name) != null) { diff --git a/src/jdk/nashorn/internal/runtime/ScriptObject.java b/src/jdk/nashorn/internal/runtime/ScriptObject.java index 331687ad..46e39b77 100644 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java @@ -37,8 +37,6 @@ import static jdk.nashorn.internal.runtime.PropertyDescriptor.SET; import static jdk.nashorn.internal.runtime.PropertyDescriptor.VALUE; import static jdk.nashorn.internal.runtime.PropertyDescriptor.WRITABLE; import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; -import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndexNoThrow; -import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; @@ -65,6 +63,7 @@ import jdk.nashorn.internal.lookup.MethodHandleFactory; import jdk.nashorn.internal.objects.AccessorPropertyDescriptor; import jdk.nashorn.internal.objects.DataPropertyDescriptor; import jdk.nashorn.internal.runtime.arrays.ArrayData; +import jdk.nashorn.internal.runtime.arrays.ArrayIndex; import jdk.nashorn.internal.runtime.linker.Bootstrap; import jdk.nashorn.internal.runtime.linker.LinkerCallSite; import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; @@ -333,7 +332,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr return global.newDataDescriptor(getWithProperty(property), configurable, enumerable, writable); } - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); final ArrayData array = getArray(); if (array.has(index)) { @@ -533,21 +532,23 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr * from any object in proto chain such as Array.prototype, Object.prototype. * This method directly sets a particular element value in the current object. * - * @param index index key for property + * @param index key for property * @param value value to define */ protected final void defineOwnProperty(final int index, final Object value) { - if (index >= getArray().length()) { + assert ArrayIndex.isValidArrayIndex(index) : "invalid array index"; + final long longIndex = ArrayIndex.toLongIndex(index); + if (longIndex >= getArray().length()) { // make array big enough to hold.. - setArray(getArray().ensure(index)); + setArray(getArray().ensure(longIndex)); } setArray(getArray().set(index, value, false)); } private void checkIntegerKey(final String key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); - if (isValidArrayIndex(index)) { + if (ArrayIndex.isValidArrayIndex(index)) { final ArrayData data = getArray(); if (data.has(index)) { @@ -557,7 +558,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr } private void removeArraySlot(final String key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); final ArrayData array = getArray(); if (array.has(index)) { @@ -2238,7 +2239,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr } private int getInt(final int index, final String key) { - if (isValidArrayIndex(index)) { + if (ArrayIndex.isValidArrayIndex(index)) { for (ScriptObject object = this; ; ) { final FindProperty find = object.findProperty(key, false, false, this); @@ -2269,7 +2270,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public int getInt(final Object key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); final ArrayData array = getArray(); if (array.has(index)) { @@ -2281,7 +2282,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public int getInt(final double key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); final ArrayData array = getArray(); if (array.has(index)) { @@ -2293,7 +2294,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public int getInt(final long key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); final ArrayData array = getArray(); if (array.has(index)) { @@ -2315,7 +2316,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr } private long getLong(final int index, final String key) { - if (isValidArrayIndex(index)) { + if (ArrayIndex.isValidArrayIndex(index)) { for (ScriptObject object = this; ; ) { final FindProperty find = object.findProperty(key, false, false, this); @@ -2346,7 +2347,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public long getLong(final Object key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); final ArrayData array = getArray(); if (array.has(index)) { @@ -2358,7 +2359,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public long getLong(final double key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); final ArrayData array = getArray(); if (array.has(index)) { @@ -2370,7 +2371,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public long getLong(final long key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); final ArrayData array = getArray(); if (array.has(index)) { @@ -2392,7 +2393,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr } private double getDouble(final int index, final String key) { - if (isValidArrayIndex(index)) { + if (ArrayIndex.isValidArrayIndex(index)) { for (ScriptObject object = this; ; ) { final FindProperty find = object.findProperty(key, false, false, this); @@ -2423,7 +2424,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public double getDouble(final Object key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); final ArrayData array = getArray(); if (array.has(index)) { @@ -2435,7 +2436,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public double getDouble(final double key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); final ArrayData array = getArray(); if (array.has(index)) { @@ -2447,7 +2448,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public double getDouble(final long key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); final ArrayData array = getArray(); if (array.has(index)) { @@ -2469,7 +2470,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr } private Object get(final int index, final String key) { - if (isValidArrayIndex(index)) { + if (ArrayIndex.isValidArrayIndex(index)) { for (ScriptObject object = this; ; ) { final FindProperty find = object.findProperty(key, false, false, this); @@ -2500,7 +2501,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public Object get(final Object key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); final ArrayData array = getArray(); if (array.has(index)) { @@ -2512,7 +2513,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public Object get(final double key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); final ArrayData array = getArray(); if (array.has(index)) { @@ -2524,7 +2525,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public Object get(final long key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); final ArrayData array = getArray(); if (array.has(index)) { @@ -2640,9 +2641,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public void set(final Object key, final int value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); - if (isValidArrayIndex(index)) { + if (ArrayIndex.isValidArrayIndex(index)) { if (getArray().has(index)) { setArray(getArray().set(index, value, strict)); } else { @@ -2657,9 +2658,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public void set(final Object key, final long value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); - if (isValidArrayIndex(index)) { + if (ArrayIndex.isValidArrayIndex(index)) { if (getArray().has(index)) { setArray(getArray().set(index, value, strict)); } else { @@ -2674,9 +2675,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public void set(final Object key, final double value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); - if (isValidArrayIndex(index)) { + if (ArrayIndex.isValidArrayIndex(index)) { if (getArray().has(index)) { setArray(getArray().set(index, value, strict)); } else { @@ -2691,9 +2692,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public void set(final Object key, final Object value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); - if (isValidArrayIndex(index)) { + if (ArrayIndex.isValidArrayIndex(index)) { if (getArray().has(index)) { setArray(getArray().set(index, value, strict)); } else { @@ -2711,9 +2712,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public void set(final double key, final int value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); - if (isValidArrayIndex(index)) { + if (ArrayIndex.isValidArrayIndex(index)) { if (getArray().has(index)) { setArray(getArray().set(index, value, strict)); } else { @@ -2728,9 +2729,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public void set(final double key, final long value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); - if (isValidArrayIndex(index)) { + if (ArrayIndex.isValidArrayIndex(index)) { if (getArray().has(index)) { setArray(getArray().set(index, value, strict)); } else { @@ -2745,9 +2746,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public void set(final double key, final double value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); - if (isValidArrayIndex(index)) { + if (ArrayIndex.isValidArrayIndex(index)) { if (getArray().has(index)) { setArray(getArray().set(index, value, strict)); } else { @@ -2762,9 +2763,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public void set(final double key, final Object value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); - if (isValidArrayIndex(index)) { + if (ArrayIndex.isValidArrayIndex(index)) { if (getArray().has(index)) { setArray(getArray().set(index, value, strict)); } else { @@ -2779,9 +2780,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public void set(final long key, final int value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); - if (isValidArrayIndex(index)) { + if (ArrayIndex.isValidArrayIndex(index)) { if (getArray().has(index)) { setArray(getArray().set(index, value, strict)); } else { @@ -2796,9 +2797,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public void set(final long key, final long value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); - if (isValidArrayIndex(index)) { + if (ArrayIndex.isValidArrayIndex(index)) { if (getArray().has(index)) { setArray(getArray().set(index, value, strict)); } else { @@ -2813,9 +2814,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public void set(final long key, final double value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); - if (isValidArrayIndex(index)) { + if (ArrayIndex.isValidArrayIndex(index)) { if (getArray().has(index)) { setArray(getArray().set(index, value, strict)); } else { @@ -2830,9 +2831,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public void set(final long key, final Object value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); - if (isValidArrayIndex(index)) { + if (ArrayIndex.isValidArrayIndex(index)) { if (getArray().has(index)) { setArray(getArray().set(index, value, strict)); } else { @@ -2847,9 +2848,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public void set(final int key, final int value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); - if (isValidArrayIndex(index)) { + if (ArrayIndex.isValidArrayIndex(index)) { if (getArray().has(index)) { setArray(getArray().set(index, value, strict)); } else { @@ -2864,9 +2865,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public void set(final int key, final long value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); - if (isValidArrayIndex(index)) { + if (ArrayIndex.isValidArrayIndex(index)) { if (getArray().has(index)) { setArray(getArray().set(index, value, strict)); } else { @@ -2881,9 +2882,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public void set(final int key, final double value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); - if (isValidArrayIndex(index)) { + if (ArrayIndex.isValidArrayIndex(index)) { if (getArray().has(index)) { setArray(getArray().set(index, value, strict)); } else { @@ -2898,9 +2899,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public void set(final int key, final Object value, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); - if (isValidArrayIndex(index)) { + if (ArrayIndex.isValidArrayIndex(index)) { if (getArray().has(index)) { setArray(getArray().set(index, value, strict)); } else { @@ -2915,9 +2916,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public boolean has(final Object key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); - if (isValidArrayIndex(index)) { + if (ArrayIndex.isValidArrayIndex(index)) { for (ScriptObject self = this; self != null; self = self.getProto()) { if (self.getArray().has(index)) { return true; @@ -2932,9 +2933,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public boolean has(final double key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); - if (isValidArrayIndex(index)) { + if (ArrayIndex.isValidArrayIndex(index)) { for (ScriptObject self = this; self != null; self = self.getProto()) { if (self.getArray().has(index)) { return true; @@ -2949,9 +2950,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public boolean has(final long key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); - if (isValidArrayIndex(index)) { + if (ArrayIndex.isValidArrayIndex(index)) { for (ScriptObject self = this; self != null; self = self.getProto()) { if (self.getArray().has(index)) { return true; @@ -2966,9 +2967,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public boolean has(final int key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); - if (isValidArrayIndex(index)) { + if (ArrayIndex.isValidArrayIndex(index)) { for (ScriptObject self = this; self != null; self = self.getProto()) { if (self.getArray().has(index)) { return true; @@ -2983,7 +2984,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public boolean hasOwnProperty(final Object key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); if (getArray().has(index)) { return true; @@ -2996,7 +2997,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public boolean hasOwnProperty(final int key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); if (getArray().has(index)) { return true; @@ -3009,7 +3010,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public boolean hasOwnProperty(final long key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); if (getArray().has(index)) { return true; @@ -3022,7 +3023,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public boolean hasOwnProperty(final double key) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); if (getArray().has(index)) { return true; @@ -3035,7 +3036,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public boolean delete(final int key, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); final ArrayData array = getArray(); if (array.has(index)) { @@ -3051,7 +3052,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public boolean delete(final long key, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); final ArrayData array = getArray(); if (array.has(index)) { @@ -3067,7 +3068,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public boolean delete(final double key, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); final ArrayData array = getArray(); if (array.has(index)) { @@ -3083,7 +3084,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr @Override public boolean delete(final Object key, final boolean strict) { - final int index = getArrayIndexNoThrow(key); + final int index = ArrayIndex.getArrayIndex(key); final ArrayData array = getArray(); if (array.has(index)) { diff --git a/src/jdk/nashorn/internal/runtime/arrays/ArrayIndex.java b/src/jdk/nashorn/internal/runtime/arrays/ArrayIndex.java index 531c56b5..f59229c4 100644 --- a/src/jdk/nashorn/internal/runtime/arrays/ArrayIndex.java +++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayIndex.java @@ -44,7 +44,7 @@ public final class ArrayIndex { /** * Fast conversion of non-negative integer string to long. * @param key Key as a string. - * @return long value of string or -1. + * @return long value of string or {@code -1} if string does not represent a valid index. */ private static long fromString(final String key) { long value = 0; @@ -52,7 +52,7 @@ public final class ArrayIndex { // Check for empty string or leading 0 if (length == 0 || (length > 1 && key.charAt(0) == '0')) { - return -1; + return INVALID_ARRAY_INDEX; } // Fast toNumber. @@ -61,7 +61,7 @@ public final class ArrayIndex { // If not a digit. if (digit < '0' || digit > '9') { - return -1; + return INVALID_ARRAY_INDEX; } // Insert digit. @@ -69,7 +69,7 @@ public final class ArrayIndex { // Check for overflow (need to catch before wrap around.) if (value > MAX_ARRAY_INDEX) { - return -1; + return INVALID_ARRAY_INDEX; } } @@ -81,136 +81,78 @@ public final class ArrayIndex { * routine needs to perform quickly since all keys are tested with it. * * @param key key to check for array index - * @return valid array index, or negative value if not valid + * @return the array index, or {@code -1} if {@code key} does not represent a valid index. + * Note that negative return values other than {@code -1} are considered valid and can be converted to + * the actual index using {@link #toLongIndex(int)}. */ - public static int getArrayIndexNoThrow(final Object key) { + public static int getArrayIndex(final Object key) { if (key instanceof Integer) { - return getArrayIndexNoThrow(((Integer)key).intValue()); + return getArrayIndex(((Integer) key).intValue()); } else if (key instanceof Number) { - return getArrayIndexNoThrow(((Number)key).doubleValue()); + return getArrayIndex(((Number) key).doubleValue()); } else if (key instanceof String) { - return (int)fromString((String)key); + return (int)fromString((String) key); } else if (key instanceof ConsString) { return (int)fromString(key.toString()); } - return -1; + return INVALID_ARRAY_INDEX; } /** - * Returns a valid array index in an int, if the object represents one + * Returns a valid array index in an int, if the long represents one. * * @param key key to check - * @return array index for key - * @throws InvalidArrayIndexException if not a valid array index key + * @return the array index, or {@code -1} if long is not a valid array index. + * Note that negative return values other than {@code -1} are considered valid and can be converted to + * the actual index using {@link #toLongIndex(int)}. */ - public static int getArrayIndex(final Object key) throws InvalidArrayIndexException { - final int index = getArrayIndexNoThrow(key); - if (index != -1) { - return index; - } - - throw new InvalidArrayIndexException(key); - } - - /** - * Returns a valid array index in an int, if the long represents one - * - * @param key key to check - * @return valid index or a negative value if long is not a valid array index - */ - public static int getArrayIndexNoThrow(final long key) { + public static int getArrayIndex(final long key) { if (key >= 0 && key <= MAX_ARRAY_INDEX) { return (int)key; } - return -1; - } - - /** - * Returns a valid array index in an int, if the long represents one - * - * @param key key to check - * @return valid index for the long - * @throws InvalidArrayIndexException if long is not a valid array index - */ - public static int getArrayIndex(final long key) throws InvalidArrayIndexException { - final int index = getArrayIndexNoThrow(key); - if (index != -1) { - return index; - } - - throw new InvalidArrayIndexException(key); + return INVALID_ARRAY_INDEX; } /** - * Return a valid index for this double, if it represents one + * Return a valid index for this double, if it represents one. * * Doubles that aren't representable exactly as longs/ints aren't working * array indexes, however, array[1.1] === array["1.1"] in JavaScript. * * @param key the key to check - * @return the array index this double represents or a negative value if this isn't an index + * @return the array index this double represents or {@code -1} if this isn't a valid index. + * Note that negative return values other than {@code -1} are considered valid and can be converted to + * the actual index using {@link #toLongIndex(int)}. */ - public static int getArrayIndexNoThrow(final double key) { + public static int getArrayIndex(final double key) { if (JSType.isRepresentableAsInt(key)) { final int intKey = (int)key; if (intKey >= 0) { return intKey; } } else if (JSType.isRepresentableAsLong(key)) { - return getArrayIndexNoThrow((long)key); + return getArrayIndex((long) key); } - return -1; + return INVALID_ARRAY_INDEX; } - /** - * Return a valid array index for this double, if it represents one - * - * Doubles that aren't representable exactly as longs/ints aren't working - * array indexes, however, array[1.1] === array["1.1"] in JavaScript. - * - * @param key the key to check - * @return the array index this double represents - * @throws InvalidArrayIndexException if this isn't an array index - */ - public static int getArrayIndex(final double key) throws InvalidArrayIndexException { - final int index = getArrayIndexNoThrow(key); - if (index != -1) { - return index; - } - - throw new InvalidArrayIndexException(key); - } /** - * Return a valid array index for this string, if it represents one + * Return a valid array index for this string, if it represents one. * * @param key the key to check - * @return the array index this string represents or a negative value if this isn't an index + * @return the array index this string represents or {@code -1} if this isn't a valid index. + * Note that negative return values other than {@code -1} are considered valid and can be converted to + * the actual index using {@link #toLongIndex(int)}. */ - public static int getArrayIndexNoThrow(final String key) { + public static int getArrayIndex(final String key) { return (int)fromString(key); } - /** - * Return a valid array index for this string, if it represents one - * - * @param key the key to check - * @return the array index this string represents - * @throws InvalidArrayIndexException if the string isn't an array index - */ - public static int getArrayIndex(final String key) throws InvalidArrayIndexException { - final int index = getArrayIndexNoThrow(key); - if (index != -1) { - return index; - } - - throw new InvalidArrayIndexException(key); - } - /** * Check whether an index is valid as an array index. This check only tests if * it is the special "invalid array index" type, not if it is e.g. less than zero @@ -226,7 +168,7 @@ public final class ArrayIndex { /** * Convert an index to a long value. This basically amounts to ANDing it * with {@link JSType#MAX_UINT}, as the maximum array index in JavaScript - * is 0xffffffff + * is 0xfffffffe * * @param index index to convert to long form * @return index as uint32 in a long @@ -236,14 +178,14 @@ public final class ArrayIndex { } /** - * Check whether a key string can be used as a valid numeric array index in - * JavaScript + * Check whether a key string represents a valid array index in JavaScript and is small enough + * to fit into a positive int. * * @param key the key - * @return true if key works as a valid numeric array index + * @return true if key works as a valid int array index */ - public static boolean isIndexKey(final String key) { - return ArrayIndex.getArrayIndexNoThrow(key) >= 0; + public static boolean isIntArrayIndex(final String key) { + return getArrayIndex(key) >= 0; } } diff --git a/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java b/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java index 04ac661f..fd52f22d 100644 --- a/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java +++ b/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java @@ -61,13 +61,15 @@ class SparseArrayData extends ArrayData { @Override public Object[] asObjectArray() { - final Object[] objArray = new Object[Math.min((int) length(), Integer.MAX_VALUE)]; + final int length = (int) Math.min(length(), Integer.MAX_VALUE); + final int underlyingLength = (int) Math.min(length, underlying.length()); + final Object[] objArray = new Object[length]; - for (int i = 0; i < underlying.length(); i++) { + for (int i = 0; i < underlyingLength; i++) { objArray[i] = underlying.getObject(i); } - Arrays.fill(objArray, (int) underlying.length(), objArray.length, ScriptRuntime.UNDEFINED); + Arrays.fill(objArray, underlyingLength, length, ScriptRuntime.UNDEFINED); for (final Map.Entry entry : sparseMap.entrySet()) { final long key = entry.getKey(); diff --git a/src/jdk/nashorn/internal/runtime/resources/Messages.properties b/src/jdk/nashorn/internal/runtime/resources/Messages.properties index 9dc0ffcf..f08f383d 100644 --- a/src/jdk/nashorn/internal/runtime/resources/Messages.properties +++ b/src/jdk/nashorn/internal/runtime/resources/Messages.properties @@ -129,6 +129,7 @@ type.error.method.not.constructor=Java method {0} can't be used as a constructor type.error.env.not.object=$ENV must be an Object. type.error.unsupported.java.to.type=Unsupported Java.to target type {0}. range.error.inappropriate.array.length=inappropriate array length: {0} +range.error.inappropriate.array.buffer.length=inappropriate array buffer length: {0} range.error.invalid.fraction.digits=fractionDigits argument to {0} must be in [0, 20] range.error.invalid.precision=precision argument toPrecision() must be in [1, 21] range.error.invalid.radix=radix argument must be in [2, 36] diff --git a/test/examples/array-micro.js b/test/examples/array-micro.js new file mode 100644 index 00000000..075e78d8 --- /dev/null +++ b/test/examples/array-micro.js @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + + +function bench(name, func) { + var start = Date.now(); + for (var iter = 0; iter < 5e6; iter++) { + func(); + } + print((Date.now() - start) + "\t" + name); +} + +bench("[]", function() { + []; + []; + []; +}); + +bench("[1, 2, 3]", function() { + [1, 2, 3]; + [1, 2, 3]; + [1, 2, 3]; +}); + +bench("[1 .. 20]", function() { + [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]; + [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]; + [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]; +}); + +bench("new Array()", function() { + new Array(); + new Array(); + new Array(); +}); + + +bench("new Array(1, 2, 3)", function() { + new Array(1, 2, 3); + new Array(1, 2, 3); + new Array(1, 2, 3); +}); + +bench("new Array(10)", function() { + new Array(10); + new Array(10); + new Array(10); +}); + +var array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + +bench("get", function() { + array[0]; + array[3]; + array[6]; +}); + +bench("set", function() { + array[0] = 0; + array[3] = 3; + array[6] = 6; +}); + +var all = function(e) { return true; }; +var none = function(e) { return false; }; + +bench("filter all", function() { + array.filter(all); +}); + +bench("filter none", function() { + array.filter(none); +}); + +var up = function(a, b) { return a > b ? 1 : -1; }; +var down = function(a, b) { return a < b ? 1 : -1; }; + +bench("sort up", function() { + [1, 2, 3, 4].sort(up); +}); + +bench("sort down", function() { + [1, 2, 3, 4].sort(down); +}); + diff --git a/test/script/basic/JDK-8012291.js b/test/script/basic/JDK-8012291.js new file mode 100644 index 00000000..b902df47 --- /dev/null +++ b/test/script/basic/JDK-8012291.js @@ -0,0 +1,48 @@ +/* + * 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-8012291: NativeArray is inconsistent in using long for length and index in some places and int for the same in other places + * + * @test + * @run + */ + +// Make sure JSON parser correctly handles large array keys +var obj = JSON.parse('{"4294967294": 1}'); +print(obj[4294967294]); + +// Make sure Array.prototype.sort handles large index correctly +obj.length = 4294967295; +Array.prototype.sort.call(obj); +print(obj[0]); +print(obj[4294967294]); +print(obj.length); + +var arr = []; +arr[4294967294] = 1; +try { + new Int32Array(arr); +} catch (e) { + print(e); +} diff --git a/test/script/basic/JDK-8012291.js.EXPECTED b/test/script/basic/JDK-8012291.js.EXPECTED new file mode 100644 index 00000000..7d723f1d --- /dev/null +++ b/test/script/basic/JDK-8012291.js.EXPECTED @@ -0,0 +1,5 @@ +1 +1 +undefined +4294967295 +RangeError: inappropriate array buffer length: 4294967295 -- GitLab