aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/bindings/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/bindings/codegen')
-rw-r--r--components/script/dom/bindings/codegen/CodegenRust.py123
-rw-r--r--components/script/dom/bindings/codegen/parser/WebIDL.py143
-rw-r--r--components/script/dom/bindings/codegen/parser/abstract.patch8
-rw-r--r--components/script/dom/bindings/codegen/parser/legacy-unenumerable-named-properties.patch25
-rw-r--r--components/script/dom/bindings/codegen/parser/tests/test_lenientSetter.py58
-rw-r--r--components/script/dom/bindings/codegen/parser/tests/test_unenumerable_own_properties.py64
-rwxr-xr-xcomponents/script/dom/bindings/codegen/parser/update.sh1
7 files changed, 287 insertions, 135 deletions
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py
index 1e26bc68c2f..0caeddb3dfa 100644
--- a/components/script/dom/bindings/codegen/CodegenRust.py
+++ b/components/script/dom/bindings/codegen/CodegenRust.py
@@ -5,6 +5,7 @@
# Common codegen classes.
from collections import defaultdict
+from itertools import groupby
import operator
import re
@@ -1322,31 +1323,23 @@ def getRetvalDeclarationForType(returnType, descriptorProvider):
returnType)
-class MemberCondition:
+def MemberCondition(pref, func):
"""
- An object representing the condition for a member to actually be
- exposed. Any of the arguments can be None. If not
- None, they should have the following types:
+ A string representing the condition for a member to actually be exposed.
+ Any of the arguments can be None. If not None, they should have the
+ following types:
pref: The name of the preference.
func: The name of the function.
"""
- def __init__(self, pref=None, func=None):
- assert pref is None or isinstance(pref, str)
- assert func is None or isinstance(func, str)
- self.pref = pref
-
- def toFuncPtr(val):
- if val is None:
- return "None"
- return "Some(%s)" % val
- self.func = toFuncPtr(func)
-
- def __eq__(self, other):
- return (self.pref == other.pref and self.func == other.func)
-
- def __ne__(self, other):
- return not self.__eq__(other)
+ assert pref is None or isinstance(pref, str)
+ assert func is None or isinstance(func, str)
+ assert func is None or pref is None
+ if pref:
+ return 'Condition::Pref("%s")' % pref
+ if func:
+ return 'Condition::Func(%s)' % func
+ return "Condition::Satisfied"
class PropertyDefiner:
@@ -1390,8 +1383,8 @@ class PropertyDefiner:
PropertyDefiner.getStringAttr(interfaceMember,
"Func"))
- def generatePrefableArray(self, array, name, specTemplate, specTerminator,
- specType, getCondition, getDataTuple):
+ def generateGuardedArray(self, array, name, specTemplate, specTerminator,
+ specType, getCondition, getDataTuple):
"""
This method generates our various arrays.
@@ -1417,43 +1410,23 @@ class PropertyDefiner:
# members while still allowing us to define all the members in the smallest
# number of JSAPI calls.
assert len(array) != 0
- # So we won't put a specTerminator at the very front of the list:
- lastCondition = getCondition(array[0], self.descriptor)
specs = []
- currentSpecs = []
prefableSpecs = []
+ prefableTemplate = ' Guard::new(%s, %s[%d])'
- prefableTemplate = ' Prefable { pref: %s, specs: %s[%d], terminator: %s }'
-
- def switchToCondition(props, condition):
- prefableSpecs.append(prefableTemplate %
- ('Some("%s")' % condition.pref if condition.pref else 'None',
- name + "_specs",
- len(specs),
- 'true' if specTerminator else 'false'))
+ for cond, members in groupby(array, lambda m: getCondition(m, self.descriptor)):
+ currentSpecs = [specTemplate % getDataTuple(m) for m in members]
+ if specTerminator:
+ currentSpecs.append(specTerminator)
specs.append("&[\n" + ",\n".join(currentSpecs) + "]\n")
- del currentSpecs[:]
-
- for member in array:
- curCondition = getCondition(member, self.descriptor)
- if lastCondition != curCondition:
- # Terminate previous list
- if specTerminator:
- currentSpecs.append(specTerminator)
- # And switch to our new pref
- switchToCondition(self, lastCondition)
- lastCondition = curCondition
- # And the actual spec
- currentSpecs.append(specTemplate % getDataTuple(member))
- if specTerminator:
- currentSpecs.append(specTerminator)
- switchToCondition(self, lastCondition)
+ prefableSpecs.append(
+ prefableTemplate % (cond, name + "_specs", len(specs) - 1))
specsArray = ("const %s_specs: &'static [&'static[%s]] = &[\n" +
",\n".join(specs) + "\n" +
"];\n") % (name, specType)
- prefArray = ("const %s: &'static [Prefable<%s>] = &[\n" +
+ prefArray = ("const %s: &'static [Guard<&'static [%s]>] = &[\n" +
",\n".join(prefableSpecs) + "\n" +
"];\n") % (name, specType)
return specsArray + prefArray
@@ -1500,7 +1473,7 @@ class MethodDefiner(PropertyDefiner):
"methodInfo": False,
"selfHostedName": "ArrayValues",
"length": 0,
- "condition": MemberCondition()})
+ "condition": "Condition::Satisfied"})
isUnforgeableInterface = bool(descriptor.interface.getExtendedAttribute("Unforgeable"))
if not static and unforgeable == isUnforgeableInterface:
@@ -1551,7 +1524,7 @@ class MethodDefiner(PropertyDefiner):
% m["name"][2:], accessor, jitinfo, m["length"], flags, selfHostedName)
return (str_to_const_array(m["name"]), accessor, jitinfo, m["length"], flags, selfHostedName)
- return self.generatePrefableArray(
+ return self.generateGuardedArray(
array, name,
' JSFunctionSpec {\n'
' name: %s as *const u8 as *const libc::c_char,\n'
@@ -1631,7 +1604,7 @@ class AttrDefiner(PropertyDefiner):
return (str_to_const_array(attr.identifier.name), flags, getter(attr),
setter(attr))
- return self.generatePrefableArray(
+ return self.generateGuardedArray(
array, name,
' JSPropertySpec {\n'
' name: %s as *const u8 as *const libc::c_char,\n'
@@ -1666,7 +1639,7 @@ class ConstDefiner(PropertyDefiner):
return (str_to_const_array(const.identifier.name),
convertConstIDLValueToJSVal(const.value))
- return self.generatePrefableArray(
+ return self.generateGuardedArray(
array, name,
' ConstantSpec { name: %s, value: %s }',
None,
@@ -1993,17 +1966,16 @@ class CGInterfaceObjectJSClass(CGThing):
args = {
"constructorBehavior": constructorBehavior,
"id": name,
- "representation": str_to_const_array("function %s() {\\n [native code]\\n}" % name),
+ "representation": 'b"function %s() {\\n [native code]\\n}"' % name,
"depth": self.descriptor.prototypeDepth
}
return """\
-static InterfaceObjectClass: NonCallbackInterfaceObjectClass = unsafe {
+static InterfaceObjectClass: NonCallbackInterfaceObjectClass =
NonCallbackInterfaceObjectClass::new(
%(constructorBehavior)s,
%(representation)s,
PrototypeList::ID::%(id)s,
- %(depth)s)
-};
+ %(depth)s);
""" % args
@@ -2088,16 +2060,15 @@ def UnionTypes(descriptors, dictionaries, callbacks, config):
'dom::bindings::conversions::FromJSValConvertible',
'dom::bindings::conversions::ToJSValConvertible',
'dom::bindings::conversions::ConversionBehavior',
- 'dom::bindings::conversions::root_from_handlevalue',
'dom::bindings::conversions::StringificationBehavior',
+ 'dom::bindings::conversions::root_from_handlevalue',
'dom::bindings::error::throw_not_in_union',
'dom::bindings::js::Root',
- 'dom::bindings::str::USVString',
+ 'dom::bindings::str::{DOMString, USVString}',
'dom::types::*',
'js::jsapi::JSContext',
'js::jsapi::{HandleValue, MutableHandleValue}',
'js::jsval::JSVal',
- 'util::str::DOMString',
]
# Now find all the things we'll need as arguments and return values because
@@ -2329,8 +2300,8 @@ def InitUnforgeablePropertiesOnHolder(descriptor, properties):
"""
unforgeables = []
- defineUnforgeableAttrs = "define_prefable_properties(cx, unforgeable_holder.handle(), %s);"
- defineUnforgeableMethods = "define_prefable_methods(cx, unforgeable_holder.handle(), %s);"
+ defineUnforgeableAttrs = "define_guarded_properties(cx, unforgeable_holder.handle(), %s);"
+ defineUnforgeableMethods = "define_guarded_methods(cx, unforgeable_holder.handle(), %s);"
unforgeableMembers = [
(defineUnforgeableAttrs, properties.unforgeable_attrs),
@@ -2419,6 +2390,7 @@ Root::from_ref(&*raw)""" % {'copyUnforgeable': unforgeable, 'createObject': crea
create = CreateBindingJSObject(self.descriptor)
return CGGeneric("""\
%(createObject)s
+(*raw).init_reflector(obj.ptr);
let _ac = JSAutoCompartment::new(cx, obj.ptr);
let mut proto = RootedObject::new(cx, ptr::null_mut());
@@ -2426,7 +2398,6 @@ GetProtoObject(cx, obj.handle(), proto.handle_mut());
JS_SetPrototype(cx, obj.handle(), proto.handle());
%(copyUnforgeable)s
-(*raw).init_reflector(obj.ptr);
Root::from_ref(&*raw)\
""" % {'copyUnforgeable': unforgeable, 'createObject': create})
@@ -2562,15 +2533,10 @@ assert!(!prototype_proto.ptr.is_null());""" % getPrototypeProto)]
properties = {"id": name}
for arrayName in self.properties.arrayNames():
array = getattr(self.properties, arrayName)
- if arrayName == "consts":
- if array.length():
- properties[arrayName] = array.variableName()
- else:
- properties[arrayName] = "&[]"
- elif array.length():
- properties[arrayName] = "Some(%s)" % array.variableName()
+ if array.length():
+ properties[arrayName] = array.variableName()
else:
- properties[arrayName] = "None"
+ properties[arrayName] = "&[]"
code.append(CGGeneric("""
let mut prototype = RootedObject::new(cx, ptr::null_mut());
@@ -5565,13 +5531,13 @@ class CGBindingRoot(CGThing):
'dom::bindings::interface::{InterfaceConstructorBehavior, NonCallbackInterfaceObjectClass}',
'dom::bindings::interface::{create_callback_interface_object, create_interface_prototype_object}',
'dom::bindings::interface::{create_named_constructors, create_noncallback_interface_object}',
- 'dom::bindings::interface::{define_prefable_methods, define_prefable_properties}',
+ 'dom::bindings::interface::{define_guarded_methods, define_guarded_properties}',
'dom::bindings::interface::{ConstantSpec, NonNullJSNative}',
'dom::bindings::interface::ConstantVal::{IntVal, UintVal}',
'dom::bindings::js::{JS, Root, RootedReference}',
'dom::bindings::js::{OptionalRootedReference}',
'dom::bindings::reflector::{Reflectable}',
- 'dom::bindings::utils::{DOMClass, DOMJSClass, Prefable}',
+ 'dom::bindings::utils::{DOMClass, DOMJSClass}',
'dom::bindings::utils::{DOM_PROTO_UNFORGEABLE_HOLDER_SLOT, JSCLASS_DOM_GLOBAL}',
'dom::bindings::utils::{ProtoOrIfaceArray, create_dom_global}',
'dom::bindings::utils::{enumerate_global, finalize_global, find_enum_string_index}',
@@ -5595,18 +5561,17 @@ class CGBindingRoot(CGThing):
'dom::bindings::error::{Fallible, Error, ErrorResult}',
'dom::bindings::error::Error::JSFailed',
'dom::bindings::error::throw_dom_exception',
+ 'dom::bindings::guard::{Condition, Guard}',
'dom::bindings::proxyhandler',
'dom::bindings::proxyhandler::{ensure_expando_object, fill_property_descriptor}',
'dom::bindings::proxyhandler::{get_expando_object, get_property_descriptor}',
'dom::bindings::num::Finite',
- 'dom::bindings::str::ByteString',
- 'dom::bindings::str::USVString',
+ 'dom::bindings::str::{ByteString, DOMString, USVString}',
'dom::bindings::trace::RootedVec',
'dom::bindings::weakref::{DOM_WEAK_SLOT, WeakBox, WeakReferenceable}',
'mem::heap_size_of_raw_self_and_children',
'libc',
'util::prefs',
- 'util::str::DOMString',
'std::borrow::ToOwned',
'std::cmp',
'std::mem',
@@ -6378,9 +6343,7 @@ class GlobalGenRoots():
if not config.getInterface(base).getExtendedAttribute("Abstract"):
variants.append(CGGeneric(base))
variants += [CGGeneric(type_id_variant(derivedName)) for derivedName in derived]
- derives = "Clone, Copy, Debug"
- if base != 'EventTarget' and base != 'HTMLElement':
- derives += ", PartialEq"
+ derives = "Clone, Copy, Debug, PartialEq"
typeIdCode.append(CGWrapper(CGIndenter(CGList(variants, ",\n"), 4),
pre="#[derive(%s)]\npub enum %sTypeId {\n" % (derives, base),
post="\n}\n\n"))
diff --git a/components/script/dom/bindings/codegen/parser/WebIDL.py b/components/script/dom/bindings/codegen/parser/WebIDL.py
index 09fab2e7a74..5795f9db767 100644
--- a/components/script/dom/bindings/codegen/parser/WebIDL.py
+++ b/components/script/dom/bindings/codegen/parser/WebIDL.py
@@ -578,8 +578,8 @@ class IDLExternalInterface(IDLObjectWithIdentifier, IDLExposureMixins):
def isProbablyShortLivingObject(self):
return False
- def getNavigatorProperty(self):
- return None
+ def isNavigatorProperty(self):
+ return False
def _getDependentObjects(self):
return set()
@@ -1078,11 +1078,22 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
specialMembersSeen[memberType] = member
- if (self.getExtendedAttribute("LegacyUnenumerableNamedProperties") and
- "named getters" not in specialMembersSeen):
- raise WebIDLError("[LegacyUnenumerableNamedProperties] used on an interface "
- "without a named getter",
- [self.location])
+ if self.getExtendedAttribute("LegacyUnenumerableNamedProperties"):
+ # Check that we have a named getter.
+ if "named getters" not in specialMembersSeen:
+ raise WebIDLError(
+ "Interface with [LegacyUnenumerableNamedProperties] does "
+ "not have a named getter",
+ [self.location])
+ ancestor = self.parent
+ while ancestor:
+ if ancestor.getExtendedAttribute("LegacyUnenumerableNamedProperties"):
+ raise WebIDLError(
+ "Interface with [LegacyUnenumerableNamedProperties] "
+ "inherits from another interface with "
+ "[LegacyUnenumerableNamedProperties]",
+ [self.location, ancestor.location])
+ ancestor = ancestor.parent
if self._isOnGlobalProtoChain:
# Make sure we have no named setters, creators, or deleters
@@ -1246,7 +1257,7 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
# interface object, unless they're navigator properties.
if (self.isExposedConditionally() and
not self.hasInterfaceObject() and
- not self.getNavigatorProperty()):
+ not self.isNavigatorProperty()):
raise WebIDLError("Interface with no interface object is "
"exposed conditionally",
[self.location])
@@ -1471,8 +1482,9 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
identifier == "UnsafeInPrerendering" or
identifier == "LegacyEventInit" or
identifier == "ProbablyShortLivingObject" or
- identifier == "Abstract" or
- identifier == "LegacyUnenumerableNamedProperties"):
+ identifier == "LegacyUnenumerableNamedProperties" or
+ identifier == "NonOrdinaryGetPrototypeOf" or
+ identifier == "Abstract"):
# Known extended attributes that do not take values
if not attr.noArguments():
raise WebIDLError("[%s] must take no arguments" % identifier,
@@ -1594,6 +1606,15 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
current = current.parent
return False
+ def isNavigatorProperty(self):
+ naviProp = self.getExtendedAttribute("NavigatorProperty")
+ if not naviProp:
+ return False
+ assert len(naviProp) == 1
+ assert isinstance(naviProp, list)
+ assert len(naviProp[0]) != 0
+ return True
+
def getNavigatorProperty(self):
naviProp = self.getExtendedAttribute("NavigatorProperty")
if not naviProp:
@@ -1601,7 +1622,22 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
assert len(naviProp) == 1
assert isinstance(naviProp, list)
assert len(naviProp[0]) != 0
- return naviProp[0]
+ conditionExtendedAttributes = self._extendedAttrDict.viewkeys() & IDLInterface.conditionExtendedAttributes
+ attr = IDLAttribute(self.location,
+ IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"), naviProp[0]),
+ IDLUnresolvedType(self.location, IDLUnresolvedIdentifier(self.location, self.identifier.name)),
+ True,
+ extendedAttrDict={ a: self._extendedAttrDict[a] for a in conditionExtendedAttributes },
+ navigatorObjectGetter=True)
+ attr._exposureGlobalNames = self._exposureGlobalNames
+ # We're abusing Constant a little bit here, because we need Cached. The
+ # getter will create a new object every time, but we're never going to
+ # clear the cached value.
+ extendedAttrs = [ IDLExtendedAttribute(self.location, ("Throws", )),
+ IDLExtendedAttribute(self.location, ("Cached", )),
+ IDLExtendedAttribute(self.location, ("Constant", )) ]
+ attr.addExtendedAttributes(extendedAttrs)
+ return attr
def hasChildInterfaces(self):
return self._hasChildInterfaces
@@ -1619,13 +1655,11 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
def hasMembersInSlots(self):
return self._ownMembersInSlots != 0
+ conditionExtendedAttributes = [ "Pref", "ChromeOnly", "Func", "AvailableIn",
+ "CheckAnyPermissions",
+ "CheckAllPermissions" ]
def isExposedConditionally(self):
- return (self.getExtendedAttribute("Pref") or
- self.getExtendedAttribute("ChromeOnly") or
- self.getExtendedAttribute("Func") or
- self.getExtendedAttribute("AvailableIn") or
- self.getExtendedAttribute("CheckAnyPermissions") or
- self.getExtendedAttribute("CheckAllPermissions"))
+ return any(self.getExtendedAttribute(a) for a in self.conditionExtendedAttributes)
class IDLDictionary(IDLObjectWithScope):
@@ -3380,11 +3414,14 @@ class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins):
AffectsValues = ("Nothing", "Everything")
DependsOnValues = ("Nothing", "DOMState", "DeviceState", "Everything")
- def __init__(self, location, identifier, tag):
+ def __init__(self, location, identifier, tag, extendedAttrDict=None):
IDLObjectWithIdentifier.__init__(self, location, None, identifier)
IDLExposureMixins.__init__(self, location)
self.tag = tag
- self._extendedAttrDict = {}
+ if extendedAttrDict is None:
+ self._extendedAttrDict = {}
+ else:
+ self._extendedAttrDict = extendedAttrDict
def isMethod(self):
return self.tag == IDLInterfaceMember.Tags.Method
@@ -3868,9 +3905,11 @@ class IDLConst(IDLInterfaceMember):
class IDLAttribute(IDLInterfaceMember):
def __init__(self, location, identifier, type, readonly, inherit=False,
- static=False, stringifier=False, maplikeOrSetlike=None):
+ static=False, stringifier=False, maplikeOrSetlike=None,
+ extendedAttrDict=None, navigatorObjectGetter=False):
IDLInterfaceMember.__init__(self, location, identifier,
- IDLInterfaceMember.Tags.Attr)
+ IDLInterfaceMember.Tags.Attr,
+ extendedAttrDict=extendedAttrDict)
assert isinstance(type, IDLType)
self.type = type
@@ -3887,6 +3926,7 @@ class IDLAttribute(IDLInterfaceMember):
self.maplikeOrSetlike = maplikeOrSetlike
self.dependsOn = "Everything"
self.affects = "Everything"
+ self.navigatorObjectGetter = navigatorObjectGetter
if static and identifier.name == "prototype":
raise WebIDLError("The identifier of a static attribute must not be 'prototype'",
@@ -4041,6 +4081,24 @@ class IDLAttribute(IDLInterfaceMember):
raise WebIDLError("[PutForwards] and [Replaceable] can't both "
"appear on the same attribute",
[attr.location, self.location])
+ elif identifier == "LenientSetter":
+ if not attr.noArguments():
+ raise WebIDLError("[LenientSetter] must take no arguments",
+ [attr.location])
+ if not self.readonly:
+ raise WebIDLError("[LenientSetter] is only allowed on readonly "
+ "attributes", [attr.location, self.location])
+ if self.isStatic():
+ raise WebIDLError("[LenientSetter] is only allowed on non-static "
+ "attributes", [attr.location, self.location])
+ if self.getExtendedAttribute("PutForwards") is not None:
+ raise WebIDLError("[LenientSetter] and [PutForwards] can't both "
+ "appear on the same attribute",
+ [attr.location, self.location])
+ if self.getExtendedAttribute("Replaceable") is not None:
+ raise WebIDLError("[LenientSetter] and [Replaceable] can't both "
+ "appear on the same attribute",
+ [attr.location, self.location])
elif identifier == "LenientFloat":
if self.readonly:
raise WebIDLError("[LenientFloat] used on a readonly attribute",
@@ -4116,6 +4174,14 @@ class IDLAttribute(IDLInterfaceMember):
raise WebIDLError("[UseCounter] must not be used on a "
"stringifier attribute",
[attr.location, self.location])
+ elif identifier == "Unscopable":
+ if not attr.noArguments():
+ raise WebIDLError("[Unscopable] must take no arguments",
+ [attr.location])
+ if self.isStatic():
+ raise WebIDLError("[Unscopable] is only allowed on non-static "
+ "attributes and operations",
+ [attr.location, self.location])
elif (identifier == "Pref" or
identifier == "Deprecated" or
identifier == "SetterThrows" or
@@ -4771,6 +4837,9 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
elif identifier == "PutForwards":
raise WebIDLError("Only attributes support [PutForwards]",
[attr.location, self.location])
+ elif identifier == "LenientSetter":
+ raise WebIDLError("Only attributes support [LenientSetter]",
+ [attr.location, self.location])
elif identifier == "LenientFloat":
# This is called before we've done overload resolution
assert len(self.signatures()) == 1
@@ -4816,6 +4885,14 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
raise WebIDLError("[UseCounter] must not be used on a special "
"operation",
[attr.location, self.location])
+ elif identifier == "Unscopable":
+ if not attr.noArguments():
+ raise WebIDLError("[Unscopable] must take no arguments",
+ [attr.location])
+ if self.isStatic():
+ raise WebIDLError("[Unscopable] is only allowed on non-static "
+ "attributes and operations",
+ [attr.location, self.location])
elif (identifier == "Throws" or
identifier == "NewObject" or
identifier == "ChromeOnly" or
@@ -5098,10 +5175,11 @@ class SqueakyCleanLogger(object):
info = debug
def warning(self, msg, *args, **kwargs):
- if msg == "%s:%d: Rule '%s' defined, but not used":
+ if msg == "%s:%d: Rule %r defined, but not used" or \
+ msg == "%s:%d: Rule '%s' defined, but not used":
# Munge things so we don't have to hardcode filenames and
# line numbers in our whitelist.
- whitelistmsg = "Rule '%s' defined, but not used"
+ whitelistmsg = "Rule %r defined, but not used"
whitelistargs = args[2:]
else:
whitelistmsg = msg
@@ -6588,11 +6666,26 @@ class Parser(Tokenizer):
def finish(self):
# If we have interfaces that are iterable, create their
# iterator interfaces and add them to the productions array.
- interfaceStatements = [p for p in self._productions if
- isinstance(p, IDLInterface)]
+ interfaceStatements = []
+ for p in self._productions:
+ if isinstance(p, IDLInterface):
+ interfaceStatements.append(p)
+ if p.identifier.name == "Navigator":
+ navigatorInterface = p
iterableIteratorIface = None
for iface in interfaceStatements:
+ navigatorProperty = iface.getNavigatorProperty()
+ if navigatorProperty:
+ # We're generating a partial interface to add a readonly
+ # property to the Navigator interface for every interface
+ # annotated with NavigatorProperty.
+ partialInterface = IDLPartialInterface(iface.location,
+ IDLUnresolvedIdentifier(iface.location, "Navigator"),
+ [ navigatorProperty ],
+ navigatorInterface)
+ self._productions.append(partialInterface)
+
iterable = None
# We haven't run finish() on the interface yet, so we don't know
# whether our interface is maplike/setlike/iterable or not. This
diff --git a/components/script/dom/bindings/codegen/parser/abstract.patch b/components/script/dom/bindings/codegen/parser/abstract.patch
index 081ee91c59b..a8e2ddcf759 100644
--- a/components/script/dom/bindings/codegen/parser/abstract.patch
+++ b/components/script/dom/bindings/codegen/parser/abstract.patch
@@ -1,11 +1,11 @@
--- WebIDL.py
+++ WebIDL.py
@@ -1416,7 +1416,8 @@
- identifier == "Unforgeable" or
- identifier == "UnsafeInPrerendering" or
identifier == "LegacyEventInit" or
-- identifier == "ProbablyShortLivingObject"):
-+ identifier == "ProbablyShortLivingObject" or
+ identifier == "ProbablyShortLivingObject" or
+ identifier == "LegacyUnenumerableNamedProperties" or
+- identifier == "NonOrdinaryGetPrototypeOf"):
++ identifier == "NonOrdinaryGetPrototypeOf" or
+ identifier == "Abstract"):
# Known extended attributes that do not take values
if not attr.noArguments():
diff --git a/components/script/dom/bindings/codegen/parser/legacy-unenumerable-named-properties.patch b/components/script/dom/bindings/codegen/parser/legacy-unenumerable-named-properties.patch
deleted file mode 100644
index 3472d054940..00000000000
--- a/components/script/dom/bindings/codegen/parser/legacy-unenumerable-named-properties.patch
+++ /dev/null
@@ -1,25 +0,0 @@
---- WebIDL.py
-+++ WebIDL.py
-@@ -1069,6 +1069,12 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
-
- specialMembersSeen[memberType] = member
-
-+ if (self.getExtendedAttribute("LegacyUnenumerableNamedProperties") and
-+ "named getters" not in specialMembersSeen):
-+ raise WebIDLError("[LegacyUnenumerableNamedProperties] used on an interface "
-+ "without a named getter",
-+ [self.location])
-+
- if self._isOnGlobalProtoChain:
- # Make sure we have no named setters, creators, or deleters
- for memberType in ["setter", "creator", "deleter"]:
-@@ -1417,7 +1423,8 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
- identifier == "UnsafeInPrerendering" or
- identifier == "LegacyEventInit" or
- identifier == "ProbablyShortLivingObject" or
-- identifier == "Abstract"):
-+ identifier == "Abstract" or
-+ identifier == "LegacyUnenumerableNamedProperties"):
- # Known extended attributes that do not take values
- if not attr.noArguments():
- raise WebIDLError("[%s] must take no arguments" % identifier,
diff --git a/components/script/dom/bindings/codegen/parser/tests/test_lenientSetter.py b/components/script/dom/bindings/codegen/parser/tests/test_lenientSetter.py
new file mode 100644
index 00000000000..78a9ffe9eaa
--- /dev/null
+++ b/components/script/dom/bindings/codegen/parser/tests/test_lenientSetter.py
@@ -0,0 +1,58 @@
+# 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 http://mozilla.org/MPL/2.0/.
+
+def should_throw(parser, harness, message, code):
+ parser = parser.reset();
+ threw = False
+ try:
+ parser.parse(code)
+ parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "Should have thrown: %s" % message)
+
+
+def WebIDLTest(parser, harness):
+ # The [LenientSetter] extended attribute MUST take no arguments.
+ should_throw(parser, harness, "no arguments", """
+ interface I {
+ [LenientSetter=X] readonly attribute long A;
+ };
+ """)
+
+ # An attribute with the [LenientSetter] extended attribute MUST NOT
+ # also be declared with the [PutForwards] extended attribute.
+ should_throw(parser, harness, "PutForwards", """
+ interface I {
+ [PutForwards=B, LenientSetter] readonly attribute J A;
+ };
+ interface J {
+ attribute long B;
+ };
+ """)
+
+ # An attribute with the [LenientSetter] extended attribute MUST NOT
+ # also be declared with the [Replaceable] extended attribute.
+ should_throw(parser, harness, "Replaceable", """
+ interface I {
+ [Replaceable, LenientSetter] readonly attribute J A;
+ };
+ """)
+
+ # The [LenientSetter] extended attribute MUST NOT be used on an
+ # attribute that is not read only.
+ should_throw(parser, harness, "writable attribute", """
+ interface I {
+ [LenientSetter] attribute long A;
+ };
+ """)
+
+ # The [LenientSetter] extended attribute MUST NOT be used on a
+ # static attribute.
+ should_throw(parser, harness, "static attribute", """
+ interface I {
+ [LenientSetter] static readonly attribute long A;
+ };
+ """)
diff --git a/components/script/dom/bindings/codegen/parser/tests/test_unenumerable_own_properties.py b/components/script/dom/bindings/codegen/parser/tests/test_unenumerable_own_properties.py
new file mode 100644
index 00000000000..d017d5ce092
--- /dev/null
+++ b/components/script/dom/bindings/codegen/parser/tests/test_unenumerable_own_properties.py
@@ -0,0 +1,64 @@
+def WebIDLTest(parser, harness):
+
+ parser.parse(
+ """
+ interface Foo {};
+ [LegacyUnenumerableNamedProperties]
+ interface Bar : Foo {
+ getter long(DOMString name);
+ };
+ interface Baz : Bar {
+ getter long(DOMString name);
+ };
+ """);
+ results = parser.finish();
+ harness.check(len(results), 3, "Should have three interfaces")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ [LegacyUnenumerableNamedProperties]
+ interface NoNamedGetter {
+ };
+ """)
+
+ results = parser.finish()
+ except Exception, x:
+ threw = True
+ harness.ok(threw, "Should have thrown.")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ [LegacyUnenumerableNamedProperties=Foo]
+ interface ShouldNotHaveArg {
+ getter long(DOMString name);
+ };
+ """)
+
+ results = parser.finish()
+ except Exception, x:
+ threw = True
+ harness.ok(threw, "Should have thrown.")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ [LegacyUnenumerableNamedProperties]
+ interface Foo {
+ getter long(DOMString name);
+ };
+ interface Bar : Foo {};
+ [LegacyUnenumerableNamedProperties]
+ interface Baz : Bar {
+ getter long(DOMString name);
+ };
+ """)
+
+ results = parser.finish()
+ except Exception, x:
+ threw = True
+ harness.ok(threw, "Should have thrown.")
diff --git a/components/script/dom/bindings/codegen/parser/update.sh b/components/script/dom/bindings/codegen/parser/update.sh
index fc764d2300c..43f873beb67 100755
--- a/components/script/dom/bindings/codegen/parser/update.sh
+++ b/components/script/dom/bindings/codegen/parser/update.sh
@@ -1,7 +1,6 @@
wget https://mxr.mozilla.org/mozilla-central/source/dom/bindings/parser/WebIDL.py?raw=1 -O WebIDL.py
patch < abstract.patch
patch < debug.patch
-patch < legacy-unenumerable-named-properties.patch
wget https://hg.mozilla.org/mozilla-central/archive/tip.tar.gz/dom/bindings/parser/tests/ -O tests.tar.gz
rm -r tests