From 6c891261d66e69182abd9b2968e0a3029ee06c21 Mon Sep 17 00:00:00 2001 From: Aleksandr Shefer Date: Wed, 19 Nov 2025 12:17:42 +0100 Subject: [PATCH] Wasm/JS uses ES modules [1], and require function is not guaranteed to be present there. It worked previously, but recent changes in K/Wasm (that'll land in 2.3.20) triggered the following error: > Cannot determine intended module format because both require() and top-level await are present. > If the code is intended to be CommonJS, wrap await in an async function. > If the code is intended to be an ES module, replace require() with import. This change provides a workaround for the issue. [1] https://kotlinlang.org/docs/wasm-js-interop.html#kotlin-wasm-and-kotlin-js-interoperability-differences --- core/wasmJs/src/node/nodeModulesWasmJs.kt | 44 ++++++++++++++--------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/core/wasmJs/src/node/nodeModulesWasmJs.kt b/core/wasmJs/src/node/nodeModulesWasmJs.kt index 9bb913ce3..012922233 100644 --- a/core/wasmJs/src/node/nodeModulesWasmJs.kt +++ b/core/wasmJs/src/node/nodeModulesWasmJs.kt @@ -5,24 +5,36 @@ package kotlinx.io.node - -internal fun requireExists(): Boolean = js("typeof require === 'function'") - -internal fun requireModule(mod: String): JsAny? = js("""{ - try { - let m = require(mod); - if (m) return m; - return null; - } catch (e) { - return null; - } - }""") +@JsFun(""" + (globalThis.module = (typeof process !== 'undefined') && (process.release.name === 'node') ? + await import('node:module') : void 0, () => {}) +""") +internal external fun persistModule() + +@JsFun("""() => { + const importMeta = import.meta; + return globalThis.module.default.createRequire(importMeta.url); +} +""") +internal external fun getRequire(): JsAny + +private val require = persistModule().let { getRequire() } + +@JsFun(""" + (require, mod) => { + try { + let m = require(mod); + if (m) return m; + return null; + } catch (e) { + return null; + } + } +""") +internal external fun requireModule(require: JsAny, mod: String): JsAny? internal fun loadModule(name: String): JsAny { - if (!requireExists()) { - throw UnsupportedOperationException("Module $name could not be loaded") - } - val mod = requireModule(name) ?: throw UnsupportedOperationException("Module '$name' could not be imported") + val mod = requireModule(require, name) ?: throw UnsupportedOperationException("Module '$name' could not be imported") return mod }