Bug 767933 part 1. Implement parser support for 'unrestricted float' and 'unrestricted double', and for the [LenientFloat] extended attribute. r=khuey

This commit is contained in:
Boris Zbarsky 2012-11-27 15:32:05 -05:00
Родитель 06234aa6b7
Коммит 866605e3b0
3 изменённых файлов: 209 добавлений и 8 удалений

Просмотреть файл

@ -928,7 +928,10 @@ class IDLType(IDLObject):
'uint64',
# Additional primitive types
'bool',
'unrestricted_float',
'float',
'unrestricted_double',
# "double" last primitive type to match IDLBuiltinType
'double',
# Other types
'any',
@ -1027,6 +1030,16 @@ class IDLType(IDLObject):
def isComplete(self):
return True
def includesRestrictedFloat(self):
return False
def isFloat(self):
return False
def isUnrestricted(self):
# Should only call this on float types
assert self.isFloat()
def tag(self):
assert False # Override me!
@ -1111,6 +1124,12 @@ class IDLNullableType(IDLType):
def isFloat(self):
return self.inner.isFloat()
def isUnrestricted(self):
return self.inner.isUnrestricted()
def includesRestrictedFloat(self):
return self.inner.includesRestrictedFloat()
def isInteger(self):
return self.inner.isInteger()
@ -1237,6 +1256,9 @@ class IDLSequenceType(IDLType):
def isEnum(self):
return False
def includesRestrictedFloat(self):
return self.inner.includesRestrictedFloat()
def tag(self):
# XXXkhuey this is probably wrong.
return self.inner.tag()
@ -1281,6 +1303,9 @@ class IDLUnionType(IDLType):
def isUnion(self):
return True
def includesRestrictedFloat(self):
return any(t.includesRestrictedFloat() for t in self.memberTypes)
def tag(self):
return IDLType.Tags.union
@ -1632,7 +1657,10 @@ class IDLBuiltinType(IDLType):
'unsigned_long_long',
# Additional primitive types
'boolean',
'unrestricted_float',
'float',
'unrestricted_double',
# IMPORTANT: "double" must be the last primitive type listed
'double',
# Other types
'any',
@ -1664,7 +1692,9 @@ class IDLBuiltinType(IDLType):
Types.long_long: IDLType.Tags.int64,
Types.unsigned_long_long: IDLType.Tags.uint64,
Types.boolean: IDLType.Tags.bool,
Types.unrestricted_float: IDLType.Tags.unrestricted_float,
Types.float: IDLType.Tags.float,
Types.unrestricted_double: IDLType.Tags.unrestricted_double,
Types.double: IDLType.Tags.double,
Types.any: IDLType.Tags.any,
Types.domstring: IDLType.Tags.domstring,
@ -1722,7 +1752,17 @@ class IDLBuiltinType(IDLType):
def isFloat(self):
return self._typeTag == IDLBuiltinType.Types.float or \
self._typeTag == IDLBuiltinType.Types.double
self._typeTag == IDLBuiltinType.Types.double or \
self._typeTag == IDLBuiltinType.Types.unrestricted_float or \
self._typeTag == IDLBuiltinType.Types.unrestricted_double
def isUnrestricted(self):
assert self.isFloat()
return self._typeTag == IDLBuiltinType.Types.unrestricted_float or \
self._typeTag == IDLBuiltinType.Types.unrestricted_double
def includesRestrictedFloat(self):
return self.isFloat() and not self.isUnrestricted()
def tag(self):
return IDLBuiltinType.TagLookup[self._typeTag]
@ -1799,9 +1839,15 @@ BuiltinTypes = {
IDLBuiltinType.Types.float:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "Float",
IDLBuiltinType.Types.float),
IDLBuiltinType.Types.unrestricted_float:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "UnrestrictedFloat",
IDLBuiltinType.Types.unrestricted_float),
IDLBuiltinType.Types.double:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "Double",
IDLBuiltinType.Types.double),
IDLBuiltinType.Types.unrestricted_double:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "UnrestrictedDouble",
IDLBuiltinType.Types.unrestricted_double),
IDLBuiltinType.Types.any:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "Any",
IDLBuiltinType.Types.any),
@ -2116,6 +2162,14 @@ class IDLAttribute(IDLInterfaceMember):
raise WebIDLError("[PutForwards] and [Replaceable] can't both "
"appear on the same attribute",
[attr.location, self.location])
elif identifier == "LenientFloat":
if self.readonly:
raise WebIDLError("[LenientFloat] used on a readonly attribute",
[attr.location, self.location])
if not self.type.includesRestrictedFloat():
raise WebIDLError("[LenientFloat] used on an attribute with a "
"non-restricted-float type",
[attr.location, self.location])
IDLInterfaceMember.handleExtendedAttribute(self, attr)
def resolve(self, parentScope):
@ -2590,6 +2644,17 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
elif identifier == "PutForwards":
raise WebIDLError("Only attributes support [PutForwards]",
[attr.location, self.location])
elif identifier == "LenientFloat":
# This is called before we've done overload resolution
assert len(self.signatures()) == 1
sig = self.signatures()[0]
if not sig[0].isVoid():
raise WebIDLError("[LenientFloat] used on a non-void method",
[attr.location, self.location])
if not any(arg.type.includesRestrictedFloat() for arg in sig[1]):
raise WebIDLError("[LenientFloat] used on an operation with no "
"restricted float type arguments",
[attr.location, self.location])
IDLInterfaceMember.handleExtendedAttribute(self, attr)
class IDLImplementsStatement(IDLObject):
@ -3783,12 +3848,24 @@ class Parser(Tokenizer):
"""
p[0] = IDLBuiltinType.Types.float
def p_PrimitiveOrStringTypeUnrestictedFloat(self, p):
"""
PrimitiveOrStringType : UNRESTRICTED FLOAT
"""
p[0] = IDLBuiltinType.Types.unrestricted_float
def p_PrimitiveOrStringTypeDouble(self, p):
"""
PrimitiveOrStringType : DOUBLE
"""
p[0] = IDLBuiltinType.Types.double
def p_PrimitiveOrStringTypeUnrestictedDouble(self, p):
"""
PrimitiveOrStringType : UNRESTRICTED DOUBLE
"""
p[0] = IDLBuiltinType.Types.unrestricted_double
def p_PrimitiveOrStringTypeDOMString(self, p):
"""
PrimitiveOrStringType : DOMSTRING

Просмотреть файл

@ -0,0 +1,125 @@
import WebIDL
def WebIDLTest(parser, harness):
parser.parse("""
typedef float myFloat;
typedef unrestricted float myUnrestrictedFloat;
interface FloatTypes {
attribute float f;
attribute unrestricted float uf;
attribute double d;
attribute unrestricted double ud;
[LenientFloat]
attribute float lf;
[LenientFloat]
attribute double ld;
void m1(float arg1, double arg2, float? arg3, double? arg4,
myFloat arg5, unrestricted float arg6,
unrestricted double arg7, unrestricted float? arg8,
unrestricted double? arg9, myUnrestrictedFloat arg10);
[LenientFloat]
void m2(float arg1, double arg2, float? arg3, double? arg4,
myFloat arg5, unrestricted float arg6,
unrestricted double arg7, unrestricted float? arg8,
unrestricted double? arg9, myUnrestrictedFloat arg10);
[LenientFloat]
void m3(float arg);
[LenientFloat]
void m4(double arg);
[LenientFloat]
void m5((float or FloatTypes) arg);
[LenientFloat]
void m6(sequence<float> arg);
};
""")
results = parser.finish()
harness.check(len(results), 3, "Should be two typedefs and one interface.")
iface = results[2]
harness.ok(isinstance(iface, WebIDL.IDLInterface),
"Should be an IDLInterface")
types = [a.type for a in iface.members if a.isAttr()]
harness.ok(types[0].isFloat(), "'float' is a float")
harness.ok(not types[0].isUnrestricted(), "'float' is not unrestricted")
harness.ok(types[1].isFloat(), "'unrestricted float' is a float")
harness.ok(types[1].isUnrestricted(), "'unrestricted float' is unrestricted")
harness.ok(types[2].isFloat(), "'double' is a float")
harness.ok(not types[2].isUnrestricted(), "'double' is not unrestricted")
harness.ok(types[3].isFloat(), "'unrestricted double' is a float")
harness.ok(types[3].isUnrestricted(), "'unrestricted double' is unrestricted")
method = iface.members[6]
harness.ok(isinstance(method, WebIDL.IDLMethod), "Should be an IDLMethod")
argtypes = [a.type for a in method.signatures()[0][1]]
for (idx, type) in enumerate(argtypes):
harness.ok(type.isFloat(), "Type %d should be float" % idx)
harness.check(type.isUnrestricted(), idx >= 5,
"Type %d should %sbe unrestricted" % (
idx, "" if idx >= 4 else "not "))
parser = parser.reset()
threw = False
try:
parser.parse("""
interface FloatTypes {
[LenientFloat]
long m(float arg);
};
""")
except Exception, x:
threw = True
harness.ok(threw, "[LenientFloat] only allowed on void methods")
parser = parser.reset()
threw = False
try:
parser.parse("""
interface FloatTypes {
[LenientFloat]
void m(unrestricted float arg);
};
""")
except Exception, x:
threw = True
harness.ok(threw, "[LenientFloat] only allowed on methods with unrestricted float args")
parser = parser.reset()
threw = False
try:
parser.parse("""
interface FloatTypes {
[LenientFloat]
void m(sequence<unrestricted float> arg);
};
""")
except Exception, x:
threw = True
harness.ok(threw, "[LenientFloat] only allowed on methods with unrestricted float args (2)")
parser = parser.reset()
threw = False
try:
parser.parse("""
interface FloatTypes {
[LenientFloat]
void m((unrestricted float or FloatTypes) arg);
};
""")
except Exception, x:
threw = True
harness.ok(threw, "[LenientFloat] only allowed on methods with unrestricted float args (3)")
parser = parser.reset()
threw = False
try:
parser.parse("""
interface FloatTypes {
[LenientFloat]
readonly attribute float foo;
};
""")
except Exception, x:
threw = True
harness.ok(threw, "[LenientFloat] only allowed on writable attributes")

Просмотреть файл

@ -39,28 +39,27 @@ def WebIDLTest(parser, harness):
attribute DOMString? b;
};
/* Not implemented. */
/*interface TestNullableEquivalency8 {
interface TestNullableEquivalency8 {
attribute float a;
attribute float? b;
};*/
};
interface TestNullableEquivalency8 {
interface TestNullableEquivalency9 {
attribute double a;
attribute double? b;
};
interface TestNullableEquivalency9 {
interface TestNullableEquivalency10 {
attribute object a;
attribute object? b;
};
interface TestNullableEquivalency10 {
interface TestNullableEquivalency11 {
attribute double[] a;
attribute double[]? b;
};
interface TestNullableEquivalency11 {
interface TestNullableEquivalency12 {
attribute TestNullableEquivalency9[] a;
attribute TestNullableEquivalency9[]? b;
};