Bug 797806 - Helper method to handle stringified JSON in C++. r=khuey, a=bajaj
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Tue, 16 Oct 2012 17:52:10 +0300
changeset 113661 5e57959751ed00c02ca6fc1f69eb786e343fc326
parent 113660 2b2fd1afed3d8ffd38698c58a5f3d19d7d26d768
child 113662 85293aa3815ed30364ea4e032afc013a82a80298
push id2453
push userryanvm@gmail.com
push dateFri, 26 Oct 2012 01:49:42 +0000
treeherdermozilla-aurora@15d6d97a9b5d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey, bajaj
bugs797806
milestone18.0a2
Bug 797806 - Helper method to handle stringified JSON in C++. r=khuey, a=bajaj
dom/bindings/BindingUtils.cpp
dom/bindings/BindingUtils.h
dom/bindings/Codegen.py
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -5,16 +5,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <stdarg.h>
 
 #include "BindingUtils.h"
 
 #include "WrapperFactory.h"
 #include "xpcprivate.h"
+#include "nsContentUtils.h"
 #include "XPCQuickStubs.h"
 
 namespace mozilla {
 namespace dom {
 
 JSErrorFormatString ErrorFormatString[] = {
 #define MSG_DEF(_name, _argc, _str) \
   { _str, _argc, JSEXN_TYPEERR },
@@ -645,10 +646,29 @@ SetXrayExpandoChain(JSObject* obj, JSObj
   JS::Value v = chain ? JS::ObjectValue(*chain) : JSVAL_VOID;
   if (IsDOMProxy(obj)) {
     js::SetProxyExtra(obj, JSPROXYSLOT_XRAY_EXPANDO, v);
   } else {
     js::SetReservedSlot(obj, DOM_XRAY_EXPANDO_SLOT, v);
   }
 }
 
+JSContext*
+MainThreadDictionaryBase::ParseJSON(const nsAString& aJSON,
+                                    mozilla::Maybe<JSAutoRequest>& aAr,
+                                    mozilla::Maybe<JSAutoCompartment>& aAc,
+                                    JS::Value& aVal)
+{
+  JSContext* cx = nsContentUtils::ThreadJSContextStack()->GetSafeJSContext();
+  NS_ENSURE_TRUE(cx, nullptr);
+  JSObject* global = JS_GetGlobalObject(cx);
+  aAr.construct(cx);
+  aAc.construct(cx, global);
+  if (!JS_ParseJSON(cx,
+                    static_cast<const jschar*>(PromiseFlatString(aJSON).get()),
+                    aJSON.Length(), &aVal)) {
+    return nullptr;
+  }
+  return cx;
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -1167,12 +1167,21 @@ MustInheritFromNonRefcountedDOMObject(No
 {
 }
 
 // Set the chain of expando objects for various consumers of the given object.
 // For Paris Bindings only. See the relevant infrastructure in XrayWrapper.cpp.
 JSObject* GetXrayExpandoChain(JSObject *obj);
 void SetXrayExpandoChain(JSObject *obj, JSObject *chain);
 
+struct MainThreadDictionaryBase
+{
+protected:
+  JSContext* ParseJSON(const nsAString& aJSON,
+                       mozilla::Maybe<JSAutoRequest>& aAr,
+                       mozilla::Maybe<JSAutoCompartment>& aAc,
+                       JS::Value& aVal);
+};
+
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_BindingUtils_h__ */
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -5336,26 +5336,41 @@ class CGDictionary(CGThing):
             self.generatable = False
 
     def declare(self):
         if not self.generatable:
             return ""
         d = self.dictionary
         if d.parent:
             inheritance = ": public %s " % self.makeClassName(d.parent)
+        elif not self.workers:
+            inheritance = ": public MainThreadDictionaryBase "
         else:
             inheritance = ""
         memberDecls = ["  %s %s;" %
                        (self.getMemberType(m), m[0].identifier.name)
                        for m in self.memberInfo]
 
         return (string.Template(
                 "struct ${selfName} ${inheritance}{\n"
                 "  ${selfName}() {}\n"
                 "  bool Init(JSContext* cx, const JS::Value& val);\n"
+                "  \n" +
+                ("  bool Init(const nsAString& aJSON)\n"
+                 "  {\n"
+                 "    if (aJSON.IsEmpty()) {\n"
+                 "      return true;\n"
+                 "    }\n"
+                 "    mozilla::Maybe<JSAutoRequest> ar;\n"
+                 "    mozilla::Maybe<JSAutoCompartment> ac;\n"
+                 "    jsval json = JSVAL_VOID;\n"
+                 "    JSContext* cx = ParseJSON(aJSON, ar, ac, json);\n"
+                 "    NS_ENSURE_TRUE(cx, false);\n"
+                 "    return Init(cx, json);\n"
+                 "  }\n" if not self.workers else "") +
                 "\n" +
                 "\n".join(memberDecls) + "\n"
                 "private:\n"
                 "  // Disallow copy-construction\n"
                 "  ${selfName}(const ${selfName}&) MOZ_DELETE;\n" +
                 # NOTE: jsids are per-runtime, so don't use them in workers
                 ("  static bool InitIds(JSContext* cx);\n"
                  "  static bool initedIds;\n" if not self.workers else "") +