This commit is contained in:
Lana Steuck 2015-01-24 23:23:06 -08:00
commit e4a553ffe4
6 changed files with 159 additions and 70 deletions

View File

@ -340,9 +340,10 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin
@Override
public boolean containsKey(final Object key) {
checkKey(key);
return inGlobal(new Callable<Boolean>() {
@Override public Boolean call() {
return sobj.containsKey(unwrap(key, global));
return sobj.containsKey(key);
}
});
}
@ -376,6 +377,7 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin
@Override
public Object get(final Object key) {
checkKey(key);
return inGlobal(new Callable<Object>() {
@Override public Object call() {
return translateUndefined(wrap(sobj.get(key), global));
@ -410,6 +412,7 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin
@Override
public Object put(final String key, final Object value) {
checkKey(key);
final ScriptObject oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != global);
return inGlobal(new Callable<Object>() {
@ -422,6 +425,9 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin
@Override
public void putAll(final Map<? extends String, ? extends Object> map) {
if (map == null) {
throw new NullPointerException("map is null");
}
final ScriptObject oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != global);
inGlobal(new Callable<Object>() {
@ -429,7 +435,9 @@ 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), getCallSiteFlags());
final String key = entry.getKey();
checkKey(key);
sobj.set(key, unwrap(modValue, global), getCallSiteFlags());
}
return null;
}
@ -438,9 +446,10 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin
@Override
public Object remove(final Object key) {
checkKey(key);
return inGlobal(new Callable<Object>() {
@Override public Object call() {
return wrap(sobj.remove(unwrap(key, global), strict), global);
return wrap(sobj.remove(key, strict), global);
}
});
}
@ -629,7 +638,7 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin
}
/**
* Utilitity to convert this script object to the given type.
* Utility to convert this script object to the given type.
*
* @param <T> destination type to convert to
* @param type destination type to convert to
@ -786,6 +795,24 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin
}
}
/**
* Ensures the key is not null, empty string, or a non-String object. The contract of the {@link Bindings}
* interface requires that these are not accepted as keys.
* @param key the key to check
* @throws NullPointerException if key is null
* @throws ClassCastException if key is not a String
* @throws IllegalArgumentException if key is empty string
*/
private static void checkKey(final Object key) {
if (key == null) {
throw new NullPointerException("key can not be null");
} else if (!(key instanceof String)) {
throw new ClassCastException("key should be a String. It is " + key.getClass().getName() + " instead.");
} else if (((String)key).length() == 0) {
throw new IllegalArgumentException("key can not be empty");
}
}
@Override
public double toNumber() {
return inGlobal(new Callable<Double>() {

View File

@ -26,6 +26,7 @@
package jdk.nashorn.internal.runtime.arrays;
import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Array;
@ -760,39 +761,6 @@ public abstract class ArrayData {
return push(strict, new Object[] { item });
}
/**
* Push an array of items to the end of the array
*
* @param strict are we in strict mode
* @param item the item
* @return new array data (or same)
*/
public ArrayData push(final boolean strict, final double item) {
return push(strict, item);
}
/**
* Push an array of items to the end of the array
*
* @param strict are we in strict mode
* @param item the item
* @return new array data (or same)
*/
public ArrayData push(final boolean strict, final long item) {
return push(strict, item);
}
/**
* Push an array of items to the end of the array
*
* @param strict are we in strict mode
* @param item the item
* @return new array data (or same)
*/
public ArrayData push(final boolean strict, final int item) {
return push(strict, item);
}
/**
* Pop an element from the end of the array
*

View File

@ -26,6 +26,7 @@
package jdk.nashorn.internal.runtime.arrays;
import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.util.Arrays;
@ -342,17 +343,6 @@ final class IntArrayData extends ContinuousArrayData implements IntElements {
return new IntArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)(to - (from < 0 ? from + length() : from)));
}
@Override
public final ArrayData push(final boolean strict, final int item) {
final long len = length();
final ArrayData newData = ensure(len);
if (newData == this) {
array[(int)len] = item;
return this;
}
return newData.set((int)len, item, strict);
}
@Override
public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
final long oldLength = length();

View File

@ -27,6 +27,7 @@ package jdk.nashorn.internal.runtime.arrays;
import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
import static jdk.nashorn.internal.lookup.Lookup.MH;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.util.Arrays;
@ -302,17 +303,6 @@ final class LongArrayData extends ContinuousArrayData implements IntOrLongElemen
return new LongArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength);
}
@Override
public final ArrayData push(final boolean strict, final long item) {
final long len = length();
final ArrayData newData = ensure(len);
if (newData == this) {
array[(int)len] = item;
return this;
}
return newData.set((int)len, item, strict);
}
@Override
public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
final long oldLength = length();

View File

@ -28,6 +28,7 @@ package jdk.nashorn.internal.runtime.arrays;
import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
import static jdk.nashorn.internal.lookup.Lookup.MH;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.util.Arrays;
@ -276,17 +277,6 @@ final class NumberArrayData extends ContinuousArrayData implements NumericElemen
return new NumberArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength);
}
@Override
public final ArrayData push(final boolean strict, final double item) {
final long len = length();
final ArrayData newData = ensure(len);
if (newData == this) {
array[(int)len] = item;
return this;
}
return newData.set((int)len, item, strict);
}
@Override
public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
final long oldLength = length();

View File

@ -36,10 +36,12 @@ import java.io.StringWriter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collections;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.function.Function;
import javax.script.Bindings;
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.Invocable;
@ -719,6 +721,128 @@ public class ScriptEngineTest {
assertTrue(invoked.get());
}
// @bug JDK-8068603: NashornScriptEngine.put/get() impls don't conform to NPE, IAE spec assertions
@Test
public void illegalBindingsValuesTest() throws Exception {
final ScriptEngineManager manager = new ScriptEngineManager();
final ScriptEngine e = manager.getEngineByName("nashorn");
try {
e.put(null, "null-value");
fail();
} catch (NullPointerException x) {
// expected
}
try {
e.put("", "empty-value");
fail();
} catch (IllegalArgumentException x) {
// expected
}
final Bindings b = e.getBindings(ScriptContext.ENGINE_SCOPE);
assertTrue(b instanceof ScriptObjectMirror);
try {
b.put(null, "null-value");
fail();
} catch (NullPointerException x) {
// expected
}
try {
b.put("", "empty-value");
fail();
} catch (IllegalArgumentException x) {
// expected
}
try {
b.get(null);
fail();
} catch (NullPointerException x) {
// expected
}
try {
b.get("");
fail();
} catch (IllegalArgumentException x) {
// expected
}
try {
b.get(1);
fail();
} catch (ClassCastException x) {
// expected
}
try {
b.remove(null);
fail();
} catch (NullPointerException x) {
// expected
}
try {
b.remove("");
fail();
} catch (IllegalArgumentException x) {
// expected
}
try {
b.remove(1);
fail();
} catch (ClassCastException x) {
// expected
}
try {
b.containsKey(null);
fail();
} catch (NullPointerException x) {
// expected
}
try {
b.containsKey("");
fail();
} catch (IllegalArgumentException x) {
// expected
}
try {
b.containsKey(1);
fail();
} catch (ClassCastException x) {
// expected
}
try {
b.putAll(null);
fail();
} catch (NullPointerException x) {
// expected
}
try {
b.putAll(Collections.singletonMap((String)null, "null-value"));
fail();
} catch (NullPointerException x) {
// expected
}
try {
b.putAll(Collections.singletonMap("", "empty-value"));
fail();
} catch (IllegalArgumentException x) {
// expected
}
}
private static void checkProperty(final ScriptEngine e, final String name)
throws ScriptException {
final String value = System.getProperty(name);