[V8] Binding: Implement EnforceRange IDL Attribute for long long conversions
authorjsbell@chromium.org <jsbell@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 15 Mar 2013 18:58:05 +0000 (18:58 +0000)
committerjsbell@chromium.org <jsbell@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 15 Mar 2013 18:58:05 +0000 (18:58 +0000)
https://bugs.webkit.org/show_bug.cgi?id=96798

Reviewed by Kentaro Hara.

Source/WebCore:

Implement [EnforceRange] attribute for V8 bindings, which specifies throwing behavior
on conversions outside int/uint 32/64 ranges and edge cases like NaNs and Infinities.
Conversely, conversions without this attribute should *not* throw.

Tests: fast/js/webidl-type-mapping.html:
       fast/dom/non-numeric-values-numeric-parameters.html
       fast/js/script-tests/select-options-add.html
       storage/indexeddb/intversion-bad-parameters.html

* Modules/indexeddb/IDBCursor.cpp: Remove custom range enforcement for advance()
* Modules/indexeddb/IDBCursor.h: Adjust type to match WebIDL.
* Modules/indexeddb/IDBCursor.idl: Specify [EnforceRange] and type matches spec WebIDL.
* Modules/indexeddb/IDBFactory.cpp: Remove custom range enforcement for open()
* Modules/indexeddb/IDBFactory.h: Adjust type to match WebIDL.
* Modules/indexeddb/IDBFactory.idl: Specify [EnforceRange] and type matches spec WebIDL.
* bindings/scripts/CodeGeneratorJS.pm:
(JSValueToNative): Add FIXME to support [EnforceRange]
* bindings/scripts/CodeGeneratorV8.pm:
(GenerateNormalAttrSetter): Handle [EnforceRange] in attribute setters
(GenerateParametersCheck): Handle [EnforceRange] in parameters.
(JSValueToNative): Pass EnforceRange to toInt() functions as appropriate.
* bindings/scripts/IDLAttributes.txt:
* bindings/scripts/test/TestObj.idl: Tests w/ [EnforceRange]
* bindings/scripts/test/V8/V8TestObj.cpp: Updated expectations
* bindings/scripts/test/V8/V8TestTypedefs.cpp: Updated expectations.
* bindings/v8/V8Binding.cpp: Overloads for toInt() variants that handle constraints.
(WebCore::toInt32):
(WebCore::toUInt32):
(WebCore::toInt64):
(WebCore::toUInt64):
* bindings/v8/V8Binding.h: Ditto, plus helpers for callers not expecting errors.
(WebCore::toInt32):
(WebCore::toUInt32):
(WebCore::toInt64):
(WebCore::toUInt64):
* bindings/v8/V8BindingMacros.h: Helper macros for type conversions that may throw.
* testing/TypeConversions.h: Added new members with EnforceRange constraint.
* testing/TypeConversions.idl: Ditto.

LayoutTests:

Some of the tests for HTMLOptionsCollection.add() assumed it should throw for
Infinities and NaNs, but this is not what the DOM+WebIDL specs say. (Firefox doesn't throw
so this does not appear to be a web-compat issue.) This updates the tests/expectations so
that V8 passes. JSC expectations are FAIL in a few places since it still incorrectly throws
on Infinity/NaN -> int32 conversion (existing tests) and does not implement EnforceRange
(new tests).

Tne non-numeric-values-numeric-parameters test was also broken for NaN testing, reporting
incorrect results which hid some of this behavior.

* fast/dom/non-numeric-values-numeric-parameters-expected.txt: Failing behavior for JSC.
* fast/dom/script-tests/non-numeric-values-numeric-parameters.js: HTMLOptionsCollection.add()
should not throw on NaNs/Infinities.
* fast/js/script-tests/select-options-add.js: Ditto.
* fast/js/select-options-add-expected.txt: Failing behavior for JSC.
* fast/js/webidl-type-mapping-expected.txt: Ditto.
* fast/js/webidl-type-mapping.html: Added test cases for [EnforceRange]
* platform/chromium/fast/dom/non-numeric-values-numeric-parameters-expected.txt: Added - passing behavior for V8.
* platform/chromium/fast/js/select-options-add-expected.txt: Ditto.
* platform/chromium/fast/js/webidl-type-mapping-expected.txt: Added.
* storage/indexeddb/intversion-bad-parameters-expected.txt: Added non-finite test cases.
* storage/indexeddb/resources/intversion-bad-parameters.js: Ditto.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@145929 268f45cc-cd09-0410-ab3c-d52691b4dbfc

30 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/dom/non-numeric-values-numeric-parameters-expected.txt
LayoutTests/fast/dom/script-tests/non-numeric-values-numeric-parameters.js
LayoutTests/fast/js/script-tests/select-options-add.js
LayoutTests/fast/js/select-options-add-expected.txt
LayoutTests/fast/js/webidl-type-mapping-expected.txt
LayoutTests/fast/js/webidl-type-mapping.html
LayoutTests/platform/chromium/fast/dom/non-numeric-values-numeric-parameters-expected.txt [new file with mode: 0644]
LayoutTests/platform/chromium/fast/js/select-options-add-expected.txt [new file with mode: 0644]
LayoutTests/platform/chromium/fast/js/webidl-type-mapping-expected.txt [new file with mode: 0644]
LayoutTests/storage/indexeddb/intversion-bad-parameters-expected.txt
LayoutTests/storage/indexeddb/resources/intversion-bad-parameters.js
Source/WebCore/ChangeLog
Source/WebCore/Modules/indexeddb/IDBCursor.cpp
Source/WebCore/Modules/indexeddb/IDBCursor.h
Source/WebCore/Modules/indexeddb/IDBCursor.idl
Source/WebCore/Modules/indexeddb/IDBFactory.cpp
Source/WebCore/Modules/indexeddb/IDBFactory.h
Source/WebCore/Modules/indexeddb/IDBFactory.idl
Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
Source/WebCore/bindings/scripts/CodeGeneratorV8.pm
Source/WebCore/bindings/scripts/IDLAttributes.txt
Source/WebCore/bindings/scripts/test/TestObj.idl
Source/WebCore/bindings/scripts/test/V8/V8TestObj.cpp
Source/WebCore/bindings/scripts/test/V8/V8TestTypedefs.cpp
Source/WebCore/bindings/v8/V8Binding.cpp
Source/WebCore/bindings/v8/V8Binding.h
Source/WebCore/bindings/v8/V8BindingMacros.h
Source/WebCore/testing/TypeConversions.h
Source/WebCore/testing/TypeConversions.idl

index a7e8c31..99b2aa1 100644 (file)
@@ -1,3 +1,33 @@
+2013-03-15  Joshua Bell  <jsbell@chromium.org>
+
+        [V8] Binding: Implement EnforceRange IDL Attribute for long long conversions
+        https://bugs.webkit.org/show_bug.cgi?id=96798
+
+        Reviewed by Kentaro Hara.
+
+        Some of the tests for HTMLOptionsCollection.add() assumed it should throw for
+        Infinities and NaNs, but this is not what the DOM+WebIDL specs say. (Firefox doesn't throw
+        so this does not appear to be a web-compat issue.) This updates the tests/expectations so
+        that V8 passes. JSC expectations are FAIL in a few places since it still incorrectly throws
+        on Infinity/NaN -> int32 conversion (existing tests) and does not implement EnforceRange
+        (new tests).
+
+        Tne non-numeric-values-numeric-parameters test was also broken for NaN testing, reporting
+        incorrect results which hid some of this behavior.
+
+        * fast/dom/non-numeric-values-numeric-parameters-expected.txt: Failing behavior for JSC.
+        * fast/dom/script-tests/non-numeric-values-numeric-parameters.js: HTMLOptionsCollection.add()
+        should not throw on NaNs/Infinities.
+        * fast/js/script-tests/select-options-add.js: Ditto.
+        * fast/js/select-options-add-expected.txt: Failing behavior for JSC.
+        * fast/js/webidl-type-mapping-expected.txt: Ditto.
+        * fast/js/webidl-type-mapping.html: Added test cases for [EnforceRange]
+        * platform/chromium/fast/dom/non-numeric-values-numeric-parameters-expected.txt: Added - passing behavior for V8.
+        * platform/chromium/fast/js/select-options-add-expected.txt: Ditto.
+        * platform/chromium/fast/js/webidl-type-mapping-expected.txt: Added.
+        * storage/indexeddb/intversion-bad-parameters-expected.txt: Added non-finite test cases.
+        * storage/indexeddb/resources/intversion-bad-parameters.js: Ditto.
+
 2013-03-15  Simon Fraser  <simon.fraser@apple.com>
 
         Marking sputnik/Conformance/10_Execution_Contexts/10.1_Definitions/10.1.8_Arguments_Object/S10.1.8_A3_T2.html
index 97bf1e0..4713c42 100644 (file)
@@ -28,7 +28,7 @@ PASS nonNumericPolicy('document.body.scrollTop = x') is 'any type allowed'
 PASS nonNumericPolicy('document.images.item(x)') is 'any type allowed'
 PASS nonNumericPolicy('document.createElement("input").setSelectionRange(x, 0)') is 'any type allowed'
 PASS nonNumericPolicy('document.createElement("input").setSelectionRange(0, x)') is 'any type allowed'
-PASS nonNumericPolicy('createHTMLOptionsCollection().add(document.createElement("option"), x)') is 'number or null allowed (or omitted, but not infinite)'
+FAIL nonNumericPolicy('createHTMLOptionsCollection().add(document.createElement("option"), x)') should be any type allowed. Was mixed.
 PASS nonNumericPolicy('createHTMLOptionsCollection().remove(x)') is 'any type allowed'
 PASS nonNumericPolicy('createHTMLSelectElement().remove(x)') is 'any type allowed'
 PASS nonNumericPolicy('createHTMLSelectElement().item(x)') is 'any type allowed'
index 2e7006c..58bed16 100644 (file)
@@ -64,7 +64,7 @@ function nonNumericPolicy(template)
     try {
         eval(template);
     } catch (e) {
-        NaNAllowed = 0;
+        nanAllowed = 0;
     }
 
     var omitAllowed = -1; // means "not applicable"
@@ -244,7 +244,7 @@ shouldBe("nonNumericPolicy('document.createElement(\"input\").setSelectionRange(
 
 // HTMLOptionsCollection
 
-shouldBe("nonNumericPolicy('createHTMLOptionsCollection().add(document.createElement(\"option\"), x)')", "'number or null allowed (or omitted, but not infinite)'");
+shouldBe("nonNumericPolicy('createHTMLOptionsCollection().add(document.createElement(\"option\"), x)')", "'any type allowed'");
 shouldBe("nonNumericPolicy('createHTMLOptionsCollection().remove(x)')", "'any type allowed'");
 
 // HTMLSelectElement
index a358cea..aacf94d 100644 (file)
@@ -244,84 +244,84 @@ debug("");
 
 debug("2.9 Add an Option at index -Infinity");
 option2 = document.createElement("OPTION");
-shouldThrow("select2.options.add(option2, -1/0)");
-shouldBe("select2.options.length", "7");
-shouldBe("select2.selectedIndex", "1");
+shouldNotThrow("select2.options.add(option2, -1/0)");
+shouldBe("select2.options.length", "8");
+shouldBe("select2.selectedIndex", "2");
 debug("");
 
 debug("2.10 Add an Option at index NaN");
 option2 = document.createElement("OPTION");
-shouldThrow("select2.options.add(option2, 0/0)");
-shouldBe("select2.options.length", "7");
-shouldBe("select2.selectedIndex", "1");
+shouldNotThrow("select2.options.add(option2, 0/0)");
+shouldBe("select2.options.length", "9");
+shouldBe("select2.selectedIndex", "3");
 debug("");
 
 debug("2.11 Add an Option at index Infinity");
 option2 = document.createElement("OPTION");
-shouldThrow("select2.options.add(option2, 1/0)");
-shouldBe("select2.options.length", "7");
-shouldBe("select2.selectedIndex", "1");
+shouldNotThrow("select2.options.add(option2, 1/0)");
+shouldBe("select2.options.length", "10");
+shouldBe("select2.selectedIndex", "4");
 debug("");
 
 debug("2.12 Add a non-Option element");
 option2 = document.createElement("DIV");
 shouldThrow("select2.options.add(option2, 1)");
-shouldBe("select2.options.length", "7");
-shouldBe("select2.selectedIndex", "1");
+shouldBe("select2.options.length", "10");
+shouldBe("select2.selectedIndex", "4");
 debug("");
 
 debug("2.13 Add a non-element (string)");
 option2 = "o";
 shouldThrow("select2.options.add(option2, 1)");
-shouldBe("select2.options.length", "7");
-shouldBe("select2.selectedIndex", "1");
+shouldBe("select2.options.length", "10");
+shouldBe("select2.selectedIndex", "4");
 debug("");
 
 debug("2.14 Add a non-element (number)");
 option2 = 3.14;
 shouldThrow("select2.options.add(option2, 1)");
-shouldBe("select2.options.length", "7");
-shouldBe("select2.selectedIndex", "1");
+shouldBe("select2.options.length", "10");
+shouldBe("select2.selectedIndex", "4");
 debug("");
 
 debug("2.15 Add a non-element (boolean)");
 option2 = true;
 shouldThrow("select2.options.add(option2, 1)");
-shouldBe("select2.options.length", "7");
-shouldBe("select2.selectedIndex", "1");
+shouldBe("select2.options.length", "10");
+shouldBe("select2.selectedIndex", "4");
 debug("");
 
 debug("2.16 Add undefined");
 option2 = undefined;
 shouldThrow("select2.options.add(option2, 1)");
-shouldBe("select2.options.length", "7");
-shouldBe("select2.selectedIndex", "1");
+shouldBe("select2.options.length", "10");
+shouldBe("select2.selectedIndex", "4");
 debug("");
 
 debug("2.17 Add null");
 option2 = null;
 shouldThrow("select2.options.add(option2, 1)");
-shouldBe("select2.options.length", "7");
-shouldBe("select2.selectedIndex", "1");
+shouldBe("select2.options.length", "10");
+shouldBe("select2.selectedIndex", "4");
 debug("");
 
 debug("2.18 Add negative infinity");
 option2 = -1/0;
 shouldThrow("select2.options.add(option2, 1)");
-shouldBe("select2.options.length", "7");
-shouldBe("select2.selectedIndex", "1");
+shouldBe("select2.options.length", "10");
+shouldBe("select2.selectedIndex", "4");
 debug("");
 
 debug("2.19 Add NaN");
 option2 = 0/0;
 shouldThrow("select2.options.add(option2, 1)");
-shouldBe("select2.options.length", "7");
-shouldBe("select2.selectedIndex", "1");
+shouldBe("select2.options.length", "10");
+shouldBe("select2.selectedIndex", "4");
 debug("");
 
 debug("2.20 Add positive infinity");
 option2 = 1/0;
 shouldThrow("select2.options.add(option2, 1)");
-shouldBe("select2.options.length", "7");
-shouldBe("select2.selectedIndex", "1");
+shouldBe("select2.options.length", "10");
+shouldBe("select2.selectedIndex", "4");
 debug("");
index 7a77778..33056ff 100644 (file)
@@ -163,64 +163,64 @@ PASS select2.options.length is 7
 PASS select2.selectedIndex is 1
 
 2.9 Add an Option at index -Infinity
-PASS select2.options.add(option2, -1/0) threw exception Error: TypeMismatchError: DOM Exception 17.
-PASS select2.options.length is 7
-PASS select2.selectedIndex is 1
+FAIL select2.options.add(option2, -1/0) should not throw exception. Threw exception Error: TypeMismatchError: DOM Exception 17.
+FAIL select2.options.length should be 8. Was 7.
+FAIL select2.selectedIndex should be 2. Was 1.
 
 2.10 Add an Option at index NaN
-PASS select2.options.add(option2, 0/0) threw exception Error: TypeMismatchError: DOM Exception 17.
-PASS select2.options.length is 7
-PASS select2.selectedIndex is 1
+FAIL select2.options.add(option2, 0/0) should not throw exception. Threw exception Error: TypeMismatchError: DOM Exception 17.
+FAIL select2.options.length should be 9. Was 7.
+FAIL select2.selectedIndex should be 3. Was 1.
 
 2.11 Add an Option at index Infinity
-PASS select2.options.add(option2, 1/0) threw exception Error: TypeMismatchError: DOM Exception 17.
-PASS select2.options.length is 7
-PASS select2.selectedIndex is 1
+FAIL select2.options.add(option2, 1/0) should not throw exception. Threw exception Error: TypeMismatchError: DOM Exception 17.
+FAIL select2.options.length should be 10. Was 7.
+FAIL select2.selectedIndex should be 4. Was 1.
 
 2.12 Add a non-Option element
 PASS select2.options.add(option2, 1) threw exception Error: TypeMismatchError: DOM Exception 17.
-PASS select2.options.length is 7
-PASS select2.selectedIndex is 1
+FAIL select2.options.length should be 10. Was 7.
+FAIL select2.selectedIndex should be 4. Was 1.
 
 2.13 Add a non-element (string)
 PASS select2.options.add(option2, 1) threw exception Error: TypeMismatchError: DOM Exception 17.
-PASS select2.options.length is 7
-PASS select2.selectedIndex is 1
+FAIL select2.options.length should be 10. Was 7.
+FAIL select2.selectedIndex should be 4. Was 1.
 
 2.14 Add a non-element (number)
 PASS select2.options.add(option2, 1) threw exception Error: TypeMismatchError: DOM Exception 17.
-PASS select2.options.length is 7
-PASS select2.selectedIndex is 1
+FAIL select2.options.length should be 10. Was 7.
+FAIL select2.selectedIndex should be 4. Was 1.
 
 2.15 Add a non-element (boolean)
 PASS select2.options.add(option2, 1) threw exception Error: TypeMismatchError: DOM Exception 17.
-PASS select2.options.length is 7
-PASS select2.selectedIndex is 1
+FAIL select2.options.length should be 10. Was 7.
+FAIL select2.selectedIndex should be 4. Was 1.
 
 2.16 Add undefined
 PASS select2.options.add(option2, 1) threw exception Error: TypeMismatchError: DOM Exception 17.
-PASS select2.options.length is 7
-PASS select2.selectedIndex is 1
+FAIL select2.options.length should be 10. Was 7.
+FAIL select2.selectedIndex should be 4. Was 1.
 
 2.17 Add null
 PASS select2.options.add(option2, 1) threw exception Error: TypeMismatchError: DOM Exception 17.
-PASS select2.options.length is 7
-PASS select2.selectedIndex is 1
+FAIL select2.options.length should be 10. Was 7.
+FAIL select2.selectedIndex should be 4. Was 1.
 
 2.18 Add negative infinity
 PASS select2.options.add(option2, 1) threw exception Error: TypeMismatchError: DOM Exception 17.
-PASS select2.options.length is 7
-PASS select2.selectedIndex is 1
+FAIL select2.options.length should be 10. Was 7.
+FAIL select2.selectedIndex should be 4. Was 1.
 
 2.19 Add NaN
 PASS select2.options.add(option2, 1) threw exception Error: TypeMismatchError: DOM Exception 17.
-PASS select2.options.length is 7
-PASS select2.selectedIndex is 1
+FAIL select2.options.length should be 10. Was 7.
+FAIL select2.selectedIndex should be 4. Was 1.
 
 2.20 Add positive infinity
 PASS select2.options.add(option2, 1) threw exception Error: TypeMismatchError: DOM Exception 17.
-PASS select2.options.length is 7
-PASS select2.selectedIndex is 1
+FAIL select2.options.length should be 10. Was 7.
+FAIL select2.selectedIndex should be 4. Was 1.
 
 PASS successfullyParsed is true
 
index 5b2a8cf..686063d 100644 (file)
@@ -69,13 +69,78 @@ converter.testLong = true
 PASS converter.testLong is 1
 converter.testLong = ''
 PASS converter.testLong is 0
+converter.testLong = '1'
+PASS converter.testLong is 1
 converter.testLong = 'abc'
 PASS converter.testLong is 0
 converter.testLong = null
 PASS converter.testLong is 0
 converter.testLong = undefined
 PASS converter.testLong is 0
-PASS converter.testLong = {valueOf:function(){throw new Error;}} threw exception Error.
+PASS converter.testLong = {valueOf:function(){throw new Error('custom');}} threw exception Error: custom.
+
+PASS 'testEnforceRangeLong' in converter is true
+PASS typeof converter.testEnforceRangeLong === 'number' is true
+converter.testEnforceRangeLong = 0
+PASS converter.testEnforceRangeLong is 0
+converter.testEnforceRangeLong = -1
+PASS converter.testEnforceRangeLong is -1
+converter.testEnforceRangeLong = 1
+PASS converter.testEnforceRangeLong is 1
+converter.testEnforceRangeLong = 0x7F
+PASS converter.testEnforceRangeLong is 0x7F
+converter.testEnforceRangeLong = 0x80
+PASS converter.testEnforceRangeLong is 0x80
+converter.testEnforceRangeLong = 0xFF
+PASS converter.testEnforceRangeLong is 0xFF
+converter.testEnforceRangeLong = -0x80
+PASS converter.testEnforceRangeLong is -0x80
+converter.testEnforceRangeLong = -0x81
+PASS converter.testEnforceRangeLong is -0x81
+converter.testEnforceRangeLong = 0x7FFF
+PASS converter.testEnforceRangeLong is 0x7FFF
+converter.testEnforceRangeLong = 0x8000
+PASS converter.testEnforceRangeLong is 0x8000
+converter.testEnforceRangeLong = 0xFFFF
+PASS converter.testEnforceRangeLong is 0xFFFF
+converter.testEnforceRangeLong = -0x8000
+PASS converter.testEnforceRangeLong is -0x8000
+converter.testEnforceRangeLong = -0x8001
+PASS converter.testEnforceRangeLong is -0x8001
+converter.testEnforceRangeLong = 0x7FFFFFFF
+PASS converter.testEnforceRangeLong is 0x7FFFFFFF
+FAIL converter.testEnforceRangeLong = 0x80000000 should throw an exception. Was 2147483648.
+FAIL converter.testEnforceRangeLong = 0xFFFFFFFF should throw an exception. Was 4294967295.
+converter.testEnforceRangeLong = -0x80000000
+PASS converter.testEnforceRangeLong is -0x80000000
+FAIL converter.testEnforceRangeLong = -0x80000001 should throw an exception. Was -2147483649.
+FAIL converter.testEnforceRangeLong = 0xDCBA9876543210 should throw an exception. Was 62129658859368980.
+FAIL converter.testEnforceRangeLong = Number.MAX_VALUE should throw an exception. Was 1.7976931348623157e+308.
+converter.testEnforceRangeLong = Number.MIN_VALUE
+PASS converter.testEnforceRangeLong is 0
+FAIL converter.testEnforceRangeLong = -Number.MAX_VALUE should throw an exception. Was -1.7976931348623157e+308.
+converter.testEnforceRangeLong = -Number.MIN_VALUE
+PASS converter.testEnforceRangeLong is 0
+converter.testEnforceRangeLong = 1.99
+PASS converter.testEnforceRangeLong is 1
+converter.testEnforceRangeLong = -1.99
+PASS converter.testEnforceRangeLong is -1
+FAIL converter.testEnforceRangeLong = Infinity should throw an exception. Was Infinity.
+FAIL converter.testEnforceRangeLong = -Infinity should throw an exception. Was -Infinity.
+FAIL converter.testEnforceRangeLong = NaN should throw an exception. Was NaN.
+converter.testEnforceRangeLong = false
+PASS converter.testEnforceRangeLong is 0
+converter.testEnforceRangeLong = true
+PASS converter.testEnforceRangeLong is 1
+converter.testEnforceRangeLong = ''
+PASS converter.testEnforceRangeLong is 0
+converter.testEnforceRangeLong = '1'
+PASS converter.testEnforceRangeLong is 1
+FAIL converter.testEnforceRangeLong = 'abc' should throw an exception. Was abc.
+converter.testEnforceRangeLong = null
+PASS converter.testEnforceRangeLong is 0
+FAIL converter.testEnforceRangeLong = undefined should throw an exception. Was undefined.
+PASS converter.testEnforceRangeLong = {valueOf:function(){throw new Error('custom');}} threw exception Error: custom.
 
 PASS 'testUnsignedLong' in converter is true
 PASS typeof converter.testUnsignedLong === 'number' is true
@@ -141,13 +206,73 @@ converter.testUnsignedLong = true
 PASS converter.testUnsignedLong is 1
 converter.testUnsignedLong = ''
 PASS converter.testUnsignedLong is 0
+converter.testUnsignedLong = '1'
+PASS converter.testUnsignedLong is 1
 converter.testUnsignedLong = 'abc'
 PASS converter.testUnsignedLong is 0
 converter.testUnsignedLong = null
 PASS converter.testUnsignedLong is 0
 converter.testUnsignedLong = undefined
 PASS converter.testUnsignedLong is 0
-PASS converter.testUnsignedLong = {valueOf:function(){throw new Error;}} threw exception Error.
+PASS converter.testUnsignedLong = {valueOf:function(){throw new Error('custom');}} threw exception Error: custom.
+
+PASS 'testEnforceRangeUnsignedLong' in converter is true
+PASS typeof converter.testEnforceRangeUnsignedLong === 'number' is true
+converter.testEnforceRangeUnsignedLong = 0
+PASS converter.testEnforceRangeUnsignedLong is 0
+FAIL converter.testEnforceRangeUnsignedLong = -1 should throw an exception. Was -1.
+converter.testEnforceRangeUnsignedLong = 1
+PASS converter.testEnforceRangeUnsignedLong is 1
+converter.testEnforceRangeUnsignedLong = 0x7F
+PASS converter.testEnforceRangeUnsignedLong is 0x7F
+converter.testEnforceRangeUnsignedLong = 0x80
+PASS converter.testEnforceRangeUnsignedLong is 0x80
+converter.testEnforceRangeUnsignedLong = 0xFF
+PASS converter.testEnforceRangeUnsignedLong is 0xFF
+FAIL converter.testEnforceRangeUnsignedLong = -0x80 should throw an exception. Was -128.
+FAIL converter.testEnforceRangeUnsignedLong = -0x81 should throw an exception. Was -129.
+converter.testEnforceRangeUnsignedLong = 0x7FFF
+PASS converter.testEnforceRangeUnsignedLong is 0x7FFF
+converter.testEnforceRangeUnsignedLong = 0x8000
+PASS converter.testEnforceRangeUnsignedLong is 0x8000
+converter.testEnforceRangeUnsignedLong = 0xFFFF
+PASS converter.testEnforceRangeUnsignedLong is 0xFFFF
+FAIL converter.testEnforceRangeUnsignedLong = -0x8000 should throw an exception. Was -32768.
+FAIL converter.testEnforceRangeUnsignedLong = -0x8001 should throw an exception. Was -32769.
+converter.testEnforceRangeUnsignedLong = 0x7FFFFFFF
+PASS converter.testEnforceRangeUnsignedLong is 0x7FFFFFFF
+converter.testEnforceRangeUnsignedLong = 0x80000000
+PASS converter.testEnforceRangeUnsignedLong is 0x80000000
+converter.testEnforceRangeUnsignedLong = 0xFFFFFFFF
+PASS converter.testEnforceRangeUnsignedLong is 0xFFFFFFFF
+FAIL converter.testEnforceRangeUnsignedLong = -0x80000000 should throw an exception. Was -2147483648.
+FAIL converter.testEnforceRangeUnsignedLong = -0x80000001 should throw an exception. Was -2147483649.
+FAIL converter.testEnforceRangeUnsignedLong = 0xDCBA9876543210 should throw an exception. Was 62129658859368980.
+FAIL converter.testEnforceRangeUnsignedLong = Number.MAX_VALUE should throw an exception. Was 1.7976931348623157e+308.
+converter.testEnforceRangeUnsignedLong = Number.MIN_VALUE
+PASS converter.testEnforceRangeUnsignedLong is 0
+FAIL converter.testEnforceRangeUnsignedLong = -Number.MAX_VALUE should throw an exception. Was -1.7976931348623157e+308.
+converter.testEnforceRangeUnsignedLong = -Number.MIN_VALUE
+PASS converter.testEnforceRangeUnsignedLong is 0
+converter.testEnforceRangeUnsignedLong = 1.99
+PASS converter.testEnforceRangeUnsignedLong is 1
+FAIL converter.testEnforceRangeUnsignedLong = -1.99 should throw an exception. Was -1.99.
+FAIL converter.testEnforceRangeUnsignedLong = Infinity should throw an exception. Was Infinity.
+FAIL converter.testEnforceRangeUnsignedLong = -Infinity should throw an exception. Was -Infinity.
+FAIL converter.testEnforceRangeUnsignedLong = NaN should throw an exception. Was NaN.
+converter.testEnforceRangeUnsignedLong = false
+PASS converter.testEnforceRangeUnsignedLong is 0
+converter.testEnforceRangeUnsignedLong = true
+PASS converter.testEnforceRangeUnsignedLong is 1
+converter.testEnforceRangeUnsignedLong = ''
+PASS converter.testEnforceRangeUnsignedLong is 0
+converter.testEnforceRangeUnsignedLong = '1'
+PASS converter.testEnforceRangeUnsignedLong is 1
+FAIL converter.testEnforceRangeUnsignedLong = 'abc' should throw an exception. Was abc.
+converter.testEnforceRangeUnsignedLong = null
+PASS converter.testEnforceRangeUnsignedLong is 0
+FAIL converter.testEnforceRangeUnsignedLong = undefined should throw an exception. Was undefined.
+PASS converter.testEnforceRangeUnsignedLong = {valueOf:function(){throw new Error('custom');}} threw exception Error: custom.
 
 PASS 'testLongLong' in converter is true
 PASS typeof converter.testLongLong === 'number' is true
@@ -193,23 +318,101 @@ converter.testLongLong = Number.MIN_VALUE
 PASS converter.testLongLong is 0
 converter.testLongLong = -Number.MIN_VALUE
 PASS converter.testLongLong is 0
+converter.testLongLong = Number.MAX_VALUE
+FAIL converter.testLongLong should be 0. Was -9223372036854776000.
+converter.testLongLong = -Number.MAX_VALUE
+FAIL converter.testLongLong should be 0. Was -9223372036854776000.
 converter.testLongLong = 1.99
 PASS converter.testLongLong is 1
 converter.testLongLong = -1.99
 PASS converter.testLongLong is -1
+converter.testLongLong = Infinity
+FAIL converter.testLongLong should be 0. Was -9223372036854776000.
+converter.testLongLong = -Infinity
+FAIL converter.testLongLong should be 0. Was -9223372036854776000.
+converter.testLongLong = NaN
+PASS converter.testLongLong is 0
 converter.testLongLong = false
 PASS converter.testLongLong is 0
 converter.testLongLong = true
 PASS converter.testLongLong is 1
 converter.testLongLong = ''
 PASS converter.testLongLong is 0
+converter.testLongLong = '1'
+PASS converter.testLongLong is 1
 converter.testLongLong = 'abc'
 PASS converter.testLongLong is 0
 converter.testLongLong = null
 PASS converter.testLongLong is 0
 converter.testLongLong = undefined
 PASS converter.testLongLong is 0
-PASS converter.testLongLong = {valueOf:function(){throw new Error;}} threw exception Error.
+PASS converter.testLongLong = {valueOf:function(){throw new Error('custom');}} threw exception Error: custom.
+
+PASS 'testEnforceRangeLongLong' in converter is true
+PASS typeof converter.testEnforceRangeLongLong === 'number' is true
+converter.testEnforceRangeLongLong = 0
+PASS converter.testEnforceRangeLongLong is 0
+converter.testEnforceRangeLongLong = -1
+PASS converter.testEnforceRangeLongLong is -1
+converter.testEnforceRangeLongLong = 1
+PASS converter.testEnforceRangeLongLong is 1
+converter.testEnforceRangeLongLong = 0x7F
+PASS converter.testEnforceRangeLongLong is 0x7F
+converter.testEnforceRangeLongLong = 0x80
+PASS converter.testEnforceRangeLongLong is 0x80
+converter.testEnforceRangeLongLong = 0xFF
+PASS converter.testEnforceRangeLongLong is 0xFF
+converter.testEnforceRangeLongLong = -0x80
+PASS converter.testEnforceRangeLongLong is -0x80
+converter.testEnforceRangeLongLong = -0x81
+PASS converter.testEnforceRangeLongLong is -0x81
+converter.testEnforceRangeLongLong = 0x7FFF
+PASS converter.testEnforceRangeLongLong is 0x7FFF
+converter.testEnforceRangeLongLong = 0x8000
+PASS converter.testEnforceRangeLongLong is 0x8000
+converter.testEnforceRangeLongLong = 0xFFFF
+PASS converter.testEnforceRangeLongLong is 0xFFFF
+converter.testEnforceRangeLongLong = -0x8000
+PASS converter.testEnforceRangeLongLong is -0x8000
+converter.testEnforceRangeLongLong = -0x8001
+PASS converter.testEnforceRangeLongLong is -0x8001
+converter.testEnforceRangeLongLong = 0x7FFFFFFF
+PASS converter.testEnforceRangeLongLong is 0x7FFFFFFF
+converter.testEnforceRangeLongLong = 0x80000000
+PASS converter.testEnforceRangeLongLong is 0x80000000
+converter.testEnforceRangeLongLong = 0xFFFFFFFF
+PASS converter.testEnforceRangeLongLong is 0xFFFFFFFF
+converter.testEnforceRangeLongLong = -0x80000000
+PASS converter.testEnforceRangeLongLong is -0x80000000
+converter.testEnforceRangeLongLong = -0x80000001
+PASS converter.testEnforceRangeLongLong is -0x80000001
+FAIL converter.testEnforceRangeLongLong = 0xDCBA9876543210 should throw an exception. Was 62129658859368980.
+converter.testEnforceRangeLongLong = Number.MIN_VALUE
+PASS converter.testEnforceRangeLongLong is 0
+converter.testEnforceRangeLongLong = -Number.MIN_VALUE
+PASS converter.testEnforceRangeLongLong is 0
+FAIL converter.testEnforceRangeLongLong = Number.MAX_VALUE should throw an exception. Was 1.7976931348623157e+308.
+FAIL converter.testEnforceRangeLongLong = -Number.MAX_VALUE should throw an exception. Was -1.7976931348623157e+308.
+converter.testEnforceRangeLongLong = 1.99
+PASS converter.testEnforceRangeLongLong is 1
+converter.testEnforceRangeLongLong = -1.99
+PASS converter.testEnforceRangeLongLong is -1
+FAIL converter.testEnforceRangeLongLong = Infinity should throw an exception. Was Infinity.
+FAIL converter.testEnforceRangeLongLong = -Infinity should throw an exception. Was -Infinity.
+FAIL converter.testEnforceRangeLongLong = NaN should throw an exception. Was NaN.
+converter.testEnforceRangeLongLong = false
+PASS converter.testEnforceRangeLongLong is 0
+converter.testEnforceRangeLongLong = true
+PASS converter.testEnforceRangeLongLong is 1
+converter.testEnforceRangeLongLong = ''
+PASS converter.testEnforceRangeLongLong is 0
+converter.testEnforceRangeLongLong = '1'
+PASS converter.testEnforceRangeLongLong is 1
+FAIL converter.testEnforceRangeLongLong = 'abc' should throw an exception. Was abc.
+converter.testEnforceRangeLongLong = null
+PASS converter.testEnforceRangeLongLong is 0
+FAIL converter.testEnforceRangeLongLong = undefined should throw an exception. Was undefined.
+PASS converter.testEnforceRangeLongLong = {valueOf:function(){throw new Error('custom');}} threw exception Error: custom.
 
 PASS 'testUnsignedLongLong' in converter is true
 PASS typeof converter.testUnsignedLongLong === 'number' is true
@@ -255,23 +458,93 @@ converter.testUnsignedLongLong = Number.MIN_VALUE
 PASS converter.testUnsignedLongLong is 0
 converter.testUnsignedLongLong = -Number.MIN_VALUE
 PASS converter.testUnsignedLongLong is 0
+converter.testUnsignedLongLong = Number.MAX_VALUE
+PASS converter.testUnsignedLongLong is 0
+converter.testUnsignedLongLong = -Number.MAX_VALUE
+FAIL converter.testUnsignedLongLong should be 0. Was 9223372036854776000.
 converter.testUnsignedLongLong = 1.99
 PASS converter.testUnsignedLongLong is 1
 converter.testUnsignedLongLong = -1.99
 PASS converter.testUnsignedLongLong is 0xFFFFFFFFFFFFFFFF
+converter.testUnsignedLongLong = Infinity
+PASS converter.testUnsignedLongLong is 0
+converter.testUnsignedLongLong = -Infinity
+FAIL converter.testUnsignedLongLong should be 0. Was 9223372036854776000.
+converter.testUnsignedLongLong = NaN
+PASS converter.testUnsignedLongLong is 0
 converter.testUnsignedLongLong = false
 PASS converter.testUnsignedLongLong is 0
 converter.testUnsignedLongLong = true
 PASS converter.testUnsignedLongLong is 1
 converter.testUnsignedLongLong = ''
 PASS converter.testUnsignedLongLong is 0
+converter.testUnsignedLongLong = '1'
+PASS converter.testUnsignedLongLong is 1
 converter.testUnsignedLongLong = 'abc'
 PASS converter.testUnsignedLongLong is 0
 converter.testUnsignedLongLong = null
 PASS converter.testUnsignedLongLong is 0
 converter.testUnsignedLongLong = undefined
 PASS converter.testUnsignedLongLong is 0
-PASS converter.testUnsignedLongLong = {valueOf:function(){throw new Error;}} threw exception Error.
+PASS converter.testUnsignedLongLong = {valueOf:function(){throw new Error('custom');}} threw exception Error: custom.
+
+PASS 'testEnforceRangeUnsignedLongLong' in converter is true
+PASS typeof converter.testEnforceRangeUnsignedLongLong === 'number' is true
+converter.testEnforceRangeUnsignedLongLong = 0
+PASS converter.testEnforceRangeUnsignedLongLong is 0
+FAIL converter.testEnforceRangeUnsignedLongLong = -1 should throw an exception. Was -1.
+converter.testEnforceRangeUnsignedLongLong = 1
+PASS converter.testEnforceRangeUnsignedLongLong is 1
+converter.testEnforceRangeUnsignedLongLong = 0x7F
+PASS converter.testEnforceRangeUnsignedLongLong is 0x7F
+converter.testEnforceRangeUnsignedLongLong = 0x80
+PASS converter.testEnforceRangeUnsignedLongLong is 0x80
+converter.testEnforceRangeUnsignedLongLong = 0xFF
+PASS converter.testEnforceRangeUnsignedLongLong is 0xFF
+FAIL converter.testEnforceRangeUnsignedLongLong = -0x80 should throw an exception. Was -128.
+FAIL converter.testEnforceRangeUnsignedLongLong = -0x81 should throw an exception. Was -129.
+converter.testEnforceRangeUnsignedLongLong = 0x7FFF
+PASS converter.testEnforceRangeUnsignedLongLong is 0x7FFF
+converter.testEnforceRangeUnsignedLongLong = 0x8000
+PASS converter.testEnforceRangeUnsignedLongLong is 0x8000
+converter.testEnforceRangeUnsignedLongLong = 0xFFFF
+PASS converter.testEnforceRangeUnsignedLongLong is 0xFFFF
+FAIL converter.testEnforceRangeUnsignedLongLong = -0x8000 should throw an exception. Was -32768.
+FAIL converter.testEnforceRangeUnsignedLongLong = -0x8001 should throw an exception. Was -32769.
+converter.testEnforceRangeUnsignedLongLong = 0x7FFFFFFF
+PASS converter.testEnforceRangeUnsignedLongLong is 0x7FFFFFFF
+converter.testEnforceRangeUnsignedLongLong = 0x80000000
+PASS converter.testEnforceRangeUnsignedLongLong is 0x80000000
+converter.testEnforceRangeUnsignedLongLong = 0xFFFFFFFF
+PASS converter.testEnforceRangeUnsignedLongLong is 0xFFFFFFFF
+FAIL converter.testEnforceRangeUnsignedLongLong = -0x80000000 should throw an exception. Was -2147483648.
+FAIL converter.testEnforceRangeUnsignedLongLong = -0x80000001 should throw an exception. Was -2147483649.
+FAIL converter.testEnforceRangeUnsignedLongLong = 0xDCBA9876543210 should throw an exception. Was 62129658859368980.
+converter.testEnforceRangeUnsignedLongLong = Number.MIN_VALUE
+PASS converter.testEnforceRangeUnsignedLongLong is 0
+converter.testEnforceRangeUnsignedLongLong = -Number.MIN_VALUE
+PASS converter.testEnforceRangeUnsignedLongLong is 0
+FAIL converter.testEnforceRangeUnsignedLongLong = Number.MAX_VALUE should throw an exception. Was 1.7976931348623157e+308.
+FAIL converter.testEnforceRangeUnsignedLongLong = -Number.MAX_VALUE should throw an exception. Was -1.7976931348623157e+308.
+converter.testEnforceRangeUnsignedLongLong = 1.99
+PASS converter.testEnforceRangeUnsignedLongLong is 1
+FAIL converter.testEnforceRangeUnsignedLongLong = -1.99 should throw an exception. Was -1.99.
+FAIL converter.testEnforceRangeUnsignedLongLong = Infinity should throw an exception. Was Infinity.
+FAIL converter.testEnforceRangeUnsignedLongLong = -Infinity should throw an exception. Was -Infinity.
+FAIL converter.testEnforceRangeUnsignedLongLong = NaN should throw an exception. Was NaN.
+converter.testEnforceRangeUnsignedLongLong = false
+PASS converter.testEnforceRangeUnsignedLongLong is 0
+converter.testEnforceRangeUnsignedLongLong = true
+PASS converter.testEnforceRangeUnsignedLongLong is 1
+converter.testEnforceRangeUnsignedLongLong = ''
+PASS converter.testEnforceRangeUnsignedLongLong is 0
+converter.testEnforceRangeUnsignedLongLong = '1'
+PASS converter.testEnforceRangeUnsignedLongLong is 1
+FAIL converter.testEnforceRangeUnsignedLongLong = 'abc' should throw an exception. Was abc.
+converter.testEnforceRangeUnsignedLongLong = null
+PASS converter.testEnforceRangeUnsignedLongLong is 0
+FAIL converter.testEnforceRangeUnsignedLongLong = undefined should throw an exception. Was undefined.
+PASS converter.testEnforceRangeUnsignedLongLong = {valueOf:function(){throw new Error('custom');}} threw exception Error: custom.
 
 PASS successfullyParsed is true
 
index 21913be..d811e5c 100644 (file)
@@ -36,11 +36,23 @@ function testNonNumericToNumeric(attribute)
     convert(attribute, "false", "0");
     convert(attribute, "true", "1");
     convert(attribute, "''", "0");
+    convert(attribute, "'1'", "1");
     convert(attribute, "'abc'", "0");
     convert(attribute, "null", "0");
     convert(attribute, "undefined", "0");
 }
 
+function testNonNumericToNumericEnforceRange(attribute)
+{
+    convert(attribute, "false", "0");
+    convert(attribute, "true", "1");
+    convert(attribute, "''", "0");
+    convert(attribute, "'1'", "1");
+    convertThrows(attribute, "'abc'");
+    convert(attribute, "null", "0");
+    convertThrows(attribute, "undefined");
+}
+
 type = "testLong";
 verifyAttribute(type);
 convert(type, "0");
@@ -72,7 +84,41 @@ convert(type, "Infinity", "0");
 convert(type, "-Infinity", "0");
 convert(type, "NaN", "0");
 testNonNumericToNumeric(type);
-convertThrows(type, "{valueOf:function(){throw new Error;}}");
+convertThrows(type, "{valueOf:function(){throw new Error('custom');}}");
+debug("");
+
+type = "testEnforceRangeLong";
+verifyAttribute(type);
+convert(type, "0");
+convert(type, "-1");
+convert(type, "1");
+convert(type, "0x7F");
+convert(type, "0x80");
+convert(type, "0xFF");
+convert(type, "-0x80");
+convert(type, "-0x81");
+convert(type, "0x7FFF");
+convert(type, "0x8000");
+convert(type, "0xFFFF");
+convert(type, "-0x8000");
+convert(type, "-0x8001");
+convert(type, "0x7FFFFFFF");
+convertThrows(type, "0x80000000");
+convertThrows(type, "0xFFFFFFFF");
+convert(type, "-0x80000000");
+convertThrows(type, "-0x80000001");
+convertThrows(type, "0xDCBA9876543210");
+convertThrows(type, "Number.MAX_VALUE");
+convert(type, "Number.MIN_VALUE", "0");
+convertThrows(type, "-Number.MAX_VALUE");
+convert(type, "-Number.MIN_VALUE", "0");
+convert(type, "1.99", "1");
+convert(type, "-1.99", "-1");
+convertThrows(type, "Infinity");
+convertThrows(type, "-Infinity");
+convertThrows(type, "NaN");
+testNonNumericToNumericEnforceRange(type);
+convertThrows(type, "{valueOf:function(){throw new Error('custom');}}");
 debug("");
 
 type = "testUnsignedLong";
@@ -106,7 +152,41 @@ convert(type, "Infinity", "0");
 convert(type, "-Infinity", "0");
 convert(type, "NaN", "0");
 testNonNumericToNumeric(type);
-convertThrows(type, "{valueOf:function(){throw new Error;}}");
+convertThrows(type, "{valueOf:function(){throw new Error('custom');}}");
+debug("");
+
+type = "testEnforceRangeUnsignedLong";
+verifyAttribute(type);
+convert(type, "0");
+convertThrows(type, "-1");
+convert(type, "1");
+convert(type, "0x7F");
+convert(type, "0x80");
+convert(type, "0xFF");
+convertThrows(type, "-0x80");
+convertThrows(type, "-0x81");
+convert(type, "0x7FFF");
+convert(type, "0x8000");
+convert(type, "0xFFFF");
+convertThrows(type, "-0x8000");
+convertThrows(type, "-0x8001");
+convert(type, "0x7FFFFFFF");
+convert(type, "0x80000000");
+convert(type, "0xFFFFFFFF");
+convertThrows(type, "-0x80000000");
+convertThrows(type, "-0x80000001");
+convertThrows(type, "0xDCBA9876543210");
+convertThrows(type, "Number.MAX_VALUE");
+convert(type, "Number.MIN_VALUE", "0");
+convertThrows(type, "-Number.MAX_VALUE");
+convert(type, "-Number.MIN_VALUE", "0");
+convert(type, "1.99", "1");
+convertThrows(type, "-1.99");
+convertThrows(type, "Infinity");
+convertThrows(type, "-Infinity");
+convertThrows(type, "NaN");
+testNonNumericToNumericEnforceRange(type);
+convertThrows(type, "{valueOf:function(){throw new Error('custom');}}");
 debug("");
 
 type = "testLongLong";
@@ -132,17 +212,49 @@ convert(type, "-0x80000001");
 convert(type, "0xDCBA9876543210");
 convert(type, "Number.MIN_VALUE", "0");
 convert(type, "-Number.MIN_VALUE", "0");
-// FIXME: Inconsistent results between V8 and JSC.
-//convert(type, "Number.MAX_VALUE", "0");
-//convert(type, "-Number.MAX_VALUE", "0");
+convert(type, "Number.MAX_VALUE", "0");
+convert(type, "-Number.MAX_VALUE", "0");
 convert(type, "1.99", "1");
 convert(type, "-1.99", "-1");
-// FIXME: Inconsistent results between V8 and JSC.
-//convert(type, "Infinity", "0");
-//convert(type, "-Infinity", "0");
-//convert(type, "NaN", "0");
+convert(type, "Infinity", "0");
+convert(type, "-Infinity", "0");
+convert(type, "NaN", "0");
 testNonNumericToNumeric(type);
-convertThrows(type, "{valueOf:function(){throw new Error;}}");
+convertThrows(type, "{valueOf:function(){throw new Error('custom');}}");
+debug("");
+
+type = "testEnforceRangeLongLong";
+verifyAttribute(type);
+convert(type, "0");
+convert(type, "-1");
+convert(type, "1");
+convert(type, "0x7F");
+convert(type, "0x80");
+convert(type, "0xFF");
+convert(type, "-0x80");
+convert(type, "-0x81");
+convert(type, "0x7FFF");
+convert(type, "0x8000");
+convert(type, "0xFFFF");
+convert(type, "-0x8000");
+convert(type, "-0x8001");
+convert(type, "0x7FFFFFFF");
+convert(type, "0x80000000");
+convert(type, "0xFFFFFFFF");
+convert(type, "-0x80000000");
+convert(type, "-0x80000001");
+convertThrows(type, "0xDCBA9876543210");
+convert(type, "Number.MIN_VALUE", "0");
+convert(type, "-Number.MIN_VALUE", "0");
+convertThrows(type, "Number.MAX_VALUE");
+convertThrows(type, "-Number.MAX_VALUE");
+convert(type, "1.99", "1");
+convert(type, "-1.99", "-1");
+convertThrows(type, "Infinity");
+convertThrows(type, "-Infinity");
+convertThrows(type, "NaN", "0");
+testNonNumericToNumericEnforceRange(type);
+convertThrows(type, "{valueOf:function(){throw new Error('custom');}}");
 debug("");
 
 type = "testUnsignedLongLong";
@@ -168,17 +280,49 @@ convert(type, "-0x80000001", "0xFFFFFFFF7FFFFFFF");
 convert(type, "0xDCBA9876543210");
 convert(type, "Number.MIN_VALUE", "0");
 convert(type, "-Number.MIN_VALUE", "0");
-// FIXME: Inconsistent results between V8 and JSC.
-//convert(type, "Number.MAX_VALUE", "0");
-//convert(type, "-Number.MAX_VALUE", "0");
+convert(type, "Number.MAX_VALUE", "0");
+convert(type, "-Number.MAX_VALUE", "0");
 convert(type, "1.99", "1");
 convert(type, "-1.99", "0xFFFFFFFFFFFFFFFF");
-// FIXME: Inconsistent results between V8 and JSC.
-//convert(type, "Infinity", "0");
-//convert(type, "-Infinity", "0");
-//convert(type, "NaN", "0");
+convert(type, "Infinity", "0");
+convert(type, "-Infinity", "0");
+convert(type, "NaN", "0");
 testNonNumericToNumeric(type);
-convertThrows(type, "{valueOf:function(){throw new Error;}}");
+convertThrows(type, "{valueOf:function(){throw new Error('custom');}}");
+debug("");
+
+type = "testEnforceRangeUnsignedLongLong";
+verifyAttribute(type);
+convert(type, "0");
+convertThrows(type, "-1");
+convert(type, "1");
+convert(type, "0x7F");
+convert(type, "0x80");
+convert(type, "0xFF");
+convertThrows(type, "-0x80");
+convertThrows(type, "-0x81");
+convert(type, "0x7FFF");
+convert(type, "0x8000");
+convert(type, "0xFFFF");
+convertThrows(type, "-0x8000");
+convertThrows(type, "-0x8001");
+convert(type, "0x7FFFFFFF");
+convert(type, "0x80000000");
+convert(type, "0xFFFFFFFF");
+convertThrows(type, "-0x80000000");
+convertThrows(type, "-0x80000001");
+convertThrows(type, "0xDCBA9876543210");
+convert(type, "Number.MIN_VALUE", "0");
+convert(type, "-Number.MIN_VALUE", "0");
+convertThrows(type, "Number.MAX_VALUE");
+convertThrows(type, "-Number.MAX_VALUE");
+convert(type, "1.99", "1");
+convertThrows(type, "-1.99");
+convertThrows(type, "Infinity");
+convertThrows(type, "-Infinity");
+convertThrows(type, "NaN");
+testNonNumericToNumericEnforceRange(type);
+convertThrows(type, "{valueOf:function(){throw new Error('custom');}}");
 debug("");
 
 </script>
diff --git a/LayoutTests/platform/chromium/fast/dom/non-numeric-values-numeric-parameters-expected.txt b/LayoutTests/platform/chromium/fast/dom/non-numeric-values-numeric-parameters-expected.txt
new file mode 100644 (file)
index 0000000..01819fc
--- /dev/null
@@ -0,0 +1,85 @@
+This tests the behavior of non-numeric values in contexts where the DOM has a numeric parameter.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS nonNumericPolicy('document.createTextNode("a").substringData(x, 0)') is 'any type allowed'
+PASS nonNumericPolicy('document.createTextNode("a").substringData(0, x)') is 'any type allowed'
+PASS nonNumericPolicy('document.createTextNode("a").insertData(x, "b")') is 'any type allowed'
+PASS nonNumericPolicy('document.createTextNode("a").deleteData(x, 0)') is 'any type allowed'
+PASS nonNumericPolicy('document.createTextNode("a").deleteData(0, x)') is 'any type allowed'
+PASS nonNumericPolicy('document.createTextNode("a").replaceData(x, 0, "b")') is 'any type allowed'
+PASS nonNumericPolicy('document.createTextNode("a").replaceData(0, x, "b")') is 'any type allowed'
+PASS nonNumericPolicy('createCSSMediaRule().insertRule(ruleText, x)') is 'any type allowed'
+PASS nonNumericPolicy('createCSSMediaRule().deleteRule(x)') is 'any type allowed'
+PASS nonNumericPolicy('createCSSRuleList().item(x)') is 'any type allowed'
+PASS nonNumericPolicy('createCSSStyleDeclaration().item(x)') is 'any type allowed'
+PASS nonNumericPolicy('createCSSStyleSheet().insertRule(ruleText, x)') is 'any type allowed'
+PASS nonNumericPolicy('createCSSStyleSheet().deleteRule(x)') is 'any type allowed'
+PASS nonNumericPolicy('createCSSStyleSheet().addRule(selector, styleText, x)') is 'any type allowed'
+PASS nonNumericPolicy('createCSSStyleSheet().removeRule(x)') is 'any type allowed'
+PASS nonNumericPolicy('createCSSValueList().item(x)') is 'any type allowed'
+PASS nonNumericPolicy('document.elementFromPoint(x, 0)') is 'any type allowed'
+PASS nonNumericPolicy('document.elementFromPoint(0, x)') is 'any type allowed'
+PASS nonNumericPolicy('document.body.scrollByLines(x)') is 'any type allowed'
+PASS nonNumericPolicy('document.body.scrollByPages(x)') is 'any type allowed'
+PASS nonNumericPolicy('document.body.scrollLeft = x') is 'any type allowed'
+PASS nonNumericPolicy('document.body.scrollTop = x') is 'any type allowed'
+PASS nonNumericPolicy('document.images.item(x)') is 'any type allowed'
+PASS nonNumericPolicy('document.createElement("input").setSelectionRange(x, 0)') is 'any type allowed'
+PASS nonNumericPolicy('document.createElement("input").setSelectionRange(0, x)') is 'any type allowed'
+PASS nonNumericPolicy('createHTMLOptionsCollection().add(document.createElement("option"), x)') is 'any type allowed'
+PASS nonNumericPolicy('createHTMLOptionsCollection().remove(x)') is 'any type allowed'
+PASS nonNumericPolicy('createHTMLSelectElement().remove(x)') is 'any type allowed'
+PASS nonNumericPolicy('createHTMLSelectElement().item(x)') is 'any type allowed'
+PASS nonNumericPolicy('createHTMLTableElement().insertRow(x)') is 'any type allowed'
+PASS nonNumericPolicy('createHTMLTableElement().deleteRow(x)') is 'any type allowed'
+PASS nonNumericPolicy('createHTMLTableRowElement().insertCell(x)') is 'any type allowed'
+PASS nonNumericPolicy('createHTMLTableRowElement().deleteCell(x)') is 'any type allowed'
+PASS nonNumericPolicy('createHTMLTableSectionElement().insertRow(x)') is 'any type allowed'
+PASS nonNumericPolicy('createHTMLTableSectionElement().deleteRow(x)') is 'any type allowed'
+PASS nonNumericPolicy('document.createElement("textarea").setSelectionRange(x, 0)') is 'any type allowed'
+PASS nonNumericPolicy('document.createElement("textarea").setSelectionRange(0, x)') is 'any type allowed'
+PASS nonNumericPolicy('document.createEvent("KeyboardEvent").initKeyboardEvent("a", false, false, null, "b", x, false, false, false, false, false)') is 'any type allowed'
+PASS nonNumericPolicy('createMediaList().item(x)') is 'any type allowed'
+PASS nonNumericPolicy('document.createEvent("MouseEvent").initMouseEvent("a", false, false, null, x, 0, 0, 0, 0, false, false, false, false, 0, null)') is 'any type allowed'
+PASS nonNumericPolicy('document.createEvent("MouseEvent").initMouseEvent("a", false, false, null, 0, x, 0, 0, 0, false, false, false, false, 0, null)') is 'any type allowed'
+PASS nonNumericPolicy('document.createEvent("MouseEvent").initMouseEvent("a", false, false, null, 0, 0, x, 0, 0, false, false, false, false, 0, null)') is 'any type allowed'
+PASS nonNumericPolicy('document.createEvent("MouseEvent").initMouseEvent("a", false, false, null, 0, 0, 0, x, 0, false, false, false, false, 0, null)') is 'any type allowed'
+PASS nonNumericPolicy('document.createEvent("MouseEvent").initMouseEvent("a", false, false, null, 0, 0, 0, 0, x, false, false, false, false, 0, null)') is 'any type allowed'
+PASS nonNumericPolicy('document.createEvent("MouseEvent").initMouseEvent("a", false, false, null, 0, 0, 0, 0, 0, false, false, false, false, x, null)') is 'any type allowed'
+PASS nonNumericPolicy('document.body.attributes.item(x)') is 'any type allowed'
+PASS nonNumericPolicy('document.createNodeIterator(document, x, null, false)') is 'any type allowed'
+PASS nonNumericPolicy('document.getElementsByTagName("div").item(x)') is 'any type allowed'
+PASS nonNumericPolicy('document.createRange().setStart(document, x)') is 'any type allowed'
+PASS nonNumericPolicy('document.createRange().setEnd(document, x)') is 'any type allowed'
+PASS nonNumericPolicy('document.createRange().comparePoint(document, x)') is 'any type allowed'
+PASS nonNumericPolicy('document.createRange().isPointInRange(document, x)') is 'any type allowed'
+PASS nonNumericPolicy('getSelection().collapse(document, x)') is 'any type allowed'
+PASS nonNumericPolicy('getSelection().setBaseAndExtent(document, x, document, 0)') is 'any type allowed'
+PASS nonNumericPolicy('getSelection().setBaseAndExtent(document, 0, document, x)') is 'any type allowed'
+PASS nonNumericPolicy('getSelection().setPosition(document, x)') is 'any type allowed'
+PASS nonNumericPolicy('getSelection().extend(document, x)') is 'any type allowed'
+PASS nonNumericPolicy('getSelection().getRangeAt(x)') is 'any type allowed'
+PASS nonNumericPolicy('document.styleSheets.item(x)') is 'any type allowed'
+PASS nonNumericPolicy('document.createTextNode("a").splitText(x)') is 'any type allowed'
+PASS nonNumericPolicy('document.createTreeWalker(document, x, null, false)') is 'any type allowed'
+PASS nonNumericPolicy('document.createEvent("UIEvent").initUIEvent("a", false, false, null, x)') is 'any type allowed'
+PASS nonNumericPolicy('window.scrollBy(x, 0)') is 'any type allowed'
+PASS nonNumericPolicy('window.scrollBy(0, x)') is 'any type allowed'
+PASS nonNumericPolicy('window.scrollTo(x, 0)') is 'any type allowed'
+PASS nonNumericPolicy('window.scrollTo(0, x)') is 'any type allowed'
+PASS nonNumericPolicy('window.scroll(x, 0)') is 'any type allowed'
+PASS nonNumericPolicy('window.scroll(0, x)') is 'any type allowed'
+PASS nonNumericPolicy('window.moveBy(x, 0)') is 'any type allowed'
+PASS nonNumericPolicy('window.moveBy(0, x)') is 'any type allowed'
+PASS nonNumericPolicy('window.moveTo(x, 0)') is 'any type allowed'
+PASS nonNumericPolicy('window.moveTo(0, x)') is 'any type allowed'
+PASS nonNumericPolicy('window.resizeBy(x, 0)') is 'any type allowed'
+PASS nonNumericPolicy('window.resizeBy(0, x)') is 'any type allowed'
+PASS nonNumericPolicy('window.resizeTo(x, 0)') is 'any type allowed'
+PASS nonNumericPolicy('window.resizeTo(0, x)') is 'any type allowed'
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/platform/chromium/fast/js/select-options-add-expected.txt b/LayoutTests/platform/chromium/fast/js/select-options-add-expected.txt
new file mode 100644 (file)
index 0000000..86f1e26
--- /dev/null
@@ -0,0 +1,228 @@
+This test checks the behavior of the add() method on the select.options object.
+It covers both the the one-argument (1.x) and two-argument (2.x) signatures of the add() method.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+1.1 Add Option to empty Options
+PASS select1.options.length is 1
+PASS select1.selectedIndex is 0
+PASS select1.options[0].value is '1'
+PASS select1.options[0].textContent is 'A'
+
+1.2 Add Option to non-empty Options
+PASS select1.options.length is 2
+PASS select1.selectedIndex is 0
+PASS select1.options[0].value is '1'
+PASS select1.options[0].textContent is 'A'
+PASS select1.options[1].value is '2'
+PASS select1.options[1].textContent is 'B'
+
+1.3 Add Option after setting parameters
+PASS select1.options.length is 3
+PASS select1.selectedIndex is 0
+PASS select1.options[0].value is '1'
+PASS select1.options[0].textContent is 'A'
+PASS select1.options[1].value is '2'
+PASS select1.options[1].textContent is 'B'
+PASS select1.options[2].value is '3'
+PASS select1.options[2].textContent is 'C'
+
+1.4 Add a non-Option element
+PASS select1.options.add(option1) threw exception Error: TypeMismatchError: DOM Exception 17.
+PASS select1.options.length is 3
+PASS select1.selectedIndex is 0
+
+1.5 Add a non-element (string)
+PASS select1.options.add(option1) threw exception Error: TypeMismatchError: DOM Exception 17.
+PASS select1.options.length is 3
+PASS select1.selectedIndex is 0
+
+1.6 Add a non-element (number)
+PASS select1.options.add(option1) threw exception Error: TypeMismatchError: DOM Exception 17.
+PASS select1.options.length is 3
+PASS select1.selectedIndex is 0
+
+1.7 Add a non-element (boolean)
+PASS select1.options.add(option1) threw exception Error: TypeMismatchError: DOM Exception 17.
+PASS select1.options.length is 3
+PASS select1.selectedIndex is 0
+
+1.8 Add undefined
+PASS select1.options.add(option1) threw exception Error: TypeMismatchError: DOM Exception 17.
+PASS select1.options.length is 3
+PASS select1.selectedIndex is 0
+
+1.9 Add null
+PASS select1.options.add(option1) threw exception Error: TypeMismatchError: DOM Exception 17.
+PASS select1.options.length is 3
+PASS select1.selectedIndex is 0
+
+1.10 Add negative infinity
+PASS select1.options.add(option1) threw exception Error: TypeMismatchError: DOM Exception 17.
+PASS select1.options.length is 3
+PASS select1.selectedIndex is 0
+
+1.11 Add NaN
+PASS select1.options.add(option1) threw exception Error: TypeMismatchError: DOM Exception 17.
+PASS select1.options.length is 3
+PASS select1.selectedIndex is 0
+
+1.12 Add positive infinity
+PASS select1.options.add(option1) threw exception Error: TypeMismatchError: DOM Exception 17.
+PASS select1.options.length is 3
+PASS select1.selectedIndex is 0
+
+2.1 Add Option to empty Options
+PASS select2.options.length is 1
+PASS select2.selectedIndex is 0
+PASS select2.options[0].value is '1'
+PASS select2.options[0].textContent is 'A'
+
+2.2 Add Option after setting parameters
+PASS select2.options.length is 2
+PASS select2.selectedIndex is 0
+PASS select2.options[0].value is '1'
+PASS select2.options[0].textContent is 'A'
+PASS select2.options[1].value is '2'
+PASS select2.options[1].textContent is 'B'
+
+2.3 Insert Option at beginning of Options
+PASS select2.options.length is 3
+PASS select2.selectedIndex is 1
+PASS select2.options[0].value is '0'
+PASS select2.options[0].textContent is 'Z'
+PASS select2.options[1].value is '1'
+PASS select2.options[1].textContent is 'A'
+PASS select2.options[2].value is '2'
+PASS select2.options[2].textContent is 'B'
+
+2.4 Insert Option in middle of Options
+PASS select2.options.length is 4
+PASS select2.selectedIndex is 1
+PASS select2.options[0].value is '0'
+PASS select2.options[0].textContent is 'Z'
+PASS select2.options[1].value is '1'
+PASS select2.options[1].textContent is 'A'
+PASS select2.options[2].value is '1.5'
+PASS select2.options[2].textContent is 'A.5'
+PASS select2.options[3].value is '2'
+PASS select2.options[3].textContent is 'B'
+
+2.5 Insert Option at end of Options
+PASS select2.options.length is 5
+PASS select2.selectedIndex is 1
+PASS select2.options[0].value is '0'
+PASS select2.options[0].textContent is 'Z'
+PASS select2.options[1].value is '1'
+PASS select2.options[1].textContent is 'A'
+PASS select2.options[2].value is '1.5'
+PASS select2.options[2].textContent is 'A.5'
+PASS select2.options[3].value is '2'
+PASS select2.options[3].textContent is 'B'
+PASS select2.options[4].value is '3'
+PASS select2.options[4].textContent is 'C'
+
+2.6 Insert Option beyond the end of Options
+PASS select2.options.length is 6
+PASS select2.selectedIndex is 1
+PASS select2.options[0].value is '0'
+PASS select2.options[0].textContent is 'Z'
+PASS select2.options[1].value is '1'
+PASS select2.options[1].textContent is 'A'
+PASS select2.options[2].value is '1.5'
+PASS select2.options[2].textContent is 'A.5'
+PASS select2.options[3].value is '2'
+PASS select2.options[3].textContent is 'B'
+PASS select2.options[4].value is '3'
+PASS select2.options[4].textContent is 'C'
+PASS select2.options[5].value is '4'
+PASS select2.options[5].textContent is 'D'
+
+2.7 Add an Option at index -1
+PASS select2.options.length is 7
+PASS select2.selectedIndex is 1
+PASS select2.options[0].value is '0'
+PASS select2.options[0].textContent is 'Z'
+PASS select2.options[1].value is '1'
+PASS select2.options[1].textContent is 'A'
+PASS select2.options[2].value is '1.5'
+PASS select2.options[2].textContent is 'A.5'
+PASS select2.options[3].value is '2'
+PASS select2.options[3].textContent is 'B'
+PASS select2.options[4].value is '3'
+PASS select2.options[4].textContent is 'C'
+PASS select2.options[5].value is '4'
+PASS select2.options[5].textContent is 'D'
+PASS select2.options[6].value is '5'
+PASS select2.options[6].textContent is 'E'
+
+2.8 Add an Option at index -2
+PASS select2.options.add(option2, -2) threw exception Error: IndexSizeError: DOM Exception 1.
+PASS select2.options.length is 7
+PASS select2.selectedIndex is 1
+
+2.9 Add an Option at index -Infinity
+PASS select2.options.add(option2, -1/0) did not throw exception.
+PASS select2.options.length is 8
+PASS select2.selectedIndex is 2
+
+2.10 Add an Option at index NaN
+PASS select2.options.add(option2, 0/0) did not throw exception.
+PASS select2.options.length is 9
+PASS select2.selectedIndex is 3
+
+2.11 Add an Option at index Infinity
+PASS select2.options.add(option2, 1/0) did not throw exception.
+PASS select2.options.length is 10
+PASS select2.selectedIndex is 4
+
+2.12 Add a non-Option element
+PASS select2.options.add(option2, 1) threw exception Error: TypeMismatchError: DOM Exception 17.
+PASS select2.options.length is 10
+PASS select2.selectedIndex is 4
+
+2.13 Add a non-element (string)
+PASS select2.options.add(option2, 1) threw exception Error: TypeMismatchError: DOM Exception 17.
+PASS select2.options.length is 10
+PASS select2.selectedIndex is 4
+
+2.14 Add a non-element (number)
+PASS select2.options.add(option2, 1) threw exception Error: TypeMismatchError: DOM Exception 17.
+PASS select2.options.length is 10
+PASS select2.selectedIndex is 4
+
+2.15 Add a non-element (boolean)
+PASS select2.options.add(option2, 1) threw exception Error: TypeMismatchError: DOM Exception 17.
+PASS select2.options.length is 10
+PASS select2.selectedIndex is 4
+
+2.16 Add undefined
+PASS select2.options.add(option2, 1) threw exception Error: TypeMismatchError: DOM Exception 17.
+PASS select2.options.length is 10
+PASS select2.selectedIndex is 4
+
+2.17 Add null
+PASS select2.options.add(option2, 1) threw exception Error: TypeMismatchError: DOM Exception 17.
+PASS select2.options.length is 10
+PASS select2.selectedIndex is 4
+
+2.18 Add negative infinity
+PASS select2.options.add(option2, 1) threw exception Error: TypeMismatchError: DOM Exception 17.
+PASS select2.options.length is 10
+PASS select2.selectedIndex is 4
+
+2.19 Add NaN
+PASS select2.options.add(option2, 1) threw exception Error: TypeMismatchError: DOM Exception 17.
+PASS select2.options.length is 10
+PASS select2.selectedIndex is 4
+
+2.20 Add positive infinity
+PASS select2.options.add(option2, 1) threw exception Error: TypeMismatchError: DOM Exception 17.
+PASS select2.options.length is 10
+PASS select2.selectedIndex is 4
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/platform/chromium/fast/js/webidl-type-mapping-expected.txt b/LayoutTests/platform/chromium/fast/js/webidl-type-mapping-expected.txt
new file mode 100644 (file)
index 0000000..aec0ac1
--- /dev/null
@@ -0,0 +1,552 @@
+Exercise WebIDL type conversions.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+converter = window.internals.typeConversions()
+
+PASS 'testLong' in converter is true
+PASS typeof converter.testLong === 'number' is true
+converter.testLong = 0
+PASS converter.testLong is 0
+converter.testLong = -1
+PASS converter.testLong is -1
+converter.testLong = 1
+PASS converter.testLong is 1
+converter.testLong = 0x7F
+PASS converter.testLong is 0x7F
+converter.testLong = 0x80
+PASS converter.testLong is 0x80
+converter.testLong = 0xFF
+PASS converter.testLong is 0xFF
+converter.testLong = -0x80
+PASS converter.testLong is -0x80
+converter.testLong = -0x81
+PASS converter.testLong is -0x81
+converter.testLong = 0x7FFF
+PASS converter.testLong is 0x7FFF
+converter.testLong = 0x8000
+PASS converter.testLong is 0x8000
+converter.testLong = 0xFFFF
+PASS converter.testLong is 0xFFFF
+converter.testLong = -0x8000
+PASS converter.testLong is -0x8000
+converter.testLong = -0x8001
+PASS converter.testLong is -0x8001
+converter.testLong = 0x7FFFFFFF
+PASS converter.testLong is 0x7FFFFFFF
+converter.testLong = 0x80000000
+PASS converter.testLong is -0x80000000
+converter.testLong = 0xFFFFFFFF
+PASS converter.testLong is -1
+converter.testLong = -0x80000000
+PASS converter.testLong is -0x80000000
+converter.testLong = -0x80000001
+PASS converter.testLong is 0x7FFFFFFF
+converter.testLong = 0xDCBA9876543210
+PASS converter.testLong is 0x76543210
+converter.testLong = Number.MAX_VALUE
+PASS converter.testLong is 0
+converter.testLong = Number.MIN_VALUE
+PASS converter.testLong is 0
+converter.testLong = -Number.MAX_VALUE
+PASS converter.testLong is 0
+converter.testLong = -Number.MIN_VALUE
+PASS converter.testLong is 0
+converter.testLong = 1.99
+PASS converter.testLong is 1
+converter.testLong = -1.99
+PASS converter.testLong is -1
+converter.testLong = Infinity
+PASS converter.testLong is 0
+converter.testLong = -Infinity
+PASS converter.testLong is 0
+converter.testLong = NaN
+PASS converter.testLong is 0
+converter.testLong = false
+PASS converter.testLong is 0
+converter.testLong = true
+PASS converter.testLong is 1
+converter.testLong = ''
+PASS converter.testLong is 0
+converter.testLong = '1'
+PASS converter.testLong is 1
+converter.testLong = 'abc'
+PASS converter.testLong is 0
+converter.testLong = null
+PASS converter.testLong is 0
+converter.testLong = undefined
+PASS converter.testLong is 0
+PASS converter.testLong = {valueOf:function(){throw new Error('custom');}} threw exception Error: custom.
+
+PASS 'testEnforceRangeLong' in converter is true
+PASS typeof converter.testEnforceRangeLong === 'number' is true
+converter.testEnforceRangeLong = 0
+PASS converter.testEnforceRangeLong is 0
+converter.testEnforceRangeLong = -1
+PASS converter.testEnforceRangeLong is -1
+converter.testEnforceRangeLong = 1
+PASS converter.testEnforceRangeLong is 1
+converter.testEnforceRangeLong = 0x7F
+PASS converter.testEnforceRangeLong is 0x7F
+converter.testEnforceRangeLong = 0x80
+PASS converter.testEnforceRangeLong is 0x80
+converter.testEnforceRangeLong = 0xFF
+PASS converter.testEnforceRangeLong is 0xFF
+converter.testEnforceRangeLong = -0x80
+PASS converter.testEnforceRangeLong is -0x80
+converter.testEnforceRangeLong = -0x81
+PASS converter.testEnforceRangeLong is -0x81
+converter.testEnforceRangeLong = 0x7FFF
+PASS converter.testEnforceRangeLong is 0x7FFF
+converter.testEnforceRangeLong = 0x8000
+PASS converter.testEnforceRangeLong is 0x8000
+converter.testEnforceRangeLong = 0xFFFF
+PASS converter.testEnforceRangeLong is 0xFFFF
+converter.testEnforceRangeLong = -0x8000
+PASS converter.testEnforceRangeLong is -0x8000
+converter.testEnforceRangeLong = -0x8001
+PASS converter.testEnforceRangeLong is -0x8001
+converter.testEnforceRangeLong = 0x7FFFFFFF
+PASS converter.testEnforceRangeLong is 0x7FFFFFFF
+PASS converter.testEnforceRangeLong = 0x80000000 threw exception TypeError: Type error.
+PASS converter.testEnforceRangeLong = 0xFFFFFFFF threw exception TypeError: Type error.
+converter.testEnforceRangeLong = -0x80000000
+PASS converter.testEnforceRangeLong is -0x80000000
+PASS converter.testEnforceRangeLong = -0x80000001 threw exception TypeError: Type error.
+PASS converter.testEnforceRangeLong = 0xDCBA9876543210 threw exception TypeError: Type error.
+PASS converter.testEnforceRangeLong = Number.MAX_VALUE threw exception TypeError: Type error.
+converter.testEnforceRangeLong = Number.MIN_VALUE
+PASS converter.testEnforceRangeLong is 0
+PASS converter.testEnforceRangeLong = -Number.MAX_VALUE threw exception TypeError: Type error.
+converter.testEnforceRangeLong = -Number.MIN_VALUE
+PASS converter.testEnforceRangeLong is 0
+converter.testEnforceRangeLong = 1.99
+PASS converter.testEnforceRangeLong is 1
+converter.testEnforceRangeLong = -1.99
+PASS converter.testEnforceRangeLong is -1
+PASS converter.testEnforceRangeLong = Infinity threw exception TypeError: Type error.
+PASS converter.testEnforceRangeLong = -Infinity threw exception TypeError: Type error.
+PASS converter.testEnforceRangeLong = NaN threw exception TypeError: Type error.
+converter.testEnforceRangeLong = false
+PASS converter.testEnforceRangeLong is 0
+converter.testEnforceRangeLong = true
+PASS converter.testEnforceRangeLong is 1
+converter.testEnforceRangeLong = ''
+PASS converter.testEnforceRangeLong is 0
+converter.testEnforceRangeLong = '1'
+PASS converter.testEnforceRangeLong is 1
+PASS converter.testEnforceRangeLong = 'abc' threw exception TypeError: Type error.
+converter.testEnforceRangeLong = null
+PASS converter.testEnforceRangeLong is 0
+PASS converter.testEnforceRangeLong = undefined threw exception TypeError: Type error.
+PASS converter.testEnforceRangeLong = {valueOf:function(){throw new Error('custom');}} threw exception Error: custom.
+
+PASS 'testUnsignedLong' in converter is true
+PASS typeof converter.testUnsignedLong === 'number' is true
+converter.testUnsignedLong = 0
+PASS converter.testUnsignedLong is 0
+converter.testUnsignedLong = -1
+PASS converter.testUnsignedLong is 0xFFFFFFFF
+converter.testUnsignedLong = 1
+PASS converter.testUnsignedLong is 1
+converter.testUnsignedLong = 0x7F
+PASS converter.testUnsignedLong is 0x7F
+converter.testUnsignedLong = 0x80
+PASS converter.testUnsignedLong is 0x80
+converter.testUnsignedLong = 0xFF
+PASS converter.testUnsignedLong is 0xFF
+converter.testUnsignedLong = -0x80
+PASS converter.testUnsignedLong is 0xFFFFFF80
+converter.testUnsignedLong = -0x81
+PASS converter.testUnsignedLong is 0xFFFFFF7F
+converter.testUnsignedLong = 0x7FFF
+PASS converter.testUnsignedLong is 0x7FFF
+converter.testUnsignedLong = 0x8000
+PASS converter.testUnsignedLong is 0x8000
+converter.testUnsignedLong = 0xFFFF
+PASS converter.testUnsignedLong is 0xFFFF
+converter.testUnsignedLong = -0x8000
+PASS converter.testUnsignedLong is 0xFFFF8000
+converter.testUnsignedLong = -0x8001
+PASS converter.testUnsignedLong is 0xFFFF7FFF
+converter.testUnsignedLong = 0x7FFFFFFF
+PASS converter.testUnsignedLong is 0x7FFFFFFF
+converter.testUnsignedLong = 0x80000000
+PASS converter.testUnsignedLong is 0x80000000
+converter.testUnsignedLong = 0xFFFFFFFF
+PASS converter.testUnsignedLong is 0xFFFFFFFF
+converter.testUnsignedLong = -0x80000000
+PASS converter.testUnsignedLong is 0x80000000
+converter.testUnsignedLong = -0x80000001
+PASS converter.testUnsignedLong is 0x7FFFFFFF
+converter.testUnsignedLong = 0xDCBA9876543210
+PASS converter.testUnsignedLong is 0x76543210
+converter.testUnsignedLong = Number.MAX_VALUE
+PASS converter.testUnsignedLong is 0
+converter.testUnsignedLong = Number.MIN_VALUE
+PASS converter.testUnsignedLong is 0
+converter.testUnsignedLong = -Number.MAX_VALUE
+PASS converter.testUnsignedLong is 0
+converter.testUnsignedLong = -Number.MIN_VALUE
+PASS converter.testUnsignedLong is 0
+converter.testUnsignedLong = 1.99
+PASS converter.testUnsignedLong is 1
+converter.testUnsignedLong = -1.99
+PASS converter.testUnsignedLong is 0xFFFFFFFF
+converter.testUnsignedLong = Infinity
+PASS converter.testUnsignedLong is 0
+converter.testUnsignedLong = -Infinity
+PASS converter.testUnsignedLong is 0
+converter.testUnsignedLong = NaN
+PASS converter.testUnsignedLong is 0
+converter.testUnsignedLong = false
+PASS converter.testUnsignedLong is 0
+converter.testUnsignedLong = true
+PASS converter.testUnsignedLong is 1
+converter.testUnsignedLong = ''
+PASS converter.testUnsignedLong is 0
+converter.testUnsignedLong = '1'
+PASS converter.testUnsignedLong is 1
+converter.testUnsignedLong = 'abc'
+PASS converter.testUnsignedLong is 0
+converter.testUnsignedLong = null
+PASS converter.testUnsignedLong is 0
+converter.testUnsignedLong = undefined
+PASS converter.testUnsignedLong is 0
+PASS converter.testUnsignedLong = {valueOf:function(){throw new Error('custom');}} threw exception Error: custom.
+
+PASS 'testEnforceRangeUnsignedLong' in converter is true
+PASS typeof converter.testEnforceRangeUnsignedLong === 'number' is true
+converter.testEnforceRangeUnsignedLong = 0
+PASS converter.testEnforceRangeUnsignedLong is 0
+PASS converter.testEnforceRangeUnsignedLong = -1 threw exception TypeError: Type error.
+converter.testEnforceRangeUnsignedLong = 1
+PASS converter.testEnforceRangeUnsignedLong is 1
+converter.testEnforceRangeUnsignedLong = 0x7F
+PASS converter.testEnforceRangeUnsignedLong is 0x7F
+converter.testEnforceRangeUnsignedLong = 0x80
+PASS converter.testEnforceRangeUnsignedLong is 0x80
+converter.testEnforceRangeUnsignedLong = 0xFF
+PASS converter.testEnforceRangeUnsignedLong is 0xFF
+PASS converter.testEnforceRangeUnsignedLong = -0x80 threw exception TypeError: Type error.
+PASS converter.testEnforceRangeUnsignedLong = -0x81 threw exception TypeError: Type error.
+converter.testEnforceRangeUnsignedLong = 0x7FFF
+PASS converter.testEnforceRangeUnsignedLong is 0x7FFF
+converter.testEnforceRangeUnsignedLong = 0x8000
+PASS converter.testEnforceRangeUnsignedLong is 0x8000
+converter.testEnforceRangeUnsignedLong = 0xFFFF
+PASS converter.testEnforceRangeUnsignedLong is 0xFFFF
+PASS converter.testEnforceRangeUnsignedLong = -0x8000 threw exception TypeError: Type error.
+PASS converter.testEnforceRangeUnsignedLong = -0x8001 threw exception TypeError: Type error.
+converter.testEnforceRangeUnsignedLong = 0x7FFFFFFF
+PASS converter.testEnforceRangeUnsignedLong is 0x7FFFFFFF
+converter.testEnforceRangeUnsignedLong = 0x80000000
+PASS converter.testEnforceRangeUnsignedLong is 0x80000000
+converter.testEnforceRangeUnsignedLong = 0xFFFFFFFF
+PASS converter.testEnforceRangeUnsignedLong is 0xFFFFFFFF
+PASS converter.testEnforceRangeUnsignedLong = -0x80000000 threw exception TypeError: Type error.
+PASS converter.testEnforceRangeUnsignedLong = -0x80000001 threw exception TypeError: Type error.
+PASS converter.testEnforceRangeUnsignedLong = 0xDCBA9876543210 threw exception TypeError: Type error.
+PASS converter.testEnforceRangeUnsignedLong = Number.MAX_VALUE threw exception TypeError: Type error.
+converter.testEnforceRangeUnsignedLong = Number.MIN_VALUE
+PASS converter.testEnforceRangeUnsignedLong is 0
+PASS converter.testEnforceRangeUnsignedLong = -Number.MAX_VALUE threw exception TypeError: Type error.
+converter.testEnforceRangeUnsignedLong = -Number.MIN_VALUE
+PASS converter.testEnforceRangeUnsignedLong is 0
+converter.testEnforceRangeUnsignedLong = 1.99
+PASS converter.testEnforceRangeUnsignedLong is 1
+PASS converter.testEnforceRangeUnsignedLong = -1.99 threw exception TypeError: Type error.
+PASS converter.testEnforceRangeUnsignedLong = Infinity threw exception TypeError: Type error.
+PASS converter.testEnforceRangeUnsignedLong = -Infinity threw exception TypeError: Type error.
+PASS converter.testEnforceRangeUnsignedLong = NaN threw exception TypeError: Type error.
+converter.testEnforceRangeUnsignedLong = false
+PASS converter.testEnforceRangeUnsignedLong is 0
+converter.testEnforceRangeUnsignedLong = true
+PASS converter.testEnforceRangeUnsignedLong is 1
+converter.testEnforceRangeUnsignedLong = ''
+PASS converter.testEnforceRangeUnsignedLong is 0
+converter.testEnforceRangeUnsignedLong = '1'
+PASS converter.testEnforceRangeUnsignedLong is 1
+PASS converter.testEnforceRangeUnsignedLong = 'abc' threw exception TypeError: Type error.
+converter.testEnforceRangeUnsignedLong = null
+PASS converter.testEnforceRangeUnsignedLong is 0
+PASS converter.testEnforceRangeUnsignedLong = undefined threw exception TypeError: Type error.
+PASS converter.testEnforceRangeUnsignedLong = {valueOf:function(){throw new Error('custom');}} threw exception Error: custom.
+
+PASS 'testLongLong' in converter is true
+PASS typeof converter.testLongLong === 'number' is true
+converter.testLongLong = 0
+PASS converter.testLongLong is 0
+converter.testLongLong = -1
+PASS converter.testLongLong is -1
+converter.testLongLong = 1
+PASS converter.testLongLong is 1
+converter.testLongLong = 0x7F
+PASS converter.testLongLong is 0x7F
+converter.testLongLong = 0x80
+PASS converter.testLongLong is 0x80
+converter.testLongLong = 0xFF
+PASS converter.testLongLong is 0xFF
+converter.testLongLong = -0x80
+PASS converter.testLongLong is -0x80
+converter.testLongLong = -0x81
+PASS converter.testLongLong is -0x81
+converter.testLongLong = 0x7FFF
+PASS converter.testLongLong is 0x7FFF
+converter.testLongLong = 0x8000
+PASS converter.testLongLong is 0x8000
+converter.testLongLong = 0xFFFF
+PASS converter.testLongLong is 0xFFFF
+converter.testLongLong = -0x8000
+PASS converter.testLongLong is -0x8000
+converter.testLongLong = -0x8001
+PASS converter.testLongLong is -0x8001
+converter.testLongLong = 0x7FFFFFFF
+PASS converter.testLongLong is 0x7FFFFFFF
+converter.testLongLong = 0x80000000
+PASS converter.testLongLong is 0x80000000
+converter.testLongLong = 0xFFFFFFFF
+PASS converter.testLongLong is 0xFFFFFFFF
+converter.testLongLong = -0x80000000
+PASS converter.testLongLong is -0x80000000
+converter.testLongLong = -0x80000001
+PASS converter.testLongLong is -0x80000001
+converter.testLongLong = 0xDCBA9876543210
+PASS converter.testLongLong is 0xDCBA9876543210
+converter.testLongLong = Number.MIN_VALUE
+PASS converter.testLongLong is 0
+converter.testLongLong = -Number.MIN_VALUE
+PASS converter.testLongLong is 0
+converter.testLongLong = Number.MAX_VALUE
+PASS converter.testLongLong is 0
+converter.testLongLong = -Number.MAX_VALUE
+PASS converter.testLongLong is 0
+converter.testLongLong = 1.99
+PASS converter.testLongLong is 1
+converter.testLongLong = -1.99
+PASS converter.testLongLong is -1
+converter.testLongLong = Infinity
+PASS converter.testLongLong is 0
+converter.testLongLong = -Infinity
+PASS converter.testLongLong is 0
+converter.testLongLong = NaN
+PASS converter.testLongLong is 0
+converter.testLongLong = false
+PASS converter.testLongLong is 0
+converter.testLongLong = true
+PASS converter.testLongLong is 1
+converter.testLongLong = ''
+PASS converter.testLongLong is 0
+converter.testLongLong = '1'
+PASS converter.testLongLong is 1
+converter.testLongLong = 'abc'
+PASS converter.testLongLong is 0
+converter.testLongLong = null
+PASS converter.testLongLong is 0
+converter.testLongLong = undefined
+PASS converter.testLongLong is 0
+PASS converter.testLongLong = {valueOf:function(){throw new Error('custom');}} threw exception Error: custom.
+
+PASS 'testEnforceRangeLongLong' in converter is true
+PASS typeof converter.testEnforceRangeLongLong === 'number' is true
+converter.testEnforceRangeLongLong = 0
+PASS converter.testEnforceRangeLongLong is 0
+converter.testEnforceRangeLongLong = -1
+PASS converter.testEnforceRangeLongLong is -1
+converter.testEnforceRangeLongLong = 1
+PASS converter.testEnforceRangeLongLong is 1
+converter.testEnforceRangeLongLong = 0x7F
+PASS converter.testEnforceRangeLongLong is 0x7F
+converter.testEnforceRangeLongLong = 0x80
+PASS converter.testEnforceRangeLongLong is 0x80
+converter.testEnforceRangeLongLong = 0xFF
+PASS converter.testEnforceRangeLongLong is 0xFF
+converter.testEnforceRangeLongLong = -0x80
+PASS converter.testEnforceRangeLongLong is -0x80
+converter.testEnforceRangeLongLong = -0x81
+PASS converter.testEnforceRangeLongLong is -0x81
+converter.testEnforceRangeLongLong = 0x7FFF
+PASS converter.testEnforceRangeLongLong is 0x7FFF
+converter.testEnforceRangeLongLong = 0x8000
+PASS converter.testEnforceRangeLongLong is 0x8000
+converter.testEnforceRangeLongLong = 0xFFFF
+PASS converter.testEnforceRangeLongLong is 0xFFFF
+converter.testEnforceRangeLongLong = -0x8000
+PASS converter.testEnforceRangeLongLong is -0x8000
+converter.testEnforceRangeLongLong = -0x8001
+PASS converter.testEnforceRangeLongLong is -0x8001
+converter.testEnforceRangeLongLong = 0x7FFFFFFF
+PASS converter.testEnforceRangeLongLong is 0x7FFFFFFF
+converter.testEnforceRangeLongLong = 0x80000000
+PASS converter.testEnforceRangeLongLong is 0x80000000
+converter.testEnforceRangeLongLong = 0xFFFFFFFF
+PASS converter.testEnforceRangeLongLong is 0xFFFFFFFF
+converter.testEnforceRangeLongLong = -0x80000000
+PASS converter.testEnforceRangeLongLong is -0x80000000
+converter.testEnforceRangeLongLong = -0x80000001
+PASS converter.testEnforceRangeLongLong is -0x80000001
+PASS converter.testEnforceRangeLongLong = 0xDCBA9876543210 threw exception TypeError: Type error.
+converter.testEnforceRangeLongLong = Number.MIN_VALUE
+PASS converter.testEnforceRangeLongLong is 0
+converter.testEnforceRangeLongLong = -Number.MIN_VALUE
+PASS converter.testEnforceRangeLongLong is 0
+PASS converter.testEnforceRangeLongLong = Number.MAX_VALUE threw exception TypeError: Type error.
+PASS converter.testEnforceRangeLongLong = -Number.MAX_VALUE threw exception TypeError: Type error.
+converter.testEnforceRangeLongLong = 1.99
+PASS converter.testEnforceRangeLongLong is 1
+converter.testEnforceRangeLongLong = -1.99
+PASS converter.testEnforceRangeLongLong is -1
+PASS converter.testEnforceRangeLongLong = Infinity threw exception TypeError: Type error.
+PASS converter.testEnforceRangeLongLong = -Infinity threw exception TypeError: Type error.
+PASS converter.testEnforceRangeLongLong = NaN threw exception TypeError: Type error.
+converter.testEnforceRangeLongLong = false
+PASS converter.testEnforceRangeLongLong is 0
+converter.testEnforceRangeLongLong = true
+PASS converter.testEnforceRangeLongLong is 1
+converter.testEnforceRangeLongLong = ''
+PASS converter.testEnforceRangeLongLong is 0
+converter.testEnforceRangeLongLong = '1'
+PASS converter.testEnforceRangeLongLong is 1
+PASS converter.testEnforceRangeLongLong = 'abc' threw exception TypeError: Type error.
+converter.testEnforceRangeLongLong = null
+PASS converter.testEnforceRangeLongLong is 0
+PASS converter.testEnforceRangeLongLong = undefined threw exception TypeError: Type error.
+PASS converter.testEnforceRangeLongLong = {valueOf:function(){throw new Error('custom');}} threw exception Error: custom.
+
+PASS 'testUnsignedLongLong' in converter is true
+PASS typeof converter.testUnsignedLongLong === 'number' is true
+converter.testUnsignedLongLong = 0
+PASS converter.testUnsignedLongLong is 0
+converter.testUnsignedLongLong = -1
+PASS converter.testUnsignedLongLong is 0xFFFFFFFFFFFFFFFF
+converter.testUnsignedLongLong = 1
+PASS converter.testUnsignedLongLong is 1
+converter.testUnsignedLongLong = 0x7F
+PASS converter.testUnsignedLongLong is 0x7F
+converter.testUnsignedLongLong = 0x80
+PASS converter.testUnsignedLongLong is 0x80
+converter.testUnsignedLongLong = 0xFF
+PASS converter.testUnsignedLongLong is 0xFF
+converter.testUnsignedLongLong = -0x80
+PASS converter.testUnsignedLongLong is 0xFFFFFFFFFFFFFF80
+converter.testUnsignedLongLong = -0x81
+PASS converter.testUnsignedLongLong is 0xFFFFFFFFFFFFFF7F
+converter.testUnsignedLongLong = 0x7FFF
+PASS converter.testUnsignedLongLong is 0x7FFF
+converter.testUnsignedLongLong = 0x8000
+PASS converter.testUnsignedLongLong is 0x8000
+converter.testUnsignedLongLong = 0xFFFF
+PASS converter.testUnsignedLongLong is 0xFFFF
+converter.testUnsignedLongLong = -0x8000
+PASS converter.testUnsignedLongLong is 0xFFFFFFFFFFFF8000
+converter.testUnsignedLongLong = -0x8001
+PASS converter.testUnsignedLongLong is 0xFFFFFFFFFFFF7FFF
+converter.testUnsignedLongLong = 0x7FFFFFFF
+PASS converter.testUnsignedLongLong is 0x7FFFFFFF
+converter.testUnsignedLongLong = 0x80000000
+PASS converter.testUnsignedLongLong is 0x80000000
+converter.testUnsignedLongLong = 0xFFFFFFFF
+PASS converter.testUnsignedLongLong is 0xFFFFFFFF
+converter.testUnsignedLongLong = -0x80000000
+PASS converter.testUnsignedLongLong is 0xFFFFFFFF80000000
+converter.testUnsignedLongLong = -0x80000001
+PASS converter.testUnsignedLongLong is 0xFFFFFFFF7FFFFFFF
+converter.testUnsignedLongLong = 0xDCBA9876543210
+PASS converter.testUnsignedLongLong is 0xDCBA9876543210
+converter.testUnsignedLongLong = Number.MIN_VALUE
+PASS converter.testUnsignedLongLong is 0
+converter.testUnsignedLongLong = -Number.MIN_VALUE
+PASS converter.testUnsignedLongLong is 0
+converter.testUnsignedLongLong = Number.MAX_VALUE
+PASS converter.testUnsignedLongLong is 0
+converter.testUnsignedLongLong = -Number.MAX_VALUE
+PASS converter.testUnsignedLongLong is 0
+converter.testUnsignedLongLong = 1.99
+PASS converter.testUnsignedLongLong is 1
+converter.testUnsignedLongLong = -1.99
+PASS converter.testUnsignedLongLong is 0xFFFFFFFFFFFFFFFF
+converter.testUnsignedLongLong = Infinity
+PASS converter.testUnsignedLongLong is 0
+converter.testUnsignedLongLong = -Infinity
+PASS converter.testUnsignedLongLong is 0
+converter.testUnsignedLongLong = NaN
+PASS converter.testUnsignedLongLong is 0
+converter.testUnsignedLongLong = false
+PASS converter.testUnsignedLongLong is 0
+converter.testUnsignedLongLong = true
+PASS converter.testUnsignedLongLong is 1
+converter.testUnsignedLongLong = ''
+PASS converter.testUnsignedLongLong is 0
+converter.testUnsignedLongLong = '1'
+PASS converter.testUnsignedLongLong is 1
+converter.testUnsignedLongLong = 'abc'
+PASS converter.testUnsignedLongLong is 0
+converter.testUnsignedLongLong = null
+PASS converter.testUnsignedLongLong is 0
+converter.testUnsignedLongLong = undefined
+PASS converter.testUnsignedLongLong is 0
+PASS converter.testUnsignedLongLong = {valueOf:function(){throw new Error('custom');}} threw exception Error: custom.
+
+PASS 'testEnforceRangeUnsignedLongLong' in converter is true
+PASS typeof converter.testEnforceRangeUnsignedLongLong === 'number' is true
+converter.testEnforceRangeUnsignedLongLong = 0
+PASS converter.testEnforceRangeUnsignedLongLong is 0
+PASS converter.testEnforceRangeUnsignedLongLong = -1 threw exception TypeError: Type error.
+converter.testEnforceRangeUnsignedLongLong = 1
+PASS converter.testEnforceRangeUnsignedLongLong is 1
+converter.testEnforceRangeUnsignedLongLong = 0x7F
+PASS converter.testEnforceRangeUnsignedLongLong is 0x7F
+converter.testEnforceRangeUnsignedLongLong = 0x80
+PASS converter.testEnforceRangeUnsignedLongLong is 0x80
+converter.testEnforceRangeUnsignedLongLong = 0xFF
+PASS converter.testEnforceRangeUnsignedLongLong is 0xFF
+PASS converter.testEnforceRangeUnsignedLongLong = -0x80 threw exception TypeError: Type error.
+PASS converter.testEnforceRangeUnsignedLongLong = -0x81 threw exception TypeError: Type error.
+converter.testEnforceRangeUnsignedLongLong = 0x7FFF
+PASS converter.testEnforceRangeUnsignedLongLong is 0x7FFF
+converter.testEnforceRangeUnsignedLongLong = 0x8000
+PASS converter.testEnforceRangeUnsignedLongLong is 0x8000
+converter.testEnforceRangeUnsignedLongLong = 0xFFFF
+PASS converter.testEnforceRangeUnsignedLongLong is 0xFFFF
+PASS converter.testEnforceRangeUnsignedLongLong = -0x8000 threw exception TypeError: Type error.
+PASS converter.testEnforceRangeUnsignedLongLong = -0x8001 threw exception TypeError: Type error.
+converter.testEnforceRangeUnsignedLongLong = 0x7FFFFFFF
+PASS converter.testEnforceRangeUnsignedLongLong is 0x7FFFFFFF
+converter.testEnforceRangeUnsignedLongLong = 0x80000000
+PASS converter.testEnforceRangeUnsignedLongLong is 0x80000000
+converter.testEnforceRangeUnsignedLongLong = 0xFFFFFFFF
+PASS converter.testEnforceRangeUnsignedLongLong is 0xFFFFFFFF
+PASS converter.testEnforceRangeUnsignedLongLong = -0x80000000 threw exception TypeError: Type error.
+PASS converter.testEnforceRangeUnsignedLongLong = -0x80000001 threw exception TypeError: Type error.
+PASS converter.testEnforceRangeUnsignedLongLong = 0xDCBA9876543210 threw exception TypeError: Type error.
+converter.testEnforceRangeUnsignedLongLong = Number.MIN_VALUE
+PASS converter.testEnforceRangeUnsignedLongLong is 0
+converter.testEnforceRangeUnsignedLongLong = -Number.MIN_VALUE
+PASS converter.testEnforceRangeUnsignedLongLong is 0
+PASS converter.testEnforceRangeUnsignedLongLong = Number.MAX_VALUE threw exception TypeError: Type error.
+PASS converter.testEnforceRangeUnsignedLongLong = -Number.MAX_VALUE threw exception TypeError: Type error.
+converter.testEnforceRangeUnsignedLongLong = 1.99
+PASS converter.testEnforceRangeUnsignedLongLong is 1
+PASS converter.testEnforceRangeUnsignedLongLong = -1.99 threw exception TypeError: Type error.
+PASS converter.testEnforceRangeUnsignedLongLong = Infinity threw exception TypeError: Type error.
+PASS converter.testEnforceRangeUnsignedLongLong = -Infinity threw exception TypeError: Type error.
+PASS converter.testEnforceRangeUnsignedLongLong = NaN threw exception TypeError: Type error.
+converter.testEnforceRangeUnsignedLongLong = false
+PASS converter.testEnforceRangeUnsignedLongLong is 0
+converter.testEnforceRangeUnsignedLongLong = true
+PASS converter.testEnforceRangeUnsignedLongLong is 1
+converter.testEnforceRangeUnsignedLongLong = ''
+PASS converter.testEnforceRangeUnsignedLongLong is 0
+converter.testEnforceRangeUnsignedLongLong = '1'
+PASS converter.testEnforceRangeUnsignedLongLong is 1
+PASS converter.testEnforceRangeUnsignedLongLong = 'abc' threw exception TypeError: Type error.
+converter.testEnforceRangeUnsignedLongLong = null
+PASS converter.testEnforceRangeUnsignedLongLong is 0
+PASS converter.testEnforceRangeUnsignedLongLong = undefined threw exception TypeError: Type error.
+PASS converter.testEnforceRangeUnsignedLongLong = {valueOf:function(){throw new Error('custom');}} threw exception Error: custom.
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
index 1e8bd57..14557d4 100644 (file)
@@ -18,6 +18,15 @@ PASS indexedDB.open(dbname, 0) threw TypeError: Type error
 Expecting TypeError exception from indexedDB.open(dbname, -5)
 PASS Exception was thrown.
 PASS indexedDB.open(dbname, -5) threw TypeError: Type error
+Expecting TypeError exception from indexedDB.open(dbname, Infinity)
+PASS Exception was thrown.
+PASS indexedDB.open(dbname, Infinity) threw TypeError: Type error
+Expecting TypeError exception from indexedDB.open(dbname, -Infinity)
+PASS Exception was thrown.
+PASS indexedDB.open(dbname, -Infinity) threw TypeError: Type error
+Expecting TypeError exception from indexedDB.open(dbname, NaN)
+PASS Exception was thrown.
+PASS indexedDB.open(dbname, NaN) threw TypeError: Type error
 Expecting TypeError exception from indexedDB.open(dbname, -1)
 PASS Exception was thrown.
 PASS indexedDB.open(dbname, -1) threw TypeError: Type error
index af35f2d..d339c32 100644 (file)
@@ -20,6 +20,9 @@ function deleteSuccess(evt) {
     evalAndExpectExceptionClass("indexedDB.open(dbname, 'stringversion')", "TypeError");
     evalAndExpectExceptionClass("indexedDB.open(dbname, 0)", "TypeError");
     evalAndExpectExceptionClass("indexedDB.open(dbname, -5)", "TypeError");
+    evalAndExpectExceptionClass("indexedDB.open(dbname, Infinity)", "TypeError");
+    evalAndExpectExceptionClass("indexedDB.open(dbname, -Infinity)", "TypeError");
+    evalAndExpectExceptionClass("indexedDB.open(dbname, NaN)", "TypeError");
     evalAndExpectExceptionClass("indexedDB.open(dbname, -1)", "TypeError");
     evalAndExpectExceptionClass("indexedDB.open(dbname, 0x20000000000000)", "TypeError");
     evalAndExpectExceptionClass("indexedDB.open(dbname, null)", "TypeError");
index 349547a..ab410e6 100644 (file)
@@ -1,3 +1,49 @@
+2013-03-15  Joshua Bell  <jsbell@chromium.org>
+
+        [V8] Binding: Implement EnforceRange IDL Attribute for long long conversions
+        https://bugs.webkit.org/show_bug.cgi?id=96798
+
+        Reviewed by Kentaro Hara.
+
+        Implement [EnforceRange] attribute for V8 bindings, which specifies throwing behavior
+        on conversions outside int/uint 32/64 ranges and edge cases like NaNs and Infinities.
+        Conversely, conversions without this attribute should *not* throw.
+
+        Tests: fast/js/webidl-type-mapping.html:
+               fast/dom/non-numeric-values-numeric-parameters.html
+               fast/js/script-tests/select-options-add.html
+               storage/indexeddb/intversion-bad-parameters.html
+
+        * Modules/indexeddb/IDBCursor.cpp: Remove custom range enforcement for advance()
+        * Modules/indexeddb/IDBCursor.h: Adjust type to match WebIDL.
+        * Modules/indexeddb/IDBCursor.idl: Specify [EnforceRange] and type matches spec WebIDL.
+        * Modules/indexeddb/IDBFactory.cpp: Remove custom range enforcement for open()
+        * Modules/indexeddb/IDBFactory.h: Adjust type to match WebIDL.
+        * Modules/indexeddb/IDBFactory.idl: Specify [EnforceRange] and type matches spec WebIDL.
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (JSValueToNative): Add FIXME to support [EnforceRange]
+        * bindings/scripts/CodeGeneratorV8.pm:
+        (GenerateNormalAttrSetter): Handle [EnforceRange] in attribute setters
+        (GenerateParametersCheck): Handle [EnforceRange] in parameters.
+        (JSValueToNative): Pass EnforceRange to toInt() functions as appropriate.
+        * bindings/scripts/IDLAttributes.txt:
+        * bindings/scripts/test/TestObj.idl: Tests w/ [EnforceRange]
+        * bindings/scripts/test/V8/V8TestObj.cpp: Updated expectations
+        * bindings/scripts/test/V8/V8TestTypedefs.cpp: Updated expectations.
+        * bindings/v8/V8Binding.cpp: Overloads for toInt() variants that handle constraints.
+        (WebCore::toInt32):
+        (WebCore::toUInt32):
+        (WebCore::toInt64):
+        (WebCore::toUInt64):
+        * bindings/v8/V8Binding.h: Ditto, plus helpers for callers not expecting errors.
+        (WebCore::toInt32):
+        (WebCore::toUInt32):
+        (WebCore::toInt64):
+        (WebCore::toUInt64):
+        * bindings/v8/V8BindingMacros.h: Helper macros for type conversions that may throw.
+        * testing/TypeConversions.h: Added new members with EnforceRange constraint.
+        * testing/TypeConversions.idl: Ditto.
+
 2013-03-15  Eugene Klyuchnikov  <eustas@chromium.org>
 
         Web Inspector: [Network] Refine JSDocs in NetworkRequest.js
index 7bb0f50..1cf9771 100644 (file)
@@ -152,7 +152,7 @@ PassRefPtr<IDBRequest> IDBCursor::update(ScriptState* state, ScriptValue& value,
     return objectStore->put(IDBDatabaseBackendInterface::CursorUpdate, IDBAny::create(this), state, value, m_currentPrimaryKey, ec);
 }
 
-void IDBCursor::advance(long long count, ExceptionCode& ec)
+void IDBCursor::advance(unsigned long count, ExceptionCode& ec)
 {
     ec = 0;
     IDB_TRACE("IDBCursor::advance");
@@ -166,8 +166,7 @@ void IDBCursor::advance(long long count, ExceptionCode& ec)
         return;
     }
 
-    // FIXME: This should only need to check for 0 once webkit.org/b/96798 lands.
-    if (count < 1 || count > UINT_MAX) {
+    if (!count) {
         ec = TypeError;
         return;
     }
index 18d200e..e358910 100644 (file)
@@ -69,8 +69,7 @@ public:
     IDBAny* source() const;
 
     PassRefPtr<IDBRequest> update(ScriptState*, ScriptValue&, ExceptionCode&);
-    // FIXME: Make this unsigned long once webkit.org/b/96798 lands.
-    void advance(long long, ExceptionCode&);
+    void advance(unsigned long, ExceptionCode&);
     // FIXME: Try to modify the code generator so this overload is unneeded.
     void continueFunction(ScriptExecutionContext*, ExceptionCode& ec) { continueFunction(static_cast<IDBKey*>(0), ec); }
     void continueFunction(ScriptExecutionContext*, const ScriptValue& key, ExceptionCode&);
index 4570c1e..4b6265b 100644 (file)
@@ -35,8 +35,7 @@
 
     [CallWith=ScriptState] IDBRequest update(in any value)
         raises (DOMException);
-    // FIXME: Make this [EnforceRange] unsigned long once webkit.org/b/96798 lands.
-    void advance(in long long count)
+    void advance(in [EnforceRange] unsigned long count)
         raises (DOMException);
     [CallWith=ScriptExecutionContext, ImplementedAs=continueFunction] void continue(in [Optional] any key)
         raises (DOMException);
index 4b02b11..f9d872f 100644 (file)
@@ -111,11 +111,9 @@ PassRefPtr<IDBRequest> IDBFactory::getDatabaseNames(ScriptExecutionContext* cont
     return request;
 }
 
-PassRefPtr<IDBOpenDBRequest> IDBFactory::open(ScriptExecutionContext* context, const String& name, int64_t version, ExceptionCode& ec)
+PassRefPtr<IDBOpenDBRequest> IDBFactory::open(ScriptExecutionContext* context, const String& name, unsigned long long version, ExceptionCode& ec)
 {
-    // FIXME: This should only need to check for 0 once webkit.org/b/96798 lands.
-    const int64_t maxECMAScriptInteger = 0x20000000000000LL - 1;
-    if (version < 1 || version > maxECMAScriptInteger) {
+    if (!version) {
         ec = TypeError;
         return 0;
     }
index cc61cd7..9742973 100644 (file)
@@ -57,7 +57,7 @@ public:
     PassRefPtr<IDBRequest> getDatabaseNames(ScriptExecutionContext*, ExceptionCode&);
 
     PassRefPtr<IDBOpenDBRequest> open(ScriptExecutionContext*, const String& name, ExceptionCode&);
-    PassRefPtr<IDBOpenDBRequest> open(ScriptExecutionContext*, const String& name, int64_t version, ExceptionCode&);
+    PassRefPtr<IDBOpenDBRequest> open(ScriptExecutionContext*, const String& name, unsigned long long version, ExceptionCode&);
     PassRefPtr<IDBOpenDBRequest> deleteDatabase(ScriptExecutionContext*, const String& name, ExceptionCode&);
 
     short cmp(ScriptExecutionContext*, const ScriptValue& first, const ScriptValue& second, ExceptionCode&);
index a51605b..ef51bbf 100644 (file)
@@ -31,8 +31,7 @@
     [CallWith=ScriptExecutionContext, ImplementedAs=getDatabaseNames] IDBRequest webkitGetDatabaseNames()
         raises (DOMException);
 
-    // FIXME: Make this [EnforceRange] unsigned long long once webkit.org/b/96798 lands.
-    [CallWith=ScriptExecutionContext] IDBOpenDBRequest open(in DOMString name, in [Optional] long long version)
+    [CallWith=ScriptExecutionContext] IDBOpenDBRequest open(in DOMString name, in [EnforceRange, Optional] unsigned long long version)
         raises (DOMException);
     [CallWith=ScriptExecutionContext] IDBOpenDBRequest deleteDatabase(in DOMString name)
         raises (DOMException);
index 1978ead..419b327 100644 (file)
@@ -3180,6 +3180,7 @@ sub JSValueToNative
     return "$value.toBoolean(exec)" if $type eq "boolean";
     return "$value.toNumber(exec)" if $type eq "double";
     return "$value.toFloat(exec)" if $type eq "float";
+    # FIXME: Add [EnforceRange] support
     return "$value.toInt32(exec)" if $type eq "long" or $type eq "short";
     return "$value.toUInt32(exec)" if $type eq "unsigned long" or $type eq "unsigned short";
     return "static_cast<$type>($value.toInteger(exec))" if $type eq "long long" or $type eq "unsigned long long";
index 16b7cda..274621b 100644 (file)
@@ -1329,6 +1329,8 @@ END
             push(@implContentInternals, "    " . ConvertToV8StringResource($attribute->signature, $nativeType, "v", $value, "VOID") . "\n");
         } elsif ($arrayType) {
             push(@implContentInternals, "    Vector<$arrayType> v = $value;\n");
+        } elsif ($attribute->signature->extendedAttributes->{"EnforceRange"}) {
+            push(@implContentInternals, "    V8TRYCATCH_WITH_TYPECHECK_VOID($nativeType, v, $value, info.GetIsolate());\n");
         } else {
             push(@implContentInternals, "    $nativeType v = $value;\n");
         }
@@ -1908,8 +1910,12 @@ sub GenerateParametersCheck
                     $parameterCheckString .= "        return throwTypeError(0, args.GetIsolate());\n";
                 }
             }
-            $parameterCheckString .= "    V8TRYCATCH($nativeType, $parameterName, " .
-                 JSValueToNative($parameter, $optional && $optional eq "DefaultIsNullString" ? "argumentOrNull(args, $paramIndex)" : "args[$paramIndex]", "args.GetIsolate()") . ");\n";
+            my $value = JSValueToNative($parameter, $optional && $optional eq "DefaultIsNullString" ? "argumentOrNull(args, $paramIndex)" : "args[$paramIndex]", "args.GetIsolate()");
+            if ($parameter->extendedAttributes->{"EnforceRange"}) {
+                $parameterCheckString .= "    V8TRYCATCH_WITH_TYPECHECK($nativeType, $parameterName, $value, args.GetIsolate());\n";
+            } else {
+                $parameterCheckString .= "    V8TRYCATCH($nativeType, $parameterName, $value);\n";
+            }
             if ($nativeType eq 'Dictionary') {
                $parameterCheckString .= "    if (!$parameterName.isUndefinedOrNull() && !$parameterName.isObject())\n";
                $parameterCheckString .= "        return throwTypeError(\"Not an object.\", args.GetIsolate());\n";
@@ -4002,14 +4008,23 @@ sub JSValueToNative
     my $getIsolate = shift;
 
     my $type = $signature->type;
+    my $intConversion = $signature->extendedAttributes->{"EnforceRange"} ? "EnforceRange" : "NormalConversion";
 
     return "$value" if $type eq "JSObject";
     return "$value->BooleanValue()" if $type eq "boolean";
     return "static_cast<$type>($value->NumberValue())" if $type eq "float" or $type eq "double";
 
-    return "toInt32($value)" if $type eq "long" or $type eq "short";
-    return "toUInt32($value)" if $type eq "unsigned long" or $type eq "unsigned short";
-    return "toInt64($value)" if $type eq "unsigned long long" or $type eq "long long";
+    if ($intConversion ne "NormalConversion") {
+        return "toInt32($value, $intConversion, ok)" if $type eq "long" or $type eq "short";
+        return "toUInt32($value, $intConversion, ok)" if $type eq "unsigned long" or $type eq "unsigned short";
+        return "toInt64($value, $intConversion, ok)" if $type eq "long long";
+        return "toUInt64($value, $intConversion, ok)" if $type eq "unsigned long long";
+    } else {
+        return "toInt32($value)" if $type eq "long" or $type eq "short";
+        return "toUInt32($value)" if $type eq "unsigned long" or $type eq "unsigned short";
+        return "toInt64($value)" if $type eq "long long";
+        return "toUInt64($value)" if $type eq "unsigned long long";
+    }
     return "static_cast<Range::CompareHow>($value->Int32Value())" if $type eq "CompareHow";
     return "toWebCoreDate($value)" if $type eq "Date";
     return "toDOMStringList($value, $getIsolate)" if $type eq "DOMStringList";
index 8edac12..28cbee3 100644 (file)
@@ -52,6 +52,7 @@ DoNotCheckConstants
 DoNotCheckSecurity
 DoNotCheckSecurityOnGetter
 DoNotCheckSecurityOnSetter
+EnforceRange
 EventTarget
 ExtendsDOMGlobalObject
 GenerateIsReachable=ImplDocument|ImplElementRoot|ImplOwnerNodeRoot
index 0305d5b..d3f6f2b 100644 (file)
@@ -150,6 +150,19 @@ enum TestEnumType { "", "EnumValue1", "EnumValue2", "EnumValue3" };
     static void    staticMethodWithCallbackArg(in [Callback] TestCallback callback);
 #endif
 
+#if defined(TESTING_V8)
+    // 'EnforceRange' extended attribute
+    void    methodWithEnforceRangeInt32(in [EnforceRange] long value);
+    void    methodWithEnforceRangeUInt32(in [EnforceRange] unsigned long value);
+    void    methodWithEnforceRangeInt64(in [EnforceRange] long long value);
+    void    methodWithEnforceRangeUInt64(in [EnforceRange] unsigned long long value);
+
+    attribute [EnforceRange] long enforcedRangeLongAttr;
+    attribute [EnforceRange] unsigned long enforcedRangeUnsignedLongAttr;
+    attribute [EnforceRange] long long enforcedRangeLongLongAttr;
+    attribute [EnforceRange] unsigned long long enforcedRangeUnsignedLongLongAttr;
+#endif
+
     // 'Conditional' extended attribute
     [Conditional=Condition1] attribute long conditionalAttr1;
     [Conditional=Condition1&Condition2] attribute long conditionalAttr2;
index a9acf4f..7205ae1 100644 (file)
@@ -321,7 +321,7 @@ static v8::Handle<v8::Value> unsignedLongLongAttrAttrGetterCallback(v8::Local<v8
 static void unsignedLongLongAttrAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
 {
     TestObj* imp = V8TestObj::toNative(info.Holder());
-    unsigned long long v = toInt64(value);
+    unsigned long long v = toUInt64(value);
     imp->setUnsignedLongLongAttr(v);
     return;
 }
@@ -1057,6 +1057,102 @@ static void withScriptArgumentsAndCallStackAttributeAttrSetterCallback(v8::Local
     TestObjV8Internal::withScriptArgumentsAndCallStackAttributeAttrSetter(name, value, info);
 }
 
+static v8::Handle<v8::Value> enforcedRangeLongAttrAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
+{
+    TestObj* imp = V8TestObj::toNative(info.Holder());
+    return v8Integer(imp->enforcedRangeLongAttr(), info.GetIsolate());
+}
+
+static v8::Handle<v8::Value> enforcedRangeLongAttrAttrGetterCallback(v8::Local<v8::String> name, const v8::AccessorInfo& info)
+{
+    return TestObjV8Internal::enforcedRangeLongAttrAttrGetter(name, info);
+}
+
+static void enforcedRangeLongAttrAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
+{
+    TestObj* imp = V8TestObj::toNative(info.Holder());
+    V8TRYCATCH_WITH_TYPECHECK_VOID(int, v, toInt32(value, EnforceRange, ok), info.GetIsolate());
+    imp->setEnforcedRangeLongAttr(v);
+    return;
+}
+
+static void enforcedRangeLongAttrAttrSetterCallback(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
+{
+    TestObjV8Internal::enforcedRangeLongAttrAttrSetter(name, value, info);
+}
+
+static v8::Handle<v8::Value> enforcedRangeUnsignedLongAttrAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
+{
+    TestObj* imp = V8TestObj::toNative(info.Holder());
+    return v8UnsignedInteger(imp->enforcedRangeUnsignedLongAttr(), info.GetIsolate());
+}
+
+static v8::Handle<v8::Value> enforcedRangeUnsignedLongAttrAttrGetterCallback(v8::Local<v8::String> name, const v8::AccessorInfo& info)
+{
+    return TestObjV8Internal::enforcedRangeUnsignedLongAttrAttrGetter(name, info);
+}
+
+static void enforcedRangeUnsignedLongAttrAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
+{
+    TestObj* imp = V8TestObj::toNative(info.Holder());
+    V8TRYCATCH_WITH_TYPECHECK_VOID(unsigned, v, toUInt32(value, EnforceRange, ok), info.GetIsolate());
+    imp->setEnforcedRangeUnsignedLongAttr(v);
+    return;
+}
+
+static void enforcedRangeUnsignedLongAttrAttrSetterCallback(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
+{
+    TestObjV8Internal::enforcedRangeUnsignedLongAttrAttrSetter(name, value, info);
+}
+
+static v8::Handle<v8::Value> enforcedRangeLongLongAttrAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
+{
+    TestObj* imp = V8TestObj::toNative(info.Holder());
+    return v8::Number::New(static_cast<double>(imp->enforcedRangeLongLongAttr()));
+}
+
+static v8::Handle<v8::Value> enforcedRangeLongLongAttrAttrGetterCallback(v8::Local<v8::String> name, const v8::AccessorInfo& info)
+{
+    return TestObjV8Internal::enforcedRangeLongLongAttrAttrGetter(name, info);
+}
+
+static void enforcedRangeLongLongAttrAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
+{
+    TestObj* imp = V8TestObj::toNative(info.Holder());
+    V8TRYCATCH_WITH_TYPECHECK_VOID(long long, v, toInt64(value, EnforceRange, ok), info.GetIsolate());
+    imp->setEnforcedRangeLongLongAttr(v);
+    return;
+}
+
+static void enforcedRangeLongLongAttrAttrSetterCallback(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
+{
+    TestObjV8Internal::enforcedRangeLongLongAttrAttrSetter(name, value, info);
+}
+
+static v8::Handle<v8::Value> enforcedRangeUnsignedLongLongAttrAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
+{
+    TestObj* imp = V8TestObj::toNative(info.Holder());
+    return v8::Number::New(static_cast<double>(imp->enforcedRangeUnsignedLongLongAttr()));
+}
+
+static v8::Handle<v8::Value> enforcedRangeUnsignedLongLongAttrAttrGetterCallback(v8::Local<v8::String> name, const v8::AccessorInfo& info)
+{
+    return TestObjV8Internal::enforcedRangeUnsignedLongLongAttrAttrGetter(name, info);
+}
+
+static void enforcedRangeUnsignedLongLongAttrAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
+{
+    TestObj* imp = V8TestObj::toNative(info.Holder());
+    V8TRYCATCH_WITH_TYPECHECK_VOID(unsigned long long, v, toUInt64(value, EnforceRange, ok), info.GetIsolate());
+    imp->setEnforcedRangeUnsignedLongLongAttr(v);
+    return;
+}
+
+static void enforcedRangeUnsignedLongLongAttrAttrSetterCallback(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
+{
+    TestObjV8Internal::enforcedRangeUnsignedLongLongAttrAttrSetter(name, value, info);
+}
+
 #if ENABLE(Condition1)
 
 static v8::Handle<v8::Value> conditionalAttr1AttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
@@ -2296,6 +2392,66 @@ static v8::Handle<v8::Value> staticMethodWithCallbackArgMethodCallback(const v8:
     return TestObjV8Internal::staticMethodWithCallbackArgMethod(args);
 }
 
+static v8::Handle<v8::Value> methodWithEnforceRangeInt32Method(const v8::Arguments& args)
+{
+    if (args.Length() < 1)
+        return throwNotEnoughArgumentsError(args.GetIsolate());
+    TestObj* imp = V8TestObj::toNative(args.Holder());
+    V8TRYCATCH_WITH_TYPECHECK(int, value, toInt32(args[0], EnforceRange, ok), args.GetIsolate());
+    imp->methodWithEnforceRangeInt32(value);
+    return v8Undefined();
+}
+
+static v8::Handle<v8::Value> methodWithEnforceRangeInt32MethodCallback(const v8::Arguments& args)
+{
+    return TestObjV8Internal::methodWithEnforceRangeInt32Method(args);
+}
+
+static v8::Handle<v8::Value> methodWithEnforceRangeUInt32Method(const v8::Arguments& args)
+{
+    if (args.Length() < 1)
+        return throwNotEnoughArgumentsError(args.GetIsolate());
+    TestObj* imp = V8TestObj::toNative(args.Holder());
+    V8TRYCATCH_WITH_TYPECHECK(unsigned, value, toUInt32(args[0], EnforceRange, ok), args.GetIsolate());
+    imp->methodWithEnforceRangeUInt32(value);
+    return v8Undefined();
+}
+
+static v8::Handle<v8::Value> methodWithEnforceRangeUInt32MethodCallback(const v8::Arguments& args)
+{
+    return TestObjV8Internal::methodWithEnforceRangeUInt32Method(args);
+}
+
+static v8::Handle<v8::Value> methodWithEnforceRangeInt64Method(const v8::Arguments& args)
+{
+    if (args.Length() < 1)
+        return throwNotEnoughArgumentsError(args.GetIsolate());
+    TestObj* imp = V8TestObj::toNative(args.Holder());
+    V8TRYCATCH_WITH_TYPECHECK(long long, value, toInt64(args[0], EnforceRange, ok), args.GetIsolate());
+    imp->methodWithEnforceRangeInt64(value);
+    return v8Undefined();
+}
+
+static v8::Handle<v8::Value> methodWithEnforceRangeInt64MethodCallback(const v8::Arguments& args)
+{
+    return TestObjV8Internal::methodWithEnforceRangeInt64Method(args);
+}
+
+static v8::Handle<v8::Value> methodWithEnforceRangeUInt64Method(const v8::Arguments& args)
+{
+    if (args.Length() < 1)
+        return throwNotEnoughArgumentsError(args.GetIsolate());
+    TestObj* imp = V8TestObj::toNative(args.Holder());
+    V8TRYCATCH_WITH_TYPECHECK(unsigned long long, value, toUInt64(args[0], EnforceRange, ok), args.GetIsolate());
+    imp->methodWithEnforceRangeUInt64(value);
+    return v8Undefined();
+}
+
+static v8::Handle<v8::Value> methodWithEnforceRangeUInt64MethodCallback(const v8::Arguments& args)
+{
+    return TestObjV8Internal::methodWithEnforceRangeUInt64Method(args);
+}
+
 #if ENABLE(Condition1)
 
 static v8::Handle<v8::Value> conditionalMethod1Method(const v8::Arguments& args)
@@ -3001,6 +3157,14 @@ static const V8DOMConfiguration::BatchedAttribute V8TestObjAttrs[] = {
     {"withScriptExecutionContextAndScriptStateWithSpacesAttribute", TestObjV8Internal::withScriptExecutionContextAndScriptStateWithSpacesAttributeAttrGetterCallback, TestObjV8Internal::withScriptExecutionContextAndScriptStateWithSpacesAttributeAttrSetterCallback, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */},
     // Attribute 'withScriptArgumentsAndCallStackAttribute' (Type: 'attribute' ExtAttr: 'CallWith')
     {"withScriptArgumentsAndCallStackAttribute", TestObjV8Internal::withScriptArgumentsAndCallStackAttributeAttrGetterCallback, TestObjV8Internal::withScriptArgumentsAndCallStackAttributeAttrSetterCallback, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */},
+    // Attribute 'enforcedRangeLongAttr' (Type: 'attribute' ExtAttr: 'EnforceRange')
+    {"enforcedRangeLongAttr", TestObjV8Internal::enforcedRangeLongAttrAttrGetterCallback, TestObjV8Internal::enforcedRangeLongAttrAttrSetterCallback, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */},
+    // Attribute 'enforcedRangeUnsignedLongAttr' (Type: 'attribute' ExtAttr: 'EnforceRange')
+    {"enforcedRangeUnsignedLongAttr", TestObjV8Internal::enforcedRangeUnsignedLongAttrAttrGetterCallback, TestObjV8Internal::enforcedRangeUnsignedLongAttrAttrSetterCallback, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */},
+    // Attribute 'enforcedRangeLongLongAttr' (Type: 'attribute' ExtAttr: 'EnforceRange')
+    {"enforcedRangeLongLongAttr", TestObjV8Internal::enforcedRangeLongLongAttrAttrGetterCallback, TestObjV8Internal::enforcedRangeLongLongAttrAttrSetterCallback, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */},
+    // Attribute 'enforcedRangeUnsignedLongLongAttr' (Type: 'attribute' ExtAttr: 'EnforceRange')
+    {"enforcedRangeUnsignedLongLongAttr", TestObjV8Internal::enforcedRangeUnsignedLongLongAttrAttrGetterCallback, TestObjV8Internal::enforcedRangeUnsignedLongLongAttrAttrSetterCallback, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */},
 #if ENABLE(Condition1)
     // Attribute 'conditionalAttr1' (Type: 'attribute' ExtAttr: 'Conditional')
     {"conditionalAttr1", TestObjV8Internal::conditionalAttr1AttrGetterCallback, TestObjV8Internal::conditionalAttr1AttrSetterCallback, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */},
@@ -3097,6 +3261,10 @@ static const V8DOMConfiguration::BatchedMethod V8TestObjMethods[] = {
     {"methodWithCallbackArg", TestObjV8Internal::methodWithCallbackArgMethodCallback},
     {"methodWithNonCallbackArgAndCallbackArg", TestObjV8Internal::methodWithNonCallbackArgAndCallbackArgMethodCallback},
     {"methodWithCallbackAndOptionalArg", TestObjV8Internal::methodWithCallbackAndOptionalArgMethodCallback},
+    {"methodWithEnforceRangeInt32", TestObjV8Internal::methodWithEnforceRangeInt32MethodCallback},
+    {"methodWithEnforceRangeUInt32", TestObjV8Internal::methodWithEnforceRangeUInt32MethodCallback},
+    {"methodWithEnforceRangeInt64", TestObjV8Internal::methodWithEnforceRangeInt64MethodCallback},
+    {"methodWithEnforceRangeUInt64", TestObjV8Internal::methodWithEnforceRangeUInt64MethodCallback},
 #if ENABLE(Condition1)
     {"conditionalMethod1", TestObjV8Internal::conditionalMethod1MethodCallback},
 #endif
index d8fc7d8..1dffac8 100644 (file)
@@ -94,7 +94,7 @@ static v8::Handle<v8::Value> unsignedLongLongAttrAttrGetterCallback(v8::Local<v8
 static void unsignedLongLongAttrAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
 {
     TestTypedefs* imp = V8TestTypedefs::toNative(info.Holder());
-    unsigned long long v = toInt64(value);
+    unsigned long long v = toUInt64(value);
     imp->setUnsignedLongLongAttr(v);
     return;
 }
index 7322c42..467d1d6 100644 (file)
@@ -103,40 +103,49 @@ PassRefPtr<NodeFilter> toNodeFilter(v8::Handle<v8::Value> callback)
     return NodeFilter::create(V8NodeFilterCondition::create(callback));
 }
 
-int toInt32(v8::Handle<v8::Value> value, bool& ok)
+const int32_t kMinInt32 = -0x80000000;
+const int32_t kMaxInt32 = 0x7fffffff;
+const uint32_t kMaxUInt32 = 0xffffffff;
+const int64_t kJSMaxInteger = 0x20000000000000LL - 1; // 2^53 - 1, maximum integer exactly representable in ECMAScript.
+
+int32_t toInt32(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok)
 {
     ok = true;
-    
+
     // Fast case. The value is already a 32-bit integer.
     if (value->IsInt32())
         return value->Int32Value();
-    
+
     // Can the value be converted to a number?
     v8::Local<v8::Number> numberObject = value->ToNumber();
     if (numberObject.IsEmpty()) {
         ok = false;
         return 0;
     }
-    
+
+    if (configuration == EnforceRange) {
+        double x = numberObject->Value();
+        if (std::isnan(x) || std::isinf(x)) {
+            ok = false;
+            return 0;
+        }
+        x = (x < 0 ? -1 : 1) * floor(fabs(x));
+        if (x < kMinInt32 || x > kMaxInt32) {
+            ok = false;
+            return 0;
+        }
+
+        return x;
+    }
+
     // Does the value convert to nan or to an infinity?
     double numberValue = numberObject->Value();
-    if (std::isnan(numberValue) || std::isinf(numberValue)) {
-        ok = false;
-        return 0;
-    }
-    
-    // Can the value be converted to a 32-bit integer?
-    v8::Local<v8::Int32> intValue = value->ToInt32();
-    if (intValue.IsEmpty()) {
-        ok = false;
+    if (std::isnan(numberValue) || std::isinf(numberValue))
         return 0;
-    }
-    
-    // Return the result of the int32 conversion.
-    return intValue->Value();
+    return numberObject->Int32Value();
 }
-    
-uint32_t toUInt32(v8::Handle<v8::Value> value, bool& ok)
+
+uint32_t toUInt32(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok)
 {
     ok = true;
 
@@ -144,10 +153,16 @@ uint32_t toUInt32(v8::Handle<v8::Value> value, bool& ok)
     if (value->IsUint32())
         return value->Uint32Value();
 
+    // Fast case. The value is a 32-bit signed integer - possibly positive?
     if (value->IsInt32()) {
         int32_t result = value->Int32Value();
         if (result >= 0)
             return result;
+        if (configuration == EnforceRange) {
+            ok = false;
+            return 0;
+        }
+        return result;
     }
 
     // Can the value be converted to a number?
@@ -157,21 +172,110 @@ uint32_t toUInt32(v8::Handle<v8::Value> value, bool& ok)
         return 0;
     }
 
+    if (configuration == EnforceRange) {
+        double x = numberObject->Value();
+        if (std::isnan(x) || std::isinf(x)) {
+            ok = false;
+            return 0;
+        }
+        x = (x < 0 ? -1 : 1) * floor(fabs(x));
+        if (x < 0 || x > kMaxUInt32) {
+            ok = false;
+            return 0;
+        }
+
+        return x;
+    }
+
     // Does the value convert to nan or to an infinity?
     double numberValue = numberObject->Value();
-    if (std::isnan(numberValue) || std::isinf(numberValue)) {
+    if (std::isnan(numberValue) || std::isinf(numberValue))
+        return 0;
+    return numberObject->Uint32Value();
+}
+
+int64_t toInt64(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok)
+{
+    ok = true;
+
+    // Fast case. The value is a 32-bit integer.
+    if (value->IsInt32())
+        return value->Int32Value();
+
+    // Can the value be converted to a number?
+    v8::Local<v8::Number> numberObject = value->ToNumber();
+    if (numberObject.IsEmpty()) {
         ok = false;
         return 0;
     }
 
-    // Can the value be converted to a 32-bit unsigned integer?
-    v8::Local<v8::Uint32> uintValue = value->ToUint32();
-    if (uintValue.IsEmpty()) {
+    double x = numberObject->Value();
+
+    if (configuration == EnforceRange) {
+        if (std::isnan(x) || std::isinf(x)) {
+            ok = false;
+            return 0;
+        }
+        x = (x < 0 ? -1 : 1) * floor(fabs(x));
+        if (x < -kJSMaxInteger || x > kJSMaxInteger) {
+            ok = false;
+            return 0;
+        }
+        return x;
+    }
+
+    // NaNs and +/-Infinity should be 0, otherwise modulo 2^64.
+    unsigned long long integer;
+    doubleToInteger(x, integer);
+    return integer;
+}
+
+uint64_t toUInt64(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok)
+{
+    ok = true;
+
+    // Fast case. The value is a 32-bit unsigned integer.
+    if (value->IsUint32())
+        return value->Uint32Value();
+
+    // Fast case. The value is a 32-bit integer.
+    if (value->IsInt32()) {
+        int32_t result = value->Int32Value();
+        if (result >= 0)
+            return result;
+        if (configuration == EnforceRange) {
+            ok = false;
+            return 0;
+        }
+        return result;
+    }
+
+    // Can the value be converted to a number?
+    v8::Local<v8::Number> numberObject = value->ToNumber();
+    if (numberObject.IsEmpty()) {
         ok = false;
         return 0;
     }
 
-    return uintValue->Value();
+    double x = numberObject->Value();
+
+    if (configuration == EnforceRange) {
+        if (std::isnan(x) || std::isinf(x)) {
+            ok = false;
+            return 0;
+        }
+        x = (x < 0 ? -1 : 1) * floor(fabs(x));
+        if (x < 0 || x > kJSMaxInteger) {
+            ok = false;
+            return 0;
+        }
+        return x;
+    }
+
+    // NaNs and +/-Infinity should be 0, otherwise modulo 2^64.
+    unsigned long long integer;
+    doubleToInteger(x, integer);
+    return integer;
 }
 
 v8::Persistent<v8::FunctionTemplate> createRawTemplate(v8::Isolate* isolate)
index c435ffc..5ab2b16 100644 (file)
@@ -243,36 +243,66 @@ namespace WebCore {
 
     v8::Handle<v8::Value> v8Array(PassRefPtr<DOMStringList>, v8::Isolate*);
 
-    // Convert a value to a 32-bit integer. The conversion fails if the
-    // value cannot be converted to an integer or converts to nan or to an infinity.
-    int toInt32(v8::Handle<v8::Value>, bool& ok);
+    // Conversion flags, used in toIntXX/toUIntXX.
+    enum IntegerConversionConfiguration {
+        NormalConversion,
+        EnforceRange,
+        // FIXME: Implement Clamp
+    };
+
+    // Convert a value to a 32-bit signed integer. The conversion fails if the
+    // value cannot be converted to a number or the range violated per WebIDL:
+    // http://www.w3.org/TR/WebIDL/#es-long
+    int32_t toInt32(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok);
+    inline int32_t toInt32(v8::Handle<v8::Value> value, bool& ok) { return toInt32(value, NormalConversion, ok); }
 
     // Convert a value to a 32-bit integer assuming the conversion cannot fail.
-    inline int toInt32(v8::Handle<v8::Value> value)
+    inline int32_t toInt32(v8::Handle<v8::Value> value)
     {
         bool ok;
-        return toInt32(value, ok);
+        return toInt32(value, NormalConversion, ok);
     }
 
     // Convert a value to a 32-bit unsigned integer. The conversion fails if the
-    // value cannot be converted to an unsigned integer or converts to nan or to an infinity.
-    uint32_t toUInt32(v8::Handle<v8::Value>, bool& ok);
+    // value cannot be converted to a number or the range violated per WebIDL:
+    // http://www.w3.org/TR/WebIDL/#es-unsigned-long
+    uint32_t toUInt32(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok);
+    inline uint32_t toUInt32(v8::Handle<v8::Value> value, bool& ok) { return toUInt32(value, NormalConversion, ok); }
 
     // Convert a value to a 32-bit unsigned integer assuming the conversion cannot fail.
     inline uint32_t toUInt32(v8::Handle<v8::Value> value)
     {
         bool ok;
-        return toUInt32(value, ok);
+        return toUInt32(value, NormalConversion, ok);
     }
 
-    inline float toFloat(v8::Local<v8::Value> value)
+    // Convert a value to a 64-bit signed integer. The conversion fails if the
+    // value cannot be converted to a number or the range violated per WebIDL:
+    // http://www.w3.org/TR/WebIDL/#es-long-long
+    int64_t toInt64(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok);
+
+    // Convert a value to a 64-bit integer assuming the conversion cannot fail.
+    inline int64_t toInt64(v8::Handle<v8::Value> value)
     {
-        return static_cast<float>(value->NumberValue());
+        bool ok;
+        return toInt64(value, NormalConversion, ok);
     }
 
-    inline long long toInt64(v8::Local<v8::Value> value)
+    // Convert a value to a 64-bit unsigned integer. The conversion fails if the
+    // value cannot be converted to a number or the range violated per WebIDL:
+    // http://www.w3.org/TR/WebIDL/#es-unsigned-long-long
+    uint64_t toUInt64(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok);
+
+    // Convert a value to a 64-bit unsigned integer assuming the conversion cannot fail.
+    inline uint64_t toUInt64(v8::Handle<v8::Value> value)
     {
-        return static_cast<long long>(value->IntegerValue());
+        bool ok;
+        return toUInt64(value, NormalConversion, ok);
+    }
+
+    inline float toFloat(v8::Local<v8::Value> value)
+    {
+        return static_cast<float>(value->NumberValue());
     }
 
     WrapperWorldType worldType(v8::Isolate*);
index 6feb53e..4366cd4 100644 (file)
@@ -42,6 +42,38 @@ namespace WebCore {
             return block.ReThrow();       \
     }
 
+#define V8TRYCATCH_WITH_TYPECHECK(type, var, value, isolate) \
+    type var;                                                \
+    {                                                        \
+        bool ok = true;                                      \
+        {                                                    \
+            v8::TryCatch block;                              \
+            var = (value);                                   \
+            if (block.HasCaught())                           \
+                return block.ReThrow();                      \
+        }                                                    \
+        if (UNLIKELY(!ok))                                   \
+            return throwTypeError(0, isolate);               \
+    }
+
+#define V8TRYCATCH_WITH_TYPECHECK_VOID(type, var, value, isolate) \
+    type var;                                                     \
+    {                                                             \
+        bool ok = true;                                           \
+        {                                                         \
+            v8::TryCatch block;                                   \
+            var = (value);                                        \
+            if (block.HasCaught()) {                              \
+                block.ReThrow();                                  \
+                return;                                           \
+            }                                                     \
+        }                                                         \
+        if (UNLIKELY(!ok)) {                                      \
+            throwTypeError(0, isolate);                           \
+            return;                                               \
+        }                                                         \
+    }
+
 #define V8TRYCATCH_FOR_V8STRINGRESOURCE(type, var, value) \
     type var(value);                                            \
     if (!var.prepare())                                         \
index 24b33dd..8de102f 100644 (file)
@@ -36,25 +36,33 @@ class TypeConversions : public RefCounted<TypeConversions> {
 public:
     static PassRefPtr<TypeConversions> create() { return adoptRef(new TypeConversions()); }
 
-    long testLong() { return m_testLong; }
-    void setTestLong(long value) { m_testLong = value; }
-    unsigned long testUnsignedLong() { return m_testUnsignedLong; }
-    void setTestUnsignedLong(unsigned long value) { m_testUnsignedLong = value; }
+    long testLong() { return m_long; }
+    void setTestLong(long value) { m_long = value; }
+    long testEnforceRangeLong() { return m_long; }
+    void setTestEnforceRangeLong(long value) { m_long = value; }
+    unsigned long testUnsignedLong() { return m_unsignedLong; }
+    void setTestUnsignedLong(unsigned long value) { m_unsignedLong = value; }
+    unsigned long testEnforceRangeUnsignedLong() { return m_unsignedLong; }
+    void setTestEnforceRangeUnsignedLong(unsigned long value) { m_unsignedLong = value; }
 
-    long long testLongLong() { return m_testLongLong; }
-    void setTestLongLong(long long value) { m_testLongLong = value; }
-    unsigned long long testUnsignedLongLong() { return m_testUnsignedLongLong; }
-    void setTestUnsignedLongLong(unsigned long long value) { m_testUnsignedLongLong = value; }
+    long long testLongLong() { return m_longLong; }
+    void setTestLongLong(long long value) { m_longLong = value; }
+    long long testEnforceRangeLongLong() { return m_longLong; }
+    void setTestEnforceRangeLongLong(long long value) { m_longLong = value; }
+    unsigned long long testUnsignedLongLong() { return m_unsignedLongLong; }
+    void setTestUnsignedLongLong(unsigned long long value) { m_unsignedLongLong = value; }
+    unsigned long long testEnforceRangeUnsignedLongLong() { return m_unsignedLongLong; }
+    void setTestEnforceRangeUnsignedLongLong(unsigned long long value) { m_unsignedLongLong = value; }
 
 private:
     TypeConversions()
     {
     }
 
-    long m_testLong;
-    unsigned long m_testUnsignedLong;
-    long long m_testLongLong;
-    unsigned long long m_testUnsignedLongLong;
+    long m_long;
+    unsigned long m_unsignedLong;
+    long long m_longLong;
+    unsigned long long m_unsignedLongLong;
 };
 
 } // namespace WebCore
index 367d1f7..b27b158 100644 (file)
     ImplementationLacksVTable
 ] interface TypeConversions {
     attribute long testLong;
+    attribute [EnforceRange] long testEnforceRangeLong;
     attribute unsigned long testUnsignedLong;
+    attribute [EnforceRange] unsigned long testEnforceRangeUnsignedLong;
 
     attribute long long testLongLong;
+    attribute [EnforceRange] long long testEnforceRangeLongLong;
     attribute unsigned long long testUnsignedLongLong;
+    attribute [EnforceRange] unsigned long long testEnforceRangeUnsignedLongLong;
 };