diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIntrinsics.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIntrinsics.kt index 144f559aea9..a060a22dd13 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIntrinsics.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIntrinsics.kt @@ -115,6 +115,9 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC // val isCharSymbol = getInternalFunction("isChar") val isObjectSymbol = getInternalFunction("isObject") + val isNumberSymbol = getInternalFunction("isNumber") + val isComparableSymbol = getInternalFunction("isComparable") + val isPrimitiveArray = mapOf( PrimitiveType.BOOLEAN to getInternalFunction("isBooleanArray"), PrimitiveType.BYTE to getInternalFunction("isByteArray"), diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TypeOperatorLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TypeOperatorLowering.kt index 2b36821c187..5303f6a6f9d 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TypeOperatorLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TypeOperatorLowering.kt @@ -141,7 +141,6 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { type.isInt() || type.isFloat() || type.isDouble() || - type.isNumber() || type.isBoolean() || type.isFunctionOrKFunction() || type.isString() @@ -217,6 +216,8 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { toType.isAny() -> generateIsObjectCheck(argument) isTypeOfCheckingType(toType) -> generateTypeOfCheck(argument, toType) // toType.isChar() -> generateCheckForChar(argument) + toType.isNumber() -> generateNumberCheck(argument) + toType.isComparable() -> generateComparableCheck(argument) toType.isArray() -> generateGenericArrayCheck(argument) toType.isPrimitiveArray() -> generatePrimitiveArrayTypeCheck(argument, toType) toType.isTypeParameter() -> generateTypeCheckWithTypeParameter(argument, toType) @@ -272,6 +273,12 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { private fun generateGenericArrayCheck(argument: IrExpression) = JsIrBuilder.buildCall(isArraySymbol).apply { putValueArgument(0, argument) } + private fun generateNumberCheck(argument: IrExpression) = + JsIrBuilder.buildCall(context.intrinsics.isNumberSymbol).apply { putValueArgument(0, argument) } + + private fun generateComparableCheck(argument: IrExpression) = + JsIrBuilder.buildCall(context.intrinsics.isComparableSymbol).apply { putValueArgument(0, argument) } + private fun generatePrimitiveArrayTypeCheck(argument: IrExpression, toType: IrType): IrExpression { val f = context.intrinsics.isPrimitiveArray[toType.getPrimitiveArrayElementType()]!! return JsIrBuilder.buildCall(f).apply { putValueArgument(0, argument) } diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicIrBoxTest.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicIrBoxTest.kt index 463d52ea7e0..b101101da62 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicIrBoxTest.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicIrBoxTest.kt @@ -69,6 +69,8 @@ private val runtimeSourcesCommon = listOfKtFilesFrom( // Replaced with irRuntime/kotlinHacks.kt "libraries/stdlib/js/src/kotlin/kotlin.kt", + "libraries/stdlib/js/src/kotlin/currentBeMisc.kt", + // Full version is defined in stdlib // This file is useful for smaller subset of runtime sources "libraries/stdlib/js/irRuntime/rangeExtensions.kt", diff --git a/js/js.translator/testData/box/number/mulInt32.kt b/js/js.translator/testData/box/number/mulInt32.kt index 05b8fb9a082..ff133b6fdd3 100644 --- a/js/js.translator/testData/box/number/mulInt32.kt +++ b/js/js.translator/testData/box/number/mulInt32.kt @@ -1,6 +1,11 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1523 -fun imul32(a: Int, b: Int): Int = js("Kotlin").imulEmulated(a, b) + +//@library +//@JsName("imulEmulated") +//internal fun imul(Int, Int): Int + +@Suppress("INVISIBLE_MEMBER") +fun imul32(a: Int, b: Int): Int = imul(a, b) fun imul64(a: Int, b: Int): Int = (a.toLong() * b.toLong()).toInt() diff --git a/js/js.translator/testData/box/number/numberIsCheck.kt b/js/js.translator/testData/box/number/numberIsCheck.kt index 5a833e0b2bb..81d24cbe396 100644 --- a/js/js.translator/testData/box/number/numberIsCheck.kt +++ b/js/js.translator/testData/box/number/numberIsCheck.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1286 package foo diff --git a/libraries/stdlib/js/irRuntime/misc.kt b/libraries/stdlib/js/irRuntime/misc.kt index e91effd202a..2ff3966103e 100644 --- a/libraries/stdlib/js/irRuntime/misc.kt +++ b/libraries/stdlib/js/irRuntime/misc.kt @@ -6,5 +6,5 @@ package kotlin.js // TODO: Polyfill -fun imul(a: dynamic, b: dynamic) = - js("((a & 0xffff0000) * (b & 0xffff) + (a & 0xffff) * (b | 0)) | 0") \ No newline at end of file +internal fun imul(a: Int, b: Int) = + js("((a & 0xffff0000) * (b & 0xffff) + (a & 0xffff) * (b | 0)) | 0").unsafeCast() \ No newline at end of file diff --git a/libraries/stdlib/js/irRuntime/typeCheckUtils.kt b/libraries/stdlib/js/irRuntime/typeCheckUtils.kt index e6da97c7c4e..88130ce41f1 100644 --- a/libraries/stdlib/js/irRuntime/typeCheckUtils.kt +++ b/libraries/stdlib/js/irRuntime/typeCheckUtils.kt @@ -150,4 +150,16 @@ public fun jsIsType(obj: dynamic, jsClass: dynamic): Boolean { } return false -} \ No newline at end of file +} + +fun isNumber(a: dynamic) = jsTypeOf(a) == "number" || a is Long + +fun isComparable(value: dynamic): Boolean { + var type = jsTypeOf(value) + + return type == "string" || + type == "boolean" || + isNumber(value) || + isInterface(value, Comparable::class.js) +} + diff --git a/libraries/stdlib/js/src/kotlin/currentBeMisc.kt b/libraries/stdlib/js/src/kotlin/currentBeMisc.kt new file mode 100644 index 00000000000..8a2550b9ec5 --- /dev/null +++ b/libraries/stdlib/js/src/kotlin/currentBeMisc.kt @@ -0,0 +1,12 @@ +/* + * 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 + +// Mirrors signature from JS IR BE +// Used for js.translator/testData/box/number/mulInt32.kt +@library +@JsName("imulEmulated") +internal fun imul(x: Int, y: Int): Int = definedExternally \ No newline at end of file