From 200319de86ddb04c4e30b326118fc8aeb4eb7a59 Mon Sep 17 00:00:00 2001 From: Terry Yiu Date: Tue, 8 Sep 2026 09:34:40 +0300 Subject: [PATCH] Fix Intl interop crash on Kotlin/JS web target js("new Foo(x).bar()") can misparse so `new` binds to the whole chain instead of just the constructor call, throwing "X.resolvedOptions is not a constructor" at runtime on the JS target (Kotlin/Wasm was unaffected, since its js() compiles through a different path). Binding the constructor result to a local variable first removes the ambiguity. This was also silently breaking systemCurrencies() and the currency display name lookup, and had been cascading into an unrelated CoinGecko test failure in the same karma bundle. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01QpjMKWGoiT5aJBzhxvXkwp --- .../xyz/tyiu/satsprice/SystemCurrencies.web.kt | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/shared/src/webMain/kotlin/xyz/tyiu/satsprice/SystemCurrencies.web.kt b/shared/src/webMain/kotlin/xyz/tyiu/satsprice/SystemCurrencies.web.kt index 2ec3fcd..ce077b1 100644 --- a/shared/src/webMain/kotlin/xyz/tyiu/satsprice/SystemCurrencies.web.kt +++ b/shared/src/webMain/kotlin/xyz/tyiu/satsprice/SystemCurrencies.web.kt @@ -4,8 +4,11 @@ package xyz.tyiu.satsprice private fun jsSupportedCurrencyCodes(): JsArray = js("Intl.supportedValuesOf('currency')") -private fun jsCurrencyDisplayName(code: String): String = - js("new Intl.DisplayNames(['en'], { type: 'currency' }).of(code)") +// A chained `new Foo(x).bar()` inside js() can misparse (`new` binding to the whole chain rather +// than just the constructor call), so the constructor result is bound to a variable first. +private fun jsCurrencyDisplayName(code: String): String = js( + "(function() { var names = new Intl.DisplayNames(['en'], { type: 'currency' }); return names.of(code); })()", +) actual fun systemCurrencies(): List = jsSupportedCurrencyCodes() @@ -24,8 +27,9 @@ actual fun systemCurrencies(): List = */ actual fun localeCurrencyCode(): String? = null -private fun jsCurrencyFractionDigits(code: String): Int = - js("new Intl.NumberFormat('en', { style: 'currency', currency: code }).resolvedOptions().maximumFractionDigits") +private fun jsCurrencyFractionDigits(code: String): Int = js( + """(function() { var fmt = new Intl.NumberFormat('en', { style: 'currency', currency: code }); return fmt.resolvedOptions().maximumFractionDigits; })()""", +) actual fun currencyDecimalDigits(code: String): Int = try { jsCurrencyFractionDigits(code)