src/jdk/nashorn/internal/runtime/ScriptObject.java

Print this page

        

@@ -44,10 +44,12 @@
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex;
 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.isScopeFlag;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.isStrictFlag;
 import static jdk.nashorn.internal.runtime.linker.NashornGuards.explicitInstanceOfCheck;
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;

@@ -96,11 +98,11 @@
  * <li>Modifications of the map include adding/deleting attributes or changing a
  *     function field value.</li>
  * </ul>
  */
 
-public abstract class ScriptObject implements PropertyAccess {
+public abstract class ScriptObject implements PropertyAccess, Cloneable {
     /** __proto__ special property name inside object literals. ES6 draft. */
     public static final String PROTO_PROPERTY_NAME   = "__proto__";
 
     /** Search fall back routine name for "no such method" */
     public static final String NO_SUCH_METHOD_NAME   = "__noSuchMethod__";

@@ -2200,10 +2202,13 @@
             }
         }
 
         if (find != null) {
             if (!find.getProperty().isWritable() && !NashornCallSiteDescriptor.isDeclaration(desc)) {
+                if (NashornCallSiteDescriptor.isScope(desc) && find.getProperty().isLexicalBinding()) {
+                    throw typeError("assign.constant", name); // Overwriting ES6 const should throw also in non-strict mode.
+                }
                 // Existing, non-writable property
                 return createEmptySetMethod(desc, explicitInstanceOfCheck, "property.not.writable", true);
             }
         } else {
             if (!isExtensible()) {

@@ -3101,11 +3106,11 @@
 
     //value agnostic
     private boolean doesNotHaveEnsureLength(final long longIndex, final long oldLength, final int callSiteFlags) {
         if (longIndex >= oldLength) {
             if (!isExtensible()) {
-                if (NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)) {
+                if (isStrictFlag(callSiteFlags)) {
                     throw typeError("object.non.extensible", JSType.toString(longIndex), ScriptRuntime.safeToString(this));
                 }
                 return true;
             }
             setArray(getArray().ensure(longIndex));

@@ -3125,41 +3130,41 @@
 
     private void doesNotHave(final int index, final int value, final int callSiteFlags) {
         final long oldLength = getArray().length();
         final long longIndex = ArrayIndex.toLongIndex(index);
         if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
-            final boolean strict = NashornCallSiteDescriptor.isStrictFlag(callSiteFlags);
+            final boolean strict = isStrictFlag(callSiteFlags);
             setArray(getArray().set(index, value, strict));
             doesNotHaveEnsureDelete(longIndex, oldLength, strict);
         }
     }
 
     private void doesNotHave(final int index, final long value, final int callSiteFlags) {
         final long oldLength = getArray().length();
         final long longIndex = ArrayIndex.toLongIndex(index);
         if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
-            final boolean strict = NashornCallSiteDescriptor.isStrictFlag(callSiteFlags);
+            final boolean strict = isStrictFlag(callSiteFlags);
             setArray(getArray().set(index, value, strict));
             doesNotHaveEnsureDelete(longIndex, oldLength, strict);
         }
     }
 
     private void doesNotHave(final int index, final double value, final int callSiteFlags) {
         final long oldLength = getArray().length();
         final long longIndex = ArrayIndex.toLongIndex(index);
         if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
-            final boolean strict = NashornCallSiteDescriptor.isStrictFlag(callSiteFlags);
+            final boolean strict = isStrictFlag(callSiteFlags);
             setArray(getArray().set(index, value, strict));
             doesNotHaveEnsureDelete(longIndex, oldLength, strict);
         }
     }
 
     private void doesNotHave(final int index, final Object value, final int callSiteFlags) {
         final long oldLength = getArray().length();
         final long longIndex = ArrayIndex.toLongIndex(index);
         if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
-            final boolean strict = NashornCallSiteDescriptor.isStrictFlag(callSiteFlags);
+            final boolean strict = isStrictFlag(callSiteFlags);
             setArray(getArray().set(index, value, strict));
             doesNotHaveEnsureDelete(longIndex, oldLength, strict);
         }
     }
 

@@ -3176,11 +3181,11 @@
         FindProperty f = find;
 
         invalidateGlobalConstant(key);
 
         if (f != null && f.isInherited() && !(f.getProperty() instanceof UserAccessorProperty)) {
-            final boolean isScope = NashornCallSiteDescriptor.isScopeFlag(callSiteFlags);
+            final boolean isScope = isScopeFlag(callSiteFlags);
             // If the start object of the find is not this object it means the property was found inside a
             // 'with' statement expression (see WithObject.findProperty()). In this case we forward the 'set'
             // to the 'with' object.
             // Note that although a 'set' operation involving a with statement follows scope rules outside
             // the 'with' expression (the 'set' operation is performed on the owning prototype if it exists),

@@ -3197,20 +3202,23 @@
             }
         }
 
         if (f != null) {
             if (!f.getProperty().isWritable()) {
-                if (NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)) {
+                if (isScopeFlag(callSiteFlags) && f.getProperty().isLexicalBinding()) {
+                    throw typeError("assign.constant", key); // Overwriting ES6 const should throw also in non-strict mode.
+                }
+                if (isStrictFlag(callSiteFlags)) {
                     throw typeError("property.not.writable", key, ScriptRuntime.safeToString(this));
                 }
                 return;
             }
 
-            f.setValue(value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags));
+            f.setValue(value, isStrictFlag(callSiteFlags));
 
         } else if (!isExtensible()) {
-            if (NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)) {
+            if (isStrictFlag(callSiteFlags)) {
                 throw typeError("object.non.extensible", key, ScriptRuntime.safeToString(this));
             }
         } else {
             ScriptObject sobj = this;
             // undefined scope properties are set in the global object.

@@ -3233,11 +3241,11 @@
         final int    index        = getArrayIndex(primitiveKey);
 
         if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
             if (data.has(index)) {
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
 
             return;

@@ -3253,11 +3261,11 @@
         final int    index        = getArrayIndex(primitiveKey);
 
         if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
             if (data.has(index)) {
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
 
             return;

@@ -3273,11 +3281,11 @@
         final int    index        = getArrayIndex(primitiveKey);
 
         if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
             if (data.has(index)) {
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
 
             return;

@@ -3293,11 +3301,11 @@
         final int    index        = getArrayIndex(primitiveKey);
 
         if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
             if (data.has(index)) {
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
 
             return;

@@ -3312,11 +3320,11 @@
         final int index = getArrayIndex(key);
 
         if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
             if (data.has(index)) {
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
 
             return;

@@ -3331,11 +3339,11 @@
         final int index = getArrayIndex(key);
 
         if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
             if (data.has(index)) {
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
 
             return;

@@ -3350,11 +3358,11 @@
         final int index = getArrayIndex(key);
 
         if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
             if (data.has(index)) {
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
 
             return;

@@ -3369,11 +3377,11 @@
         final int index = getArrayIndex(key);
 
         if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
             if (data.has(index)) {
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
 
             return;

@@ -3388,11 +3396,11 @@
         final int index = getArrayIndex(key);
 
         if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
             if (data.has(index)) {
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
 
             return;

@@ -3407,11 +3415,11 @@
         final int index = getArrayIndex(key);
 
         if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
             if (data.has(index)) {
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
 
             return;

@@ -3426,11 +3434,11 @@
         final int index = getArrayIndex(key);
 
         if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
             if (data.has(index)) {
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
 
             return;

@@ -3445,11 +3453,11 @@
         final int index = getArrayIndex(key);
 
         if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
             if (data.has(index)) {
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
 
             return;

@@ -3463,11 +3471,11 @@
     public void set(final int key, final int value, final int callSiteFlags) {
         final int index = getArrayIndex(key);
         if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
                 final ArrayData data = getArray();
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
             return;
         }

@@ -3481,11 +3489,11 @@
         final int index = getArrayIndex(key);
 
         if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
             if (data.has(index)) {
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
 
             return;

@@ -3500,11 +3508,11 @@
         final int index = getArrayIndex(key);
 
         if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
             if (data.has(index)) {
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
 
             return;

@@ -3519,11 +3527,11 @@
         final int index = getArrayIndex(key);
 
         if (isValidArrayIndex(index)) {
             final ArrayData data = getArray();
             if (data.has(index)) {
-                setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
+                setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
             } else {
                 doesNotHave(index, value, callSiteFlags);
             }
 
             return;

@@ -3684,10 +3692,33 @@
 
         return true;
     }
 
     /**
+     * Return a shallow copy of this ScriptObject.
+     * @return a shallow copy.
+     */
+    public final ScriptObject copy() {
+        try {
+            return clone();
+        } catch (final CloneNotSupportedException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    protected ScriptObject clone() throws CloneNotSupportedException {
+        final ScriptObject clone = (ScriptObject) super.clone();
+        if (objectSpill != null) {
+            clone.objectSpill = objectSpill.clone();
+            clone.primitiveSpill = primitiveSpill.clone();
+        }
+        clone.arrayData = arrayData.copy();
+        return clone;
+    }
+
+    /**
      * Make a new UserAccessorProperty property. getter and setter functions are stored in
      * this ScriptObject and slot values are used in property object.
      *
      * @param key the property name
      * @param propertyFlags attribute flags of the property