[JS IR BE] hashCode, toString, number conversion support
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package kotlin.js
|
||||
|
||||
|
||||
// Adopted from misc.js
|
||||
|
||||
fun compareTo(a: dynamic, b: dynamic): Int {
|
||||
var typeA = typeOf(a)
|
||||
if (typeA == "number") {
|
||||
if (typeOf(b) == "number") {
|
||||
return doubleCompareTo(a, b)
|
||||
}
|
||||
return primitiveCompareTo(a, b)
|
||||
}
|
||||
if (typeA == "string" || typeA == "boolean") {
|
||||
return primitiveCompareTo(a, b)
|
||||
}
|
||||
|
||||
// TODO: Replace to a.unsafeCast<Comparable<*>>().compareTo(b) when bridge is implemented
|
||||
return js("a.compareTo(b)").unsafeCast<Int>()
|
||||
}
|
||||
|
||||
fun primitiveCompareTo(a: dynamic, b: dynamic): Int =
|
||||
js("a < b ? -1 : a > b ? 1 : 0").unsafeCast<Int>()
|
||||
|
||||
fun doubleCompareTo(a: dynamic, b: dynamic): Int =
|
||||
js("""
|
||||
if (a < b) return -1;
|
||||
if (a > b) return 1;
|
||||
|
||||
if (a === b) {
|
||||
if (a !== 0) return 0;
|
||||
|
||||
var ia = 1 / a;
|
||||
return ia === 1 / b ? 0 : (ia < 0 ? -1 : 1);
|
||||
}
|
||||
|
||||
return a !== a ? (b !== b ? 0 : 1) : -1
|
||||
""").unsafeCast<Int>()
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package kotlin.js
|
||||
|
||||
fun equals(obj1: dynamic, obj2: dynamic): Boolean {
|
||||
if (obj1 == null) {
|
||||
return obj2 == null
|
||||
}
|
||||
|
||||
if (obj2 == null) {
|
||||
return false
|
||||
}
|
||||
|
||||
return js("""
|
||||
if (typeof obj1 === "object" && typeof obj1.equals === "function") {
|
||||
return obj1.equals(obj2);
|
||||
}
|
||||
|
||||
if (obj1 !== obj1) {
|
||||
return obj2 !== obj2;
|
||||
}
|
||||
|
||||
if (typeof obj1 === "number" && typeof obj2 === "number") {
|
||||
return obj1 === obj2 && (obj1 !== 0 || 1 / obj1 === 1 / obj2)
|
||||
}
|
||||
return obj1 === obj2;
|
||||
""").unsafeCast<Boolean>()
|
||||
}
|
||||
|
||||
fun toString(o: dynamic): String = when {
|
||||
o == null -> "null"
|
||||
isArrayish(o) -> "[...]"
|
||||
else -> js("o.toString()").unsafeCast<String>()
|
||||
}
|
||||
|
||||
// TODO: Simplify, extract kotlin declarations for inner helper functions
|
||||
fun hashCode(obj: dynamic): Int {
|
||||
return js(
|
||||
"""
|
||||
function hashCode(obj) {
|
||||
if (obj == null) {
|
||||
return 0;
|
||||
}
|
||||
var objType = typeof obj;
|
||||
if ("object" === objType) {
|
||||
return "function" === typeof obj.hashCode ? obj.hashCode() : getObjectHashCode(obj);
|
||||
}
|
||||
if ("function" === objType) {
|
||||
return getObjectHashCode(obj);
|
||||
}
|
||||
if ("number" === objType) {
|
||||
return getNumberHashCode(obj);
|
||||
}
|
||||
if ("boolean" === objType) {
|
||||
return Number(obj)
|
||||
}
|
||||
|
||||
var str = String(obj);
|
||||
return getStringHashCode(str);
|
||||
};
|
||||
|
||||
/** @const */
|
||||
var POW_2_32 = 4294967296;
|
||||
// TODO: consider switching to Symbol type once we are on ES6.
|
||||
/** @const */
|
||||
var OBJECT_HASH_CODE_PROPERTY_NAME = "kotlinHashCodeValue${'$'}";
|
||||
|
||||
function getObjectHashCode(obj) {
|
||||
if (!(OBJECT_HASH_CODE_PROPERTY_NAME in obj)) {
|
||||
var hash = (Math.random() * POW_2_32) | 0; // Make 32-bit singed integer.
|
||||
Object.defineProperty(obj, OBJECT_HASH_CODE_PROPERTY_NAME, { value: hash, enumerable: false });
|
||||
}
|
||||
return obj[OBJECT_HASH_CODE_PROPERTY_NAME];
|
||||
}
|
||||
|
||||
function getStringHashCode(str) {
|
||||
var hash = 0;
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
var code = str.charCodeAt(i);
|
||||
hash = (hash * 31 + code) | 0; // Keep it 32-bit.
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
function getNumberHashCode(obj) {
|
||||
if ((obj | 0) === obj) {
|
||||
return obj | 0;
|
||||
}
|
||||
else {
|
||||
bufFloat64[0] = obj;
|
||||
return (bufInt32[highIndex] * 31 | 0) + bufInt32[lowIndex] | 0;
|
||||
}
|
||||
}
|
||||
|
||||
return hashCode(obj);
|
||||
"""
|
||||
).unsafeCast<Int>()
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package kotlin.js
|
||||
|
||||
fun asIs(a: dynamic) = a
|
||||
|
||||
fun numberToByte(a: dynamic): Byte = toByte(numberToInt(a))
|
||||
|
||||
fun numberToDouble(a: dynamic): Double = js("+a").unsafeCast<Double>()
|
||||
|
||||
fun numberToInt(a: dynamic): Int = doubleToInt(a)
|
||||
|
||||
fun numberToShort(a: dynamic): Short = toShort(numberToInt(a))
|
||||
|
||||
// << and >> shifts are used to preserve sign of the number
|
||||
fun toByte(a: dynamic): Byte = js("a << 24 >> 24").unsafeCast<Byte>()
|
||||
fun toShort(a: dynamic): Short = js("a << 16 >> 16").unsafeCast<Short>()
|
||||
|
||||
fun doubleToInt(a: dynamic) = js("""
|
||||
if (a > 2147483647) return 2147483647;
|
||||
if (a < -2147483648) return -2147483648;
|
||||
return a | 0;
|
||||
""").unsafeCast<Int>()
|
||||
@@ -75,7 +75,7 @@ public fun isInterface(ctor: dynamic, IType: dynamic): Boolean {
|
||||
}
|
||||
*/
|
||||
|
||||
inline private fun typeOf(obj: dynamic) = js("typeof obj").unsafeCast<String>()
|
||||
fun typeOf(obj: dynamic) = js("typeof obj").unsafeCast<String>()
|
||||
|
||||
fun isObject(obj: dynamic): Boolean {
|
||||
val objTypeOf = typeOf(obj)
|
||||
@@ -93,6 +93,10 @@ public fun isArray(obj: Any): Boolean {
|
||||
return js("Array.isArray(obj)").unsafeCast<Boolean>()
|
||||
}
|
||||
|
||||
public fun isArrayish(o: dynamic) =
|
||||
isArray(o) || js("ArrayBuffer.isView(o)").unsafeCast<Boolean>()
|
||||
|
||||
|
||||
public fun isChar(c: Any): Boolean {
|
||||
return js("throw Error(\"isChar is not implemented\")").unsafeCast<Boolean>()
|
||||
}
|
||||
Reference in New Issue
Block a user