зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
06234aa6b7
Коммит
866605e3b0
|
@ -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;
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче