package org.dynjs.runtime; import org.dynjs.exception.ThrowException; public class Arguments extends DynObject { private JSObject map; public Arguments(GlobalContext globalContext) { super(globalContext); setClassName("Arguments"); this.map = new DynObject(globalContext); } public void setParameterMap(JSObject map) { this.map = map; } public JSObject getParameterMap() { return this.map; } @Override public Object get(ExecutionContext context, String name) { // 10.6 [[Get]] Object d = this.map.getOwnProperty(context, name); if (d == Types.UNDEFINED) { Object v = super.get(context, name); if (name.equals("caller") && (v instanceof JSFunction) && ((JSFunction) v).isStrict()) { throw new ThrowException(context, context.createTypeError("may not reference 'caller'")); } return v; } return this.map.get(context, name); } @Override public Object getOwnProperty(ExecutionContext context, String name, boolean dupe) { // Always dupe here since we call .setValue on the returned property // 10.6 [[GetOwnProperty]] Object d = super.getOwnProperty(context, name, true); if (d == Types.UNDEFINED) { return d; } Object isMapped = this.map.getOwnProperty(context, name, true); if (isMapped != Types.UNDEFINED) { PropertyDescriptor desc = (PropertyDescriptor) d; desc.setValue(this.map.get(context, name)); } return d; } @Override public boolean defineOwnProperty(ExecutionContext context, String name, PropertyDescriptor desc, boolean shouldThrow) { // 10.6 [[DefineOwnProperty]] boolean allowed = super.defineOwnProperty(context, name, desc, false); if (!allowed) { return reject(context, shouldThrow); } if (this.map.getOwnProperty(context, name) != Types.UNDEFINED) { if (desc.isAccessorDescriptor()) { this.map.delete(context, name, false); } else { if (desc.hasValue()) { this.map.put(context, name, desc.getValue(), shouldThrow); } if (desc.hasWritable() && !desc.isWritable()) { this.map.delete(context, name, false); } } } return true; } @Override public boolean delete(ExecutionContext context, String name, boolean shouldThrow) { // 10.6 [[Delete]] boolean result = super.delete(context, name, shouldThrow); if (result && (this.map.getOwnProperty(context, name) != Types.UNDEFINED)) { this.map.delete(context, name, false); } return result; } public String toString() { return "[Arguments: length=" + get(null, "length") + "]"; } }