aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/bindings/codegen/parser/WebIDL.py
diff options
context:
space:
mode:
authorAgostonSzepessy <agszepp@gmail.com>2016-03-06 18:47:35 -0500
committerAgostonSzepessy <agszepp@gmail.com>2016-03-22 23:13:30 -0400
commitd3528ffce4092e0b28b9494f96555368bf8945b9 (patch)
treeaf13c09d65a3a61e6131b96e4aa45e6bab27905b /components/script/dom/bindings/codegen/parser/WebIDL.py
parent003fdd41769652188a5954e6499f3cb44eef6b10 (diff)
downloadservo-d3528ffce4092e0b28b9494f96555368bf8945b9.tar.gz
servo-d3528ffce4092e0b28b9494f96555368bf8945b9.zip
components/script/dom/bindings/codegen/parser/update.sh now downloads all
the latest *.py tests from https://hg.mozilla.org/mozilla-central/archive/tip.tar.gz/dom/bindings/parser/tests/
Diffstat (limited to 'components/script/dom/bindings/codegen/parser/WebIDL.py')
-rw-r--r--components/script/dom/bindings/codegen/parser/WebIDL.py140
1 files changed, 112 insertions, 28 deletions
diff --git a/components/script/dom/bindings/codegen/parser/WebIDL.py b/components/script/dom/bindings/codegen/parser/WebIDL.py
index e653ad7e9ac..09fab2e7a74 100644
--- a/components/script/dom/bindings/codegen/parser/WebIDL.py
+++ b/components/script/dom/bindings/codegen/parser/WebIDL.py
@@ -508,6 +508,9 @@ class IDLExposureMixins():
def isExposedInAnyWorker(self):
return len(self.getWorkerExposureSet()) > 0
+ def isExposedInWorkerDebugger(self):
+ return len(self.getWorkerDebuggerExposureSet()) > 0
+
def isExposedInSystemGlobals(self):
return 'BackstagePass' in self.exposureSet
@@ -527,6 +530,10 @@ class IDLExposureMixins():
workerScopes = self._globalScope.globalNameMapping["Worker"]
return workerScopes.intersection(self.exposureSet)
+ def getWorkerDebuggerExposureSet(self):
+ workerDebuggerScopes = self._globalScope.globalNameMapping["WorkerDebugger"]
+ return workerDebuggerScopes.intersection(self.exposureSet)
+
class IDLExternalInterface(IDLObjectWithIdentifier, IDLExposureMixins):
def __init__(self, location, parentScope, identifier):
@@ -978,7 +985,9 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
(member.getExtendedAttribute("StoreInSlot") or
member.getExtendedAttribute("Cached"))) or
member.isMaplikeOrSetlike()):
- member.slotIndex = self.totalMembersInSlots
+ if member.slotIndices is None:
+ member.slotIndices = dict()
+ member.slotIndices[self.identifier.name] = self.totalMembersInSlots
self.totalMembersInSlots += 1
if member.getExtendedAttribute("StoreInSlot"):
self._ownMembersInSlots += 1
@@ -1102,7 +1111,7 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
def validate(self):
# We don't support consequential unforgeable interfaces. Need to check
- # this here, becaue in finish() an interface might not know yet that
+ # this here, because in finish() an interface might not know yet that
# it's consequential.
if self.getExtendedAttribute("Unforgeable") and self.isConsequential():
raise WebIDLError(
@@ -1121,6 +1130,8 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
self.identifier.name,
locations)
+ indexedGetter = None
+ hasLengthAttribute = False
for member in self.members:
member.validate()
@@ -1131,8 +1142,13 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
[self.location, member.location])
# Check that PutForwards refers to another attribute and that no
- # cycles exist in forwarded assignments.
+ # cycles exist in forwarded assignments. Also check for a
+ # integer-typed "length" attribute.
if member.isAttr():
+ if (member.identifier.name == "length" and
+ member.type.isInteger()):
+ hasLengthAttribute = True
+
iface = self
attr = member
putForwards = attr.getExtendedAttribute("PutForwards")
@@ -1170,8 +1186,11 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
putForwards = attr.getExtendedAttribute("PutForwards")
# Check that the name of an [Alias] doesn't conflict with an
- # interface member.
+ # interface member and whether we support indexed properties.
if member.isMethod():
+ if member.isGetter() and member.isIndexed():
+ indexedGetter = member
+
for alias in member.aliases:
if self.isOnGlobalProtoChain():
raise WebIDLError("[Alias] must not be used on a "
@@ -1232,6 +1251,35 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins):
"exposed conditionally",
[self.location])
+ # Value iterators are only allowed on interfaces with indexed getters,
+ # and pair iterators are only allowed on interfaces without indexed
+ # getters.
+ if self.isIterable():
+ iterableDecl = self.maplikeOrSetlikeOrIterable
+ if iterableDecl.isValueIterator():
+ if not indexedGetter:
+ raise WebIDLError("Interface with value iterator does not "
+ "support indexed properties",
+ [self.location])
+
+ if iterableDecl.valueType != indexedGetter.signatures()[0][0]:
+ raise WebIDLError("Iterable type does not match indexed "
+ "getter type",
+ [iterableDecl.location,
+ indexedGetter.location])
+
+ if not hasLengthAttribute:
+ raise WebIDLError('Interface with value iterator does not '
+ 'have an integer-typed "length" attribute',
+ [self.location])
+ else:
+ assert iterableDecl.isPairIterator()
+ if indexedGetter:
+ raise WebIDLError("Interface with pair iterator supports "
+ "indexed properties",
+ [self.location, iterableDecl.location,
+ indexedGetter.location])
+
def isInterface(self):
return True
@@ -3432,7 +3480,10 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
def __init__(self, location, identifier, ifaceType, keyType, valueType, ifaceKind):
IDLInterfaceMember.__init__(self, location, identifier, ifaceKind)
- assert isinstance(keyType, IDLType)
+ if keyType is not None:
+ assert isinstance(keyType, IDLType)
+ else:
+ assert valueType is not None
assert ifaceType in ['maplike', 'setlike', 'iterable']
if valueType is not None:
assert isinstance(valueType, IDLType)
@@ -3451,6 +3502,9 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
def isIterable(self):
return self.maplikeOrSetlikeOrIterableType == "iterable"
+ def hasKeyType(self):
+ return self.keyType is not None
+
def hasValueType(self):
return self.valueType is not None
@@ -3475,7 +3529,8 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
[self.location, member.location])
def addMethod(self, name, members, allowExistingOperations, returnType, args=[],
- chromeOnly=False, isPure=False, affectsNothing=False, newObject=False):
+ chromeOnly=False, isPure=False, affectsNothing=False, newObject=False,
+ isIteratorAlias=False):
"""
Create an IDLMethod based on the parameters passed in.
@@ -3535,16 +3590,20 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
if newObject:
method.addExtendedAttributes(
[IDLExtendedAttribute(self.location, ("NewObject",))])
+ if isIteratorAlias:
+ method.addExtendedAttributes(
+ [IDLExtendedAttribute(self.location, ("Alias", "@@iterator"))])
members.append(method)
def resolve(self, parentScope):
- self.keyType.resolveType(parentScope)
+ if self.keyType:
+ self.keyType.resolveType(parentScope)
if self.valueType:
self.valueType.resolveType(parentScope)
def finish(self, scope):
IDLInterfaceMember.finish(self, scope)
- if not self.keyType.isComplete():
+ if self.keyType and not self.keyType.isComplete():
t = self.keyType.complete(scope)
assert not isinstance(t, IDLUnresolvedType)
@@ -3566,9 +3625,23 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
IDLInterfaceMember.handleExtendedAttribute(self, attr)
def _getDependentObjects(self):
+ deps = set()
+ if self.keyType:
+ deps.add(self.keyType)
if self.valueType:
- return set([self.keyType, self.valueType])
- return set([self.keyType])
+ deps.add(self.valueType)
+ return deps
+
+ def getForEachArguments(self):
+ return [IDLArgument(self.location,
+ IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
+ "callback"),
+ BuiltinTypes[IDLBuiltinType.Types.object]),
+ IDLArgument(self.location,
+ IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
+ "thisArg"),
+ BuiltinTypes[IDLBuiltinType.Types.any],
+ optional=True)]
# Iterable adds ES6 iterator style functions and traits
# (keys/values/entries/@@iterator) to an interface.
@@ -3589,9 +3662,15 @@ class IDLIterable(IDLMaplikeOrSetlikeOrIterableBase):
we generate our functions as if they were part of the interface
specification during parsing.
"""
+ # We only need to add entries/keys/values here if we're a pair iterator.
+ # Value iterators just copy these from %ArrayPrototype% instead.
+ if not self.isPairIterator():
+ return
+
# object entries()
self.addMethod("entries", members, False, self.iteratorType,
- affectsNothing=True, newObject=True)
+ affectsNothing=True, newObject=True,
+ isIteratorAlias=True)
# object keys()
self.addMethod("keys", members, False, self.iteratorType,
affectsNothing=True, newObject=True)
@@ -3599,6 +3678,17 @@ class IDLIterable(IDLMaplikeOrSetlikeOrIterableBase):
self.addMethod("values", members, False, self.iteratorType,
affectsNothing=True, newObject=True)
+ # void forEach(callback(valueType, keyType), optional any thisArg)
+ self.addMethod("forEach", members, False,
+ BuiltinTypes[IDLBuiltinType.Types.void],
+ self.getForEachArguments())
+
+ def isValueIterator(self):
+ return not self.isPairIterator()
+
+ def isPairIterator(self):
+ return self.hasKeyType()
+
# MaplikeOrSetlike adds ES6 map-or-set-like traits to an interface.
class IDLMaplikeOrSetlike(IDLMaplikeOrSetlikeOrIterableBase):
@@ -3607,7 +3697,7 @@ class IDLMaplikeOrSetlike(IDLMaplikeOrSetlikeOrIterableBase):
IDLMaplikeOrSetlikeOrIterableBase.__init__(self, location, identifier, maplikeOrSetlikeType,
keyType, valueType, IDLInterfaceMember.Tags.MaplikeOrSetlike)
self.readonly = readonly
- self.slotIndex = None
+ self.slotIndices = None
# When generating JSAPI access code, we need to know the backing object
# type prefix to create the correct function. Generate here for reuse.
@@ -3635,26 +3725,17 @@ class IDLMaplikeOrSetlike(IDLMaplikeOrSetlikeOrIterableBase):
# object entries()
self.addMethod("entries", members, False, BuiltinTypes[IDLBuiltinType.Types.object],
- affectsNothing=True)
+ affectsNothing=True, isIteratorAlias=self.isMaplike())
# object keys()
self.addMethod("keys", members, False, BuiltinTypes[IDLBuiltinType.Types.object],
affectsNothing=True)
# object values()
self.addMethod("values", members, False, BuiltinTypes[IDLBuiltinType.Types.object],
- affectsNothing=True)
+ affectsNothing=True, isIteratorAlias=self.isSetlike())
# void forEach(callback(valueType, keyType), thisVal)
- foreachArguments = [IDLArgument(self.location,
- IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
- "callback"),
- BuiltinTypes[IDLBuiltinType.Types.object]),
- IDLArgument(self.location,
- IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
- "thisArg"),
- BuiltinTypes[IDLBuiltinType.Types.any],
- optional=True)]
self.addMethod("forEach", members, False, BuiltinTypes[IDLBuiltinType.Types.void],
- foreachArguments)
+ self.getForEachArguments())
def getKeyArg():
return IDLArgument(self.location,
@@ -3801,7 +3882,7 @@ class IDLAttribute(IDLInterfaceMember):
self.stringifier = stringifier
self.enforceRange = False
self.clamp = False
- self.slotIndex = None
+ self.slotIndices = None
assert maplikeOrSetlike is None or isinstance(maplikeOrSetlike, IDLMaplikeOrSetlike)
self.maplikeOrSetlike = maplikeOrSetlike
self.dependsOn = "Everything"
@@ -5444,10 +5525,13 @@ class Parser(Tokenizer):
location = self.getLocation(p, 2)
identifier = IDLUnresolvedIdentifier(location, "__iterable",
allowDoubleUnderscore=True)
- keyType = p[3]
- valueType = None
if (len(p) > 6):
+ keyType = p[3]
valueType = p[5]
+ else:
+ keyType = None
+ valueType = p[3]
+
p[0] = IDLIterable(location, identifier, keyType, valueType, self.globalScope())
def p_Setlike(self, p):
@@ -6518,7 +6602,7 @@ class Parser(Tokenizer):
if isinstance(m, IDLIterable):
iterable = m
break
- if iterable:
+ if iterable and iterable.isPairIterator():
def simpleExtendedAttr(str):
return IDLExtendedAttribute(iface.location, (str, ))
nextMethod = IDLMethod(