yawkat
02/17/2025, 9:03 PMEdoardo Luppi
02/17/2025, 9:09 PMwasmJs
project from a js
one. What does the web-app do with the WASM code?Edoardo Luppi
02/17/2025, 9:11 PMyawkat
02/17/2025, 9:12 PMyawkat
02/17/2025, 9:13 PMyawkat
02/17/2025, 9:15 PMEdoardo Luppi
02/17/2025, 9:15 PMexternal
bindings in the js
project, for the `@JsExport`ed functions in the wasmJs
project is what you're looking for I believe.
You'll then have to do some Gradle magic to depend on the common-wasm module, and include its output in the final JS bundle.yawkat
02/17/2025, 9:16 PMyawkat
02/17/2025, 9:17 PMEdoardo Luppi
02/17/2025, 9:19 PMEdoardo Luppi
02/17/2025, 9:24 PMEdoardo Luppi
02/17/2025, 9:28 PMexternal
declarations to load the exported WASM functions through the JS wrapper.yawkat
02/17/2025, 9:36 PM@JsModule("kcd2dicesim-common-wasm-wasm-js")
yawkat
02/17/2025, 9:36 PMyawkat
02/17/2025, 9:36 PMyawkat
02/17/2025, 9:43 PM@file:JsModule("kcd2dicesim-common-wasm-wasm-js")
@file:JsNonModule
but i would really only like the former. would it be better to fix this on the js side by fixing the import or on the wasm side by making the export non-module?yawkat
02/17/2025, 9:44 PMUncaught TypeError: wasmCalculateEv is not a function
think webpack-internal:///./kotlin/kcd2dicesim-web-app.js:684
lambda_5 webpack-internal:///./kotlin/kcd2dicesim-web-app.js:430
lambda webpack-internal:///./kotlin/kvision.js:12638
invokeHandler webpack-internal:///../../node_modules/snabbdom/build/modules/eventlisteners.js:8
handleEvent webpack-internal:///../../node_modules/snabbdom/build/modules/eventlisteners.js:22
handler webpack-internal:///../../node_modules/snabbdom/build/modules/eventlisteners.js:27
and looking at the js, wasmCalculateEv is just called bare, not on a module like i think it should be?Edoardo Luppi
02/17/2025, 9:45 PMjs()
capability, and make the js
tasks depend on the wasmJs
ones, than move the outputted WASM binary into js
resources.
At this point you can depend directly from web-app to common-wasm using js
source sets.
but the javascript external functions try to use a non-module function. it's forcing me to useDid you set
useEsModules()
in the web-app project?yawkat
02/17/2025, 9:46 PMuseEsModules
seems to have broken a bunch of other things 🙂yawkat
02/17/2025, 9:47 PMEdoardo Luppi
02/17/2025, 9:47 PMyawkat
02/17/2025, 9:47 PMEdoardo Luppi
02/17/2025, 9:48 PMyawkat
02/17/2025, 9:49 PMyawkat
02/17/2025, 9:51 PMyawkat
02/17/2025, 9:51 PMEdoardo Luppi
02/17/2025, 9:52 PM- web-app
js()
- wasm-module
wasmJs()
js() <-- This simply wraps what is outputted by the wasmJs tasks.
You basically do the wrapping work here, instead of doing it in web-app
You then have the following in your web-app Gradle script:
jsMain {
dependencies {
implementation(project(":wasm-module"))
}
}
yawkat
02/17/2025, 9:52 PMEdoardo Luppi
02/17/2025, 9:54 PMwasm-module
you could even play with expect-actual to mandate functions' implementations between js
and wasmJs
source sets, ensuring signatures stay the same.yawkat
02/17/2025, 9:55 PMyawkat
02/17/2025, 9:56 PMEdoardo Luppi
02/17/2025, 9:57 PMwasm-module:js would still be IR that is consumed by the web-app:js compiler after allYes, but the
js
functions' implementations would load and call the WASM binary - through the JS wrapper - that you now have in your js
resources, thanks to having a dependency to the wasmJs
tasksEdoardo Luppi
02/17/2025, 9:58 PMyawkat
02/17/2025, 9:58 PMyawkat
02/17/2025, 9:58 PMEdoardo Luppi
02/17/2025, 9:58 PMwasmJs
compilation tasksEdoardo Luppi
02/17/2025, 10:01 PMEdoardo Luppi
02/17/2025, 10:02 PMyawkat
02/17/2025, 10:02 PMyawkat
02/17/2025, 10:03 PMyawkat
02/17/2025, 10:04 PMimport { instantiate } from './kcd2dicesim-common-wasm-wasm-js.uninstantiated.mjs';
const exports = (await instantiate({
})).exports;
export const {
wasmCalculateEv,
wasmGetMoveKeep,
wasmGetMoveShouldContinue,
memory,
_initialize,
startUnitTests
} = exports;
yawkat
02/17/2025, 10:08 PMEdoardo Luppi
02/17/2025, 10:08 PMjs
source set you'll simply use @JsModule("wasm-wrapper.js")
, there is no need to use useEsModules()
or useCommonJs()
because you're simply building a multiplatform library.
In the web-app side, on the other hand, you'll be somewhat forced to use useEsModules()
, as that's how the JS wrapper exports those functions.yawkat
02/17/2025, 10:09 PMyawkat
02/17/2025, 10:10 PMEdoardo Luppi
02/17/2025, 10:11 PMEdoardo Luppi
02/17/2025, 10:13 PMyawkat
02/17/2025, 10:14 PMyawkat
02/17/2025, 10:15 PMEdoardo Luppi
02/17/2025, 10:17 PMVampire
02/17/2025, 10:58 PMEdoardo Luppi
02/18/2025, 1:19 AMyawkat
02/18/2025, 10:28 AMimport {
wasmCalculateEv,
wasmGetMoveKeep,
wasmGetMoveShouldContinue
} from "./kcd2dicesim-common-wasm-wasm-js.mjs";
window.wasmCalculateEv = wasmCalculateEv;
window.wasmGetMoveKeep = wasmGetMoveKeep;
window.wasmGetMoveShouldContinue = wasmGetMoveShouldContinue;
ugly but it does the job.yawkat
02/18/2025, 12:39 PMval commonWasm = project.parent!!.project("common-wasm")
kotlin {
...
sourceSets["jsMain"].resources.srcDir(commonWasm.layout.buildDirectory.dir("dist/wasmJs/productionLibrary").get().asFile)
}
tasks.named("jsProcessResources").configure {
dependsOn(commonWasm.tasks.named("wasmJsNodeProductionLibraryDistribution"))
}
yawkat
02/18/2025, 12:40 PMEdoardo Luppi
02/18/2025, 12:42 PMyawkat
02/18/2025, 12:43 PMEdoardo Luppi
02/18/2025, 11:29 PMval instrumentedJars by configurations.creating ...
It looks familiar to what is used in KGP, so I'd say the answer might be yes.
I also recall seeing attributes mentioned when discussing multiple js()
targets, to distinguish themVampire
02/18/2025, 11:35 PMVampire
02/18/2025, 11:45 PMidea-debugger-enhancer
and add Kotlin support and actually make it work with latest IJ versions 😉)