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