static JSBool StrictArgSetter(JSContext *cx, HandleObject obj, HandleId id, JSBool strict, MutableHandleValue vp) { if (!obj->isStrictArguments()) 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 */ Rooted<StrictArgumentsObject*> argsobj(cx, &obj->asStrictArguments()); if (JSID_IS_INT(id)) { unsigned arg = unsigned(JSID_TO_INT(id)); if (arg < argsobj->initialLength()) { argsobj->setElement(arg, vp); return true; } } else { JS_ASSERT(JSID_IS_ATOM(id, cx->names().length)); } /* * 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. */ RootedValue value(cx); return baseops::DeleteGeneric(cx, argsobj, id, &value, strict) && baseops::DefineGeneric(cx, argsobj, id, vp, NULL, NULL, attrs); }
static JSBool StrictArgSetter(JSContext *cx, HandleObject obj, HandleId id, JSBool strict, Value *vp) { if (!obj->isStrictArguments()) return true; Rooted<StrictArgumentsObject*> argsobj(cx, &obj->asStrictArguments()); if (JSID_IS_INT(id)) { unsigned arg = unsigned(JSID_TO_INT(id)); if (arg < argsobj->initialLength()) { argsobj->setElement(arg, *vp); return true; } } else { JS_ASSERT(JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)); } /* * For simplicity we use delete/set 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. */ RootedValue value(cx); return baseops::DeleteGeneric(cx, argsobj, id, value.address(), strict) && baseops::SetPropertyHelper(cx, argsobj, id, 0, vp, strict); }
static JSBool strictargs_resolve(JSContext *cx, HandleObject obj, HandleId id, unsigned flags, JSObject **objp) { *objp = NULL; Rooted<StrictArgumentsObject*> argsobj(cx, &obj->asStrictArguments()); unsigned attrs = JSPROP_SHARED | JSPROP_SHADOWABLE; PropertyOp getter = StrictArgGetter; StrictPropertyOp setter = StrictArgSetter; 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) && !JSID_IS_ATOM(id, cx->runtime->atomState.callerAtom)) { return true; } attrs = JSPROP_PERMANENT | JSPROP_GETTER | JSPROP_SETTER | JSPROP_SHARED; getter = CastAsPropertyOp(argsobj->global().getThrowTypeError()); setter = CastAsStrictPropertyOp(argsobj->global().getThrowTypeError()); } Value undef = UndefinedValue(); if (!baseops::DefineProperty(cx, argsobj, id, &undef, getter, setter, attrs)) return false; *objp = argsobj; return true; }
static JSBool StrictArgGetter(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp) { if (!obj->isStrictArguments()) return true; StrictArgumentsObject &argsobj = obj->asStrictArguments(); 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 { JS_ASSERT(JSID_IS_ATOM(id, cx->names().length)); if (!argsobj.hasOverriddenLength()) vp.setInt32(argsobj.initialLength()); } return true; }
static JSBool strictargs_resolve(JSContext *cx, HandleObject obj, HandleId id, unsigned flags, MutableHandleObject objp) { objp.set(NULL); Rooted<StrictArgumentsObject*> argsobj(cx, &obj->asStrictArguments()); unsigned attrs = JSPROP_SHARED | JSPROP_SHADOWABLE; PropertyOp getter = StrictArgGetter; StrictPropertyOp setter = StrictArgSetter; 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) && !JSID_IS_ATOM(id, cx->names().caller)) return true; attrs = JSPROP_PERMANENT | JSPROP_GETTER | JSPROP_SETTER | JSPROP_SHARED; getter = CastAsPropertyOp(argsobj->global().getThrowTypeError()); setter = CastAsStrictPropertyOp(argsobj->global().getThrowTypeError()); } RootedValue undef(cx, UndefinedValue()); if (!baseops::DefineGeneric(cx, argsobj, id, undef, getter, setter, attrs)) return false; objp.set(argsobj); return true; }
static JSBool strictargs_enumerate(JSContext *cx, HandleObject obj) { Rooted<StrictArgumentsObject*> argsobj(cx, &obj->asStrictArguments()); /* * Trigger reflection in strictargs_resolve using a series of * js_LookupProperty calls. */ RootedObject pobj(cx); RootedShape prop(cx); RootedId id(cx); // length id = NameToId(cx->names().length); if (!baseops::LookupProperty(cx, argsobj, id, &pobj, &prop)) return false; // callee id = NameToId(cx->names().callee); if (!baseops::LookupProperty(cx, argsobj, id, &pobj, &prop)) return false; // caller id = NameToId(cx->names().caller); if (!baseops::LookupProperty(cx, argsobj, id, &pobj, &prop)) return false; for (uint32_t i = 0, argc = argsobj->initialLength(); i < argc; i++) { id = INT_TO_JSID(i); if (!baseops::LookupProperty(cx, argsobj, id, &pobj, &prop)) return false; } return true; }
static JSBool strictargs_enumerate(JSContext *cx, HandleObject obj) { RootedVar<StrictArgumentsObject*> argsobj(cx, &obj->asStrictArguments()); /* * Trigger reflection in strictargs_resolve using a series of * js_LookupProperty calls. */ JSObject *pobj; JSProperty *prop; RootedVarId id(cx); // length id = NameToId(cx->runtime->atomState.lengthAtom); if (!baseops::LookupProperty(cx, argsobj, id, &pobj, &prop)) return false; // callee id = NameToId(cx->runtime->atomState.calleeAtom); if (!baseops::LookupProperty(cx, argsobj, id, &pobj, &prop)) return false; // caller id = NameToId(cx->runtime->atomState.callerAtom); if (!baseops::LookupProperty(cx, argsobj, id, &pobj, &prop)) return false; for (uint32_t i = 0, argc = argsobj->initialLength(); i < argc; i++) { id = INT_TO_JSID(i); if (!baseops::LookupProperty(cx, argsobj, id, &pobj, &prop)) return false; } return true; }