mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
Update WebIDL.py to 4166cae81546
https://hg.mozilla.org/integration/autoland/rev/4166cae81546f54accae807413f806d20bf30920 Pulls in changes from https://bugzilla.mozilla.org/show_bug.cgi?id=1359269
This commit is contained in:
parent
5fa80a8be0
commit
7b48df53a1
21 changed files with 917 additions and 621 deletions
|
@ -420,48 +420,11 @@ class IDLObjectWithIdentifier(IDLObject):
|
|||
if parentScope:
|
||||
self.resolve(parentScope)
|
||||
|
||||
self.treatNullAs = "Default"
|
||||
|
||||
def resolve(self, parentScope):
|
||||
assert isinstance(parentScope, IDLScope)
|
||||
assert isinstance(self.identifier, IDLUnresolvedIdentifier)
|
||||
self.identifier.resolve(parentScope, self)
|
||||
|
||||
def checkForStringHandlingExtendedAttributes(self, attrs,
|
||||
isDictionaryMember=False,
|
||||
isOptional=False):
|
||||
"""
|
||||
A helper function to deal with TreatNullAs. Returns the list
|
||||
of attrs it didn't handle itself.
|
||||
"""
|
||||
assert isinstance(self, IDLArgument) or isinstance(self, IDLAttribute)
|
||||
unhandledAttrs = list()
|
||||
for attr in attrs:
|
||||
if not attr.hasValue():
|
||||
unhandledAttrs.append(attr)
|
||||
continue
|
||||
|
||||
identifier = attr.identifier()
|
||||
value = attr.value()
|
||||
if identifier == "TreatNullAs":
|
||||
if not self.type.isDOMString() or self.type.nullable():
|
||||
raise WebIDLError("[TreatNullAs] is only allowed on "
|
||||
"arguments or attributes whose type is "
|
||||
"DOMString",
|
||||
[self.location])
|
||||
if isDictionaryMember:
|
||||
raise WebIDLError("[TreatNullAs] is not allowed for "
|
||||
"dictionary members", [self.location])
|
||||
if value != 'EmptyString':
|
||||
raise WebIDLError("[TreatNullAs] must take the identifier "
|
||||
"'EmptyString', not '%s'" % value,
|
||||
[self.location])
|
||||
self.treatNullAs = value
|
||||
else:
|
||||
unhandledAttrs.append(attr)
|
||||
|
||||
return unhandledAttrs
|
||||
|
||||
|
||||
class IDLObjectWithScope(IDLObjectWithIdentifier, IDLScope):
|
||||
def __init__(self, location, parentScope, identifier):
|
||||
|
@ -2090,9 +2053,15 @@ class IDLType(IDLObject):
|
|||
IDLObject.__init__(self, location)
|
||||
self.name = name
|
||||
self.builtin = False
|
||||
self.clamp = False
|
||||
self.treatNullAsEmpty = False
|
||||
self.enforceRange = False
|
||||
self._extendedAttrDict = {}
|
||||
|
||||
def __eq__(self, other):
|
||||
return other and self.builtin == other.builtin and self.name == other.name
|
||||
return (other and self.builtin == other.builtin and self.name == other.name and
|
||||
self.clamp == other.clamp and self.enforceRange == other.enforceRange and
|
||||
self.treatNullAsEmpty == other.treatNullAsEmpty)
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
@ -2218,12 +2187,14 @@ class IDLType(IDLObject):
|
|||
assert self.tag() == IDLType.Tags.callback
|
||||
return self.nullable() and self.inner.callback._treatNonObjectAsNull
|
||||
|
||||
def addExtendedAttributes(self, attrs):
|
||||
if len(attrs) != 0:
|
||||
raise WebIDLError("There are no extended attributes that are "
|
||||
"allowed on types, for now (but this is "
|
||||
"changing; see bug 1359269)",
|
||||
def withExtendedAttributes(self, attrs):
|
||||
if len(attrs) > 0:
|
||||
raise WebIDLError("Extended attributes on types only supported for builtins",
|
||||
[attrs[0].location, self.location])
|
||||
return self
|
||||
|
||||
def getExtendedAttribute(self, name):
|
||||
return self._extendedAttrDict.get(name, None)
|
||||
|
||||
def resolveType(self, parentScope):
|
||||
pass
|
||||
|
@ -2244,8 +2215,9 @@ class IDLUnresolvedType(IDLType):
|
|||
Unresolved types are interface types
|
||||
"""
|
||||
|
||||
def __init__(self, location, name):
|
||||
def __init__(self, location, name, attrs=[]):
|
||||
IDLType.__init__(self, location, name)
|
||||
self.extraTypeAttributes = attrs
|
||||
|
||||
def isComplete(self):
|
||||
return False
|
||||
|
@ -2267,7 +2239,7 @@ class IDLUnresolvedType(IDLType):
|
|||
typedefType = IDLTypedefType(self.location, obj.innerType,
|
||||
obj.identifier)
|
||||
assert not typedefType.isComplete()
|
||||
return typedefType.complete(scope)
|
||||
return typedefType.complete(scope).withExtendedAttributes(self.extraTypeAttributes)
|
||||
elif obj.isCallback() and not obj.isInterface():
|
||||
assert self.name.name == obj.identifier.name
|
||||
return IDLCallbackType(obj.location, obj)
|
||||
|
@ -2275,6 +2247,9 @@ class IDLUnresolvedType(IDLType):
|
|||
name = self.name.resolve(scope, None)
|
||||
return IDLWrapperType(self.location, obj)
|
||||
|
||||
def withExtendedAttributes(self, attrs):
|
||||
return IDLUnresolvedType(self.location, self.name, attrs)
|
||||
|
||||
def isDistinguishableFrom(self, other):
|
||||
raise TypeError("Can't tell whether an unresolved type is or is not "
|
||||
"distinguishable from other things")
|
||||
|
@ -2790,12 +2765,17 @@ class IDLTypedefType(IDLType):
|
|||
def _getDependentObjects(self):
|
||||
return self.inner._getDependentObjects()
|
||||
|
||||
def withExtendedAttributes(self, attrs):
|
||||
return IDLTypedefType(self.location, self.inner.withExtendedAttributes(attrs), self.name)
|
||||
|
||||
|
||||
class IDLTypedef(IDLObjectWithIdentifier):
|
||||
def __init__(self, location, parentScope, innerType, name):
|
||||
# Set self.innerType first, because IDLObjectWithIdentifier.__init__
|
||||
# will call our __str__, which wants to use it.
|
||||
self.innerType = innerType
|
||||
identifier = IDLUnresolvedIdentifier(location, name)
|
||||
IDLObjectWithIdentifier.__init__(self, location, parentScope, identifier)
|
||||
self.innerType = innerType
|
||||
|
||||
def __str__(self):
|
||||
return "Typedef %s %s" % (self.identifier.name, self.innerType)
|
||||
|
@ -3107,10 +3087,59 @@ class IDLBuiltinType(IDLType):
|
|||
Types.ReadableStream: IDLType.Tags.interface,
|
||||
}
|
||||
|
||||
def __init__(self, location, name, type):
|
||||
def __init__(self, location, name, type, clamp=False, enforceRange=False, treatNullAsEmpty=False,
|
||||
attrLocation=[]):
|
||||
"""
|
||||
The mutually exclusive clamp/enforceRange/treatNullAsEmpty arguments are used to create instances
|
||||
of this type with the appropriate attributes attached. Use .clamped(), .rangeEnforced(), and .treatNullAs().
|
||||
|
||||
attrLocation is an array of source locations of these attributes for error reporting.
|
||||
"""
|
||||
IDLType.__init__(self, location, name)
|
||||
self.builtin = True
|
||||
self._typeTag = type
|
||||
self._clamped = None
|
||||
self._rangeEnforced = None
|
||||
self._withTreatNullAs = None
|
||||
if self.isNumeric():
|
||||
if clamp:
|
||||
self.clamp = True
|
||||
self.name = "Clamped" + self.name
|
||||
self._extendedAttrDict["Clamp"] = True
|
||||
elif enforceRange:
|
||||
self.enforceRange = True
|
||||
self.name = "RangeEnforced" + self.name
|
||||
self._extendedAttrDict["EnforceRange"] = True
|
||||
elif clamp or enforceRange:
|
||||
raise WebIDLError("Non-numeric types cannot be [Clamp] or [EnforceRange]", attrLocation)
|
||||
if self.isDOMString():
|
||||
if treatNullAsEmpty:
|
||||
self.treatNullAsEmpty = True
|
||||
self.name = "NullIsEmpty" + self.name
|
||||
self._extendedAttrDict["TreatNullAs"] = ["EmptyString"]
|
||||
elif treatNullAsEmpty:
|
||||
raise WebIDLError("Non-string types cannot be [TreatNullAs]", attrLocation)
|
||||
|
||||
def clamped(self, attrLocation):
|
||||
if not self._clamped:
|
||||
self._clamped = IDLBuiltinType(self.location, self.name,
|
||||
self._typeTag, clamp=True,
|
||||
attrLocation=attrLocation)
|
||||
return self._clamped
|
||||
|
||||
def rangeEnforced(self, attrLocation):
|
||||
if not self._rangeEnforced:
|
||||
self._rangeEnforced = IDLBuiltinType(self.location, self.name,
|
||||
self._typeTag, enforceRange=True,
|
||||
attrLocation=attrLocation)
|
||||
return self._rangeEnforced
|
||||
|
||||
def withTreatNullAs(self, attrLocation):
|
||||
if not self._withTreatNullAs:
|
||||
self._withTreatNullAs = IDLBuiltinType(self.location, self.name,
|
||||
self._typeTag, treatNullAsEmpty=True,
|
||||
attrLocation=attrLocation)
|
||||
return self._withTreatNullAs
|
||||
|
||||
def isPrimitive(self):
|
||||
return self._typeTag <= IDLBuiltinType.Types.double
|
||||
|
@ -3246,6 +3275,45 @@ class IDLBuiltinType(IDLType):
|
|||
def _getDependentObjects(self):
|
||||
return set()
|
||||
|
||||
def withExtendedAttributes(self, attrs):
|
||||
ret = self
|
||||
for attribute in attrs:
|
||||
identifier = attribute.identifier()
|
||||
if identifier == "Clamp":
|
||||
if not attribute.noArguments():
|
||||
raise WebIDLError("[Clamp] must take no arguments",
|
||||
[attribute.location])
|
||||
if ret.enforceRange or self.enforceRange:
|
||||
raise WebIDLError("[EnforceRange] and [Clamp] are mutually exclusive",
|
||||
[self.location, attribute.location])
|
||||
ret = self.clamped([self.location, attribute.location])
|
||||
elif identifier == "EnforceRange":
|
||||
if not attribute.noArguments():
|
||||
raise WebIDLError("[EnforceRange] must take no arguments",
|
||||
[attribute.location])
|
||||
if ret.clamp or self.clamp:
|
||||
raise WebIDLError("[EnforceRange] and [Clamp] are mutually exclusive",
|
||||
[self.location, attribute.location])
|
||||
ret = self.rangeEnforced([self.location, attribute.location])
|
||||
elif identifier == "TreatNullAs":
|
||||
if not self.isDOMString():
|
||||
raise WebIDLError("[TreatNullAs] only allowed on DOMStrings",
|
||||
[self.location, attribute.location])
|
||||
assert not self.nullable()
|
||||
if not attribute.hasValue():
|
||||
raise WebIDLError("[TreatNullAs] must take an identifier argument"
|
||||
[attribute.location])
|
||||
value = attribute.value()
|
||||
if value != 'EmptyString':
|
||||
raise WebIDLError("[TreatNullAs] must take the identifier "
|
||||
"'EmptyString', not '%s'" % value,
|
||||
[attribute.location])
|
||||
ret = self.withTreatNullAs([self.location, attribute.location])
|
||||
else:
|
||||
raise WebIDLError("Unhandled extended attribute on type",
|
||||
[self.location, attribute.location])
|
||||
return ret
|
||||
|
||||
BuiltinTypes = {
|
||||
IDLBuiltinType.Types.byte:
|
||||
IDLBuiltinType(BuiltinLocation("<builtin type>"), "Byte",
|
||||
|
@ -3460,6 +3528,10 @@ class IDLValue(IDLObject):
|
|||
# extra normalization step.
|
||||
assert self.type.isDOMString()
|
||||
return self
|
||||
elif self.type.isDOMString() and type.treatNullAsEmpty:
|
||||
# TreatNullAsEmpty is a different type for resolution reasons,
|
||||
# however once you have a value it doesn't matter
|
||||
return self
|
||||
elif self.type.isString() and type.isByteString():
|
||||
# Allow ByteStrings to use a default value like DOMString.
|
||||
# No coercion is required as Codegen.py will handle the
|
||||
|
@ -4096,8 +4168,6 @@ class IDLAttribute(IDLInterfaceMember):
|
|||
self.lenientThis = False
|
||||
self._unforgeable = False
|
||||
self.stringifier = stringifier
|
||||
self.enforceRange = False
|
||||
self.clamp = False
|
||||
self.slotIndices = None
|
||||
assert maplikeOrSetlike is None or isinstance(maplikeOrSetlike, IDLMaplikeOrSetlike)
|
||||
self.maplikeOrSetlike = maplikeOrSetlike
|
||||
|
@ -4134,6 +4204,9 @@ class IDLAttribute(IDLInterfaceMember):
|
|||
assert not isinstance(t.name, IDLUnresolvedIdentifier)
|
||||
self.type = t
|
||||
|
||||
if self.readonly and (self.type.clamp or self.type.enforceRange or self.type.treatNullAsEmpty):
|
||||
raise WebIDLError("A readonly attribute cannot be [Clamp] or [EnforceRange]",
|
||||
[self.location])
|
||||
if self.type.isDictionary() and not self.getExtendedAttribute("Cached"):
|
||||
raise WebIDLError("An attribute cannot be of a dictionary type",
|
||||
[self.location])
|
||||
|
@ -4357,16 +4430,6 @@ class IDLAttribute(IDLInterfaceMember):
|
|||
raise WebIDLError("[LenientFloat] used on an attribute with a "
|
||||
"non-restricted-float type",
|
||||
[attr.location, self.location])
|
||||
elif identifier == "EnforceRange":
|
||||
if self.readonly:
|
||||
raise WebIDLError("[EnforceRange] used on a readonly attribute",
|
||||
[attr.location, self.location])
|
||||
self.enforceRange = True
|
||||
elif identifier == "Clamp":
|
||||
if self.readonly:
|
||||
raise WebIDLError("[Clamp] used on a readonly attribute",
|
||||
[attr.location, self.location])
|
||||
self.clamp = True
|
||||
elif identifier == "StoreInSlot":
|
||||
if self.getExtendedAttribute("Cached"):
|
||||
raise WebIDLError("[StoreInSlot] and [Cached] must not be "
|
||||
|
@ -4468,10 +4531,6 @@ class IDLAttribute(IDLInterfaceMember):
|
|||
self.type.resolveType(parentScope)
|
||||
IDLObjectWithIdentifier.resolve(self, parentScope)
|
||||
|
||||
def addExtendedAttributes(self, attrs):
|
||||
attrs = self.checkForStringHandlingExtendedAttributes(attrs)
|
||||
IDLInterfaceMember.addExtendedAttributes(self, attrs)
|
||||
|
||||
def hasLenientThis(self):
|
||||
return self.lenientThis
|
||||
|
||||
|
@ -4491,7 +4550,7 @@ class IDLAttribute(IDLInterfaceMember):
|
|||
|
||||
|
||||
class IDLArgument(IDLObjectWithIdentifier):
|
||||
def __init__(self, location, identifier, type, optional=False, defaultValue=None, variadic=False, dictionaryMember=False):
|
||||
def __init__(self, location, identifier, type, optional=False, defaultValue=None, variadic=False, dictionaryMember=False, allowTypeAttributes=False):
|
||||
IDLObjectWithIdentifier.__init__(self, location, None, identifier)
|
||||
|
||||
assert isinstance(type, IDLType)
|
||||
|
@ -4502,37 +4561,19 @@ class IDLArgument(IDLObjectWithIdentifier):
|
|||
self.variadic = variadic
|
||||
self.dictionaryMember = dictionaryMember
|
||||
self._isComplete = False
|
||||
self.enforceRange = False
|
||||
self.clamp = False
|
||||
self._allowTreatNonCallableAsNull = False
|
||||
self._extendedAttrDict = {}
|
||||
self.allowTypeAttributes = allowTypeAttributes
|
||||
|
||||
assert not variadic or optional
|
||||
assert not variadic or not defaultValue
|
||||
|
||||
def addExtendedAttributes(self, attrs):
|
||||
attrs = self.checkForStringHandlingExtendedAttributes(
|
||||
attrs,
|
||||
isDictionaryMember=self.dictionaryMember,
|
||||
isOptional=self.optional)
|
||||
for attribute in attrs:
|
||||
identifier = attribute.identifier()
|
||||
if identifier == "Clamp":
|
||||
if not attribute.noArguments():
|
||||
raise WebIDLError("[Clamp] must take no arguments",
|
||||
[attribute.location])
|
||||
if self.enforceRange:
|
||||
raise WebIDLError("[EnforceRange] and [Clamp] are mutually exclusive",
|
||||
[self.location])
|
||||
self.clamp = True
|
||||
elif identifier == "EnforceRange":
|
||||
if not attribute.noArguments():
|
||||
raise WebIDLError("[EnforceRange] must take no arguments",
|
||||
[attribute.location])
|
||||
if self.clamp:
|
||||
raise WebIDLError("[EnforceRange] and [Clamp] are mutually exclusive",
|
||||
[self.location])
|
||||
self.enforceRange = True
|
||||
if self.allowTypeAttributes and (identifier == "EnforceRange" or identifier == "Clamp" or
|
||||
identifier == "TreatNullAs"):
|
||||
self.type = self.type.withExtendedAttributes([attribute])
|
||||
elif identifier == "TreatNonCallableAsNull":
|
||||
self._allowTreatNonCallableAsNull = True
|
||||
elif (self.dictionaryMember and
|
||||
|
@ -4583,6 +4624,8 @@ class IDLArgument(IDLObjectWithIdentifier):
|
|||
# codegen doesn't have to special-case this.
|
||||
self.defaultValue = IDLUndefinedValue(self.location)
|
||||
|
||||
if self.dictionaryMember and self.type.treatNullAsEmpty:
|
||||
raise WebIDLError("Dictionary members cannot be [TreatNullAs]", [self.location])
|
||||
# Now do the coercing thing; this needs to happen after the
|
||||
# above creation of a default value.
|
||||
if self.defaultValue:
|
||||
|
@ -5811,31 +5854,42 @@ class Parser(Tokenizer):
|
|||
# We're at the end of the list
|
||||
p[0] = []
|
||||
return
|
||||
# Add our extended attributes
|
||||
p[2].addExtendedAttributes(p[1])
|
||||
p[0] = [p[2]]
|
||||
p[0].extend(p[3])
|
||||
|
||||
def p_DictionaryMember(self, p):
|
||||
def p_DictionaryMemberRequired(self, p):
|
||||
"""
|
||||
DictionaryMember : Required Type IDENTIFIER Default SEMICOLON
|
||||
DictionaryMember : REQUIRED TypeWithExtendedAttributes IDENTIFIER SEMICOLON
|
||||
"""
|
||||
# These quack a lot like optional arguments, so just treat them that way.
|
||||
# These quack a lot like required arguments, so just treat them that way.
|
||||
t = p[2]
|
||||
assert isinstance(t, IDLType)
|
||||
identifier = IDLUnresolvedIdentifier(self.getLocation(p, 3), p[3])
|
||||
defaultValue = p[4]
|
||||
optional = not p[1]
|
||||
|
||||
if not optional and defaultValue:
|
||||
raise WebIDLError("Required dictionary members can't have a default value.",
|
||||
[self.getLocation(p, 4)])
|
||||
|
||||
p[0] = IDLArgument(self.getLocation(p, 3), identifier, t,
|
||||
optional=optional,
|
||||
defaultValue=defaultValue, variadic=False,
|
||||
optional=False,
|
||||
defaultValue=None, variadic=False,
|
||||
dictionaryMember=True)
|
||||
|
||||
def p_DictionaryMember(self, p):
|
||||
"""
|
||||
DictionaryMember : Type IDENTIFIER Default SEMICOLON
|
||||
"""
|
||||
# These quack a lot like optional arguments, so just treat them that way.
|
||||
t = p[1]
|
||||
assert isinstance(t, IDLType)
|
||||
identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
|
||||
defaultValue = p[3]
|
||||
|
||||
# Any attributes that precede this may apply to the type, so
|
||||
# we configure the argument to forward type attributes down instead of producing
|
||||
# a parse error
|
||||
p[0] = IDLArgument(self.getLocation(p, 2), identifier, t,
|
||||
optional=True,
|
||||
defaultValue=defaultValue, variadic=False,
|
||||
dictionaryMember=True, allowTypeAttributes=True)
|
||||
|
||||
def p_Default(self, p):
|
||||
"""
|
||||
Default : EQUALS DefaultValue
|
||||
|
@ -5923,7 +5977,7 @@ class Parser(Tokenizer):
|
|||
|
||||
def p_Typedef(self, p):
|
||||
"""
|
||||
Typedef : TYPEDEF Type IDENTIFIER SEMICOLON
|
||||
Typedef : TYPEDEF TypeWithExtendedAttributes IDENTIFIER SEMICOLON
|
||||
"""
|
||||
typedef = IDLTypedef(self.getLocation(p, 1), self.globalScope(),
|
||||
p[2], p[3])
|
||||
|
@ -6016,8 +6070,8 @@ class Parser(Tokenizer):
|
|||
|
||||
def p_Iterable(self, p):
|
||||
"""
|
||||
Iterable : ITERABLE LT Type GT SEMICOLON
|
||||
| ITERABLE LT Type COMMA Type GT SEMICOLON
|
||||
Iterable : ITERABLE LT TypeWithExtendedAttributes GT SEMICOLON
|
||||
| ITERABLE LT TypeWithExtendedAttributes COMMA TypeWithExtendedAttributes GT SEMICOLON
|
||||
"""
|
||||
location = self.getLocation(p, 2)
|
||||
identifier = IDLUnresolvedIdentifier(location, "__iterable",
|
||||
|
@ -6033,7 +6087,7 @@ class Parser(Tokenizer):
|
|||
|
||||
def p_Setlike(self, p):
|
||||
"""
|
||||
Setlike : ReadOnly SETLIKE LT Type GT SEMICOLON
|
||||
Setlike : ReadOnly SETLIKE LT TypeWithExtendedAttributes GT SEMICOLON
|
||||
"""
|
||||
readonly = p[1]
|
||||
maplikeOrSetlikeType = p[2]
|
||||
|
@ -6047,7 +6101,7 @@ class Parser(Tokenizer):
|
|||
|
||||
def p_Maplike(self, p):
|
||||
"""
|
||||
Maplike : ReadOnly MAPLIKE LT Type COMMA Type GT SEMICOLON
|
||||
Maplike : ReadOnly MAPLIKE LT TypeWithExtendedAttributes COMMA TypeWithExtendedAttributes GT SEMICOLON
|
||||
"""
|
||||
readonly = p[1]
|
||||
maplikeOrSetlikeType = p[2]
|
||||
|
@ -6085,7 +6139,7 @@ class Parser(Tokenizer):
|
|||
|
||||
def p_AttributeRest(self, p):
|
||||
"""
|
||||
AttributeRest : ReadOnly ATTRIBUTE Type AttributeName SEMICOLON
|
||||
AttributeRest : ReadOnly ATTRIBUTE TypeWithExtendedAttributes AttributeName SEMICOLON
|
||||
"""
|
||||
location = self.getLocation(p, 2)
|
||||
readonly = p[1]
|
||||
|
@ -6339,32 +6393,47 @@ class Parser(Tokenizer):
|
|||
|
||||
def p_Argument(self, p):
|
||||
"""
|
||||
Argument : ExtendedAttributeList Optional Type Ellipsis ArgumentName Default
|
||||
Argument : ExtendedAttributeList ArgumentRest
|
||||
"""
|
||||
t = p[3]
|
||||
p[0] = p[2]
|
||||
p[0].addExtendedAttributes(p[1])
|
||||
|
||||
def p_ArgumentRestOptional(self, p):
|
||||
"""
|
||||
ArgumentRest : OPTIONAL TypeWithExtendedAttributes ArgumentName Default
|
||||
"""
|
||||
t = p[2]
|
||||
assert isinstance(t, IDLType)
|
||||
identifier = IDLUnresolvedIdentifier(self.getLocation(p, 5), p[5])
|
||||
identifier = IDLUnresolvedIdentifier(self.getLocation(p, 3), p[3])
|
||||
|
||||
optional = p[2]
|
||||
variadic = p[4]
|
||||
defaultValue = p[6]
|
||||
defaultValue = p[4]
|
||||
|
||||
if not optional and defaultValue:
|
||||
raise WebIDLError("Mandatory arguments can't have a default value.",
|
||||
[self.getLocation(p, 6)])
|
||||
|
||||
# We can't test t.isAny() here and give it a default value as needed,
|
||||
# since at this point t is not a fully resolved type yet (e.g. it might
|
||||
# be a typedef). We'll handle the 'any' case in IDLArgument.complete.
|
||||
|
||||
if variadic:
|
||||
if optional:
|
||||
raise WebIDLError("Variadic arguments should not be marked optional.",
|
||||
[self.getLocation(p, 2)])
|
||||
optional = variadic
|
||||
p[0] = IDLArgument(self.getLocation(p, 3), identifier, t, True, defaultValue, False)
|
||||
|
||||
p[0] = IDLArgument(self.getLocation(p, 5), identifier, t, optional, defaultValue, variadic)
|
||||
p[0].addExtendedAttributes(p[1])
|
||||
def p_ArgumentRest(self, p):
|
||||
"""
|
||||
ArgumentRest : Type Ellipsis ArgumentName
|
||||
"""
|
||||
t = p[1]
|
||||
assert isinstance(t, IDLType)
|
||||
identifier = IDLUnresolvedIdentifier(self.getLocation(p, 3), p[3])
|
||||
|
||||
variadic = p[2]
|
||||
|
||||
# We can't test t.isAny() here and give it a default value as needed,
|
||||
# since at this point t is not a fully resolved type yet (e.g. it might
|
||||
# be a typedef). We'll handle the 'any' case in IDLArgument.complete.
|
||||
|
||||
# variadic implies optional
|
||||
# Any attributes that precede this may apply to the type, so
|
||||
# we configure the argument to forward type attributes down instead of producing
|
||||
# a parse error
|
||||
p[0] = IDLArgument(self.getLocation(p, 3), identifier, t, variadic, None, variadic, allowTypeAttributes=True)
|
||||
|
||||
def p_ArgumentName(self, p):
|
||||
"""
|
||||
|
@ -6403,30 +6472,6 @@ class Parser(Tokenizer):
|
|||
"""
|
||||
p[0] = p[1]
|
||||
|
||||
def p_Optional(self, p):
|
||||
"""
|
||||
Optional : OPTIONAL
|
||||
"""
|
||||
p[0] = True
|
||||
|
||||
def p_OptionalEmpty(self, p):
|
||||
"""
|
||||
Optional :
|
||||
"""
|
||||
p[0] = False
|
||||
|
||||
def p_Required(self, p):
|
||||
"""
|
||||
Required : REQUIRED
|
||||
"""
|
||||
p[0] = True
|
||||
|
||||
def p_RequiredEmpty(self, p):
|
||||
"""
|
||||
Required :
|
||||
"""
|
||||
p[0] = False
|
||||
|
||||
def p_Ellipsis(self, p):
|
||||
"""
|
||||
Ellipsis : ELLIPSIS
|
||||
|
@ -6567,6 +6612,12 @@ class Parser(Tokenizer):
|
|||
"""
|
||||
p[0] = self.handleNullable(p[1], p[2])
|
||||
|
||||
def p_TypeWithExtendedAttributes(self, p):
|
||||
"""
|
||||
TypeWithExtendedAttributes : ExtendedAttributeList Type
|
||||
"""
|
||||
p[0] = p[2].withExtendedAttributes(p[1])
|
||||
|
||||
def p_SingleTypeNonAnyType(self, p):
|
||||
"""
|
||||
SingleType : NonAnyType
|
||||
|
@ -6589,9 +6640,9 @@ class Parser(Tokenizer):
|
|||
|
||||
def p_UnionMemberTypeNonAnyType(self, p):
|
||||
"""
|
||||
UnionMemberType : NonAnyType
|
||||
UnionMemberType : ExtendedAttributeList NonAnyType
|
||||
"""
|
||||
p[0] = p[1]
|
||||
p[0] = p[2].withExtendedAttributes(p[1])
|
||||
|
||||
def p_UnionMemberType(self, p):
|
||||
"""
|
||||
|
@ -6641,7 +6692,7 @@ class Parser(Tokenizer):
|
|||
|
||||
def p_NonAnyTypeSequenceType(self, p):
|
||||
"""
|
||||
NonAnyType : SEQUENCE LT Type GT Null
|
||||
NonAnyType : SEQUENCE LT TypeWithExtendedAttributes GT Null
|
||||
"""
|
||||
innerType = p[3]
|
||||
type = IDLSequenceType(self.getLocation(p, 1), innerType)
|
||||
|
@ -6657,7 +6708,7 @@ class Parser(Tokenizer):
|
|||
|
||||
def p_NonAnyTypeRecordType(self, p):
|
||||
"""
|
||||
NonAnyType : RECORD LT StringType COMMA Type GT Null
|
||||
NonAnyType : RECORD LT StringType COMMA TypeWithExtendedAttributes GT Null
|
||||
"""
|
||||
keyType = p[3]
|
||||
valueType = p[5]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue