From 93775369fd13e87fb9eb3ae94dbb2c81a9ba4e30 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Thu, 19 Feb 2015 14:36:26 -0500 Subject: [PATCH] Bug 1134112 part 1. When doing fast-init of a Web IDL dictionary, do fast-init of its dictionary members and its ancestors too. r=peterv --- dom/bindings/BindingDeclarations.h | 8 ++++++++ dom/bindings/Codegen.py | 30 +++++++++++++++++++++++++--- dom/bindings/test/TestCodeGen.webidl | 2 ++ 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/dom/bindings/BindingDeclarations.h b/dom/bindings/BindingDeclarations.h index 5b84610e9a1..27468993291 100644 --- a/dom/bindings/BindingDeclarations.h +++ b/dom/bindings/BindingDeclarations.h @@ -39,6 +39,14 @@ protected: bool StringifyToJSON(JSContext* aCx, JS::MutableHandle aValue, nsAString& aJSON) const; + + // Struct used as a way to force a dictionary constructor to not init the + // dictionary (via constructing from a pointer to this class). We're putting + // it here so that all the dictionaries will have access to it, but outside + // code will not. + struct FastDictionaryInitializer { + }; + private: // aString is expected to actually be an nsAString*. Should only be // called from StringifyToJSON. diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 8a0c025cabb..77ba217a6b0 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -11605,16 +11605,28 @@ class CGDictionary(CGThing): visibility="public", body=self.getMemberInitializer(m)) for m in self.memberInfo] + if d.parent: + # We always want to init our parent with our non-initializing + # constructor arg, because either we're about to init ourselves (and + # hence our parent) or we don't want any init happening. + baseConstructors = [ + "%s(%s)" % (self.makeClassName(d.parent), + self.getNonInitializingCtorArg()) + ] + else: + baseConstructors = None ctors = [ ClassConstructor( [], visibility="public", + baseConstructors=baseConstructors, body=( "// Safe to pass a null context if we pass a null value\n" "Init(nullptr, JS::NullHandleValue);\n")), ClassConstructor( - [Argument("int", "")], - visibility="protected", + [Argument("const FastDictionaryInitializer&", "")], + visibility="public", + baseConstructors=baseConstructors, explicit=True, bodyInHeader=True, body='// Do nothing here; this is used by our "Fast" subclass\n') @@ -11663,7 +11675,9 @@ class CGDictionary(CGThing): [], visibility="public", bodyInHeader=True, - baseConstructors=["%s(42)" % selfName], + baseConstructors=["%s(%s)" % + (selfName, + self.getNonInitializingCtorArg())], body="// Doesn't matter what int we pass to the parent constructor\n") fastStruct = CGClass("Fast" + selfName, @@ -11889,6 +11903,12 @@ class CGDictionary(CGThing): return "JS::UndefinedValue()" if type.isObject(): return "nullptr" + if type.isDictionary(): + # When we construct ourselves, we don't want to init our member + # dictionaries. Either we're being constructed-but-not-initialized + # ourselves (and then we don't want to init them) or we're about to + # init ourselves and then we'll init them anyway. + return CGDictionary.getNonInitializingCtorArg(); return None def getMemberSourceDescription(self, member): @@ -11899,6 +11919,10 @@ class CGDictionary(CGThing): def makeIdName(name): return IDLToCIdentifier(name) + "_id" + @staticmethod + def getNonInitializingCtorArg(): + return "FastDictionaryInitializer()" + @staticmethod def isDictionaryCopyConstructible(dictionary): if (dictionary.parent and diff --git a/dom/bindings/test/TestCodeGen.webidl b/dom/bindings/test/TestCodeGen.webidl index 20128743072..edfe852a60f 100644 --- a/dom/bindings/test/TestCodeGen.webidl +++ b/dom/bindings/test/TestCodeGen.webidl @@ -990,6 +990,8 @@ dictionary Dict : ParentDict { required long requiredLong; required object requiredObject; + + CustomEventInit customEventInit; }; dictionary ParentDict : GrandparentDict {