8015355: Array.prototype functions don't honour non-writable length and / or index properties
Reviewed-by: lagergren, hannesw
--- a/nashorn/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java Wed Jun 12 16:41:38 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java Thu Jun 13 16:08:35 2013 +0530
@@ -138,18 +138,16 @@
@Override
public PropertyDescriptor fillFrom(final ScriptObject sobj) {
- final boolean strict = isStrictContext();
-
if (sobj.has(CONFIGURABLE)) {
this.configurable = JSType.toBoolean(sobj.get(CONFIGURABLE));
} else {
- delete(CONFIGURABLE, strict);
+ delete(CONFIGURABLE, false);
}
if (sobj.has(ENUMERABLE)) {
this.enumerable = JSType.toBoolean(sobj.get(ENUMERABLE));
} else {
- delete(ENUMERABLE, strict);
+ delete(ENUMERABLE, false);
}
if (sobj.has(GET)) {
@@ -160,7 +158,7 @@
throw typeError("not.a.function", ScriptRuntime.safeToString(getter));
}
} else {
- delete(GET, strict);
+ delete(GET, false);
}
if (sobj.has(SET)) {
@@ -171,7 +169,7 @@
throw typeError("not.a.function", ScriptRuntime.safeToString(setter));
}
} else {
- delete(SET, strict);
+ delete(SET, false);
}
return this;
--- a/nashorn/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java Wed Jun 12 16:41:38 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java Thu Jun 13 16:08:35 2013 +0530
@@ -136,29 +136,28 @@
@Override
public PropertyDescriptor fillFrom(final ScriptObject sobj) {
- final boolean strict = isStrictContext();
if (sobj.has(CONFIGURABLE)) {
this.configurable = JSType.toBoolean(sobj.get(CONFIGURABLE));
} else {
- delete(CONFIGURABLE, strict);
+ delete(CONFIGURABLE, false);
}
if (sobj.has(ENUMERABLE)) {
this.enumerable = JSType.toBoolean(sobj.get(ENUMERABLE));
} else {
- delete(ENUMERABLE, strict);
+ delete(ENUMERABLE, false);
}
if (sobj.has(WRITABLE)) {
this.writable = JSType.toBoolean(sobj.get(WRITABLE));
} else {
- delete(WRITABLE, strict);
+ delete(WRITABLE, false);
}
if (sobj.has(VALUE)) {
this.value = sobj.get(VALUE);
} else {
- delete(VALUE, strict);
+ delete(VALUE, false);
}
return this;
--- a/nashorn/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java Wed Jun 12 16:41:38 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java Thu Jun 13 16:08:35 2013 +0530
@@ -124,17 +124,16 @@
@Override
public PropertyDescriptor fillFrom(final ScriptObject sobj) {
- final boolean strict = isStrictContext();
if (sobj.has(CONFIGURABLE)) {
this.configurable = JSType.toBoolean(sobj.get(CONFIGURABLE));
} else {
- delete(CONFIGURABLE, strict);
+ delete(CONFIGURABLE, false);
}
if (sobj.has(ENUMERABLE)) {
this.enumerable = JSType.toBoolean(sobj.get(ENUMERABLE));
} else {
- delete(ENUMERABLE, strict);
+ delete(ENUMERABLE, false);
}
return this;
--- a/nashorn/src/jdk/nashorn/internal/objects/Global.java Wed Jun 12 16:41:38 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/Global.java Thu Jun 13 16:08:35 2013 +0530
@@ -430,15 +430,6 @@
return instance().context;
}
- /**
- * Script access check for strict mode
- *
- * @return true if strict mode enabled in {@link Global#getThisContext()}
- */
- static boolean isStrict() {
- return getEnv()._strict;
- }
-
// GlobalObject interface implementation
@Override
@@ -616,14 +607,12 @@
public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) {
final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set);
- final boolean strict = context.getEnv()._strict;
-
if (get == null) {
- desc.delete(PropertyDescriptor.GET, strict);
+ desc.delete(PropertyDescriptor.GET, false);
}
if (set == null) {
- desc.delete(PropertyDescriptor.SET, strict);
+ desc.delete(PropertyDescriptor.SET, false);
}
return desc;
@@ -1485,7 +1474,6 @@
// Error objects
this.builtinError = (ScriptFunction)initConstructor("Error");
final ScriptObject errorProto = getErrorPrototype();
- final boolean strict = Global.isStrict();
// Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK);
@@ -1503,10 +1491,10 @@
// ECMA 15.11.4.2 Error.prototype.name
// Error.prototype.name = "Error";
- errorProto.set(NativeError.NAME, "Error", strict);
+ errorProto.set(NativeError.NAME, "Error", false);
// ECMA 15.11.4.3 Error.prototype.message
// Error.prototype.message = "";
- errorProto.set(NativeError.MESSAGE, "", strict);
+ errorProto.set(NativeError.MESSAGE, "", false);
this.builtinEvalError = initErrorSubtype("EvalError", errorProto);
this.builtinRangeError = initErrorSubtype("RangeError", errorProto);
@@ -1519,9 +1507,8 @@
private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
final ScriptObject cons = initConstructor(name);
final ScriptObject prototype = ScriptFunction.getPrototype(cons);
- final boolean strict = Global.isStrict();
- prototype.set(NativeError.NAME, name, strict);
- prototype.set(NativeError.MESSAGE, "", strict);
+ prototype.set(NativeError.NAME, name, false);
+ prototype.set(NativeError.MESSAGE, "", false);
prototype.setProto(errorProto);
return (ScriptFunction)cons;
}
@@ -1730,7 +1717,7 @@
// <anon-function>
builtinFunction.setProto(anon);
builtinFunction.setPrototype(anon);
- anon.set("constructor", builtinFunction, anon.isStrict());
+ anon.set("constructor", builtinFunction, false);
anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
// now initialize Object
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java Wed Jun 12 16:41:38 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java Thu Jun 13 16:08:35 2013 +0530
@@ -118,7 +118,7 @@
if (value == ScriptRuntime.EMPTY) {
arrayData = arrayData.delete(index);
} else {
- arrayData = arrayData.set(index, value, isStrictContext());
+ arrayData = arrayData.set(index, value, false);
}
}
@@ -158,6 +158,11 @@
// Step 3
if ("length".equals(key)) {
+ // check for length being made non-writable
+ if (desc.has(WRITABLE) && !desc.isWritable()) {
+ setIsLengthNotWritable();
+ }
+
// Step 3a
if (!desc.has(VALUE)) {
return super.defineOwnProperty("length", desc, reject);
@@ -603,7 +608,6 @@
public static Object pop(final Object self) {
try {
final ScriptObject sobj = (ScriptObject)self;
- final boolean strict = sobj.isStrictContext();
if (bulkable(sobj)) {
return sobj.getArray().pop();
@@ -612,15 +616,15 @@
final long len = JSType.toUint32(sobj.getLength());
if (len == 0) {
- sobj.set("length", 0, strict);
+ sobj.set("length", 0, true);
return ScriptRuntime.UNDEFINED;
}
final long index = len - 1;
final Object element = sobj.get(index);
- sobj.delete(index, strict);
- sobj.set("length", index, strict);
+ sobj.delete(index, true);
+ sobj.set("length", index, true);
return element;
} catch (final ClassCastException | NullPointerException e) {
@@ -639,11 +643,10 @@
public static Object push(final Object self, final Object... args) {
try {
final ScriptObject sobj = (ScriptObject)self;
- final boolean strict = sobj.isStrictContext();
if (bulkable(sobj)) {
if (sobj.getArray().length() + args.length <= JSType.MAX_UINT) {
- final ArrayData newData = sobj.getArray().push(sobj.isStrictContext(), args);
+ final ArrayData newData = sobj.getArray().push(true, args);
sobj.setArray(newData);
return newData.length();
}
@@ -652,9 +655,9 @@
long len = JSType.toUint32(sobj.getLength());
for (final Object element : args) {
- sobj.set(len++, element, strict);
+ sobj.set(len++, element, true);
}
- sobj.set("length", len, strict);
+ sobj.set("length", len, true);
return len;
} catch (final ClassCastException | NullPointerException e) {
@@ -672,7 +675,6 @@
public static Object reverse(final Object self) {
try {
final ScriptObject sobj = (ScriptObject)self;
- final boolean strict = sobj.isStrictContext();
final long len = JSType.toUint32(sobj.getLength());
final long middle = len / 2;
@@ -684,14 +686,14 @@
final boolean upperExists = sobj.has(upper);
if (lowerExists && upperExists) {
- sobj.set(lower, upperValue, strict);
- sobj.set(upper, lowerValue, strict);
+ sobj.set(lower, upperValue, true);
+ sobj.set(upper, lowerValue, true);
} else if (!lowerExists && upperExists) {
- sobj.set(lower, upperValue, strict);
- sobj.delete(upper, strict);
+ sobj.set(lower, upperValue, true);
+ sobj.delete(upper, true);
} else if (lowerExists && !upperExists) {
- sobj.delete(lower, strict);
- sobj.set(upper, lowerValue, strict);
+ sobj.delete(lower, true);
+ sobj.set(upper, lowerValue, true);
}
}
return sobj;
@@ -717,7 +719,6 @@
}
final ScriptObject sobj = (ScriptObject) obj;
- final boolean strict = Global.isStrict();
long len = JSType.toUint32(sobj.getLength());
@@ -728,15 +729,15 @@
sobj.getArray().shiftLeft(1);
} else {
for (long k = 1; k < len; k++) {
- sobj.set(k - 1, sobj.get(k), strict);
+ sobj.set(k - 1, sobj.get(k), true);
}
}
- sobj.delete(--len, strict);
+ sobj.delete(--len, true);
} else {
len = 0;
}
- sobj.set("length", len, strict);
+ sobj.set("length", len, true);
return first;
}
@@ -833,7 +834,6 @@
public static Object sort(final Object self, final Object comparefn) {
try {
final ScriptObject sobj = (ScriptObject) self;
- final boolean strict = sobj.isStrictContext();
final long len = JSType.toUint32(sobj.getLength());
ArrayData array = sobj.getArray();
@@ -850,7 +850,7 @@
final Object[] sorted = sort(src.toArray(), comparefn);
for (int i = 0; i < sorted.length; i++) {
- array = array.set(i, sorted[i], strict);
+ array = array.set(i, sorted[i], true);
}
// delete missing elements - which are at the end of sorted array
@@ -891,7 +891,6 @@
}
final ScriptObject sobj = (ScriptObject)obj;
- final boolean strict = Global.isStrict();
final long len = JSType.toUint32(sobj.getLength());
final long relativeStart = JSType.toLong(start);
@@ -914,14 +913,14 @@
final long to = k + items.length;
if (sobj.has(from)) {
- sobj.set(to, sobj.get(from), strict);
+ sobj.set(to, sobj.get(from), true);
} else {
- sobj.delete(to, strict);
+ sobj.delete(to, true);
}
}
for (long k = len; k > (len - actualDeleteCount + items.length); k--) {
- sobj.delete(k - 1, strict);
+ sobj.delete(k - 1, true);
}
} else if (items.length > actualDeleteCount) {
for (long k = len - actualDeleteCount; k > actualStart; k--) {
@@ -930,20 +929,20 @@
if (sobj.has(from)) {
final Object fromValue = sobj.get(from);
- sobj.set(to, fromValue, strict);
+ sobj.set(to, fromValue, true);
} else {
- sobj.delete(to, strict);
+ sobj.delete(to, true);
}
}
}
long k = actualStart;
for (int i = 0; i < items.length; i++, k++) {
- sobj.set(k, items[i], strict);
+ sobj.set(k, items[i], true);
}
final long newLength = len - actualDeleteCount + items.length;
- sobj.set("length", newLength, strict);
+ sobj.set("length", newLength, true);
return array;
}
@@ -964,7 +963,6 @@
}
final ScriptObject sobj = (ScriptObject)obj;
- final boolean strict = Global.isStrict();
final long len = JSType.toUint32(sobj.getLength());
if (items == null) {
@@ -975,7 +973,7 @@
sobj.getArray().shiftRight(items.length);
for (int j = 0; j < items.length; j++) {
- sobj.setArray(sobj.getArray().set(j, items[j], sobj.isStrictContext()));
+ sobj.setArray(sobj.getArray().set(j, items[j], true));
}
} else {
for (long k = len; k > 0; k--) {
@@ -984,19 +982,19 @@
if (sobj.has(from)) {
final Object fromValue = sobj.get(from);
- sobj.set(to, fromValue, strict);
+ sobj.set(to, fromValue, true);
} else {
- sobj.delete(to, strict);
+ sobj.delete(to, true);
}
}
for (int j = 0; j < items.length; j++) {
- sobj.set(j, items[j], strict);
+ sobj.set(j, items[j], true);
}
}
final long newLength = len + items.length;
- sobj.set("length", newLength, strict);
+ sobj.set("length", newLength, true);
return newLength;
}
@@ -1239,7 +1237,7 @@
* @return true if optimizable
*/
private static boolean bulkable(final ScriptObject self) {
- return self.isArray() && !hasInheritedArrayEntries(self);
+ return self.isArray() && !hasInheritedArrayEntries(self) && !self.isLengthNotWritable();
}
private static boolean hasInheritedArrayEntries(final ScriptObject self) {
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeError.java Wed Jun 12 16:41:38 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeError.java Thu Jun 13 16:08:35 2013 +0530
@@ -90,7 +90,7 @@
if (msg != UNDEFINED) {
this.instMessage = JSType.toString(msg);
} else {
- this.delete(NativeError.MESSAGE, Global.isStrict());
+ this.delete(NativeError.MESSAGE, false);
}
}
@@ -166,7 +166,7 @@
public static Object setLineNumber(final Object self, final Object value) {
Global.checkObject(self);
final ScriptObject sobj = (ScriptObject)self;
- sobj.set(LINENUMBER, value, Global.isStrict());
+ sobj.set(LINENUMBER, value, false);
return value;
}
@@ -194,7 +194,7 @@
public static Object setColumnNumber(final Object self, final Object value) {
Global.checkObject(self);
final ScriptObject sobj = (ScriptObject)self;
- sobj.set(COLUMNNUMBER, value, Global.isStrict());
+ sobj.set(COLUMNNUMBER, value, false);
return value;
}
@@ -222,7 +222,7 @@
public static Object setFileName(final Object self, final Object value) {
Global.checkObject(self);
final ScriptObject sobj = (ScriptObject)self;
- sobj.set(FILENAME, value, Global.isStrict());
+ sobj.set(FILENAME, value, false);
return value;
}
@@ -278,7 +278,7 @@
public static Object setStack(final Object self, final Object value) {
Global.checkObject(self);
final ScriptObject sobj = (ScriptObject)self;
- sobj.set(STACK, value, Global.isStrict());
+ sobj.set(STACK, value, false);
return value;
}
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeEvalError.java Wed Jun 12 16:41:38 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeEvalError.java Thu Jun 13 16:08:35 2013 +0530
@@ -59,7 +59,7 @@
if (msg != UNDEFINED) {
this.instMessage = JSType.toString(msg);
} else {
- this.delete(NativeError.MESSAGE, Global.isStrict());
+ this.delete(NativeError.MESSAGE, false);
}
}
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeFunction.java Wed Jun 12 16:41:38 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeFunction.java Thu Jun 13 16:08:35 2013 +0530
@@ -216,7 +216,7 @@
final Global global = Global.instance();
- return Global.directEval(global, sb.toString(), global, "<function>", Global.isStrict());
+ return Global.directEval(global, sb.toString(), global, "<function>", global.isStrictContext());
}
private static void checkFunctionParameters(final String params) {
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeJSON.java Wed Jun 12 16:41:38 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeJSON.java Thu Jun 13 16:08:35 2013 +0530
@@ -158,7 +158,7 @@
state.gap = gap;
final ScriptObject wrapper = Global.newEmptyInstance();
- wrapper.set("", value, Global.isStrict());
+ wrapper.set("", value, false);
return str("", wrapper, state);
}
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeJavaImporter.java Wed Jun 12 16:41:38 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeJavaImporter.java Thu Jun 13 16:08:35 2013 +0530
@@ -121,7 +121,7 @@
final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
final Object value = createProperty(name);
if(value != null) {
- set(name, value, isStrictContext());
+ set(name, value, false);
return true;
}
return false;
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeRangeError.java Wed Jun 12 16:41:38 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeRangeError.java Thu Jun 13 16:08:35 2013 +0530
@@ -59,7 +59,7 @@
if (msg != UNDEFINED) {
this.instMessage = JSType.toString(msg);
} else {
- this.delete(NativeError.MESSAGE, Global.isStrict());
+ this.delete(NativeError.MESSAGE, false);
}
}
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeReferenceError.java Wed Jun 12 16:41:38 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeReferenceError.java Thu Jun 13 16:08:35 2013 +0530
@@ -59,7 +59,7 @@
if (msg != UNDEFINED) {
this.instMessage = JSType.toString(msg);
} else {
- this.delete(NativeError.MESSAGE, Global.isStrict());
+ this.delete(NativeError.MESSAGE, false);
}
}
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeSyntaxError.java Wed Jun 12 16:41:38 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeSyntaxError.java Thu Jun 13 16:08:35 2013 +0530
@@ -59,7 +59,7 @@
if (msg != UNDEFINED) {
this.instMessage = JSType.toString(msg);
} else {
- this.delete(NativeError.MESSAGE, Global.isStrict());
+ this.delete(NativeError.MESSAGE, false);
}
}
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeTypeError.java Wed Jun 12 16:41:38 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeTypeError.java Thu Jun 13 16:08:35 2013 +0530
@@ -59,7 +59,7 @@
if (msg != UNDEFINED) {
this.instMessage = JSType.toString(msg);
} else {
- delete(NativeError.MESSAGE, Global.isStrict());
+ delete(NativeError.MESSAGE, false);
}
}
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeURIError.java Wed Jun 12 16:41:38 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeURIError.java Thu Jun 13 16:08:35 2013 +0530
@@ -58,7 +58,7 @@
if (msg != UNDEFINED) {
this.instMessage = JSType.toString(msg);
} else {
- this.delete(NativeError.MESSAGE, Global.isStrict());
+ this.delete(NativeError.MESSAGE, false);
}
}
--- a/nashorn/src/jdk/nashorn/internal/runtime/Context.java Wed Jun 12 16:41:38 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/Context.java Thu Jun 13 16:08:35 2013 +0530
@@ -188,7 +188,7 @@
private final ScriptEnvironment env;
/** is this context in strict mode? Cached from env. as this is used heavily. */
- public final boolean _strict;
+ final boolean _strict;
/** class loader to resolve classes from script. */
private final ClassLoader appLoader;
--- a/nashorn/src/jdk/nashorn/internal/runtime/JSONFunctions.java Wed Jun 12 16:41:38 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/JSONFunctions.java Thu Jun 13 16:08:35 2013 +0530
@@ -101,7 +101,6 @@
final Object val = holder.get(name);
if (val instanceof ScriptObject) {
final ScriptObject valueObj = (ScriptObject)val;
- final boolean strict = valueObj.isStrictContext();
final Iterator<String> iter = valueObj.propertyIterator();
while (iter.hasNext()) {
@@ -109,9 +108,9 @@
final Object newElement = walk(valueObj, key, reviver);
if (newElement == ScriptRuntime.UNDEFINED) {
- valueObj.delete(key, strict);
+ valueObj.delete(key, false);
} else {
- setPropertyValue(valueObj, key, newElement, strict);
+ setPropertyValue(valueObj, key, newElement, false);
}
}
}
@@ -164,14 +163,13 @@
} else if (node instanceof ObjectNode) {
final ObjectNode objNode = (ObjectNode) node;
final ScriptObject object = ((GlobalObject)global).newObject();
- final boolean strict = global.isStrictContext();
for (final PropertyNode pNode: objNode.getElements()) {
final Node valueNode = pNode.getValue();
final String name = pNode.getKeyName();
final Object value = convertNode(global, valueNode);
- setPropertyValue(object, name, value, strict);
+ setPropertyValue(object, name, value, false);
}
return object;
--- a/nashorn/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java Wed Jun 12 16:41:38 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java Thu Jun 13 16:08:35 2013 +0530
@@ -199,7 +199,6 @@
final String fullName = name.isEmpty() ? propertyName : name + "." + propertyName;
final Context context = getContext();
- final boolean strict = context._strict;
Class<?> javaClass = null;
try {
@@ -209,9 +208,9 @@
}
if (javaClass == null) {
- set(propertyName, new NativeJavaPackage(fullName, getProto()), strict);
+ set(propertyName, new NativeJavaPackage(fullName, getProto()), false);
} else {
- set(propertyName, StaticClass.forClass(javaClass), strict);
+ set(propertyName, StaticClass.forClass(javaClass), false);
}
return super.lookup(desc, request);
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java Wed Jun 12 16:41:38 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java Thu Jun 13 16:08:35 2013 +0530
@@ -105,6 +105,9 @@
/** Is this a prototype PropertyMap? */
public static final int IS_PROTOTYPE = 0b0000_1000;
+ /** Is length property not-writable? */
+ public static final int IS_LENGTH_NOT_WRITABLE = 0b0001_0000;
+
/** Spill growth rate - by how many elements does {@link ScriptObject#spill} when full */
public static final int SPILL_RATE = 8;
@@ -443,7 +446,7 @@
if (newValue && property != null) {
// Temporarily clear flags.
property = modifyOwnProperty(property, 0);
- set(key, value, getContext()._strict);
+ set(key, value, false);
}
if (property == null) {
@@ -998,7 +1001,7 @@
* @param value the value to write at the given index
*/
public void setArgument(final int key, final Object value) {
- set(key, value, getContext()._strict);
+ set(key, value, false);
}
/**
@@ -1277,14 +1280,14 @@
*
* @return {@code true} if is prototype
*/
- public boolean isPrototype() {
+ public final boolean isPrototype() {
return (flags & IS_PROTOTYPE) != 0;
}
/**
* Flag this object as having a prototype.
*/
- public void setIsPrototype() {
+ public final void setIsPrototype() {
if (proto != null && !isPrototype()) {
proto.addPropertyListener(this);
}
@@ -1292,6 +1295,22 @@
}
/**
+ * Check if this object has non-writable length property
+ *
+ * @return {@code true} if 'length' property is non-writable
+ */
+ public final boolean isLengthNotWritable() {
+ return (flags & IS_LENGTH_NOT_WRITABLE) != 0;
+ }
+
+ /**
+ * Flag this object as having non-writable length property
+ */
+ public void setIsLengthNotWritable() {
+ flags |= IS_LENGTH_NOT_WRITABLE;
+ }
+
+ /**
* Get the {@link ArrayData} for this ScriptObject if it is an array
* @return array data
*/
@@ -1393,7 +1412,7 @@
* (java.util.Map-like method to help ScriptObjectMirror implementation)
*/
public void clear() {
- final boolean strict = getContext()._strict;
+ final boolean strict = isStrictContext();
final Iterator<String> iter = propertyIterator();
while (iter.hasNext()) {
delete(iter.next(), strict);
@@ -1481,7 +1500,7 @@
*/
public Object put(final Object key, final Object value) {
final Object oldValue = get(key);
- set(key, value, getContext()._strict);
+ set(key, value, isStrictContext());
return oldValue;
}
@@ -1493,7 +1512,7 @@
* @param otherMap a {@literal <key,value>} map of properties to add
*/
public void putAll(final Map<?, ?> otherMap) {
- final boolean strict = getContext()._strict;
+ final boolean strict = isStrictContext();
for (final Map.Entry<?, ?> entry : otherMap.entrySet()) {
set(entry.getKey(), entry.getValue(), strict);
}
@@ -1508,7 +1527,7 @@
*/
public Object remove(final Object key) {
final Object oldValue = get(key);
- delete(key, getContext()._strict);
+ delete(key, isStrictContext());
return oldValue;
}
@@ -1520,7 +1539,7 @@
* @return if the delete was successful or not
*/
public boolean delete(final Object key) {
- return delete(key, getContext()._strict);
+ return delete(key, isStrictContext());
}
/**
@@ -2222,7 +2241,7 @@
return;
}
- final boolean isStrict = getContext()._strict;
+ final boolean isStrict = isStrictContext();
if (newLength > arrayLength) {
setArray(getArray().ensure(newLength - 1));
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java Wed Jun 12 16:41:38 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java Thu Jun 13 16:08:35 2013 +0530
@@ -221,10 +221,9 @@
final String err = errBuffer.toString();
// Set globals for secondary results.
- final boolean isStrict = global.isStrictContext();
- global.set(OUT_NAME, out, isStrict);
- global.set(ERR_NAME, err, isStrict);
- global.set(EXIT_NAME, exit, isStrict);
+ global.set(OUT_NAME, out, false);
+ global.set(ERR_NAME, err, false);
+ global.set(EXIT_NAME, exit, false);
// Propagate exception if present.
for (int i = 0; i < exception.length; i++) {
--- a/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayIterator.java Wed Jun 12 16:41:38 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayIterator.java Thu Jun 13 16:08:35 2013 +0530
@@ -83,6 +83,6 @@
@Override
public void remove() {
- array.delete(index, array.isStrictContext());
+ array.delete(index, false);
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8015355.js Thu Jun 13 16:08:35 2013 +0530
@@ -0,0 +1,122 @@
+/*
+ * 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-8015355: Array.prototype functions don't honour non-writable length and / or index properties
+ *
+ * @test
+ * @run
+ */
+
+function fail(msg) {
+ print(msg);
+}
+
+function check(callback) {
+ try {
+ callback();
+ fail("TypeError expected for " + callback);
+ } catch (e) {
+ if (! (e instanceof TypeError)) {
+ fail("TypeError expected, got " + e);
+ }
+ }
+}
+
+var array = Object.defineProperty([],"length", { writable: false });
+
+check(function() {
+ array.push(0)
+});
+
+check(function() {
+ array.pop()
+});
+
+check(function() {
+ Object.defineProperty([,,],"0",{ writable: false }).reverse();
+});
+
+check(function() {
+ array.shift()
+});
+
+check(function() {
+ array.splice(0)
+});
+
+check(function() {
+ array.unshift()
+});
+
+// try the above via call
+
+check(function() {
+ Array.prototype.push.call(array, 0);
+});
+
+check(function() {
+ Array.prototype.pop.call(array);
+});
+
+check(function() {
+ Array.prototype.shift.call(array);
+});
+
+check(function() {
+ Array.prototype.unshift.call(array);
+});
+
+check(function() {
+ Array.prototype.splice.call(array, 0);
+});
+
+check(function() {
+ Array.prototype.reverse.call(Object.defineProperty([,,],"0",{ writable: false }));
+});
+
+// try the above via apply
+
+check(function() {
+ Array.prototype.push.apply(array, [ 0 ]);
+});
+
+check(function() {
+ Array.prototype.pop.apply(array);
+});
+
+check(function() {
+ Array.prototype.shift.apply(array);
+});
+
+check(function() {
+ Array.prototype.unshift.apply(array);
+});
+
+check(function() {
+ Array.prototype.splice.apply(array, [ 0 ]);
+});
+
+check(function() {
+ Array.prototype.reverse.apply(Object.defineProperty([,,],"0",{ writable: false }));
+});