diff --git a/dom/bindings/parser/WebIDL.py b/dom/bindings/parser/WebIDL.py
index 715e5e3cec2fdf42975965525e4152fc8309f998..f1fafb56c05bcde2c4922d622b7c453f024c7ee4 100644
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -283,6 +283,9 @@ class IDLScope(IDLObject):
             self._dict[identifier.name] = replacement
             return
 
+        self.addNewIdentifier(identifier, object)
+
+    def addNewIdentifier(self, identifier, object):
         assert object
 
         self._dict[identifier.name] = object
@@ -323,6 +326,9 @@ class IDLScope(IDLObject):
             return originalObject.addOverload(newObject)
 
         # Default to throwing, derived classes can override.
+        raise self.createIdentifierConflictError(identifier, originalObject, newObject)
+
+    def createIdentifierConflictError(self, identifier, originalObject, newObject):
         conflictdesc = "\n\t%s at %s\n\t%s at %s" % (
             originalObject,
             originalObject.location,
@@ -330,7 +336,7 @@ class IDLScope(IDLObject):
             newObject.location,
         )
 
-        raise WebIDLError(
+        return WebIDLError(
             "Multiple unresolvable definitions of identifier '%s' in scope '%s'%s"
             % (identifier.name, str(self), conflictdesc),
             [],
@@ -727,6 +733,15 @@ def globalNameSetToExposureSet(globalScope, nameSet, exposureSet):
         exposureSet.update(globalScope.globalNameMapping[name])
 
 
+# Because WebIDL allows static and regular operations with the same identifier
+# we use a special class to be able to store them both in the scope for the
+# same identifier.
+class IDLOperations:
+    def __init__(self, static=None, regular=None):
+        self.static = static
+        self.regular = regular
+
+
 class IDLInterfaceOrInterfaceMixinOrNamespace(IDLObjectWithScope, IDLExposureMixins):
     def __init__(self, location, parentScope, name):
         assert isinstance(parentScope, IDLScope)
@@ -756,15 +771,66 @@ class IDLInterfaceOrInterfaceMixinOrNamespace(IDLObjectWithScope, IDLExposureMix
             self.addExtendedAttributes(partial.propagatedExtendedAttrs)
             self.members.extend(partial.members)
 
+    def addNewIdentifier(self, identifier, object):
+        if isinstance(object, IDLMethod):
+            if object.isStatic():
+                object = IDLOperations(static=object)
+            else:
+                object = IDLOperations(regular=object)
+
+        IDLScope.addNewIdentifier(self, identifier, object)
+
     def resolveIdentifierConflict(self, scope, identifier, originalObject, newObject):
         assert isinstance(scope, IDLScope)
-        assert isinstance(originalObject, IDLInterfaceMember)
         assert isinstance(newObject, IDLInterfaceMember)
 
+        # The identifier of a regular operation or static operation must not be
+        # the same as the identifier of a constant or attribute.
+        if isinstance(newObject, IDLMethod) != isinstance(
+            originalObject, IDLOperations
+        ):
+            if isinstance(originalObject, IDLOperations):
+                if originalObject.regular is not None:
+                    originalObject = originalObject.regular
+                else:
+                    assert originalObject.static is not None
+                    originalObject = originalObject.static
+
+            raise self.createIdentifierConflictError(
+                identifier, originalObject, newObject
+            )
+
+        if isinstance(newObject, IDLMethod):
+            originalOperations = originalObject
+            if newObject.isStatic():
+                if originalOperations.static is None:
+                    originalOperations.static = newObject
+                    return originalOperations
+
+                originalObject = originalOperations.static
+            else:
+                if originalOperations.regular is None:
+                    originalOperations.regular = newObject
+                    return originalOperations
+
+                originalObject = originalOperations.regular
+
+            assert isinstance(originalObject, IDLMethod)
+        else:
+            assert isinstance(originalObject, IDLInterfaceMember)
+
         retval = IDLScope.resolveIdentifierConflict(
             self, scope, identifier, originalObject, newObject
         )
 
+        if isinstance(newObject, IDLMethod):
+            if newObject.isStatic():
+                originalOperations.static = retval
+            else:
+                originalOperations.regular = retval
+
+            retval = originalOperations
+
         # Might be a ctor, which isn't in self.members
         if newObject in self.members:
             self.members.remove(newObject)
@@ -995,7 +1061,7 @@ class IDLInterfaceOrNamespace(IDLInterfaceOrInterfaceMixinOrNamespace):
             self.location, "constructor", allowForbidden=True
         )
         try:
-            return self._lookupIdentifier(identifier)
+            return self._lookupIdentifier(identifier).static
         except Exception:
             return None
 
@@ -4568,7 +4634,12 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
         for member in members:
             # Check that there are no disallowed members
             if member.identifier.name in self.disallowedMemberNames and not (
-                (member.isMethod() and member.isMaplikeOrSetlikeOrIterableMethod())
+                (
+                    member.isMethod()
+                    and (
+                        member.isStatic() or member.isMaplikeOrSetlikeOrIterableMethod()
+                    )
+                )
                 or (member.isAttr() and member.isMaplikeOrSetlikeAttr())
             ):
                 raise WebIDLError(
@@ -4634,9 +4705,7 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
                 self.disallowedNonMethodNames.append(name)
         # If allowExistingOperations is True, and another operation exists
         # with the same name as the one we're trying to add, don't add the
-        # maplike/setlike operation. However, if the operation is static,
-        # then fail by way of creating the function, which will cause a
-        # naming conflict, per the spec.
+        # maplike/setlike operation.
         if allowExistingOperations:
             for m in members:
                 if m.identifier.name == name and m.isMethod() and not m.isStatic():
diff --git a/dom/bindings/parser/tests/test_interface_identifier_conflicts_across_members.py b/dom/bindings/parser/tests/test_interface_identifier_conflicts_across_members.py
index abafda9677f8c19e5b9cb00088f652ce81d8b1bd..d8398d46ba768165f39408e22707d40de937d2e6 100644
--- a/dom/bindings/parser/tests/test_interface_identifier_conflicts_across_members.py
+++ b/dom/bindings/parser/tests/test_interface_identifier_conflicts_across_members.py
@@ -14,8 +14,9 @@ def WebIDLTest(parser, harness):
     except Exception:
         threw = True
 
-    harness.ok(threw, "Should have thrown.")
+    harness.ok(threw, "Should have thrown for IdentifierConflictAcrossMembers1.")
 
+    parser = parser.reset()
     threw = False
     try:
         parser.parse(
@@ -31,8 +32,9 @@ def WebIDLTest(parser, harness):
     except Exception:
         threw = True
 
-    harness.ok(threw, "Should have thrown.")
+    harness.ok(threw, "Should have thrown for IdentifierConflictAcrossMembers2.")
 
+    parser = parser.reset()
     threw = False
     try:
         parser.parse(
@@ -48,13 +50,14 @@ def WebIDLTest(parser, harness):
     except Exception:
         threw = True
 
-    harness.ok(threw, "Should have thrown.")
+    harness.ok(threw, "Should have thrown for IdentifierConflictAcrossMembers3.")
 
+    parser = parser.reset()
     threw = False
     try:
         parser.parse(
             """
-            interface IdentifierConflictAcrossMembers1 {
+            interface IdentifierConflictAcrossMembers4 {
               const byte thing1 = 1;
               long thing1();
             };
@@ -65,4 +68,101 @@ def WebIDLTest(parser, harness):
     except Exception:
         threw = True
 
-    harness.ok(threw, "Should have thrown.")
+    harness.ok(threw, "Should have thrown for IdentifierConflictAcrossMembers4.")
+
+    parser = parser.reset()
+    threw = False
+    try:
+        parser.parse(
+            """
+            interface IdentifierConflictAcrossMembers5 {
+              static long thing1();
+              undefined thing1();
+            };
+        """
+        )
+
+        parser.finish()
+    except Exception:
+        threw = True
+
+    harness.ok(
+        not threw, "Should not have thrown for IdentifierConflictAcrossMembers5."
+    )
+
+    parser = parser.reset()
+    threw = False
+    try:
+        parser.parse(
+            """
+            interface mixin IdentifierConflictAcrossMembers6Mixin {
+              undefined thing1();
+            };
+            interface IdentifierConflictAcrossMembers6 {
+              static long thing1();
+            };
+            IdentifierConflictAcrossMembers6 includes IdentifierConflictAcrossMembers6Mixin;
+        """
+        )
+
+        parser.finish()
+    except Exception:
+        threw = True
+
+    harness.ok(
+        not threw, "Should not have thrown for IdentifierConflictAcrossMembers6."
+    )
+
+    parser = parser.reset()
+    threw = False
+    try:
+        parser.parse(
+            """
+            interface IdentifierConflictAcrossMembers7 {
+              const byte thing1 = 1;
+              static readonly attribute long thing1;
+            };
+        """
+        )
+
+        parser.finish()
+    except Exception:
+        threw = True
+
+    harness.ok(threw, "Should have thrown for IdentifierConflictAcrossMembers7.")
+
+    parser = parser.reset()
+    threw = False
+    try:
+        parser.parse(
+            """
+            interface IdentifierConflictAcrossMembers8 {
+              readonly attribute long thing1 = 1;
+              static readonly attribute long thing1;
+            };
+        """
+        )
+
+        parser.finish()
+    except Exception:
+        threw = True
+
+    harness.ok(threw, "Should have thrown for IdentifierConflictAcrossMembers8.")
+
+    parser = parser.reset()
+    threw = False
+    try:
+        parser.parse(
+            """
+            interface IdentifierConflictAcrossMembers9 {
+              void thing1();
+              static readonly attribute long thing1;
+            };
+        """
+        )
+
+        parser.finish()
+    except Exception:
+        threw = True
+
+    harness.ok(threw, "Should have thrown for IdentifierConflictAcrossMembers9.")
diff --git a/dom/bindings/parser/tests/test_interface_maplikesetlikeiterable.py b/dom/bindings/parser/tests/test_interface_maplikesetlikeiterable.py
index dcff52b8c661ff35f69ae432a32ec2d310c572a2..fdd9c009653205393c5d3265eee4bdeb95c1b747 100644
--- a/dom/bindings/parser/tests/test_interface_maplikesetlikeiterable.py
+++ b/dom/bindings/parser/tests/test_interface_maplikesetlikeiterable.py
@@ -19,7 +19,10 @@ def WebIDLTest(parser, harness):
         expectedMembers = list(expectedMembers)
         for m in results[0].members:
             name = m.identifier.name
-            if (name, type(m)) in expectedMembers:
+            if m.isMethod() and m.isStatic():
+                # None of the expected members are static methods, so ignore those.
+                harness.ok(True, "%s - %s - Should be a %s" % (prefix, name, type(m)))
+            elif (name, type(m)) in expectedMembers:
                 harness.ok(True, "%s - %s - Should be a %s" % (prefix, name, type(m)))
                 expectedMembers.remove((name, type(m)))
             else:
@@ -91,12 +94,23 @@ def WebIDLTest(parser, harness):
     valueAsyncIterableMembers = [("__iterable", WebIDL.IDLAsyncIterable)]
     valueAsyncIterableMembers.append(("values", WebIDL.IDLMethod))
 
-    disallowedIterableNames = ["keys", "entries", "values"]
-    disallowedMemberNames = ["forEach", "has", "size"] + disallowedIterableNames
-    mapDisallowedMemberNames = ["get"] + disallowedMemberNames
-    disallowedNonMethodNames = ["clear", "delete"]
-    mapDisallowedNonMethodNames = ["set"] + disallowedNonMethodNames
-    setDisallowedNonMethodNames = ["add"] + disallowedNonMethodNames
+    disallowedIterableNames = [
+        ("keys", WebIDL.IDLMethod),
+        ("entries", WebIDL.IDLMethod),
+        ("values", WebIDL.IDLMethod),
+    ]
+    disallowedMemberNames = [
+        ("forEach", WebIDL.IDLMethod),
+        ("has", WebIDL.IDLMethod),
+        ("size", WebIDL.IDLAttribute),
+    ] + disallowedIterableNames
+    mapDisallowedMemberNames = [("get", WebIDL.IDLMethod)] + disallowedMemberNames
+    disallowedNonMethodNames = [
+        ("clear", WebIDL.IDLMethod),
+        ("delete", WebIDL.IDLMethod),
+    ]
+    mapDisallowedNonMethodNames = [("set", WebIDL.IDLMethod)] + disallowedNonMethodNames
+    setDisallowedNonMethodNames = [("add", WebIDL.IDLMethod)] + disallowedNonMethodNames
     unrelatedMembers = [
         ("unrelatedAttribute", WebIDL.IDLAttribute),
         ("unrelatedMethod", WebIDL.IDLMethod),
@@ -560,7 +574,9 @@ def WebIDLTest(parser, harness):
     # Member name collision tests
     #
 
-    def testConflictingMembers(likeMember, conflictName, expectedMembers, methodPasses):
+    def testConflictingMembers(
+        likeMember, conflict, expectedMembers, methodPasses, numProductions=1
+    ):
         """
         Tests for maplike/setlike member generation against conflicting member
         names. If methodPasses is True, this means we expect the interface to
@@ -568,6 +584,7 @@ def WebIDLTest(parser, harness):
         list of interface members to check against on the passing interface.
 
         """
+        (conflictName, conflictType) = conflict
         if methodPasses:
             shouldPass(
                 "Conflicting method: %s and %s" % (likeMember, conflictName),
@@ -606,16 +623,30 @@ def WebIDLTest(parser, harness):
                    """
             % (conflictName, likeMember),
         )
-        shouldFail(
-            "Conflicting static method: %s and %s" % (likeMember, conflictName),
-            """
-                   interface Foo1 {
-                   %s;
-                   static undefined %s(long test1, double test2, double test3);
-                   };
-                   """
-            % (likeMember, conflictName),
-        )
+        if conflictType == WebIDL.IDLAttribute:
+            shouldFail(
+                "Conflicting static method: %s and %s" % (likeMember, conflictName),
+                """
+                       interface Foo1 {
+                       %s;
+                       static undefined %s(long test1, double test2, double test3);
+                       };
+                       """
+                % (likeMember, conflictName),
+            )
+        else:
+            shouldPass(
+                "Conflicting static method: %s and %s" % (likeMember, conflictName),
+                """
+                       interface Foo1 {
+                       %s;
+                       static undefined %s(long test1, double test2, double test3);
+                       };
+                       """
+                % (likeMember, conflictName),
+                expectedMembers,
+                numProductions=numProductions,
+            )
         shouldFail(
             "Conflicting attribute: %s and %s" % (likeMember, conflictName),
             """
@@ -648,7 +679,9 @@ def WebIDLTest(parser, harness):
         )
 
     for member in disallowedIterableNames:
-        testConflictingMembers("iterable<long, long>", member, iterableMembers, False)
+        testConflictingMembers(
+            "iterable<long, long>", member, iterableMembers, False, numProductions=2
+        )
     for member in mapDisallowedMemberNames:
         testConflictingMembers("maplike<long, long>", member, mapRWMembers, False)
     for member in disallowedMemberNames: