All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlin.ir.backend.js.JsSymbols.kt Maven / Gradle / Ivy

/*
 * Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
 * 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

import org.jetbrains.kotlin.backend.common.ir.Symbols
import org.jetbrains.kotlin.builtins.StandardNames.COLLECTIONS_PACKAGE_FQ_NAME
import org.jetbrains.kotlin.ir.InternalSymbolFinderAPI
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.StageController
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.types.makeNotNull
import org.jetbrains.kotlin.ir.util.irError
import org.jetbrains.kotlin.ir.util.kotlinPackageFqn
import org.jetbrains.kotlin.name.JsStandardClassIds.BASE_JS_PACKAGE
import org.jetbrains.kotlin.name.Name

abstract class JsCommonSymbols(
    irBuiltIns: IrBuiltIns,
) : Symbols(irBuiltIns) {
    @OptIn(InternalSymbolFinderAPI::class)
    val coroutineSymbols = JsCommonCoroutineSymbols(irBuiltIns.symbolFinder)
}

@OptIn(ObsoleteDescriptorBasedAPI::class, InternalSymbolFinderAPI::class)
class JsSymbols(
    irBuiltIns: IrBuiltIns,
    private val stageController: StageController,
    private val intrinsics: JsIntrinsics,
) : JsCommonSymbols(irBuiltIns) {
    override val throwNullPointerException =
        symbolFinder.topLevelFunction(kotlinPackageFqn, "THROW_NPE")

    init {
        symbolFinder.topLevelFunction(kotlinPackageFqn, "noWhenBranchMatchedException")
    }

    override val throwTypeCastException =
        symbolFinder.topLevelFunction(kotlinPackageFqn, "THROW_CCE")

    override val throwUninitializedPropertyAccessException =
        symbolFinder.topLevelFunction(kotlinPackageFqn, "throwUninitializedPropertyAccessException")

    override val throwKotlinNothingValueException: IrSimpleFunctionSymbol =
        symbolFinder.topLevelFunction(kotlinPackageFqn, "throwKotlinNothingValueException")

    override val defaultConstructorMarker =
        symbolFinder.topLevelClass(BASE_JS_PACKAGE, "DefaultConstructorMarker")

    override val throwISE: IrSimpleFunctionSymbol =
        symbolFinder.topLevelFunction(kotlinPackageFqn, "THROW_ISE")

    override val throwIAE: IrSimpleFunctionSymbol =
        symbolFinder.topLevelFunction(kotlinPackageFqn, "THROW_IAE")

    override val stringBuilder
        get() = TODO("not implemented")
    override val coroutineImpl =
        coroutineSymbols.coroutineImpl
    override val coroutineSuspendedGetter =
        coroutineSymbols.coroutineSuspendedGetter

    private val _arraysContentEquals = symbolFinder.topLevelFunctions(COLLECTIONS_PACKAGE_FQ_NAME, "contentEquals").filter {
        it.descriptor.extensionReceiverParameter?.type?.isMarkedNullable == true
    }

    // Can't use .owner until ExternalStubGenerator is invoked, hence get() = here.
    override val arraysContentEquals: Map
        get() = _arraysContentEquals.associateBy { it.owner.extensionReceiverParameter!!.type.makeNotNull() }

    override val getContinuation = symbolFinder.topLevelFunction(BASE_JS_PACKAGE, "getContinuation")

    override val continuationClass = coroutineSymbols.continuationClass

    override val coroutineContextGetter = coroutineSymbols.coroutineContextGetter

    override val suspendCoroutineUninterceptedOrReturn = symbolFinder.topLevelFunction(BASE_JS_PACKAGE, COROUTINE_SUSPEND_OR_RETURN_JS_NAME)

    override val coroutineGetContext = symbolFinder.topLevelFunction(BASE_JS_PACKAGE, GET_COROUTINE_CONTEXT_NAME)

    override val returnIfSuspended = symbolFinder.topLevelFunction(BASE_JS_PACKAGE, "returnIfSuspended")

    override val functionAdapter = symbolFinder.topLevelClass(BASE_JS_PACKAGE, "FunctionAdapter")

    override fun functionN(n: Int): IrClassSymbol {
        return stageController.withInitialIr { super.functionN(n) }
    }

    override fun suspendFunctionN(n: Int): IrClassSymbol {
        return stageController.withInitialIr { super.suspendFunctionN(n) }
    }


    private val getProgressionLastElementSymbols =
        symbolFinder.findFunctions(Name.identifier("getProgressionLastElement"), "kotlin", "internal")

    override val getProgressionLastElementByReturnType: Map by lazy(LazyThreadSafetyMode.NONE) {
        getProgressionLastElementSymbols.associateBy { it.owner.returnType.classifierOrFail }
    }

    private val toUIntSymbols = symbolFinder.findFunctions(Name.identifier("toUInt"), "kotlin")

    override val toUIntByExtensionReceiver: Map by lazy(LazyThreadSafetyMode.NONE) {
        toUIntSymbols.associateBy {
            it.owner.extensionReceiverParameter?.type?.classifierOrFail
                ?: irError("Expected extension receiver for") {
                    withIrEntry("it.owner", it.owner)
                }
        }
    }

    private val toULongSymbols = symbolFinder.findFunctions(Name.identifier("toULong"), "kotlin")

    override val toULongByExtensionReceiver: Map by lazy(LazyThreadSafetyMode.NONE) {
        toULongSymbols.associateBy {
            it.owner.extensionReceiverParameter?.type?.classifierOrFail
                ?: irError("Expected extension receiver for") {
                    withIrEntry("it.owner", it.owner)
                }
        }
    }

    override fun isSideEffectFree(call: IrCall): Boolean =
        call.symbol in intrinsics.primitiveToLiteralConstructor.values ||
                call.symbol == intrinsics.arrayLiteral ||
                call.symbol == intrinsics.arrayConcat ||
                call.symbol == intrinsics.jsBoxIntrinsic ||
                call.symbol == intrinsics.jsUnboxIntrinsic

    companion object {
        // TODO: due to name clash those weird suffix is required, remove it once `MemberNameGenerator` is implemented
        private const val COROUTINE_SUSPEND_OR_RETURN_JS_NAME = "suspendCoroutineUninterceptedOrReturnJS"
        private const val GET_COROUTINE_CONTEXT_NAME = "getCoroutineContext"
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy