~~~ [Wasm]: String  related hacks
diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmSymbols.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmSymbols.kt
index 6231a0e..cf24909 100644
--- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmSymbols.kt
+++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmSymbols.kt
@@ -193,6 +193,7 @@
     val refCastNull = getInternalFunction("wasm_ref_cast_null")
     val wasmArrayCopy = getInternalFunction("wasm_array_copy")
     val wasmArrayNewData0 = getInternalFunction("array_new_data0")
+    val wasmArrayNewFiexd1 = getInternalFunction("array_new_fixed1")
 
     val primitiveTypeToCreateTypedArray = mapOf(
         context.irBuiltIns.arrayClass to getFunction("createAnyArray", kotlinTopLevelPackage),
@@ -215,6 +216,7 @@
     val unboxIntrinsic: IrSimpleFunctionSymbol = getInternalFunction("unboxIntrinsic")
 
     val stringGetLiteral = getFunction("stringLiteral", builtInsPackage)
+    val streqeq = getFunction("streqeq", builtInsPackage)
     val stringGetPoolSize = getInternalFunction("stringGetPoolSize")
 
     val testFun = maybeGetFunction("test", kotlinTestPackage)
diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt
index d8781e7..369bd21 100644
--- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt
+++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt
@@ -629,6 +629,14 @@
                 body.buildInstr(WasmOp.ARRAY_NEW_DATA, location, arrayGcType, WasmImmediate.DataIdx(0))
             }
 
+            wasmSymbols.wasmArrayNewFiexd1 -> {
+                val arrayGcType = WasmImmediate.GcType(
+                    context.referenceGcType(call.type.getRuntimeClass(irBuiltIns).symbol)
+                )
+
+                body.buildInstr(WasmOp.ARRAY_NEW_FIXED, location, arrayGcType, WasmImmediate.ConstI32(1))
+            }
+
             else -> {
                 return false
             }
diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/BuiltInsLowering.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/BuiltInsLowering.kt
index 32a33e9..53aab84 100644
--- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/BuiltInsLowering.kt
+++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/BuiltInsLowering.kt
@@ -84,6 +84,9 @@
 
                 // For eqeqSymbol use overridden `Any.equals(Any?)` if there is any.
                 if (call.symbol === irBuiltins.eqeqSymbol && !lhsType.isNullable()) {
+                    if (lhsType.isString() && rhsType.isString()) {
+                        return irCall(call, symbols.streqeq)
+                    }
                     return irCall(call, lhsType.findEqualsMethod().symbol, argumentsAsReceivers = true)
                 }
 
diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmStringSwitchOptimizerLowering.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmStringSwitchOptimizerLowering.kt
index 5da1db5..62af9e4 100644
--- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmStringSwitchOptimizerLowering.kt
+++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmStringSwitchOptimizerLowering.kt
@@ -11,6 +11,7 @@
 import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
 import org.jetbrains.kotlin.backend.wasm.WasmBackendContext
 import org.jetbrains.kotlin.ir.IrStatement
+import org.jetbrains.kotlin.ir.backend.js.utils.valueArguments
 import org.jetbrains.kotlin.ir.builders.*
 import org.jetbrains.kotlin.ir.builders.declarations.buildVariable
 import org.jetbrains.kotlin.ir.declarations.*
@@ -18,7 +19,10 @@
 import org.jetbrains.kotlin.ir.interpreter.toIrConst
 import org.jetbrains.kotlin.ir.types.IrType
 import org.jetbrains.kotlin.ir.types.isNullable
+import org.jetbrains.kotlin.ir.types.makeNotNull
+import org.jetbrains.kotlin.ir.util.copyTypeAndValueArgumentsFrom
 import org.jetbrains.kotlin.ir.util.getSimpleFunction
+import org.jetbrains.kotlin.ir.util.irCall
 import org.jetbrains.kotlin.ir.util.isElseBranch
 import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
 import org.jetbrains.kotlin.name.Name
@@ -46,7 +50,7 @@
     private fun asEqCall(expression: IrExpression): IrCall? =
         (expression as? IrCall)?.takeIf { it.symbol == context.irBuiltIns.eqeqSymbol }
 
-    private class MatchedCase(val condition: IrCall, val branchIndex: Int)
+    private class MatchedCase(var condition: IrCall, val branchIndex: Int)
     private class BucketSelector(val hashCode: Int, val selector: IrExpression)
 
     override fun lower(irFile: IrFile) {
@@ -262,6 +266,14 @@
             irBlock(resultType = visitedWhen.type) {
                 val tempIntVariable = addHashCodeVariable(firstEqCall!!)
 
+                stringConstantToMatchedCase.forEach {(_, c) ->
+                    if (c.condition.symbol ==  context.irBuiltIns.eqeqSymbol) {
+                        val nc = irCall(c.condition, symbols.streqeq)
+                        c.condition = nc
+                    }
+                    c.condition.valueArguments[0]?.let { it.type = it.type.makeNotNull() }
+                }
+
                 val buckets = stringConstantToMatchedCase.keys.groupBy { it.hashCode() }
 
                 if (isSimpleWhen) {
diff --git a/libraries/stdlib/wasm/builtins/kotlin/String.kt b/libraries/stdlib/wasm/builtins/kotlin/String.kt
index 85d08d8..66096a5 100644
--- a/libraries/stdlib/wasm/builtins/kotlin/String.kt
+++ b/libraries/stdlib/wasm/builtins/kotlin/String.kt
@@ -6,7 +6,6 @@
 package kotlin
 
 import kotlin.wasm.internal.*
-import kotlin.math.min
 
 /**
  * The `String` class represents character strings. All string literals in Kotlin programs, such as `"abc"`, are
@@ -16,7 +15,7 @@
     private var leftIfInSum: String?,
     @kotlin.internal.IntrinsicConstEvaluation
     public override val length: Int,
-    private var _chars: WasmCharArray,
+    internal var _chars: WasmCharArray,
 ) : Comparable<String>, CharSequence {
     public companion object {}
 
@@ -26,6 +25,8 @@
     @kotlin.internal.IntrinsicConstEvaluation
     public operator fun plus(other: Any?): String {
         val right = other.toString()
+        if (right.isEmpty()) return this
+        if (this.isEmpty()) return right
         return String(this, this.length + right.length, right.chars)
     }
 
@@ -66,14 +67,28 @@
         return _chars
     }
 
-    public override fun subSequence(startIndex: Int, endIndex: Int): CharSequence {
-        val actualStartIndex = startIndex.coerceAtLeast(0)
-        val actualEndIndex = endIndex.coerceAtMost(this.length)
-        val newLength = actualEndIndex - actualStartIndex
-        if (newLength <= 0) return ""
+    public override fun subSequence(startIndex: Int, endIndex: Int): String {
+//        val actualStartIndex = if (startIndex < 0) 0 else startIndex
+//        val length1 = this.length
+//        val actualEndIndex = if (endIndex > length1) length1 else endIndex
+//        val newLength = actualEndIndex - actualStartIndex
+        if (startIndex < 0) error("start")
+        if (endIndex > length) error("end")
+
+        val newLength = endIndex - startIndex
+
+        when (newLength) {
+            0 -> return EMPTY_STRING
+            1 -> {
+                return String(null, 1, array_new_fixed1(chars.get(startIndex)))
+            }
+        }
+
+        if (newLength < 0) error("")
+
         val newChars = WasmCharArray(newLength)
-        copyWasmArray(chars, newChars, actualStartIndex, 0, newLength)
-        return newChars.createString()
+        copyWasmArray(chars, newChars, startIndex, 0, newLength)
+        return String(null, newLength, newChars)
     }
 
     @kotlin.internal.IntrinsicConstEvaluation
@@ -93,24 +108,30 @@
         return thisLength - otherLength
     }
 
+
     @kotlin.internal.IntrinsicConstEvaluation
     public override fun equals(other: Any?): Boolean {
-        if (other == null) return false
+        if (other == null) return false //
         if (other === this) return true
-        val otherString = other as? String ?: return false
+        if (other !is String) return false //
+
+        val otherString: String = other //
 
         val thisLength = this.length
-        val otherLength = otherString.length
-        if (thisLength != otherLength) return false
+        if (thisLength != otherString.length) return false
 
         val thisHash = this._hashCode
-        val otherHash = other._hashCode
-        if (thisHash != otherHash && thisHash != 0 && otherHash != 0) return false
+        if (thisHash != 0) {
+            val otherHash = otherString._hashCode
+            if (otherHash != 0 && thisHash != otherHash) return false
+        }
 
-        val thisChars = this.chars
-        val otherChars = other.chars
-        repeat(thisLength) {
-            if (thisChars.get(it) != otherChars.get(it)) return false
+        val thisChars = this.chars // _chars
+        val otherChars = otherString.chars // _chars
+        var index = 0
+        while (index < thisLength) {
+            if (thisChars.get(index) != otherChars.get(index)) return false
+            index = index + 1
         }
         return true
     }
@@ -147,4 +168,25 @@
     val newString = String(null, length, chars)
     stringPool[poolId] = newString
     return newString
-}
\ No newline at end of file
+}
+
+internal fun streqeq(this_: String, other: String): Boolean {
+    if (other === this_) return true
+
+    val thisChars = this_.chars
+    val otherChars = other.chars
+
+    if (otherChars === thisChars) return true
+
+    val thisLength = thisChars.len()
+    val otherLength = otherChars.len()
+
+    if (thisLength != otherLength) return false
+
+    var index = 0
+    while (index < thisLength) {
+        if (thisChars.get(index) != otherChars.get(index)) return false
+        index = index + 1
+    }
+    return true
+}
diff --git a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/Runtime.kt b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/Runtime.kt
index fb8bd73..e1ccd95 100644
--- a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/Runtime.kt
+++ b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/Runtime.kt
@@ -47,6 +47,21 @@
     if (wasm_ref_is_null(lhs))
         return wasm_ref_is_null(rhs)
     return unsafeNotNull(lhs).equals(rhs)
+    /*
+    block {
+        if (l is null) {
+            r is null
+            br 
+        }
+        
+        if (r is null) {
+          0
+          br
+        }
+
+        l.eqauls(r)
+    }
+     */
 }
 
 internal fun anyNtoString(x: Any?): String = x.toString()
@@ -119,4 +134,20 @@
 // This initializer is a special case in FieldInitializersLowering
 @Suppress("DEPRECATION")
 @EagerInitialization
-internal val stringPool: Array<String?> = Array(stringGetPoolSize())
\ No newline at end of file
+internal val stringPool: WasmStringArray/*<String?>*/ = WasmStringArray(stringGetPoolSize())
+internal val EMPTY_STRING = ""
+
+@WasmArrayOf(String::class, isNullable = true)
+internal class WasmStringArray(size: Int) {
+    @WasmOp(WasmOp.ARRAY_GET)
+    operator fun get(index: Int): String? =
+        implementedAsIntrinsic
+
+    @WasmOp(WasmOp.ARRAY_SET)
+    operator fun set(index: Int, value: String?): Unit =
+        implementedAsIntrinsic
+
+    @WasmOp(WasmOp.ARRAY_LEN)
+    fun length(): Int =
+        implementedAsIntrinsic
+}
diff --git a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/WasmInstructions.kt b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/WasmInstructions.kt
index ab1fb81..ffec793 100644
--- a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/WasmInstructions.kt
+++ b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/WasmInstructions.kt
@@ -34,6 +34,9 @@
 internal fun <T> array_new_data0(address: Int, length: Int): T =
     implementedAsIntrinsic
 
+internal fun array_new_fixed1(c: Char): WasmCharArray =
+    implementedAsIntrinsic
+
 @WasmOp(WasmOp.I32_EQ)
 internal external fun wasm_i32_eq(a: Int, b: Int): Boolean
 
diff --git a/libraries/stdlib/wasm/src/kotlin/text/StringsWasm.kt b/libraries/stdlib/wasm/src/kotlin/text/StringsWasm.kt
index 753439f..7e0622c 100644
--- a/libraries/stdlib/wasm/src/kotlin/text/StringsWasm.kt
+++ b/libraries/stdlib/wasm/src/kotlin/text/StringsWasm.kt
@@ -217,7 +217,7 @@
  * Returns a substring of this string that starts at the specified [startIndex] and continues to the end of the string.
  */
 public actual fun String.substring(startIndex: Int): String =
-    subSequence(startIndex, this.length) as String
+    subSequence(startIndex, this.length)// as String
 
 /**
  * Returns the substring of this string starting at the [startIndex] and ending right before the [endIndex].
@@ -226,7 +226,7 @@
  * @param endIndex the end index (exclusive).
  */
 public actual fun String.substring(startIndex: Int, endIndex: Int): String =
-    subSequence(startIndex, endIndex) as String
+    subSequence(startIndex, endIndex)// as String
 
 /**
  * Returns a copy of this string converted to upper case using the rules of the default locale.