8015354: JSON.parse should not use [[Put]] but use [[DefineOwnProperty]] instead
authorsundar
Fri, 24 May 2013 18:39:25 +0530
changeset 17771 9fedae4933e4
parent 17770 3c8602ec5565
child 17772 9acc52342786
8015354: JSON.parse should not use [[Put]] but use [[DefineOwnProperty]] instead Reviewed-by: lagergren, hannesw
nashorn/src/jdk/nashorn/internal/objects/NativeFloat32Array.java
nashorn/src/jdk/nashorn/internal/objects/NativeFloat64Array.java
nashorn/src/jdk/nashorn/internal/objects/NativeInt16Array.java
nashorn/src/jdk/nashorn/internal/objects/NativeInt32Array.java
nashorn/src/jdk/nashorn/internal/objects/NativeInt8Array.java
nashorn/src/jdk/nashorn/internal/objects/NativeUint16Array.java
nashorn/src/jdk/nashorn/internal/objects/NativeUint32Array.java
nashorn/src/jdk/nashorn/internal/objects/NativeUint8Array.java
nashorn/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java
nashorn/src/jdk/nashorn/internal/runtime/JSONFunctions.java
nashorn/src/jdk/nashorn/internal/runtime/Property.java
nashorn/test/script/basic/JDK-8015354.js
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeFloat32Array.java	Fri May 24 13:54:18 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeFloat32Array.java	Fri May 24 18:39:25 2013 +0530
@@ -40,6 +40,9 @@
  */
 @ScriptClass("Float32Array")
 public final class NativeFloat32Array extends ArrayBufferView {
+    /**
+     * The size in bytes of each element in the array.
+     */
     @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE, where = Where.CONSTRUCTOR)
     public static final int BYTES_PER_ELEMENT = 4;
 
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeFloat64Array.java	Fri May 24 13:54:18 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeFloat64Array.java	Fri May 24 18:39:25 2013 +0530
@@ -40,6 +40,9 @@
  */
 @ScriptClass("Float64Array")
 public final class NativeFloat64Array extends ArrayBufferView {
+    /**
+     * The size in bytes of each element in the array.
+     */
     @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE, where = Where.CONSTRUCTOR)
     public static final int BYTES_PER_ELEMENT = 8;
 
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeInt16Array.java	Fri May 24 13:54:18 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeInt16Array.java	Fri May 24 18:39:25 2013 +0530
@@ -39,6 +39,9 @@
  */
 @ScriptClass("Int16Array")
 public final class NativeInt16Array extends ArrayBufferView {
+    /**
+     * The size in bytes of each element in the array.
+     */
     @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE, where = Where.CONSTRUCTOR)
     public static final int BYTES_PER_ELEMENT = 2;
 
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeInt32Array.java	Fri May 24 13:54:18 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeInt32Array.java	Fri May 24 18:39:25 2013 +0530
@@ -39,6 +39,9 @@
  */
 @ScriptClass("Int32Array")
 public final class NativeInt32Array extends ArrayBufferView {
+    /**
+     * The size in bytes of each element in the array.
+     */
     @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE, where = Where.CONSTRUCTOR)
     public static final int BYTES_PER_ELEMENT = 4;
 
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeInt8Array.java	Fri May 24 13:54:18 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeInt8Array.java	Fri May 24 18:39:25 2013 +0530
@@ -39,6 +39,9 @@
  */
 @ScriptClass("Int8Array")
 public final class NativeInt8Array extends ArrayBufferView {
+    /**
+     * The size in bytes of each element in the array.
+     */
     @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE, where = Where.CONSTRUCTOR)
     public static final int BYTES_PER_ELEMENT = 1;
 
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeUint16Array.java	Fri May 24 13:54:18 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint16Array.java	Fri May 24 18:39:25 2013 +0530
@@ -39,6 +39,9 @@
  */
 @ScriptClass("Uint16Array")
 public final class NativeUint16Array extends ArrayBufferView {
+    /**
+     * The size in bytes of each element in the array.
+     */
     @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE, where = Where.CONSTRUCTOR)
     public static final int BYTES_PER_ELEMENT = 2;
 
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeUint32Array.java	Fri May 24 13:54:18 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint32Array.java	Fri May 24 18:39:25 2013 +0530
@@ -40,6 +40,9 @@
  */
 @ScriptClass("Uint32Array")
 public final class NativeUint32Array extends ArrayBufferView {
+    /**
+     * The size in bytes of each element in the array.
+     */
     @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE, where = Where.CONSTRUCTOR)
     public static final int BYTES_PER_ELEMENT = 4;
 
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeUint8Array.java	Fri May 24 13:54:18 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint8Array.java	Fri May 24 18:39:25 2013 +0530
@@ -39,6 +39,9 @@
  */
 @ScriptClass("Uint8Array")
 public final class NativeUint8Array extends ArrayBufferView {
+    /**
+     * The size in bytes of each element in the array.
+     */
     @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE, where = Where.CONSTRUCTOR)
     public static final int BYTES_PER_ELEMENT = 1;
 
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java	Fri May 24 13:54:18 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java	Fri May 24 18:39:25 2013 +0530
@@ -40,6 +40,9 @@
  */
 @ScriptClass("Uint8ClampedArray")
 public final class NativeUint8ClampedArray extends ArrayBufferView {
+    /**
+     * The size in bytes of each element in the array.
+     */
     @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE, where = Where.CONSTRUCTOR)
     public static final int BYTES_PER_ELEMENT = 1;
 
--- a/nashorn/src/jdk/nashorn/internal/runtime/JSONFunctions.java	Fri May 24 13:54:18 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/JSONFunctions.java	Fri May 24 18:39:25 2013 +0530
@@ -36,6 +36,8 @@
 import jdk.nashorn.internal.parser.JSONParser;
 import jdk.nashorn.internal.parser.TokenType;
 import jdk.nashorn.internal.runtime.linker.Bootstrap;
+import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndexNoThrow;
+import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
 
 /**
  * Utilities used by "JSON" object implementation.
@@ -94,7 +96,7 @@
         if (reviver instanceof ScriptFunction) {
             assert global instanceof GlobalObject;
             final ScriptObject root = ((GlobalObject)global).newObject();
-            root.set("", unfiltered, root.isStrictContext());
+            root.addOwnProperty("", Property.WRITABLE_ENUMERABLE_CONFIGURABLE, unfiltered);
             return walk(root, "", (ScriptFunction)reviver);
         }
         return unfiltered;
@@ -115,7 +117,7 @@
                 if (newElement == ScriptRuntime.UNDEFINED) {
                     valueObj.delete(key, strict);
                 } else {
-                    valueObj.set(key, newElement, strict);
+                    setPropertyValue(valueObj, key, newElement, strict);
                 }
             }
         }
@@ -175,7 +177,9 @@
                 final PropertyNode pNode     = (PropertyNode) elem;
                 final Node         valueNode = pNode.getValue();
 
-                object.set(pNode.getKeyName(), convertNode(global, valueNode), strict);
+                final String name = pNode.getKeyName();
+                final Object value = convertNode(global, valueNode);
+                setPropertyValue(object, name, value, strict);
             }
 
             return object;
@@ -188,6 +192,21 @@
         }
     }
 
+    // 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)) {
+            // array index key
+            sobj.defineOwnProperty(index, value);
+        } else if (sobj.getMap().findProperty(name) != null) {
+            // pre-existing non-inherited property, call set
+            sobj.set(name, value, strict);
+        } else {
+            // add new property
+            sobj.addOwnProperty(name, Property.WRITABLE_ENUMERABLE_CONFIGURABLE, value);
+        }
+    }
+
     // does the given IR node represent a numeric array?
     private static boolean isNumericArray(final Node[] values) {
         for (final Node node : values) {
--- a/nashorn/src/jdk/nashorn/internal/runtime/Property.java	Fri May 24 13:54:18 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/Property.java	Fri May 24 18:39:25 2013 +0530
@@ -52,6 +52,8 @@
      * we can use leave flag byte initialized with (the default) zero value.
      */
 
+    public static final int WRITABLE_ENUMERABLE_CONFIGURABLE = 0b0000_0000_0000;
+
     /** ECMA 8.6.1 - Is this property not writable? */
     public static final int NOT_WRITABLE     = 0b0000_0000_0001;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8015354.js	Fri May 24 18:39:25 2013 +0530
@@ -0,0 +1,46 @@
+/*
+ * 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-8015354: JSON.parse should not use [[Put]] but use [[DefineOwnProperty]] instead 
+ *
+ * @test
+ * @run
+ */
+
+Object.defineProperty(Object.prototype,
+    "", {
+    set: function(v) {
+        throw "set called";
+    }
+});
+
+JSON.parse('{}',function(){});
+
+Object.defineProperty(Object.prototype,
+    "foo",{
+    set: function(v) {
+        throw "set called";
+    }
+});
+JSON.parse('{"foo": 1}');