diff --git a/js/ipc/JavaScriptBase.h b/js/ipc/JavaScriptBase.h index 28db09b557ac..7ed41fe07311 100644 --- a/js/ipc/JavaScriptBase.h +++ b/js/ipc/JavaScriptBase.h @@ -111,6 +111,14 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base return Answer::AnswerDOMInstanceOf(objId, prototypeID, depth, rs, instanceof); } + bool AnswerIsCallable(const ObjectId &objId, bool *result) { + return Answer::AnswerIsCallable(objId, result); + } + + bool AnswerIsConstructor(const ObjectId &objId, bool *result) { + return Answer::AnswerIsConstructor(objId, result); + } + bool RecvDropObject(const ObjectId &objId) { return Answer::RecvDropObject(objId); } @@ -196,6 +204,14 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base return Base::CallDOMInstanceOf(objId, prototypeID, depth, rs, instanceof); } + bool CallIsCallable(const ObjectId &objId, bool *result) { + return Base::CallIsCallable(objId, result); + } + + bool CallIsConstructor(const ObjectId &objId, bool *result) { + return Base::CallIsConstructor(objId, result); + } + /* The following code is needed to suppress a bogus MSVC warning (C4250). */ virtual bool toObjectVariant(JSContext *cx, JSObject *obj, ObjectVariant *objVarp) { diff --git a/js/ipc/PJavaScript.ipdl b/js/ipc/PJavaScript.ipdl index 46b4dd4a9b31..9e79afa8a039 100644 --- a/js/ipc/PJavaScript.ipdl +++ b/js/ipc/PJavaScript.ipdl @@ -45,6 +45,9 @@ both: rpc InstanceOf(uint64_t objId, JSIID iid) returns (ReturnStatus rs, bool instanceof); rpc DOMInstanceOf(uint64_t objId, int prototypeID, int depth) returns (ReturnStatus rs, bool instanceof); + rpc IsCallable(uint64_t objId) returns (bool result); + rpc IsConstructor(uint64_t objId) returns (bool result); + parent: async __delete__(); }; diff --git a/js/ipc/WrapperAnswer.cpp b/js/ipc/WrapperAnswer.cpp index 4f13668d63e2..d6e93c197d83 100644 --- a/js/ipc/WrapperAnswer.cpp +++ b/js/ipc/WrapperAnswer.cpp @@ -635,6 +635,47 @@ WrapperAnswer::AnswerDOMInstanceOf(const ObjectId &objId, const int &prototypeID return ok(rs); } +bool +WrapperAnswer::AnswerIsCallable(const ObjectId &objId, bool *result) +{ + AutoSafeJSContext cx; + JSAutoRequest request(cx); + + RootedObject obj(cx, findObjectById(cx, objId)); + if (!obj) { + // This is very unfortunate, but we have no choice. + *result = false; + return true; + } + JSAutoCompartment ac(cx, obj); // Not really necessary here, but be safe. + + LOG("%s.isCallable()", ReceiverObj(objId)); + + *result = JS::IsCallable(obj); + return true; +} + +bool +WrapperAnswer::AnswerIsConstructor(const ObjectId &objId, bool *result) +{ + AutoSafeJSContext cx; + JSAutoRequest request(cx); + + RootedObject obj(cx, findObjectById(cx, objId)); + if (!obj) { + // This is very unfortunate, but we have no choice. + *result = false; + return true; + } + JSAutoCompartment ac(cx, obj); // Not really necessary here, but be safe. + + LOG("%s.isConstructor()", ReceiverObj(objId)); + + *result = JS::IsConstructor(obj); + return true; +} + + bool WrapperAnswer::RecvDropObject(const ObjectId &objId) { diff --git a/js/ipc/WrapperAnswer.h b/js/ipc/WrapperAnswer.h index e48a4962683d..3f425ce717ed 100644 --- a/js/ipc/WrapperAnswer.h +++ b/js/ipc/WrapperAnswer.h @@ -60,6 +60,9 @@ class WrapperAnswer : public virtual JavaScriptShared bool AnswerDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth, ReturnStatus *rs, bool *instanceof); + bool AnswerIsCallable(const ObjectId &objId, bool *result); + bool AnswerIsConstructor(const ObjectId &objId, bool *result); + bool RecvDropObject(const ObjectId &objId); private: diff --git a/js/ipc/WrapperOwner.cpp b/js/ipc/WrapperOwner.cpp index e808745a14de..835866ec0f81 100644 --- a/js/ipc/WrapperOwner.cpp +++ b/js/ipc/WrapperOwner.cpp @@ -663,22 +663,49 @@ CPOWProxyHandler::objectMoved(JSObject *proxy, const JSObject *old) const } bool -CPOWProxyHandler::isCallable(JSObject *obj) const +CPOWProxyHandler::isCallable(JSObject *proxy) const { - return OwnerOf(obj)->isCallable(obj); -} - -bool -CPOWProxyHandler::isConstructor(JSObject *obj) const -{ - return isCallable(obj); + WrapperOwner *parent = OwnerOf(proxy); + if (!parent->active()) + return false; + return parent->isCallable(proxy); } bool WrapperOwner::isCallable(JSObject *obj) { ObjectId objId = idOf(obj); - return !!(objId & OBJECT_IS_CALLABLE); + + bool callable = false; + if (!CallIsCallable(objId, &callable)) { + NS_WARNING("IPC isCallable() failed"); + return false; + } + + return callable; +} + +bool +CPOWProxyHandler::isConstructor(JSObject *proxy) const +{ + WrapperOwner *parent = OwnerOf(proxy); + if (!parent->active()) + return false; + return parent->isConstructor(proxy); +} + +bool +WrapperOwner::isConstructor(JSObject *obj) +{ + ObjectId objId = idOf(obj); + + bool constructor = false; + if (!CallIsConstructor(objId, &constructor)) { + NS_WARNING("IPC isConstructor() failed"); + return false; + } + + return constructor; } void diff --git a/js/ipc/WrapperOwner.h b/js/ipc/WrapperOwner.h index e263c86ec459..b70e7446d6c1 100644 --- a/js/ipc/WrapperOwner.h +++ b/js/ipc/WrapperOwner.h @@ -61,7 +61,7 @@ class WrapperOwner : public virtual JavaScriptShared bool objectClassIs(JSContext *cx, JS::HandleObject obj, js::ESClassValue classValue); const char* className(JSContext *cx, JS::HandleObject proxy); bool isCallable(JSObject *obj); - // isConstructable is implemented here as isCallable. + bool isConstructor(JSObject *obj); nsresult instanceOf(JSObject *obj, const nsID *id, bool *bp); @@ -147,6 +147,9 @@ class WrapperOwner : public virtual JavaScriptShared ReturnStatus *rs, bool *instanceof) = 0; virtual bool CallDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth, ReturnStatus *rs, bool *instanceof) = 0; + + virtual bool CallIsCallable(const ObjectId &objId, bool *result) = 0; + virtual bool CallIsConstructor(const ObjectId &objId, bool *result) = 0; }; bool