Bug 919603 part 1. Introduce support for the [Global] extended attribute. r=peterv

This commit is contained in:
Boris Zbarsky 2013-09-25 14:38:30 -04:00
parent d1348f2403
commit 0581c74c0b
2 changed files with 165 additions and 0 deletions

View File

@ -523,6 +523,7 @@ class IDLInterface(IDLObjectWithScope):
# have self as a consequential interface
self.interfacesImplementingSelf = set()
self._hasChildInterfaces = False
self._isOnGlobalProtoChain = False
IDLObjectWithScope.__init__(self, location, parentScope, name)
@ -586,6 +587,15 @@ class IDLInterface(IDLObjectWithScope):
self.parent._hasChildInterfaces = True
# Interfaces with [Global] must not have anything inherit from them
if self.parent.getExtendedAttribute("Global"):
# Note: This is not a self.parent.isOnGlobalProtoChain() check
# because ancestors of a [Global] interface can have other
# descendants.
raise WebIDLError("[Global] interface has another interface "
"inheriting from it",
[self.location, self.parent.location])
# Callbacks must not inherit from non-callbacks or inherit from
# anything that has consequential interfaces.
# XXXbz Can non-callbacks inherit from callbacks? Spec issue pending.
@ -741,6 +751,31 @@ class IDLInterface(IDLObjectWithScope):
specialMembersSeen[memberType] = member
if self._isOnGlobalProtoChain:
# Make sure we have no named setters, creators, or deleters
for memberType in ["setter", "creator", "deleter"]:
memberId = "named " + memberType + "s"
if memberId in specialMembersSeen:
raise WebIDLError("Interface with [Global] has a named %s" %
memberType,
[self.location,
specialMembersSeen[memberId].location])
# Make sure we're not [OverrideBuiltins]
if self.getExtendedAttribute("OverrideBuiltins"):
raise WebIDLError("Interface with [Global] also has "
"[OverrideBuiltins]",
[self.location])
# Mark all of our ancestors as being on the global's proto chain too
parent = self.parent
while parent:
# Must not inherit from an interface with [OverrideBuiltins]
if parent.getExtendedAttribute("OverrideBuiltins"):
raise WebIDLError("Interface with [Global] inherits from "
"interface with [OverrideBuiltins]",
[self.location, parent.location])
parent._isOnGlobalProtoChain = True
parent = parent.parent
def validate(self):
for member in self.members:
member.validate()
@ -924,6 +959,11 @@ class IDLInterface(IDLObjectWithScope):
raise WebIDLError("[ArrayClass] must not be specified on "
"an interface with inherited interfaces",
[attr.location, self.location])
elif identifier == "Global":
if not attr.noArguments():
raise WebIDLError("[Global] must take no arguments",
[attr.location])
self._isOnGlobalProtoChain = True
elif (identifier == "PrefControlled" or
identifier == "NeedNewResolve" or
identifier == "OverrideBuiltins" or
@ -1042,6 +1082,9 @@ class IDLInterface(IDLObjectWithScope):
def hasChildInterfaces(self):
return self._hasChildInterfaces
def isOnGlobalProtoChain(self):
return self._isOnGlobalProtoChain
def _getDependentObjects(self):
deps = set(self.members)
deps.union(self.implementedInterfaces)

View File

@ -0,0 +1,122 @@
def WebIDLTest(parser, harness):
parser.parse("""
[Global]
interface Foo : Bar {
getter any(DOMString name);
};
interface Bar {};
""")
results = parser.finish()
harness.ok(results[0].isOnGlobalProtoChain(),
"[Global] interface should be on global's proto chain")
harness.ok(results[1].isOnGlobalProtoChain(),
"[Global] interface should be on global's proto chain")
parser = parser.reset()
threw = False
try:
parser.parse("""
[Global]
interface Foo {
getter any(DOMString name);
setter void(DOMString name, any arg);
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw,
"Should have thrown for [Global] used on an interface with a "
"named setter")
parser = parser.reset()
threw = False
try:
parser.parse("""
[Global]
interface Foo {
getter any(DOMString name);
creator void(DOMString name, any arg);
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw,
"Should have thrown for [Global] used on an interface with a "
"named creator")
parser = parser.reset()
threw = False
try:
parser.parse("""
[Global]
interface Foo {
getter any(DOMString name);
deleter void(DOMString name);
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw,
"Should have thrown for [Global] used on an interface with a "
"named deleter")
parser = parser.reset()
threw = False
try:
parser.parse("""
[Global, OverrideBuiltins]
interface Foo {
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw,
"Should have thrown for [Global] used on an interface with a "
"[OverrideBuiltins]")
parser = parser.reset()
threw = False
try:
parser.parse("""
[Global]
interface Foo : Bar {
};
[OverrideBuiltins]
interface Bar {
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw,
"Should have thrown for [Global] used on an interface with an "
"[OverrideBuiltins] ancestor")
parser = parser.reset()
threw = False
try:
parser.parse("""
[Global]
interface Foo {
};
interface Bar : Foo {
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw,
"Should have thrown for [Global] used on an interface with a "
"descendant")