Thu, 05 Feb 2015 14:47:28 +0100
8068872: Nashorn JSON.parse drops numeric keys
Reviewed-by: attila, lagergren
1.1 --- a/src/jdk/nashorn/internal/objects/NativeArray.java Thu Feb 05 14:42:14 2015 +0100 1.2 +++ b/src/jdk/nashorn/internal/objects/NativeArray.java Thu Feb 05 14:47:28 2015 +0100 1.3 @@ -120,9 +120,6 @@ 1.4 this(ArrayData.allocate(array.length)); 1.5 1.6 ArrayData arrayData = this.getArray(); 1.7 - if (array.length > 0) { 1.8 - arrayData.ensure(array.length - 1); 1.9 - } 1.10 1.11 for (int index = 0; index < array.length; index++) { 1.12 final Object value = array[index];
2.1 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java Thu Feb 05 14:42:14 2015 +0100 2.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java Thu Feb 05 14:47:28 2015 +0100 2.3 @@ -722,8 +722,12 @@ 2.4 public void defineOwnProperty(final int index, final Object value) { 2.5 assert isValidArrayIndex(index) : "invalid array index"; 2.6 final long longIndex = ArrayIndex.toLongIndex(index); 2.7 - doesNotHaveEnsureDelete(longIndex, getArray().length(), false); 2.8 - setArray(getArray().ensure(longIndex).set(index,value, false)); 2.9 + final long oldLength = getArray().length(); 2.10 + if (longIndex >= oldLength) { 2.11 + setArray(getArray().ensure(longIndex)); 2.12 + doesNotHaveEnsureDelete(longIndex, oldLength, false); 2.13 + } 2.14 + setArray(getArray().set(index,value, false)); 2.15 } 2.16 2.17 private void checkIntegerKey(final String key) {
3.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java Thu Feb 05 14:42:14 2015 +0100 3.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java Thu Feb 05 14:47:28 2015 +0100 3.3 @@ -118,7 +118,7 @@ 3.4 return new SparseArrayData(this, safeIndex + 1); 3.5 } 3.6 //known to fit in int 3.7 - return toRealArrayData((int)safeIndex).ensure(safeIndex); 3.8 + return toRealArrayData((int)safeIndex); 3.9 } 3.10 return this; 3.11 } 3.12 @@ -497,7 +497,9 @@ 3.13 public abstract ArrayData shiftRight(final int by); 3.14 3.15 /** 3.16 - * Ensure that the given index exists and won't fail subsequent 3.17 + * Ensure that the given index exists and won't fail in a subsequent access. 3.18 + * If {@code safeIndex} is equal or greater than the current length the length is 3.19 + * updated to {@code safeIndex + 1}. 3.20 * 3.21 * @param safeIndex the index to ensure wont go out of bounds 3.22 * @return new array data (or same)
4.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java Thu Feb 05 14:42:14 2015 +0100 4.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java Thu Feb 05 14:47:28 2015 +0100 4.3 @@ -57,7 +57,7 @@ 4.4 } 4.5 4.6 /** 4.7 - * Check if we can put one more element at the end of this continous 4.8 + * Check if we can put one more element at the end of this continuous 4.9 * array without reallocating, or if we are overwriting an already 4.10 * allocated element 4.11 *
5.1 --- a/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java Thu Feb 05 14:42:14 2015 +0100 5.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java Thu Feb 05 14:47:28 2015 +0100 5.3 @@ -221,7 +221,9 @@ 5.4 final int newLength = ArrayData.nextSize((int)safeIndex); 5.5 array = Arrays.copyOf(array, newLength); 5.6 } 5.7 - setLength(safeIndex + 1); 5.8 + if (safeIndex >= length()) { 5.9 + setLength(safeIndex + 1); 5.10 + } 5.11 return this; 5.12 } 5.13
6.1 --- a/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java Thu Feb 05 14:42:14 2015 +0100 6.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java Thu Feb 05 14:47:28 2015 +0100 6.3 @@ -157,7 +157,9 @@ 6.4 final int newLength = ArrayData.nextSize((int)safeIndex); 6.5 array = Arrays.copyOf(array, newLength); 6.6 } 6.7 - setLength(safeIndex + 1); 6.8 + if (safeIndex >= length()) { 6.9 + setLength(safeIndex + 1); 6.10 + } 6.11 return this; 6.12 } 6.13
7.1 --- a/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java Thu Feb 05 14:42:14 2015 +0100 7.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java Thu Feb 05 14:47:28 2015 +0100 7.3 @@ -139,7 +139,9 @@ 7.4 final int newLength = ArrayData.nextSize((int)safeIndex); 7.5 array = Arrays.copyOf(array, newLength); //todo fill with nan or never accessed? 7.6 } 7.7 - setLength(safeIndex + 1); 7.8 + if (safeIndex >= length()) { 7.9 + setLength(safeIndex + 1); 7.10 + } 7.11 return this; 7.12 7.13 }
8.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java Thu Feb 05 14:42:14 2015 +0100 8.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java Thu Feb 05 14:47:28 2015 +0100 8.3 @@ -123,7 +123,9 @@ 8.4 final int newLength = ArrayData.nextSize((int)safeIndex); 8.5 array = Arrays.copyOf(array, newLength); //fill with undefined or OK? TODO 8.6 } 8.7 - setLength(safeIndex + 1); 8.8 + if (safeIndex >= length()) { 8.9 + setLength(safeIndex + 1); 8.10 + } 8.11 return this; 8.12 } 8.13
9.1 --- a/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java Thu Feb 05 14:42:14 2015 +0100 9.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java Thu Feb 05 14:47:28 2015 +0100 9.3 @@ -135,10 +135,17 @@ 9.4 9.5 @Override 9.6 public ArrayData ensure(final long safeIndex) { 9.7 + // Usually #ensure only needs to be called if safeIndex is greater or equal current length. 9.8 + // SparseArrayData is an exception as an index smaller than our current length may still 9.9 + // exceed the underlying ArrayData's capacity. Because of this, SparseArrayData invokes 9.10 + // its ensure method internally in various places where other ArrayData subclasses don't, 9.11 + // making it safe for outside uses to only call ensure(safeIndex) if safeIndex >= length. 9.12 if (safeIndex < maxDenseLength && underlying.length() <= safeIndex) { 9.13 underlying = underlying.ensure(safeIndex); 9.14 } 9.15 - setLength(Math.max(safeIndex + 1, length())); 9.16 + if (safeIndex >= length()) { 9.17 + setLength(safeIndex + 1); 9.18 + } 9.19 return this; 9.20 } 9.21
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/test/script/basic/JDK-8068872.js Thu Feb 05 14:47:28 2015 +0100 10.3 @@ -0,0 +1,34 @@ 10.4 +/* 10.5 + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 10.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 10.7 + * 10.8 + * This code is free software; you can redistribute it and/or modify it 10.9 + * under the terms of the GNU General Public License version 2 only, as 10.10 + * published by the Free Software Foundation. 10.11 + * 10.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 10.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 10.15 + * version 2 for more details (a copy is included in the LICENSE file that 10.16 + * accompanied this code). 10.17 + * 10.18 + * You should have received a copy of the GNU General Public License version 10.19 + * 2 along with this work; if not, write to the Free Software Foundation, 10.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 10.21 + * 10.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 10.23 + * or visit www.oracle.com if you need additional information or have any 10.24 + * questions. 10.25 + */ 10.26 + 10.27 +/** 10.28 + * JDK-8068872: Nashorn JSON.parse drops numeric keys 10.29 + * 10.30 + * @test 10.31 + * @run 10.32 + */ 10.33 + 10.34 +print(JSON.stringify(JSON.parse('{"3": 1, "5": "a"}'))); 10.35 +print(JSON.stringify(JSON.parse('{"5": 1, "3": "a"}'))); 10.36 +print(JSON.stringify(JSON.parse('{"0": 1, "4294967294": "a"}'))); 10.37 +print(JSON.stringify(JSON.parse('{"4294967294": 1, "0": "a"}')));
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/test/script/basic/JDK-8068872.js.EXPECTED Thu Feb 05 14:47:28 2015 +0100 11.3 @@ -0,0 +1,4 @@ 11.4 +{"3":1,"5":"a"} 11.5 +{"3":"a","5":1} 11.6 +{"0":1,"4294967294":"a"} 11.7 +{"0":"a","4294967294":1}