src/jdk/nashorn/internal/runtime/ScriptObject.java
Print this page
*** 44,53 ****
--- 44,55 ----
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,106 ****
* <li>Modifications of the map include adding/deleting attributes or changing a
* function field value.</li>
* </ul>
*/
! public abstract class ScriptObject implements PropertyAccess {
/** __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__";
--- 98,108 ----
* <li>Modifications of the map include adding/deleting attributes or changing a
* function field value.</li>
* </ul>
*/
! 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,2209 ****
--- 2202,2214 ----
}
}
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,3111 ****
//value agnostic
private boolean doesNotHaveEnsureLength(final long longIndex, final long oldLength, final int callSiteFlags) {
if (longIndex >= oldLength) {
if (!isExtensible()) {
! if (NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)) {
throw typeError("object.non.extensible", JSType.toString(longIndex), ScriptRuntime.safeToString(this));
}
return true;
}
setArray(getArray().ensure(longIndex));
--- 3106,3116 ----
//value agnostic
private boolean doesNotHaveEnsureLength(final long longIndex, final long oldLength, final int callSiteFlags) {
if (longIndex >= oldLength) {
if (!isExtensible()) {
! if (isStrictFlag(callSiteFlags)) {
throw typeError("object.non.extensible", JSType.toString(longIndex), ScriptRuntime.safeToString(this));
}
return true;
}
setArray(getArray().ensure(longIndex));
*** 3125,3165 ****
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);
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);
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);
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);
setArray(getArray().set(index, value, strict));
doesNotHaveEnsureDelete(longIndex, oldLength, strict);
}
}
--- 3130,3170 ----
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 = 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 = 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 = 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 = isStrictFlag(callSiteFlags);
setArray(getArray().set(index, value, strict));
doesNotHaveEnsureDelete(longIndex, oldLength, strict);
}
}
*** 3176,3186 ****
FindProperty f = find;
invalidateGlobalConstant(key);
if (f != null && f.isInherited() && !(f.getProperty() instanceof UserAccessorProperty)) {
! final boolean isScope = NashornCallSiteDescriptor.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),
--- 3181,3191 ----
FindProperty f = find;
invalidateGlobalConstant(key);
if (f != null && f.isInherited() && !(f.getProperty() instanceof UserAccessorProperty)) {
! 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,3216 ****
}
}
if (f != null) {
if (!f.getProperty().isWritable()) {
! if (NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)) {
throw typeError("property.not.writable", key, ScriptRuntime.safeToString(this));
}
return;
}
! f.setValue(value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags));
} else if (!isExtensible()) {
! if (NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)) {
throw typeError("object.non.extensible", key, ScriptRuntime.safeToString(this));
}
} else {
ScriptObject sobj = this;
// undefined scope properties are set in the global object.
--- 3202,3224 ----
}
}
if (f != null) {
if (!f.getProperty().isWritable()) {
! 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, isStrictFlag(callSiteFlags));
} else if (!isExtensible()) {
! 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,3243 ****
final int index = getArrayIndex(primitiveKey);
if (isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
! setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
--- 3241,3251 ----
final int index = getArrayIndex(primitiveKey);
if (isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
! setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
*** 3253,3263 ****
final int index = getArrayIndex(primitiveKey);
if (isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
! setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
--- 3261,3271 ----
final int index = getArrayIndex(primitiveKey);
if (isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
! setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
*** 3273,3283 ****
final int index = getArrayIndex(primitiveKey);
if (isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
! setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
--- 3281,3291 ----
final int index = getArrayIndex(primitiveKey);
if (isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
! setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
*** 3293,3303 ****
final int index = getArrayIndex(primitiveKey);
if (isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
! setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
--- 3301,3311 ----
final int index = getArrayIndex(primitiveKey);
if (isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
! setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
*** 3312,3322 ****
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
! setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
--- 3320,3330 ----
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
! setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
*** 3331,3341 ****
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
! setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
--- 3339,3349 ----
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
! setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
*** 3350,3360 ****
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
! setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
--- 3358,3368 ----
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
! setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
*** 3369,3379 ****
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
! setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
--- 3377,3387 ----
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
! setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
*** 3388,3398 ****
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
! setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
--- 3396,3406 ----
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
! setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
*** 3407,3417 ****
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
! setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
--- 3415,3425 ----
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
! setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
*** 3426,3436 ****
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
! setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
--- 3434,3444 ----
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
! setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
*** 3445,3455 ****
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
! setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
--- 3453,3463 ----
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
! setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
*** 3463,3473 ****
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)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
}
--- 3471,3481 ----
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, isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
}
*** 3481,3491 ****
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
! setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
--- 3489,3499 ----
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
! setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
*** 3500,3510 ****
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
! setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
--- 3508,3518 ----
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
! setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
*** 3519,3529 ****
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
! setArray(data.set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
--- 3527,3537 ----
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
! setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
} else {
doesNotHave(index, value, callSiteFlags);
}
return;
*** 3684,3693 ****
--- 3692,3724 ----
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