Sat, 16 Nov 2013 00:23:46 +0100
8028210: Missing conversions on array index expression
Reviewed-by: attila, jlaskey, lagergren
1.1 --- a/src/jdk/nashorn/internal/objects/NativeArguments.java Thu Nov 14 15:53:49 2013 +0530 1.2 +++ b/src/jdk/nashorn/internal/objects/NativeArguments.java Sat Nov 16 00:23:46 2013 +0100 1.3 @@ -35,6 +35,7 @@ 1.4 import java.util.Arrays; 1.5 import java.util.BitSet; 1.6 import jdk.nashorn.internal.runtime.AccessorProperty; 1.7 +import jdk.nashorn.internal.runtime.JSType; 1.8 import jdk.nashorn.internal.runtime.Property; 1.9 import jdk.nashorn.internal.runtime.PropertyDescriptor; 1.10 import jdk.nashorn.internal.runtime.PropertyMap; 1.11 @@ -140,8 +141,9 @@ 1.12 1.13 @Override 1.14 public boolean delete(final Object key, final boolean strict) { 1.15 - final int index = ArrayIndex.getArrayIndex(key); 1.16 - return isMapped(index) ? deleteMapped(index, strict) : super.delete(key, strict); 1.17 + final Object primitiveKey = JSType.toPrimitive(key, String.class); 1.18 + final int index = ArrayIndex.getArrayIndex(primitiveKey); 1.19 + return isMapped(index) ? deleteMapped(index, strict) : super.delete(primitiveKey, strict); 1.20 } 1.21 1.22 /**
2.1 --- a/src/jdk/nashorn/internal/objects/NativeObject.java Thu Nov 14 15:53:49 2013 +0530 2.2 +++ b/src/jdk/nashorn/internal/objects/NativeObject.java Sat Nov 16 00:23:46 2013 +0100 2.3 @@ -484,10 +484,12 @@ 2.4 */ 2.5 @Function(attributes = Attribute.NOT_ENUMERABLE) 2.6 public static Object hasOwnProperty(final Object self, final Object v) { 2.7 - final String str = JSType.toString(v); 2.8 + // Convert ScriptObjects to primitive with String.class hint 2.9 + // but no need to convert other primitives to string. 2.10 + final Object key = JSType.toPrimitive(v, String.class); 2.11 final Object obj = Global.toObject(self); 2.12 2.13 - return (obj instanceof ScriptObject) && ((ScriptObject)obj).hasOwnProperty(str); 2.14 + return (obj instanceof ScriptObject) && ((ScriptObject)obj).hasOwnProperty(key); 2.15 } 2.16 2.17 /**
3.1 --- a/src/jdk/nashorn/internal/objects/NativeString.java Thu Nov 14 15:53:49 2013 +0530 3.2 +++ b/src/jdk/nashorn/internal/objects/NativeString.java Sat Nov 16 00:23:46 2013 +0100 3.3 @@ -167,11 +167,12 @@ 3.4 @SuppressWarnings("unused") 3.5 private static Object get(final Object self, final Object key) { 3.6 final CharSequence cs = JSType.toCharSequence(self); 3.7 - final int index = ArrayIndex.getArrayIndex(key); 3.8 + final Object primitiveKey = JSType.toPrimitive(key, String.class); 3.9 + final int index = ArrayIndex.getArrayIndex(primitiveKey); 3.10 if (index >= 0 && index < cs.length()) { 3.11 return String.valueOf(cs.charAt(index)); 3.12 } 3.13 - return ((ScriptObject) Global.toObject(self)).get(key); 3.14 + return ((ScriptObject) Global.toObject(self)).get(primitiveKey); 3.15 } 3.16 3.17 @SuppressWarnings("unused") 3.18 @@ -202,11 +203,12 @@ 3.19 // String characters can be accessed with array-like indexing.. 3.20 @Override 3.21 public Object get(final Object key) { 3.22 - final int index = ArrayIndex.getArrayIndex(key); 3.23 + final Object primitiveKey = JSType.toPrimitive(key, String.class); 3.24 + final int index = ArrayIndex.getArrayIndex(primitiveKey); 3.25 if (index >= 0 && index < value.length()) { 3.26 return String.valueOf(value.charAt(index)); 3.27 } 3.28 - return super.get(key); 3.29 + return super.get(primitiveKey); 3.30 } 3.31 3.32 @Override 3.33 @@ -295,8 +297,9 @@ 3.34 3.35 @Override 3.36 public boolean has(final Object key) { 3.37 - final int index = ArrayIndex.getArrayIndex(key); 3.38 - return isValid(index) || super.has(key); 3.39 + final Object primitiveKey = JSType.toPrimitive(key, String.class); 3.40 + final int index = ArrayIndex.getArrayIndex(primitiveKey); 3.41 + return isValid(index) || super.has(primitiveKey); 3.42 } 3.43 3.44 @Override 3.45 @@ -318,8 +321,9 @@ 3.46 3.47 @Override 3.48 public boolean hasOwnProperty(final Object key) { 3.49 - final int index = ArrayIndex.getArrayIndex(key); 3.50 - return isValid(index) || super.hasOwnProperty(key); 3.51 + final Object primitiveKey = JSType.toPrimitive(key, String.class); 3.52 + final int index = ArrayIndex.getArrayIndex(primitiveKey); 3.53 + return isValid(index) || super.hasOwnProperty(primitiveKey); 3.54 } 3.55 3.56 @Override 3.57 @@ -358,8 +362,9 @@ 3.58 3.59 @Override 3.60 public boolean delete(final Object key, final boolean strict) { 3.61 - final int index = ArrayIndex.getArrayIndex(key); 3.62 - return checkDeleteIndex(index, strict)? false : super.delete(key, strict); 3.63 + final Object primitiveKey = JSType.toPrimitive(key, String.class); 3.64 + final int index = ArrayIndex.getArrayIndex(primitiveKey); 3.65 + return checkDeleteIndex(index, strict)? false : super.delete(primitiveKey, strict); 3.66 } 3.67 3.68 private boolean checkDeleteIndex(final int index, final boolean strict) {
4.1 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java Thu Nov 14 15:53:49 2013 +0530 4.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java Sat Nov 16 00:23:46 2013 +0100 4.3 @@ -2373,11 +2373,13 @@ 4.4 4.5 private int getInt(final int index, final String key) { 4.6 if (isValidArrayIndex(index)) { 4.7 - for (ScriptObject object = this; ; ) { 4.8 - final FindProperty find = object.findProperty(key, false, false, this); 4.9 - 4.10 - if (find != null) { 4.11 - return getIntValue(find); 4.12 + for (ScriptObject object = this; ; ) { 4.13 + if (object.getMap().containsArrayKeys()) { 4.14 + final FindProperty find = object.findProperty(key, false, false, this); 4.15 + 4.16 + if (find != null) { 4.17 + return getIntValue(find); 4.18 + } 4.19 } 4.20 4.21 if ((object = object.getProto()) == null) { 4.22 @@ -2389,7 +2391,7 @@ 4.23 if (array.has(index)) { 4.24 return array.getInt(index); 4.25 } 4.26 - } 4.27 + } 4.28 } else { 4.29 final FindProperty find = findProperty(key, true); 4.30 4.31 @@ -2403,14 +2405,15 @@ 4.32 4.33 @Override 4.34 public int getInt(final Object key) { 4.35 - final int index = getArrayIndex(key); 4.36 + final Object primitiveKey = JSType.toPrimitive(key, String.class); 4.37 + final int index = getArrayIndex(primitiveKey); 4.38 final ArrayData array = getArray(); 4.39 4.40 if (array.has(index)) { 4.41 return array.getInt(index); 4.42 } 4.43 4.44 - return getInt(index, JSType.toString(key)); 4.45 + return getInt(index, JSType.toString(primitiveKey)); 4.46 } 4.47 4.48 @Override 4.49 @@ -2439,22 +2442,25 @@ 4.50 4.51 @Override 4.52 public int getInt(final int key) { 4.53 + final int index = getArrayIndex(key); 4.54 final ArrayData array = getArray(); 4.55 4.56 - if (array.has(key)) { 4.57 - return array.getInt(key); 4.58 + if (array.has(index)) { 4.59 + return array.getInt(index); 4.60 } 4.61 4.62 - return getInt(key, JSType.toString(key)); 4.63 + return getInt(index, JSType.toString(key)); 4.64 } 4.65 4.66 private long getLong(final int index, final String key) { 4.67 if (isValidArrayIndex(index)) { 4.68 for (ScriptObject object = this; ; ) { 4.69 - final FindProperty find = object.findProperty(key, false, false, this); 4.70 - 4.71 - if (find != null) { 4.72 - return getLongValue(find); 4.73 + if (object.getMap().containsArrayKeys()) { 4.74 + final FindProperty find = object.findProperty(key, false, false, this); 4.75 + 4.76 + if (find != null) { 4.77 + return getLongValue(find); 4.78 + } 4.79 } 4.80 4.81 if ((object = object.getProto()) == null) { 4.82 @@ -2466,7 +2472,7 @@ 4.83 if (array.has(index)) { 4.84 return array.getLong(index); 4.85 } 4.86 - } 4.87 + } 4.88 } else { 4.89 final FindProperty find = findProperty(key, true); 4.90 4.91 @@ -2480,14 +2486,15 @@ 4.92 4.93 @Override 4.94 public long getLong(final Object key) { 4.95 - final int index = getArrayIndex(key); 4.96 + final Object primitiveKey = JSType.toPrimitive(key, String.class); 4.97 + final int index = getArrayIndex(primitiveKey); 4.98 final ArrayData array = getArray(); 4.99 4.100 if (array.has(index)) { 4.101 return array.getLong(index); 4.102 } 4.103 4.104 - return getLong(index, JSType.toString(key)); 4.105 + return getLong(index, JSType.toString(primitiveKey)); 4.106 } 4.107 4.108 @Override 4.109 @@ -2516,22 +2523,25 @@ 4.110 4.111 @Override 4.112 public long getLong(final int key) { 4.113 + final int index = getArrayIndex(key); 4.114 final ArrayData array = getArray(); 4.115 4.116 - if (array.has(key)) { 4.117 - return array.getLong(key); 4.118 + if (array.has(index)) { 4.119 + return array.getLong(index); 4.120 } 4.121 4.122 - return getLong(key, JSType.toString(key)); 4.123 + return getLong(index, JSType.toString(key)); 4.124 } 4.125 4.126 private double getDouble(final int index, final String key) { 4.127 if (isValidArrayIndex(index)) { 4.128 for (ScriptObject object = this; ; ) { 4.129 - final FindProperty find = object.findProperty(key, false, false, this); 4.130 - 4.131 - if (find != null) { 4.132 - return getDoubleValue(find); 4.133 + if (object.getMap().containsArrayKeys()) { 4.134 + final FindProperty find = object.findProperty(key, false, false, this); 4.135 + 4.136 + if (find != null) { 4.137 + return getDoubleValue(find); 4.138 + } 4.139 } 4.140 4.141 if ((object = object.getProto()) == null) { 4.142 @@ -2543,7 +2553,7 @@ 4.143 if (array.has(index)) { 4.144 return array.getDouble(index); 4.145 } 4.146 - } 4.147 + } 4.148 } else { 4.149 final FindProperty find = findProperty(key, true); 4.150 4.151 @@ -2557,14 +2567,15 @@ 4.152 4.153 @Override 4.154 public double getDouble(final Object key) { 4.155 - final int index = getArrayIndex(key); 4.156 + final Object primitiveKey = JSType.toPrimitive(key, String.class); 4.157 + final int index = getArrayIndex(primitiveKey); 4.158 final ArrayData array = getArray(); 4.159 4.160 if (array.has(index)) { 4.161 return array.getDouble(index); 4.162 } 4.163 4.164 - return getDouble(index, JSType.toString(key)); 4.165 + return getDouble(index, JSType.toString(primitiveKey)); 4.166 } 4.167 4.168 @Override 4.169 @@ -2593,22 +2604,25 @@ 4.170 4.171 @Override 4.172 public double getDouble(final int key) { 4.173 + final int index = getArrayIndex(key); 4.174 final ArrayData array = getArray(); 4.175 4.176 - if (array.has(key)) { 4.177 - return array.getDouble(key); 4.178 + if (array.has(index)) { 4.179 + return array.getDouble(index); 4.180 } 4.181 4.182 - return getDouble(key, JSType.toString(key)); 4.183 + return getDouble(index, JSType.toString(key)); 4.184 } 4.185 4.186 private Object get(final int index, final String key) { 4.187 if (isValidArrayIndex(index)) { 4.188 for (ScriptObject object = this; ; ) { 4.189 - final FindProperty find = object.findProperty(key, false, false, this); 4.190 - 4.191 - if (find != null) { 4.192 - return getObjectValue(find); 4.193 + if (object.getMap().containsArrayKeys()) { 4.194 + final FindProperty find = object.findProperty(key, false, false, this); 4.195 + 4.196 + if (find != null) { 4.197 + return getObjectValue(find); 4.198 + } 4.199 } 4.200 4.201 if ((object = object.getProto()) == null) { 4.202 @@ -2634,14 +2648,15 @@ 4.203 4.204 @Override 4.205 public Object get(final Object key) { 4.206 - final int index = getArrayIndex(key); 4.207 + final Object primitiveKey = JSType.toPrimitive(key, String.class); 4.208 + final int index = getArrayIndex(primitiveKey); 4.209 final ArrayData array = getArray(); 4.210 4.211 if (array.has(index)) { 4.212 return array.getObject(index); 4.213 } 4.214 4.215 - return get(index, JSType.toString(key)); 4.216 + return get(index, JSType.toString(primitiveKey)); 4.217 } 4.218 4.219 @Override 4.220 @@ -2670,13 +2685,14 @@ 4.221 4.222 @Override 4.223 public Object get(final int key) { 4.224 + final int index = getArrayIndex(key); 4.225 final ArrayData array = getArray(); 4.226 4.227 - if (array.has(key)) { 4.228 - return array.getObject(key); 4.229 + if (array.has(index)) { 4.230 + return array.getObject(index); 4.231 } 4.232 4.233 - return get(key, JSType.toString(key)); 4.234 + return get(index, JSType.toString(key)); 4.235 } 4.236 4.237 /** 4.238 @@ -2688,7 +2704,7 @@ 4.239 */ 4.240 private void doesNotHave(final int index, final Object value, final boolean strict) { 4.241 final long oldLength = getArray().length(); 4.242 - final long longIndex = index & JSType.MAX_UINT; 4.243 + final long longIndex = ArrayIndex.toLongIndex(index); 4.244 4.245 if (getMap().containsArrayKeys()) { 4.246 final String key = JSType.toString(longIndex); 4.247 @@ -2774,7 +2790,8 @@ 4.248 4.249 @Override 4.250 public void set(final Object key, final int value, final boolean strict) { 4.251 - final int index = getArrayIndex(key); 4.252 + final Object primitiveKey = JSType.toPrimitive(key, String.class); 4.253 + final int index = getArrayIndex(primitiveKey); 4.254 4.255 if (isValidArrayIndex(index)) { 4.256 if (getArray().has(index)) { 4.257 @@ -2786,13 +2803,14 @@ 4.258 return; 4.259 } 4.260 4.261 - final String propName = JSType.toString(key); 4.262 + final String propName = JSType.toString(primitiveKey); 4.263 setObject(findProperty(propName, true), strict, propName, JSType.toObject(value)); 4.264 } 4.265 4.266 @Override 4.267 public void set(final Object key, final long value, final boolean strict) { 4.268 - final int index = getArrayIndex(key); 4.269 + final Object primitiveKey = JSType.toPrimitive(key, String.class); 4.270 + final int index = getArrayIndex(primitiveKey); 4.271 4.272 if (isValidArrayIndex(index)) { 4.273 if (getArray().has(index)) { 4.274 @@ -2804,13 +2822,14 @@ 4.275 return; 4.276 } 4.277 4.278 - final String propName = JSType.toString(key); 4.279 + final String propName = JSType.toString(primitiveKey); 4.280 setObject(findProperty(propName, true), strict, propName, JSType.toObject(value)); 4.281 } 4.282 4.283 @Override 4.284 public void set(final Object key, final double value, final boolean strict) { 4.285 - final int index = getArrayIndex(key); 4.286 + final Object primitiveKey = JSType.toPrimitive(key, String.class); 4.287 + final int index = getArrayIndex(primitiveKey); 4.288 4.289 if (isValidArrayIndex(index)) { 4.290 if (getArray().has(index)) { 4.291 @@ -2822,13 +2841,14 @@ 4.292 return; 4.293 } 4.294 4.295 - final String propName = JSType.toString(key); 4.296 + final String propName = JSType.toString(primitiveKey); 4.297 setObject(findProperty(propName, true), strict, propName, JSType.toObject(value)); 4.298 } 4.299 4.300 @Override 4.301 public void set(final Object key, final Object value, final boolean strict) { 4.302 - final int index = getArrayIndex(key); 4.303 + final Object primitiveKey = JSType.toPrimitive(key, String.class); 4.304 + final int index = getArrayIndex(primitiveKey); 4.305 4.306 if (isValidArrayIndex(index)) { 4.307 if (getArray().has(index)) { 4.308 @@ -2840,7 +2860,7 @@ 4.309 return; 4.310 } 4.311 4.312 - final String propName = JSType.toString(key); 4.313 + final String propName = JSType.toString(primitiveKey); 4.314 setObject(findProperty(propName, true), strict, propName, value); 4.315 } 4.316 4.317 @@ -3062,82 +3082,69 @@ 4.318 4.319 @Override 4.320 public boolean has(final Object key) { 4.321 - final int index = getArrayIndex(key); 4.322 - 4.323 - if (isValidArrayIndex(index)) { 4.324 - for (ScriptObject self = this; self != null; self = self.getProto()) { 4.325 - if (self.getArray().has(index)) { 4.326 - return true; 4.327 - } 4.328 - } 4.329 - } 4.330 - 4.331 - return hasProperty(JSType.toString(key), true); 4.332 + final Object primitiveKey = JSType.toPrimitive(key); 4.333 + final int index = getArrayIndex(primitiveKey); 4.334 + return isValidArrayIndex(index) ? hasArrayProperty(index) : hasProperty(JSType.toString(primitiveKey), true); 4.335 } 4.336 4.337 @Override 4.338 public boolean has(final double key) { 4.339 final int index = getArrayIndex(key); 4.340 - 4.341 - if (isValidArrayIndex(index)) { 4.342 - for (ScriptObject self = this; self != null; self = self.getProto()) { 4.343 - if (self.getArray().has(index)) { 4.344 - return true; 4.345 - } 4.346 - } 4.347 - } 4.348 - 4.349 - return hasProperty(JSType.toString(key), true); 4.350 + return isValidArrayIndex(index) ? hasArrayProperty(index) : hasProperty(JSType.toString(key), true); 4.351 } 4.352 4.353 @Override 4.354 public boolean has(final long key) { 4.355 final int index = getArrayIndex(key); 4.356 - 4.357 - if (isValidArrayIndex(index)) { 4.358 - for (ScriptObject self = this; self != null; self = self.getProto()) { 4.359 - if (self.getArray().has(index)) { 4.360 - return true; 4.361 - } 4.362 - } 4.363 - } 4.364 - 4.365 - return hasProperty(JSType.toString(key), true); 4.366 + return isValidArrayIndex(index) ? hasArrayProperty(index) : hasProperty(JSType.toString(key), true); 4.367 } 4.368 4.369 @Override 4.370 public boolean has(final int key) { 4.371 final int index = getArrayIndex(key); 4.372 - 4.373 - if (isValidArrayIndex(index)) { 4.374 - for (ScriptObject self = this; self != null; self = self.getProto()) { 4.375 - if (self.getArray().has(index)) { 4.376 - return true; 4.377 - } 4.378 + return isValidArrayIndex(index) ? hasArrayProperty(index) : hasProperty(JSType.toString(key), true); 4.379 + } 4.380 + 4.381 + private boolean hasArrayProperty(final int index) { 4.382 + boolean hasArrayKeys = false; 4.383 + 4.384 + for (ScriptObject self = this; self != null; self = self.getProto()) { 4.385 + if (self.getArray().has(index)) { 4.386 + return true; 4.387 } 4.388 + hasArrayKeys = hasArrayKeys || self.getMap().containsArrayKeys(); 4.389 } 4.390 4.391 - return hasProperty(JSType.toString(key), true); 4.392 + return hasArrayKeys && hasProperty(ArrayIndex.toKey(index), true); 4.393 } 4.394 4.395 @Override 4.396 public boolean hasOwnProperty(final Object key) { 4.397 - return getArray().has(getArrayIndex(key)) || hasProperty(JSType.toString(key), false); 4.398 + final Object primitiveKey = JSType.toPrimitive(key, String.class); 4.399 + final int index = getArrayIndex(primitiveKey); 4.400 + return isValidArrayIndex(index) ? hasOwnArrayProperty(index) : hasProperty(JSType.toString(primitiveKey), false); 4.401 } 4.402 4.403 @Override 4.404 public boolean hasOwnProperty(final int key) { 4.405 - return getArray().has(getArrayIndex(key)) || hasProperty(JSType.toString(key), false); 4.406 + final int index = getArrayIndex(key); 4.407 + return isValidArrayIndex(index) ? hasOwnArrayProperty(index) : hasProperty(JSType.toString(key), false); 4.408 } 4.409 4.410 @Override 4.411 public boolean hasOwnProperty(final long key) { 4.412 - return getArray().has(getArrayIndex(key)) || hasProperty(JSType.toString(key), false); 4.413 + final int index = getArrayIndex(key); 4.414 + return isValidArrayIndex(index) ? hasOwnArrayProperty(index) : hasProperty(JSType.toString(key), false); 4.415 } 4.416 4.417 @Override 4.418 public boolean hasOwnProperty(final double key) { 4.419 - return getArray().has(getArrayIndex(key)) || hasProperty(JSType.toString(key), false); 4.420 + final int index = getArrayIndex(key); 4.421 + return isValidArrayIndex(index) ? hasOwnArrayProperty(index) : hasProperty(JSType.toString(key), false); 4.422 + } 4.423 + 4.424 + private boolean hasOwnArrayProperty(final int index) { 4.425 + return getArray().has(index) || (getMap().containsArrayKeys() && hasProperty(ArrayIndex.toKey(index), false)); 4.426 } 4.427 4.428 @Override 4.429 @@ -3190,7 +3197,8 @@ 4.430 4.431 @Override 4.432 public boolean delete(final Object key, final boolean strict) { 4.433 - final int index = getArrayIndex(key); 4.434 + final Object primitiveKey = JSType.toPrimitive(key, String.class); 4.435 + final int index = getArrayIndex(primitiveKey); 4.436 final ArrayData array = getArray(); 4.437 4.438 if (array.has(index)) { 4.439 @@ -3201,7 +3209,7 @@ 4.440 return false; 4.441 } 4.442 4.443 - return deleteObject(key, strict); 4.444 + return deleteObject(primitiveKey, strict); 4.445 } 4.446 4.447 private boolean deleteObject(final Object key, final boolean strict) {
5.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ArrayIndex.java Thu Nov 14 15:53:49 2013 +0530 5.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayIndex.java Sat Nov 16 00:23:46 2013 +0100 5.3 @@ -27,6 +27,7 @@ 5.4 5.5 import jdk.nashorn.internal.runtime.ConsString; 5.6 import jdk.nashorn.internal.runtime.JSType; 5.7 +import jdk.nashorn.internal.runtime.ScriptObject; 5.8 5.9 /** 5.10 * Array index computation helpers. that both throw exceptions or return 5.11 @@ -80,7 +81,12 @@ 5.12 * Returns a valid array index in an int, if the object represents one. This 5.13 * routine needs to perform quickly since all keys are tested with it. 5.14 * 5.15 - * @param key key to check for array index 5.16 + * <p>The {@code key} parameter must be a JavaScript primitive type, i.e. one of 5.17 + * {@code String}, {@code Number}, {@code Boolean}, {@code null}, or {@code undefined}. 5.18 + * {@code ScriptObject} instances should be converted to primitive with 5.19 + * {@code String.class} hint before being passed to this method.</p> 5.20 + * 5.21 + * @param key key to check for array index. 5.22 * @return the array index, or {@code -1} if {@code key} does not represent a valid index. 5.23 * Note that negative return values other than {@code -1} are considered valid and can be converted to 5.24 * the actual index using {@link #toLongIndex(int)}. 5.25 @@ -88,18 +94,31 @@ 5.26 public static int getArrayIndex(final Object key) { 5.27 if (key instanceof Integer) { 5.28 return getArrayIndex(((Integer) key).intValue()); 5.29 - } else if (key instanceof Number) { 5.30 - return getArrayIndex(((Number) key).doubleValue()); 5.31 + } else if (key instanceof Double) { 5.32 + return getArrayIndex(((Double) key).doubleValue()); 5.33 } else if (key instanceof String) { 5.34 return (int)fromString((String) key); 5.35 + } else if (key instanceof Long) { 5.36 + return getArrayIndex(((Long) key).longValue()); 5.37 } else if (key instanceof ConsString) { 5.38 return (int)fromString(key.toString()); 5.39 } 5.40 5.41 + assert !(key instanceof ScriptObject); 5.42 return INVALID_ARRAY_INDEX; 5.43 } 5.44 5.45 /** 5.46 + * Returns a valid array index in an int, if {@code key} represents one. 5.47 + * 5.48 + * @param key key to check 5.49 + * @return the array index, or {@code -1} if {@code key} is not a valid array index. 5.50 + */ 5.51 + public static int getArrayIndex(final int key) { 5.52 + return (key >= 0) ? key : INVALID_ARRAY_INDEX; 5.53 + } 5.54 + 5.55 + /** 5.56 * Returns a valid array index in an int, if the long represents one. 5.57 * 5.58 * @param key key to check 5.59 @@ -129,10 +148,7 @@ 5.60 */ 5.61 public static int getArrayIndex(final double key) { 5.62 if (JSType.isRepresentableAsInt(key)) { 5.63 - final int intKey = (int)key; 5.64 - if (intKey >= 0) { 5.65 - return intKey; 5.66 - } 5.67 + return getArrayIndex((int) key); 5.68 } else if (JSType.isRepresentableAsLong(key)) { 5.69 return getArrayIndex((long) key); 5.70 } 5.71 @@ -177,5 +193,16 @@ 5.72 return index & JSType.MAX_UINT; 5.73 } 5.74 5.75 + /** 5.76 + * Convert an index to a key string. This is the same as calling {@link #toLongIndex(int)} 5.77 + * and converting the result to String. 5.78 + * 5.79 + * @param index index to convert 5.80 + * @return index as string 5.81 + */ 5.82 + public static String toKey(final int index) { 5.83 + return Long.toString(index & JSType.MAX_UINT); 5.84 + } 5.85 + 5.86 } 5.87
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/test/script/basic/JDK-8028210.js Sat Nov 16 00:23:46 2013 +0100 6.3 @@ -0,0 +1,83 @@ 6.4 +/* 6.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 6.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6.7 + * 6.8 + * This code is free software; you can redistribute it and/or modify it 6.9 + * under the terms of the GNU General Public License version 2 only, as 6.10 + * published by the Free Software Foundation. 6.11 + * 6.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 6.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 6.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 6.15 + * version 2 for more details (a copy is included in the LICENSE file that 6.16 + * accompanied this code). 6.17 + * 6.18 + * You should have received a copy of the GNU General Public License version 6.19 + * 2 along with this work; if not, write to the Free Software Foundation, 6.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 6.21 + * 6.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 6.23 + * or visit www.oracle.com if you need additional information or have any 6.24 + * questions. 6.25 + */ 6.26 + 6.27 +/** 6.28 + * JDK-8028210: Missing conversions on array index expression 6.29 + * 6.30 + * @test 6.31 + * @run 6.32 + */ 6.33 + 6.34 +var array = [1, 2]; 6.35 +var key1 = [[[0]]]; 6.36 +var key2 = new String("1"); 6.37 +var key3 = { 6.38 + toString: function() { 6.39 + print("toString called"); 6.40 + return "2"; 6.41 + } 6.42 +}; 6.43 + 6.44 +print(array[key1]); 6.45 +print(array[key2]); 6.46 +array[key3] = 3; 6.47 +print(array[key3]); 6.48 +print(key3 in array); 6.49 +print(array.hasOwnProperty(key3)); 6.50 +print(delete array[key3]); 6.51 +print(array[key3]); 6.52 + 6.53 +// string access 6.54 +print("abc"[key1]); 6.55 +print("abc"[key2]); 6.56 +print("abc"[key3]); 6.57 + 6.58 +// arguments object 6.59 +(function(a, b, c) { 6.60 + print(arguments[key3]); 6.61 + delete arguments[key3]; 6.62 + print(arguments[key3], c); 6.63 +})(1, 2, 3); 6.64 + 6.65 +// int keys 6.66 +array = []; 6.67 +array[4294967294] = 1; 6.68 +print(array[-2]); 6.69 +print(array[4294967294]); 6.70 +print(-2 in array); 6.71 +print(4294967294 in array); 6.72 +print(delete(array[-2])); 6.73 +print(array[4294967294]); 6.74 +print(delete(array[4294967294])); 6.75 +print(array[4294967294]); 6.76 + 6.77 +array = []; 6.78 +array[-2] = 1; 6.79 +print(array[-2]); 6.80 +print(array[4294967294]); 6.81 +print(-2 in array); 6.82 +print(4294967294 in array); 6.83 +print(delete(array[4294967294])); 6.84 +print(array[-2]); 6.85 +print(delete(array[-2])); 6.86 +print(array[-2]);
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/test/script/basic/JDK-8028210.js.EXPECTED Sat Nov 16 00:23:46 2013 +0100 7.3 @@ -0,0 +1,38 @@ 7.4 +1 7.5 +2 7.6 +toString called 7.7 +toString called 7.8 +3 7.9 +toString called 7.10 +true 7.11 +toString called 7.12 +true 7.13 +toString called 7.14 +true 7.15 +toString called 7.16 +undefined 7.17 +a 7.18 +b 7.19 +toString called 7.20 +c 7.21 +toString called 7.22 +3 7.23 +toString called 7.24 +toString called 7.25 +undefined 3 7.26 +undefined 7.27 +1 7.28 +false 7.29 +true 7.30 +true 7.31 +1 7.32 +true 7.33 +undefined 7.34 +1 7.35 +undefined 7.36 +true 7.37 +false 7.38 +true 7.39 +1 7.40 +true 7.41 +undefined