Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Update WebIDL.py
  • Loading branch information
saschanaz committed Oct 29, 2019
1 parent 4ff24af commit 97c01fc
Show file tree
Hide file tree
Showing 2 changed files with 172 additions and 6 deletions.
78 changes: 72 additions & 6 deletions components/script/dom/bindings/codegen/parser/WebIDL.py
Expand Up @@ -760,6 +760,8 @@ def finishMembers(self, scope):
# specified, it already has a nonempty exposure global names set.
if len(m._exposureGlobalNames) == 0:
m._exposureGlobalNames.update(self._exposureGlobalNames)
if m.isAttr() and m.stringifier:
m.expand(self.members)

# resolve() will modify self.members, so we need to iterate
# over a copy of the member list here.
Expand Down Expand Up @@ -1855,6 +1857,9 @@ def __init__(self, location, parentScope, name, parent, members):
self._finished = False
self.members = list(members)
self._partialDictionaries = []
self._extendedAttrDict = {}
self.needsConversionToJS = False
self.needsConversionFromJS = False

IDLObjectWithScope.__init__(self, location, parentScope, name)

Expand Down Expand Up @@ -1988,11 +1993,34 @@ def dictionaryContainsDictionary(dictMember, dictionary):
self.identifier.name,
[member.location] + locations)

def getExtendedAttribute(self, name):
return self._extendedAttrDict.get(name, None)

def addExtendedAttributes(self, attrs):
if len(attrs) != 0:
raise WebIDLError("There are no extended attributes that are "
"allowed on dictionaries",
[attrs[0].location, self.location])
for attr in attrs:
identifier = attr.identifier()

if (identifier == "GenerateInitFromJSON" or
identifier == "GenerateInit"):
if not attr.noArguments():
raise WebIDLError("[%s] must not have arguments" % identifier,
[attr.location])
self.needsConversionFromJS = True
elif (identifier == "GenerateConversionToJS" or
identifier == "GenerateToJSON"):
if not attr.noArguments():
raise WebIDLError("[%s] must not have arguments" % identifier,
[attr.location])
# ToJSON methods require to-JS conversion, because we
# implement ToJSON by converting to a JS object and
# then using JSON.stringify.
self.needsConversionToJS = True
else:
raise WebIDLError("[%s] extended attribute not allowed on "
"dictionaries" % identifier,
[attr.location])

self._extendedAttrDict[identifier] = True

def _getDependentObjects(self):
deps = set(self.members)
Expand All @@ -2004,6 +2032,7 @@ 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):
assert isinstance(parentScope, IDLScope)
Expand Down Expand Up @@ -4622,6 +4651,40 @@ def isUnforgeable(self):
def _getDependentObjects(self):
return set([self.type])

def expand(self, members):
assert self.stringifier
if not self.type.isDOMString() and not self.type.isUSVString():
raise WebIDLError("The type of a stringifer attribute must be "
"either DOMString or USVString",
[self.location])
identifier = IDLUnresolvedIdentifier(self.location, "__stringifier",
allowDoubleUnderscore=True)
method = IDLMethod(self.location,
identifier,
returnType=self.type, arguments=[],
stringifier=True, underlyingAttr=self)
allowedExtAttrs = ["Throws", "NeedsSubjectPrincipal", "Pure"]
# Safe to ignore these as they are only meaningful for attributes
attributeOnlyExtAttrs = [
"CEReactions",
"CrossOriginWritable",
"SetterThrows",
]
for (key, value) in self._extendedAttrDict.items():
if key in allowedExtAttrs:
if value is not True:
raise WebIDLError("[%s] with a value is currently "
"unsupported in stringifier attributes, "
"please file a bug to add support" % key,
[self.location])
method.addExtendedAttributes([IDLExtendedAttribute(self.location, (key,))])
elif not key in attributeOnlyExtAttrs:
raise WebIDLError("[%s] is currently unsupported in "
"stringifier attributes, please file a bug "
"to add support" % key,
[self.location])
members.append(method)


class IDLArgument(IDLObjectWithIdentifier):
def __init__(self, location, identifier, type, optional=False, defaultValue=None, variadic=False, dictionaryMember=False, allowTypeAttributes=False):
Expand Down Expand Up @@ -4867,7 +4930,8 @@ def __init__(self, location, identifier, returnType, arguments,
static=False, getter=False, setter=False,
deleter=False, specialType=NamedOrIndexed.Neither,
legacycaller=False, stringifier=False,
maplikeOrSetlikeOrIterable=None):
maplikeOrSetlikeOrIterable=None,
underlyingAttr=None):
# REVIEW: specialType is NamedOrIndexed -- wow, this is messed up.
IDLInterfaceMember.__init__(self, location, identifier,
IDLInterfaceMember.Tags.Method)
Expand All @@ -4894,6 +4958,7 @@ def __init__(self, location, identifier, returnType, arguments,
assert maplikeOrSetlikeOrIterable is None or isinstance(maplikeOrSetlikeOrIterable, IDLMaplikeOrSetlikeOrIterableBase)
self.maplikeOrSetlikeOrIterable = maplikeOrSetlikeOrIterable
self._htmlConstructor = False
self.underlyingAttr = underlyingAttr
self._specialType = specialType
self._unforgeable = False
self.dependsOn = "Everything"
Expand Down Expand Up @@ -4933,7 +4998,8 @@ def assertSignatureConstraints(self):
assert len(self._overloads) == 1
overload = self._overloads[0]
assert len(overload.arguments) == 0
assert overload.returnType == BuiltinTypes[IDLBuiltinType.Types.domstring]
if not self.underlyingAttr:
assert overload.returnType == BuiltinTypes[IDLBuiltinType.Types.domstring]

def isStatic(self):
return self._static
Expand Down
Expand Up @@ -44,3 +44,103 @@ def WebIDLTest(parser, harness):

harness.ok(threw, "Should not allow a 'stringifier;' and a 'stringifier()'")

parser = parser.reset()
parser.parse("""
interface TestStringifier {
stringifier attribute DOMString foo;
};
""")
results = parser.finish()
harness.ok(isinstance(results[0].members[0], WebIDL.IDLAttribute),
"Stringifier attribute should be an attribute")
stringifier = results[0].members[1]
harness.ok(isinstance(stringifier, WebIDL.IDLMethod),
"Stringifier attribute should insert a method")
harness.ok(stringifier.isStringifier(),
"Inserted method should be a stringifier")

parser = parser.reset()
parser.parse("""
interface TestStringifier {};
interface mixin TestStringifierMixin {
stringifier attribute DOMString foo;
};
TestStringifier includes TestStringifierMixin;
""")
results = parser.finish()
harness.ok(isinstance(results[0].members[0], WebIDL.IDLAttribute),
"Stringifier attribute should be an attribute")
stringifier = results[0].members[1]
harness.ok(isinstance(stringifier, WebIDL.IDLMethod),
"Stringifier attribute should insert a method")
harness.ok(stringifier.isStringifier(),
"Inserted method should be a stringifier")

parser = parser.reset()
parser.parse("""
interface TestStringifier {
stringifier attribute USVString foo;
};
""")
results = parser.finish()
stringifier = results[0].members[1]
harness.ok(stringifier.signatures()[0][0].isUSVString(),
"Stringifier attributes should allow USVString")

parser = parser.reset()
parser.parse("""
interface TestStringifier {
[Throws, NeedsSubjectPrincipal]
stringifier attribute USVString foo;
};
""")
results = parser.finish()
stringifier = results[0].members[1]
harness.ok(stringifier.getExtendedAttribute("Throws"),
"Stringifier attributes should support [Throws]")
harness.ok(stringifier.getExtendedAttribute("NeedsSubjectPrincipal"),
"Stringifier attributes should support [NeedsSubjectPrincipal]")

parser = parser.reset()
threw = False
try:
parser.parse("""
interface TestStringifier {
stringifier attribute ByteString foo;
};
""")
results = parser.finish()
except:
threw = True

harness.ok(threw, "Should not allow ByteString")

parser = parser.reset()
threw = False
try:
parser.parse("""
interface TestStringifier {
stringifier;
stringifier attribute DOMString foo;
};
""")
results = parser.finish()
except:
threw = True

harness.ok(threw, "Should not allow a 'stringifier;' and a stringifier attribute")

parser = parser.reset()
threw = False
try:
parser.parse("""
interface TestStringifier {
stringifier attribute DOMString foo;
stringifier attribute DOMString bar;
};
""")
results = parser.finish()
except:
threw = True

harness.ok(threw, "Should not allow multiple stringifier attributes")

0 comments on commit 97c01fc

Please sign in to comment.