Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Convert [HTMLConstructor] as constructor extension
  • Loading branch information
saschanaz committed Oct 19, 2019
1 parent 175c0d5 commit e271eda
Show file tree
Hide file tree
Showing 71 changed files with 323 additions and 217 deletions.
8 changes: 6 additions & 2 deletions components/script/dom/bindings/codegen/Configuration.py
Expand Up @@ -392,15 +392,19 @@ def hasDescendants(self):
return (self.interface.getUserData("hasConcreteDescendant", False) or
self.interface.getUserData("hasProxyDescendant", False))

def hasHTMLConstructor(self):
ctor = self.interface.ctor()
return ctor and ctor.isHTMLConstructor()

def shouldHaveGetConstructorObjectMethod(self):
assert self.interface.hasInterfaceObject()
if self.interface.getExtendedAttribute("Inline"):
return False
return (self.interface.isCallback() or self.interface.isNamespace() or
self.hasDescendants() or self.interface.getExtendedAttribute("HTMLConstructor"))
self.hasDescendants() or self.hasHTMLConstructor())

def shouldCacheConstructor(self):
return self.hasDescendants() or self.interface.getExtendedAttribute("HTMLConstructor")
return self.hasDescendants() or self.hasHTMLConstructor()

def isExposedConditionally(self):
return self.interface.isExposedConditionally()
Expand Down
199 changes: 100 additions & 99 deletions components/script/dom/bindings/codegen/parser/WebIDL.py
Expand Up @@ -1084,18 +1084,11 @@ def finish(self, scope):
"Can't have both a constructor and [Global]",
[self.location, ctor.location])

assert(len(ctor._exposureGlobalNames) == 0 or
ctor._exposureGlobalNames == self._exposureGlobalNames)
assert(ctor._exposureGlobalNames == self._exposureGlobalNames)
ctor._exposureGlobalNames.update(self._exposureGlobalNames)
if ctor in self.members:
# constructor operation.
self.members.remove(ctor)
else:
# extended attribute. This can only happen with
# [HTMLConstructor] and this is the only way we can get into this
# code with len(ctor._exposureGlobalNames) !=
# self._exposureGlobalNames.
ctor.finish(scope)
# Remove the constructor operation from our member list so
# it doesn't get in the way later.
self.members.remove(ctor)

for ctor in self.namedConstructors:
if self.globalNames:
Expand Down Expand Up @@ -1653,60 +1646,45 @@ def addExtendedAttributes(self, attrs):
[attr.location])

self._noInterfaceObject = True
elif identifier == "NamedConstructor" or identifier == "HTMLConstructor":
if identifier == "NamedConstructor" and not attr.hasValue():
elif identifier == "NamedConstructor":
if not attr.hasValue():
raise WebIDLError("NamedConstructor must either take an identifier or take a named argument list",
[attr.location])

if identifier == "HTMLConstructor":
if not attr.noArguments():
raise WebIDLError(str(identifier) + " must take no arguments",
[attr.location])

args = attr.args() if attr.hasArgs() else []

retType = IDLWrapperType(self.location, self)

if identifier == "HTMLConstructor":
name = "constructor"
allowForbidden = True
else:
name = attr.value()
allowForbidden = False

method = IDLConstructor(
attr.location, args, name,
htmlConstructor=(identifier == "HTMLConstructor"))
method = IDLConstructor(attr.location, args, attr.value())
method.reallyInit(self)

# Are always assumed to be able to throw (since there's no way to
# indicate otherwise).
# Named constructors are always assumed to be able to
# throw (since there's no way to indicate otherwise).
method.addExtendedAttributes(
[IDLExtendedAttribute(self.location, ("Throws",))])

if identifier == "HTMLConstructor":
method.resolve(self)
else:
# We need to detect conflicts for NamedConstructors across
# interfaces. We first call resolve on the parentScope,
# which will merge all NamedConstructors with the same
# identifier accross interfaces as overloads.
method.resolve(self.parentScope)

# Then we look up the identifier on the parentScope. If the
# result is the same as the method we're adding then it
# hasn't been added as an overload and it's the first time
# we've encountered a NamedConstructor with that identifier.
# If the result is not the same as the method we're adding
# then it has been added as an overload and we need to check
# whether the result is actually one of our existing
# NamedConstructors.
newMethod = self.parentScope.lookupIdentifier(method.identifier)
if newMethod == method:
self.namedConstructors.append(method)
elif newMethod not in self.namedConstructors:
raise WebIDLError("NamedConstructor conflicts with a NamedConstructor of a different interface",
[method.location, newMethod.location])
# We need to detect conflicts for NamedConstructors across
# interfaces. We first call resolve on the parentScope,
# which will merge all NamedConstructors with the same
# identifier accross interfaces as overloads.
method.resolve(self.parentScope)

# Then we look up the identifier on the parentScope. If the
# result is the same as the method we're adding then it
# hasn't been added as an overload and it's the first time
# we've encountered a NamedConstructor with that identifier.
# If the result is not the same as the method we're adding
# then it has been added as an overload and we need to check
# whether the result is actually one of our existing
# NamedConstructors.
newMethod = self.parentScope.lookupIdentifier(method.identifier)
if newMethod == method:
self.namedConstructors.append(method)
elif newMethod not in self.namedConstructors:
raise WebIDLError("NamedConstructor conflicts with a "
"NamedConstructor of a different interface",
[method.location, newMethod.location])
elif (identifier == "ExceptionClass"):
if not attr.noArguments():
raise WebIDLError("[ExceptionClass] must take no arguments",
Expand Down Expand Up @@ -1777,6 +1755,11 @@ def addExtendedAttributes(self, attrs):
if not attr.hasValue():
raise WebIDLError("[%s] must have a value" % identifier,
[attr.location])
elif identifier == "InstrumentedProps":
# Known extended attributes that take a list
if not attr.hasArgs():
raise WebIDLError("[%s] must have arguments" % identifier,
[attr.location])
else:
raise WebIDLError("Unknown extended attribute %s on interface" % identifier,
[attr.location])
Expand Down Expand Up @@ -4884,7 +4867,7 @@ def __init__(self, location, identifier, returnType, arguments,
static=False, getter=False, setter=False,
deleter=False, specialType=NamedOrIndexed.Neither,
legacycaller=False, stringifier=False,
maplikeOrSetlikeOrIterable=None, htmlConstructor=False):
maplikeOrSetlikeOrIterable=None):
# REVIEW: specialType is NamedOrIndexed -- wow, this is messed up.
IDLInterfaceMember.__init__(self, location, identifier,
IDLInterfaceMember.Tags.Method)
Expand All @@ -4910,10 +4893,7 @@ def __init__(self, location, identifier, returnType, arguments,
self._stringifier = stringifier
assert maplikeOrSetlikeOrIterable is None or isinstance(maplikeOrSetlikeOrIterable, IDLMaplikeOrSetlikeOrIterableBase)
self.maplikeOrSetlikeOrIterable = maplikeOrSetlikeOrIterable
assert isinstance(htmlConstructor, bool)
# The identifier of a HTMLConstructor must be 'constructor'.
assert not htmlConstructor or identifier.name == "constructor"
self._htmlConstructor = htmlConstructor
self._htmlConstructor = False
self._specialType = specialType
self._unforgeable = False
self.dependsOn = "Everything"
Expand Down Expand Up @@ -5408,14 +5388,13 @@ def _getDependentObjects(self):


class IDLConstructor(IDLMethod):
def __init__(self, location, args, name, htmlConstructor=False):
def __init__(self, location, args, name):
# We can't actually init our IDLMethod yet, because we do not know the
# return type yet. Just save the info we have for now and we will init
# it later.
self._initLocation = location
self._initArgs = args
self._initName = name
self._htmlConstructor = htmlConstructor
self._inited = False
self._initExtendedAttrs = []

Expand All @@ -5432,6 +5411,18 @@ def handleExtendedAttribute(self, attr):
identifier == "SecureContext" or
identifier == "Throws"):
IDLMethod.handleExtendedAttribute(self, attr)
elif identifier == "HTMLConstructor":
if not attr.noArguments():
raise WebIDLError("[HTMLConstructor] must take no arguments",
[attr.location])
# We shouldn't end up here for named constructors.
assert(self.identifier.name == "constructor")

if any(len(sig[1]) != 0 for sig in self.signatures()):
raise WebIDLError("[HTMLConstructor] must not be applied to a "
"constructor operation that has arguments.",
[attr.location])
self._htmlConstructor = True
else:
raise WebIDLError("Unknown extended attribute %s on method" % identifier,
[attr.location])
Expand All @@ -5442,7 +5433,7 @@ def reallyInit(self, parentInterface):
identifier = IDLUnresolvedIdentifier(location, name, allowForbidden=True)
retType = IDLWrapperType(parentInterface.location, parentInterface)
IDLMethod.__init__(self, location, identifier, retType, self._initArgs,
static=True, htmlConstructor=self._htmlConstructor)
static=True)
self._inited = True;
# Propagate through whatever extended attributes we already had
self.addExtendedAttributes(self._initExtendedAttrs)
Expand Down Expand Up @@ -5660,6 +5651,8 @@ def t_OTHER(self, t):
"namespace": "NAMESPACE",
"ReadableStream": "READABLESTREAM",
"constructor": "CONSTRUCTOR",
"symbol": "SYMBOL",
"async": "ASYNC",
}

tokens.extend(keywords.values())
Expand Down Expand Up @@ -6746,37 +6739,54 @@ def p_ArgumentRest(self, p):
def p_ArgumentName(self, p):
"""
ArgumentName : IDENTIFIER
| ATTRIBUTE
| CALLBACK
| CONST
| CONSTRUCTOR
| DELETER
| DICTIONARY
| ENUM
| EXCEPTION
| GETTER
| INHERIT
| INTERFACE
| ITERABLE
| LEGACYCALLER
| MAPLIKE
| PARTIAL
| REQUIRED
| SERIALIZER
| SETLIKE
| SETTER
| STATIC
| STRINGIFIER
| TYPEDEF
| UNRESTRICTED
| NAMESPACE
| ArgumentNameKeyword
"""
p[0] = p[1]

def p_ArgumentNameKeyword(self, p):
"""
ArgumentNameKeyword : ASYNC
| ATTRIBUTE
| CALLBACK
| CONST
| CONSTRUCTOR
| DELETER
| DICTIONARY
| ENUM
| EXCEPTION
| GETTER
| INCLUDES
| INHERIT
| INTERFACE
| ITERABLE
| LEGACYCALLER
| MAPLIKE
| MIXIN
| NAMESPACE
| PARTIAL
| READONLY
| REQUIRED
| SERIALIZER
| SETLIKE
| SETTER
| STATIC
| STRINGIFIER
| TYPEDEF
| UNRESTRICTED
"""
p[0] = p[1]

def p_AttributeName(self, p):
"""
AttributeName : IDENTIFIER
| REQUIRED
| AttributeNameKeyword
"""
p[0] = p[1]

def p_AttributeNameKeyword(self, p):
"""
AttributeNameKeyword : ASYNC
| REQUIRED
"""
p[0] = p[1]

Expand Down Expand Up @@ -6868,36 +6878,27 @@ def p_Other(self, p):
| BYTESTRING
| USVSTRING
| JSSTRING
| PROMISE
| ANY
| ATTRIBUTE
| BOOLEAN
| BYTE
| LEGACYCALLER
| CONST
| CONSTRUCTOR
| DELETER
| DOUBLE
| EXCEPTION
| FALSE
| FLOAT
| GETTER
| INHERIT
| INTERFACE
| LONG
| NULL
| OBJECT
| OCTET
| OR
| OPTIONAL
| SEQUENCE
| RECORD
| SETTER
| SEQUENCE
| SHORT
| STATIC
| STRINGIFIER
| SYMBOL
| TRUE
| TYPEDEF
| UNSIGNED
| VOID
| ArgumentNameKeyword
"""
pass

Expand Down

0 comments on commit e271eda

Please sign in to comment.