Improve Number.hashCode implementation in JavaScript

Fix KT-13577
This commit is contained in:
Alexey Andreev
2017-04-13 15:25:02 +03:00
parent c0542f7dc0
commit 38aecb14a2
3 changed files with 67 additions and 7 deletions
+41 -7
View File
@@ -27,7 +27,7 @@ Kotlin.equals = function (obj1, obj2) {
return obj2 !== obj2; return obj2 !== obj2;
} }
if (typeof obj1 == "object" && typeof obj1.equals === "function") { if (typeof obj1 === "object" && typeof obj1.equals === "function") {
return obj1.equals(obj2); return obj1.equals(obj2);
} }
@@ -38,16 +38,17 @@ Kotlin.hashCode = function (obj) {
if (obj == null) { if (obj == null) {
return 0; return 0;
} }
if ("function" == typeof obj.hashCode) { if ("function" === typeof obj.hashCode) {
return obj.hashCode(); return obj.hashCode();
} }
var objType = typeof obj; var objType = typeof obj;
if ("object" == objType || "function" == objType) { if ("object" === objType || "function" === objType) {
return getObjectHashCode(obj); return getObjectHashCode(obj);
} else if ("number" == objType) { }
// TODO: a more elaborate code is needed for floating point values. else if ("number" === objType) {
return obj | 0; return numberHashCode(obj);
} if ("boolean" == objType) { }
if ("boolean" === objType) {
return Number(obj) return Number(obj)
} }
@@ -55,6 +56,39 @@ Kotlin.hashCode = function (obj) {
return getStringHashCode(str); return getStringHashCode(str);
}; };
var numberHashCode;
if (typeof ArrayBuffer === "function") {
var bufferForNumberConversion = new ArrayBuffer(8);
var arrayForDoubleConversion = new Float64Array(bufferForNumberConversion);
var arrayForIntegerConversion = new Int32Array(bufferForNumberConversion);
// Detect endiannes of ArrayBuffer
var lowerIntegerIndex = 0;
var upperIntegerIndex = 1;
(function() {
arrayForDoubleConversion[0] = 1.2;
if (arrayForIntegerConversion[0] !== 0x3FF33333) {
lowerIntegerIndex = 1;
upperIntegerIndex = 0;
}
})();
numberHashCode = function(obj) {
if ((obj | 0) === obj) {
return obj | 0;
}
else {
arrayForDoubleConversion[0] = obj;
return (arrayForIntegerConversion[lowerIntegerIndex] * 31 | 0) + arrayForIntegerConversion[upperIntegerIndex] | 0;
}
}
}
else {
numberHashCode = function(obj) {
return obj | 0;
}
}
Kotlin.toString = function (o) { Kotlin.toString = function (o) {
if (o == null) { if (o == null) {
return "null"; return "null";
@@ -6275,6 +6275,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("hashCode.kt")
public void testHashCode() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/number/hashCode.kt");
doTest(fileName);
}
@TestMetadata("hexadecimalConstant.kt") @TestMetadata("hexadecimalConstant.kt")
public void testHexadecimalConstant() throws Exception { public void testHexadecimalConstant() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/number/hexadecimalConstant.kt"); String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/number/hexadecimalConstant.kt");
+20
View File
@@ -0,0 +1,20 @@
fun box(): String {
var value = (3).hashCode()
if (value != 3) return "fail1: $value"
value = (3.14).hashCode()
if (value != 319176039) return "fail2: $value"
value = (3.14159).hashCode()
if (value != -1321819243) return "fail3: $value"
value = (1e80).hashCode()
if (value != 314940496) return "fail4: $value"
value = (1e81).hashCode()
if (value != 1519485350) return "fail5: $value"
return "OK"
}