From 90a4da3e6f8cf03d5a8473f343c76fef044a439b Mon Sep 17 00:00:00 2001 From: Olli Pettay Date: Thu, 18 Apr 2013 19:58:01 +0300 Subject: [PATCH] Bug 863094 - Infinity/-Infinity/NaN defaults for unrestricted types, r=bz --HG-- extra : rebase_source : c2495008be9b084656222e6a0773c72d5224e9cc --- dom/bindings/Codegen.py | 18 +++- dom/bindings/parser/WebIDL.py | 22 ++-- dom/bindings/parser/tests/test_dictionary.py | 108 +++++++++++++++++++ dom/bindings/test/TestBindingHeader.h | 9 ++ dom/bindings/test/TestCodeGen.webidl | 26 +++++ 5 files changed, 174 insertions(+), 9 deletions(-) diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 800ab4f78f8..0dd833a32b1 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -8,6 +8,7 @@ import operator import os import re import string +import math from WebIDL import BuiltinTypes, IDLBuiltinType, IDLNullValue, IDLSequenceType, IDLType from Configuration import NoSuchDescriptorError, getTypesFromDescriptor, getTypesFromDictionary, getTypesFromCallback, Descriptor @@ -2045,10 +2046,23 @@ numericSuffixes = { IDLType.Tags.uint32: 'U', IDLType.Tags.int64: 'LL', IDLType.Tags.uint64: 'ULL', + IDLType.Tags.unrestricted_float: 'F', IDLType.Tags.float: 'F', + IDLType.Tags.unrestricted_double: 'D', IDLType.Tags.double: 'D' } +def numericValue(t, v): + if (t == IDLType.Tags.unrestricted_double or + t == IDLType.Tags.unrestricted_float): + if v == float("inf"): + return "MOZ_DOUBLE_POSITIVE_INFINITY()" + if v == float("-inf"): + return "MOZ_DOUBLE_NEGATIVE_INFINITY()" + if math.isnan(v): + return "MOZ_DOUBLE_NaN()" + return "%s%s" % (v, numericSuffixes[t]) + class CastableObjectUnwrapper(): """ A class for unwrapping an object named by the "source" argument @@ -3179,7 +3193,7 @@ for (uint32_t i = 0; i < length; ++i) { tag = defaultValue.type.tag() if tag in numericSuffixes: # Some numeric literals require a suffix to compile without warnings - defaultStr = "%s%s" % (defaultValue.value, numericSuffixes[tag]) + defaultStr = numericValue(tag, defaultValue.value) else: assert(tag == IDLType.Tags.bool) defaultStr = toStringBool(defaultValue.value) @@ -3286,7 +3300,7 @@ def convertConstIDLValueToJSVal(value): if tag == IDLType.Tags.uint32: return "UINT_TO_JSVAL(%sU)" % (value.value) if tag in [IDLType.Tags.int64, IDLType.Tags.uint64]: - return "DOUBLE_TO_JSVAL(%s%s)" % (value.value, numericSuffixes[tag]) + return "DOUBLE_TO_JSVAL(%s)" % numericValue(tag, value.value) if tag == IDLType.Tags.bool: return "JSVAL_TRUE" if value.value else "JSVAL_FALSE" if tag in [IDLType.Tags.float, IDLType.Tags.double]: diff --git a/dom/bindings/parser/WebIDL.py b/dom/bindings/parser/WebIDL.py index 902e4bce804..4494a229cc1 100644 --- a/dom/bindings/parser/WebIDL.py +++ b/dom/bindings/parser/WebIDL.py @@ -8,6 +8,7 @@ from ply import lex, yacc import re import os import traceback +import math # Machinery @@ -2257,6 +2258,13 @@ class IDLValue(IDLObject): % (self.value, type.inner.identifier.name), [location, type.inner.location]) return self + elif self.type.isFloat() and type.isFloat(): + if (not type.isUnrestricted() and + (self.value == float("inf") or self.value == float("-inf") or + math.isnan(self.value))): + raise WebIDLError("Trying to convert unrestricted value %s to non-unrestricted" + % self.value, [location]); + return self else: raise WebIDLError("Cannot coerce type %s to type %s." % (self.type, type), [location]) @@ -3148,6 +3156,11 @@ class Tokenizer(object): "OTHER" ] + def t_FLOATLITERAL(self, t): + r'(-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][+-]?[0-9]+)?|[0-9]+[Ee][+-]?[0-9]+|Infinity))|NaN' + t.value = float(t.value) + return t + def t_INTEGER(self, t): r'-?(0([0-7]+|[Xx][0-9A-Fa-f]+)?|[1-9][0-9]*)' try: @@ -3161,11 +3174,6 @@ class Tokenizer(object): filename=self._filename)]) return t - def t_FLOATLITERAL(self, t): - r'-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][+-]?[0-9]+)?|[0-9]+[Ee][+-]?[0-9]+)' - assert False - return t - def t_IDENTIFIER(self, t): r'[A-Z_a-z][0-9A-Z_a-z]*' t.type = self.keywords.get(t.value, 'IDENTIFIER') @@ -3594,8 +3602,8 @@ class Parser(Tokenizer): """ ConstValue : FLOATLITERAL """ - assert False - pass + location = self.getLocation(p, 1) + p[0] = IDLValue(location, BuiltinTypes[IDLBuiltinType.Types.unrestricted_float], p[1]) def p_ConstValueString(self, p): """ diff --git a/dom/bindings/parser/tests/test_dictionary.py b/dom/bindings/parser/tests/test_dictionary.py index 39037168ecd..4de41050981 100644 --- a/dom/bindings/parser/tests/test_dictionary.py +++ b/dom/bindings/parser/tests/test_dictionary.py @@ -442,3 +442,111 @@ def WebIDLTest(parser, harness): threw = True harness.ok(threw, "Member type must not be a nullable dictionary") + + parser = parser.reset(); + parser.parse(""" + dictionary Foo { + unrestricted float urFloat = 0; + unrestricted float urFloat2 = 1.1; + unrestricted float urFloat3 = -1.1; + unrestricted float? urFloat4 = null; + unrestricted float infUrFloat = Infinity; + unrestricted float negativeInfUrFloat = -Infinity; + unrestricted float nanUrFloat = NaN; + + unrestricted double urDouble = 0; + unrestricted double urDouble2 = 1.1; + unrestricted double urDouble3 = -1.1; + unrestricted double? urDouble4 = null; + unrestricted double infUrDouble = Infinity; + unrestricted double negativeInfUrDouble = -Infinity; + unrestricted double nanUrDouble = NaN; + }; + """) + results = parser.finish() + harness.ok(True, "Parsing default values for unrestricted types succeeded.") + + parser = parser.reset(); + threw = False + try: + parser.parse(""" + dictionary Foo { + double f = Infinity; + }; + """) + results = parser.finish() + except: + threw = True + + harness.ok(threw, "Only unrestricted values can be initialized to Infinity") + + parser = parser.reset(); + threw = False + try: + parser.parse(""" + dictionary Foo { + double f = -Infinity; + }; + """) + results = parser.finish() + except: + threw = True + + harness.ok(threw, "Only unrestricted values can be initialized to -Infinity") + + parser = parser.reset(); + threw = False + try: + parser.parse(""" + dictionary Foo { + double f = NaN; + }; + """) + results = parser.finish() + except: + threw = True + + harness.ok(threw, "Only unrestricted values can be initialized to NaN") + + parser = parser.reset(); + threw = False + try: + parser.parse(""" + dictionary Foo { + float f = Infinity; + }; + """) + results = parser.finish() + except: + threw = True + + harness.ok(threw, "Only unrestricted values can be initialized to Infinity") + + + parser = parser.reset(); + threw = False + try: + parser.parse(""" + dictionary Foo { + float f = -Infinity; + }; + """) + results = parser.finish() + except: + threw = True + + harness.ok(threw, "Only unrestricted values can be initialized to -Infinity") + + parser = parser.reset(); + threw = False + try: + parser.parse(""" + dictionary Foo { + float f = NaN; + }; + """) + results = parser.finish() + except: + threw = True + + harness.ok(threw, "Only unrestricted values can be initialized to NaN") diff --git a/dom/bindings/test/TestBindingHeader.h b/dom/bindings/test/TestBindingHeader.h index fcfb7a04e50..2434ff38861 100644 --- a/dom/bindings/test/TestBindingHeader.h +++ b/dom/bindings/test/TestBindingHeader.h @@ -229,6 +229,15 @@ public: double LenientDoubleAttr() const; void SetLenientDoubleAttr(double); + void PassUnrestricted(float arg1, + float arg2, + float arg3, + float arg4, + double arg5, + double arg6, + double arg7, + double arg8); + // Interface types already_AddRefed ReceiveSelf(); already_AddRefed ReceiveNullableSelf(); diff --git a/dom/bindings/test/TestCodeGen.webidl b/dom/bindings/test/TestCodeGen.webidl index 9f9aa9d3b80..a6f5384a84d 100644 --- a/dom/bindings/test/TestCodeGen.webidl +++ b/dom/bindings/test/TestCodeGen.webidl @@ -192,6 +192,15 @@ interface TestInterface { [LenientFloat] attribute double lenientDoubleAttr; + void passUnrestricted(optional unrestricted float arg1 = 0, + optional unrestricted float arg2 = Infinity, + optional unrestricted float arg3 = -Infinity, + optional unrestricted float arg4 = NaN, + optional unrestricted double arg5 = 0, + optional unrestricted double arg6 = Infinity, + optional unrestricted double arg7 = -Infinity, + optional unrestricted double arg8 = NaN); + // Castable interface types // XXXbz add tests for throwing versions of all the castable interface stuff TestInterface receiveSelf(); @@ -589,6 +598,23 @@ dictionary Dict : ParentDict { object? anotherObj = null; TestCallback? someCallback = null; any someAny; + + unrestricted float urFloat = 0; + unrestricted float urFloat2 = 1.1; + unrestricted float urFloat3 = -1.1; + unrestricted float? urFloat4 = null; + unrestricted float infUrFloat = Infinity; + unrestricted float negativeInfUrFloat = -Infinity; + unrestricted float nanUrFloat = NaN; + + unrestricted double urDouble = 0; + unrestricted double urDouble2 = 1.1; + unrestricted double urDouble3 = -1.1; + unrestricted double? urDouble4 = null; + unrestricted double infUrDouble = Infinity; + unrestricted double negativeInfUrDouble = -Infinity; + unrestricted double nanUrDouble = NaN; + }; dictionary ParentDict : GrandparentDict {