package jdk.nashorn.internal.objects;
import static jdk.nashorn.internal.lookup.Lookup.MH;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.Arrays;
import jdk.nashorn.internal.runtime.AccessorProperty;
import jdk.nashorn.internal.runtime.Property;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
public final class NativeStrictArguments extends ScriptObject {
private static final MethodHandle G$LENGTH = findOwnMH("G$length", Object.class, Object.class);
private static final MethodHandle S$LENGTH = findOwnMH("S$length", void.class, Object.class, Object.class);
private static final PropertyMap map$;
static {
final ArrayList<Property> properties = new ArrayList<>(1);
properties.add(AccessorProperty.create("length", Property.NOT_ENUMERABLE, G$LENGTH, S$LENGTH));
PropertyMap map = PropertyMap.newMap(properties);
final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE;
map = map.addPropertyNoHistory(map.newUserAccessors("caller", flags));
map = map.addPropertyNoHistory(map.newUserAccessors("callee", flags));
map$ = map;
}
static PropertyMap getInitialMap() {
return map$;
}
private Object length;
private final Object[] namedArgs;
NativeStrictArguments(final Object[] values, final int numParams,final ScriptObject proto, final PropertyMap map) {
super(proto, map);
setIsArguments();
final ScriptFunction func = Global.instance().getTypeErrorThrower();
initUserAccessors("caller", func, func);
initUserAccessors("callee", func, func);
setArray(ArrayData.allocate(values));
this.length = values.length;
this.namedArgs = new Object[numParams];
if (numParams > values.length) {
Arrays.fill(namedArgs, UNDEFINED);
}
System.arraycopy(values, 0, namedArgs, 0, Math.min(namedArgs.length, values.length));
}
@Override
public String getClassName() {
return "Arguments";
}
@Override
public Object getArgument(final int key) {
return (key >=0 && key < namedArgs.length) ? namedArgs[key] : UNDEFINED;
}
@Override
public void setArgument(final int key, final Object value) {
if (key >= 0 && key < namedArgs.length) {
namedArgs[key] = value;
}
}
public static Object G$length(final Object self) {
if (self instanceof NativeStrictArguments) {
return ((NativeStrictArguments)self).getArgumentsLength();
}
return 0;
}
public static void S$length(final Object self, final Object value) {
if (self instanceof NativeStrictArguments) {
((NativeStrictArguments)self).setArgumentsLength(value);
}
}
private Object getArgumentsLength() {
return length;
}
private void setArgumentsLength(final Object length) {
this.length = length;
}
private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
return MH.findStatic(MethodHandles.lookup(), NativeStrictArguments.class, name, MH.type(rtype, types));
}
}