diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/utils/kotlinTypeBasedUtils.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/utils/kotlinTypeBasedUtils.kt index b832970d9f7..a40fdb51d31 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/utils/kotlinTypeBasedUtils.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/utils/kotlinTypeBasedUtils.kt @@ -26,6 +26,8 @@ fun IrType.isInterface() = toKotlinType().isInterface() fun IrType.isPrimitiveArray() = KotlinBuiltIns.isPrimitiveArray(toKotlinType()) +fun IrType.getPrimitiveArrayElementType() = KotlinBuiltIns.getPrimitiveArrayElementType(toKotlinType()) + fun IrType.isTypeParameter() = toKotlinType().isTypeParameter() fun IrType.isFunctionOrKFunction() = toKotlinType().isFunctionOrKFunctionType 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 9994275ce83..f49f28d2681 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 @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.ir.backend.js import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl @@ -118,11 +119,21 @@ class JsIntrinsics( // val isCharSymbol = getInternalFunction("isChar") val isObjectSymbol = getInternalFunction("isObject") + val isPrimitiveArray = mapOf( + PrimitiveType.BOOLEAN to getInternalFunction("isBooleanArray"), + PrimitiveType.BYTE to getInternalFunction("isByteArray"), + PrimitiveType.SHORT to getInternalFunction("isShortArray"), + PrimitiveType.CHAR to getInternalFunction("isCharArray"), + PrimitiveType.INT to getInternalFunction("isIntArray"), + PrimitiveType.FLOAT to getInternalFunction("isFloatArray"), + PrimitiveType.LONG to getInternalFunction("isLongArray"), + PrimitiveType.DOUBLE to getInternalFunction("isLongArray") + ) + // Other: val jsObjectCreate = defineObjectCreateIntrinsic() // Object.create val jsSetJSField = defineSetJSPropertyIntrinsic() // till we don't have dynamic type we use intrinsic which sets a field with any name - val jsToJsType = defineToJsType() // creates name reference to KotlinType val jsCode = getInternalFunction("js") // js("") val jsHashCode = getInternalFunction("hashCode") val jsGetObjectHashCode = getInternalFunction("getObjectHashCode") @@ -139,6 +150,10 @@ class JsIntrinsics( val f = getInternalFunctions("getContinuation") symbolTable.referenceSimpleFunction(f.single()) } + val jsGetKClass = getInternalWithoutPackage("getKClass") + val jsGetKClassFromExpression = getInternalWithoutPackage("getKClassFromExpression") + val jsClass = getInternalFunction("jsClass") + val jsNumberRangeToNumber = getInternalFunction("numberRangeToNumber") val jsNumberRangeToLong = getInternalFunction("numberRangeToLong") @@ -162,28 +177,9 @@ class JsIntrinsics( private fun getInternalFunction(name: String) = context.symbolTable.referenceSimpleFunction(context.getInternalFunctions(name).single()) - private fun defineToJsType(): IrSimpleFunction { - val desc = SimpleFunctionDescriptorImpl.create( - module, - Annotations.EMPTY, - Name.identifier("\$toJSType\$"), - CallableMemberDescriptor.Kind.SYNTHESIZED, - SourceElement.NO_SOURCE - ).apply { + private fun getInternalWithoutPackage(name: String) = + context.symbolTable.referenceSimpleFunction(context.getFunctions(FqName(name)).single()) - val typeParameter = TypeParameterDescriptorImpl.createWithDefaultBound( - this, - Annotations.EMPTY, - false, - Variance.INVARIANT, - Name.identifier("T"), - 0 - ) - initialize(null, null, listOf(typeParameter), emptyList(), builtIns.anyType, Modality.FINAL, Visibilities.PUBLIC) - } - - return stubBuilder.generateFunctionStub(desc) - } // TODO: unify how we create intrinsic symbols private fun defineObjectCreateIntrinsic(): IrSimpleFunction { diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt index 27136c40dba..706936ebdf9 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt @@ -114,6 +114,7 @@ private fun JsIrBackendContext.lower(moduleFragment: IrModuleFragment) { moduleFragment.files.forEach(clble.getReferenceCollector()) moduleFragment.files.forEach(clble.getClosureBuilder()) moduleFragment.files.forEach(clble.getReferenceReplacer()) + moduleFragment.files.forEach(ClassReferenceLowering(this)::lower) moduleFragment.files.forEach(IntrinsicifyCallsLowering(this)::lower) } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ClassReferenceLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ClassReferenceLowering.kt new file mode 100644 index 00000000000..37addfdbe81 --- /dev/null +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ClassReferenceLowering.kt @@ -0,0 +1,53 @@ +/* + * 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 org.jetbrains.kotlin.ir.backend.js.lower + +import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext +import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.expressions.IrClassReference +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrGetClass +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid + +class ClassReferenceLowering(val context: JsIrBackendContext) : FileLoweringPass { + private val intrinsics = context.intrinsics + + private fun callGetKClassFromExpression(returnType: IrType, typeArgument: IrType, argument: IrExpression) = + JsIrBuilder.buildCall(intrinsics.jsGetKClassFromExpression, returnType, listOf(typeArgument)).apply { + putValueArgument(0, argument) + } + + private fun callGetKClass(returnType: IrType, typeArgument: IrType, argument: IrExpression) = + JsIrBuilder.buildCall(intrinsics.jsGetKClass, returnType, listOf(typeArgument)).apply { + putValueArgument(0, argument) + } + + private fun callJsClass(type: IrType) = + JsIrBuilder.buildCall(intrinsics.jsClass, typeArguments = listOf(type)) + + override fun lower(irFile: IrFile) { + irFile.transformChildrenVoid(object : IrElementTransformerVoid() { + override fun visitGetClass(expression: IrGetClass) = + callGetKClassFromExpression( + returnType = expression.type, + typeArgument = expression.argument.type, + argument = expression.argument.transform(this, null) + ) + + override fun visitClassReference(expression: IrClassReference) = + callGetKClass( + returnType = expression.type, + typeArgument = expression.classType, + argument = callJsClass(expression.classType) + ) + }) + } +} + diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/IntrinsicifyCallsLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/IntrinsicifyCallsLowering.kt index cfa3d8b348a..a6dc3451a8e 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/IntrinsicifyCallsLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/IntrinsicifyCallsLowering.kt @@ -325,9 +325,10 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL // assignment to a property IrStatementOrigin.EQ -> { - val fieldSymbol = IrFieldSymbolImpl((symbol.descriptor as PropertyAccessorDescriptor).correspondingProperty) - return JsIrBuilder.buildSetField(fieldSymbol, call.dispatchReceiver, call.getValueArgument(0)!!, call.type) - + if (symbol.descriptor is PropertyAccessorDescriptor) { + val fieldSymbol = IrFieldSymbolImpl((symbol.descriptor as PropertyAccessorDescriptor).correspondingProperty) + return JsIrBuilder.buildSetField(fieldSymbol, call.dispatchReceiver, call.getValueArgument(0)!!, call.type) + } } } } 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 e81ce016d43..597cd5572c3 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 @@ -50,7 +50,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { private val instanceOfIntrinsicSymbol = context.intrinsics.jsInstanceOf.symbol private val typeOfIntrinsicSymbol = context.intrinsics.jsTypeOf.symbol - private val toJSTypeIntrinsicSymbol = context.intrinsics.jsToJsType.symbol + private val jsClassIntrinsicSymbol = context.intrinsics.jsClass private val stringMarker = JsIrBuilder.buildString(context.irBuiltIns.stringType, "string") private val booleanMarker = JsIrBuilder.buildString(context.irBuiltIns.stringType, "boolean") @@ -241,13 +241,14 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass { } private fun wrapTypeReference(toType: IrType) = - JsIrBuilder.buildCall(toJSTypeIntrinsicSymbol).apply { putTypeArgument(0, toType) } + JsIrBuilder.buildCall(jsClassIntrinsicSymbol).apply { putTypeArgument(0, toType) } private fun generateGenericArrayCheck(argument: IrExpression) = JsIrBuilder.buildCall(isArraySymbol).apply { putValueArgument(0, argument) } private fun generatePrimitiveArrayTypeCheck(argument: IrExpression, toType: IrType): IrExpression { - TODO("Implement Typed Array check") + val f = context.intrinsics.isPrimitiveArray[toType.getPrimitiveArrayElementType()]!! + return JsIrBuilder.buildCall(f).apply { putValueArgument(0, argument) } } private fun generateInterfaceCheck(argument: IrExpression, toType: IrType): IrExpression { diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsClassGenerator.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsClassGenerator.kt index cbc9f1b301f..018e2cf93de 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsClassGenerator.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsClassGenerator.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.ir.types.classifierOrFail import org.jetbrains.kotlin.ir.types.isAny import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.isInterface +import org.jetbrains.kotlin.ir.util.isObject import org.jetbrains.kotlin.ir.util.isReal import org.jetbrains.kotlin.ir.util.resolveFakeOverride import org.jetbrains.kotlin.js.backend.ast.* @@ -158,6 +159,15 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo metadataLiteral.propertyInitializers += simpleNameProp } + val classKind = JsStringLiteral( + when { + irClass.isInterface -> "interface" + irClass.isObject -> "object" + else -> "class" + } + ) + metadataLiteral.propertyInitializers += JsPropertyInitializer(JsNameRef(Namer.METADATA_CLASS_KIND), classKind) + metadataLiteral.propertyInitializers += generateSuperClasses() return jsAssignment(JsNameRef(Namer.METADATA, classNameRef), metadataLiteral).makeStmt() } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt index ab680f21842..4aed1bb5d9d 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt @@ -90,7 +90,7 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) { jsAssignment(JsNameRef(fieldNameLiteral, receiver), fieldValue) } - add(intrinsics.jsToJsType) { call, context -> + add(intrinsics.jsClass) { call, context -> val typeName = context.getNameForSymbol(call.getTypeArgument(0)!!.classifierOrFail) typeName.makeRef() } diff --git a/compiler/testData/codegen/box/binaryOp/kt11163.kt b/compiler/testData/codegen/box/binaryOp/kt11163.kt index 4e051a61be1..6a20534e140 100644 --- a/compiler/testData/codegen/box/binaryOp/kt11163.kt +++ b/compiler/testData/codegen/box/binaryOp/kt11163.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR operator fun Int.compareTo(c: Char) = 0 fun foo(x: Int, y: Char): String { diff --git a/compiler/testData/codegen/box/binaryOp/kt11163_properIeee754comparisons.kt b/compiler/testData/codegen/box/binaryOp/kt11163_properIeee754comparisons.kt index 7d1c0c03db6..b89e8ac39ce 100644 --- a/compiler/testData/codegen/box/binaryOp/kt11163_properIeee754comparisons.kt +++ b/compiler/testData/codegen/box/binaryOp/kt11163_properIeee754comparisons.kt @@ -1,5 +1,4 @@ // !LANGUAGE: +ProperIeee754Comparisons -// IGNORE_BACKEND: JS_IR operator fun Int.compareTo(c: Char) = 0 fun foo(x: Int, y: Char): String { diff --git a/compiler/testData/codegen/box/binaryOp/kt23030_properIeee754comparisons.kt b/compiler/testData/codegen/box/binaryOp/kt23030_properIeee754comparisons.kt index cd1c9570182..6b80dab5ba0 100644 --- a/compiler/testData/codegen/box/binaryOp/kt23030_properIeee754comparisons.kt +++ b/compiler/testData/codegen/box/binaryOp/kt23030_properIeee754comparisons.kt @@ -1,5 +1,4 @@ // !LANGUAGE: +ProperIeee754Comparisons -// IGNORE_BACKEND: JS_IR class C { operator fun Int.compareTo(c: Char) = 0 diff --git a/compiler/testData/codegen/box/boxingOptimization/kt5844.kt b/compiler/testData/codegen/box/boxingOptimization/kt5844.kt index a45c0b64871..acc4da5c729 100644 --- a/compiler/testData/codegen/box/boxingOptimization/kt5844.kt +++ b/compiler/testData/codegen/box/boxingOptimization/kt5844.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // WITH_RUNTIME import kotlin.test.assertEquals diff --git a/compiler/testData/codegen/box/callableReference/bound/genericValOnLHS.kt b/compiler/testData/codegen/box/callableReference/bound/genericValOnLHS.kt index 9ba998b1a3b..43c649e6923 100644 --- a/compiler/testData/codegen/box/callableReference/bound/genericValOnLHS.kt +++ b/compiler/testData/codegen/box/callableReference/bound/genericValOnLHS.kt @@ -1,5 +1,4 @@ // IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND: JS_IR // IGNORE_BACKEND: NATIVE class Generic

(val p: P) diff --git a/compiler/testData/codegen/box/callableReference/bound/smartCastForExtensionReceiver.kt b/compiler/testData/codegen/box/callableReference/bound/smartCastForExtensionReceiver.kt index f7d51aded17..c48830488c4 100644 --- a/compiler/testData/codegen/box/callableReference/bound/smartCastForExtensionReceiver.kt +++ b/compiler/testData/codegen/box/callableReference/bound/smartCastForExtensionReceiver.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR class B fun B.magic() { diff --git a/compiler/testData/codegen/box/callableReference/property/privateSetterOutsideClass.kt b/compiler/testData/codegen/box/callableReference/property/privateSetterOutsideClass.kt index 20fcce4b3ca..c13582000e5 100644 --- a/compiler/testData/codegen/box/callableReference/property/privateSetterOutsideClass.kt +++ b/compiler/testData/codegen/box/callableReference/property/privateSetterOutsideClass.kt @@ -1,5 +1,4 @@ // IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND: JS_IR // See KT-12337 Reference to property with invisible setter should not be a KMutableProperty import kotlin.reflect.KProperty1 diff --git a/compiler/testData/codegen/box/classLiteral/bound/smartCast.kt b/compiler/testData/codegen/box/classLiteral/bound/smartCast.kt index fd2fe866997..f7832e00d15 100644 --- a/compiler/testData/codegen/box/classLiteral/bound/smartCast.kt +++ b/compiler/testData/codegen/box/classLiteral/bound/smartCast.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // IGNORE_BACKEND: NATIVE // KT-16291 Smart cast doesn't work when getting class of instance diff --git a/compiler/testData/codegen/box/closures/capturedVarsOptimization/capturedInInlineOnlyAssign.kt b/compiler/testData/codegen/box/closures/capturedVarsOptimization/capturedInInlineOnlyAssign.kt index a6012c931ab..5faf6875838 100644 --- a/compiler/testData/codegen/box/closures/capturedVarsOptimization/capturedInInlineOnlyAssign.kt +++ b/compiler/testData/codegen/box/closures/capturedVarsOptimization/capturedInInlineOnlyAssign.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // WITH_RUNTIME fun box(): String { diff --git a/compiler/testData/codegen/box/closures/capturedVarsOptimization/capturedInInlineOnlyCAO.kt b/compiler/testData/codegen/box/closures/capturedVarsOptimization/capturedInInlineOnlyCAO.kt index 6ceddee94e9..0f62af3ed4d 100644 --- a/compiler/testData/codegen/box/closures/capturedVarsOptimization/capturedInInlineOnlyCAO.kt +++ b/compiler/testData/codegen/box/closures/capturedVarsOptimization/capturedInInlineOnlyCAO.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // WITH_RUNTIME fun box(): String { diff --git a/compiler/testData/codegen/box/closures/capturedVarsOptimization/capturedInInlineOnlyIncrDecr.kt b/compiler/testData/codegen/box/closures/capturedVarsOptimization/capturedInInlineOnlyIncrDecr.kt index dd67c7940eb..c8d5c31083e 100644 --- a/compiler/testData/codegen/box/closures/capturedVarsOptimization/capturedInInlineOnlyIncrDecr.kt +++ b/compiler/testData/codegen/box/closures/capturedVarsOptimization/capturedInInlineOnlyIncrDecr.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // WITH_RUNTIME fun box(): String { diff --git a/compiler/testData/codegen/box/closures/capturedVarsOptimization/capturedInInlineOnlyIndexedCAO.kt b/compiler/testData/codegen/box/closures/capturedVarsOptimization/capturedInInlineOnlyIndexedCAO.kt index 53bbbdc0f1b..44e0531c7b7 100644 --- a/compiler/testData/codegen/box/closures/capturedVarsOptimization/capturedInInlineOnlyIndexedCAO.kt +++ b/compiler/testData/codegen/box/closures/capturedVarsOptimization/capturedInInlineOnlyIndexedCAO.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // WITH_RUNTIME class Host(var value: String) { diff --git a/compiler/testData/codegen/box/closures/capturedVarsOptimization/capturedVarsOfSize2.kt b/compiler/testData/codegen/box/closures/capturedVarsOptimization/capturedVarsOfSize2.kt index cc711d0dd81..10f31cbc43a 100644 --- a/compiler/testData/codegen/box/closures/capturedVarsOptimization/capturedVarsOfSize2.kt +++ b/compiler/testData/codegen/box/closures/capturedVarsOptimization/capturedVarsOfSize2.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // WITH_RUNTIME fun box(): String { diff --git a/compiler/testData/codegen/box/closures/capturedVarsOptimization/kt17588.kt b/compiler/testData/codegen/box/closures/capturedVarsOptimization/kt17588.kt index 83089eae129..b7a8b8ed808 100644 --- a/compiler/testData/codegen/box/closures/capturedVarsOptimization/kt17588.kt +++ b/compiler/testData/codegen/box/closures/capturedVarsOptimization/kt17588.kt @@ -1,5 +1,4 @@ // IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND: JS_IR //WITH_RUNTIME class Test { diff --git a/compiler/testData/codegen/box/closures/capturedVarsOptimization/sharedSlotsWithCapturedVars.kt b/compiler/testData/codegen/box/closures/capturedVarsOptimization/sharedSlotsWithCapturedVars.kt index 0e6077860c1..0b2fcdbb0c3 100644 --- a/compiler/testData/codegen/box/closures/capturedVarsOptimization/sharedSlotsWithCapturedVars.kt +++ b/compiler/testData/codegen/box/closures/capturedVarsOptimization/sharedSlotsWithCapturedVars.kt @@ -1,5 +1,4 @@ // IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND: JS_IR // WITH_RUNTIME fun box(): String { diff --git a/compiler/testData/codegen/box/defaultArguments/kt6382.kt b/compiler/testData/codegen/box/defaultArguments/kt6382.kt index e9cee253e12..d7ce755d751 100644 --- a/compiler/testData/codegen/box/defaultArguments/kt6382.kt +++ b/compiler/testData/codegen/box/defaultArguments/kt6382.kt @@ -1,5 +1,4 @@ // IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND: JS_IR // WITH_RUNTIME fun box(): String { diff --git a/compiler/testData/codegen/box/enum/kt20651_inlineLambda.kt b/compiler/testData/codegen/box/enum/kt20651_inlineLambda.kt index 6a82510222c..41697c5dced 100644 --- a/compiler/testData/codegen/box/enum/kt20651_inlineLambda.kt +++ b/compiler/testData/codegen/box/enum/kt20651_inlineLambda.kt @@ -1,5 +1,4 @@ // IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND: JS_IR enum class Test(val x: String, val closure1: () -> String) { FOO("O", run { { FOO.x } }) { override val y: String = "K" diff --git a/compiler/testData/codegen/box/enum/kt7257.kt b/compiler/testData/codegen/box/enum/kt7257.kt index a1680cffa34..e2fe684b5e1 100644 --- a/compiler/testData/codegen/box/enum/kt7257.kt +++ b/compiler/testData/codegen/box/enum/kt7257.kt @@ -1,5 +1,4 @@ // IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND: JS_IR enum class X { B { val value2 = "K" diff --git a/compiler/testData/codegen/box/extensionFunctions/kt13312.kt b/compiler/testData/codegen/box/extensionFunctions/kt13312.kt index 4109d0d3bd4..097fa273eb5 100644 --- a/compiler/testData/codegen/box/extensionFunctions/kt13312.kt +++ b/compiler/testData/codegen/box/extensionFunctions/kt13312.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR fun test1(f: (Int) -> Int) = f(1) fun test2(f: Int.() -> Int) = 2.f() diff --git a/compiler/testData/codegen/box/functions/localFunctions/localFunctionVsLocalVariable.kt b/compiler/testData/codegen/box/functions/localFunctions/localFunctionVsLocalVariable.kt index 5bdd069ab94..df58363773a 100644 --- a/compiler/testData/codegen/box/functions/localFunctions/localFunctionVsLocalVariable.kt +++ b/compiler/testData/codegen/box/functions/localFunctions/localFunctionVsLocalVariable.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR fun box(): String { var s = "" var foo = "O" diff --git a/compiler/testData/codegen/box/functions/localFunctions/overloadedLocalFunWithoutClosure.kt b/compiler/testData/codegen/box/functions/localFunctions/overloadedLocalFunWithoutClosure.kt index e712b0ec7e6..078f029fe75 100644 --- a/compiler/testData/codegen/box/functions/localFunctions/overloadedLocalFunWithoutClosure.kt +++ b/compiler/testData/codegen/box/functions/localFunctions/overloadedLocalFunWithoutClosure.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR fun box(): String { fun foo(x: String) = x fun foo() = foo("K") diff --git a/compiler/testData/codegen/box/functions/localFunctions/overloadedLocalFunction.kt b/compiler/testData/codegen/box/functions/localFunctions/overloadedLocalFunction.kt index 5cc89458912..6e349f27ae9 100644 --- a/compiler/testData/codegen/box/functions/localFunctions/overloadedLocalFunction.kt +++ b/compiler/testData/codegen/box/functions/localFunctions/overloadedLocalFunction.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR fun box(): String { var s = "" diff --git a/compiler/testData/codegen/box/functions/localFunctions/overloadedLocalFunction1.kt b/compiler/testData/codegen/box/functions/localFunctions/overloadedLocalFunction1.kt index 5644fa417c9..79645a8716d 100644 --- a/compiler/testData/codegen/box/functions/localFunctions/overloadedLocalFunction1.kt +++ b/compiler/testData/codegen/box/functions/localFunctions/overloadedLocalFunction1.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR fun box(): String { var s = "" var foo = "K" diff --git a/compiler/testData/codegen/box/functions/localFunctions/overloadedLocalFunction3.kt b/compiler/testData/codegen/box/functions/localFunctions/overloadedLocalFunction3.kt index b790c538740..9504e6ebfac 100644 --- a/compiler/testData/codegen/box/functions/localFunctions/overloadedLocalFunction3.kt +++ b/compiler/testData/codegen/box/functions/localFunctions/overloadedLocalFunction3.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR fun box(): String { var s = "" var foo = "O" diff --git a/compiler/testData/codegen/box/inlineClasses/castInsideWhenExpression.kt b/compiler/testData/codegen/box/inlineClasses/castInsideWhenExpression.kt index 88f6a6bd9dc..010b8437e25 100644 --- a/compiler/testData/codegen/box/inlineClasses/castInsideWhenExpression.kt +++ b/compiler/testData/codegen/box/inlineClasses/castInsideWhenExpression.kt @@ -1,6 +1,5 @@ // !LANGUAGE: +InlineClasses // IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND: JS_IR inline class Foo(val x: Any) { fun bar() {} diff --git a/compiler/testData/codegen/box/inlineClasses/kt25771.kt b/compiler/testData/codegen/box/inlineClasses/kt25771.kt index 83bd568a02e..413f4d8af91 100644 --- a/compiler/testData/codegen/box/inlineClasses/kt25771.kt +++ b/compiler/testData/codegen/box/inlineClasses/kt25771.kt @@ -1,5 +1,5 @@ // !LANGUAGE: +InlineClasses -// IGNORE_BACKEND: JVM_IR, JS_IR +// IGNORE_BACKEND: JVM_IR inline class SuccessOrFailure(val value: Any?) { val isFailure: Boolean get() = value is Failure diff --git a/compiler/testData/codegen/box/objects/selfReferenceToCompanionObjectInInlineLambdaInSuperConstructorCall.kt b/compiler/testData/codegen/box/objects/selfReferenceToCompanionObjectInInlineLambdaInSuperConstructorCall.kt index 4f8d39ba151..fc2a08dd42e 100644 --- a/compiler/testData/codegen/box/objects/selfReferenceToCompanionObjectInInlineLambdaInSuperConstructorCall.kt +++ b/compiler/testData/codegen/box/objects/selfReferenceToCompanionObjectInInlineLambdaInSuperConstructorCall.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR abstract class Base(val fn: () -> String) class Host { diff --git a/compiler/testData/codegen/box/objects/selfReferenceToInterfaceCompanionObjectInInlineLambdaInSuperConstructorCall.kt b/compiler/testData/codegen/box/objects/selfReferenceToInterfaceCompanionObjectInInlineLambdaInSuperConstructorCall.kt index 26ee4696345..226506094b2 100644 --- a/compiler/testData/codegen/box/objects/selfReferenceToInterfaceCompanionObjectInInlineLambdaInSuperConstructorCall.kt +++ b/compiler/testData/codegen/box/objects/selfReferenceToInterfaceCompanionObjectInInlineLambdaInSuperConstructorCall.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR abstract class Base(val fn: () -> String) interface Host { diff --git a/compiler/testData/codegen/box/objects/selfReferenceToObjectInInlineLambdaInSuperConstructorCall.kt b/compiler/testData/codegen/box/objects/selfReferenceToObjectInInlineLambdaInSuperConstructorCall.kt index 09ae203fcaa..045499084e6 100644 --- a/compiler/testData/codegen/box/objects/selfReferenceToObjectInInlineLambdaInSuperConstructorCall.kt +++ b/compiler/testData/codegen/box/objects/selfReferenceToObjectInInlineLambdaInSuperConstructorCall.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR abstract class Base(val fn: () -> String) object Test : Base(run { { Test.ok() } }) { diff --git a/compiler/testData/codegen/box/properties/lateinit/local/localLateinit.kt b/compiler/testData/codegen/box/properties/lateinit/local/localLateinit.kt index f7ad98f3b72..bb68d6f3f3e 100644 --- a/compiler/testData/codegen/box/properties/lateinit/local/localLateinit.kt +++ b/compiler/testData/codegen/box/properties/lateinit/local/localLateinit.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // LANGUAGE_VERSION: 1.2 fun box(): String { diff --git a/compiler/testData/codegen/box/ranges/forInDownTo/forIntInDownTo.kt b/compiler/testData/codegen/box/ranges/forInDownTo/forIntInDownTo.kt index 299f8601187..fd046640e37 100644 --- a/compiler/testData/codegen/box/ranges/forInDownTo/forIntInDownTo.kt +++ b/compiler/testData/codegen/box/ranges/forInDownTo/forIntInDownTo.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // WITH_RUNTIME import kotlin.test.assertEquals diff --git a/compiler/testData/codegen/box/ranges/forInUntil/forInUntilChar0.kt b/compiler/testData/codegen/box/ranges/forInUntil/forInUntilChar0.kt index ca8bfb7bbd2..5b7357ba109 100644 --- a/compiler/testData/codegen/box/ranges/forInUntil/forInUntilChar0.kt +++ b/compiler/testData/codegen/box/ranges/forInUntil/forInUntilChar0.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // WITH_RUNTIME import kotlin.test.assertEquals diff --git a/compiler/testData/codegen/box/ranges/forWithPossibleOverflow/forInDownToCharMinValue.kt b/compiler/testData/codegen/box/ranges/forWithPossibleOverflow/forInDownToCharMinValue.kt index 0ab72900b67..4af3c19ea1b 100644 --- a/compiler/testData/codegen/box/ranges/forWithPossibleOverflow/forInDownToCharMinValue.kt +++ b/compiler/testData/codegen/box/ranges/forWithPossibleOverflow/forInDownToCharMinValue.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // WITH_RUNTIME const val M = 0.toChar() diff --git a/compiler/testData/codegen/box/reflection/classLiterals/annotationClassLiteral.kt b/compiler/testData/codegen/box/reflection/classLiterals/annotationClassLiteral.kt index 2ffaf8b328f..28d5dd9a046 100644 --- a/compiler/testData/codegen/box/reflection/classLiterals/annotationClassLiteral.kt +++ b/compiler/testData/codegen/box/reflection/classLiterals/annotationClassLiteral.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // TODO: muted automatically, investigate should it be ran for JS or not // IGNORE_BACKEND: JS, NATIVE diff --git a/compiler/testData/codegen/box/reflection/classLiterals/genericClass.kt b/compiler/testData/codegen/box/reflection/classLiterals/genericClass.kt index 08a28febdbd..5c0fabfb976 100644 --- a/compiler/testData/codegen/box/reflection/classLiterals/genericClass.kt +++ b/compiler/testData/codegen/box/reflection/classLiterals/genericClass.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // IGNORE_BACKEND: NATIVE // WITH_REFLECT diff --git a/compiler/testData/codegen/box/reflection/classLiterals/simpleClassLiteral.kt b/compiler/testData/codegen/box/reflection/classLiterals/simpleClassLiteral.kt index e5beacdd1cf..966c774df65 100644 --- a/compiler/testData/codegen/box/reflection/classLiterals/simpleClassLiteral.kt +++ b/compiler/testData/codegen/box/reflection/classLiterals/simpleClassLiteral.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // IGNORE_BACKEND: NATIVE // WITH_REFLECT diff --git a/compiler/testData/codegen/box/reflection/classes/localClassSimpleName.kt b/compiler/testData/codegen/box/reflection/classes/localClassSimpleName.kt index a82b22bda4f..e39a2d551c9 100644 --- a/compiler/testData/codegen/box/reflection/classes/localClassSimpleName.kt +++ b/compiler/testData/codegen/box/reflection/classes/localClassSimpleName.kt @@ -1,5 +1,4 @@ // IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND: JS_IR // IGNORE_BACKEND: NATIVE // WITH_REFLECT diff --git a/compiler/testData/codegen/box/regressions/intersectionOfEqualTypes.kt b/compiler/testData/codegen/box/regressions/intersectionOfEqualTypes.kt index fd446f722cb..220d3759335 100644 --- a/compiler/testData/codegen/box/regressions/intersectionOfEqualTypes.kt +++ b/compiler/testData/codegen/box/regressions/intersectionOfEqualTypes.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // WITH_RUNTIME // FILE: test.kt diff --git a/compiler/testData/codegen/box/regressions/kt5786_privateWithDefault.kt b/compiler/testData/codegen/box/regressions/kt5786_privateWithDefault.kt index a8dfcf9be56..916ed482c60 100644 --- a/compiler/testData/codegen/box/regressions/kt5786_privateWithDefault.kt +++ b/compiler/testData/codegen/box/regressions/kt5786_privateWithDefault.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // WITH_RUNTIME fun box(): String { diff --git a/compiler/testData/codegen/box/regressions/lambdaAsLastExpressionInLambda.kt b/compiler/testData/codegen/box/regressions/lambdaAsLastExpressionInLambda.kt index da98e00762d..05336badb47 100644 --- a/compiler/testData/codegen/box/regressions/lambdaAsLastExpressionInLambda.kt +++ b/compiler/testData/codegen/box/regressions/lambdaAsLastExpressionInLambda.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR val foo: ((String) -> String) = run { { it } } diff --git a/compiler/testData/codegen/box/regressions/lambdaWrongReturnType.kt b/compiler/testData/codegen/box/regressions/lambdaWrongReturnType.kt index 01910008ab2..b60e314e0fb 100644 --- a/compiler/testData/codegen/box/regressions/lambdaWrongReturnType.kt +++ b/compiler/testData/codegen/box/regressions/lambdaWrongReturnType.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR fun test() = foo({ line: String -> line }) fun foo(x: T): T = TODO() diff --git a/compiler/testData/codegen/box/secondaryConstructors/withNonLocalReturn.kt b/compiler/testData/codegen/box/secondaryConstructors/withNonLocalReturn.kt index 8901803ee51..8d335594840 100644 --- a/compiler/testData/codegen/box/secondaryConstructors/withNonLocalReturn.kt +++ b/compiler/testData/codegen/box/secondaryConstructors/withNonLocalReturn.kt @@ -1,12 +1,12 @@ // IGNORE_BACKEND: JVM_IR -inline fun run(block: () -> Unit) = block() +inline fun run2(block: () -> Unit) = block() class A { val prop: Int constructor(arg: Boolean) { if (arg) { prop = 1 - run { return } + run2 { return } throw RuntimeException("fail 0") } prop = 2 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 c0431da232c..b979b08f1d3 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 @@ -5,10 +5,7 @@ package org.jetbrains.kotlin.js.test -import org.jetbrains.kotlin.config.ApiVersion -import org.jetbrains.kotlin.config.LanguageVersion -import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl -import org.jetbrains.kotlin.config.languageVersionSettings +import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.ir.backend.js.Result import org.jetbrains.kotlin.ir.backend.js.compile import org.jetbrains.kotlin.js.config.JsConfig @@ -24,9 +21,11 @@ private val runtimeSources = listOfKtFilesFrom( "libraries/stdlib/js/src/kotlin/jsTypeOf.kt", "libraries/stdlib/js/src/kotlin/dynamic.kt", "libraries/stdlib/js/src/kotlin/annotations.kt", + "libraries/stdlib/js/src/kotlin/reflect", + "libraries/stdlib/js/src/kotlin/annotationsJVM.kt", - "libraries/stdlib/src/kotlin/internal/Annotations.kt", - + "libraries/stdlib/src/kotlin/internal", + "libraries/stdlib/src/kotlin/util/Standard.kt", "core/builtins/native/kotlin/Annotation.kt", "core/builtins/native/kotlin/Number.kt", "core/builtins/native/kotlin/Comparable.kt", @@ -39,9 +38,14 @@ private val runtimeSources = listOfKtFilesFrom( "core/builtins/src/kotlin/Range.kt", "core/builtins/src/kotlin/Ranges.kt", "core/builtins/src/kotlin/Unit.kt", + "core/builtins/src/kotlin/reflect", + "core/builtins/src/kotlin/Function.kt", + "core/builtins/native/kotlin/Collections.kt", "core/builtins/native/kotlin/Iterator.kt", + "libraries/stdlib/common/src/kotlin/JvmAnnotationsH.kt", + "libraries/stdlib/js/irRuntime", BasicBoxTest.COMMON_FILES_DIR_PATH ) @@ -85,13 +89,20 @@ abstract class BasicIrBoxTest( // TODO: split input files to some parts (global common, local common, test) .filterNot { it.virtualFilePath.contains(BasicBoxTest.COMMON_FILES_DIR_PATH) } + val runtimeConfiguration = config.configuration.copy() + + // TODO: is it right in general? Maybe sometimes we need to compile with newer versions or with additional language features. + runtimeConfiguration.languageVersionSettings = LanguageVersionSettingsImpl( + LanguageVersion.LATEST_STABLE, ApiVersion.LATEST_STABLE, + specificFeatures = mapOf( + LanguageFeature.AllowContractsForCustomFunctions to LanguageFeature.State.ENABLED, + LanguageFeature.MultiPlatformProjects to LanguageFeature.State.ENABLED + ) + ) + + if (runtimeResult == null) { - val myConfiguration = config.configuration.copy() - - // TODO: is it right in general? Maybe sometimes we need to compile with newer versions or with additional language features. - myConfiguration.languageVersionSettings = LanguageVersionSettingsImpl(LanguageVersion.LATEST_STABLE, ApiVersion.LATEST_STABLE) - - runtimeResult = compile(config.project, runtimeSources.map(::createPsiFile), myConfiguration) + runtimeResult = compile(config.project, runtimeSources.map(::createPsiFile), runtimeConfiguration) runtimeFile.write(runtimeResult!!.generatedCode) } @@ -101,7 +112,7 @@ abstract class BasicIrBoxTest( compile( config.project, allFiles, - config.configuration, + runtimeConfiguration, FqName((testPackage?.let { "$it." } ?: "") + testFunction)) } else { compile( diff --git a/js/js.translator/testData/box/char/charInStringTemplate.kt b/js/js.translator/testData/box/char/charInStringTemplate.kt index c0fc9aabaf3..692e44ee9d4 100644 --- a/js/js.translator/testData/box/char/charInStringTemplate.kt +++ b/js/js.translator/testData/box/char/charInStringTemplate.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1114 package foo import kotlin.test.assertEquals diff --git a/js/js.translator/testData/box/expression/cast/checkThrowCCE.kt b/js/js.translator/testData/box/expression/cast/checkThrowCCE.kt index 696a5cd5c83..b5dd7fc5c84 100644 --- a/js/js.translator/testData/box/expression/cast/checkThrowCCE.kt +++ b/js/js.translator/testData/box/expression/cast/checkThrowCCE.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1094 package foo diff --git a/js/js.translator/testData/box/inline/extension.kt b/js/js.translator/testData/box/inline/extension.kt index 52da85d906c..45ffb0f961d 100644 --- a/js/js.translator/testData/box/inline/extension.kt +++ b/js/js.translator/testData/box/inline/extension.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1122 /* * Copy of JVM-backend test diff --git a/js/js.translator/testData/box/inlineMultiFile/with.kt b/js/js.translator/testData/box/inlineMultiFile/with.kt index ada6e75ff1c..170c114c1a5 100644 --- a/js/js.translator/testData/box/inlineMultiFile/with.kt +++ b/js/js.translator/testData/box/inlineMultiFile/with.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1131 /* * Copy of JVM-backend test diff --git a/js/js.translator/testData/box/inlineStdlib/callNameClash.kt b/js/js.translator/testData/box/inlineStdlib/callNameClash.kt index ddb313438f4..bf20a5b606a 100644 --- a/js/js.translator/testData/box/inlineStdlib/callNameClash.kt +++ b/js/js.translator/testData/box/inlineStdlib/callNameClash.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1127 package foo diff --git a/js/js.translator/testData/box/inlineStdlib/localNamesClash.kt b/js/js.translator/testData/box/inlineStdlib/localNamesClash.kt index 56242775bdc..d20bc11d2ba 100644 --- a/js/js.translator/testData/box/inlineStdlib/localNamesClash.kt +++ b/js/js.translator/testData/box/inlineStdlib/localNamesClash.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1115 package foo diff --git a/js/js.translator/testData/box/inlineStdlib/thisInExtension.kt b/js/js.translator/testData/box/inlineStdlib/thisInExtension.kt index de98098a983..3199c05d385 100644 --- a/js/js.translator/testData/box/inlineStdlib/thisInExtension.kt +++ b/js/js.translator/testData/box/inlineStdlib/thisInExtension.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1116 package foo diff --git a/js/js.translator/testData/box/labels/labelOnExpression.kt b/js/js.translator/testData/box/labels/labelOnExpression.kt index 4a9c7d9b59c..f74cb90b0fe 100644 --- a/js/js.translator/testData/box/labels/labelOnExpression.kt +++ b/js/js.translator/testData/box/labels/labelOnExpression.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1122 // CHECK_LABELS_COUNT: function=test0 count=0 // CHECK_LABELS_COUNT: function=test1 count=0 diff --git a/js/js.translator/testData/box/nameClashes/withBuiltin.kt b/js/js.translator/testData/box/nameClashes/withBuiltin.kt index 5e460d5ae92..3aa7c039f0a 100644 --- a/js/js.translator/testData/box/nameClashes/withBuiltin.kt +++ b/js/js.translator/testData/box/nameClashes/withBuiltin.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1135 open class C { private fun constructor() = "C.constructor" diff --git a/js/js.translator/testData/box/native/nativeClassAsReifiedTypeArgument.kt b/js/js.translator/testData/box/native/nativeClassAsReifiedTypeArgument.kt index 7db8fd21144..6b8f9bdf42c 100644 --- a/js/js.translator/testData/box/native/nativeClassAsReifiedTypeArgument.kt +++ b/js/js.translator/testData/box/native/nativeClassAsReifiedTypeArgument.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1111 //FILE: nativeClassAsReifiedTypeArgument.kt diff --git a/js/js.translator/testData/box/reflection/external.kt b/js/js.translator/testData/box/reflection/external.kt index 22c1d08a3c0..07060d59df5 100644 --- a/js/js.translator/testData/box/reflection/external.kt +++ b/js/js.translator/testData/box/reflection/external.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1099 external class A diff --git a/js/js.translator/testData/box/reflection/jsClass.kt b/js/js.translator/testData/box/reflection/jsClass.kt index 9b116cf9310..f4d1ebf6213 100644 --- a/js/js.translator/testData/box/reflection/jsClass.kt +++ b/js/js.translator/testData/box/reflection/jsClass.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1169 package foo diff --git a/js/js.translator/testData/box/reflection/jsClassOnReifiedType.kt b/js/js.translator/testData/box/reflection/jsClassOnReifiedType.kt index 81809b83425..8488e739897 100644 --- a/js/js.translator/testData/box/reflection/jsClassOnReifiedType.kt +++ b/js/js.translator/testData/box/reflection/jsClassOnReifiedType.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1165 package foo diff --git a/js/js.translator/testData/box/reflection/jsClassSimpleName.kt b/js/js.translator/testData/box/reflection/jsClassSimpleName.kt index c4af2d1cf8a..a96013539d3 100644 --- a/js/js.translator/testData/box/reflection/jsClassSimpleName.kt +++ b/js/js.translator/testData/box/reflection/jsClassSimpleName.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1177 package foo diff --git a/js/js.translator/testData/box/reflection/kClass.kt b/js/js.translator/testData/box/reflection/kClass.kt index 9b4c21439c8..74df1aff4fd 100644 --- a/js/js.translator/testData/box/reflection/kClass.kt +++ b/js/js.translator/testData/box/reflection/kClass.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1168 package foo diff --git a/js/js.translator/testData/box/reflection/kClassIsInstance.kt b/js/js.translator/testData/box/reflection/kClassIsInstance.kt index f682f74095b..ce9a101aae4 100644 --- a/js/js.translator/testData/box/reflection/kClassIsInstance.kt +++ b/js/js.translator/testData/box/reflection/kClassIsInstance.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1177 package foo diff --git a/js/js.translator/testData/box/reflection/kClassOnReifiedType.kt b/js/js.translator/testData/box/reflection/kClassOnReifiedType.kt index de077cafcf2..cb2d9334a38 100644 --- a/js/js.translator/testData/box/reflection/kClassOnReifiedType.kt +++ b/js/js.translator/testData/box/reflection/kClassOnReifiedType.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1165 package foo diff --git a/js/js.translator/testData/box/reflection/kClassSimpleName.kt b/js/js.translator/testData/box/reflection/kClassSimpleName.kt index 54787b54663..a738bf277eb 100644 --- a/js/js.translator/testData/box/reflection/kClassSimpleName.kt +++ b/js/js.translator/testData/box/reflection/kClassSimpleName.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1177 package foo diff --git a/libraries/stdlib/js/irRuntime/exceptions.kt b/libraries/stdlib/js/irRuntime/exceptions.kt index 0b1e3fe53fd..07eccafec03 100644 --- a/libraries/stdlib/js/irRuntime/exceptions.kt +++ b/libraries/stdlib/js/irRuntime/exceptions.kt @@ -4,6 +4,12 @@ */ package kotlin +open class Error(override val message: String?, override val cause: Throwable?) : Throwable() { + constructor() : this(null, null) + constructor(_message: String?) : this(_message, null) + constructor(_cause: Throwable?) : this(null, _cause) +} + open class Exception(override val message: String?, override val cause: Throwable?) : Throwable() { constructor() : this(null, null) constructor(_message: String?) : this(_message, null) diff --git a/libraries/stdlib/js/irRuntime/hacks.kt b/libraries/stdlib/js/irRuntime/hacks.kt new file mode 100644 index 00000000000..738992ca2c0 --- /dev/null +++ b/libraries/stdlib/js/irRuntime/hacks.kt @@ -0,0 +1,27 @@ +/* + * 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 + +// TODO: Ignore FunctionN interfaces + +public interface Function0 : Function { + public operator fun invoke(): R +} + +public interface Function1 : Function { + public operator fun invoke(p1: P1): R +} + +public interface Function2 : Function { + public operator fun invoke(p1: P1, p2: P2): R +} + +public interface Function3 : Function { + public operator fun invoke(p1: P1, p2: P2, p3: P3): R +} + +public inline fun arrayOfNulls(size: Int): Array = js("[]") // FIXME: Implement + diff --git a/libraries/stdlib/js/irRuntime/rangeExtensions.kt b/libraries/stdlib/js/irRuntime/rangeExtensions.kt new file mode 100644 index 00000000000..fdf7681ca38 --- /dev/null +++ b/libraries/stdlib/js/irRuntime/rangeExtensions.kt @@ -0,0 +1,355 @@ +/* + * 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.ranges + +// FIXME: Use stdlib _Ranges.kt instead + +/** + * Returns a progression from this value down to the specified [to] value with the step -1. + * + * The [to] value should be less than or equal to `this` value. + * If the [to] value is greater than `this` value the returned progression is empty. + */ +public infix fun Int.downTo(to: Byte): IntProgression { + return IntProgression.fromClosedRange(this, to.toInt(), -1) +} + +/** + * Returns a progression from this value down to the specified [to] value with the step -1. + * + * The [to] value should be less than or equal to `this` value. + * If the [to] value is greater than `this` value the returned progression is empty. + */ +public infix fun Long.downTo(to: Byte): LongProgression { + return LongProgression.fromClosedRange(this, to.toLong(), -1L) +} + +/** + * Returns a progression from this value down to the specified [to] value with the step -1. + * + * The [to] value should be less than or equal to `this` value. + * If the [to] value is greater than `this` value the returned progression is empty. + */ +public infix fun Byte.downTo(to: Byte): IntProgression { + return IntProgression.fromClosedRange(this.toInt(), to.toInt(), -1) +} + +/** + * Returns a progression from this value down to the specified [to] value with the step -1. + * + * The [to] value should be less than or equal to `this` value. + * If the [to] value is greater than `this` value the returned progression is empty. + */ +public infix fun Short.downTo(to: Byte): IntProgression { + return IntProgression.fromClosedRange(this.toInt(), to.toInt(), -1) +} + +/** + * Returns a progression from this value down to the specified [to] value with the step -1. + * + * The [to] value should be less than or equal to `this` value. + * If the [to] value is greater than `this` value the returned progression is empty. + */ +public infix fun Char.downTo(to: Char): CharProgression { + return CharProgression.fromClosedRange(this, to, -1) +} + +/** + * Returns a progression from this value down to the specified [to] value with the step -1. + * + * The [to] value should be less than or equal to `this` value. + * If the [to] value is greater than `this` value the returned progression is empty. + */ +public infix fun Int.downTo(to: Int): IntProgression { + return IntProgression.fromClosedRange(this, to, -1) +} + +/** + * Returns a progression from this value down to the specified [to] value with the step -1. + * + * The [to] value should be less than or equal to `this` value. + * If the [to] value is greater than `this` value the returned progression is empty. + */ +public infix fun Long.downTo(to: Int): LongProgression { + return LongProgression.fromClosedRange(this, to.toLong(), -1L) +} + +/** + * Returns a progression from this value down to the specified [to] value with the step -1. + * + * The [to] value should be less than or equal to `this` value. + * If the [to] value is greater than `this` value the returned progression is empty. + */ +public infix fun Byte.downTo(to: Int): IntProgression { + return IntProgression.fromClosedRange(this.toInt(), to, -1) +} + +/** + * Returns a progression from this value down to the specified [to] value with the step -1. + * + * The [to] value should be less than or equal to `this` value. + * If the [to] value is greater than `this` value the returned progression is empty. + */ +public infix fun Short.downTo(to: Int): IntProgression { + return IntProgression.fromClosedRange(this.toInt(), to, -1) +} + +/** + * Returns a progression from this value down to the specified [to] value with the step -1. + * + * The [to] value should be less than or equal to `this` value. + * If the [to] value is greater than `this` value the returned progression is empty. + */ +public infix fun Int.downTo(to: Long): LongProgression { + return LongProgression.fromClosedRange(this.toLong(), to, -1L) +} + +/** + * Returns a progression from this value down to the specified [to] value with the step -1. + * + * The [to] value should be less than or equal to `this` value. + * If the [to] value is greater than `this` value the returned progression is empty. + */ +public infix fun Long.downTo(to: Long): LongProgression { + return LongProgression.fromClosedRange(this, to, -1L) +} + +/** + * Returns a progression from this value down to the specified [to] value with the step -1. + * + * The [to] value should be less than or equal to `this` value. + * If the [to] value is greater than `this` value the returned progression is empty. + */ +public infix fun Byte.downTo(to: Long): LongProgression { + return LongProgression.fromClosedRange(this.toLong(), to, -1L) +} + +/** + * Returns a progression from this value down to the specified [to] value with the step -1. + * + * The [to] value should be less than or equal to `this` value. + * If the [to] value is greater than `this` value the returned progression is empty. + */ +public infix fun Short.downTo(to: Long): LongProgression { + return LongProgression.fromClosedRange(this.toLong(), to, -1L) +} + +/** + * Returns a progression from this value down to the specified [to] value with the step -1. + * + * The [to] value should be less than or equal to `this` value. + * If the [to] value is greater than `this` value the returned progression is empty. + */ +public infix fun Int.downTo(to: Short): IntProgression { + return IntProgression.fromClosedRange(this, to.toInt(), -1) +} + +/** + * Returns a progression from this value down to the specified [to] value with the step -1. + * + * The [to] value should be less than or equal to `this` value. + * If the [to] value is greater than `this` value the returned progression is empty. + */ +public infix fun Long.downTo(to: Short): LongProgression { + return LongProgression.fromClosedRange(this, to.toLong(), -1L) +} + +/** + * Returns a progression from this value down to the specified [to] value with the step -1. + * + * The [to] value should be less than or equal to `this` value. + * If the [to] value is greater than `this` value the returned progression is empty. + */ +public infix fun Byte.downTo(to: Short): IntProgression { + return IntProgression.fromClosedRange(this.toInt(), to.toInt(), -1) +} + +/** + * Returns a progression from this value down to the specified [to] value with the step -1. + * + * The [to] value should be less than or equal to `this` value. + * If the [to] value is greater than `this` value the returned progression is empty. + */ +public infix fun Short.downTo(to: Short): IntProgression { + return IntProgression.fromClosedRange(this.toInt(), to.toInt(), -1) +} + +/** + * Returns a range from this value up to but excluding the specified [to] value. + * + * If the [to] value is less than or equal to `this` value the returned range is empty. + */ +public infix fun Int.until(to: Byte): IntRange { + return this .. (to.toInt() - 1).toInt() +} + +/** + * Returns a range from this value up to but excluding the specified [to] value. + * + * If the [to] value is less than or equal to `this` value the returned range is empty. + */ +public infix fun Long.until(to: Byte): LongRange { + return this .. (to.toLong() - 1).toLong() +} + +/** + * Returns a range from this value up to but excluding the specified [to] value. + * + * If the [to] value is less than or equal to `this` value the returned range is empty. + */ +public infix fun Byte.until(to: Byte): IntRange { + return this.toInt() .. (to.toInt() - 1).toInt() +} + +/** + * Returns a range from this value up to but excluding the specified [to] value. + * + * If the [to] value is less than or equal to `this` value the returned range is empty. + */ +public infix fun Short.until(to: Byte): IntRange { + return this.toInt() .. (to.toInt() - 1).toInt() +} + +/** + * Returns a range from this value up to but excluding the specified [to] value. + * + * If the [to] value is less than or equal to `this` value the returned range is empty. + * + * If the [to] value is less than or equal to `'\u0000'` the returned range is empty. + */ +public infix fun Char.until(to: Char): CharRange { + if (to <= '\u0000') return CharRange.EMPTY + return this .. (to - 1).toChar() +} + +/** + * Returns a range from this value up to but excluding the specified [to] value. + * + * If the [to] value is less than or equal to `this` value the returned range is empty. + * + * If the [to] value is less than or equal to [Int.MIN_VALUE] the returned range is empty. + */ +public infix fun Int.until(to: Int): IntRange { + if (to <= Int.MIN_VALUE) return IntRange.EMPTY + return this .. (to - 1).toInt() +} + +/** + * Returns a range from this value up to but excluding the specified [to] value. + * + * If the [to] value is less than or equal to `this` value the returned range is empty. + */ +public infix fun Long.until(to: Int): LongRange { + return this .. (to.toLong() - 1).toLong() +} + +/** + * Returns a range from this value up to but excluding the specified [to] value. + * + * If the [to] value is less than or equal to `this` value the returned range is empty. + * + * If the [to] value is less than or equal to [Int.MIN_VALUE] the returned range is empty. + */ +public infix fun Byte.until(to: Int): IntRange { + if (to <= Int.MIN_VALUE) return IntRange.EMPTY + return this.toInt() .. (to - 1).toInt() +} + +/** + * Returns a range from this value up to but excluding the specified [to] value. + * + * If the [to] value is less than or equal to `this` value the returned range is empty. + * + * If the [to] value is less than or equal to [Int.MIN_VALUE] the returned range is empty. + */ +public infix fun Short.until(to: Int): IntRange { + if (to <= Int.MIN_VALUE) return IntRange.EMPTY + return this.toInt() .. (to - 1).toInt() +} + +/** + * Returns a range from this value up to but excluding the specified [to] value. + * + * If the [to] value is less than or equal to `this` value the returned range is empty. + * + * If the [to] value is less than or equal to [Long.MIN_VALUE] the returned range is empty. + */ +public infix fun Int.until(to: Long): LongRange { + if (to <= Long.MIN_VALUE) return LongRange.EMPTY + return this.toLong() .. (to - 1).toLong() +} + +/** + * Returns a range from this value up to but excluding the specified [to] value. + * + * If the [to] value is less than or equal to `this` value the returned range is empty. + * + * If the [to] value is less than or equal to [Long.MIN_VALUE] the returned range is empty. + */ +public infix fun Long.until(to: Long): LongRange { + if (to <= Long.MIN_VALUE) return LongRange.EMPTY + return this .. (to - 1).toLong() +} + +/** + * Returns a range from this value up to but excluding the specified [to] value. + * + * If the [to] value is less than or equal to `this` value the returned range is empty. + * + * If the [to] value is less than or equal to [Long.MIN_VALUE] the returned range is empty. + */ +public infix fun Byte.until(to: Long): LongRange { + if (to <= Long.MIN_VALUE) return LongRange.EMPTY + return this.toLong() .. (to - 1).toLong() +} + +/** + * Returns a range from this value up to but excluding the specified [to] value. + * + * If the [to] value is less than or equal to `this` value the returned range is empty. + * + * If the [to] value is less than or equal to [Long.MIN_VALUE] the returned range is empty. + */ +public infix fun Short.until(to: Long): LongRange { + if (to <= Long.MIN_VALUE) return LongRange.EMPTY + return this.toLong() .. (to - 1).toLong() +} + +/** + * Returns a range from this value up to but excluding the specified [to] value. + * + * If the [to] value is less than or equal to `this` value the returned range is empty. + */ +public infix fun Int.until(to: Short): IntRange { + return this .. (to.toInt() - 1).toInt() +} + +/** + * Returns a range from this value up to but excluding the specified [to] value. + * + * If the [to] value is less than or equal to `this` value the returned range is empty. + */ +public infix fun Long.until(to: Short): LongRange { + return this .. (to.toLong() - 1).toLong() +} + +/** + * Returns a range from this value up to but excluding the specified [to] value. + * + * If the [to] value is less than or equal to `this` value the returned range is empty. + */ +public infix fun Byte.until(to: Short): IntRange { + return this.toInt() .. (to.toInt() - 1).toInt() +} + +/** + * Returns a range from this value up to but excluding the specified [to] value. + * + * If the [to] value is less than or equal to `this` value the returned range is empty. + */ +public infix fun Short.until(to: Short): IntRange { + return this.toInt() .. (to.toInt() - 1).toInt() +} diff --git a/libraries/stdlib/js/irRuntime/typeCheckUtils.kt b/libraries/stdlib/js/irRuntime/typeCheckUtils.kt index d1ac6d70099..9bffde33c60 100644 --- a/libraries/stdlib/js/irRuntime/typeCheckUtils.kt +++ b/libraries/stdlib/js/irRuntime/typeCheckUtils.kt @@ -74,6 +74,8 @@ public fun isInterface(ctor: dynamic, IType: dynamic): Boolean { fun typeOf(obj: dynamic) = js("typeof obj").unsafeCast() +fun instanceOf(obj: dynamic, jsClass: dynamic) = js("obj instanceof jsClass").unsafeCast() + fun isObject(obj: dynamic): Boolean { val objTypeOf = typeOf(obj) @@ -96,4 +98,54 @@ public fun isArrayish(o: dynamic) = public fun isChar(c: Any): Boolean { return js("throw Error(\"isChar is not implemented\")").unsafeCast() +} + +// TODO: Distinguish Boolean/Byte and Short/Char +public fun isBooleanArray(a: dynamic) = js("a instanceof Int8Array") +public fun isByteArray(a: dynamic) = js("a instanceof Int8Array") +public fun isShortArray(a: dynamic) = js("a instanceof Int16Array") +public fun isCharArray(a: dynamic) = js("a instanceof Uint16Array") +public fun isIntArray(a: dynamic) = js("a instanceof Int32Array") +public fun isFloatArray(a: dynamic) = js("a instanceof Float32Array") +public fun isDoubleArray(a: dynamic) = js("a instanceof Float64Array") +public fun isLongArray(a: dynamic) = isArray(a) // TODO: Implement + + +internal fun jsIn(x: String, y: dynamic): Boolean = js("x in y") +internal fun jsGetPrototypeOf(jsClass: dynamic) = js("Object.getPrototypeOf(jsClass)") + +public fun jsIsType(obj: dynamic, jsClass: dynamic): Boolean { + if (jsClass === js("Object")) { + return isObject(obj) + } + + if (obj == null || jsClass == null || (typeOf(obj) != "object" && typeOf(obj) != "function")) { + return false + } + + if (typeOf(jsClass) == "function" && instanceOf(obj, jsClass)) { + return true + } + + var proto = jsGetPrototypeOf(jsClass) + var constructor = proto?.constructor + if (constructor != null && jsIn("${'$'}metadata${'$'}", constructor)) { + var metadata = constructor.`$metadata$` + if (metadata.kind === "object") { + return obj === jsClass + } + } + + var klassMetadata = jsClass.`$metadata$` + + // In WebKit (JavaScriptCore) for some interfaces from DOM typeof returns "object", nevertheless they can be used in RHS of instanceof + if (klassMetadata == null) { + return instanceOf(obj, jsClass) + } + + if (klassMetadata.kind === "interface" && obj.constructor != null) { + return isInterfaceImpl(obj.constructor, jsClass) + } + + return false } \ No newline at end of file diff --git a/libraries/stdlib/js/src/kotlin/kotlin.kt b/libraries/stdlib/js/src/kotlin/kotlin.kt index 0e013f763b3..ab674b04e4a 100644 --- a/libraries/stdlib/js/src/kotlin/kotlin.kt +++ b/libraries/stdlib/js/src/kotlin/kotlin.kt @@ -98,3 +98,5 @@ internal inline fun copyArrayType(from: dynamic, to: dynamic) { to.`$type$` = from.`$type$` } } + +internal inline fun jsIsType(obj: dynamic, jsClass: dynamic) = js("Kotlin").isType(obj, jsClass) \ No newline at end of file diff --git a/libraries/stdlib/js/src/kotlin/reflect/KClassImpl.kt b/libraries/stdlib/js/src/kotlin/reflect/KClassImpl.kt index 899560f4f3c..b6279f7ef5d 100644 --- a/libraries/stdlib/js/src/kotlin/reflect/KClassImpl.kt +++ b/libraries/stdlib/js/src/kotlin/reflect/KClassImpl.kt @@ -60,7 +60,7 @@ internal class SimpleKClassImpl(jClass: JsClass) : KClassImpl(jCl override val simpleName: String? = jClass.asDynamic().`$metadata$`?.simpleName.unsafeCast() override fun isInstance(value: Any?): Boolean { - return js("Kotlin").isType(value, jClass) + return jsIsType(value, jClass) } }