static JSBool args_resolve(JSContext *cx, HandleObject obj, HandleId id, unsigned flags, MutableHandleObject objp) { objp.set(NULL); Rooted<NormalArgumentsObject*> argsobj(cx, &obj->asNormalArguments()); unsigned attrs = JSPROP_SHARED | JSPROP_SHADOWABLE; if (JSID_IS_INT(id)) { uint32_t arg = uint32_t(JSID_TO_INT(id)); if (arg >= argsobj->initialLength() || argsobj->isElementDeleted(arg)) return true; attrs |= JSPROP_ENUMERATE; } else if (JSID_IS_ATOM(id, cx->names().length)) { if (argsobj->hasOverriddenLength()) return true; } else { if (!JSID_IS_ATOM(id, cx->names().callee)) return true; if (argsobj->callee().isMagic(JS_OVERWRITTEN_CALLEE)) return true; } RootedValue undef(cx, UndefinedValue()); if (!baseops::DefineGeneric(cx, argsobj, id, undef, ArgGetter, ArgSetter, attrs)) return JS_FALSE; objp.set(argsobj); return true; }
static JSBool args_enumerate(JSContext *cx, HandleObject obj) { Rooted<NormalArgumentsObject*> argsobj(cx, &obj->asNormalArguments()); RootedId id(cx); /* * Trigger reflection in args_resolve using a series of js_LookupProperty * calls. */ int argc = int(argsobj->initialLength()); for (int i = -2; i != argc; i++) { id = (i == -2) ? NameToId(cx->names().length) : (i == -1) ? NameToId(cx->names().callee) : INT_TO_JSID(i); RootedObject pobj(cx); RootedShape prop(cx); if (!baseops::LookupProperty(cx, argsobj, id, &pobj, &prop)) return false; } return true; }
static JSBool ArgGetter(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp) { if (!obj->isNormalArguments()) return true; NormalArgumentsObject &argsobj = obj->asNormalArguments(); if (JSID_IS_INT(id)) { /* * arg can exceed the number of arguments if a script changed the * prototype to point to another Arguments object with a bigger argc. */ unsigned arg = unsigned(JSID_TO_INT(id)); if (arg < argsobj.initialLength() && !argsobj.isElementDeleted(arg)) vp.set(argsobj.element(arg)); } else if (JSID_IS_ATOM(id, cx->names().length)) { if (!argsobj.hasOverriddenLength()) vp.setInt32(argsobj.initialLength()); } else { JS_ASSERT(JSID_IS_ATOM(id, cx->names().callee)); if (!argsobj.callee().isMagic(JS_OVERWRITTEN_CALLEE)) vp.set(argsobj.callee()); } return true; }
static JSBool args_resolve(JSContext *cx, HandleObject obj, HandleId id, unsigned flags, JSObject **objp) { *objp = NULL; Rooted<NormalArgumentsObject*> argsobj(cx, &obj->asNormalArguments()); unsigned attrs = JSPROP_SHARED | JSPROP_SHADOWABLE; if (JSID_IS_INT(id)) { uint32_t arg = uint32_t(JSID_TO_INT(id)); if (arg >= argsobj->initialLength() || argsobj->isElementDeleted(arg)) return true; attrs |= JSPROP_ENUMERATE; } else if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) { if (argsobj->hasOverriddenLength()) return true; } else { if (!JSID_IS_ATOM(id, cx->runtime->atomState.calleeAtom)) return true; if (argsobj->callee().isMagic(JS_OVERWRITTEN_CALLEE)) return true; } Value undef = UndefinedValue(); if (!baseops::DefineProperty(cx, argsobj, id, &undef, ArgGetter, ArgSetter, attrs)) return JS_FALSE; *objp = argsobj; return true; }
static JSBool ArgGetter(JSContext *cx, HandleObject obj, HandleId id, Value *vp) { if (!obj->isNormalArguments()) return true; NormalArgumentsObject &argsobj = obj->asNormalArguments(); if (JSID_IS_INT(id)) { /* * arg can exceed the number of arguments if a script changed the * prototype to point to another Arguments object with a bigger argc. */ unsigned arg = unsigned(JSID_TO_INT(id)); if (arg < argsobj.initialLength() && !argsobj.isElementDeleted(arg)) { if (StackFrame *fp = argsobj.maybeStackFrame()) { JS_ASSERT_IF(arg < fp->numFormalArgs(), fp->script()->formalIsAliased(arg)); *vp = fp->canonicalActualArg(arg); } else { *vp = argsobj.element(arg); } } } else if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) { if (!argsobj.hasOverriddenLength()) vp->setInt32(argsobj.initialLength()); } else { JS_ASSERT(JSID_IS_ATOM(id, cx->runtime->atomState.calleeAtom)); const Value &v = argsobj.callee(); if (!v.isMagic(JS_OVERWRITTEN_CALLEE)) *vp = v; } return true; }
static JSBool ArgSetter(JSContext *cx, HandleObject obj, HandleId id, JSBool strict, MutableHandleValue vp) { if (!obj->isNormalArguments()) return true; unsigned attrs; if (!baseops::GetAttributes(cx, obj, id, &attrs)) return false; JS_ASSERT(!(attrs & JSPROP_READONLY)); attrs &= (JSPROP_ENUMERATE | JSPROP_PERMANENT); /* only valid attributes */ NormalArgumentsObject &argsobj = obj->asNormalArguments(); RootedScript script(cx, argsobj.containingScript()); if (JSID_IS_INT(id)) { unsigned arg = unsigned(JSID_TO_INT(id)); if (arg < argsobj.initialLength() && !argsobj.isElementDeleted(arg)) { argsobj.setElement(arg, vp); if (arg < script->function()->nargs) { if (!script->ensureHasTypes(cx)) return false; types::TypeScript::SetArgument(cx, script, arg, vp); } return true; } } else { JS_ASSERT(JSID_IS_ATOM(id, cx->names().length) || JSID_IS_ATOM(id, cx->names().callee)); } /* * For simplicity we use delete/define to replace the property with one * backed by the default Object getter and setter. Note that we rely on * args_delProperty to clear the corresponding reserved slot so the GC can * collect its value. Note also that we must define the property instead * of setting it in case the user has changed the prototype to an object * that has a setter for this id. */ RootedValue value(cx); return baseops::DeleteGeneric(cx, obj, id, &value, false) && baseops::DefineGeneric(cx, obj, id, vp, NULL, NULL, attrs); }
static JSBool ArgSetter(JSContext *cx, HandleObject obj, HandleId id, JSBool strict, Value *vp) { if (!obj->isNormalArguments()) return true; NormalArgumentsObject &argsobj = obj->asNormalArguments(); if (JSID_IS_INT(id)) { unsigned arg = unsigned(JSID_TO_INT(id)); if (arg < argsobj.initialLength()) { if (StackFrame *fp = argsobj.maybeStackFrame()) { JSScript *script = fp->functionScript(); JS_ASSERT(script->needsArgsObj()); if (arg < fp->numFormalArgs()) { JS_ASSERT(fp->script()->formalIsAliased(arg)); types::TypeScript::SetArgument(cx, script, arg, *vp); } fp->canonicalActualArg(arg) = *vp; return true; } } } else { JS_ASSERT(JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom) || JSID_IS_ATOM(id, cx->runtime->atomState.calleeAtom)); } /* * For simplicity we use delete/define to replace the property with one * backed by the default Object getter and setter. Note that we rely on * args_delProperty to clear the corresponding reserved slot so the GC can * collect its value. Note also that we must define the property instead * of setting it in case the user has changed the prototype to an object * that has a setter for this id. */ RootedVarValue value(cx); return baseops::DeleteGeneric(cx, obj, id, value.address(), false) && baseops::DefineProperty(cx, obj, id, vp, NULL, NULL, JSPROP_ENUMERATE); }