What's new in Kotlin 2.4.20-Beta1
The Kotlin 2.4.20-Beta1 release is out! Here are some details of this EAP release:
Standard library: Support for coroutine stack trace recovery
Kotlin/Native: Default incremental compilation for
klibartifactsKotlin/Wasm: Changes to top-level
require()calls and improved companion object initialization orderKotlin/JS: New DSL for browser-testing
Build tools API: Support for new targets: Kotlin/JS, Kotlin/Wasm, and Kotlin metadata
Update to Kotlin 2.4.20-Beta1
The latest version of Kotlin is included in the latest versions of IntelliJ IDEA and Android Studio.
To update to the new Kotlin version, make sure your IDE is updated to the latest version and change the Kotlin version to 2.4.20-Beta1 in your build scripts.
Standard library: Support for coroutine stack trace recovery
Kotlin 2.4.20-Beta1 adds the StackTraceRecoverable interface to the standard library. This improves integration with the kotlinx.coroutines library because it lets you define how to create new exception instances for stack trace recovery without adding a dependency on kotlinx.coroutines.
Stack trace recovery helps with debugging when one coroutine throws an exception, and another rethrows it. It lets you see where the exception originates and where another coroutine rethrows it.
The kotlinx.coroutines library performs stack trace recovery by creating a new exception instance with additional coroutine stack trace information. This happens automatically for exceptions with constructors that take only an exception message, a cause, both, or no arguments.
If an exception constructor has additional required arguments, such as a line number or an error code, implement the StackTraceRecoverable interface to define how the kotlinx.coroutines library creates a new instance of that exception.
To do so, override the copyForStackTraceRecovery() function. This function returns a new exception instance for stack trace recovery, or null if you don't want the kotlinx.coroutines library to copy the exception.
These APIs are Experimental and require opt-in with the @OptIn(ExperimentalStdlibCoroutineSupportApi::class) annotation.
Here's an example of a custom exception that preserves a line property when it creates a new instance for stack trace recovery:
For more information, see the feature's KEEP. We would appreciate your feedback in YouTrack.
Kotlin/Native: Incremental compilation enabled by default
Starting with 2.4.20-Beta1, incremental compilation of klib artifacts is enabled by default.
With incremental compilation, if only a part of the klib artifact produced by the project module changes, only the affected part of the klib is further recompiled into a binary.
This optimization was first introduced in Kotlin 1.9.20 and has proven to drastically reduce compilation time for debug builds.
Note that in some cases, this optimization may come with a performance cost for clean builds.
If you face unexpected problems with this feature, you can disable it manually. To do that, set the following option in your gradle.properties file:
Please report any problems to our issue tracker YouTrack. For more tips on improving compilation time, see our documentation.
Kotlin/Wasm
Kotlin 2.4.20-Beta1 changes how Kotlin/Wasm handles top-level require() calls in @JsFun declarations and aligns companion object initialization order with JVM behavior.
Changes to top-level require() calls in @JsFun declarations
Kotlin/Wasm now reports an error when a @JsFun declaration uses the top-level require() function.
Previously, the compiler generated a require variable in the import-object.mjs file, allowing @JsFun declarations to call require().
This behavior unintentionally exposed a compiler implementation detail. To support migration away from it, Kotlin/Wasm removes this generated require declaration, and the compiler now reports errors for such calls. For example:
To prepare for this change, replace top-level require() calls in @JsFun declarations with the @JsModule annotation:
For dynamic module loading, use the import() expression instead. Add the /* webpackIgnore: true */ magic comment to prevent webpack from parsing the dynamic import:
You can also use the import() expression conditionally. For example, you can load a module only when running in Node.js:
If your project relies on dependencies that require a top-level require() function, add it as a property of globalThis as a workaround:
If you run into any issues, share your feedback in our issue tracker.
Improved companion object initialization order
Kotlin/Wasm now initializes superclass companion objects before subclass companion objects, matching the JVM behavior. Previously, the initialization could be reversed, leading to inconsistent behavior across platforms.
The update improves cross-platform consistency and reduces platform-specific differences in class initialization behavior. It also enables correct handling of companion object initialization in deeper inheritance hierarchies, including cases where intermediate classes don’t declare companion objects.
Kotlin/JS: new DSL for browser-testing
Kotlin 2.4.20-Beta1 introduces a new experimental DSL for running Kotlin/JS tests in a browser environment.
Currently, the Kotlin Gradle plugin uses Karma as a browser launcher to run JavaScript tests across different browsers. The Karma project has been deprecated for 2 years now, which made us explore alternative ways to support browser testing.
The new DSL is intended to replace Karma as a manager of different tools under the hood and includes:
Mocha as a test runner.
Webpack as a bundler (will be replaced with Vite in future releases).
Playwright as a browser driver and a distribution manager that supports Chromium, Firefox, and WebKit (Safari) browser engines.
To try out the new testing DSL, add the opt-in test{} block inside browser{} for your Kotlin/JS target:
The new DSL is in active development. We would appreciate your feedback in YouTrack.
Build tools API: Support for Kotlin/JS, Kotlin/Wasm, and Kotlin metadata
In Kotlin 2.2.0, the build tools API (BTA) became available for Kotlin/JVM. Kotlin 2.4.20-Beta1 takes the next step toward BTA stabilization by adding support for new targets: Kotlin/JS, Kotlin/Wasm, and Kotlin metadata.
This makes the Kotlin Gradle plugin interact with the compiler more consistently. In some cases, you can also benefit from faster, more stable compilation.
The BTA is a universal API that acts as an abstraction layer between build systems and the Kotlin compiler ecosystem. It helps support Kotlin features and compatibility with the Kotlin compiler in available build tools.
We plan to roll out the BTA support for the new targets in the Kotlin Gradle plugin gradually:
In Kotlin 2.4.20-Beta1, BTA is enabled in Kotlin/JS, Kotlin/Wasm, and Kotlin metadata by default to gather feedback. No additional changes in projects are required.
Between Kotlin 2.4.20-Beta2 and the final Kotlin 2.4.20 release, BTA in the new targets will be available as an opt-in. To try it out, add the corresponding properties to your
gradle.propertiesfile:kotlin.wasm.runViaBuildToolsApi = true kotlin.js.runViaBuildToolsApi = true kotlin.metadata.runViaBuildToolsApi = trueStarting with Kotlin 2.5.0, BTA will be enabled in Kotlin/JS, Kotlin/Wasm, and Kotlin metadata by default again.
If you're curious about the BTA proposal or want to share your feedback, see this KEEP.