8047764: Indexed or polymorphic set on global affects Object.prototype
Reviewed-by: lagergren, attila
This commit is contained in:
parent
7cb28afba6
commit
62f4b355b5
@ -50,6 +50,7 @@ import jdk.nashorn.internal.runtime.ScriptFunction;
|
||||
import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
import jdk.nashorn.internal.runtime.ScriptRuntime;
|
||||
import jdk.nashorn.internal.runtime.arrays.ArrayData;
|
||||
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
|
||||
|
||||
/**
|
||||
* Mirror object that wraps a given Nashorn Script object.
|
||||
@ -261,7 +262,7 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin
|
||||
public void setSlot(final int index, final Object value) {
|
||||
inGlobal(new Callable<Void>() {
|
||||
@Override public Void call() {
|
||||
sobj.set(index, unwrap(value, global), strict);
|
||||
sobj.set(index, unwrap(value, global), getCallSiteFlags());
|
||||
return null;
|
||||
}
|
||||
});
|
||||
@ -425,7 +426,7 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin
|
||||
for (final Map.Entry<? extends String, ? extends Object> entry : map.entrySet()) {
|
||||
final Object value = entry.getValue();
|
||||
final Object modValue = globalChanged? wrap(value, oldGlobal) : value;
|
||||
sobj.set(entry.getKey(), unwrap(modValue, global), strict);
|
||||
sobj.set(entry.getKey(), unwrap(modValue, global), getCallSiteFlags());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -756,6 +757,10 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin
|
||||
return (obj == ScriptRuntime.UNDEFINED)? null : obj;
|
||||
}
|
||||
|
||||
private int getCallSiteFlags() {
|
||||
return strict ? NashornCallSiteDescriptor.CALLSITE_STRICT : 0;
|
||||
}
|
||||
|
||||
// internals only below this.
|
||||
private <V> V inGlobal(final Callable<V> callable) {
|
||||
final Global oldGlobal = Context.getGlobal();
|
||||
|
@ -228,11 +228,11 @@ abstract class ArrayBufferView extends ScriptObject {
|
||||
private static void copyElements(final ArrayBufferView dest, final int length, final ScriptObject source, final int offset) {
|
||||
if (!dest.isFloatArray()) {
|
||||
for (int i = 0, j = offset; i < length; i++, j++) {
|
||||
dest.set(j, source.getInt(i, INVALID_PROGRAM_POINT), false);
|
||||
dest.set(j, source.getInt(i, INVALID_PROGRAM_POINT), 0);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0, j = offset; i < length; i++, j++) {
|
||||
dest.set(j, source.getDouble(i, INVALID_PROGRAM_POINT), false);
|
||||
dest.set(j, source.getDouble(i, INVALID_PROGRAM_POINT), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1825,10 +1825,10 @@ public final class Global extends ScriptObject implements Scope {
|
||||
|
||||
// ECMA 15.11.4.2 Error.prototype.name
|
||||
// Error.prototype.name = "Error";
|
||||
errorProto.set(NativeError.NAME, "Error", false);
|
||||
errorProto.set(NativeError.NAME, "Error", 0);
|
||||
// ECMA 15.11.4.3 Error.prototype.message
|
||||
// Error.prototype.message = "";
|
||||
errorProto.set(NativeError.MESSAGE, "", false);
|
||||
errorProto.set(NativeError.MESSAGE, "", 0);
|
||||
|
||||
this.builtinEvalError = initErrorSubtype("EvalError", errorProto);
|
||||
this.builtinRangeError = initErrorSubtype("RangeError", errorProto);
|
||||
@ -1841,8 +1841,8 @@ public final class Global extends ScriptObject implements Scope {
|
||||
private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
|
||||
final ScriptFunction cons = initConstructor(name, ScriptFunction.class);
|
||||
final ScriptObject prototype = ScriptFunction.getPrototype(cons);
|
||||
prototype.set(NativeError.NAME, name, false);
|
||||
prototype.set(NativeError.MESSAGE, "", false);
|
||||
prototype.set(NativeError.NAME, name, 0);
|
||||
prototype.set(NativeError.MESSAGE, "", 0);
|
||||
prototype.setInitialProto(errorProto);
|
||||
return cons;
|
||||
}
|
||||
@ -1902,7 +1902,7 @@ public final class Global extends ScriptObject implements Scope {
|
||||
private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) {
|
||||
for (final Field f : scriptEnv.getClass().getFields()) {
|
||||
try {
|
||||
options.set(f.getName(), f.get(scriptEnv), false);
|
||||
options.set(f.getName(), f.get(scriptEnv), 0);
|
||||
} catch (final IllegalArgumentException | IllegalAccessException exp) {
|
||||
throw new RuntimeException(exp);
|
||||
}
|
||||
@ -2046,7 +2046,7 @@ public final class Global extends ScriptObject implements Scope {
|
||||
// <anon-function>
|
||||
builtinFunction.setInitialProto(anon);
|
||||
builtinFunction.setPrototype(anon);
|
||||
anon.set("constructor", builtinFunction, false);
|
||||
anon.set("constructor", builtinFunction, 0);
|
||||
anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
|
||||
|
||||
// use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3
|
||||
|
@ -32,6 +32,7 @@ import static jdk.nashorn.internal.runtime.PropertyDescriptor.WRITABLE;
|
||||
import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
|
||||
import static jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator.arrayLikeIterator;
|
||||
import static jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator.reverseArrayLikeIterator;
|
||||
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_STRICT;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.util.ArrayList;
|
||||
@ -69,6 +70,7 @@ import jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator;
|
||||
import jdk.nashorn.internal.runtime.arrays.IteratorAction;
|
||||
import jdk.nashorn.internal.runtime.linker.Bootstrap;
|
||||
import jdk.nashorn.internal.runtime.linker.InvokeByName;
|
||||
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
|
||||
|
||||
/**
|
||||
* Runtime representation of a JavaScript array. NativeArray only holds numeric
|
||||
@ -341,7 +343,7 @@ public final class NativeArray extends ScriptObject {
|
||||
if (!newWritable) {
|
||||
// make 'length' property not writable
|
||||
final ScriptObject newDesc = Global.newEmptyInstance();
|
||||
newDesc.set(WRITABLE, false, false);
|
||||
newDesc.set(WRITABLE, false, 0);
|
||||
return super.defineOwnProperty("length", newDesc, false);
|
||||
}
|
||||
|
||||
@ -808,7 +810,7 @@ public final class NativeArray extends ScriptObject {
|
||||
final long len = JSType.toUint32(sobj.getLength());
|
||||
|
||||
if (len == 0) {
|
||||
sobj.set("length", 0, true);
|
||||
sobj.set("length", 0, CALLSITE_STRICT);
|
||||
return ScriptRuntime.UNDEFINED;
|
||||
}
|
||||
|
||||
@ -816,7 +818,7 @@ public final class NativeArray extends ScriptObject {
|
||||
final Object element = sobj.get(index);
|
||||
|
||||
sobj.delete(index, true);
|
||||
sobj.set("length", index, true);
|
||||
sobj.set("length", index, CALLSITE_STRICT);
|
||||
|
||||
return element;
|
||||
} catch (final ClassCastException | NullPointerException e) {
|
||||
@ -844,9 +846,9 @@ public final class NativeArray extends ScriptObject {
|
||||
|
||||
long len = JSType.toUint32(sobj.getLength());
|
||||
for (final Object element : args) {
|
||||
sobj.set(len++, element, true);
|
||||
sobj.set(len++, element, CALLSITE_STRICT);
|
||||
}
|
||||
sobj.set("length", len, true);
|
||||
sobj.set("length", len, CALLSITE_STRICT);
|
||||
|
||||
return len;
|
||||
} catch (final ClassCastException | NullPointerException e) {
|
||||
@ -928,8 +930,8 @@ public final class NativeArray extends ScriptObject {
|
||||
}
|
||||
|
||||
long len = JSType.toUint32(sobj.getLength());
|
||||
sobj.set(len++, arg, true);
|
||||
sobj.set("length", len, true);
|
||||
sobj.set(len++, arg, CALLSITE_STRICT);
|
||||
sobj.set("length", len, CALLSITE_STRICT);
|
||||
return len;
|
||||
} catch (final ClassCastException | NullPointerException e) {
|
||||
throw typeError("not.an.object", ScriptRuntime.safeToString(self));
|
||||
@ -957,14 +959,14 @@ public final class NativeArray extends ScriptObject {
|
||||
final boolean upperExists = sobj.has(upper);
|
||||
|
||||
if (lowerExists && upperExists) {
|
||||
sobj.set(lower, upperValue, true);
|
||||
sobj.set(upper, lowerValue, true);
|
||||
sobj.set(lower, upperValue, CALLSITE_STRICT);
|
||||
sobj.set(upper, lowerValue, CALLSITE_STRICT);
|
||||
} else if (!lowerExists && upperExists) {
|
||||
sobj.set(lower, upperValue, true);
|
||||
sobj.set(lower, upperValue, CALLSITE_STRICT);
|
||||
sobj.delete(upper, true);
|
||||
} else if (lowerExists && !upperExists) {
|
||||
sobj.delete(lower, true);
|
||||
sobj.set(upper, lowerValue, true);
|
||||
sobj.set(upper, lowerValue, CALLSITE_STRICT);
|
||||
}
|
||||
}
|
||||
return sobj;
|
||||
@ -1003,7 +1005,7 @@ public final class NativeArray extends ScriptObject {
|
||||
for (long k = 1; k < len; k++) {
|
||||
final boolean hasCurrent = sobj.has(k);
|
||||
if (hasCurrent) {
|
||||
sobj.set(k - 1, sobj.get(k), true);
|
||||
sobj.set(k - 1, sobj.get(k), CALLSITE_STRICT);
|
||||
} else if (hasPrevious) {
|
||||
sobj.delete(k - 1, true);
|
||||
}
|
||||
@ -1015,7 +1017,7 @@ public final class NativeArray extends ScriptObject {
|
||||
len = 0;
|
||||
}
|
||||
|
||||
sobj.set("length", len, true);
|
||||
sobj.set("length", len, CALLSITE_STRICT);
|
||||
|
||||
return first;
|
||||
}
|
||||
@ -1226,7 +1228,7 @@ public final class NativeArray extends ScriptObject {
|
||||
final long to = k + items.length;
|
||||
|
||||
if (sobj.has(from)) {
|
||||
sobj.set(to, sobj.get(from), true);
|
||||
sobj.set(to, sobj.get(from), CALLSITE_STRICT);
|
||||
} else {
|
||||
sobj.delete(to, true);
|
||||
}
|
||||
@ -1242,7 +1244,7 @@ public final class NativeArray extends ScriptObject {
|
||||
|
||||
if (sobj.has(from)) {
|
||||
final Object fromValue = sobj.get(from);
|
||||
sobj.set(to, fromValue, true);
|
||||
sobj.set(to, fromValue, CALLSITE_STRICT);
|
||||
} else {
|
||||
sobj.delete(to, true);
|
||||
}
|
||||
@ -1251,11 +1253,11 @@ public final class NativeArray extends ScriptObject {
|
||||
|
||||
long k = start;
|
||||
for (int i = 0; i < items.length; i++, k++) {
|
||||
sobj.set(k, items[i], true);
|
||||
sobj.set(k, items[i], CALLSITE_STRICT);
|
||||
}
|
||||
|
||||
final long newLength = len - deleteCount + items.length;
|
||||
sobj.set("length", newLength, true);
|
||||
sobj.set("length", newLength, CALLSITE_STRICT);
|
||||
|
||||
return array;
|
||||
}
|
||||
@ -1295,19 +1297,19 @@ public final class NativeArray extends ScriptObject {
|
||||
|
||||
if (sobj.has(from)) {
|
||||
final Object fromValue = sobj.get(from);
|
||||
sobj.set(to, fromValue, true);
|
||||
sobj.set(to, fromValue, CALLSITE_STRICT);
|
||||
} else {
|
||||
sobj.delete(to, true);
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < items.length; j++) {
|
||||
sobj.set(j, items[j], true);
|
||||
sobj.set(j, items[j], CALLSITE_STRICT);
|
||||
}
|
||||
}
|
||||
|
||||
final long newLength = len + items.length;
|
||||
sobj.set("length", newLength, true);
|
||||
sobj.set("length", newLength, CALLSITE_STRICT);
|
||||
|
||||
return newLength;
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ import jdk.nashorn.internal.runtime.ScriptFunction;
|
||||
import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
import jdk.nashorn.internal.runtime.events.RuntimeEvent;
|
||||
import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
|
||||
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
|
||||
|
||||
/**
|
||||
* Nashorn specific debug utils. This is meant for Nashorn developers.
|
||||
@ -266,7 +267,7 @@ public final class NativeDebug extends ScriptObject {
|
||||
*/
|
||||
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
|
||||
public static void setEventQueueCapacity(final Object self, final Object newCapacity) {
|
||||
((ScriptObject)self).set(EVENT_QUEUE_CAPACITY, newCapacity, true);
|
||||
((ScriptObject)self).set(EVENT_QUEUE_CAPACITY, newCapacity, NashornCallSiteDescriptor.CALLSITE_STRICT);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -355,7 +356,7 @@ public final class NativeDebug extends ScriptObject {
|
||||
if (sobj.has(EVENT_QUEUE)) {
|
||||
q = (LinkedList<RuntimeEvent<?>>)((ScriptObject)self).get(EVENT_QUEUE);
|
||||
} else {
|
||||
((ScriptObject)self).set(EVENT_QUEUE, q = new LinkedList<>(), true);
|
||||
((ScriptObject)self).set(EVENT_QUEUE, q = new LinkedList<>(), NashornCallSiteDescriptor.CALLSITE_STRICT);
|
||||
}
|
||||
return q;
|
||||
}
|
||||
|
@ -250,146 +250,146 @@ public final class NativeJSAdapter extends ScriptObject {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final Object key, final int value, final boolean strict) {
|
||||
public void set(final Object key, final int value, final int flags) {
|
||||
if (overrides && super.hasOwnProperty(key)) {
|
||||
super.set(key, value, strict);
|
||||
super.set(key, value, flags);
|
||||
} else {
|
||||
callAdaptee(__put__, key, value, strict);
|
||||
callAdaptee(__put__, key, value, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final Object key, final long value, final boolean strict) {
|
||||
public void set(final Object key, final long value, final int flags) {
|
||||
if (overrides && super.hasOwnProperty(key)) {
|
||||
super.set(key, value, strict);
|
||||
super.set(key, value, flags);
|
||||
} else {
|
||||
callAdaptee(__put__, key, value, strict);
|
||||
callAdaptee(__put__, key, value, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final Object key, final double value, final boolean strict) {
|
||||
public void set(final Object key, final double value, final int flags) {
|
||||
if (overrides && super.hasOwnProperty(key)) {
|
||||
super.set(key, value, strict);
|
||||
super.set(key, value, flags);
|
||||
} else {
|
||||
callAdaptee(__put__, key, value, strict);
|
||||
callAdaptee(__put__, key, value, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final Object key, final Object value, final boolean strict) {
|
||||
public void set(final Object key, final Object value, final int flags) {
|
||||
if (overrides && super.hasOwnProperty(key)) {
|
||||
super.set(key, value, strict);
|
||||
super.set(key, value, flags);
|
||||
} else {
|
||||
callAdaptee(__put__, key, value, strict);
|
||||
callAdaptee(__put__, key, value, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final double key, final int value, final boolean strict) {
|
||||
public void set(final double key, final int value, final int flags) {
|
||||
if (overrides && super.hasOwnProperty(key)) {
|
||||
super.set(key, value, strict);
|
||||
super.set(key, value, flags);
|
||||
} else {
|
||||
callAdaptee(__put__, key, value, strict);
|
||||
callAdaptee(__put__, key, value, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final double key, final long value, final boolean strict) {
|
||||
public void set(final double key, final long value, final int flags) {
|
||||
if (overrides && super.hasOwnProperty(key)) {
|
||||
super.set(key, value, strict);
|
||||
super.set(key, value, flags);
|
||||
} else {
|
||||
callAdaptee(__put__, key, value, strict);
|
||||
callAdaptee(__put__, key, value, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final double key, final double value, final boolean strict) {
|
||||
public void set(final double key, final double value, final int flags) {
|
||||
if (overrides && super.hasOwnProperty(key)) {
|
||||
super.set(key, value, strict);
|
||||
super.set(key, value, flags);
|
||||
} else {
|
||||
callAdaptee(__put__, key, value, strict);
|
||||
callAdaptee(__put__, key, value, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final double key, final Object value, final boolean strict) {
|
||||
public void set(final double key, final Object value, final int flags) {
|
||||
if (overrides && super.hasOwnProperty(key)) {
|
||||
super.set(key, value, strict);
|
||||
super.set(key, value, flags);
|
||||
} else {
|
||||
callAdaptee(__put__, key, value, strict);
|
||||
callAdaptee(__put__, key, value, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final long key, final int value, final boolean strict) {
|
||||
public void set(final long key, final int value, final int flags) {
|
||||
if (overrides && super.hasOwnProperty(key)) {
|
||||
super.set(key, value, strict);
|
||||
super.set(key, value, flags);
|
||||
} else {
|
||||
callAdaptee(__put__, key, value, strict);
|
||||
callAdaptee(__put__, key, value, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final long key, final long value, final boolean strict) {
|
||||
public void set(final long key, final long value, final int flags) {
|
||||
if (overrides && super.hasOwnProperty(key)) {
|
||||
super.set(key, value, strict);
|
||||
super.set(key, value, flags);
|
||||
} else {
|
||||
callAdaptee(__put__, key, value, strict);
|
||||
callAdaptee(__put__, key, value, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final long key, final double value, final boolean strict) {
|
||||
public void set(final long key, final double value, final int flags) {
|
||||
if (overrides && super.hasOwnProperty(key)) {
|
||||
super.set(key, value, strict);
|
||||
super.set(key, value, flags);
|
||||
} else {
|
||||
callAdaptee(__put__, key, value, strict);
|
||||
callAdaptee(__put__, key, value, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final long key, final Object value, final boolean strict) {
|
||||
public void set(final long key, final Object value, final int flags) {
|
||||
if (overrides && super.hasOwnProperty(key)) {
|
||||
super.set(key, value, strict);
|
||||
super.set(key, value, flags);
|
||||
} else {
|
||||
callAdaptee(__put__, key, value, strict);
|
||||
callAdaptee(__put__, key, value, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final int key, final int value, final boolean strict) {
|
||||
public void set(final int key, final int value, final int flags) {
|
||||
if (overrides && super.hasOwnProperty(key)) {
|
||||
super.set(key, value, strict);
|
||||
super.set(key, value, flags);
|
||||
} else {
|
||||
callAdaptee(__put__, key, value, strict);
|
||||
callAdaptee(__put__, key, value, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final int key, final long value, final boolean strict) {
|
||||
public void set(final int key, final long value, final int flags) {
|
||||
if (overrides && super.hasOwnProperty(key)) {
|
||||
super.set(key, value, strict);
|
||||
super.set(key, value, flags);
|
||||
} else {
|
||||
callAdaptee(__put__, key, value, strict);
|
||||
callAdaptee(__put__, key, value, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final int key, final double value, final boolean strict) {
|
||||
public void set(final int key, final double value, final int flags) {
|
||||
if (overrides && super.hasOwnProperty(key)) {
|
||||
super.set(key, value, strict);
|
||||
super.set(key, value, flags);
|
||||
} else {
|
||||
callAdaptee(__put__, key, value, strict);
|
||||
callAdaptee(__put__, key, value, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final int key, final Object value, final boolean strict) {
|
||||
public void set(final int key, final Object value, final int flags) {
|
||||
if (overrides && super.hasOwnProperty(key)) {
|
||||
super.set(key, value, strict);
|
||||
super.set(key, value, flags);
|
||||
} else {
|
||||
callAdaptee(__put__, key, value, strict);
|
||||
callAdaptee(__put__, key, value, flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,7 +191,7 @@ public final class NativeJSON extends ScriptObject {
|
||||
state.gap = gap;
|
||||
|
||||
final ScriptObject wrapper = Global.newEmptyInstance();
|
||||
wrapper.set("", value, false);
|
||||
wrapper.set("", value, 0);
|
||||
|
||||
return str("", wrapper, state);
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ public final class NativeJavaImporter extends ScriptObject {
|
||||
final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
|
||||
final Object value = createProperty(name);
|
||||
if(value != null) {
|
||||
set(name, value, false);
|
||||
set(name, value, 0);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -112,82 +112,82 @@ public abstract class DefaultPropertyAccess implements PropertyAccess {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final double key, final int value, final boolean strict) {
|
||||
set(JSType.toObject(key), JSType.toObject(value), strict);
|
||||
public void set(final double key, final int value, final int flags) {
|
||||
set(JSType.toObject(key), JSType.toObject(value), flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final double key, final long value, final boolean strict) {
|
||||
set(JSType.toObject(key), JSType.toObject(value), strict);
|
||||
public void set(final double key, final long value, final int flags) {
|
||||
set(JSType.toObject(key), JSType.toObject(value), flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final double key, final double value, final boolean strict) {
|
||||
set(JSType.toObject(key), JSType.toObject(value), strict);
|
||||
public void set(final double key, final double value, final int flags) {
|
||||
set(JSType.toObject(key), JSType.toObject(value), flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final double key, final Object value, final boolean strict) {
|
||||
set(JSType.toObject(key), JSType.toObject(value), strict);
|
||||
public void set(final double key, final Object value, final int flags) {
|
||||
set(JSType.toObject(key), JSType.toObject(value), flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final long key, final int value, final boolean strict) {
|
||||
set(JSType.toObject(key), JSType.toObject(value), strict);
|
||||
public void set(final long key, final int value, final int flags) {
|
||||
set(JSType.toObject(key), JSType.toObject(value), flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final long key, final long value, final boolean strict) {
|
||||
set(JSType.toObject(key), JSType.toObject(value), strict);
|
||||
public void set(final long key, final long value, final int flags) {
|
||||
set(JSType.toObject(key), JSType.toObject(value), flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final long key, final double value, final boolean strict) {
|
||||
set(JSType.toObject(key), JSType.toObject(value), strict);
|
||||
public void set(final long key, final double value, final int flags) {
|
||||
set(JSType.toObject(key), JSType.toObject(value), flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final long key, final Object value, final boolean strict) {
|
||||
set(JSType.toObject(key), value, strict);
|
||||
public void set(final long key, final Object value, final int flags) {
|
||||
set(JSType.toObject(key), value, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final int key, final int value, final boolean strict) {
|
||||
set(JSType.toObject(key), JSType.toObject(value), strict);
|
||||
public void set(final int key, final int value, final int flags) {
|
||||
set(JSType.toObject(key), JSType.toObject(value), flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final int key, final long value, final boolean strict) {
|
||||
set(JSType.toObject(key), JSType.toObject(value), strict);
|
||||
public void set(final int key, final long value, final int flags) {
|
||||
set(JSType.toObject(key), JSType.toObject(value), flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final int key, final double value, final boolean strict) {
|
||||
set(JSType.toObject(key), JSType.toObject(value), strict);
|
||||
public void set(final int key, final double value, final int flags) {
|
||||
set(JSType.toObject(key), JSType.toObject(value), flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final int key, final Object value, final boolean strict) {
|
||||
set(JSType.toObject(key), value, strict);
|
||||
public void set(final int key, final Object value, final int flags) {
|
||||
set(JSType.toObject(key), value, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final Object key, final int value, final boolean strict) {
|
||||
set(key, JSType.toObject(value), strict);
|
||||
public void set(final Object key, final int value, final int flags) {
|
||||
set(key, JSType.toObject(value), flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final Object key, final long value, final boolean strict) {
|
||||
set(key, JSType.toObject(value), strict);
|
||||
public void set(final Object key, final long value, final int flags) {
|
||||
set(key, JSType.toObject(value), flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final Object key, final double value, final boolean strict) {
|
||||
set(key, JSType.toObject(value), strict);
|
||||
public void set(final Object key, final double value, final int flags) {
|
||||
set(key, JSType.toObject(value), flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract void set(Object key, Object value, boolean strict);
|
||||
public abstract void set(Object key, Object value, int flags);
|
||||
|
||||
@Override
|
||||
public abstract boolean has(Object key);
|
||||
|
@ -285,7 +285,7 @@ public final class ECMAException extends NashornException {
|
||||
if (!sobj.has(EXCEPTION_PROPERTY)) {
|
||||
sobj.addOwnProperty(EXCEPTION_PROPERTY, Property.NOT_ENUMERABLE, this);
|
||||
} else {
|
||||
sobj.set(EXCEPTION_PROPERTY, this, false);
|
||||
sobj.set(EXCEPTION_PROPERTY, this, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -138,6 +138,17 @@ public final class FindProperty {
|
||||
return prototype;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@code ScriptObject} where the search started. This is usually the ScriptObject the
|
||||
* operation was started on, except for properties found inside a 'with' statement, where it is the
|
||||
* top-level 'with' expression object.
|
||||
*
|
||||
* @return the start object.
|
||||
*/
|
||||
public ScriptObject getSelf() {
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the appropriate receiver for a getter.
|
||||
* @return appropriate receiver
|
||||
|
@ -309,7 +309,7 @@ public final class GlobalConstants implements Loggable {
|
||||
*
|
||||
* @param find property lookup
|
||||
* @param inv normal guarded invocation for this setter, as computed by the ScriptObject linker
|
||||
* @param desc callsite descriptr
|
||||
* @param desc callsite descriptor
|
||||
* @param request link request
|
||||
*
|
||||
* @return null if failed to set up constant linkage
|
||||
@ -376,8 +376,12 @@ public final class GlobalConstants implements Loggable {
|
||||
* @return resulting getter, or null if failed to create constant
|
||||
*/
|
||||
synchronized GuardedInvocation findGetMethod(final FindProperty find, final ScriptObject receiver, final CallSiteDescriptor desc) {
|
||||
// Also return null if property may have side effects
|
||||
if ((GLOBAL_ONLY && !find.getOwner().isGlobal()) || find.getProperty() instanceof UserAccessorProperty) {
|
||||
// Only use constant getter for fast scope access, because the receiver may change between invocations
|
||||
// for slow-scope and non-scope callsites.
|
||||
// Also return null for user accessor properties as they may have side effects.
|
||||
if (!NashornCallSiteDescriptor.isFastScope(desc)
|
||||
|| (GLOBAL_ONLY && !find.getOwner().isGlobal())
|
||||
|| find.getProperty() instanceof UserAccessorProperty) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -122,7 +122,7 @@ public final class JSONFunctions {
|
||||
if (newElement == ScriptRuntime.UNDEFINED) {
|
||||
valueObj.delete(key, false);
|
||||
} else {
|
||||
setPropertyValue(valueObj, key, newElement, false);
|
||||
setPropertyValue(valueObj, key, newElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -179,7 +179,7 @@ public final class JSONFunctions {
|
||||
|
||||
final String name = pNode.getKeyName();
|
||||
final Object value = convertNode(global, valueNode);
|
||||
setPropertyValue(object, name, value, false);
|
||||
setPropertyValue(object, name, value);
|
||||
}
|
||||
|
||||
return object;
|
||||
@ -193,14 +193,14 @@ public final class JSONFunctions {
|
||||
}
|
||||
|
||||
// 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) {
|
||||
private static void setPropertyValue(final ScriptObject sobj, final String name, final Object value) {
|
||||
final int index = ArrayIndex.getArrayIndex(name);
|
||||
if (ArrayIndex.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);
|
||||
sobj.set(name, value, 0);
|
||||
} else {
|
||||
// add new property
|
||||
sobj.addOwnProperty(name, Property.WRITABLE_ENUMERABLE_CONFIGURABLE, value);
|
||||
|
@ -256,7 +256,7 @@ public final class NativeJavaPackage extends ScriptObject {
|
||||
final Object constructor = BeansLinker.getConstructorMethod(
|
||||
javaClass, propertyName.substring(openBrace + 1, lastChar));
|
||||
if (constructor != null) {
|
||||
set(propertyName, constructor, false);
|
||||
set(propertyName, constructor, 0);
|
||||
return constructor;
|
||||
}
|
||||
// we didn't find a matching constructor!
|
||||
@ -270,7 +270,7 @@ public final class NativeJavaPackage extends ScriptObject {
|
||||
propertyValue = StaticClass.forClass(javaClass);
|
||||
}
|
||||
|
||||
set(propertyName, propertyValue, false);
|
||||
set(propertyName, propertyValue, 0);
|
||||
return propertyValue;
|
||||
}
|
||||
}
|
||||
|
@ -163,129 +163,129 @@ public interface PropertyAccess {
|
||||
* Set the value of a given key
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @param strict are we in strict mode
|
||||
* @param flags call site flags
|
||||
*/
|
||||
public void set(Object key, int value, boolean strict);
|
||||
public void set(Object key, int value, int flags);
|
||||
|
||||
/**
|
||||
* Set the value of a given key
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @param strict are we in strict mode
|
||||
* @param flags call site flags
|
||||
*/
|
||||
public void set(Object key, long value, boolean strict);
|
||||
public void set(Object key, long value, int flags);
|
||||
|
||||
/**
|
||||
* Set the value of a given key
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @param strict are we in strict mode
|
||||
* @param flags call site flags
|
||||
*/
|
||||
public void set(Object key, double value, boolean strict);
|
||||
public void set(Object key, double value, int flags);
|
||||
|
||||
/**
|
||||
* Set the value of a given key
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @param strict are we in strict mode
|
||||
* @param flags call site flags
|
||||
*/
|
||||
public void set(Object key, Object value, boolean strict);
|
||||
public void set(Object key, Object value, int flags);
|
||||
|
||||
/**
|
||||
* Set the value of a given key
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @param strict are we in strict mode
|
||||
* @param flags call site flags
|
||||
*/
|
||||
public void set(double key, int value, boolean strict);
|
||||
public void set(double key, int value, int flags);
|
||||
|
||||
/**
|
||||
* Set the value of a given key
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @param strict are we in strict mode
|
||||
* @param flags call site flags
|
||||
*/
|
||||
public void set(double key, long value, boolean strict);
|
||||
public void set(double key, long value, int flags);
|
||||
|
||||
/**
|
||||
* Set the value of a given key
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @param strict are we in strict mode
|
||||
* @param flags call site flags
|
||||
*/
|
||||
public void set(double key, double value, boolean strict);
|
||||
public void set(double key, double value, int flags);
|
||||
|
||||
/**
|
||||
* Set the value of a given key
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @param strict are we in strict mode
|
||||
* @param flags call site flags
|
||||
*/
|
||||
public void set(double key, Object value, boolean strict);
|
||||
public void set(double key, Object value, int flags);
|
||||
|
||||
/**
|
||||
* Set the value of a given key
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @param strict are we in strict mode
|
||||
* @param flags call site flags
|
||||
*/
|
||||
public void set(long key, int value, boolean strict);
|
||||
public void set(long key, int value, int flags);
|
||||
|
||||
/**
|
||||
* Set the value of a given key
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @param strict are we in strict mode
|
||||
* @param flags call site flags
|
||||
*/
|
||||
public void set(long key, long value, boolean strict);
|
||||
public void set(long key, long value, int flags);
|
||||
|
||||
/**
|
||||
* Set the value of a given key
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @param strict are we in strict mode
|
||||
* @param flags call site flags
|
||||
*/
|
||||
public void set(long key, double value, boolean strict);
|
||||
public void set(long key, double value, int flags);
|
||||
|
||||
/**
|
||||
* Set the value of a given key
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @param strict are we in strict mode
|
||||
* @param flags call site flags
|
||||
*/
|
||||
public void set(long key, Object value, boolean strict);
|
||||
public void set(long key, Object value, int flags);
|
||||
|
||||
/**
|
||||
* Set the value of a given key
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @param strict are we in strict mode
|
||||
* @param flags call site flags
|
||||
*/
|
||||
public void set(int key, int value, boolean strict);
|
||||
public void set(int key, int value, int flags);
|
||||
|
||||
/**
|
||||
* Set the value of a given key
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @param strict are we in strict mode
|
||||
* @param flags call site flags
|
||||
*/
|
||||
public void set(int key, long value, boolean strict);
|
||||
public void set(int key, long value, int flags);
|
||||
|
||||
/**
|
||||
* Set the value of a given key
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @param strict are we in strict mode
|
||||
* @param flags call site flags
|
||||
*/
|
||||
public void set(int key, double value, boolean strict);
|
||||
public void set(int key, double value, int flags);
|
||||
|
||||
/**
|
||||
* Set the value of a given key
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @param strict are we in strict mode
|
||||
* @param flags call site flags
|
||||
*/
|
||||
public void set(int key, Object value, boolean strict);
|
||||
public void set(int key, Object value, int flags);
|
||||
|
||||
/**
|
||||
* Check if the given key exists anywhere in the proto chain
|
||||
|
@ -45,6 +45,7 @@ import jdk.nashorn.internal.codegen.types.Type;
|
||||
import jdk.nashorn.internal.lookup.MethodHandleFactory;
|
||||
import jdk.nashorn.internal.lookup.MethodHandleFunctionality;
|
||||
import jdk.nashorn.internal.objects.Global;
|
||||
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
|
||||
|
||||
/**
|
||||
* Used to signal to the linker to relink the callee
|
||||
@ -161,7 +162,7 @@ public final class RewriteException extends Exception {
|
||||
assert runtimeScope == null;
|
||||
runtimeScope = (ScriptObject)value;
|
||||
} else if(name != null) {
|
||||
locals.set(name, value, true);
|
||||
locals.set(name, value, NashornCallSiteDescriptor.CALLSITE_STRICT);
|
||||
}
|
||||
}
|
||||
locals.setProto(runtimeScope);
|
||||
|
@ -198,10 +198,10 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
public static final Call SET_USER_ACCESSORS = virtualCall(MethodHandles.lookup(), ScriptObject.class, "setUserAccessors", void.class, String.class, ScriptFunction.class, ScriptFunction.class);
|
||||
|
||||
static final MethodHandle[] SET_SLOW = new MethodHandle[] {
|
||||
findOwnMH_V("set", void.class, Object.class, int.class, boolean.class),
|
||||
findOwnMH_V("set", void.class, Object.class, long.class, boolean.class),
|
||||
findOwnMH_V("set", void.class, Object.class, double.class, boolean.class),
|
||||
findOwnMH_V("set", void.class, Object.class, Object.class, boolean.class)
|
||||
findOwnMH_V("set", void.class, Object.class, int.class, int.class),
|
||||
findOwnMH_V("set", void.class, Object.class, long.class, int.class),
|
||||
findOwnMH_V("set", void.class, Object.class, double.class, int.class),
|
||||
findOwnMH_V("set", void.class, Object.class, Object.class, int.class)
|
||||
};
|
||||
|
||||
/** Method handle to reset the map of this ScriptObject */
|
||||
@ -593,7 +593,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
if (newValue && property != null) {
|
||||
// Temporarily clear flags.
|
||||
property = modifyOwnProperty(property, 0);
|
||||
set(key, value, false);
|
||||
set(key, value, 0);
|
||||
//this might change the map if we change types of the property
|
||||
//hence we need to read it again. note that we should probably
|
||||
//have the setter return the new property throughout and in
|
||||
@ -758,7 +758,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
* @return FindPropertyData or null if not found.
|
||||
*/
|
||||
public final FindProperty findProperty(final String key, final boolean deep) {
|
||||
return findProperty(key, deep, false, this);
|
||||
return findProperty(key, deep, this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -775,16 +775,11 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
*
|
||||
* @param key Property key.
|
||||
* @param deep Whether the search should look up proto chain.
|
||||
* @param stopOnNonScope should a deep search stop on the first non-scope object?
|
||||
* @param start the object on which the lookup was originally initiated
|
||||
*
|
||||
* @return FindPropertyData or null if not found.
|
||||
*/
|
||||
FindProperty findProperty(final String key, final boolean deep, final boolean stopOnNonScope, final ScriptObject start) {
|
||||
// if doing deep search, stop search on the first non-scope object if asked to do so
|
||||
if (stopOnNonScope && start != this && !isScope()) {
|
||||
return null;
|
||||
}
|
||||
FindProperty findProperty(final String key, final boolean deep, final ScriptObject start) {
|
||||
|
||||
final PropertyMap selfMap = getMap();
|
||||
final Property property = selfMap.findProperty(key);
|
||||
@ -796,7 +791,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
if (deep) {
|
||||
final ScriptObject myProto = getProto();
|
||||
if (myProto != null) {
|
||||
return myProto.findProperty(key, deep, stopOnNonScope, start);
|
||||
return myProto.findProperty(key, deep, start);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1164,7 +1159,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
* @param value the value to write at the given index
|
||||
*/
|
||||
public void setArgument(final int key, final Object value) {
|
||||
set(key, value, false);
|
||||
set(key, value, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1725,7 +1720,8 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
*/
|
||||
public Object put(final Object key, final Object value, final boolean strict) {
|
||||
final Object oldValue = get(key);
|
||||
set(key, value, strict);
|
||||
final int flags = strict ? NashornCallSiteDescriptor.CALLSITE_STRICT : 0;
|
||||
set(key, value, flags);
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
@ -1738,8 +1734,9 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
* @param strict strict mode or not
|
||||
*/
|
||||
public void putAll(final Map<?, ?> otherMap, final boolean strict) {
|
||||
final int flags = strict ? NashornCallSiteDescriptor.CALLSITE_STRICT : 0;
|
||||
for (final Map.Entry<?, ?> entry : otherMap.entrySet()) {
|
||||
set(entry.getKey(), entry.getValue(), strict);
|
||||
set(entry.getKey(), entry.getValue(), flags);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2042,7 +2039,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
|
||||
final PropertyMap newMap = map.replaceProperty(property, property.removeFlags(Property.NEEDS_DECLARATION));
|
||||
setMap(newMap);
|
||||
set(key, value, true);
|
||||
set(key, value, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2135,7 +2132,6 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
return findMegaMorphicSetMethod(desc, name);
|
||||
}
|
||||
|
||||
final boolean scope = isScope();
|
||||
final boolean explicitInstanceOfCheck = explicitInstanceOfCheck(desc, request);
|
||||
|
||||
/*
|
||||
@ -2145,17 +2141,19 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
*
|
||||
* toString = function() { print("global toString"); } // don't affect Object.prototype.toString
|
||||
*/
|
||||
FindProperty find = findProperty(name, true, scope, this);
|
||||
FindProperty find = findProperty(name, true, this);
|
||||
|
||||
// If it's not a scope search, then we don't want any inherited properties except those with user defined accessors.
|
||||
if (!scope && find != null && find.isInherited() && !(find.getProperty() instanceof UserAccessorProperty)) {
|
||||
if (find != null && find.isInherited() && !(find.getProperty() instanceof UserAccessorProperty)) {
|
||||
// We should still check if inherited data property is not writable
|
||||
if (isExtensible() && !find.getProperty().isWritable()) {
|
||||
return createEmptySetMethod(desc, explicitInstanceOfCheck, "property.not.writable", false);
|
||||
return createEmptySetMethod(desc, explicitInstanceOfCheck, "property.not.writable", true);
|
||||
}
|
||||
// Otherwise, forget the found property
|
||||
// Otherwise, forget the found property unless this is a scope callsite and the owner is a scope object as well.
|
||||
if (!NashornCallSiteDescriptor.isScope(desc) || !find.getOwner().isScope()) {
|
||||
find = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (find != null) {
|
||||
if (!find.getProperty().isWritable() && !NashornCallSiteDescriptor.isDeclaration(desc)) {
|
||||
@ -2207,7 +2205,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
private GuardedInvocation findMegaMorphicSetMethod(final CallSiteDescriptor desc, final String name) {
|
||||
final MethodType type = desc.getMethodType().insertParameterTypes(1, Object.class);
|
||||
//never bother with ClassCastExceptionGuard for megamorphic callsites
|
||||
final GuardedInvocation inv = findSetIndexMethod(getClass(), false, type, NashornCallSiteDescriptor.isStrict(desc));
|
||||
final GuardedInvocation inv = findSetIndexMethod(getClass(), desc, false, type);
|
||||
return inv.replaceMethods(MH.insertArguments(inv.getInvocation(), 1, name), inv.getGuard());
|
||||
}
|
||||
|
||||
@ -2230,24 +2228,26 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
* @return GuardedInvocation to be invoked at call site.
|
||||
*/
|
||||
protected GuardedInvocation findSetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) { // array, index, value
|
||||
return findSetIndexMethod(getClass(), explicitInstanceOfCheck(desc, request), desc.getMethodType(), NashornCallSiteDescriptor.isStrict(desc));
|
||||
return findSetIndexMethod(getClass(), desc, explicitInstanceOfCheck(desc, request), desc.getMethodType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the appropriate SETINDEX method for an invoke dynamic call.
|
||||
*
|
||||
* @param clazz the receiver class
|
||||
* @param desc the call site descriptor
|
||||
* @param explicitInstanceOfCheck add an explicit instanceof check?
|
||||
* @param callType the method type at the call site
|
||||
* @param isStrict are we in strict mode?
|
||||
*
|
||||
* @return GuardedInvocation to be invoked at call site.
|
||||
*/
|
||||
private static GuardedInvocation findSetIndexMethod(final Class<? extends ScriptObject> clazz, final boolean explicitInstanceOfCheck, final MethodType callType, final boolean isStrict) {
|
||||
private static GuardedInvocation findSetIndexMethod(final Class<? extends ScriptObject> clazz, final CallSiteDescriptor desc, final boolean explicitInstanceOfCheck, final MethodType callType) {
|
||||
assert callType.parameterCount() == 3;
|
||||
final Class<?> keyClass = callType.parameterType(1);
|
||||
final Class<?> valueClass = callType.parameterType(2);
|
||||
|
||||
MethodHandle methodHandle = findOwnMH_V(clazz, "set", void.class, keyClass, valueClass, boolean.class);
|
||||
methodHandle = MH.insertArguments(methodHandle, 3, isStrict);
|
||||
MethodHandle methodHandle = findOwnMH_V(clazz, "set", void.class, keyClass, valueClass, int.class);
|
||||
methodHandle = MH.insertArguments(methodHandle, 3, NashornCallSiteDescriptor.getFlags(desc));
|
||||
|
||||
return new GuardedInvocation(methodHandle, getScriptObjectGuard(callType, explicitInstanceOfCheck), (SwitchPoint)null, explicitInstanceOfCheck ? null : ClassCastException.class);
|
||||
}
|
||||
@ -2672,7 +2672,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
if (isValidArrayIndex(index)) {
|
||||
for (ScriptObject object = this; ; ) {
|
||||
if (object.getMap().containsArrayKeys()) {
|
||||
final FindProperty find = object.findProperty(key, false, false, this);
|
||||
final FindProperty find = object.findProperty(key, false, this);
|
||||
|
||||
if (find != null) {
|
||||
return getIntValue(find, programPoint);
|
||||
@ -2755,7 +2755,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
if (isValidArrayIndex(index)) {
|
||||
for (ScriptObject object = this; ; ) {
|
||||
if (object.getMap().containsArrayKeys()) {
|
||||
final FindProperty find = object.findProperty(key, false, false, this);
|
||||
final FindProperty find = object.findProperty(key, false, this);
|
||||
if (find != null) {
|
||||
return getLongValue(find, programPoint);
|
||||
}
|
||||
@ -2837,7 +2837,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
if (isValidArrayIndex(index)) {
|
||||
for (ScriptObject object = this; ; ) {
|
||||
if (object.getMap().containsArrayKeys()) {
|
||||
final FindProperty find = object.findProperty(key, false, false, this);
|
||||
final FindProperty find = object.findProperty(key, false, this);
|
||||
if (find != null) {
|
||||
return getDoubleValue(find, programPoint);
|
||||
}
|
||||
@ -2919,7 +2919,7 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
if (isValidArrayIndex(index)) {
|
||||
for (ScriptObject object = this; ; ) {
|
||||
if (object.getMap().containsArrayKeys()) {
|
||||
final FindProperty find = object.findProperty(key, false, false, this);
|
||||
final FindProperty find = object.findProperty(key, false, this);
|
||||
|
||||
if (find != null) {
|
||||
return find.getObjectValue();
|
||||
@ -2996,48 +2996,48 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
return get(index, JSType.toString(key));
|
||||
}
|
||||
|
||||
private boolean doesNotHaveCheckArrayKeys(final long longIndex, final int value, final boolean strict) {
|
||||
private boolean doesNotHaveCheckArrayKeys(final long longIndex, final int value, final int callSiteFlags) {
|
||||
if (getMap().containsArrayKeys()) {
|
||||
final String key = JSType.toString(longIndex);
|
||||
final FindProperty find = findProperty(key, true);
|
||||
if (find != null) {
|
||||
setObject(find, strict, key, value);
|
||||
setObject(find, callSiteFlags, key, value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean doesNotHaveCheckArrayKeys(final long longIndex, final long value, final boolean strict) {
|
||||
private boolean doesNotHaveCheckArrayKeys(final long longIndex, final long value, final int callSiteFlags) {
|
||||
if (getMap().containsArrayKeys()) {
|
||||
final String key = JSType.toString(longIndex);
|
||||
final FindProperty find = findProperty(key, true);
|
||||
if (find != null) {
|
||||
setObject(find, strict, key, value);
|
||||
setObject(find, callSiteFlags, key, value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean doesNotHaveCheckArrayKeys(final long longIndex, final double value, final boolean strict) {
|
||||
private boolean doesNotHaveCheckArrayKeys(final long longIndex, final double value, final int callSiteFlags) {
|
||||
if (getMap().containsArrayKeys()) {
|
||||
final String key = JSType.toString(longIndex);
|
||||
final FindProperty find = findProperty(key, true);
|
||||
if (find != null) {
|
||||
setObject(find, strict, key, value);
|
||||
setObject(find, callSiteFlags, key, value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean doesNotHaveCheckArrayKeys(final long longIndex, final Object value, final boolean strict) {
|
||||
private boolean doesNotHaveCheckArrayKeys(final long longIndex, final Object value, final int callSiteFlags) {
|
||||
if (getMap().containsArrayKeys()) {
|
||||
final String key = JSType.toString(longIndex);
|
||||
final FindProperty find = findProperty(key, true);
|
||||
if (find != null) {
|
||||
setObject(find, strict, key, value);
|
||||
setObject(find, callSiteFlags, key, value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -3045,10 +3045,10 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
}
|
||||
|
||||
//value agnostic
|
||||
private boolean doesNotHaveEnsureLength(final long longIndex, final long oldLength, final boolean strict) {
|
||||
private boolean doesNotHaveEnsureLength(final long longIndex, final long oldLength, final int callSiteFlags) {
|
||||
if (longIndex >= oldLength) {
|
||||
if (!isExtensible()) {
|
||||
if (strict) {
|
||||
if (NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)) {
|
||||
throw typeError("object.non.extensible", JSType.toString(longIndex), ScriptRuntime.safeToString(this));
|
||||
}
|
||||
return true;
|
||||
@ -3068,37 +3068,41 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
}
|
||||
}
|
||||
|
||||
private void doesNotHave(final int index, final int value, final boolean strict) {
|
||||
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, strict) && !doesNotHaveEnsureLength(longIndex, oldLength, strict)) {
|
||||
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 boolean 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, strict) && !doesNotHaveEnsureLength(longIndex, oldLength, strict)) {
|
||||
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 boolean 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, strict) && !doesNotHaveEnsureLength(longIndex, oldLength, strict)) {
|
||||
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 boolean 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, strict) && !doesNotHaveEnsureLength(longIndex, oldLength, strict)) {
|
||||
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);
|
||||
}
|
||||
@ -3109,31 +3113,46 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
* TODO: should be further specialized
|
||||
*
|
||||
* @param find found property
|
||||
* @param strict are we in strict mode
|
||||
* @param callSiteFlags callsite flags
|
||||
* @param key property key
|
||||
* @param value property value
|
||||
*/
|
||||
public final void setObject(final FindProperty find, final boolean strict, final String key, final Object value) {
|
||||
public final void setObject(final FindProperty find, final int callSiteFlags, final String key, final Object value) {
|
||||
FindProperty f = find;
|
||||
|
||||
if (f != null && f.isInherited() && !(f.getProperty() instanceof UserAccessorProperty) && !isScope()) {
|
||||
// Setting a property should not modify the property in prototype unless this is a scope object.
|
||||
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),
|
||||
// it follows non-scope rules inside the 'with' expression (set is performed on the top level object).
|
||||
// This is why we clear the callsite flags and FindProperty in the forward call to the 'with' object.
|
||||
if (isScope && f.getSelf() != this) {
|
||||
f.getSelf().setObject(null, 0, key, value);
|
||||
return;
|
||||
}
|
||||
// Setting a property should not modify the property in prototype unless this is a scope callsite
|
||||
// and the owner is a scope object as well (with the exception of 'with' statement handled above).
|
||||
if (!isScope || !f.getOwner().isScope()) {
|
||||
f = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (f != null) {
|
||||
if (!f.getProperty().isWritable()) {
|
||||
if (strict) {
|
||||
if (NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)) {
|
||||
throw typeError("property.not.writable", key, ScriptRuntime.safeToString(this));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
f.setValue(value, strict);
|
||||
f.setValue(value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags));
|
||||
|
||||
} else if (!isExtensible()) {
|
||||
if (strict) {
|
||||
if (NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)) {
|
||||
throw typeError("object.non.extensible", key, ScriptRuntime.safeToString(this));
|
||||
}
|
||||
} else {
|
||||
@ -3153,293 +3172,293 @@ public abstract class ScriptObject implements PropertyAccess {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final Object key, final int value, final boolean strict) {
|
||||
public void set(final Object key, final int value, final int callSiteFlags) {
|
||||
final Object primitiveKey = JSType.toPrimitive(key, String.class);
|
||||
final int index = getArrayIndex(primitiveKey);
|
||||
|
||||
if (isValidArrayIndex(index)) {
|
||||
if (getArray().has(index)) {
|
||||
setArray(getArray().set(index, value, strict));
|
||||
setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, strict);
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
final String propName = JSType.toString(primitiveKey);
|
||||
setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
|
||||
setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final Object key, final long value, final boolean strict) {
|
||||
public void set(final Object key, final long value, final int callSiteFlags) {
|
||||
final Object primitiveKey = JSType.toPrimitive(key, String.class);
|
||||
final int index = getArrayIndex(primitiveKey);
|
||||
|
||||
if (isValidArrayIndex(index)) {
|
||||
if (getArray().has(index)) {
|
||||
setArray(getArray().set(index, value, strict));
|
||||
setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, strict);
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
final String propName = JSType.toString(primitiveKey);
|
||||
setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
|
||||
setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final Object key, final double value, final boolean strict) {
|
||||
public void set(final Object key, final double value, final int callSiteFlags) {
|
||||
final Object primitiveKey = JSType.toPrimitive(key, String.class);
|
||||
final int index = getArrayIndex(primitiveKey);
|
||||
|
||||
if (isValidArrayIndex(index)) {
|
||||
if (getArray().has(index)) {
|
||||
setArray(getArray().set(index, value, strict));
|
||||
setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, strict);
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
final String propName = JSType.toString(primitiveKey);
|
||||
setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
|
||||
setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final Object key, final Object value, final boolean strict) {
|
||||
public void set(final Object key, final Object value, final int callSiteFlags) {
|
||||
final Object primitiveKey = JSType.toPrimitive(key, String.class);
|
||||
final int index = getArrayIndex(primitiveKey);
|
||||
|
||||
if (isValidArrayIndex(index)) {
|
||||
if (getArray().has(index)) {
|
||||
setArray(getArray().set(index, value, strict));
|
||||
setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, strict);
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
final String propName = JSType.toString(primitiveKey);
|
||||
setObject(findProperty(propName, true), strict, propName, value);
|
||||
setObject(findProperty(propName, true), callSiteFlags, propName, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final double key, final int value, final boolean strict) {
|
||||
public void set(final double key, final int value, final int callSiteFlags) {
|
||||
final int index = getArrayIndex(key);
|
||||
|
||||
if (isValidArrayIndex(index)) {
|
||||
if (getArray().has(index)) {
|
||||
setArray(getArray().set(index, value, strict));
|
||||
setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, strict);
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
final String propName = JSType.toString(key);
|
||||
setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
|
||||
setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final double key, final long value, final boolean strict) {
|
||||
public void set(final double key, final long value, final int callSiteFlags) {
|
||||
final int index = getArrayIndex(key);
|
||||
|
||||
if (isValidArrayIndex(index)) {
|
||||
if (getArray().has(index)) {
|
||||
setArray(getArray().set(index, value, strict));
|
||||
setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, strict);
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
final String propName = JSType.toString(key);
|
||||
setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
|
||||
setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final double key, final double value, final boolean strict) {
|
||||
public void set(final double key, final double value, final int callSiteFlags) {
|
||||
final int index = getArrayIndex(key);
|
||||
|
||||
if (isValidArrayIndex(index)) {
|
||||
if (getArray().has(index)) {
|
||||
setArray(getArray().set(index, value, strict));
|
||||
setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, strict);
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
final String propName = JSType.toString(key);
|
||||
setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
|
||||
setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final double key, final Object value, final boolean strict) {
|
||||
public void set(final double key, final Object value, final int callSiteFlags) {
|
||||
final int index = getArrayIndex(key);
|
||||
|
||||
if (isValidArrayIndex(index)) {
|
||||
if (getArray().has(index)) {
|
||||
setArray(getArray().set(index, value, strict));
|
||||
setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, strict);
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
final String propName = JSType.toString(key);
|
||||
setObject(findProperty(propName, true), strict, propName, value);
|
||||
setObject(findProperty(propName, true), callSiteFlags, propName, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final long key, final int value, final boolean strict) {
|
||||
public void set(final long key, final int value, final int callSiteFlags) {
|
||||
final int index = getArrayIndex(key);
|
||||
|
||||
if (isValidArrayIndex(index)) {
|
||||
if (getArray().has(index)) {
|
||||
setArray(getArray().set(index, value, strict));
|
||||
setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, strict);
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
final String propName = JSType.toString(key);
|
||||
setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
|
||||
setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final long key, final long value, final boolean strict) {
|
||||
public void set(final long key, final long value, final int callSiteFlags) {
|
||||
final int index = getArrayIndex(key);
|
||||
|
||||
if (isValidArrayIndex(index)) {
|
||||
if (getArray().has(index)) {
|
||||
setArray(getArray().set(index, value, strict));
|
||||
setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, strict);
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
final String propName = JSType.toString(key);
|
||||
setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
|
||||
setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final long key, final double value, final boolean strict) {
|
||||
public void set(final long key, final double value, final int callSiteFlags) {
|
||||
final int index = getArrayIndex(key);
|
||||
|
||||
if (isValidArrayIndex(index)) {
|
||||
if (getArray().has(index)) {
|
||||
setArray(getArray().set(index, value, strict));
|
||||
setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, strict);
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
final String propName = JSType.toString(key);
|
||||
setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
|
||||
setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final long key, final Object value, final boolean strict) {
|
||||
public void set(final long key, final Object value, final int callSiteFlags) {
|
||||
final int index = getArrayIndex(key);
|
||||
|
||||
if (isValidArrayIndex(index)) {
|
||||
if (getArray().has(index)) {
|
||||
setArray(getArray().set(index, value, strict));
|
||||
setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, strict);
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
final String propName = JSType.toString(key);
|
||||
setObject(findProperty(propName, true), strict, propName, value);
|
||||
setObject(findProperty(propName, true), callSiteFlags, propName, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final int key, final int value, final boolean strict) {
|
||||
public void set(final int key, final int value, final int callSiteFlags) {
|
||||
final int index = getArrayIndex(key);
|
||||
if (isValidArrayIndex(index)) {
|
||||
if (getArray().has(index)) {
|
||||
setArray(getArray().set(index, value, strict));
|
||||
setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, strict);
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final String propName = JSType.toString(key);
|
||||
setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
|
||||
setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final int key, final long value, final boolean strict) {
|
||||
public void set(final int key, final long value, final int callSiteFlags) {
|
||||
final int index = getArrayIndex(key);
|
||||
|
||||
if (isValidArrayIndex(index)) {
|
||||
if (getArray().has(index)) {
|
||||
setArray(getArray().set(index, value, strict));
|
||||
setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, strict);
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
final String propName = JSType.toString(key);
|
||||
setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
|
||||
setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final int key, final double value, final boolean strict) {
|
||||
public void set(final int key, final double value, final int callSiteFlags) {
|
||||
final int index = getArrayIndex(key);
|
||||
|
||||
if (isValidArrayIndex(index)) {
|
||||
if (getArray().has(index)) {
|
||||
setArray(getArray().set(index, value, strict));
|
||||
setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, strict);
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
final String propName = JSType.toString(key);
|
||||
setObject(findProperty(propName, true), strict, propName, JSType.toObject(value));
|
||||
setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final int key, final Object value, final boolean strict) {
|
||||
public void set(final int key, final Object value, final int callSiteFlags) {
|
||||
final int index = getArrayIndex(key);
|
||||
|
||||
if (isValidArrayIndex(index)) {
|
||||
if (getArray().has(index)) {
|
||||
setArray(getArray().set(index, value, strict));
|
||||
setArray(getArray().set(index, value, NashornCallSiteDescriptor.isStrictFlag(callSiteFlags)));
|
||||
} else {
|
||||
doesNotHave(index, value, strict);
|
||||
doesNotHave(index, value, callSiteFlags);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
final String propName = JSType.toString(key);
|
||||
setObject(findProperty(propName, true), strict, propName, value);
|
||||
setObject(findProperty(propName, true), callSiteFlags, propName, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -221,9 +221,9 @@ public final class ScriptingFunctions {
|
||||
final String err = errBuffer.toString();
|
||||
|
||||
// Set globals for secondary results.
|
||||
global.set(OUT_NAME, out, false);
|
||||
global.set(ERR_NAME, err, false);
|
||||
global.set(EXIT_NAME, exit, false);
|
||||
global.set(OUT_NAME, out, 0);
|
||||
global.set(ERR_NAME, err, 0);
|
||||
global.set(EXIT_NAME, exit, 0);
|
||||
|
||||
// Propagate exception if present.
|
||||
for (final IOException element : exception) {
|
||||
|
@ -205,7 +205,7 @@ final class SetMethodCreator {
|
||||
|
||||
//slow setter, that calls ScriptObject.set with appropraite type and key name
|
||||
MethodHandle slowSetter = ScriptObject.SET_SLOW[getAccessorTypeIndex(type)];
|
||||
slowSetter = MH.insertArguments(slowSetter, 3, NashornCallSiteDescriptor.isStrict(desc));
|
||||
slowSetter = MH.insertArguments(slowSetter, 3, NashornCallSiteDescriptor.getFlags(desc));
|
||||
slowSetter = MH.insertArguments(slowSetter, 1, name);
|
||||
slowSetter = MH.asType(slowSetter, slowSetter.type().changeParameterType(0, Object.class));
|
||||
|
||||
|
@ -34,6 +34,7 @@ import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
|
||||
import jdk.internal.dynalink.support.Guards;
|
||||
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
|
||||
|
||||
/**
|
||||
* Unique instance of this class is used to represent JavaScript undefined.
|
||||
@ -128,7 +129,7 @@ public final class Undefined extends DefaultPropertyAccess {
|
||||
}
|
||||
|
||||
private static final MethodHandle GET_METHOD = findOwnMH("get", Object.class, Object.class);
|
||||
private static final MethodHandle SET_METHOD = MH.insertArguments(findOwnMH("set", void.class, Object.class, Object.class, boolean.class), 3, Boolean.TRUE);
|
||||
private static final MethodHandle SET_METHOD = MH.insertArguments(findOwnMH("set", void.class, Object.class, Object.class, int.class), 3, NashornCallSiteDescriptor.CALLSITE_STRICT);
|
||||
|
||||
private static GuardedInvocation findGetMethod(final CallSiteDescriptor desc) {
|
||||
return new GuardedInvocation(MH.insertArguments(GET_METHOD, 1, desc.getNameToken(2)), UNDEFINED_GUARD).asType(desc);
|
||||
@ -152,7 +153,7 @@ public final class Undefined extends DefaultPropertyAccess {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final Object key, final Object value, final boolean strict) {
|
||||
public void set(final Object key, final Object value, final int flags) {
|
||||
throw typeError("cant.set.property.of.undefined", ScriptRuntime.safeToString(key));
|
||||
}
|
||||
|
||||
|
@ -193,18 +193,20 @@ public final class WithObject extends ScriptObject implements Scope {
|
||||
*
|
||||
* @param key Property key.
|
||||
* @param deep Whether the search should look up proto chain.
|
||||
* @param stopOnNonScope should a deep search stop on the first non-scope object?
|
||||
* @param start the object on which the lookup was originally initiated
|
||||
*
|
||||
* @return FindPropertyData or null if not found.
|
||||
*/
|
||||
@Override
|
||||
FindProperty findProperty(final String key, final boolean deep, final boolean stopOnNonScope, final ScriptObject start) {
|
||||
final FindProperty exprProperty = expression.findProperty(key, deep, stopOnNonScope, start);
|
||||
FindProperty findProperty(final String key, final boolean deep, final ScriptObject start) {
|
||||
// We call findProperty on 'expression' with 'expression' itself as start parameter.
|
||||
// This way in ScriptObject.setObject we can tell the property is from a 'with' expression
|
||||
// (as opposed from another non-scope object in the proto chain such as Object.prototype).
|
||||
final FindProperty exprProperty = expression.findProperty(key, true, expression);
|
||||
if (exprProperty != null) {
|
||||
return exprProperty;
|
||||
}
|
||||
return super.findProperty(key, deep, stopOnNonScope, start);
|
||||
return super.findProperty(key, deep, start);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -255,7 +255,7 @@ public final class NashornCallSiteDescriptor extends AbstractCallSiteDescriptor
|
||||
* @return the Nashorn-specific flags for the call site, or 0 if the passed descriptor is not a Nashorn call site
|
||||
* descriptor.
|
||||
*/
|
||||
private static int getFlags(final CallSiteDescriptor desc) {
|
||||
public static int getFlags(final CallSiteDescriptor desc) {
|
||||
return desc instanceof NashornCallSiteDescriptor ? ((NashornCallSiteDescriptor)desc).flags : 0;
|
||||
}
|
||||
|
||||
@ -342,6 +342,24 @@ public final class NashornCallSiteDescriptor extends AbstractCallSiteDescriptor
|
||||
return isFlag(desc, CALLSITE_DECLARE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if {@code flags} has the {@link #CALLSITE_STRICT} bit set.
|
||||
* @param flags the flags
|
||||
* @return true if the flag is set, false otherwise.
|
||||
*/
|
||||
public static boolean isStrictFlag(final int flags) {
|
||||
return (flags & CALLSITE_STRICT) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if {@code flags} has the {@link #CALLSITE_SCOPE} bit set.
|
||||
* @param flags the flags
|
||||
* @return true if the flag is set, false otherwise.
|
||||
*/
|
||||
public static boolean isScopeFlag(final int flags) {
|
||||
return (flags & CALLSITE_SCOPE) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a program point from a descriptor (must be optimistic)
|
||||
* @param desc descriptor
|
||||
|
69
nashorn/test/script/basic/JDK-8047764-strict.js
Normal file
69
nashorn/test/script/basic/JDK-8047764-strict.js
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 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-8047764: Indexed or polymorphic set on global affects Object.prototype
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
*/
|
||||
|
||||
// Same as JDK-8047764.js but running in strict mode
|
||||
"use strict";
|
||||
|
||||
// Test global set operation on properties defined in Object.prototype
|
||||
|
||||
Object.defineProperty(Object.prototype, "prop1", { get: function() { return 1; }, set: function(v) { print("setting prop1: " + v); }});
|
||||
Object.defineProperty(Object.prototype, "prop2", { value: 1, writable: false, configurable: false });
|
||||
|
||||
try {
|
||||
prop1 = 1;
|
||||
print("prop 1: " + prop2);
|
||||
} catch (e) {
|
||||
print(e.name);
|
||||
}
|
||||
|
||||
try {
|
||||
prop2 = 2;
|
||||
print("prop 2: " + prop2);
|
||||
} catch (e) {
|
||||
print(e.name);
|
||||
}
|
||||
|
||||
// Make sure various ways of setting global toString don't affect Object.prototype.toString
|
||||
|
||||
function checkToString() {
|
||||
print(global);
|
||||
print(Object.prototype);
|
||||
print(global.toString === Object.prototype.toString);
|
||||
print(objProtoToString === Object.prototype.toString);
|
||||
}
|
||||
|
||||
var global = this;
|
||||
var objProtoToString = Object.prototype.toString;
|
||||
global["toString"] = function() { return "global toString 1"; };
|
||||
checkToString();
|
||||
global.toString = function() { return "global toString 2"; };
|
||||
checkToString();
|
||||
toString = function() { return "global toString 3"; };
|
||||
checkToString();
|
15
nashorn/test/script/basic/JDK-8047764-strict.js.EXPECTED
Normal file
15
nashorn/test/script/basic/JDK-8047764-strict.js.EXPECTED
Normal file
@ -0,0 +1,15 @@
|
||||
setting prop1: 1
|
||||
prop 1: 1
|
||||
TypeError
|
||||
global toString 1
|
||||
[object Object]
|
||||
false
|
||||
true
|
||||
global toString 2
|
||||
[object Object]
|
||||
false
|
||||
true
|
||||
global toString 3
|
||||
[object Object]
|
||||
false
|
||||
true
|
94
nashorn/test/script/basic/JDK-8047764.js
Normal file
94
nashorn/test/script/basic/JDK-8047764.js
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 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-8047764: Indexed or polymorphic set on global affects Object.prototype
|
||||
*
|
||||
* @test
|
||||
* @run
|
||||
*/
|
||||
|
||||
// Test global set operation on properties defined in Object.prototype
|
||||
|
||||
Object.defineProperty(Object.prototype, "prop1", { get: function() { return 1; }, set: function(v) { print("setting prop1: " + v); }});
|
||||
Object.defineProperty(Object.prototype, "prop2", { value: 1, writable: false, configurable: false });
|
||||
|
||||
try {
|
||||
prop1 = 1;
|
||||
print("prop 1: " + prop2);
|
||||
} catch (e) {
|
||||
print(e.name);
|
||||
}
|
||||
|
||||
try {
|
||||
prop2 = 2;
|
||||
print("prop 2: " + prop2);
|
||||
} catch (e) {
|
||||
print(e.name);
|
||||
}
|
||||
|
||||
// Make sure various ways of setting global toString don't affect Object.prototype.toString
|
||||
|
||||
function checkToString() {
|
||||
print(global);
|
||||
print(Object.prototype);
|
||||
print(global.toString === Object.prototype.toString);
|
||||
print(objProtoToString === Object.prototype.toString);
|
||||
}
|
||||
|
||||
var global = this;
|
||||
var objProtoToString = Object.prototype.toString;
|
||||
global["toString"] = function() { return "global toString 1"; };
|
||||
checkToString();
|
||||
global.toString = function() { return "global toString 2"; };
|
||||
checkToString();
|
||||
toString = function() { return "global toString 3"; };
|
||||
checkToString();
|
||||
|
||||
// Test setters on 'with' object
|
||||
|
||||
var p = { prop3: 3, toString: function() { return "[object p]"; }};
|
||||
Object.defineProperty(p, "prop4", { get: function() { print("get", this); return 4; }, set: function(v) { print("set", this, v); }});
|
||||
var o = Object.create(p);
|
||||
o.toString = function() { return "[object o]"; };
|
||||
|
||||
with(o) {
|
||||
(function() {
|
||||
var m = 5;
|
||||
(function() {
|
||||
print(prop3);
|
||||
prop3 = m;
|
||||
print(prop3);
|
||||
print(prop4);
|
||||
prop4 = m;
|
||||
print(prop4);
|
||||
})();
|
||||
})();
|
||||
}
|
||||
|
||||
print(o.hasOwnProperty("prop3"));
|
||||
print(o.prop3);
|
||||
print(p.prop3);
|
||||
print(o.hasOwnProperty("prop4"));
|
||||
print(o.prop4);
|
||||
print(p.prop4);
|
30
nashorn/test/script/basic/JDK-8047764.js.EXPECTED
Normal file
30
nashorn/test/script/basic/JDK-8047764.js.EXPECTED
Normal file
@ -0,0 +1,30 @@
|
||||
setting prop1: 1
|
||||
prop 1: 1
|
||||
prop 2: 1
|
||||
global toString 1
|
||||
[object Object]
|
||||
false
|
||||
true
|
||||
global toString 2
|
||||
[object Object]
|
||||
false
|
||||
true
|
||||
global toString 3
|
||||
[object Object]
|
||||
false
|
||||
true
|
||||
3
|
||||
5
|
||||
get [object o]
|
||||
4
|
||||
set [object o] 5
|
||||
get [object o]
|
||||
4
|
||||
true
|
||||
5
|
||||
3
|
||||
false
|
||||
get [object o]
|
||||
4
|
||||
get [object p]
|
||||
4
|
Loading…
x
Reference in New Issue
Block a user