From 1fb9c2eedff7c0d63ecd6d86bfdea04013273e73 Mon Sep 17 00:00:00 2001 From: Luna712 <142361265+Luna712@users.noreply.github.com> Date: Fri, 29 May 2026 14:42:49 -0600 Subject: [PATCH 1/6] Fix direct java usage I had there when first testing and forgot to remove --- .../com/lagradost/cloudstream3/utils/JsInterpreter.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt index 8b2b96584b4..bddb05e93bb 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt @@ -2,6 +2,8 @@ package com.lagradost.cloudstream3.utils import com.lagradost.cloudstream3.Prerelease import com.lagradost.cloudstream3.mvvm.logError +import com.lagradost.cloudstream3.utils.StringUtils.decodeUri +import com.lagradost.cloudstream3.utils.StringUtils.encodeUri import kotlin.math.* /** @@ -739,10 +741,10 @@ private class JsInterpreter { globalScope.define("parseFloat", nativeFn { args -> toNumber(args.getOrNull(0)) }) globalScope.define("isNaN", nativeFn { args -> toNumber(args.getOrNull(0)).isNaN() }) globalScope.define("isFinite", nativeFn { args -> toNumber(args.getOrNull(0)).isFinite() }) - globalScope.define("decodeURIComponent", nativeFn { args -> java.net.URLDecoder.decode(toJsString(args.getOrNull(0)), "UTF-8") }) - globalScope.define("encodeURIComponent", nativeFn { args -> java.net.URLEncoder.encode(toJsString(args.getOrNull(0)), "UTF-8") }) - globalScope.define("escape", nativeFn { args -> java.net.URLEncoder.encode(toJsString(args.getOrNull(0)), "UTF-8") }) - globalScope.define("unescape", nativeFn { args -> java.net.URLDecoder.decode(toJsString(args.getOrNull(0)), "UTF-8") }) + globalScope.define("decodeURIComponent", nativeFn { args -> toJsString(args.getOrNull(0)).decodeUri() }) + globalScope.define("encodeURIComponent", nativeFn { args -> toJsString(args.getOrNull(0)).encodeUri() }) + globalScope.define("escape", nativeFn { args -> toJsString(args.getOrNull(0)).encodeUri() }) + globalScope.define("unescape", nativeFn { args -> toJsString(args.getOrNull(0)).decodeUri() }) globalScope.define("eval", nativeFn { args -> eval(toJsString(args.getOrNull(0))) }) globalScope.define("undefined", Unit) globalScope.define("NaN", Double.NaN) From 29ff478bb034a6b4b90dcac6b20914f53abbd662 Mon Sep 17 00:00:00 2001 From: Luna712 <142361265+Luna712@users.noreply.github.com> Date: Fri, 29 May 2026 14:47:25 -0600 Subject: [PATCH 2/6] Update --- .../kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt index bddb05e93bb..559ce46d46e 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt @@ -5,6 +5,7 @@ import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.utils.StringUtils.decodeUri import com.lagradost.cloudstream3.utils.StringUtils.encodeUri import kotlin.math.* +import kotlin.random.Random.nextDouble /** * Lightweight pure-Kotlin JavaScript interpreter designed to replace Rhino for @@ -707,7 +708,7 @@ private class JsInterpreter { private fun installGlobals() { val mathObj = JsObject(mutableMapOf( - "PI" to Math.PI, "E" to Math.E, + "PI" to PI, "E" to E, "floor" to nativeFn { args -> floor(toNumber(args.getOrNull(0))) }, "ceil" to nativeFn { args -> ceil(toNumber(args.getOrNull(0))) }, "round" to nativeFn { args -> round(toNumber(args.getOrNull(0))) }, @@ -720,7 +721,7 @@ private class JsInterpreter { "tan" to nativeFn { args -> tan(toNumber(args.getOrNull(0))) }, "max" to nativeFn { args -> args.maxOfOrNull { toNumber(it) } ?: Double.NEGATIVE_INFINITY }, "min" to nativeFn { args -> args.minOfOrNull { toNumber(it) } ?: Double.POSITIVE_INFINITY }, - "random" to nativeFn { _ -> Math.random() }, + "random" to nativeFn { _ -> nextDouble() }, "trunc" to nativeFn { args -> truncate(toNumber(args.getOrNull(0))) }, "log2" to nativeFn { args -> log2(toNumber(args.getOrNull(0))) }, "log10" to nativeFn { args -> log10(toNumber(args.getOrNull(0))) }, From cb206ea158ef65a7c1f1e39c17991b966467c58c Mon Sep 17 00:00:00 2001 From: Luna712 <142361265+Luna712@users.noreply.github.com> Date: Fri, 29 May 2026 14:51:33 -0600 Subject: [PATCH 3/6] Update --- .../com/lagradost/cloudstream3/utils/JsInterpreter.kt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt index 559ce46d46e..b70b29fab8b 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt @@ -1191,8 +1191,15 @@ private class JsInterpreter { if (radix == 10) toJsString(obj) else obj.toLong().toString(radix) } "toFixed" -> nativeFn { args -> - val digits = args.getOrNull(0)?.let { toNumber(it).toInt() } ?: 0 - "%.${digits}f".format(obj) + val digits = (args.getOrNull(0)?.let { toNumber(it).toInt() } ?: 0).coerceIn(0, 20) + val factor = 10.0.pow(digits) + val rounded = round(obj * factor) / factor + val sign = if (rounded < 0) "-" else "" + val absVal = abs(rounded) + val intPart = absVal.toLong() + val fracPart = round((absVal - intPart) * factor).toLong() + val fracStr = fracPart.toString().padStart(digits, '0') + if (digits == 0) "$sign$intPart" else "$sign$intPart.$fracStr" } else -> Unit } From 3cccc2d43dd80ddafa7298ecdcdb117507380a23 Mon Sep 17 00:00:00 2001 From: Luna712 <142361265+Luna712@users.noreply.github.com> Date: Fri, 29 May 2026 14:52:50 -0600 Subject: [PATCH 4/6] Fix --- .../kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt index b70b29fab8b..482085a0e9e 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/utils/JsInterpreter.kt @@ -5,7 +5,7 @@ import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.utils.StringUtils.decodeUri import com.lagradost.cloudstream3.utils.StringUtils.encodeUri import kotlin.math.* -import kotlin.random.Random.nextDouble +import kotlin.random.Random /** * Lightweight pure-Kotlin JavaScript interpreter designed to replace Rhino for @@ -721,7 +721,7 @@ private class JsInterpreter { "tan" to nativeFn { args -> tan(toNumber(args.getOrNull(0))) }, "max" to nativeFn { args -> args.maxOfOrNull { toNumber(it) } ?: Double.NEGATIVE_INFINITY }, "min" to nativeFn { args -> args.minOfOrNull { toNumber(it) } ?: Double.POSITIVE_INFINITY }, - "random" to nativeFn { _ -> nextDouble() }, + "random" to nativeFn { _ -> Random.nextDouble() }, "trunc" to nativeFn { args -> truncate(toNumber(args.getOrNull(0))) }, "log2" to nativeFn { args -> log2(toNumber(args.getOrNull(0))) }, "log10" to nativeFn { args -> log10(toNumber(args.getOrNull(0))) }, From 7b35c5027c4f58584a2183fe8ac6f9b8e8437efc Mon Sep 17 00:00:00 2001 From: Luna712 <142361265+Luna712@users.noreply.github.com> Date: Fri, 29 May 2026 15:03:02 -0600 Subject: [PATCH 5/6] Add tests --- .../cloudstream3/utils/JsInterpreterTest.kt | 71 ++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/library/src/commonTest/kotlin/com/lagradost/cloudstream3/utils/JsInterpreterTest.kt b/library/src/commonTest/kotlin/com/lagradost/cloudstream3/utils/JsInterpreterTest.kt index 3e90feccd39..0df545dd6f1 100644 --- a/library/src/commonTest/kotlin/com/lagradost/cloudstream3/utils/JsInterpreterTest.kt +++ b/library/src/commonTest/kotlin/com/lagradost/cloudstream3/utils/JsInterpreterTest.kt @@ -1,5 +1,7 @@ package com.lagradost.cloudstream3.utils +import kotlin.math.E +import kotlin.math.PI import kotlin.math.abs import kotlin.test.Test import kotlin.test.assertEquals @@ -422,6 +424,41 @@ class JsInterpreterTest { assertEquals("3.14", str("(3.14159).toFixed(2)")) } + @Test + fun toFixedZeroDigits() { + assertEquals("3", str("(3.6).toFixed(0)")) + } + + @Test + fun toFixedTwoDigits() { + assertEquals("3.14", str("(3.14159).toFixed(2)")) + } + + @Test + fun toFixedPadsWithZeroes() { + assertEquals("3.10", str("(3.1).toFixed(2)")) + } + + @Test + fun toFixedNegativeNumber() { + assertEquals("-3.14", str("(-3.14159).toFixed(2)")) + } + + @Test + fun toFixedNegativeBetweenZeroAndMinusOne() { + assertEquals("-0.50", str("(-0.5).toFixed(2)")) + } + + @Test + fun toFixedWholeNumber() { + assertEquals("5.00", str("(5).toFixed(2)")) + } + + @Test + fun toFixedZeroValue() { + assertEquals("0.00", str("(0).toFixed(2)")) + } + @Test fun arrayLiteralAndLength() { assertEquals(3.0, num("[1,2,3].length")) @@ -629,7 +666,12 @@ class JsInterpreterTest { @Test fun mathPi() { - assertApprox(Math.PI, num("Math.PI")) + assertApprox(PI, num("Math.PI")) + } + + @Test + fun mathE() { + assertApprox(E, num("Math.E")) } @Test @@ -637,6 +679,33 @@ class JsInterpreterTest { assertApprox(0.0, num("Math.log(1)")) } + @Test + fun mathTruncPositive() { + assertEquals(3.0, num("Math.trunc(3.9)")) + } + + @Test + fun mathTruncNegative() { + assertEquals(-3.0, num("Math.trunc(-3.9)")) + } + + @Test + fun mathTruncZero() { + assertEquals(0.0, num("Math.trunc(0.5)")) + } + + @Test + fun mathRandomInRange() { + val r = num("Math.random()") + assertTrue(r >= 0.0 && r < 1.0, "Math.random() should be in [0,1) but was $r") + } + + @Test + fun mathRandomProducesDifferentValues() { + val results = (1..20).map { num("Math.random()") }.toSet() + assertTrue(results.size > 1, "Math.random() produced identical values across 20 calls") + } + @Test fun parseIntDecimal() { assertEquals(42.0, num("parseInt('42')")) From 99d008a5344e1a0b0ae6ef771371e93fc969d7a1 Mon Sep 17 00:00:00 2001 From: Luna712 <142361265+Luna712@users.noreply.github.com> Date: Fri, 29 May 2026 15:06:17 -0600 Subject: [PATCH 6/6] Fix --- .../com/lagradost/cloudstream3/utils/JsInterpreterTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/src/commonTest/kotlin/com/lagradost/cloudstream3/utils/JsInterpreterTest.kt b/library/src/commonTest/kotlin/com/lagradost/cloudstream3/utils/JsInterpreterTest.kt index 0df545dd6f1..fd9d0730466 100644 --- a/library/src/commonTest/kotlin/com/lagradost/cloudstream3/utils/JsInterpreterTest.kt +++ b/library/src/commonTest/kotlin/com/lagradost/cloudstream3/utils/JsInterpreterTest.kt @@ -426,7 +426,7 @@ class JsInterpreterTest { @Test fun toFixedZeroDigits() { - assertEquals("3", str("(3.6).toFixed(0)")) + assertEquals("4", str("(3.6).toFixed(0)")) } @Test