aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/bindings/codegen/parser
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2019-02-25 11:48:45 +0530
committerManish Goregaokar <manishsmail@gmail.com>2019-03-01 16:58:46 +0530
commit8f5db8a7e114ec9a6705da5284f9e5abc3bc7cd2 (patch)
tree6165f7e9338d3e491cc8774c081178229ecf2806 /components/script/dom/bindings/codegen/parser
parent427003210b3e16a82f958e35ff4212f26ffa35ab (diff)
downloadservo-8f5db8a7e114ec9a6705da5284f9e5abc3bc7cd2.tar.gz
servo-8f5db8a7e114ec9a6705da5284f9e5abc3bc7cd2.zip
Update webidl.py from upstream
Diffstat (limited to 'components/script/dom/bindings/codegen/parser')
-rw-r--r--components/script/dom/bindings/codegen/parser/WebIDL.py148
-rw-r--r--components/script/dom/bindings/codegen/parser/abstract.patch10
-rw-r--r--components/script/dom/bindings/codegen/parser/callback-location.patch14
-rw-r--r--components/script/dom/bindings/codegen/parser/debug.patch2
-rw-r--r--components/script/dom/bindings/codegen/parser/inline.patch6
-rw-r--r--components/script/dom/bindings/codegen/parser/pref-main-thread.patch28
-rw-r--r--components/script/dom/bindings/codegen/parser/tests/test_dictionary.py43
-rw-r--r--components/script/dom/bindings/codegen/parser/tests/test_lenientSetter.py2
-rw-r--r--components/script/dom/bindings/codegen/parser/tests/test_replaceable.py2
-rw-r--r--components/script/dom/bindings/codegen/parser/undo-dictionary-optional.patch12
-rw-r--r--components/script/dom/bindings/codegen/parser/union-typedef.patch16
-rwxr-xr-xcomponents/script/dom/bindings/codegen/parser/update.sh1
12 files changed, 191 insertions, 93 deletions
diff --git a/components/script/dom/bindings/codegen/parser/WebIDL.py b/components/script/dom/bindings/codegen/parser/WebIDL.py
index 59e32fb7b17..95cf21a65ed 100644
--- a/components/script/dom/bindings/codegen/parser/WebIDL.py
+++ b/components/script/dom/bindings/codegen/parser/WebIDL.py
@@ -1,6 +1,6 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at https://mozilla.org/MPL/2.0/.
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
""" A WebIDL parser. """
@@ -248,8 +248,14 @@ class IDLScope(IDLObject):
return self.QName()
def QName(self):
- if self._name:
- return self._name.QName() + "::"
+ # It's possible for us to be called before __init__ has been called, for
+ # the IDLObjectWithScope case. In that case, self._name won't be set yet.
+ if hasattr(self, "_name"):
+ name = self._name
+ else:
+ name = None
+ if name:
+ return name.QName() + "::"
return "::"
def ensureUnique(self, identifier, object):
@@ -327,6 +333,13 @@ class IDLScope(IDLObject):
assert identifier.scope == self
return self._lookupIdentifier(identifier)
+ def addIfaceGlobalNames(self, interfaceName, globalNames):
+ """Record the global names (from |globalNames|) that can be used in
+ [Exposed] to expose things in a global named |interfaceName|"""
+ self.globalNames.update(globalNames)
+ for name in globalNames:
+ self.globalNameMapping[name].add(interfaceName)
+
class IDLIdentifier(IDLObject):
def __init__(self, location, scope, name):
@@ -504,8 +517,10 @@ class IDLExposureMixins():
return 'Window' in self.exposureSet
def isExposedOnMainThread(self):
- return (self.isExposedInWindow() or
- self.isExposedInSystemGlobals())
+ return self.isExposedInWindow()
+
+ def isExposedOffMainThread(self):
+ return len(self.exposureSet - {'Window', 'FakeTestPrimaryGlobal'}) > 0
def isExposedInAnyWorker(self):
return len(self.getWorkerExposureSet()) > 0
@@ -516,9 +531,6 @@ class IDLExposureMixins():
def isExposedInAnyWorklet(self):
return len(self.getWorkletExposureSet()) > 0
- def isExposedInSystemGlobals(self):
- return 'BackstagePass' in self.exposureSet
-
def isExposedInSomeButNotAllWorkers(self):
"""
Returns true if the Exposed extended attribute for this interface
@@ -597,6 +609,34 @@ class IDLExternalInterface(IDLObjectWithIdentifier, IDLExposureMixins):
return set()
+class IDLPartialDictionary(IDLObject):
+ def __init__(self, location, name, members, nonPartialDictionary):
+ assert isinstance(name, IDLUnresolvedIdentifier)
+
+ IDLObject.__init__(self, location)
+ self.identifier = name
+ self.members = members
+ self._nonPartialDictionary = nonPartialDictionary
+ self._finished = False
+ nonPartialDictionary.addPartialDictionary(self)
+
+ def addExtendedAttributes(self, attrs):
+ pass
+
+ def finish(self, scope):
+ if self._finished:
+ return
+ self._finished = True
+
+ # Need to make sure our non-partial dictionary gets
+ # finished so it can report cases when we only have partial
+ # dictionaries.
+ self._nonPartialDictionary.finish(scope)
+
+ def validate(self):
+ pass
+
+
class IDLPartialInterfaceOrNamespace(IDLObject):
def __init__(self, location, name, members, nonPartialInterfaceOrNamespace):
assert isinstance(name, IDLUnresolvedIdentifier)
@@ -1322,7 +1362,6 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
for bindingAlias in member.bindingAliases:
checkDuplicateNames(member, bindingAlias, "BindingAlias")
-
# Conditional exposure makes no sense for interfaces with no
# interface object, unless they're navigator properties.
# And SecureContext makes sense for interfaces with no interface object,
@@ -1704,9 +1743,8 @@ class IDLInterface(IDLInterfaceOrNamespace):
self.globalNames = attr.args()
else:
self.globalNames = [self.identifier.name]
- self.parentScope.globalNames.update(self.globalNames)
- for globalName in self.globalNames:
- self.parentScope.globalNameMapping[globalName].add(self.identifier.name)
+ self.parentScope.addIfaceGlobalNames(self.identifier.name,
+ self.globalNames)
self._isOnGlobalProtoChain = True
elif identifier == "PrimaryGlobal":
if not attr.noArguments():
@@ -1719,8 +1757,8 @@ class IDLInterface(IDLInterfaceOrNamespace):
self.parentScope.primaryGlobalAttr.location])
self.parentScope.primaryGlobalAttr = attr
self.parentScope.primaryGlobalName = self.identifier.name
- self.parentScope.globalNames.add(self.identifier.name)
- self.parentScope.globalNameMapping[self.identifier.name].add(self.identifier.name)
+ self.parentScope.addIfaceGlobalNames(self.identifier.name,
+ [self.identifier.name])
self._isOnGlobalProtoChain = True
elif identifier == "SecureContext":
if not attr.noArguments():
@@ -1743,7 +1781,6 @@ class IDLInterface(IDLInterfaceOrNamespace):
identifier == "LegacyUnenumerableNamedProperties" or
identifier == "RunConstructorInCallerCompartment" or
identifier == "WantsEventListenerHooks" or
- identifier == "NonOrdinaryGetPrototypeOf" or
identifier == "Abstract" or
identifier == "Inline"):
# Known extended attributes that do not take values
@@ -1805,7 +1842,7 @@ class IDLNamespace(IDLInterfaceOrNamespace):
if not attr.noArguments():
raise WebIDLError("[%s] must not have arguments" % identifier,
[attr.location])
- elif identifier == "Pref":
+ elif identifier == "Pref" or identifier == "Func":
# Known extended attributes that take a string value
if not attr.hasValue():
raise WebIDLError("[%s] must have a value" % identifier,
@@ -1828,6 +1865,7 @@ class IDLDictionary(IDLObjectWithScope):
self.parent = parent
self._finished = False
self.members = list(members)
+ self._partialDictionaries = []
IDLObjectWithScope.__init__(self, location, parentScope, name)
@@ -1864,6 +1902,11 @@ class IDLDictionary(IDLObjectWithScope):
# looking at them.
self.parent.finish(scope)
+ # Now go ahead and merge in our partial dictionaries.
+ for partial in self._partialDictionaries:
+ partial.finish(scope)
+ self.members.extend(partial.members)
+
for member in self.members:
member.resolve(self)
if not member.isComplete():
@@ -1968,6 +2011,9 @@ class IDLDictionary(IDLObjectWithScope):
deps.add(self.parent)
return deps
+ def addPartialDictionary(self, partial):
+ assert self.identifier.name == partial.identifier.name
+ self._partialDictionaries.append(partial)
class IDLEnum(IDLObjectWithIdentifier):
def __init__(self, location, parentScope, name, values):
@@ -4333,7 +4379,7 @@ class IDLAttribute(IDLInterfaceMember):
[attr.location, self.location])
elif (identifier == "CrossOriginReadable" or
identifier == "CrossOriginWritable"):
- if not attr.noArguments() and identifier == "CrossOriginReadable":
+ if not attr.noArguments():
raise WebIDLError("[%s] must take no arguments" % identifier,
[attr.location])
if self.isStatic():
@@ -4525,7 +4571,7 @@ class IDLArgument(IDLObjectWithIdentifier):
if ((self.type.isDictionary() or
self.type.isUnion() and self.type.unroll().hasDictionaryType()) and
self.optional and not self.defaultValue and not self.variadic):
- # Default optional non-variadic dictionaries to null,
+ # Default optional non-variadic dictionary arguments to null,
# for simplicity, so the codegen doesn't have to special-case this.
self.defaultValue = IDLNullValue(self.location)
elif self.type.isAny():
@@ -5089,6 +5135,10 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
if not attr.noArguments():
raise WebIDLError("[%s] must take no arguments" % identifier,
[attr.location])
+ if identifier == "CrossOriginCallable" and self.isStatic():
+ raise WebIDLError("[CrossOriginCallable] is only allowed on non-static "
+ "attributes"
+ [attr.location, self.location])
elif identifier == "Pure":
if not attr.noArguments():
raise WebIDLError("[Pure] must take no arguments",
@@ -5293,7 +5343,7 @@ class Tokenizer(object):
return t
def t_IDENTIFIER(self, t):
- r'[A-Z_a-z][0-9A-Z_a-z-]*'
+ r'[_-]?[A-Za-z][0-9A-Z_a-z-]*'
t.type = self.keywords.get(t.value, 'IDENTIFIER')
return t
@@ -5518,9 +5568,10 @@ class Parser(Tokenizer):
def handleNonPartialObject(self, location, identifier, constructor,
constructorArgs, nonPartialArgs):
"""
- This handles non-partial objects (interfaces and namespaces) by
- checking for an existing partial object, and promoting it to
- non-partial as needed. The return value is the non-partial object.
+ This handles non-partial objects (interfaces, namespaces and
+ dictionaries) by checking for an existing partial object, and promoting
+ it to non-partial as needed. The return value is the non-partial
+ object.
constructorArgs are all the args for the constructor except the last
one: isKnownNonPartial.
@@ -5610,6 +5661,7 @@ class Parser(Tokenizer):
"""
PartialDefinition : PartialInterface
| PartialNamespace
+ | PartialDictionary
"""
p[0] = p[1]
@@ -5617,17 +5669,17 @@ class Parser(Tokenizer):
nonPartialConstructorArgs,
partialConstructorArgs):
"""
- This handles partial objects (interfaces and namespaces) by checking for
- an existing non-partial object, and adding ourselves to it as needed.
- The return value is our partial object. For now we just use
- IDLPartialInterfaceOrNamespace for partial objects.
+ This handles partial objects (interfaces, namespaces and dictionaries)
+ by checking for an existing non-partial object, and adding ourselves to
+ it as needed. The return value is our partial object. We use
+ IDLPartialInterfaceOrNamespace for partial interfaces or namespaces,
+ and IDLPartialDictionary for partial dictionaries.
nonPartialConstructorArgs are all the args for the non-partial
constructor except the last two: members and isKnownNonPartial.
- partialConstructorArgs are the arguments for the
- IDLPartialInterfaceOrNamespace constructor, except the last one (the
- non-partial object).
+ partialConstructorArgs are the arguments for the partial object
+ constructor, except the last one (the non-partial object).
"""
# The name of the class starts with "IDL", so strip that off.
# Also, starts with a capital letter after that, so nix that
@@ -5652,9 +5704,19 @@ class Parser(Tokenizer):
nonPartialObject = nonPartialConstructor(
# No members, False for isKnownNonPartial
*(nonPartialConstructorArgs + [[], False]))
- partialInterface = IDLPartialInterfaceOrNamespace(
- *(partialConstructorArgs + [nonPartialObject]))
- return partialInterface
+
+ partialObject = None
+ if isinstance(nonPartialObject, IDLDictionary):
+ partialObject = IDLPartialDictionary(
+ *(partialConstructorArgs + [nonPartialObject]))
+ elif isinstance(nonPartialObject, (IDLInterface, IDLNamespace)):
+ partialObject = IDLPartialInterfaceOrNamespace(
+ *(partialConstructorArgs + [nonPartialObject]))
+ else:
+ raise WebIDLError("Unknown partial object type %s" %
+ type(partialObject))
+
+ return partialObject
def p_PartialInterface(self, p):
"""
@@ -5682,6 +5744,19 @@ class Parser(Tokenizer):
[location, self.globalScope(), identifier],
[location, identifier, members])
+ def p_PartialDictionary(self, p):
+ """
+ PartialDictionary : DICTIONARY IDENTIFIER LBRACE DictionaryMembers RBRACE SEMICOLON
+ """
+ location = self.getLocation(p, 1)
+ identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
+ members = p[4]
+
+ p[0] = self.handlePartialObject(
+ location, identifier, IDLDictionary,
+ [location, self.globalScope(), identifier],
+ [location, identifier, members])
+
def p_Inheritance(self, p):
"""
Inheritance : COLON ScopedName
@@ -6894,16 +6969,13 @@ class Parser(Tokenizer):
logger.reportGrammarErrors()
self._globalScope = IDLScope(BuiltinLocation("<Global Scope>"), None, None)
+
# To make our test harness work, pretend like we have a primary global already.
# Note that we _don't_ set _globalScope.primaryGlobalAttr,
# so we'll still be able to detect multiple PrimaryGlobal extended attributes.
self._globalScope.primaryGlobalName = "FakeTestPrimaryGlobal"
- self._globalScope.globalNames.add("FakeTestPrimaryGlobal")
- self._globalScope.globalNameMapping["FakeTestPrimaryGlobal"].add("FakeTestPrimaryGlobal")
- # And we add the special-cased "System" global name, which
- # doesn't have any corresponding interfaces.
- self._globalScope.globalNames.add("System")
- self._globalScope.globalNameMapping["System"].add("BackstagePass")
+ self._globalScope.addIfaceGlobalNames("FakeTestPrimaryGlobal", ["FakeTestPrimaryGlobal"])
+
self._installBuiltins(self._globalScope)
self._productions = []
diff --git a/components/script/dom/bindings/codegen/parser/abstract.patch b/components/script/dom/bindings/codegen/parser/abstract.patch
index cf4c89b84d0..8e6c272b2c5 100644
--- a/components/script/dom/bindings/codegen/parser/abstract.patch
+++ b/components/script/dom/bindings/codegen/parser/abstract.patch
@@ -1,12 +1,12 @@
--- WebIDL.py
+++ WebIDL.py
-@@ -1744,7 +1744,8 @@
+@@ -1786,7 +1786,8 @@ class IDLInterface(IDLInterfaceOrNamespace):
+ identifier == "ProbablyShortLivingWrapper" or
identifier == "LegacyUnenumerableNamedProperties" or
identifier == "RunConstructorInCallerCompartment" or
- identifier == "WantsEventListenerHooks" or
-- identifier == "NonOrdinaryGetPrototypeOf"):
-+ identifier == "NonOrdinaryGetPrototypeOf" or
+- identifier == "WantsEventListenerHooks"):
++ identifier == "WantsEventListenerHooks" or
+ identifier == "Abstract"):
# Known extended attributes that do not take values
if not attr.noArguments():
- raise WebIDLError("[%s] must take no arguments" % identifier,
+ raise WebIDLError("[%s] must take no arguments" % identifier, \ No newline at end of file
diff --git a/components/script/dom/bindings/codegen/parser/callback-location.patch b/components/script/dom/bindings/codegen/parser/callback-location.patch
index fac5d035801..00b3b034396 100644
--- a/components/script/dom/bindings/codegen/parser/callback-location.patch
+++ b/components/script/dom/bindings/codegen/parser/callback-location.patch
@@ -1,17 +1,15 @@
-diff --git a/components/script/dom/bindings/codegen/parser/WebIDL.py b/components/script/dom/bindings/codegen/parser/WebIDL.py
-index da32340..81c52b7 100644
--- WebIDL.py
+++ WebIDL.py
-@@ -2170,7 +2170,7 @@ class IDLUnresolvedType(IDLType):
+@@ -2275,7 +2275,7 @@ class IDLUnresolvedType(IDLType):
return typedefType.complete(scope)
elif obj.isCallback() and not obj.isInterface():
assert self.name.name == obj.identifier.name
- return IDLCallbackType(self.location, obj)
+ return IDLCallbackType(obj.location, obj)
-
- if self._promiseInnerType and not self._promiseInnerType.isComplete():
- self._promiseInnerType = self._promiseInnerType.complete(scope)
-@@ -6521,7 +6521,7 @@ class Parser(Tokenizer):
+
+ name = self.name.resolve(scope, None)
+ return IDLWrapperType(self.location, obj)
+@@ -6688,7 +6688,7 @@ class Parser(Tokenizer):
type = IDLTypedefType(self.getLocation(p, 1), obj.innerType,
obj.identifier.name)
elif obj.isCallback() and not obj.isInterface():
@@ -19,4 +17,4 @@ index da32340..81c52b7 100644
+ type = IDLCallbackType(obj.location, obj)
else:
type = IDLWrapperType(self.getLocation(p, 1), p[1])
- p[0] = self.handleModifiers(type, p[2])
+ p[0] = self.handleNullable(type, p[2])
diff --git a/components/script/dom/bindings/codegen/parser/debug.patch b/components/script/dom/bindings/codegen/parser/debug.patch
index ca391c38273..49cb962cbba 100644
--- a/components/script/dom/bindings/codegen/parser/debug.patch
+++ b/components/script/dom/bindings/codegen/parser/debug.patch
@@ -1,6 +1,6 @@
--- WebIDL.py
+++ WebIDL.py
-@@ -6823,7 +6823,8 @@ class Parser(Tokenizer):
+@@ -6959,7 +6959,8 @@ class Parser(Tokenizer):
self.parser = yacc.yacc(module=self,
outputdir=outputdir,
tabmodule='webidlyacc',
diff --git a/components/script/dom/bindings/codegen/parser/inline.patch b/components/script/dom/bindings/codegen/parser/inline.patch
index 028fb9345d0..e2b16f9b158 100644
--- a/components/script/dom/bindings/codegen/parser/inline.patch
+++ b/components/script/dom/bindings/codegen/parser/inline.patch
@@ -1,9 +1,9 @@
--- WebIDL.py
+++ WebIDL.py
-@@ -1695,7 +1695,8 @@ class IDLInterface(IDLInterfaceOrNamespace):
- identifier == "ProbablyShortLivingObject" or
+@@ -1787,7 +1787,8 @@ class IDLInterface(IDLInterfaceOrNamespace):
identifier == "LegacyUnenumerableNamedProperties" or
- identifier == "NonOrdinaryGetPrototypeOf" or
+ identifier == "RunConstructorInCallerCompartment" or
+ identifier == "WantsEventListenerHooks" or
- identifier == "Abstract"):
+ identifier == "Abstract" or
+ identifier == "Inline"):
diff --git a/components/script/dom/bindings/codegen/parser/pref-main-thread.patch b/components/script/dom/bindings/codegen/parser/pref-main-thread.patch
deleted file mode 100644
index 7be2dcbfc5e..00000000000
--- a/components/script/dom/bindings/codegen/parser/pref-main-thread.patch
+++ /dev/null
@@ -1,28 +0,0 @@
---- WebIDL.py
-+++ WebIDL.py
-@@ -1239,12 +1239,6 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
- alias,
- [member.location, m.location])
-
-- if (self.getExtendedAttribute("Pref") and
-- self._exposureGlobalNames != set([self.parentScope.primaryGlobalName])):
-- raise WebIDLError("[Pref] used on an interface that is not %s-only" %
-- self.parentScope.primaryGlobalName,
-- [self.location])
--
- # Conditional exposure makes no sense for interfaces with no
- # interface object, unless they're navigator properties.
- # And SecureContext makes sense for interfaces with no interface object,
-@@ -3459,12 +3453,6 @@ class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins):
- IDLExposureMixins.finish(self, scope)
-
- def validate(self):
-- if (self.getExtendedAttribute("Pref") and
-- self.exposureSet != set([self._globalScope.primaryGlobalName])):
-- raise WebIDLError("[Pref] used on an interface member that is not "
-- "%s-only" % self._globalScope.primaryGlobalName,
-- [self.location])
--
- if self.isAttr() or self.isMethod():
- if self.affects == "Everything" and self.dependsOn != "Everything":
- raise WebIDLError("Interface member is flagged as affecting "
diff --git a/components/script/dom/bindings/codegen/parser/tests/test_dictionary.py b/components/script/dom/bindings/codegen/parser/tests/test_dictionary.py
index 2c0fa61239d..361b83ea52b 100644
--- a/components/script/dom/bindings/codegen/parser/tests/test_dictionary.py
+++ b/components/script/dom/bindings/codegen/parser/tests/test_dictionary.py
@@ -26,6 +26,31 @@ def WebIDLTest(parser, harness):
harness.check(dict2.members[1].identifier.name, "child",
"'a' really comes before 'c'")
+ # Test partial dictionary.
+ parser = parser.reset();
+ parser.parse("""
+ dictionary A {
+ long c;
+ long g;
+ };
+ partial dictionary A {
+ long h;
+ long d;
+ };
+ """)
+ results = parser.finish()
+
+ dict1 = results[0];
+ harness.check(len(dict1.members), 4, "Dict1 has four members")
+ harness.check(dict1.members[0].identifier.name, "c",
+ "c should be first")
+ harness.check(dict1.members[1].identifier.name, "d",
+ "d should come after c")
+ harness.check(dict1.members[2].identifier.name, "g",
+ "g should come after d")
+ harness.check(dict1.members[3].identifier.name, "h",
+ "h should be last")
+
# Now reset our parser
parser = parser.reset()
threw = False
@@ -42,6 +67,24 @@ def WebIDLTest(parser, harness):
harness.ok(threw, "Should not allow name duplication in a dictionary")
+ # Test no name duplication across normal and partial dictionary.
+ parser = parser.reset();
+ threw = False
+ try:
+ parser.parse("""
+ dictionary A {
+ long prop = 5;
+ };
+ partial dictionary A {
+ long prop;
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "Should not allow name duplication across normal and partial dictionary")
+
# Now reset our parser again
parser = parser.reset()
threw = False
diff --git a/components/script/dom/bindings/codegen/parser/tests/test_lenientSetter.py b/components/script/dom/bindings/codegen/parser/tests/test_lenientSetter.py
index 50e9df658e9..78a9ffe9eaa 100644
--- a/components/script/dom/bindings/codegen/parser/tests/test_lenientSetter.py
+++ b/components/script/dom/bindings/codegen/parser/tests/test_lenientSetter.py
@@ -1,6 +1,6 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at https://mozilla.org/MPL/2.0/.
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
def should_throw(parser, harness, message, code):
parser = parser.reset();
diff --git a/components/script/dom/bindings/codegen/parser/tests/test_replaceable.py b/components/script/dom/bindings/codegen/parser/tests/test_replaceable.py
index 78b1bf7e60b..93ee42ed919 100644
--- a/components/script/dom/bindings/codegen/parser/tests/test_replaceable.py
+++ b/components/script/dom/bindings/codegen/parser/tests/test_replaceable.py
@@ -1,6 +1,6 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at https://mozilla.org/MPL/2.0/.
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
def should_throw(parser, harness, message, code):
parser = parser.reset();
diff --git a/components/script/dom/bindings/codegen/parser/undo-dictionary-optional.patch b/components/script/dom/bindings/codegen/parser/undo-dictionary-optional.patch
new file mode 100644
index 00000000000..b414a536415
--- /dev/null
+++ b/components/script/dom/bindings/codegen/parser/undo-dictionary-optional.patch
@@ -0,0 +1,12 @@
+--- WebIDL.py
++++ WebIDL.py
+@@ -4570,8 +4570,7 @@ class IDLArgument(IDLObjectWithIdentifier):
+
+ if ((self.type.isDictionary() or
+ self.type.isUnion() and self.type.unroll().hasDictionaryType()) and
+- self.optional and not self.defaultValue and not self.variadic and
+- not self.dictionaryMember):
++ self.optional and not self.defaultValue and not self.variadic):
+ # Default optional non-variadic dictionary arguments to null,
+ # for simplicity, so the codegen doesn't have to special-case this.
+ self.defaultValue = IDLNullValue(self.location)
diff --git a/components/script/dom/bindings/codegen/parser/union-typedef.patch b/components/script/dom/bindings/codegen/parser/union-typedef.patch
index 3021e14193f..ec045300b6d 100644
--- a/components/script/dom/bindings/codegen/parser/union-typedef.patch
+++ b/components/script/dom/bindings/codegen/parser/union-typedef.patch
@@ -1,22 +1,22 @@
--- WebIDL.py
+++ WebIDL.py
-@@ -2481,10 +2481,18 @@ class IDLUnionType(IDLType):
+@@ -2613,10 +2613,18 @@ class IDLUnionType(IDLType):
return type.name
for (i, type) in enumerate(self.memberTypes):
+- if not type.isComplete():
+ # Exclude typedefs because if given "typedef (B or C) test",
+ # we want AOrTest, not AOrBOrC
+ if not type.isComplete() and not isinstance(type, IDLTypedefType):
-+ self.memberTypes[i] = type.complete(scope)
-+
-+ self.name = "Or".join(typeName(type) for type in self.memberTypes)
+ self.memberTypes[i] = type.complete(scope)
+
+ self.name = "Or".join(typeName(type) for type in self.memberTypes)
+
+ # We do this again to complete the typedef types
+ for (i, type) in enumerate(self.memberTypes):
- if not type.isComplete():
- self.memberTypes[i] = type.complete(scope)
-
-- self.name = "Or".join(typeName(type) for type in self.memberTypes)
++ if not type.isComplete():
++ self.memberTypes[i] = type.complete(scope)
++
self.flatMemberTypes = list(self.memberTypes)
i = 0
while i < len(self.flatMemberTypes):
diff --git a/components/script/dom/bindings/codegen/parser/update.sh b/components/script/dom/bindings/codegen/parser/update.sh
index 213aba6df89..0386b0294fe 100755
--- a/components/script/dom/bindings/codegen/parser/update.sh
+++ b/components/script/dom/bindings/codegen/parser/update.sh
@@ -5,6 +5,7 @@ patch < pref-main-thread.patch
patch < callback-location.patch
patch < union-typedef.patch
patch < inline.patch
+patch < undo-dictionary-optional.patch
wget https://hg.mozilla.org/mozilla-central/archive/tip.tar.gz/dom/bindings/parser/tests/ -O tests.tar.gz
rm -r tests