static bool ProtoSetter(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); HandleValue thisv = args.thisv(); if (thisv.isNullOrUndefined()) { ReportIncompatible(cx, args); return false; } if (thisv.isPrimitive()) { // Mutating a boxed primitive's [[Prototype]] has no side effects. args.rval().setUndefined(); return true; } if (!cx->runningWithTrustedPrincipals()) ++sSetProtoCalled; Rooted<JSObject*> obj(cx, &args.thisv().toObject()); /* Do nothing if __proto__ isn't being set to an object or null. */ if (args.length() == 0 || !args[0].isObjectOrNull()) { args.rval().setUndefined(); return true; } Rooted<JSObject*> newProto(cx, args[0].toObjectOrNull()); if (!SetPrototype(cx, obj, newProto)) return false; args.rval().setUndefined(); return true; }
static bool ProtoGetterImpl(JSContext *cx, CallArgs args) { JS_ASSERT(TestProtoThis(args.thisv())); HandleValue thisv = args.thisv(); if (thisv.isPrimitive() && !BoxNonStrictThis(cx, args)) return false; RootedObject obj(cx, &args.thisv().toObject()); RootedObject proto(cx); if (!JSObject::getProto(cx, obj, &proto)) return false; args.rval().setObjectOrNull(proto); return true; }
NS_IMETHODIMP nsJSIID::HasInstance(nsIXPConnectWrappedNative* wrapper, JSContext* cx, JSObject * /* unused */, HandleValue val, bool* bp, bool* _retval) { *bp = false; if (val.isPrimitive()) return NS_OK; // we have a JSObject RootedObject obj(cx, &val.toObject()); const nsIID* iid; mInfo->GetIIDShared(&iid); return xpc::HasInstance(cx, obj, iid, bp); }
static bool ProtoGetterImpl(JSContext *cx, CallArgs args) { JS_ASSERT(TestProtoGetterThis(args.thisv())); HandleValue thisv = args.thisv(); if (thisv.isPrimitive() && !BoxNonStrictThis(cx, args)) return false; unsigned dummy; RootedObject obj(cx, &args.thisv().toObject()); RootedId nid(cx, NameToId(cx->names().proto)); RootedValue v(cx); if (!CheckAccess(cx, obj, nid, JSACC_PROTO, &v, &dummy)) return false; args.rval().set(v); return true; }
static bool ProtoGetter(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); HandleValue thisv = args.thisv(); if (thisv.isNullOrUndefined()) { ReportIncompatible(cx, args); return false; } if (thisv.isPrimitive() && !BoxNonStrictThis(cx, args)) return false; RootedObject obj(cx, &args.thisv().toObject()); RootedObject proto(cx); if (!GetPrototype(cx, obj, &proto)) return false; args.rval().setObjectOrNull(proto); return true; }
static bool ProtoSetter(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); // Do this here, rather than after the this-check so even likely-buggy // use of the __proto__ setter on unacceptable values, where no subsequent // use occurs on an acceptable value, will trigger a warning. RootedObject callee(cx, &args.callee()); if (!GlobalObject::warnOnceAboutPrototypeMutation(cx, callee)) return false; HandleValue thisv = args.thisv(); if (thisv.isNullOrUndefined()) { ReportIncompatible(cx, args); return false; } if (thisv.isPrimitive()) { // Mutating a boxed primitive's [[Prototype]] has no side effects. args.rval().setUndefined(); return true; } if (!cx->runningWithTrustedPrincipals()) ++sSetProtoCalled; Rooted<JSObject*> obj(cx, &args.thisv().toObject()); /* Do nothing if __proto__ isn't being set to an object or null. */ if (args.length() == 0 || !args[0].isObjectOrNull()) { args.rval().setUndefined(); return true; } Rooted<JSObject*> newProto(cx, args[0].toObjectOrNull()); if (!SetPrototype(cx, obj, newProto)) return false; args.rval().setUndefined(); return true; }
static bool ProtoSetterImpl(JSContext *cx, CallArgs args) { JS_ASSERT(TestProtoThis(args.thisv())); HandleValue thisv = args.thisv(); if (thisv.isPrimitive()) { JS_ASSERT(!thisv.isNullOrUndefined()); // Mutating a boxed primitive's [[Prototype]] has no side effects. args.rval().setUndefined(); return true; } if (!cx->runningWithTrustedPrincipals()) ++sSetProtoCalled; Rooted<JSObject*> obj(cx, &args.thisv().toObject()); /* Do nothing if __proto__ isn't being set to an object or null. */ if (args.length() == 0 || !args[0].isObjectOrNull()) { args.rval().setUndefined(); return true; } Rooted<JSObject*> newProto(cx, args[0].toObjectOrNull()); bool success; if (!JSObject::setProto(cx, obj, newProto, &success)) return false; if (!success) { js_ReportValueError(cx, JSMSG_SETPROTOTYPEOF_FAIL, JSDVG_IGNORE_STACK, thisv, js::NullPtr()); return false; } args.rval().setUndefined(); return true; }
static bool ProtoSetterImpl(JSContext *cx, CallArgs args) { JS_ASSERT(TestProtoSetterThis(args.thisv())); HandleValue thisv = args.thisv(); if (thisv.isPrimitive()) { JS_ASSERT(!thisv.isNullOrUndefined()); // Mutating a boxed primitive's [[Prototype]] has no side effects. args.rval().setUndefined(); return true; } if (!cx->runningWithTrustedPrincipals()) ++sSetProtoCalled; Rooted<JSObject*> obj(cx, &args.thisv().toObject()); /* ES5 8.6.2 forbids changing [[Prototype]] if not [[Extensible]]. */ bool extensible; if (!JSObject::isExtensible(cx, obj, &extensible)) return false; if (!extensible) { obj->reportNotExtensible(cx); return false; } /* * Disallow mutating the [[Prototype]] of a proxy that wasn't simply * wrapping some other object. Also disallow it on ArrayBuffer objects, * which due to their complicated delegate-object shenanigans can't easily * have a mutable [[Prototype]]. */ if (obj->is<ProxyObject>() || obj->is<ArrayBufferObject>()) { JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_INCOMPATIBLE_PROTO, "Object", "__proto__ setter", obj->is<ProxyObject>() ? "Proxy" : "ArrayBuffer"); return false; } /* Do nothing if __proto__ isn't being set to an object or null. */ if (args.length() == 0 || !args[0].isObjectOrNull()) { args.rval().setUndefined(); return true; } Rooted<JSObject*> newProto(cx, args[0].toObjectOrNull()); unsigned dummy; RootedId nid(cx, NameToId(cx->names().proto)); RootedValue v(cx); if (!CheckAccess(cx, obj, nid, JSAccessMode(JSACC_PROTO | JSACC_WRITE), &v, &dummy)) return false; if (!SetClassAndProto(cx, obj, obj->getClass(), newProto, true)) return false; args.rval().setUndefined(); return true; }