This commit is contained in:
Athijegannathan Sundararajan 2013-06-11 13:12:35 +05:30
commit 0886052a85
26 changed files with 703 additions and 268 deletions

View File

@ -202,18 +202,52 @@ final class Attr extends NodeOperatorVisitor<LexicalContext> {
private void acceptDeclarations(final FunctionNode functionNode, final Block body) { private void acceptDeclarations(final FunctionNode functionNode, final Block body) {
// This visitor will assign symbol to all declared variables, except function declarations (which are taken care // This visitor will assign symbol to all declared variables, except function declarations (which are taken care
// in a separate step above) and "var" declarations in for loop initializers. // in a separate step above) and "var" declarations in for loop initializers.
//
// It also handles the case that a variable can be undefined, e.g
// if (cond) {
// x = x.y;
// }
// var x = 17;
//
// by making sure that no identifier has been found earlier in the body than the
// declaration - if such is the case the identifier is flagged as caBeUndefined to
// be safe if it turns into a local var. Otherwise corrupt bytecode results
body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
private final Set<String> uses = new HashSet<>();
private final Set<String> canBeUndefined = new HashSet<>();
@Override @Override
public boolean enterFunctionNode(final FunctionNode nestedFn) { public boolean enterFunctionNode(final FunctionNode nestedFn) {
return false; return false;
} }
@Override
public Node leaveIdentNode(final IdentNode identNode) {
uses.add(identNode.getName());
return identNode;
}
@Override
public boolean enterVarNode(final VarNode varNode) {
final String name = varNode.getName().getName();
//if this is used the var node symbol needs to be tagged as can be undefined
if (uses.contains(name)) {
canBeUndefined.add(name);
}
return true;
}
@Override @Override
public Node leaveVarNode(final VarNode varNode) { public Node leaveVarNode(final VarNode varNode) {
// any declared symbols that aren't visited need to be typed as well, hence the list // any declared symbols that aren't visited need to be typed as well, hence the list
if (varNode.isStatement()) { if (varNode.isStatement()) {
final IdentNode ident = varNode.getName(); final IdentNode ident = varNode.getName();
final Symbol symbol = defineSymbol(body, ident.getName(), IS_VAR); final Symbol symbol = defineSymbol(body, ident.getName(), IS_VAR);
if (canBeUndefined.contains(ident.getName())) {
symbol.setType(Type.OBJECT);
symbol.setCanBeUndefined();
}
functionNode.addDeclaredSymbol(symbol); functionNode.addDeclaredSymbol(symbol);
if (varNode.isFunctionDeclaration()) { if (varNode.isFunctionDeclaration()) {
newType(symbol, FunctionNode.FUNCTION_TYPE); newType(symbol, FunctionNode.FUNCTION_TYPE);

View File

@ -126,7 +126,7 @@ public abstract class FieldObjectCreator<T> extends ObjectCreator {
final T value = valueIter.next(); final T value = valueIter.next();
if (symbol != null && value != null) { if (symbol != null && value != null) {
final int index = ArrayIndex.getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (index < 0) { if (index < 0) {
putField(method, key, symbol.getFieldIndex(), value); putField(method, key, symbol.getFieldIndex(), value);

View File

@ -79,7 +79,7 @@ public class MapCreator {
final String key = keys[i]; final String key = keys[i];
final Symbol symbol = symbols[i]; final Symbol symbol = symbols[i];
if (symbol != null && !ArrayIndex.isIndexKey(key)) { if (symbol != null && !ArrayIndex.isIntArrayIndex(key)) {
properties.add(new AccessorProperty(key, getPropertyFlags(symbol, hasArguments), structure, symbol.getFieldIndex())); properties.add(new AccessorProperty(key, getPropertyFlags(symbol, hasArguments), structure, symbol.getFieldIndex()));
} }
} }

View File

@ -63,6 +63,7 @@ public class BlockLexicalContext extends LexicalContext {
return sstack.pop(); return sstack.pop();
} }
@SuppressWarnings("unchecked")
@Override @Override
public <T extends LexicalContextNode> T pop(final T node) { public <T extends LexicalContextNode> T pop(final T node) {
T expected = node; T expected = node;

View File

@ -462,7 +462,7 @@ public final class Symbol implements Comparable<Symbol> {
*/ */
public void setCanBeUndefined() { public void setCanBeUndefined() {
assert type.isObject() : type; assert type.isObject() : type;
if(!canBeUndefined()) { if (!isParam() && !canBeUndefined()) {//parameters are never undefined
assert !isShared(); assert !isShared();
flags |= CAN_BE_UNDEFINED; flags |= CAN_BE_UNDEFINED;
} }

View File

@ -33,6 +33,8 @@ import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime; import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.arrays.ArrayData; import jdk.nashorn.internal.runtime.arrays.ArrayData;
import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
@ScriptClass("ArrayBufferView") @ScriptClass("ArrayBufferView")
abstract class ArrayBufferView extends ScriptObject { abstract class ArrayBufferView extends ScriptObject {
@ -305,11 +307,11 @@ abstract class ArrayBufferView extends ScriptObject {
dst = factory.construct(length); dst = factory.construct(length);
} else if (arg0 instanceof NativeArray) { } else if (arg0 instanceof NativeArray) {
// Constructor(type[] array) // Constructor(type[] array)
length = (int) (((NativeArray) arg0).getArray().length() & 0x7fff_ffff); length = lengthToInt(((NativeArray) arg0).getArray().length());
dst = factory.construct(length); dst = factory.construct(length);
} else { } else {
// Constructor(unsigned long length) // Constructor(unsigned long length)
length = JSType.toInt32(arg0); length = lengthToInt(JSType.toInt64(arg0));
return factory.construct(length); return factory.construct(length);
} }
@ -354,6 +356,13 @@ abstract class ArrayBufferView extends ScriptObject {
} }
} }
private static int lengthToInt(final long length) {
if (length > Integer.MAX_VALUE || length < 0) {
throw rangeError("inappropriate.array.buffer.length", JSType.toString(length));
}
return (int) (length & Integer.MAX_VALUE);
}
protected static Object subarrayImpl(final Object self, final Object begin0, final Object end0) { protected static Object subarrayImpl(final Object self, final Object begin0, final Object end0) {
final ArrayBufferView arrayView = ((ArrayBufferView)self); final ArrayBufferView arrayView = ((ArrayBufferView)self);
final int elementLength = arrayView.elementLength(); final int elementLength = arrayView.elementLength();

View File

@ -372,7 +372,7 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
private static final MethodHandle PRINT = findOwnMH("print", Object.class, Object.class, Object[].class); private static final MethodHandle PRINT = findOwnMH("print", Object.class, Object.class, Object[].class);
private static final MethodHandle PRINTLN = findOwnMH("println", Object.class, Object.class, Object[].class); private static final MethodHandle PRINTLN = findOwnMH("println", Object.class, Object.class, Object[].class);
private static final MethodHandle LOAD = findOwnMH("load", Object.class, Object.class, Object.class); private static final MethodHandle LOAD = findOwnMH("load", Object.class, Object.class, Object.class);
private static final MethodHandle LOADWITHNEWGLOBAL = findOwnMH("loadWithNewGlobal", Object.class, Object.class, Object.class); private static final MethodHandle LOADWITHNEWGLOBAL = findOwnMH("loadWithNewGlobal", Object.class, Object.class, Object.class, Object[].class);
private static final MethodHandle EXIT = findOwnMH("exit", Object.class, Object.class, Object.class); private static final MethodHandle EXIT = findOwnMH("exit", Object.class, Object.class, Object.class);
private final Context context; private final Context context;
@ -752,14 +752,15 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
* *
* @param self scope * @param self scope
* @param source source to load * @param source source to load
* @param args (optional) arguments to be passed to the loaded script
* *
* @return result of load (undefined) * @return result of load (undefined)
* *
* @throws IOException if source could not be read * @throws IOException if source could not be read
*/ */
public static Object loadWithNewGlobal(final Object self, final Object source) throws IOException { public static Object loadWithNewGlobal(final Object self, final Object source, final Object...args) throws IOException {
final Global global = Global.instance(); final Global global = Global.instance();
return global.context.loadWithNewGlobal(source); return global.context.loadWithNewGlobal(source, args);
} }
/** /**

View File

@ -27,7 +27,6 @@ package jdk.nashorn.internal.objects;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndexNoThrow;
import static jdk.nashorn.internal.lookup.Lookup.MH; import static jdk.nashorn.internal.lookup.Lookup.MH;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;
@ -132,103 +131,103 @@ public final class NativeArguments extends ScriptObject {
@Override @Override
public int getInt(final Object key) { public int getInt(final Object key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getInt(index) : super.getInt(key); return isMapped(index) ? namedArgs.getInt(index) : super.getInt(key);
} }
@Override @Override
public int getInt(final double key) { public int getInt(final double key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getInt(index) : super.getInt(key); return isMapped(index) ? namedArgs.getInt(index) : super.getInt(key);
} }
@Override @Override
public int getInt(final long key) { public int getInt(final long key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getInt(index) : super.getInt(key); return isMapped(index) ? namedArgs.getInt(index) : super.getInt(key);
} }
@Override @Override
public int getInt(final int key) { public int getInt(final int key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getInt(index) : super.getInt(key); return isMapped(index) ? namedArgs.getInt(index) : super.getInt(key);
} }
@Override @Override
public long getLong(final Object key) { public long getLong(final Object key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getLong(index) : super.getLong(key); return isMapped(index) ? namedArgs.getLong(index) : super.getLong(key);
} }
@Override @Override
public long getLong(final double key) { public long getLong(final double key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getLong(index) : super.getLong(key); return isMapped(index) ? namedArgs.getLong(index) : super.getLong(key);
} }
@Override @Override
public long getLong(final long key) { public long getLong(final long key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getLong(index) : super.getLong(key); return isMapped(index) ? namedArgs.getLong(index) : super.getLong(key);
} }
@Override @Override
public long getLong(final int key) { public long getLong(final int key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getLong(index) : super.getLong(key); return isMapped(index) ? namedArgs.getLong(index) : super.getLong(key);
} }
@Override @Override
public double getDouble(final Object key) { public double getDouble(final Object key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getDouble(index) : super.getDouble(key); return isMapped(index) ? namedArgs.getDouble(index) : super.getDouble(key);
} }
@Override @Override
public double getDouble(final double key) { public double getDouble(final double key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getDouble(index) : super.getDouble(key); return isMapped(index) ? namedArgs.getDouble(index) : super.getDouble(key);
} }
@Override @Override
public double getDouble(final long key) { public double getDouble(final long key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getDouble(index) : super.getDouble(key); return isMapped(index) ? namedArgs.getDouble(index) : super.getDouble(key);
} }
@Override @Override
public double getDouble(final int key) { public double getDouble(final int key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getDouble(index) : super.getDouble(key); return isMapped(index) ? namedArgs.getDouble(index) : super.getDouble(key);
} }
@Override @Override
public Object get(final Object key) { public Object get(final Object key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getObject(index) : super.get(key); return isMapped(index) ? namedArgs.getObject(index) : super.get(key);
} }
@Override @Override
public Object get(final double key) { public Object get(final double key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getObject(index) : super.get(key); return isMapped(index) ? namedArgs.getObject(index) : super.get(key);
} }
@Override @Override
public Object get(final long key) { public Object get(final long key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getObject(index) : super.get(key); return isMapped(index) ? namedArgs.getObject(index) : super.get(key);
} }
@Override @Override
public Object get(final int key) { public Object get(final int key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getObject(index) : super.get(key); return isMapped(index) ? namedArgs.getObject(index) : super.get(key);
} }
@Override @Override
public void set(final Object key, final int value, final boolean strict) { public void set(final Object key, final int value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) { if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict); namedArgs = namedArgs.set(index, value, strict);
} else { } else {
@ -238,7 +237,7 @@ public final class NativeArguments extends ScriptObject {
@Override @Override
public void set(final Object key, final long value, final boolean strict) { public void set(final Object key, final long value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) { if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict); namedArgs = namedArgs.set(index, value, strict);
} else { } else {
@ -248,7 +247,7 @@ public final class NativeArguments extends ScriptObject {
@Override @Override
public void set(final Object key, final double value, final boolean strict) { public void set(final Object key, final double value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) { if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict); namedArgs = namedArgs.set(index, value, strict);
} else { } else {
@ -258,7 +257,7 @@ public final class NativeArguments extends ScriptObject {
@Override @Override
public void set(final Object key, final Object value, final boolean strict) { public void set(final Object key, final Object value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) { if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict); namedArgs = namedArgs.set(index, value, strict);
} else { } else {
@ -268,7 +267,7 @@ public final class NativeArguments extends ScriptObject {
@Override @Override
public void set(final double key, final int value, final boolean strict) { public void set(final double key, final int value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) { if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict); namedArgs = namedArgs.set(index, value, strict);
} else { } else {
@ -278,7 +277,7 @@ public final class NativeArguments extends ScriptObject {
@Override @Override
public void set(final double key, final long value, final boolean strict) { public void set(final double key, final long value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) { if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict); namedArgs = namedArgs.set(index, value, strict);
} else { } else {
@ -288,7 +287,7 @@ public final class NativeArguments extends ScriptObject {
@Override @Override
public void set(final double key, final double value, final boolean strict) { public void set(final double key, final double value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) { if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict); namedArgs = namedArgs.set(index, value, strict);
} else { } else {
@ -298,7 +297,7 @@ public final class NativeArguments extends ScriptObject {
@Override @Override
public void set(final double key, final Object value, final boolean strict) { public void set(final double key, final Object value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) { if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict); namedArgs = namedArgs.set(index, value, strict);
} else { } else {
@ -308,7 +307,7 @@ public final class NativeArguments extends ScriptObject {
@Override @Override
public void set(final long key, final int value, final boolean strict) { public void set(final long key, final int value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) { if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict); namedArgs = namedArgs.set(index, value, strict);
} else { } else {
@ -318,7 +317,7 @@ public final class NativeArguments extends ScriptObject {
@Override @Override
public void set(final long key, final long value, final boolean strict) { public void set(final long key, final long value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) { if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict); namedArgs = namedArgs.set(index, value, strict);
} else { } else {
@ -328,7 +327,7 @@ public final class NativeArguments extends ScriptObject {
@Override @Override
public void set(final long key, final double value, final boolean strict) { public void set(final long key, final double value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) { if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict); namedArgs = namedArgs.set(index, value, strict);
} else { } else {
@ -338,7 +337,7 @@ public final class NativeArguments extends ScriptObject {
@Override @Override
public void set(final long key, final Object value, final boolean strict) { public void set(final long key, final Object value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) { if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict); namedArgs = namedArgs.set(index, value, strict);
} else { } else {
@ -348,7 +347,7 @@ public final class NativeArguments extends ScriptObject {
@Override @Override
public void set(final int key, final int value, final boolean strict) { public void set(final int key, final int value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) { if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict); namedArgs = namedArgs.set(index, value, strict);
} else { } else {
@ -358,7 +357,7 @@ public final class NativeArguments extends ScriptObject {
@Override @Override
public void set(final int key, final long value, final boolean strict) { public void set(final int key, final long value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) { if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict); namedArgs = namedArgs.set(index, value, strict);
} else { } else {
@ -368,7 +367,7 @@ public final class NativeArguments extends ScriptObject {
@Override @Override
public void set(final int key, final double value, final boolean strict) { public void set(final int key, final double value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) { if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict); namedArgs = namedArgs.set(index, value, strict);
} else { } else {
@ -378,7 +377,7 @@ public final class NativeArguments extends ScriptObject {
@Override @Override
public void set(final int key, final Object value, final boolean strict) { public void set(final int key, final Object value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) { if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict); namedArgs = namedArgs.set(index, value, strict);
} else { } else {
@ -388,55 +387,55 @@ public final class NativeArguments extends ScriptObject {
@Override @Override
public boolean has(final Object key) { public boolean has(final Object key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) || super.has(key); return isMapped(index) || super.has(key);
} }
@Override @Override
public boolean has(final double key) { public boolean has(final double key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) || super.has(key); return isMapped(index) || super.has(key);
} }
@Override @Override
public boolean has(final long key) { public boolean has(final long key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) || super.has(key); return isMapped(index) || super.has(key);
} }
@Override @Override
public boolean has(final int key) { public boolean has(final int key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) || super.has(key); return isMapped(index) || super.has(key);
} }
@Override @Override
public boolean hasOwnProperty(final Object key) { public boolean hasOwnProperty(final Object key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) || super.hasOwnProperty(key); return isMapped(index) || super.hasOwnProperty(key);
} }
@Override @Override
public boolean hasOwnProperty(final int key) { public boolean hasOwnProperty(final int key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) || super.hasOwnProperty(key); return isMapped(index) || super.hasOwnProperty(key);
} }
@Override @Override
public boolean hasOwnProperty(final long key) { public boolean hasOwnProperty(final long key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) || super.hasOwnProperty(key); return isMapped(index) || super.hasOwnProperty(key);
} }
@Override @Override
public boolean hasOwnProperty(final double key) { public boolean hasOwnProperty(final double key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) || super.hasOwnProperty(key); return isMapped(index) || super.hasOwnProperty(key);
} }
@Override @Override
public boolean delete(final int key, final boolean strict) { public boolean delete(final int key, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
final boolean success = super.delete(key, strict); final boolean success = super.delete(key, strict);
if (success && namedArgs.has(index)) { if (success && namedArgs.has(index)) {
setDeleted(index); setDeleted(index);
@ -446,7 +445,7 @@ public final class NativeArguments extends ScriptObject {
@Override @Override
public boolean delete(final long key, final boolean strict) { public boolean delete(final long key, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
final boolean success = super.delete(key, strict); final boolean success = super.delete(key, strict);
if (success && namedArgs.has(index)) { if (success && namedArgs.has(index)) {
setDeleted(index); setDeleted(index);
@ -456,7 +455,7 @@ public final class NativeArguments extends ScriptObject {
@Override @Override
public boolean delete(final double key, final boolean strict) { public boolean delete(final double key, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
final boolean success = super.delete(key, strict); final boolean success = super.delete(key, strict);
if (success && namedArgs.has(index)) { if (success && namedArgs.has(index)) {
setDeleted(index); setDeleted(index);
@ -466,7 +465,7 @@ public final class NativeArguments extends ScriptObject {
@Override @Override
public boolean delete(final Object key, final boolean strict) { public boolean delete(final Object key, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
final boolean success = super.delete(key, strict); final boolean success = super.delete(key, strict);
if (success && namedArgs.has(index)) { if (success && namedArgs.has(index)) {
setDeleted(index); setDeleted(index);
@ -480,7 +479,7 @@ public final class NativeArguments extends ScriptObject {
*/ */
@Override @Override
public boolean defineOwnProperty(final String key, final Object propertyDesc, final boolean reject) { public boolean defineOwnProperty(final String key, final Object propertyDesc, final boolean reject) {
final int index = ArrayIndex.getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (index >= 0) { if (index >= 0) {
final boolean allowed = super.defineOwnProperty(key, propertyDesc, false); final boolean allowed = super.defineOwnProperty(key, propertyDesc, false);
if (!allowed) { if (!allowed) {

View File

@ -228,7 +228,7 @@ public final class NativeArray extends ScriptObject {
} }
// Step 4a // Step 4a
final int index = ArrayIndex.getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (ArrayIndex.isValidArrayIndex(index)) { if (ArrayIndex.isValidArrayIndex(index)) {
final long longIndex = ArrayIndex.toLongIndex(index); final long longIndex = ArrayIndex.toLongIndex(index);
// Step 4b // Step 4b
@ -770,7 +770,7 @@ public final class NativeArray extends ScriptObject {
final NativeArray copy = new NativeArray(0); final NativeArray copy = new NativeArray(0);
for (long n = 0; k < finale; n++, k++) { for (long n = 0; k < finale; n++, k++) {
copy.defineOwnProperty((int) n, sobj.get(k)); copy.defineOwnProperty(ArrayIndex.getArrayIndex(n), sobj.get(k));
} }
return copy; return copy;
@ -835,28 +835,26 @@ public final class NativeArray extends ScriptObject {
final ScriptObject sobj = (ScriptObject) self; final ScriptObject sobj = (ScriptObject) self;
final boolean strict = sobj.isStrictContext(); final boolean strict = sobj.isStrictContext();
final long len = JSType.toUint32(sobj.getLength()); final long len = JSType.toUint32(sobj.getLength());
ArrayData array = sobj.getArray();
if (len > 1) { if (len > 1) {
// Get only non-missing elements. Missing elements go at the end // Get only non-missing elements. Missing elements go at the end
// of the sorted array. So, just don't copy these to sort input. // of the sorted array. So, just don't copy these to sort input.
final ArrayList<Object> src = new ArrayList<>(); final ArrayList<Object> src = new ArrayList<>();
for (int i = 0; i < (int)len; i++) { for (long i = 0; i < len; i = array.nextIndex(i)) {
if (sobj.has(i)) { if (array.has((int) i)) {
src.add(sobj.get(i)); src.add(array.getObject((int) i));
} }
} }
final Object[] sorted = sort(src.toArray(), comparefn); final Object[] sorted = sort(src.toArray(), comparefn);
for (int i = 0; i < sorted.length; i++) { for (int i = 0; i < sorted.length; i++) {
sobj.set(i, sorted[i], strict); array = array.set(i, sorted[i], strict);
} }
// delete missing elements - which are at the end of sorted array // delete missing elements - which are at the end of sorted array
for (int j = sorted.length; j < (int)len; j++) { sobj.setArray(array.delete(sorted.length, len - 1));
sobj.delete(j, strict);
}
} }
return sobj; return sobj;
@ -906,7 +904,7 @@ public final class NativeArray extends ScriptObject {
final long from = actualStart + k; final long from = actualStart + k;
if (sobj.has(from)) { if (sobj.has(from)) {
array.defineOwnProperty((int) k, sobj.get(from)); array.defineOwnProperty(ArrayIndex.getArrayIndex(k), sobj.get(from));
} }
} }
@ -1143,7 +1141,7 @@ public final class NativeArray extends ScriptObject {
@Override @Override
protected boolean forEach(final Object val, final long i) throws Throwable { protected boolean forEach(final Object val, final long i) throws Throwable {
final Object r = MAP_CALLBACK_INVOKER.invokeExact(callbackfn, thisArg, val, i, self); final Object r = MAP_CALLBACK_INVOKER.invokeExact(callbackfn, thisArg, val, i, self);
result.defineOwnProperty((int)index, r); result.defineOwnProperty(ArrayIndex.getArrayIndex(index), r);
return true; return true;
} }
@ -1172,7 +1170,7 @@ public final class NativeArray extends ScriptObject {
@Override @Override
protected boolean forEach(final Object val, final long i) throws Throwable { protected boolean forEach(final Object val, final long i) throws Throwable {
if ((boolean)FILTER_CALLBACK_INVOKER.invokeExact(callbackfn, thisArg, val, i, self)) { if ((boolean)FILTER_CALLBACK_INVOKER.invokeExact(callbackfn, thisArg, val, i, self)) {
result.defineOwnProperty((int)(to++), val); result.defineOwnProperty(ArrayIndex.getArrayIndex(to++), val);
} }
return true; return true;
} }

View File

@ -29,7 +29,6 @@ import static jdk.nashorn.internal.lookup.Lookup.MH;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.JSType.isRepresentableAsInt; import static jdk.nashorn.internal.runtime.JSType.isRepresentableAsInt;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndexNoThrow;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles;
@ -156,7 +155,7 @@ public final class NativeString extends ScriptObject {
@SuppressWarnings("unused") @SuppressWarnings("unused")
private static Object get(final Object self, final Object key) { private static Object get(final Object self, final Object key) {
final CharSequence cs = JSType.toCharSequence(self); final CharSequence cs = JSType.toCharSequence(self);
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (index >= 0 && index < cs.length()) { if (index >= 0 && index < cs.length()) {
return String.valueOf(cs.charAt(index)); return String.valueOf(cs.charAt(index));
} }
@ -191,7 +190,7 @@ public final class NativeString extends ScriptObject {
// String characters can be accessed with array-like indexing.. // String characters can be accessed with array-like indexing..
@Override @Override
public Object get(final Object key) { public Object get(final Object key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (index >= 0 && index < value.length()) { if (index >= 0 && index < value.length()) {
return String.valueOf(value.charAt(index)); return String.valueOf(value.charAt(index));
} }
@ -284,7 +283,7 @@ public final class NativeString extends ScriptObject {
@Override @Override
public boolean has(final Object key) { public boolean has(final Object key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return isValid(index) || super.has(key); return isValid(index) || super.has(key);
} }
@ -295,19 +294,19 @@ public final class NativeString extends ScriptObject {
@Override @Override
public boolean has(final long key) { public boolean has(final long key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return isValid(index) || super.has(key); return isValid(index) || super.has(key);
} }
@Override @Override
public boolean has(final double key) { public boolean has(final double key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return isValid(index) || super.has(key); return isValid(index) || super.has(key);
} }
@Override @Override
public boolean hasOwnProperty(final Object key) { public boolean hasOwnProperty(final Object key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return isValid(index) || super.hasOwnProperty(key); return isValid(index) || super.hasOwnProperty(key);
} }
@ -318,13 +317,13 @@ public final class NativeString extends ScriptObject {
@Override @Override
public boolean hasOwnProperty(final long key) { public boolean hasOwnProperty(final long key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return isValid(index) || super.hasOwnProperty(key); return isValid(index) || super.hasOwnProperty(key);
} }
@Override @Override
public boolean hasOwnProperty(final double key) { public boolean hasOwnProperty(final double key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return isValid(index) || super.hasOwnProperty(key); return isValid(index) || super.hasOwnProperty(key);
} }
@ -335,19 +334,19 @@ public final class NativeString extends ScriptObject {
@Override @Override
public boolean delete(final long key, final boolean strict) { public boolean delete(final long key, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return checkDeleteIndex(index, strict)? false : super.delete(key, strict); return checkDeleteIndex(index, strict)? false : super.delete(key, strict);
} }
@Override @Override
public boolean delete(final double key, final boolean strict) { public boolean delete(final double key, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return checkDeleteIndex(index, strict)? false : super.delete(key, strict); return checkDeleteIndex(index, strict)? false : super.delete(key, strict);
} }
@Override @Override
public boolean delete(final Object key, final boolean strict) { public boolean delete(final Object key, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
return checkDeleteIndex(index, strict)? false : super.delete(key, strict); return checkDeleteIndex(index, strict)? false : super.delete(key, strict);
} }
@ -364,7 +363,7 @@ public final class NativeString extends ScriptObject {
@Override @Override
public Object getOwnPropertyDescriptor(final String key) { public Object getOwnPropertyDescriptor(final String key) {
final int index = ArrayIndex.getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (index >= 0 && index < value.length()) { if (index >= 0 && index < value.length()) {
final Global global = Global.instance(); final Global global = Global.instance();
return global.newDataDescriptor(String.valueOf(value.charAt(index)), false, true, false); return global.newDataDescriptor(String.valueOf(value.charAt(index)), false, true, false);

View File

@ -54,10 +54,9 @@ public class JSONParser extends AbstractParser {
* Constructor * Constructor
* @param source the source * @param source the source
* @param errors the error manager * @param errors the error manager
* @param strict are we in strict mode
*/ */
public JSONParser(final Source source, final ErrorManager errors, final boolean strict) { public JSONParser(final Source source, final ErrorManager errors) {
super(source, errors, strict); super(source, errors, false);
} }
/** /**
@ -135,6 +134,7 @@ public class JSONParser extends AbstractParser {
return ch == '\"'; return ch == '\"';
} }
// ECMA 15.12.1.1 The JSON Lexical Grammar - JSONWhiteSpace
@Override @Override
protected boolean isWhitespace(final char ch) { protected boolean isWhitespace(final char ch) {
return Lexer.isJsonWhitespace(ch); return Lexer.isJsonWhitespace(ch);
@ -144,6 +144,99 @@ public class JSONParser extends AbstractParser {
protected boolean isEOL(final char ch) { protected boolean isEOL(final char ch) {
return Lexer.isJsonEOL(ch); return Lexer.isJsonEOL(ch);
} }
// ECMA 15.12.1.1 The JSON Lexical Grammar - JSONNumber
@Override
protected void scanNumber() {
// Record beginning of number.
final int start = position;
// Assume value is a decimal.
TokenType type = TokenType.DECIMAL;
// floating point can't start with a "." with no leading digit before
if (ch0 == '.') {
error(Lexer.message("json.invalid.number"), STRING, position, limit);
}
// First digit of number.
int digit = convertDigit(ch0, 10);
// skip first digit
skip(1);
if (digit != 0) {
// Skip over remaining digits.
while (convertDigit(ch0, 10) != -1) {
skip(1);
}
}
if (ch0 == '.' || ch0 == 'E' || ch0 == 'e') {
// Must be a double.
if (ch0 == '.') {
// Skip period.
skip(1);
boolean mantissa = false;
// Skip mantissa.
while (convertDigit(ch0, 10) != -1) {
mantissa = true;
skip(1);
}
if (! mantissa) {
// no digit after "."
error(Lexer.message("json.invalid.number"), STRING, position, limit);
}
}
// Detect exponent.
if (ch0 == 'E' || ch0 == 'e') {
// Skip E.
skip(1);
// Detect and skip exponent sign.
if (ch0 == '+' || ch0 == '-') {
skip(1);
}
boolean exponent = false;
// Skip exponent.
while (convertDigit(ch0, 10) != -1) {
exponent = true;
skip(1);
}
if (! exponent) {
// no digit after "E"
error(Lexer.message("json.invalid.number"), STRING, position, limit);
}
}
type = TokenType.FLOATING;
}
// Add number token.
add(type, start);
}
// ECMA 15.12.1.1 The JSON Lexical Grammar - JSONEscapeCharacter
@Override
protected boolean isEscapeCharacter(final char ch) {
switch (ch) {
case '"':
case '/':
case '\\':
case 'b':
case 'f':
case 'n':
case 'r':
case 't':
// could be unicode escape
case 'u':
return true;
default:
return false;
}
}
}; };
k = -1; k = -1;

View File

@ -648,7 +648,7 @@ public class Lexer extends Scanner {
* *
* @return The converted digit or -1 if invalid. * @return The converted digit or -1 if invalid.
*/ */
private static int convertDigit(final char ch, final int base) { protected static int convertDigit(final char ch, final int base) {
int digit; int digit;
if ('0' <= ch && ch <= '9') { if ('0' <= ch && ch <= '9') {
@ -908,7 +908,7 @@ public class Lexer extends Scanner {
/** /**
* Scan over a string literal. * Scan over a string literal.
*/ */
private void scanString(final boolean add) { protected void scanString(final boolean add) {
// Type of string. // Type of string.
TokenType type = STRING; TokenType type = STRING;
// Record starting quote. // Record starting quote.
@ -925,6 +925,9 @@ public class Lexer extends Scanner {
if (ch0 == '\\') { if (ch0 == '\\') {
type = ESCSTRING; type = ESCSTRING;
skip(1); skip(1);
if (! isEscapeCharacter(ch0)) {
error(Lexer.message("invalid.escape.char"), STRING, position, limit);
}
if (isEOL(ch0)) { if (isEOL(ch0)) {
// Multiline string literal // Multiline string literal
skipEOL(false); skipEOL(false);
@ -978,6 +981,16 @@ public class Lexer extends Scanner {
} }
} }
/**
* Is the given character a valid escape char after "\" ?
*
* @param ch character to be checked
* @return if the given character is valid after "\"
*/
protected boolean isEscapeCharacter(final char ch) {
return true;
}
/** /**
* Convert string to number. * Convert string to number.
* *
@ -1024,7 +1037,7 @@ public class Lexer extends Scanner {
/** /**
* Scan a number. * Scan a number.
*/ */
private void scanNumber() { protected void scanNumber() {
// Record beginning of number. // Record beginning of number.
final int start = position; final int start = position;
// Assume value is a decimal. // Assume value is a decimal.
@ -1583,7 +1596,7 @@ public class Lexer extends Scanner {
return null; return null;
} }
private static String message(final String msgId, final String... args) { protected static String message(final String msgId, final String... args) {
return ECMAErrors.getMessage("lexer.error." + msgId, args); return ECMAErrors.getMessage("lexer.error." + msgId, args);
} }

View File

@ -496,12 +496,13 @@ public final class Context {
* expression, after creating a new global scope. * expression, after creating a new global scope.
* *
* @param from source expression for script * @param from source expression for script
* @param args (optional) arguments to be passed to the loaded script
* *
* @return return value for load call (undefined) * @return return value for load call (undefined)
* *
* @throws IOException if source cannot be found or loaded * @throws IOException if source cannot be found or loaded
*/ */
public Object loadWithNewGlobal(final Object from) throws IOException { public Object loadWithNewGlobal(final Object from, final Object...args) throws IOException {
final ScriptObject oldGlobal = getGlobalTrusted(); final ScriptObject oldGlobal = getGlobalTrusted();
final ScriptObject newGlobal = AccessController.doPrivileged(new PrivilegedAction<ScriptObject>() { final ScriptObject newGlobal = AccessController.doPrivileged(new PrivilegedAction<ScriptObject>() {
@Override @Override
@ -518,6 +519,9 @@ public final class Context {
}); });
setGlobalTrusted(newGlobal); setGlobalTrusted(newGlobal);
final Object[] wrapped = args == null? ScriptRuntime.EMPTY_ARRAY : ScriptObjectMirror.wrapArray(args, newGlobal);
newGlobal.put("arguments", ((GlobalObject)newGlobal).wrapAsObject(wrapped));
try { try {
return ScriptObjectMirror.wrap(load(newGlobal, from), newGlobal); return ScriptObjectMirror.wrap(load(newGlobal, from), newGlobal);
} finally { } finally {

View File

@ -25,9 +25,6 @@
package jdk.nashorn.internal.runtime; package jdk.nashorn.internal.runtime;
import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndexNoThrow;
import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;
import java.util.Iterator; import java.util.Iterator;
import jdk.nashorn.internal.ir.LiteralNode; import jdk.nashorn.internal.ir.LiteralNode;
@ -37,6 +34,7 @@ import jdk.nashorn.internal.ir.PropertyNode;
import jdk.nashorn.internal.ir.UnaryNode; import jdk.nashorn.internal.ir.UnaryNode;
import jdk.nashorn.internal.parser.JSONParser; import jdk.nashorn.internal.parser.JSONParser;
import jdk.nashorn.internal.parser.TokenType; import jdk.nashorn.internal.parser.TokenType;
import jdk.nashorn.internal.runtime.arrays.ArrayIndex;
import jdk.nashorn.internal.runtime.linker.Bootstrap; import jdk.nashorn.internal.runtime.linker.Bootstrap;
/** /**
@ -66,13 +64,9 @@ public final class JSONFunctions {
*/ */
public static Object parse(final Object text, final Object reviver) { public static Object parse(final Object text, final Object reviver) {
final String str = JSType.toString(text); final String str = JSType.toString(text);
final Context context = Context.getContextTrusted();
final JSONParser parser = new JSONParser( final JSONParser parser = new JSONParser(
new Source("<json>", str), new Source("<json>", str),
new Context.ThrowErrorManager(), new Context.ThrowErrorManager());
(context != null) ?
context.getEnv()._strict :
false);
Node node; Node node;
@ -192,8 +186,8 @@ public final class JSONFunctions {
// add a new property if does not exist already, or else set old property // 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 boolean strict) {
final int index = getArrayIndexNoThrow(name); final int index = ArrayIndex.getArrayIndex(name);
if (isValidArrayIndex(index)) { if (ArrayIndex.isValidArrayIndex(index)) {
// array index key // array index key
sobj.defineOwnProperty(index, value); sobj.defineOwnProperty(index, value);
} else if (sobj.getMap().findProperty(name) != null) { } else if (sobj.getMap().findProperty(name) != null) {

View File

@ -37,8 +37,6 @@ import static jdk.nashorn.internal.runtime.PropertyDescriptor.SET;
import static jdk.nashorn.internal.runtime.PropertyDescriptor.VALUE; import static jdk.nashorn.internal.runtime.PropertyDescriptor.VALUE;
import static jdk.nashorn.internal.runtime.PropertyDescriptor.WRITABLE; import static jdk.nashorn.internal.runtime.PropertyDescriptor.WRITABLE;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndexNoThrow;
import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles;
@ -65,6 +63,7 @@ import jdk.nashorn.internal.lookup.MethodHandleFactory;
import jdk.nashorn.internal.objects.AccessorPropertyDescriptor; import jdk.nashorn.internal.objects.AccessorPropertyDescriptor;
import jdk.nashorn.internal.objects.DataPropertyDescriptor; import jdk.nashorn.internal.objects.DataPropertyDescriptor;
import jdk.nashorn.internal.runtime.arrays.ArrayData; import jdk.nashorn.internal.runtime.arrays.ArrayData;
import jdk.nashorn.internal.runtime.arrays.ArrayIndex;
import jdk.nashorn.internal.runtime.linker.Bootstrap; import jdk.nashorn.internal.runtime.linker.Bootstrap;
import jdk.nashorn.internal.runtime.linker.LinkerCallSite; import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
@ -333,7 +332,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
return global.newDataDescriptor(getWithProperty(property), configurable, enumerable, writable); return global.newDataDescriptor(getWithProperty(property), configurable, enumerable, writable);
} }
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray(); final ArrayData array = getArray();
if (array.has(index)) { if (array.has(index)) {
@ -533,21 +532,23 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
* from any object in proto chain such as Array.prototype, Object.prototype. * from any object in proto chain such as Array.prototype, Object.prototype.
* This method directly sets a particular element value in the current object. * This method directly sets a particular element value in the current object.
* *
* @param index index key for property * @param index key for property
* @param value value to define * @param value value to define
*/ */
protected final void defineOwnProperty(final int index, final Object value) { protected final void defineOwnProperty(final int index, final Object value) {
if (index >= getArray().length()) { assert ArrayIndex.isValidArrayIndex(index) : "invalid array index";
final long longIndex = ArrayIndex.toLongIndex(index);
if (longIndex >= getArray().length()) {
// make array big enough to hold.. // make array big enough to hold..
setArray(getArray().ensure(index)); setArray(getArray().ensure(longIndex));
} }
setArray(getArray().set(index, value, false)); setArray(getArray().set(index, value, false));
} }
private void checkIntegerKey(final String key) { private void checkIntegerKey(final String key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isValidArrayIndex(index)) { if (ArrayIndex.isValidArrayIndex(index)) {
final ArrayData data = getArray(); final ArrayData data = getArray();
if (data.has(index)) { if (data.has(index)) {
@ -557,7 +558,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
} }
private void removeArraySlot(final String key) { private void removeArraySlot(final String key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray(); final ArrayData array = getArray();
if (array.has(index)) { if (array.has(index)) {
@ -2238,7 +2239,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
} }
private int getInt(final int index, final String key) { private int getInt(final int index, final String key) {
if (isValidArrayIndex(index)) { if (ArrayIndex.isValidArrayIndex(index)) {
for (ScriptObject object = this; ; ) { for (ScriptObject object = this; ; ) {
final FindProperty find = object.findProperty(key, false, false, this); final FindProperty find = object.findProperty(key, false, false, this);
@ -2269,7 +2270,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public int getInt(final Object key) { public int getInt(final Object key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray(); final ArrayData array = getArray();
if (array.has(index)) { if (array.has(index)) {
@ -2281,7 +2282,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public int getInt(final double key) { public int getInt(final double key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray(); final ArrayData array = getArray();
if (array.has(index)) { if (array.has(index)) {
@ -2293,7 +2294,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public int getInt(final long key) { public int getInt(final long key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray(); final ArrayData array = getArray();
if (array.has(index)) { if (array.has(index)) {
@ -2315,7 +2316,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
} }
private long getLong(final int index, final String key) { private long getLong(final int index, final String key) {
if (isValidArrayIndex(index)) { if (ArrayIndex.isValidArrayIndex(index)) {
for (ScriptObject object = this; ; ) { for (ScriptObject object = this; ; ) {
final FindProperty find = object.findProperty(key, false, false, this); final FindProperty find = object.findProperty(key, false, false, this);
@ -2346,7 +2347,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public long getLong(final Object key) { public long getLong(final Object key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray(); final ArrayData array = getArray();
if (array.has(index)) { if (array.has(index)) {
@ -2358,7 +2359,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public long getLong(final double key) { public long getLong(final double key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray(); final ArrayData array = getArray();
if (array.has(index)) { if (array.has(index)) {
@ -2370,7 +2371,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public long getLong(final long key) { public long getLong(final long key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray(); final ArrayData array = getArray();
if (array.has(index)) { if (array.has(index)) {
@ -2392,7 +2393,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
} }
private double getDouble(final int index, final String key) { private double getDouble(final int index, final String key) {
if (isValidArrayIndex(index)) { if (ArrayIndex.isValidArrayIndex(index)) {
for (ScriptObject object = this; ; ) { for (ScriptObject object = this; ; ) {
final FindProperty find = object.findProperty(key, false, false, this); final FindProperty find = object.findProperty(key, false, false, this);
@ -2423,7 +2424,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public double getDouble(final Object key) { public double getDouble(final Object key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray(); final ArrayData array = getArray();
if (array.has(index)) { if (array.has(index)) {
@ -2435,7 +2436,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public double getDouble(final double key) { public double getDouble(final double key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray(); final ArrayData array = getArray();
if (array.has(index)) { if (array.has(index)) {
@ -2447,7 +2448,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public double getDouble(final long key) { public double getDouble(final long key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray(); final ArrayData array = getArray();
if (array.has(index)) { if (array.has(index)) {
@ -2469,7 +2470,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
} }
private Object get(final int index, final String key) { private Object get(final int index, final String key) {
if (isValidArrayIndex(index)) { if (ArrayIndex.isValidArrayIndex(index)) {
for (ScriptObject object = this; ; ) { for (ScriptObject object = this; ; ) {
final FindProperty find = object.findProperty(key, false, false, this); final FindProperty find = object.findProperty(key, false, false, this);
@ -2500,7 +2501,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public Object get(final Object key) { public Object get(final Object key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray(); final ArrayData array = getArray();
if (array.has(index)) { if (array.has(index)) {
@ -2512,7 +2513,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public Object get(final double key) { public Object get(final double key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray(); final ArrayData array = getArray();
if (array.has(index)) { if (array.has(index)) {
@ -2524,7 +2525,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public Object get(final long key) { public Object get(final long key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray(); final ArrayData array = getArray();
if (array.has(index)) { if (array.has(index)) {
@ -2640,9 +2641,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public void set(final Object key, final int value, final boolean strict) { public void set(final Object key, final int value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isValidArrayIndex(index)) { if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) { if (getArray().has(index)) {
setArray(getArray().set(index, value, strict)); setArray(getArray().set(index, value, strict));
} else { } else {
@ -2657,9 +2658,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public void set(final Object key, final long value, final boolean strict) { public void set(final Object key, final long value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isValidArrayIndex(index)) { if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) { if (getArray().has(index)) {
setArray(getArray().set(index, value, strict)); setArray(getArray().set(index, value, strict));
} else { } else {
@ -2674,9 +2675,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public void set(final Object key, final double value, final boolean strict) { public void set(final Object key, final double value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isValidArrayIndex(index)) { if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) { if (getArray().has(index)) {
setArray(getArray().set(index, value, strict)); setArray(getArray().set(index, value, strict));
} else { } else {
@ -2691,9 +2692,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public void set(final Object key, final Object value, final boolean strict) { public void set(final Object key, final Object value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isValidArrayIndex(index)) { if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) { if (getArray().has(index)) {
setArray(getArray().set(index, value, strict)); setArray(getArray().set(index, value, strict));
} else { } else {
@ -2711,9 +2712,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public void set(final double key, final int value, final boolean strict) { public void set(final double key, final int value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isValidArrayIndex(index)) { if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) { if (getArray().has(index)) {
setArray(getArray().set(index, value, strict)); setArray(getArray().set(index, value, strict));
} else { } else {
@ -2728,9 +2729,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public void set(final double key, final long value, final boolean strict) { public void set(final double key, final long value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isValidArrayIndex(index)) { if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) { if (getArray().has(index)) {
setArray(getArray().set(index, value, strict)); setArray(getArray().set(index, value, strict));
} else { } else {
@ -2745,9 +2746,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public void set(final double key, final double value, final boolean strict) { public void set(final double key, final double value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isValidArrayIndex(index)) { if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) { if (getArray().has(index)) {
setArray(getArray().set(index, value, strict)); setArray(getArray().set(index, value, strict));
} else { } else {
@ -2762,9 +2763,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public void set(final double key, final Object value, final boolean strict) { public void set(final double key, final Object value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isValidArrayIndex(index)) { if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) { if (getArray().has(index)) {
setArray(getArray().set(index, value, strict)); setArray(getArray().set(index, value, strict));
} else { } else {
@ -2779,9 +2780,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public void set(final long key, final int value, final boolean strict) { public void set(final long key, final int value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isValidArrayIndex(index)) { if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) { if (getArray().has(index)) {
setArray(getArray().set(index, value, strict)); setArray(getArray().set(index, value, strict));
} else { } else {
@ -2796,9 +2797,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public void set(final long key, final long value, final boolean strict) { public void set(final long key, final long value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isValidArrayIndex(index)) { if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) { if (getArray().has(index)) {
setArray(getArray().set(index, value, strict)); setArray(getArray().set(index, value, strict));
} else { } else {
@ -2813,9 +2814,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public void set(final long key, final double value, final boolean strict) { public void set(final long key, final double value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isValidArrayIndex(index)) { if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) { if (getArray().has(index)) {
setArray(getArray().set(index, value, strict)); setArray(getArray().set(index, value, strict));
} else { } else {
@ -2830,9 +2831,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public void set(final long key, final Object value, final boolean strict) { public void set(final long key, final Object value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isValidArrayIndex(index)) { if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) { if (getArray().has(index)) {
setArray(getArray().set(index, value, strict)); setArray(getArray().set(index, value, strict));
} else { } else {
@ -2847,9 +2848,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public void set(final int key, final int value, final boolean strict) { public void set(final int key, final int value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isValidArrayIndex(index)) { if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) { if (getArray().has(index)) {
setArray(getArray().set(index, value, strict)); setArray(getArray().set(index, value, strict));
} else { } else {
@ -2864,9 +2865,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public void set(final int key, final long value, final boolean strict) { public void set(final int key, final long value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isValidArrayIndex(index)) { if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) { if (getArray().has(index)) {
setArray(getArray().set(index, value, strict)); setArray(getArray().set(index, value, strict));
} else { } else {
@ -2881,9 +2882,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public void set(final int key, final double value, final boolean strict) { public void set(final int key, final double value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isValidArrayIndex(index)) { if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) { if (getArray().has(index)) {
setArray(getArray().set(index, value, strict)); setArray(getArray().set(index, value, strict));
} else { } else {
@ -2898,9 +2899,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public void set(final int key, final Object value, final boolean strict) { public void set(final int key, final Object value, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isValidArrayIndex(index)) { if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) { if (getArray().has(index)) {
setArray(getArray().set(index, value, strict)); setArray(getArray().set(index, value, strict));
} else { } else {
@ -2915,9 +2916,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public boolean has(final Object key) { public boolean has(final Object key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isValidArrayIndex(index)) { if (ArrayIndex.isValidArrayIndex(index)) {
for (ScriptObject self = this; self != null; self = self.getProto()) { for (ScriptObject self = this; self != null; self = self.getProto()) {
if (self.getArray().has(index)) { if (self.getArray().has(index)) {
return true; return true;
@ -2932,9 +2933,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public boolean has(final double key) { public boolean has(final double key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isValidArrayIndex(index)) { if (ArrayIndex.isValidArrayIndex(index)) {
for (ScriptObject self = this; self != null; self = self.getProto()) { for (ScriptObject self = this; self != null; self = self.getProto()) {
if (self.getArray().has(index)) { if (self.getArray().has(index)) {
return true; return true;
@ -2949,9 +2950,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public boolean has(final long key) { public boolean has(final long key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isValidArrayIndex(index)) { if (ArrayIndex.isValidArrayIndex(index)) {
for (ScriptObject self = this; self != null; self = self.getProto()) { for (ScriptObject self = this; self != null; self = self.getProto()) {
if (self.getArray().has(index)) { if (self.getArray().has(index)) {
return true; return true;
@ -2966,9 +2967,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public boolean has(final int key) { public boolean has(final int key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (isValidArrayIndex(index)) { if (ArrayIndex.isValidArrayIndex(index)) {
for (ScriptObject self = this; self != null; self = self.getProto()) { for (ScriptObject self = this; self != null; self = self.getProto()) {
if (self.getArray().has(index)) { if (self.getArray().has(index)) {
return true; return true;
@ -2983,7 +2984,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public boolean hasOwnProperty(final Object key) { public boolean hasOwnProperty(final Object key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (getArray().has(index)) { if (getArray().has(index)) {
return true; return true;
@ -2996,7 +2997,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public boolean hasOwnProperty(final int key) { public boolean hasOwnProperty(final int key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (getArray().has(index)) { if (getArray().has(index)) {
return true; return true;
@ -3009,7 +3010,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public boolean hasOwnProperty(final long key) { public boolean hasOwnProperty(final long key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (getArray().has(index)) { if (getArray().has(index)) {
return true; return true;
@ -3022,7 +3023,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public boolean hasOwnProperty(final double key) { public boolean hasOwnProperty(final double key) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
if (getArray().has(index)) { if (getArray().has(index)) {
return true; return true;
@ -3035,7 +3036,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public boolean delete(final int key, final boolean strict) { public boolean delete(final int key, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray(); final ArrayData array = getArray();
if (array.has(index)) { if (array.has(index)) {
@ -3051,7 +3052,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public boolean delete(final long key, final boolean strict) { public boolean delete(final long key, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray(); final ArrayData array = getArray();
if (array.has(index)) { if (array.has(index)) {
@ -3067,7 +3068,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public boolean delete(final double key, final boolean strict) { public boolean delete(final double key, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray(); final ArrayData array = getArray();
if (array.has(index)) { if (array.has(index)) {
@ -3083,7 +3084,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override @Override
public boolean delete(final Object key, final boolean strict) { public boolean delete(final Object key, final boolean strict) {
final int index = getArrayIndexNoThrow(key); final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray(); final ArrayData array = getArray();
if (array.has(index)) { if (array.has(index)) {

View File

@ -44,7 +44,7 @@ public final class ArrayIndex {
/** /**
* Fast conversion of non-negative integer string to long. * Fast conversion of non-negative integer string to long.
* @param key Key as a string. * @param key Key as a string.
* @return long value of string or -1. * @return long value of string or {@code -1} if string does not represent a valid index.
*/ */
private static long fromString(final String key) { private static long fromString(final String key) {
long value = 0; long value = 0;
@ -52,7 +52,7 @@ public final class ArrayIndex {
// Check for empty string or leading 0 // Check for empty string or leading 0
if (length == 0 || (length > 1 && key.charAt(0) == '0')) { if (length == 0 || (length > 1 && key.charAt(0) == '0')) {
return -1; return INVALID_ARRAY_INDEX;
} }
// Fast toNumber. // Fast toNumber.
@ -61,7 +61,7 @@ public final class ArrayIndex {
// If not a digit. // If not a digit.
if (digit < '0' || digit > '9') { if (digit < '0' || digit > '9') {
return -1; return INVALID_ARRAY_INDEX;
} }
// Insert digit. // Insert digit.
@ -69,7 +69,7 @@ public final class ArrayIndex {
// Check for overflow (need to catch before wrap around.) // Check for overflow (need to catch before wrap around.)
if (value > MAX_ARRAY_INDEX) { if (value > MAX_ARRAY_INDEX) {
return -1; return INVALID_ARRAY_INDEX;
} }
} }
@ -81,136 +81,78 @@ public final class ArrayIndex {
* routine needs to perform quickly since all keys are tested with it. * routine needs to perform quickly since all keys are tested with it.
* *
* @param key key to check for array index * @param key key to check for array index
* @return valid array index, or negative value if not valid * @return the array index, or {@code -1} if {@code key} does not represent a valid index.
* Note that negative return values other than {@code -1} are considered valid and can be converted to
* the actual index using {@link #toLongIndex(int)}.
*/ */
public static int getArrayIndexNoThrow(final Object key) { public static int getArrayIndex(final Object key) {
if (key instanceof Integer) { if (key instanceof Integer) {
return getArrayIndexNoThrow(((Integer)key).intValue()); return getArrayIndex(((Integer) key).intValue());
} else if (key instanceof Number) { } else if (key instanceof Number) {
return getArrayIndexNoThrow(((Number)key).doubleValue()); return getArrayIndex(((Number) key).doubleValue());
} else if (key instanceof String) { } else if (key instanceof String) {
return (int)fromString((String) key); return (int)fromString((String) key);
} else if (key instanceof ConsString) { } else if (key instanceof ConsString) {
return (int)fromString(key.toString()); return (int)fromString(key.toString());
} }
return -1; return INVALID_ARRAY_INDEX;
} }
/** /**
* Returns a valid array index in an int, if the object represents one * Returns a valid array index in an int, if the long represents one.
* *
* @param key key to check * @param key key to check
* @return array index for key * @return the array index, or {@code -1} if long is not a valid array index.
* @throws InvalidArrayIndexException if not a valid array index key * Note that negative return values other than {@code -1} are considered valid and can be converted to
* the actual index using {@link #toLongIndex(int)}.
*/ */
public static int getArrayIndex(final Object key) throws InvalidArrayIndexException { public static int getArrayIndex(final long key) {
final int index = getArrayIndexNoThrow(key);
if (index != -1) {
return index;
}
throw new InvalidArrayIndexException(key);
}
/**
* Returns a valid array index in an int, if the long represents one
*
* @param key key to check
* @return valid index or a negative value if long is not a valid array index
*/
public static int getArrayIndexNoThrow(final long key) {
if (key >= 0 && key <= MAX_ARRAY_INDEX) { if (key >= 0 && key <= MAX_ARRAY_INDEX) {
return (int)key; return (int)key;
} }
return -1; return INVALID_ARRAY_INDEX;
}
/**
* Returns a valid array index in an int, if the long represents one
*
* @param key key to check
* @return valid index for the long
* @throws InvalidArrayIndexException if long is not a valid array index
*/
public static int getArrayIndex(final long key) throws InvalidArrayIndexException {
final int index = getArrayIndexNoThrow(key);
if (index != -1) {
return index;
}
throw new InvalidArrayIndexException(key);
} }
/** /**
* Return a valid index for this double, if it represents one * Return a valid index for this double, if it represents one.
* *
* Doubles that aren't representable exactly as longs/ints aren't working * Doubles that aren't representable exactly as longs/ints aren't working
* array indexes, however, array[1.1] === array["1.1"] in JavaScript. * array indexes, however, array[1.1] === array["1.1"] in JavaScript.
* *
* @param key the key to check * @param key the key to check
* @return the array index this double represents or a negative value if this isn't an index * @return the array index this double represents or {@code -1} if this isn't a valid index.
* Note that negative return values other than {@code -1} are considered valid and can be converted to
* the actual index using {@link #toLongIndex(int)}.
*/ */
public static int getArrayIndexNoThrow(final double key) { public static int getArrayIndex(final double key) {
if (JSType.isRepresentableAsInt(key)) { if (JSType.isRepresentableAsInt(key)) {
final int intKey = (int)key; final int intKey = (int)key;
if (intKey >= 0) { if (intKey >= 0) {
return intKey; return intKey;
} }
} else if (JSType.isRepresentableAsLong(key)) { } else if (JSType.isRepresentableAsLong(key)) {
return getArrayIndexNoThrow((long)key); return getArrayIndex((long) key);
} }
return -1; return INVALID_ARRAY_INDEX;
} }
/** /**
* Return a valid array index for this double, if it represents one * Return a valid array index for this string, if it represents one.
*
* Doubles that aren't representable exactly as longs/ints aren't working
* array indexes, however, array[1.1] === array["1.1"] in JavaScript.
* *
* @param key the key to check * @param key the key to check
* @return the array index this double represents * @return the array index this string represents or {@code -1} if this isn't a valid index.
* @throws InvalidArrayIndexException if this isn't an array index * Note that negative return values other than {@code -1} are considered valid and can be converted to
* the actual index using {@link #toLongIndex(int)}.
*/ */
public static int getArrayIndex(final double key) throws InvalidArrayIndexException { public static int getArrayIndex(final String key) {
final int index = getArrayIndexNoThrow(key);
if (index != -1) {
return index;
}
throw new InvalidArrayIndexException(key);
}
/**
* Return a valid array index for this string, if it represents one
*
* @param key the key to check
* @return the array index this string represents or a negative value if this isn't an index
*/
public static int getArrayIndexNoThrow(final String key) {
return (int)fromString(key); return (int)fromString(key);
} }
/**
* Return a valid array index for this string, if it represents one
*
* @param key the key to check
* @return the array index this string represents
* @throws InvalidArrayIndexException if the string isn't an array index
*/
public static int getArrayIndex(final String key) throws InvalidArrayIndexException {
final int index = getArrayIndexNoThrow(key);
if (index != -1) {
return index;
}
throw new InvalidArrayIndexException(key);
}
/** /**
* Check whether an index is valid as an array index. This check only tests if * Check whether an index is valid as an array index. This check only tests if
* it is the special "invalid array index" type, not if it is e.g. less than zero * it is the special "invalid array index" type, not if it is e.g. less than zero
@ -226,7 +168,7 @@ public final class ArrayIndex {
/** /**
* Convert an index to a long value. This basically amounts to ANDing it * Convert an index to a long value. This basically amounts to ANDing it
* with {@link JSType#MAX_UINT}, as the maximum array index in JavaScript * with {@link JSType#MAX_UINT}, as the maximum array index in JavaScript
* is 0xffffffff * is 0xfffffffe
* *
* @param index index to convert to long form * @param index index to convert to long form
* @return index as uint32 in a long * @return index as uint32 in a long
@ -236,14 +178,14 @@ public final class ArrayIndex {
} }
/** /**
* Check whether a key string can be used as a valid numeric array index in * Check whether a key string represents a valid array index in JavaScript and is small enough
* JavaScript * to fit into a positive int.
* *
* @param key the key * @param key the key
* @return true if key works as a valid numeric array index * @return true if key works as a valid int array index
*/ */
public static boolean isIndexKey(final String key) { public static boolean isIntArrayIndex(final String key) {
return ArrayIndex.getArrayIndexNoThrow(key) >= 0; return getArrayIndex(key) >= 0;
} }
} }

View File

@ -61,13 +61,15 @@ class SparseArrayData extends ArrayData {
@Override @Override
public Object[] asObjectArray() { public Object[] asObjectArray() {
final Object[] objArray = new Object[Math.min((int) length(), Integer.MAX_VALUE)]; final int length = (int) Math.min(length(), Integer.MAX_VALUE);
final int underlyingLength = (int) Math.min(length, underlying.length());
final Object[] objArray = new Object[length];
for (int i = 0; i < underlying.length(); i++) { for (int i = 0; i < underlyingLength; i++) {
objArray[i] = underlying.getObject(i); objArray[i] = underlying.getObject(i);
} }
Arrays.fill(objArray, (int) underlying.length(), objArray.length, ScriptRuntime.UNDEFINED); Arrays.fill(objArray, underlyingLength, length, ScriptRuntime.UNDEFINED);
for (final Map.Entry<Long, Object> entry : sparseMap.entrySet()) { for (final Map.Entry<Long, Object> entry : sparseMap.entrySet()) {
final long key = entry.getKey(); final long key = entry.getKey();

View File

@ -28,6 +28,8 @@ lexer.error.missing.close.quote=Missing close quote
lexer.error.invalid.hex=Invalid hex digit lexer.error.invalid.hex=Invalid hex digit
lexer.error.invalid.octal=Invalid octal digit lexer.error.invalid.octal=Invalid octal digit
lexer.error.strict.no.octal=cannot use octal escapes in strict mode lexer.error.strict.no.octal=cannot use octal escapes in strict mode
lexer.error.json.invalid.number=Invalid JSON number format
lexer.error.invalid.escape.char=Invalid escape character
lexer.error.illegal.identifier.character=Illegal character in identifier lexer.error.illegal.identifier.character=Illegal character in identifier
parser.error.illegal.continue.stmt=Illegal continue statement parser.error.illegal.continue.stmt=Illegal continue statement
@ -127,6 +129,7 @@ type.error.method.not.constructor=Java method {0} can't be used as a constructor
type.error.env.not.object=$ENV must be an Object. type.error.env.not.object=$ENV must be an Object.
type.error.unsupported.java.to.type=Unsupported Java.to target type {0}. type.error.unsupported.java.to.type=Unsupported Java.to target type {0}.
range.error.inappropriate.array.length=inappropriate array length: {0} range.error.inappropriate.array.length=inappropriate array length: {0}
range.error.inappropriate.array.buffer.length=inappropriate array buffer length: {0}
range.error.invalid.fraction.digits=fractionDigits argument to {0} must be in [0, 20] range.error.invalid.fraction.digits=fractionDigits argument to {0} must be in [0, 20]
range.error.invalid.precision=precision argument toPrecision() must be in [1, 21] range.error.invalid.precision=precision argument toPrecision() must be in [1, 21]
range.error.invalid.radix=radix argument must be in [2, 36] range.error.invalid.radix=radix argument must be in [2, 36]

View File

@ -0,0 +1,114 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
function bench(name, func) {
var start = Date.now();
for (var iter = 0; iter < 5e6; iter++) {
func();
}
print((Date.now() - start) + "\t" + name);
}
bench("[]", function() {
[];
[];
[];
});
bench("[1, 2, 3]", function() {
[1, 2, 3];
[1, 2, 3];
[1, 2, 3];
});
bench("[1 .. 20]", function() {
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
});
bench("new Array()", function() {
new Array();
new Array();
new Array();
});
bench("new Array(1, 2, 3)", function() {
new Array(1, 2, 3);
new Array(1, 2, 3);
new Array(1, 2, 3);
});
bench("new Array(10)", function() {
new Array(10);
new Array(10);
new Array(10);
});
var array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
bench("get", function() {
array[0];
array[3];
array[6];
});
bench("set", function() {
array[0] = 0;
array[3] = 3;
array[6] = 6;
});
var all = function(e) { return true; };
var none = function(e) { return false; };
bench("filter all", function() {
array.filter(all);
});
bench("filter none", function() {
array.filter(none);
});
var up = function(a, b) { return a > b ? 1 : -1; };
var down = function(a, b) { return a < b ? 1 : -1; };
bench("sort up", function() {
[1, 2, 3, 4].sort(up);
});
bench("sort down", function() {
[1, 2, 3, 4].sort(down);
});

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* JDK-8012291: NativeArray is inconsistent in using long for length and index in some places and int for the same in other places
*
* @test
* @run
*/
// Make sure JSON parser correctly handles large array keys
var obj = JSON.parse('{"4294967294": 1}');
print(obj[4294967294]);
// Make sure Array.prototype.sort handles large index correctly
obj.length = 4294967295;
Array.prototype.sort.call(obj);
print(obj[0]);
print(obj[4294967294]);
print(obj.length);
var arr = [];
arr[4294967294] = 1;
try {
new Int32Array(arr);
} catch (e) {
print(e);
}

View File

@ -0,0 +1,5 @@
1
1
undefined
4294967295
RangeError: inappropriate array buffer length: 4294967295

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* JDK-8015346: JSON parsing issues with escaped strings, octal, decimal numbers *
* @test
* @run
*/
function checkJSON(str) {
try {
JSON.parse(str);
fail("should have thrown SyntaxError for JSON.parse on " + str);
} catch (e) {
if (! (e instanceof SyntaxError)) {
fail("Expected SyntaxError, but got " + e);
}
}
}
// invalid escape in a string
checkJSON('"\\a"')
// invalid floating point number patterns
checkJSON("1.")
checkJSON(".8")
checkJSON("2.3e+")
checkJSON("0.3E+")
// octal, hexadecimal not allowed
checkJSON("08")
checkJSON("06")
checkJSON('0x3')

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* JDK-8015357: a = []; a[0x7fffffff]=1; a.sort()[0] should evaluate to 1 instead of undefined
*
* @test
* @run
*/
var a = [];
a[0x7fffffff]=1;
if (a.sort()[0] != 1) {
fail("a.sort()[0] != 1");
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* JDK-8015892.js : use before definition with valid declaration that turns into
* local var must be "canBeUndefined"
*
* @test
* @run
*/
function doIt() {
if (something) {
x = x.obj;
} else {
var x = "x";
}
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* JDK-8016239: loadWithNewGlobal should support user supplied arguments from the caller
*
* @test
* @run
*/
var jmap = new java.util.HashMap();
jmap.put("foo", "bar");
loadWithNewGlobal({
name: "<code>",
script:
" print(arguments[0]); "+
" print(arguments[1]); " +
" print(arguments[2].foo); " +
" print(arguments[3])"
},
"hello", 23, { foo: 33}, jmap
);

View File

@ -0,0 +1,4 @@
hello
23
33
{foo=bar}