Bug 1071177 - Introduce JSIDVariant type for CPOWs. r=billm
authorTom Schuster <evilpies@gmail.com>
Tue, 07 Oct 2014 11:29:02 +0200
changeset 232347 765ab5eaab5b12281c1cbad4c8a0828e37c92ba7
parent 232346 27626f68637d6c531ba0836dce5b8785e5d39510
child 232348 6e6f184e59285a2dcdf106c830e7ec0db2da6a97
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs1071177
milestone35.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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,