Start function or `export "_start"`?
Now MoonBit is generating the following code:
(export "_start" (func $*init*/5))
Looks like the WASM Start Function is precisely the same thing:
(start $*init*/5)
I can confirm the Start Function works fine on Chrome 120.0.6099.199 and wasmtime 17.0.0 (component).
Q: why do we generate export "_start" in the first place?
The issue here is with component model - the core wasm exports are not visible to component runtimes, I had to rewrite export "_start" to start with a hack, without which MoonBit modules couldn't initialize.
The issue with the start function is that we can't use any FFI that relies on the current module. That's the same reason why WASI preview 1 defined another function _start as entrance, because the FFI relies the exported memory of the module.
The initialization step and main execution logic may get separated. And if I understand correctly, the component model also allows a start function that may have arbitrary inputs & outputs which may get things more complicated.
The issue with the start function is that we can't use any FFI that relies on the current module. That's the same reason why WASI preview 1 defined another function _start as entrance, because the FFI relies the exported memory of the module.
I see, thanks for explaining! But why allowing calling FFI functions in the initializer? I thought initializers are pure module local initialization, setting global values, etc. On the other hand, feels like the on-load hook could be a user-space kinda thing.
The initialization step and main execution logic may get separated.
Oh, is "main execution logic" the same thing as I understood as "on-load hook"? Did you mean it is already considered that maybe someday fn init maps only to the start function, while creating something new for the on-load hook?
As in the playground and in the case of wasi, the wasm can be used as the main executable, so it contains the initialization + 'on-load hook'. Other cases (such as those in the gallery) we embed the wasm as a library and it should only contains the initialization.
I think you are right about it could be a user-space kinda thing. If we resolve #151 and #152, the WASI preview 1 case can definately be handled by a single pub function in the user-space. The playground can be replaced with initiailization + inline test.
As of whether FFI calling should be allowed in the initializer, it is an interesting question. I don't have a lot of opinions with that yet.
The init function will become start function after today's release. If there's anything that relies on the initialized instance, then user can export a public function, such as
pub fn initialize() -> Unit {
}
or
pub fn start() -> Unit {
}
and define the alias in the moon.pkg.json