Bug 1071177 - Introduce JSIDVariant type for CPOWs. r=billm
authorTom Schuster <evilpies@gmail.com>
Tue, 07 Oct 2014 11:29:02 +0200
changeset 209132 765ab5eaab5b12281c1cbad4c8a0828e37c92ba7
parent 209131 27626f68637d6c531ba0836dce5b8785e5d39510
child 209133 6e6f184e59285a2dcdf106c830e7ec0db2da6a97
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersbillm
bugs1071177
milestone35.0a1
Bug 1071177 - Introduce JSIDVariant type for CPOWs. r=billm
js/ipc/JavaScriptBase.h
js/ipc/JavaScriptLogging.h
js/ipc/JavaScriptShared.cpp
js/ipc/JavaScriptShared.h
js/ipc/JavaScriptTypes.ipdlh
js/ipc/PJavaScript.ipdl
js/ipc/WrapperAnswer.cpp
js/ipc/WrapperAnswer.h
js/ipc/WrapperOwner.cpp
js/ipc/WrapperOwner.h
--- a/js/ipc/JavaScriptBase.h
+++ b/js/ipc/JavaScriptBase.h
@@ -33,52 +33,52 @@ class JavaScriptBase : public WrapperOwn
         WrapperOwner::ActorDestroy(why);
     }
 
     /*** IPC handlers ***/
 
     bool AnswerPreventExtensions(const uint64_t &objId, ReturnStatus *rs) {
         return Answer::AnswerPreventExtensions(ObjectId::deserialize(objId), rs);
     }
-    bool AnswerGetPropertyDescriptor(const uint64_t &objId, const nsString &id,
+    bool AnswerGetPropertyDescriptor(const uint64_t &objId, const JSIDVariant &id,
                                      ReturnStatus *rs,
                                      PPropertyDescriptor *out) {
         return Answer::AnswerGetPropertyDescriptor(ObjectId::deserialize(objId), id, rs, out);
     }
     bool AnswerGetOwnPropertyDescriptor(const uint64_t &objId,
-                                        const nsString &id,
+                                        const JSIDVariant &id,
                                         ReturnStatus *rs,
                                         PPropertyDescriptor *out) {
         return Answer::AnswerGetOwnPropertyDescriptor(ObjectId::deserialize(objId), id, rs, out);
     }
-    bool AnswerDefineProperty(const uint64_t &objId, const nsString &id,
+    bool AnswerDefineProperty(const uint64_t &objId, const JSIDVariant &id,
                               const PPropertyDescriptor &flags,
                               ReturnStatus *rs) {
         return Answer::AnswerDefineProperty(ObjectId::deserialize(objId), id, flags, rs);
     }
-    bool AnswerDelete(const uint64_t &objId, const nsString &id,
+    bool AnswerDelete(const uint64_t &objId, const JSIDVariant &id,
                       ReturnStatus *rs, bool *success) {
         return Answer::AnswerDelete(ObjectId::deserialize(objId), id, rs, success);
     }
 
-    bool AnswerHas(const uint64_t &objId, const nsString &id,
+    bool AnswerHas(const uint64_t &objId, const JSIDVariant &id,
                    ReturnStatus *rs, bool *bp) {
         return Answer::AnswerHas(ObjectId::deserialize(objId), id, rs, bp);
     }
-    bool AnswerHasOwn(const uint64_t &objId, const nsString &id,
+    bool AnswerHasOwn(const uint64_t &objId, const JSIDVariant &id,
                       ReturnStatus *rs, bool *bp) {
         return Answer::AnswerHasOwn(ObjectId::deserialize(objId), id, rs, bp);
     }
     bool AnswerGet(const uint64_t &objId, const ObjectVariant &receiverVar,
-                   const nsString &id,
+                   const JSIDVariant &id,
                    ReturnStatus *rs, JSVariant *result) {
         return Answer::AnswerGet(ObjectId::deserialize(objId), receiverVar, id, rs, result);
     }
     bool AnswerSet(const uint64_t &objId, const ObjectVariant &receiverVar,
-                   const nsString &id, const bool &strict,
+                   const JSIDVariant &id, const bool &strict,
                    const JSVariant &value, ReturnStatus *rs, JSVariant *result) {
         return Answer::AnswerSet(ObjectId::deserialize(objId), receiverVar, id, strict, value, rs, result);
     }
 
     bool AnswerIsExtensible(const uint64_t &objId, ReturnStatus *rs,
                             bool *result) {
         return Answer::AnswerIsExtensible(ObjectId::deserialize(objId), rs, result);
     }
@@ -129,52 +129,52 @@ class JavaScriptBase : public WrapperOwn
     /*** Dummy call handlers ***/
 
     bool SendDropObject(const ObjectId &objId) {
         return Base::SendDropObject(objId.serialize());
     }
     bool CallPreventExtensions(const ObjectId &objId, ReturnStatus *rs) {
         return Base::CallPreventExtensions(objId.serialize(), rs);
     }
-    bool CallGetPropertyDescriptor(const ObjectId &objId, const nsString &id,
+    bool CallGetPropertyDescriptor(const ObjectId &objId, const JSIDVariant &id,
                                      ReturnStatus *rs,
                                      PPropertyDescriptor *out) {
         return Base::CallGetPropertyDescriptor(objId.serialize(), id, rs, out);
     }
     bool CallGetOwnPropertyDescriptor(const ObjectId &objId,
-                                      const nsString &id,
+                                      const JSIDVariant &id,
                                       ReturnStatus *rs,
                                       PPropertyDescriptor *out) {
         return Base::CallGetOwnPropertyDescriptor(objId.serialize(), id, rs, out);
     }
-    bool CallDefineProperty(const ObjectId &objId, const nsString &id,
+    bool CallDefineProperty(const ObjectId &objId, const JSIDVariant &id,
                             const PPropertyDescriptor &flags,
                               ReturnStatus *rs) {
         return Base::CallDefineProperty(objId.serialize(), id, flags, rs);
     }
-    bool CallDelete(const ObjectId &objId, const nsString &id,
+    bool CallDelete(const ObjectId &objId, const JSIDVariant &id,
                     ReturnStatus *rs, bool *success) {
         return Base::CallDelete(objId.serialize(), id, rs, success);
     }
 
-    bool CallHas(const ObjectId &objId, const nsString &id,
+    bool CallHas(const ObjectId &objId, const JSIDVariant &id,
                    ReturnStatus *rs, bool *bp) {
         return Base::CallHas(objId.serialize(), id, rs, bp);
     }
-    bool CallHasOwn(const ObjectId &objId, const nsString &id,
+    bool CallHasOwn(const ObjectId &objId, const JSIDVariant &id,
                     ReturnStatus *rs, bool *bp) {
         return Base::CallHasOwn(objId.serialize(), id, rs, bp);
     }
     bool CallGet(const ObjectId &objId, const ObjectVariant &receiverVar,
-                 const nsString &id,
+                 const JSIDVariant &id,
                  ReturnStatus *rs, JSVariant *result) {
         return Base::CallGet(objId.serialize(), receiverVar, id, rs, result);
     }
     bool CallSet(const ObjectId &objId, const ObjectVariant &receiverVar,
-                 const nsString &id, const bool &strict,
+                 const JSIDVariant &id, const bool &strict,
                  const JSVariant &value, ReturnStatus *rs, JSVariant *result) {
         return Base::CallSet(objId.serialize(), receiverVar, id, strict, value, rs, result);
     }
 
     bool CallIsExtensible(const ObjectId &objId, ReturnStatus *rs,
                           bool *result) {
         return Base::CallIsExtensible(objId.serialize(), rs, result);
     }
--- a/js/ipc/JavaScriptLogging.h
+++ b/js/ipc/JavaScriptLogging.h
@@ -44,16 +44,22 @@ struct InVariant
 };
 
 struct OutVariant
 {
     JSVariant variant;
     explicit OutVariant(const JSVariant &variant) : variant(variant) {}
 };
 
+struct Identifier
+{
+    JSIDVariant variant;
+    explicit Identifier(const JSIDVariant &variant) : variant(variant) {}
+};
+
 class Logging
 {
   public:
     Logging(JavaScriptShared *shared, JSContext *cx) : shared(shared), cx(cx) {}
 
     void print(const nsCString &str) {
         const char *side = shared->isParent() ? "from child" : "from parent";
         printf("CPOW %s: %s\n", side, str.get());
@@ -179,16 +185,35 @@ class Logging
           }
           default: {
               out = "<JSIID>";
               break;
           }
         }
     }
 
+    void format(const Identifier &id, nsCString &out) {
+        switch (id.variant.type()) {
+          case JSIDVariant::TnsString: {
+              nsAutoCString tmp;
+              format(id.variant.get_nsString(), tmp);
+              out = nsPrintfCString("\"%s\"", tmp.get());
+              break;
+          }
+          case JSIDVariant::Tint32_t: {
+              out = nsPrintfCString("%d", id.variant.get_int32_t());
+              break;
+          }
+          default: {
+              out = "Unknown";
+              break;
+          }
+      }
+    }
+
   private:
     JavaScriptShared *shared;
     JSContext *cx;
 };
 
 }
 }
 
--- a/js/ipc/JavaScriptShared.cpp
+++ b/js/ipc/JavaScriptShared.cpp
@@ -343,20 +343,55 @@ JavaScriptShared::fromVariant(JSContext 
           JSObject *obj = xpc_NewIDObject(cx, global, iid);
           if (!obj)
               return false;
           to.set(ObjectValue(*obj));
           return true;
         }
 
         default:
+          MOZ_CRASH("NYI");
           return false;
     }
 }
 
+bool
+JavaScriptShared::toJSIDVariant(JSContext *cx, HandleId from, JSIDVariant *to)
+{
+    if (JSID_IS_STRING(from)) {
+        nsAutoJSString autoStr;
+        if (!autoStr.init(cx, JSID_TO_STRING(from)))
+            return false;
+        *to = autoStr;
+        return true;
+    }
+    if (JSID_IS_INT(from)) {
+        *to = JSID_TO_INT(from);
+        return true;
+    }
+    MOZ_CRASH("NYI");
+    return false;
+}
+
+bool
+JavaScriptShared::fromJSIDVariant(JSContext *cx, const JSIDVariant &from, MutableHandleId to)
+{
+    switch (from.type()) {
+      case JSIDVariant::TnsString:
+        return convertGeckoStringToId(cx, from.get_nsString(), to);
+
+      case JSIDVariant::Tint32_t:
+        to.set(INT_TO_JSID(from.get_int32_t()));
+        return true;
+
+      default:
+        return false;
+    }
+}
+
 /* static */ void
 JavaScriptShared::ConvertID(const nsID &from, JSIID *to)
 {
     to->m0() = from.m0;
     to->m1() = from.m1;
     to->m2() = from.m2;
     to->m3_0() = from.m3[0];
     to->m3_1() = from.m3[1];
--- a/js/ipc/JavaScriptShared.h
+++ b/js/ipc/JavaScriptShared.h
@@ -153,16 +153,19 @@ class JavaScriptShared
 
     bool Unwrap(JSContext *cx, const InfallibleTArray<CpowEntry> &aCpows, JS::MutableHandleObject objp);
     bool Wrap(JSContext *cx, JS::HandleObject aObj, InfallibleTArray<CpowEntry> *outCpows);
 
   protected:
     bool toVariant(JSContext *cx, JS::HandleValue from, JSVariant *to);
     bool fromVariant(JSContext *cx, const JSVariant &from, JS::MutableHandleValue to);
 
+    bool toJSIDVariant(JSContext *cx, JS::HandleId from, JSIDVariant *to);
+    bool fromJSIDVariant(JSContext *cx, const JSIDVariant &from, JS::MutableHandleId to);
+
     bool fromDescriptor(JSContext *cx, JS::Handle<JSPropertyDescriptor> desc,
                         PPropertyDescriptor *out);
     bool toDescriptor(JSContext *cx, const PPropertyDescriptor &in,
                       JS::MutableHandle<JSPropertyDescriptor> out);
 
     bool convertIdToGeckoString(JSContext *cx, JS::HandleId id, nsString *to);
     bool convertGeckoStringToId(JSContext *cx, const nsString &from, JS::MutableHandleId id);
 
--- a/js/ipc/JavaScriptTypes.ipdlh
+++ b/js/ipc/JavaScriptTypes.ipdlh
@@ -52,16 +52,22 @@ union JSVariant
     NullVariant;
     ObjectVariant;
     nsString;   /* StringValue(x) */
     double;     /* NumberValue(x) */
     bool;       /* BooleanValue(x) */
     JSIID;      /* XPC nsIID */
 };
 
+union JSIDVariant
+{
+    nsString;
+    int32_t;
+};
+
 struct ReturnSuccess
 {
 };
 
 struct ReturnStopIteration
 {
 };
 
--- a/js/ipc/PJavaScript.ipdl
+++ b/js/ipc/PJavaScript.ipdl
@@ -20,25 +20,25 @@ intr protocol PJavaScript
     manager PContent or PContentBridge;
 
 both:
     // Sent when a CPOW has been finalized and table entries can be freed up.
     async DropObject(uint64_t objId);
 
     // These roughly map to the ProxyHandler hooks that CPOWs need.
     rpc PreventExtensions(uint64_t objId) returns (ReturnStatus rs);
-    rpc GetPropertyDescriptor(uint64_t objId, nsString id) returns (ReturnStatus rs, PPropertyDescriptor result);
-    rpc GetOwnPropertyDescriptor(uint64_t objId, nsString id) returns (ReturnStatus rs, PPropertyDescriptor result);
-    rpc DefineProperty(uint64_t objId, nsString id, PPropertyDescriptor descriptor) returns (ReturnStatus rs);
-    rpc Delete(uint64_t objId, nsString id) returns (ReturnStatus rs, bool successful);
+    rpc GetPropertyDescriptor(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, PPropertyDescriptor result);
+    rpc GetOwnPropertyDescriptor(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, PPropertyDescriptor result);
+    rpc DefineProperty(uint64_t objId, JSIDVariant id, PPropertyDescriptor descriptor) returns (ReturnStatus rs);
+    rpc Delete(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, bool successful);
 
-    rpc Has(uint64_t objId, nsString id) returns (ReturnStatus rs, bool has);
-    rpc HasOwn(uint64_t objId, nsString id) returns (ReturnStatus rs, bool has);
-    rpc Get(uint64_t objId, ObjectVariant receiver, nsString id) returns (ReturnStatus rs, JSVariant result);
-    rpc Set(uint64_t objId, ObjectVariant receiver, nsString id, bool strict, JSVariant value) returns (ReturnStatus rs, JSVariant result);
+    rpc Has(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, bool has);
+    rpc HasOwn(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, bool has);
+    rpc Get(uint64_t objId, ObjectVariant receiver, JSIDVariant id) returns (ReturnStatus rs, JSVariant result);
+    rpc Set(uint64_t objId, ObjectVariant receiver, JSIDVariant id, bool strict, JSVariant value) returns (ReturnStatus rs, JSVariant result);
 
     rpc IsExtensible(uint64_t objId) returns (ReturnStatus rs, bool result);
     rpc CallOrConstruct(uint64_t objId, JSParam[] argv, bool construct) returns (ReturnStatus rs, JSVariant result, JSParam[] outparams);
     rpc HasInstance(uint64_t objId, JSVariant v) returns (ReturnStatus rs, bool has);
     rpc ObjectClassIs(uint64_t objId, uint32_t classValue) returns (bool result);
     rpc ClassName(uint64_t objId) returns (nsString name);
     rpc RegExpToShared(uint64_t objId) returns (ReturnStatus rs, nsString source, uint32_t flags);
 
--- a/js/ipc/WrapperAnswer.cpp
+++ b/js/ipc/WrapperAnswer.cpp
@@ -82,207 +82,208 @@ EmptyDesc(PPropertyDescriptor *desc)
     desc->obj() = LocalObject(0);
     desc->attrs() = 0;
     desc->value() = UndefinedVariant();
     desc->getter() = 0;
     desc->setter() = 0;
 }
 
 bool
-WrapperAnswer::AnswerGetPropertyDescriptor(const ObjectId &objId, const nsString &id,
-					   ReturnStatus *rs, PPropertyDescriptor *out)
+WrapperAnswer::AnswerGetPropertyDescriptor(const ObjectId &objId, const JSIDVariant &idVar,
+                                           ReturnStatus *rs, PPropertyDescriptor *out)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     EmptyDesc(out);
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
         return fail(cx, rs);
 
     JSAutoCompartment comp(cx, obj);
 
-    LOG("%s.getPropertyDescriptor(%s)", ReceiverObj(objId), id);
+    LOG("%s.getPropertyDescriptor(%s)", ReceiverObj(objId), Identifier(idVar));
 
-    RootedId internedId(cx);
-    if (!convertGeckoStringToId(cx, id, &internedId))
+    RootedId id(cx);
+    if (!fromJSIDVariant(cx, idVar, &id))
         return fail(cx, rs);
 
     Rooted<JSPropertyDescriptor> desc(cx);
-    if (!JS_GetPropertyDescriptorById(cx, obj, internedId, &desc))
+    if (!JS_GetPropertyDescriptorById(cx, obj, id, &desc))
         return fail(cx, rs);
 
     if (!desc.object())
         return ok(rs);
 
     if (!fromDescriptor(cx, desc, out))
         return fail(cx, rs);
 
     return ok(rs);
 }
 
 bool
-WrapperAnswer::AnswerGetOwnPropertyDescriptor(const ObjectId &objId, const nsString &id,
-					      ReturnStatus *rs, PPropertyDescriptor *out)
+WrapperAnswer::AnswerGetOwnPropertyDescriptor(const ObjectId &objId, const JSIDVariant &idVar,
+                                              ReturnStatus *rs, PPropertyDescriptor *out)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     EmptyDesc(out);
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
         return fail(cx, rs);
 
     JSAutoCompartment comp(cx, obj);
 
-    LOG("%s.getOwnPropertyDescriptor(%s)", ReceiverObj(objId), id);
+    LOG("%s.getOwnPropertyDescriptor(%s)", ReceiverObj(objId), Identifier(idVar));
 
-    RootedId internedId(cx);
-    if (!convertGeckoStringToId(cx, id, &internedId))
+    RootedId id(cx);
+    if (!fromJSIDVariant(cx, idVar, &id))
         return fail(cx, rs);
 
     Rooted<JSPropertyDescriptor> desc(cx);
-    if (!JS_GetPropertyDescriptorById(cx, obj, internedId, &desc))
+    if (!JS_GetPropertyDescriptorById(cx, obj, id, &desc))
         return fail(cx, rs);
 
     if (desc.object() != obj)
         return ok(rs);
 
     if (!fromDescriptor(cx, desc, out))
         return fail(cx, rs);
 
     return ok(rs);
 }
 
 bool
-WrapperAnswer::AnswerDefineProperty(const ObjectId &objId, const nsString &id,
-				    const PPropertyDescriptor &descriptor, ReturnStatus *rs)
+WrapperAnswer::AnswerDefineProperty(const ObjectId &objId, const JSIDVariant &idVar,
+                                    const PPropertyDescriptor &descriptor, ReturnStatus *rs)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
         return fail(cx, rs);
 
     JSAutoCompartment comp(cx, obj);
 
-    LOG("define %s[%s]", ReceiverObj(objId), id);
+    LOG("define %s[%s]", ReceiverObj(objId), Identifier(idVar));
 
-    RootedId internedId(cx);
-    if (!convertGeckoStringToId(cx, id, &internedId))
+    RootedId id(cx);
+    if (!fromJSIDVariant(cx, idVar, &id))
         return fail(cx, rs);
 
     Rooted<JSPropertyDescriptor> desc(cx);
     if (!toDescriptor(cx, descriptor, &desc))
         return fail(cx, rs);
 
-    if (!js::CheckDefineProperty(cx, obj, internedId, desc.value(), desc.attributes(),
+    if (!js::CheckDefineProperty(cx, obj, id, desc.value(), desc.attributes(),
                                  desc.getter(), desc.setter()))
     {
         return fail(cx, rs);
     }
 
-    if (!JS_DefinePropertyById(cx, obj, internedId, desc.value(), desc.attributes(),
+    if (!JS_DefinePropertyById(cx, obj, id, desc.value(), desc.attributes(),
                                desc.getter(), desc.setter()))
     {
         return fail(cx, rs);
     }
 
     return ok(rs);
 }
 
 bool
-WrapperAnswer::AnswerDelete(const ObjectId &objId, const nsString &id, ReturnStatus *rs,
-			    bool *success)
+WrapperAnswer::AnswerDelete(const ObjectId &objId, const JSIDVariant &idVar, ReturnStatus *rs,
+                            bool *success)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     *success = false;
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
         return fail(cx, rs);
 
     JSAutoCompartment comp(cx, obj);
 
-    LOG("delete %s[%s]", ReceiverObj(objId), id);
+    LOG("delete %s[%s]", ReceiverObj(objId), Identifier(idVar));
 
-    RootedId internedId(cx);
-    if (!convertGeckoStringToId(cx, id, &internedId))
+    RootedId id(cx);
+    if (!fromJSIDVariant(cx, idVar, &id))
         return fail(cx, rs);
 
-    if (!JS_DeletePropertyById2(cx, obj, internedId, success))
+    if (!JS_DeletePropertyById2(cx, obj, id, success))
         return fail(cx, rs);
 
     return ok(rs);
 }
 
 bool
-WrapperAnswer::AnswerHas(const ObjectId &objId, const nsString &id, ReturnStatus *rs, bool *bp)
+WrapperAnswer::AnswerHas(const ObjectId &objId, const JSIDVariant &idVar, ReturnStatus *rs, bool *bp)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     *bp = false;
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
         return fail(cx, rs);
 
     JSAutoCompartment comp(cx, obj);
 
-    LOG("%s.has(%s)", ReceiverObj(objId), id);
+    LOG("%s.has(%s)", ReceiverObj(objId), Identifier(idVar));
 
-    RootedId internedId(cx);
-    if (!convertGeckoStringToId(cx, id, &internedId))
+    RootedId id(cx);
+    if (!fromJSIDVariant(cx, idVar, &id))
         return fail(cx, rs);
 
     bool found;
-    if (!JS_HasPropertyById(cx, obj, internedId, &found))
+    if (!JS_HasPropertyById(cx, obj, id, &found))
         return fail(cx, rs);
     *bp = !!found;
 
     return ok(rs);
 }
 
 bool
-WrapperAnswer::AnswerHasOwn(const ObjectId &objId, const nsString &id, ReturnStatus *rs, bool *bp)
+WrapperAnswer::AnswerHasOwn(const ObjectId &objId, const JSIDVariant &idVar, ReturnStatus *rs,
+                            bool *bp)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     *bp = false;
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
         return fail(cx, rs);
 
     JSAutoCompartment comp(cx, obj);
 
-    LOG("%s.hasOwn(%s)", ReceiverObj(objId), id);
+    LOG("%s.hasOwn(%s)", ReceiverObj(objId), Identifier(idVar));
 
-    RootedId internedId(cx);
-    if (!convertGeckoStringToId(cx, id, &internedId))
+    RootedId id(cx);
+    if (!fromJSIDVariant(cx, idVar, &id))
         return fail(cx, rs);
 
     Rooted<JSPropertyDescriptor> desc(cx);
-    if (!JS_GetPropertyDescriptorById(cx, obj, internedId, &desc))
+    if (!JS_GetPropertyDescriptorById(cx, obj, id, &desc))
         return fail(cx, rs);
     *bp = (desc.object() == obj);
 
     return ok(rs);
 }
 
 bool
-WrapperAnswer::AnswerGet(const ObjectId &objId, const ObjectVariant &receiverVar, const nsString &id,
-			 ReturnStatus *rs, JSVariant *result)
+WrapperAnswer::AnswerGet(const ObjectId &objId, const ObjectVariant &receiverVar,
+                         const JSIDVariant &idVar, ReturnStatus *rs, JSVariant *result)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     // The outparam will be written to the buffer, so it must be set even if
     // the parent won't read it.
     *result = UndefinedVariant();
 
@@ -291,36 +292,36 @@ WrapperAnswer::AnswerGet(const ObjectId 
         return fail(cx, rs);
 
     JSAutoCompartment comp(cx, obj);
 
     RootedObject receiver(cx, fromObjectVariant(cx, receiverVar));
     if (!receiver)
         return fail(cx, rs);
 
-    RootedId internedId(cx);
-    if (!convertGeckoStringToId(cx, id, &internedId))
+    RootedId id(cx);
+    if (!fromJSIDVariant(cx, idVar, &id))
         return fail(cx, rs);
 
     JS::RootedValue val(cx);
-    if (!JS_ForwardGetPropertyTo(cx, obj, internedId, receiver, &val))
+    if (!JS_ForwardGetPropertyTo(cx, obj, id, receiver, &val))
         return fail(cx, rs);
 
     if (!toVariant(cx, val, result))
         return fail(cx, rs);
 
-    LOG("get %s.%s = %s", ReceiverObj(objId), id, OutVariant(*result));
+    LOG("get %s.%s = %s", ReceiverObj(objId), Identifier(idVar), OutVariant(*result));
 
     return ok(rs);
 }
 
 bool
-WrapperAnswer::AnswerSet(const ObjectId &objId, const ObjectVariant &receiverVar, const nsString &id,
-			 const bool &strict, const JSVariant &value, ReturnStatus *rs,
-			 JSVariant *result)
+WrapperAnswer::AnswerSet(const ObjectId &objId, const ObjectVariant &receiverVar,
+                         const JSIDVariant &idVar, const bool &strict, const JSVariant &value,
+                         ReturnStatus *rs, JSVariant *result)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     // The outparam will be written to the buffer, so it must be set even if
     // the parent won't read it.
     *result = UndefinedVariant();
 
@@ -329,29 +330,29 @@ WrapperAnswer::AnswerSet(const ObjectId 
         return fail(cx, rs);
 
     JSAutoCompartment comp(cx, obj);
 
     RootedObject receiver(cx, fromObjectVariant(cx, receiverVar));
     if (!receiver)
         return fail(cx, rs);
 
-    LOG("set %s[%s] = %s", ReceiverObj(objId), id, InVariant(value));
+    LOG("set %s[%s] = %s", ReceiverObj(objId), Identifier(idVar), InVariant(value));
 
-    RootedId internedId(cx);
-    if (!convertGeckoStringToId(cx, id, &internedId))
+    RootedId id(cx);
+    if (!fromJSIDVariant(cx, idVar, &id))
         return fail(cx, rs);
 
     MOZ_ASSERT(obj == receiver);
 
     RootedValue val(cx);
     if (!fromVariant(cx, value, &val))
         return fail(cx, rs);
 
-    if (!JS_SetPropertyById(cx, obj, internedId, val))
+    if (!JS_SetPropertyById(cx, obj, id, val))
         return fail(cx, rs);
 
     if (!toVariant(cx, val, result))
         return fail(cx, rs);
 
     return ok(rs);
 }
 
@@ -507,17 +508,17 @@ WrapperAnswer::AnswerHasInstance(const O
     if (!JS_HasInstance(cx, obj, val, bp))
         return fail(cx, rs);
 
     return ok(rs);
 }
 
 bool
 WrapperAnswer::AnswerObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
-				   bool *result)
+                                   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;
@@ -574,17 +575,17 @@ WrapperAnswer::AnswerRegExpToShared(cons
 
     *flags = JS_GetRegExpFlags(cx, obj);
 
     return ok(rs);
 }
 
 bool
 WrapperAnswer::AnswerGetPropertyNames(const ObjectId &objId, const uint32_t &flags,
-				      ReturnStatus *rs, nsTArray<nsString> *names)
+                                      ReturnStatus *rs, nsTArray<nsString> *names)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
         return fail(cx, rs);
 
@@ -604,17 +605,17 @@ WrapperAnswer::AnswerGetPropertyNames(co
         names->AppendElement(name);
     }
 
     return ok(rs);
 }
 
 bool
 WrapperAnswer::AnswerInstanceOf(const ObjectId &objId, const JSIID &iid, ReturnStatus *rs,
-				bool *instanceof)
+                                bool *instanceof)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     *instanceof = false;
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
@@ -631,18 +632,17 @@ WrapperAnswer::AnswerInstanceOf(const Ob
     if (rv != NS_OK)
         return fail(cx, rs);
 
     return ok(rs);
 }
 
 bool
 WrapperAnswer::AnswerDOMInstanceOf(const ObjectId &objId, const int &prototypeID,
-				   const int &depth,
-				   ReturnStatus *rs, bool *instanceof)
+                                   const int &depth, ReturnStatus *rs, bool *instanceof)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     *instanceof = false;
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
--- a/js/ipc/WrapperAnswer.h
+++ b/js/ipc/WrapperAnswer.h
@@ -14,38 +14,38 @@ namespace mozilla {
 namespace jsipc {
 
 class WrapperAnswer : public virtual JavaScriptShared
 {
   public:
     explicit WrapperAnswer(JSRuntime *rt) : JavaScriptShared(rt) {}
 
     bool AnswerPreventExtensions(const ObjectId &objId, ReturnStatus *rs);
-    bool AnswerGetPropertyDescriptor(const ObjectId &objId, const nsString &id,
+    bool AnswerGetPropertyDescriptor(const ObjectId &objId, const JSIDVariant &id,
                                      ReturnStatus *rs,
                                      PPropertyDescriptor *out);
     bool AnswerGetOwnPropertyDescriptor(const ObjectId &objId,
-                                        const nsString &id,
+                                        const JSIDVariant &id,
                                         ReturnStatus *rs,
                                         PPropertyDescriptor *out);
-    bool AnswerDefineProperty(const ObjectId &objId, const nsString &id,
+    bool AnswerDefineProperty(const ObjectId &objId, const JSIDVariant &id,
                               const PPropertyDescriptor &flags,
                               ReturnStatus *rs);
-    bool AnswerDelete(const ObjectId &objId, const nsString &id,
+    bool AnswerDelete(const ObjectId &objId, const JSIDVariant &id,
                       ReturnStatus *rs, bool *success);
 
-    bool AnswerHas(const ObjectId &objId, const nsString &id,
+    bool AnswerHas(const ObjectId &objId, const JSIDVariant &id,
                        ReturnStatus *rs, bool *bp);
-    bool AnswerHasOwn(const ObjectId &objId, const nsString &id,
+    bool AnswerHasOwn(const ObjectId &objId, const JSIDVariant &id,
                           ReturnStatus *rs, bool *bp);
     bool AnswerGet(const ObjectId &objId, const ObjectVariant &receiverVar,
-                       const nsString &id,
+                       const JSIDVariant &id,
                        ReturnStatus *rs, JSVariant *result);
     bool AnswerSet(const ObjectId &objId, const ObjectVariant &receiverVar,
-                   const nsString &id, const bool &strict,
+                   const JSIDVariant &id, const bool &strict,
                    const JSVariant &value, ReturnStatus *rs, JSVariant *result);
 
     bool AnswerIsExtensible(const ObjectId &objId, ReturnStatus *rs,
                             bool *result);
     bool AnswerCallOrConstruct(const ObjectId &objId, const nsTArray<JSParam> &argv,
                                const bool &construct, ReturnStatus *rs, JSVariant *result,
                                nsTArray<JSParam> *outparams);
     bool AnswerHasInstance(const ObjectId &objId, const JSVariant &v, ReturnStatus *rs, bool *bp);
--- a/js/ipc/WrapperOwner.cpp
+++ b/js/ipc/WrapperOwner.cpp
@@ -140,23 +140,23 @@ CPOWProxyHandler::getPropertyDescriptor(
 }
 
 bool
 WrapperOwner::getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
 				    MutableHandle<JSPropertyDescriptor> desc)
 {
     ObjectId objId = idOf(proxy);
 
-    nsString idstr;
-    if (!convertIdToGeckoString(cx, id, &idstr))
+    JSIDVariant idVar;
+    if (!toJSIDVariant(cx, id, &idVar))
         return false;
 
     ReturnStatus status;
     PPropertyDescriptor result;
-    if (!CallGetPropertyDescriptor(objId, idstr, &status, &result))
+    if (!CallGetPropertyDescriptor(objId, idVar, &status, &result))
         return ipcfail(cx);
 
     LOG_STACK();
 
     if (!ok(cx, status))
         return false;
 
     return toDescriptor(cx, result, desc);
@@ -170,23 +170,23 @@ CPOWProxyHandler::getOwnPropertyDescript
 }
 
 bool
 WrapperOwner::getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
 				       MutableHandle<JSPropertyDescriptor> desc)
 {
     ObjectId objId = idOf(proxy);
 
-    nsString idstr;
-    if (!convertIdToGeckoString(cx, id, &idstr))
+    JSIDVariant idVar;
+    if (!toJSIDVariant(cx, id, &idVar))
         return false;
 
     ReturnStatus status;
     PPropertyDescriptor result;
-    if (!CallGetOwnPropertyDescriptor(objId, idstr, &status, &result))
+    if (!CallGetOwnPropertyDescriptor(objId, idVar, &status, &result))
         return ipcfail(cx);
 
     LOG_STACK();
 
     if (!ok(cx, status))
         return false;
 
     return toDescriptor(cx, result, desc);
@@ -200,26 +200,26 @@ CPOWProxyHandler::defineProperty(JSConte
 }
 
 bool
 WrapperOwner::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
 			     MutableHandle<JSPropertyDescriptor> desc)
 {
     ObjectId objId = idOf(proxy);
 
-    nsString idstr;
-    if (!convertIdToGeckoString(cx, id, &idstr))
+    JSIDVariant idVar;
+    if (!toJSIDVariant(cx, id, &idVar))
         return false;
 
     PPropertyDescriptor descriptor;
     if (!fromDescriptor(cx, desc, &descriptor))
         return false;
 
     ReturnStatus status;
-    if (!CallDefineProperty(objId, idstr, descriptor, &status))
+    if (!CallDefineProperty(objId, idVar, descriptor, &status))
         return ipcfail(cx);
 
     LOG_STACK();
 
     return ok(cx, status);
 }
 
 bool
@@ -241,22 +241,22 @@ CPOWProxyHandler::delete_(JSContext *cx,
     FORWARD(delete_, (cx, proxy, id, bp));
 }
 
 bool
 WrapperOwner::delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
 {
     ObjectId objId = idOf(proxy);
 
-    nsString idstr;
-    if (!convertIdToGeckoString(cx, id, &idstr))
+    JSIDVariant idVar;
+    if (!toJSIDVariant(cx, id, &idVar))
         return false;
 
     ReturnStatus status;
-    if (!CallDelete(objId, idstr, &status, bp))
+    if (!CallDelete(objId, idVar, &status, bp))
         return ipcfail(cx);
 
     LOG_STACK();
 
     return ok(cx, status);
 }
 
 bool
@@ -277,22 +277,22 @@ CPOWProxyHandler::has(JSContext *cx, Han
     FORWARD(has, (cx, proxy, id, bp));
 }
 
 bool
 WrapperOwner::has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
 {
     ObjectId objId = idOf(proxy);
 
-    nsString idstr;
-    if (!convertIdToGeckoString(cx, id, &idstr))
+    JSIDVariant idVar;
+    if (!toJSIDVariant(cx, id, &idVar))
         return false;
 
     ReturnStatus status;
-    if (!CallHas(objId, idstr, &status, bp))
+    if (!CallHas(objId, idVar, &status, bp))
         return ipcfail(cx);
 
     LOG_STACK();
 
     return ok(cx, status);
 }
 
 bool
@@ -301,22 +301,22 @@ CPOWProxyHandler::hasOwn(JSContext *cx, 
     FORWARD(hasOwn, (cx, proxy, id, bp));
 }
 
 bool
 WrapperOwner::hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
 {
     ObjectId objId = idOf(proxy);
 
-    nsString idstr;
-    if (!convertIdToGeckoString(cx, id, &idstr))
+    JSIDVariant idVar;
+    if (!toJSIDVariant(cx, id, &idVar))
         return false;
 
     ReturnStatus status;
-    if (!CallHasOwn(objId, idstr, &status, bp))
+    if (!CallHasOwn(objId, idVar, &status, bp))
         return ipcfail(cx);
 
     LOG_STACK();
 
     return !!ok(cx, status);
 }
 
 bool
@@ -377,42 +377,43 @@ WrapperOwner::toString(JSContext *cx, Ha
         return false;
 
     args.rval().setString(str);
     return true;
 }
 
 bool
 WrapperOwner::get(JSContext *cx, HandleObject proxy, HandleObject receiver,
-		  HandleId id, MutableHandleValue vp)
+                  HandleId id, MutableHandleValue vp)
 {
     ObjectId objId = idOf(proxy);
 
     ObjectVariant receiverVar;
     if (!toObjectVariant(cx, receiver, &receiverVar))
         return false;
 
-    nsString idstr;
-    if (!convertIdToGeckoString(cx, id, &idstr))
+    JSIDVariant idVar;
+    if (!toJSIDVariant(cx, id, &idVar))
         return false;
 
     JSVariant val;
     ReturnStatus status;
-    if (!CallGet(objId, receiverVar, idstr, &status, &val))
+    if (!CallGet(objId, receiverVar, idVar, &status, &val))
         return ipcfail(cx);
 
     LOG_STACK();
 
     if (!ok(cx, status))
         return false;
 
     if (!fromVariant(cx, val, vp))
         return false;
 
-    if (idstr.EqualsLiteral("toString")) {
+    if (idVar.type() == JSIDVariant::TnsString &&
+        idVar.get_nsString().EqualsLiteral("toString")) {
         RootedFunction toString(cx, JS_NewFunction(cx, CPOWToString, 0, 0, proxy, "toString"));
         if (!toString)
             return false;
 
         RootedObject toStringObj(cx, JS_GetFunctionObject(toString));
 
         if (!JS_DefineProperty(cx, toStringObj, "__cpow__", vp, JSPROP_PERMANENT | JSPROP_READONLY))
             return false;
@@ -427,35 +428,35 @@ bool
 CPOWProxyHandler::set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
                       JS::HandleId id, bool strict, JS::MutableHandleValue vp) const
 {
     FORWARD(set, (cx, proxy, receiver, id, strict, vp));
 }
 
 bool
 WrapperOwner::set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
-		  JS::HandleId id, bool strict, JS::MutableHandleValue vp)
+                  JS::HandleId id, bool strict, JS::MutableHandleValue vp)
 {
     ObjectId objId = idOf(proxy);
 
     ObjectVariant receiverVar;
     if (!toObjectVariant(cx, receiver, &receiverVar))
         return false;
 
-    nsString idstr;
-    if (!convertIdToGeckoString(cx, id, &idstr))
+    JSIDVariant idVar;
+    if (!toJSIDVariant(cx, id, &idVar))
         return false;
 
     JSVariant val;
     if (!toVariant(cx, vp, &val))
         return false;
 
     ReturnStatus status;
     JSVariant result;
-    if (!CallSet(objId, receiverVar, idstr, strict, val, &status, &result))
+    if (!CallSet(objId, receiverVar, idVar, strict, val, &status, &result))
         return ipcfail(cx);
 
     LOG_STACK();
 
     if (!ok(cx, status))
         return false;
 
     return fromVariant(cx, result, vp);
--- a/js/ipc/WrapperOwner.h
+++ b/js/ipc/WrapperOwner.h
@@ -103,38 +103,38 @@ class WrapperOwner : public virtual Java
     bool ok(JSContext *cx, const ReturnStatus &status);
 
     bool inactive_;
 
     /*** Dummy call handlers ***/
   public:
     virtual bool SendDropObject(const ObjectId &objId) = 0;
     virtual bool CallPreventExtensions(const ObjectId &objId, ReturnStatus *rs) = 0;
-    virtual bool CallGetPropertyDescriptor(const ObjectId &objId, const nsString &id,
+    virtual bool CallGetPropertyDescriptor(const ObjectId &objId, const JSIDVariant &id,
                                            ReturnStatus *rs,
                                            PPropertyDescriptor *out) = 0;
     virtual bool CallGetOwnPropertyDescriptor(const ObjectId &objId,
-                                              const nsString &id,
+                                              const JSIDVariant &id,
                                               ReturnStatus *rs,
                                               PPropertyDescriptor *out) = 0;
-    virtual bool CallDefineProperty(const ObjectId &objId, const nsString &id,
+    virtual bool CallDefineProperty(const ObjectId &objId, const JSIDVariant &id,
                                     const PPropertyDescriptor &flags,
                                     ReturnStatus *rs) = 0;
-    virtual bool CallDelete(const ObjectId &objId, const nsString &id,
+    virtual bool CallDelete(const ObjectId &objId, const JSIDVariant &id,
                             ReturnStatus *rs, bool *success) = 0;
 
-    virtual bool CallHas(const ObjectId &objId, const nsString &id,
+    virtual bool CallHas(const ObjectId &objId, const JSIDVariant &id,
                          ReturnStatus *rs, bool *bp) = 0;
-    virtual bool CallHasOwn(const ObjectId &objId, const nsString &id,
+    virtual bool CallHasOwn(const ObjectId &objId, const JSIDVariant &id,
                             ReturnStatus *rs, bool *bp) = 0;
     virtual bool CallGet(const ObjectId &objId, const ObjectVariant &receiverVar,
-                         const nsString &id,
+                         const JSIDVariant &id,
                          ReturnStatus *rs, JSVariant *result) = 0;
     virtual bool CallSet(const ObjectId &objId, const ObjectVariant &receiverVar,
-                         const nsString &id, const bool &strict,
+                         const JSIDVariant &id, const bool &strict,
                          const JSVariant &value, ReturnStatus *rs, JSVariant *result) = 0;
 
     virtual bool CallIsExtensible(const ObjectId &objId, ReturnStatus *rs,
                                   bool *result) = 0;
     virtual bool CallCallOrConstruct(const ObjectId &objId, const nsTArray<JSParam> &argv,
                                      const bool &construct, ReturnStatus *rs, JSVariant *result,
                                      nsTArray<JSParam> *outparams) = 0;
     virtual bool CallHasInstance(const ObjectId &objId, const JSVariant &v,