Bug 1249698 - Use parent stack instead of vanished child stack. r=billm
authorWei-Cheng Pan <wpan@mozilla.com>
Tue, 26 Jul 2016 18:30:42 +0800
changeset 333354 0901574275090b099b3ae1d704297416689d06fe
parent 333353 893aa91455dec467b7257da0731261cc3fa2cd88
child 333355 df2fb7caf5e1918ff02ff97314eb69b7a54472d3
push id10033
push userraliiev@mozilla.com
push dateMon, 19 Sep 2016 13:50:26 +0000
treeherdermozilla-aurora@5dddbefdf759 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs1249698
milestone50.0a1
Bug 1249698 - Use parent stack instead of vanished child stack. r=billm MozReview-Commit-ID: LaX5K1uPZo9
js/ipc/JavaScriptTypes.ipdlh
js/ipc/WrapperAnswer.cpp
js/ipc/WrapperAnswer.h
js/ipc/WrapperOwner.cpp
--- a/js/ipc/JavaScriptTypes.ipdlh
+++ b/js/ipc/JavaScriptTypes.ipdlh
@@ -94,30 +94,35 @@ union JSIDVariant
 struct ReturnSuccess
 {
 };
 
 struct ReturnStopIteration
 {
 };
 
+struct ReturnDeadCPOW
+{
+};
+
 struct ReturnException
 {
     JSVariant exn;
 };
 
 struct ReturnObjectOpResult
 {
     uint32_t code;
 };
 
 union ReturnStatus
 {
     ReturnSuccess;
     ReturnStopIteration;
+    ReturnDeadCPOW;
     ReturnException;
     ReturnObjectOpResult;
 };
 
 union JSParam
 {
     void_t;     /* value is strictly an xpc out param */
     JSVariant;  /* actual value to pass through */
--- a/js/ipc/WrapperAnswer.cpp
+++ b/js/ipc/WrapperAnswer.cpp
@@ -69,26 +69,35 @@ WrapperAnswer::ok(ReturnStatus* rs, cons
 {
     *rs = result
           ? ReturnStatus(ReturnSuccess())
           : ReturnStatus(ReturnObjectOpResult(result.failureCode()));
     return true;
 }
 
 bool
+WrapperAnswer::deadCPOW(AutoJSAPI& jsapi, ReturnStatus* rs)
+{
+    JSContext* cx = jsapi.cx();
+    JS_ClearPendingException(cx);
+    *rs = ReturnStatus(ReturnDeadCPOW());
+    return true;
+}
+
+bool
 WrapperAnswer::RecvPreventExtensions(const ObjectId& objId, ReturnStatus* rs)
 {
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     ObjectOpResult success;
     if (!JS_PreventExtensions(cx, obj, success))
         return fail(jsapi, rs);
 
     LOG("%s.preventExtensions()", ReceiverObj(objId));
     return ok(rs, success);
 }
@@ -110,17 +119,17 @@ WrapperAnswer::RecvGetPropertyDescriptor
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
     EmptyDesc(out);
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     LOG("%s.getPropertyDescriptor(%s)", ReceiverObj(objId), Identifier(idVar));
 
     RootedId id(cx);
     if (!fromJSIDVariant(cx, idVar, &id))
         return fail(jsapi, rs);
 
     Rooted<PropertyDescriptor> desc(cx);
@@ -140,17 +149,17 @@ WrapperAnswer::RecvGetOwnPropertyDescrip
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
     EmptyDesc(out);
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     LOG("%s.getOwnPropertyDescriptor(%s)", ReceiverObj(objId), Identifier(idVar));
 
     RootedId id(cx);
     if (!fromJSIDVariant(cx, idVar, &id))
         return fail(jsapi, rs);
 
     Rooted<PropertyDescriptor> desc(cx);
@@ -169,17 +178,17 @@ WrapperAnswer::RecvDefineProperty(const 
 {
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     LOG("define %s[%s]", ReceiverObj(objId), Identifier(idVar));
 
     RootedId id(cx);
     if (!fromJSIDVariant(cx, idVar, &id))
         return fail(jsapi, rs);
 
     Rooted<PropertyDescriptor> desc(cx);
@@ -197,17 +206,17 @@ WrapperAnswer::RecvDelete(const ObjectId
 {
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     LOG("delete %s[%s]", ReceiverObj(objId), Identifier(idVar));
 
     RootedId id(cx);
     if (!fromJSIDVariant(cx, idVar, &id))
         return fail(jsapi, rs);
 
     ObjectOpResult success;
@@ -223,17 +232,17 @@ WrapperAnswer::RecvHas(const ObjectId& o
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
     *foundp = false;
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     LOG("%s.has(%s)", ReceiverObj(objId), Identifier(idVar));
 
     RootedId id(cx);
     if (!fromJSIDVariant(cx, idVar, &id))
         return fail(jsapi, rs);
 
     if (!JS_HasPropertyById(cx, obj, id, foundp))
@@ -248,17 +257,17 @@ WrapperAnswer::RecvHasOwn(const ObjectId
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
     *foundp = false;
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     LOG("%s.hasOwn(%s)", ReceiverObj(objId), Identifier(idVar));
 
     RootedId id(cx);
     if (!fromJSIDVariant(cx, idVar, &id))
         return fail(jsapi, rs);
 
     if (!JS_HasOwnPropertyById(cx, obj, id, foundp))
@@ -276,17 +285,17 @@ WrapperAnswer::RecvGet(const ObjectId& o
     JSContext* cx = aes.cx();
 
     // The outparam will be written to the buffer, so it must be set even if
     // the parent won't read it.
     *result = UndefinedVariant();
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(aes, rs);
+        return deadCPOW(aes, rs);
 
     RootedValue receiver(cx);
     if (!fromVariant(cx, receiverVar, &receiver))
         return fail(aes, rs);
 
     RootedId id(cx);
     if (!fromJSIDVariant(cx, idVar, &id))
         return fail(aes, rs);
@@ -309,17 +318,17 @@ WrapperAnswer::RecvSet(const ObjectId& o
 {
     // We may run scripted setters.
     AutoEntryScript aes(scopeForTargetObjects(),
                         "Cross-Process Object Wrapper 'set'");
     JSContext* cx = aes.cx();
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(aes, rs);
+        return deadCPOW(aes, rs);
 
     LOG("set %s[%s] = %s", ReceiverObj(objId), Identifier(idVar), InVariant(value));
 
     RootedId id(cx);
     if (!fromJSIDVariant(cx, idVar, &id))
         return fail(aes, rs);
 
     RootedValue val(cx);
@@ -343,17 +352,17 @@ WrapperAnswer::RecvIsExtensible(const Ob
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
     *result = false;
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     LOG("%s.isExtensible()", ReceiverObj(objId));
 
     bool extensible;
     if (!JS_IsExtensible(cx, obj, &extensible))
         return fail(jsapi, rs);
 
     *result = !!extensible;
@@ -373,17 +382,17 @@ WrapperAnswer::RecvCallOrConstruct(const
     JSContext* cx = aes.cx();
 
     // The outparam will be written to the buffer, so it must be set even if
     // the parent won't read it.
     *result = UndefinedVariant();
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(aes, rs);
+        return deadCPOW(aes, rs);
 
     MOZ_ASSERT(argv.Length() >= 2);
 
     RootedValue objv(cx);
     if (!fromVariant(cx, argv[0], &objv))
         return fail(aes, rs);
 
     *result = JSVariant(UndefinedVariant());
@@ -468,17 +477,17 @@ WrapperAnswer::RecvHasInstance(const Obj
 {
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     LOG("%s.hasInstance(%s)", ReceiverObj(objId), InVariant(vVar));
 
     RootedValue val(cx);
     if (!fromVariant(cx, vVar, &val))
         return fail(jsapi, rs);
 
     if (!JS_HasInstance(cx, obj, val, bp))
@@ -495,17 +504,17 @@ WrapperAnswer::RecvGetBuiltinClass(const
 
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     LOG("%s.getBuiltinClass()", ReceiverObj(objId));
 
     js::ESClass cls;
     if (!js::GetBuiltinClass(cx, obj, &cls))
         return fail(jsapi, rs);
 
     *classValue = uint32_t(cls);
@@ -520,17 +529,17 @@ WrapperAnswer::RecvIsArray(const ObjectI
 
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     LOG("%s.isArray()", ReceiverObj(objId));
 
     IsArrayAnswer answer;
     if (!JS::IsArray(cx, obj, &answer))
         return fail(jsapi, rs);
 
     *ans = uint32_t(answer);
@@ -565,17 +574,17 @@ WrapperAnswer::RecvGetPrototype(const Ob
 
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     JS::RootedObject proto(cx);
     if (!JS_GetPrototype(cx, obj, &proto))
         return fail(jsapi, rs);
 
     if (!toObjectOrNullVariant(cx, proto, result))
         return fail(jsapi, rs);
 
@@ -593,17 +602,17 @@ WrapperAnswer::RecvGetPrototypeIfOrdinar
 
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     JS::RootedObject proto(cx);
     if (!JS_GetPrototypeIfOrdinary(cx, obj, isOrdinary, &proto))
         return fail(jsapi, rs);
 
     if (!toObjectOrNullVariant(cx, proto, result))
         return fail(jsapi, rs);
 
@@ -618,17 +627,17 @@ WrapperAnswer::RecvRegExpToShared(const 
 {
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     RootedString sourceJSStr(cx, JS_GetRegExpSource(cx, obj));
     if (!sourceJSStr)
         return fail(jsapi, rs);
     nsAutoJSString sourceStr;
     if (!sourceStr.init(cx, sourceJSStr))
         return fail(jsapi, rs);
     source->Assign(sourceStr);
@@ -644,17 +653,17 @@ WrapperAnswer::RecvGetPropertyKeys(const
 {
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     LOG("%s.getPropertyKeys()", ReceiverObj(objId));
 
     AutoIdVector props(cx);
     if (!js::GetPropertyKeys(cx, obj, flags, &props))
         return fail(jsapi, rs);
 
     for (size_t i = 0; i < props.length(); i++) {
@@ -676,17 +685,17 @@ WrapperAnswer::RecvInstanceOf(const Obje
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
 
     *instanceof = false;
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     LOG("%s.instanceOf()", ReceiverObj(objId));
 
     nsID nsiid;
     ConvertID(iid, &nsiid);
 
     nsresult rv = xpc::HasInstance(cx, obj, &nsiid, instanceof);
     if (rv != NS_OK)
@@ -702,17 +711,17 @@ WrapperAnswer::RecvDOMInstanceOf(const O
     AutoJSAPI jsapi;
     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
         return false;
     JSContext* cx = jsapi.cx();
     *instanceof = false;
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
-        return fail(jsapi, rs);
+        return deadCPOW(jsapi, rs);
 
     LOG("%s.domInstanceOf()", ReceiverObj(objId));
 
     bool tmp;
     if (!mozilla::dom::InterfaceHasInstance(cx, prototypeID, depth, obj, &tmp))
         return fail(jsapi, rs);
     *instanceof = tmp;
 
--- a/js/ipc/WrapperAnswer.h
+++ b/js/ipc/WrapperAnswer.h
@@ -68,14 +68,15 @@ class WrapperAnswer : public virtual Jav
                            ReturnStatus* rs, bool* instanceof);
 
     bool RecvDropObject(const ObjectId& objId);
 
   private:
     bool fail(dom::AutoJSAPI& jsapi, ReturnStatus* rs);
     bool ok(ReturnStatus* rs);
     bool ok(ReturnStatus* rs, const JS::ObjectOpResult& result);
+    bool deadCPOW(dom::AutoJSAPI& jsapi, ReturnStatus* rs);
 };
 
 } // namespace jsipc
 } // namespace mozilla
 
 #endif
--- a/js/ipc/WrapperOwner.cpp
+++ b/js/ipc/WrapperOwner.cpp
@@ -1071,16 +1071,21 @@ bool
 WrapperOwner::ok(JSContext* cx, const ReturnStatus& status)
 {
     if (status.type() == ReturnStatus::TReturnSuccess)
         return true;
 
     if (status.type() == ReturnStatus::TReturnStopIteration)
         return JS_ThrowStopIteration(cx);
 
+    if (status.type() == ReturnStatus::TReturnDeadCPOW) {
+        JS_ReportError(cx, "operation not possible on dead CPOW");
+        return false;
+    }
+
     RootedValue exn(cx);
     if (!fromVariant(cx, status.get_ReturnException().exn(), &exn))
         return false;
 
     JS_SetPendingException(cx, exn);
     return false;
 }