Bug 832014 part 1. Add parser support for an [Unforgeable] annotation on WebIDL interfaces. r=peterv

This commit is contained in:
Boris Zbarsky 2014-07-11 19:30:26 -04:00
parent 317399940c
commit ee5c456d8a
3 changed files with 124 additions and 19 deletions

View File

@ -669,8 +669,36 @@ class IDLInterface(IDLObjectWithScope):
for ancestorConsequential in ancestor.getConsequentialInterfaces():
ancestorConsequential.interfacesBasedOnSelf.add(self)
# Deal with interfaces marked [Unforgeable], now that we have our full
# member list, except unforgeables pulled in from parents. We want to
# do this before we set "originatingInterface" on our unforgeable
# members.
if self.getExtendedAttribute("Unforgeable"):
# Check that the interface already has all the things the
# spec would otherwise require us to synthesize and is
# missing the ones we plan to synthesize.
if not any(m.isMethod() and m.isStringifier() for m in self.members):
raise WebIDLError("Unforgeable interface %s does not have a "
"stringifier" % self.identifier.name,
[self.location])
for m in self.members:
if ((m.isMethod() and m.isJsonifier()) or
m.identifier.name == "toJSON"):
raise WebIDLError("Unforgeable interface %s has a "
"jsonifier so we won't be able to add "
"one ourselves" % self.identifier.name,
[self.location, m.location])
if m.identifier.name == "valueOf" and not m.isStatic():
raise WebIDLError("Unforgeable interface %s has a valueOf "
"member so we won't be able to add one "
"ourselves" % self.identifier.name,
[self.location, m.location])
for member in self.members:
if (member.isAttr() and member.isUnforgeable() and
if ((member.isAttr() or member.isMethod()) and
member.isUnforgeable() and
not hasattr(member, "originatingInterface")):
member.originatingInterface = self
@ -693,16 +721,16 @@ class IDLInterface(IDLObjectWithScope):
# worry about anything other than our parent, because it has already
# imported its ancestors unforgeable attributes into its member
# list.
for unforgeableAttr in (attr for attr in self.parent.members if
attr.isAttr() and not attr.isStatic() and
attr.isUnforgeable()):
for unforgeableMember in (member for member in self.parent.members if
(member.isAttr() or member.isMethod()) and
member.isUnforgeable()):
shadows = [ m for m in self.members if
(m.isAttr() or m.isMethod()) and
not m.isStatic() and
m.identifier.name == unforgeableAttr.identifier.name ]
m.identifier.name == unforgeableMember.identifier.name ]
if len(shadows) != 0:
locs = [unforgeableAttr.location] + [ s.location for s
in shadows ]
locs = [unforgeableMember.location] + [ s.location for s
in shadows ]
raise WebIDLError("Interface %s shadows [Unforgeable] "
"members of %s" %
(self.identifier.name,
@ -711,10 +739,10 @@ class IDLInterface(IDLObjectWithScope):
# And now just stick it in our members, since we won't be
# inheriting this down the proto chain. If we really cared we
# could try to do something where we set up the unforgeable
# attributes of ancestor interfaces, with their corresponding
# getters, on our interface, but that gets pretty complicated
# and seems unnecessary.
self.members.append(unforgeableAttr)
# attributes/methods of ancestor interfaces, with their
# corresponding getters, on our interface, but that gets pretty
# complicated and seems unnecessary.
self.members.append(unforgeableMember)
# Ensure that there's at most one of each {named,indexed}
# {getter,setter,creator,deleter}, at most one stringifier,
@ -785,6 +813,26 @@ class IDLInterface(IDLObjectWithScope):
parent = parent.parent
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
# it's consequential.
if self.getExtendedAttribute("Unforgeable") and self.isConsequential():
raise WebIDLError(
"%s is an unforgeable consequential interface" %
self.identifier.name,
[self.location] +
list(i.location for i in
(self.interfacesBasedOnSelf - { self }) ))
# We also don't support inheriting from unforgeable interfaces.
if self.getExtendedAttribute("Unforgeable") and self.hasChildInterfaces():
raise WebIDLError("%s is an unforgeable ancestor interface" %
self.identifier.name,
[self.location] +
list(i.location for i in
self.interfacesBasedOnSelf if i.parent == self))
for member in self.members:
member.validate()
@ -992,6 +1040,7 @@ class IDLInterface(IDLObjectWithScope):
elif (identifier == "NeedNewResolve" or
identifier == "OverrideBuiltins" or
identifier == "ChromeOnly" or
identifier == "Unforgeable" or
identifier == "LegacyEventInit"):
# Known extended attributes that do not take values
if not attr.noArguments():
@ -2889,9 +2938,6 @@ class IDLAttribute(IDLInterfaceMember):
[attr.location, self.location])
self.lenientThis = True
elif identifier == "Unforgeable":
if not self.readonly:
raise WebIDLError("[Unforgeable] is only allowed on readonly "
"attributes", [attr.location, self.location])
if self.isStatic():
raise WebIDLError("[Unforgeable] is only allowed on non-static "
"attributes", [attr.location, self.location])

View File

@ -79,6 +79,25 @@ def WebIDLTest(parser, harness):
"Should have thrown when shadowing unforgeable attribute on "
"parent with operation.")
parser = parser.reset();
threw = False
try:
parser.parse("""
interface Child : Parent {
void foo();
};
interface Parent {
[Unforgeable] void foo();
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw,
"Should have thrown when shadowing unforgeable operation on "
"parent with operation.")
parser = parser.reset();
threw = False
try:
@ -98,6 +117,25 @@ def WebIDLTest(parser, harness):
"Should have thrown when shadowing unforgeable attribute on "
"parent with attribute.")
parser = parser.reset();
threw = False
try:
parser.parse("""
interface Child : Parent {
attribute short foo;
};
interface Parent {
[Unforgeable] void foo();
};
""")
results = parser.finish()
except Exception,x:
threw = True
harness.ok(threw,
"Should have thrown when shadowing unforgeable operation on "
"parent with attribute.")
parser = parser.reset();
parser.parse("""
interface Child : Parent {
@ -166,16 +204,38 @@ def WebIDLTest(parser, harness):
threw = False
try:
parser.parse("""
interface iface {
[Unforgeable] attribute long foo;
interface Child : Parent {
};
interface Parent : GrandParent {};
interface GrandParent {};
interface Consequential {
[Unforgeable] void foo();
};
GrandParent implements Consequential;
interface ChildConsequential {
void foo();
};
Child implements ChildConsequential;
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Should have thrown for writable [Unforgeable] attribute.")
harness.ok(threw,
"Should have thrown when our consequential interface shadows unforgeable operation "
"of ancestor's consequential interface.")
parser = parser.reset();
parser.parse("""
interface iface {
[Unforgeable] attribute long foo;
};
""")
results = parser.finish()
harness.check(len(results), 1,
"Should allow writable [Unforgeable] attribute.")
parser = parser.reset();
threw = False

View File

@ -11,8 +11,7 @@
* and create derivative works of this document.
*/
// No support for [Unforgeable] on interfaces yet
//[Unforgeable]
[Unforgeable]
interface Location {
void assign(DOMString url);
void replace(DOMString url);