[Wasm, JS] refactor static initialization check to the following:
1. check for successfull initialization
2. check for previously failed initialization (with obtaining KClass and throwing staticInitializationFailure)
3. try to initialize

So, we do not create KClass instances on successful path
Fixes ^KT-88002
diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/BackendJsSymbols.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/BackendJsSymbols.kt
index 0f4b651..b1751c9 100644
--- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/BackendJsSymbols.kt
+++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/BackendJsSymbols.kt
@@ -522,7 +522,7 @@
 
     val constructCallableReferenceSymbol by CallableIds.constructCallableReference.functionSymbol()
 
-    val checkStaticInitializationState by CallableIds.checkStaticInitializationState.functionSymbol()
+    val staticInitializationFailureWithClassName by CallableIds.staticInitializationFailureWithClassName.functionSymbol()
 }
 
 private object ClassIds {
@@ -794,5 +794,5 @@
     val test = CallableId(StandardClassIds.BASE_TEST_PACKAGE, Name.identifier("test"))
     val suite = CallableId(StandardClassIds.BASE_TEST_PACKAGE, Name.identifier("suite"))
     val EmptyContinuation = CallableId(FqName.fromSegments(listOf("kotlin", "coroutines", "js", "internal")), Name.identifier("EmptyContinuation"))
-    val checkStaticInitializationState = "checkStaticInitializationState".jsCallableId
+    val staticInitializationFailureWithClassName = "staticInitializationFailureWithClassName".jsCallableId
 }
diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsInitializersLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsInitializersLowering.kt
index cca5141..e53f73d 100644
--- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsInitializersLowering.kt
+++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsInitializersLowering.kt
@@ -25,6 +25,6 @@
     context,
     shouldEraseFieldInitializer = {
         it.correspondingPropertySymbol?.owner?.isConst != true &&
-                it.origin != WebStaticInitializersDeclarationLowering.STATIC_CLASS_INITIALIZER // We need to preserve initializers for `static_init_called` fields (KT-89144).
+                it.origin != WebStaticInitializersDeclarationLowering.STATIC_CLASS_INITIALIZER // We need to preserve initializers for `static_init_state` fields (KT-89144).
     }
 )
diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/LazyGlobalInitializationGenerator.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/LazyGlobalInitializationGenerator.kt
index af162a5..852d35f 100644
--- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/LazyGlobalInitializationGenerator.kt
+++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/LazyGlobalInitializationGenerator.kt
@@ -8,6 +8,7 @@
 import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
 import org.jetbrains.kotlin.backend.common.lower.irCatch
 import org.jetbrains.kotlin.backend.common.lower.irIfThen
+import org.jetbrains.kotlin.backend.common.lower.irNot
 import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
 import org.jetbrains.kotlin.descriptors.DescriptorVisibility
 import org.jetbrains.kotlin.ir.IrStatement
@@ -20,7 +21,6 @@
 import org.jetbrains.kotlin.ir.builders.declarations.buildField
 import org.jetbrains.kotlin.ir.builders.declarations.buildFun
 import org.jetbrains.kotlin.ir.declarations.*
-import org.jetbrains.kotlin.ir.expressions.IrCall
 import org.jetbrains.kotlin.ir.expressions.IrExpression
 import org.jetbrains.kotlin.ir.expressions.IrGetField
 import org.jetbrains.kotlin.ir.types.IrType
@@ -34,12 +34,36 @@
     protected abstract val backendContext: JsCommonBackendContext
 
     private object InitializationState {
-        const val UNINITIALIZED: Int = 0
-        const val INITIALIZED: Int = 1
+        const val UNINITIALIZED: Int = 1
+        const val INITIALIZED: Int = 0
         const val ERROR: Int = 2
     }
 
-    protected abstract fun IrBuilderWithScope.generateStaticInitializationStateCheck(getStateField: IrGetField, klass: IrClass?): IrCall
+    protected abstract fun IrBuilderWithScope.staticInitializationFailureBranch(klass: IrClass?): IrExpression
+
+    private fun IrBuilderWithScope.generateStaticInitializationStateChecks(
+        getStateField: IrGetField,
+        klass: IrClass?
+    ): List<IrStatement> {
+
+        val state = scope.createTemporaryVariable(
+            getStateField,
+            nameHint = "state",
+            inventUniqueName = false,
+        )
+
+        return listOf(
+            state,
+            irIfThen(
+                irNot(irGet(state)), // state == InitializationState.INITIALIZED
+                irReturnUnit()
+            ),
+            irIfThen(
+                irEqeqeq(irGet(state), irInt(InitializationState.ERROR)),
+                staticInitializationFailureBranch(klass)
+            )
+        )
+    }
 
     protected open fun IrBuilderWithScope.undefinedOrNull(): IrExpression = irNull()
 
@@ -82,8 +106,7 @@
             val builder = backendContext.createIrBuilder(symbol)
             body = backendContext.irFactory.createBlockBody(startOffset, endOffset) {
                 with(builder) {
-                    val stateCheck = generateStaticInitializationStateCheck(irGetField(null, stateField), klass)
-                    statements += irIfThen(stateCheck, irReturnUnit())
+                    statements += generateStaticInitializationStateChecks(irGetField(null, stateField), klass)
                     statements += irSetField(null, stateField, irInt(InitializationState.INITIALIZED))
                     val allInitializers = irComposite {
                         beforeAll()
@@ -115,10 +138,9 @@
 }
 
 class JsLazyGlobalInitializationGenerator(override val backendContext: JsIrBackendContext) : LazyGlobalInitializationGenerator() {
-    override fun IrBuilderWithScope.generateStaticInitializationStateCheck(getStateField: IrGetField, klass: IrClass?): IrCall =
-        irCall(backendContext.symbols.checkStaticInitializationState).apply {
-            arguments[0] = getStateField
-            arguments[1] = klass?.jsConstructorReference(backendContext) ?: backendContext.getVoid()
+    override fun IrBuilderWithScope.staticInitializationFailureBranch(klass: IrClass?): IrExpression =
+        irCall(backendContext.symbols.staticInitializationFailureWithClassName).apply {
+            arguments[0] = klass?.jsConstructorReference(backendContext) ?: backendContext.getVoid()
         }
 
     override fun IrBuilderWithScope.undefinedOrNull(): IrExpression = backendContext.getVoid()
diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/WebStaticInitializersDeclarationLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/WebStaticInitializersDeclarationLowering.kt
index f625a91..6a99b6a 100644
--- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/WebStaticInitializersDeclarationLowering.kt
+++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/WebStaticInitializersDeclarationLowering.kt
@@ -56,17 +56,20 @@
  * ```kotlin
  * class Foo {
  *   companion {
- *     var static_init_called = 0
+ *     var static_init_state = 1
  *     static_init() {
- *       if (checkInitializationState(static_init_called, Foo::class)) return
- *       static_init_called = 1
+ *       if (!static_init_state) return
+ *       if (static_init_state == 2) {
+ *         staticInitializationFailureWithClassName(Foo::class)
+ *       }
+ *       static_init_state = 0
  *       try {
  *         first = initFirst()
  *         second = initSecond()
  *         third = initThird()
  *       } catch (reason: Throwable) {
- *         static_init_called = 2
- *         kotlint.internal.staticInitializationFailure(reason, null)
+ *         static_init_state = 2
+ *         kotlin.internal.staticInitializationFailure(reason, null)
  *       }
  *     }
  *   }
@@ -88,7 +91,7 @@
         val STATIC_CLASS_INITIALIZER by IrDeclarationOriginImpl.Synthetic
 
         const val STATIC_INIT_FUNCTION_NAME = "static_init"
-        const val STATIC_INIT_CALLED_PROPERTY_NAME = "static_init_called"
+        const val STATIC_INIT_STATE_PROPERTY_NAME = "static_init_state"
     }
 
     protected abstract val context: JsCommonBackendContext
@@ -180,10 +183,10 @@
         // Both declarations must be created within the *same* restrictTo block: the stage controller resets its signature index
         // on every restrictTo call, so creating them in two separate blocks gives both the very same
         // `IdSignature.LoweredDeclarationSignature`. Cross-file references are resolved by the rendered signature, so the
-        // collision makes a reference to `static_init` resolve to `static_init_called` instead.
-        val [staticInitCalledField, staticInitFunction] = context.irFactory.stageController.restrictTo(container) {
+        // collision makes a reference to `static_init` resolve to `static_init_state` instead.
+        val [staticInitStateField, staticInitFunction] = context.irFactory.stageController.restrictTo(container) {
             val stateField = initializationGenerator.createStateField(
-                name = Name.identifier(STATIC_INIT_CALLED_PROPERTY_NAME),
+                name = Name.identifier(STATIC_INIT_STATE_PROPERTY_NAME),
                 origin = STATIC_CLASS_INITIALIZER,
             ).apply {
                 parent = container
@@ -212,7 +215,7 @@
         // Adding static_init declaration after adding its usages to make sure we don't insert usages inside static_init itself
         container.staticInitFunction = staticInitFunction
         container.companionObject()?.staticInitFunction = staticInitFunction
-        container.declarations.addAll(0, listOf(staticInitCalledField, staticInitFunction))
+        container.declarations.addAll(0, listOf(staticInitStateField, staticInitFunction))
     }
 
     private fun IrClass.createInitializer(declaration: IrDeclaration, field: IrField, initializer: IrExpression): IrSetField =
diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/WebStaticInitializersUsageLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/WebStaticInitializersUsageLowering.kt
index 2426c1f..da4dba4 100644
--- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/WebStaticInitializersUsageLowering.kt
+++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/WebStaticInitializersUsageLowering.kt
@@ -34,13 +34,21 @@
  * ```kotlin
  * class Foo {
  *   companion {
- *     var static_init_called = false
+ *     var static_init_state = 1
  *     static_init() {
- *       if (static_init_called) return
- *       static_init_called = true
- *       first = initFirst()
- *       second = initSecond()
- *       third = initThird()
+ *       if (!static_init_state) return
+ *       if (static_init_state == 2) {
+ *         staticInitializationFailureWithClassName(Foo::class)
+ *       }
+ *       static_init_state = 0
+ *       try {
+ *         first = initFirst()
+ *         second = initSecond()
+ *         third = initThird()
+ *       } catch (reason: Throwable) {
+ *         static_init_state = 2
+ *         kotlin.internal.staticInitializationFailure(reason, null)
+ *       }
  *     }
  *   }
  *   companion {
@@ -62,10 +70,10 @@
  *     static_init()
  *   }
  *   companion {
- *     var static_init_called = false
+ *     var static_init_state = 1
  *     static_init() {
- *       static_init_called = true
- *       // ...
+ *       if (!static_init_state) return
+ *       ...
  *     }
  *   }
  *   companion {
diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/BackendWasmSymbols.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/BackendWasmSymbols.kt
index fdaafa7..11351d5 100644
--- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/BackendWasmSymbols.kt
+++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/BackendWasmSymbols.kt
@@ -317,7 +317,7 @@
 
     val wasmAnyRefClass = ClassIds.anyref.classSymbol()
 
-    val checkStaticInitializationState by CallableIds.checkStaticInitializationState.functionSymbol()
+    val staticInitializationFailureWithClassName by CallableIds.staticInitializationFailureWithClassName.functionSymbol()
 
     inner class JsInteropAdapters {
         val kotlinToJsStringAdapter by CallableIds.kotlinToJsStringAdapter.functionSymbol()
@@ -678,7 +678,7 @@
     val js = CallableId(JsStandardClassIds.BASE_JS_PACKAGE, Name.identifier("js"))
     val registerRootSuiteBlock = CallableId(StandardClassIds.BASE_TEST_PACKAGE, Name.identifier("registerRootSuiteBlock"))
     val runRootSuites = CallableId(StandardClassIds.BASE_TEST_PACKAGE, Name.identifier("runRootSuites"))
-    val checkStaticInitializationState = "checkStaticInitializationState".wasmCallableId
+    val staticInitializationFailureWithClassName = "staticInitializationFailureWithClassName".wasmCallableId
     val cabiRealloc = "cabi_realloc".wasmCallableId
 }
 
diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmInitializersLowering.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmInitializersLowering.kt
index ebb3805a..228dffc 100644
--- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmInitializersLowering.kt
+++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmInitializersLowering.kt
@@ -25,6 +25,6 @@
     context,
     shouldEraseFieldInitializer = {
         it.correspondingPropertySymbol?.owner?.isConst != true &&
-                it.origin != WebStaticInitializersDeclarationLowering.STATIC_CLASS_INITIALIZER // We need to preserve initializers for `static_init_called` fields (KT-89144).
+                it.origin != WebStaticInitializersDeclarationLowering.STATIC_CLASS_INITIALIZER // We need to preserve initializers for `static_init_state` fields (KT-89144).
     }
 )
diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmLazyGlobalInitializationGenerator.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmLazyGlobalInitializationGenerator.kt
index aa96b15..125bc7c 100644
--- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmLazyGlobalInitializationGenerator.kt
+++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmLazyGlobalInitializationGenerator.kt
@@ -12,14 +12,12 @@
 import org.jetbrains.kotlin.ir.builders.irNull
 import org.jetbrains.kotlin.ir.builders.kClassReference
 import org.jetbrains.kotlin.ir.declarations.IrClass
-import org.jetbrains.kotlin.ir.expressions.IrCall
-import org.jetbrains.kotlin.ir.expressions.IrGetField
+import org.jetbrains.kotlin.ir.expressions.IrExpression
 import org.jetbrains.kotlin.ir.types.starProjectedType
 
 class WasmLazyGlobalInitializationGenerator(override val backendContext: WasmBackendContext) : LazyGlobalInitializationGenerator() {
-    override fun IrBuilderWithScope.generateStaticInitializationStateCheck(getStateField: IrGetField, klass: IrClass?): IrCall =
-        irCall(backendContext.symbols.checkStaticInitializationState).apply {
-            arguments[0] = getStateField
-            arguments[1] = klass?.let { kClassReference(it.symbol.starProjectedType) } ?: irNull()
+    override fun IrBuilderWithScope.staticInitializationFailureBranch(klass: IrClass?): IrExpression =
+        irCall(backendContext.symbols.staticInitializationFailureWithClassName).apply {
+            arguments[0] = klass?.let { kClassReference(it.symbol.starProjectedType) } ?: irNull()
         }
 }
diff --git a/libraries/stdlib/js/runtime/staticInitialization.kt b/libraries/stdlib/js/runtime/staticInitialization.kt
index d7a3c9b..4b6e07b 100644
--- a/libraries/stdlib/js/runtime/staticInitialization.kt
+++ b/libraries/stdlib/js/runtime/staticInitialization.kt
@@ -11,6 +11,7 @@
 private const val INITIALIZATION_STATE_INITIALIZED: Int = 1
 private const val INITIALIZATION_STATE_ERROR: Int = 2
 
+// TODO: remove after bootstrap KT-89126
 @UsedFromCompilerGeneratedCode
 internal fun checkStaticInitializationState(state: Int, ctor: Ctor?): Boolean {
     if (state == INITIALIZATION_STATE_ERROR) {
@@ -18,3 +19,8 @@
     }
     return state == INITIALIZATION_STATE_INITIALIZED
 }
+
+@UsedFromCompilerGeneratedCode
+internal fun staticInitializationFailureWithClassName(ctor: Ctor?): Nothing {
+    staticInitializationFailure(null, ctor?.`$metadata$`?.simpleName)
+}
diff --git a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/ThrowHelpers.kt b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/ThrowHelpers.kt
index 9e5572f..7cb0662 100644
--- a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/ThrowHelpers.kt
+++ b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/ThrowHelpers.kt
@@ -73,6 +73,7 @@
 private const val INITIALIZATION_STATE_INITIALIZED: Int = 1
 private const val INITIALIZATION_STATE_ERROR: Int = 2
 
+// TODO: Remove after bootstrap KT-89126
 @UsedFromCompilerGeneratedCode
 internal fun checkStaticInitializationState(state: Int, klass: KClass<*>?): Boolean {
     if (state == INITIALIZATION_STATE_ERROR) {
@@ -80,3 +81,12 @@
     }
     return state == INITIALIZATION_STATE_INITIALIZED
 }
+
+@UsedFromCompilerGeneratedCode
+internal fun staticInitializationFailureWithClassName(klass: KClass<*>?): Nothing {
+    var className: String? = null
+    if (klass != null) {
+        className = klass.qualifiedName ?: klass.simpleName
+    }
+    staticInitializationFailure(null, className)
+}