8028210: Missing conversions on array index expression

Sat, 16 Nov 2013 00:23:46 +0100

author
hannesw
date
Sat, 16 Nov 2013 00:23:46 +0100
changeset 678
a165c0fb5be6
parent 677
fea9f0f9bbde
child 679
bce2bbfb35ae

8028210: Missing conversions on array index expression
Reviewed-by: attila, jlaskey, lagergren

src/jdk/nashorn/internal/objects/NativeArguments.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeObject.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/objects/NativeString.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/ScriptObject.java file | annotate | diff | comparison | revisions
src/jdk/nashorn/internal/runtime/arrays/ArrayIndex.java file | annotate | diff | comparison | revisions
test/script/basic/JDK-8028210.js file | annotate | diff | comparison | revisions
test/script/basic/JDK-8028210.js.EXPECTED file | annotate | diff | comparison | revisions
     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

mercurial