Bug 804319. Implement parsing of the "stringifier;" shorthand. r=khuey
authorBoris Zbarsky <bzbarsky@mit.edu>
Mon, 05 Nov 2012 14:40:32 -0500
changeset 112340 287f8cf1f1e163e07e6b0addbfa1e7258ceb8677
parent 112339 bc191fe62b436ff9b265110ba16d09af7bb9c863
child 112341 d56f12af4cd16521030bc708e1963cd531602c5e
push id17526
push userbzbarsky@mozilla.com
push dateMon, 05 Nov 2012 19:40:57 +0000
treeherdermozilla-inbound@13a34f4d0d67 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey
bugs804319
milestone19.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 804319. Implement parsing of the "stringifier;" shorthand. r=khuey
dom/bindings/Bindings.conf
dom/bindings/parser/WebIDL.py
dom/bindings/parser/tests/test_stringifier.py
dom/bindings/test/TestBindingHeader.h
dom/bindings/test/TestCodeGen.webidl
dom/bindings/test/TestExampleGen.webidl
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -503,17 +503,18 @@ DOMInterfaces = {
                                'ReceiveWeakCallbackInterface',
                                'ReceiveWeakNullableCallbackInterface',
                                'receiveWeakCastableObjectSequence',
                                'receiveWeakNullableCastableObjectSequence',
                                'receiveWeakCastableObjectNullableSequence',
                                'receiveWeakNullableCastableObjectNullableSequence' ],
         'binaryNames': { 'methodRenamedFrom': 'methodRenamedTo',
                          'attributeGetterRenamedFrom': 'attributeGetterRenamedTo',
-                         'attributeRenamedFrom': 'attributeRenamedTo' }
+                         'attributeRenamedFrom': 'attributeRenamedTo',
+                         '__stringifier' : 'Stringify' }
         },
 
 'TestNonCastableInterface' : {
         'headerFile': 'TestBindingHeader.h',
         'register': False,
         'castable': False
         },
 
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -595,45 +595,49 @@ class IDLInterface(IDLObjectWithScope):
             self.members.extend(additionalMembers)
 
         for ancestor in self.getInheritedInterfaces():
             ancestor.interfacesBasedOnSelf.add(self)
             for ancestorConsequential in ancestor.getConsequentialInterfaces():
                 ancestorConsequential.interfacesBasedOnSelf.add(self)
 
         # Ensure that there's at most one of each {named,indexed}
-        # {getter,setter,creator,deleter}.
-        specialMembersSeen = set()
+        # {getter,setter,creator,deleter} and at most one stringifier.
+        specialMembersSeen = {}
         for member in self.members:
             if not member.isMethod():
                 continue
 
             if member.isGetter():
                 memberType = "getters"
             elif member.isSetter():
                 memberType = "setters"
             elif member.isCreator():
                 memberType = "creators"
             elif member.isDeleter():
                 memberType = "deleters"
+            elif member.isStringifier():
+                memberType = "stringifiers"
             else:
                 continue
 
-            if member.isNamed():
-                memberType = "named " + memberType
-            elif member.isIndexed():
-                memberType = "indexed " + memberType
-            else:
-                continue
+            if memberType != "stringifiers":
+                if member.isNamed():
+                    memberType = "named " + memberType
+                else:
+                    assert member.isIndexed()
+                    memberType = "indexed " + memberType
 
             if memberType in specialMembersSeen:
                 raise WebIDLError("Multiple " + memberType + " on %s" % (self),
-                                   [self.location])
-
-            specialMembersSeen.add(memberType)
+                                   [self.location,
+                                    specialMembersSeen[memberType].location,
+                                    member.location])
+
+            specialMembersSeen[memberType] = member
 
     def validate(self):
         for member in self.members:
             member.validate()
 
             # Check that PutForwards refers to another attribute and that no
             # cycles exist in forwarded assignments.
             if member.isAttr():
@@ -3294,16 +3298,30 @@ class Parser(Tokenizer):
                  "stringifier" if stringifier else ""), allowDoubleUnderscore=True)
 
         method = IDLMethod(self.getLocation(p, 2), identifier, returnType, arguments,
                            static=static, getter=getter, setter=setter, creator=creator,
                            deleter=deleter, specialType=specialType,
                            legacycaller=legacycaller, stringifier=stringifier)
         p[0] = method
 
+    def p_Stringifier(self, p):
+        """
+            Operation : STRINGIFIER SEMICOLON
+        """
+        identifier = IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
+                                             "__stringifier",
+                                             allowDoubleUnderscore=True)
+        method = IDLMethod(self.getLocation(p, 1),
+                           identifier,
+                           returnType=BuiltinTypes[IDLBuiltinType.Types.domstring],
+                           arguments=[],
+                           stringifier=True)
+        p[0] = method
+
     def p_QualifierStatic(self, p):
         """
             Qualifier : STATIC
         """
         p[0] = [IDLInterfaceMember.Special.Static]
 
     def p_QualifierStringifier(self, p):
         """
new file mode 100644
--- /dev/null
+++ b/dom/bindings/parser/tests/test_stringifier.py
@@ -0,0 +1,46 @@
+import WebIDL
+
+def WebIDLTest(parser, harness):
+    parser.parse("""
+        interface TestStringifier {
+          stringifier;
+        };
+    """)
+
+    results = parser.finish()
+
+    harness.ok(isinstance(results[0].members[0], WebIDL.IDLMethod),
+               "Stringifer should be method")
+
+    parser = parser.reset()
+
+    threw = False
+    try:
+        parser.parse("""
+            interface TestStringifier {
+              stringifier;
+              stringifier;
+            };
+        """)
+        results = parser.finish()
+    except:
+        threw = True
+
+    harness.ok(threw, "Should not allow two 'stringifier;'")
+
+    parser = parser.reset()
+
+    threw = False
+    try:
+        parser.parse("""
+            interface TestStringifier {
+              stringifier;
+              stringifier DOMString foo();
+            };
+        """)
+        results = parser.finish()
+    except:
+        threw = True
+
+    harness.ok(threw, "Should not allow a 'stringifier;' and a 'stringifier()'")
+
--- a/dom/bindings/test/TestBindingHeader.h
+++ b/dom/bindings/test/TestBindingHeader.h
@@ -433,16 +433,17 @@ public:
   static bool StaticAttribute(nsISupports*);
   static void SetStaticAttribute(nsISupports*, bool);
 
   // Miscellania
   int32_t AttrWithLenientThis();
   void SetAttrWithLenientThis(int32_t);
   uint32_t UnforgeableAttr();
   uint32_t UnforgeableAttr2();
+  void Stringify(nsString&);
   void PassRenamedInterface(nsRenamedInterface&);
   TestInterface* PutForwardsAttr();
   TestInterface* PutForwardsAttr2();
   TestInterface* PutForwardsAttr3();
 
   // Methods and properties imported via "implements"
   bool ImplementedProperty();
   void SetImplementedProperty(bool);
--- a/dom/bindings/test/TestCodeGen.webidl
+++ b/dom/bindings/test/TestCodeGen.webidl
@@ -337,16 +337,17 @@ interface TestInterface {
   // Static methods and attributes
   static attribute boolean staticAttribute;
   static void staticMethod(boolean arg);
 
   // Miscellania
   [LenientThis] attribute long attrWithLenientThis;
   [Unforgeable] readonly attribute long unforgeableAttr;
   [Unforgeable, ChromeOnly] readonly attribute long unforgeableAttr2;
+  stringifier;
   void passRenamedInterface(TestRenamedInterface arg);
   [PutForwards=writableByte] readonly attribute TestInterface putForwardsAttr;
   [PutForwards=writableByte, LenientThis] readonly attribute TestInterface putForwardsAttr2;
   [PutForwards=writableByte, ChromeOnly] readonly attribute TestInterface putForwardsAttr3;
 
   // If you add things here, add them to TestExampleGen as well
 };
 
--- a/dom/bindings/test/TestExampleGen.webidl
+++ b/dom/bindings/test/TestExampleGen.webidl
@@ -304,15 +304,16 @@ interface TestExampleInterface {
   // Static methods and attributes
   static attribute boolean staticAttribute;
   static void staticMethod(boolean arg);
 
   // Miscellania
   [LenientThis] attribute long attrWithLenientThis;
   [Unforgeable] readonly attribute long unforgeableAttr;
   [Unforgeable, ChromeOnly] readonly attribute long unforgeableAttr2;
+  stringifier;
   void passRenamedInterface(TestRenamedInterface arg);
   [PutForwards=writableByte] readonly attribute TestExampleInterface putForwardsAttr;
   [PutForwards=writableByte, LenientThis] readonly attribute TestExampleInterface putForwardsAttr2;
   [PutForwards=writableByte, ChromeOnly] readonly attribute TestExampleInterface putForwardsAttr3;
 
   // If you add things here, add them to TestCodeGen as well
 };