Stream: jco

Topic: Fixing #1393


view this post on Zulip QuantumSegfault (Apr 17 2026 at 04:40):

@Victor Adossi

I'm working on fixing #1393.

Things are going relatively smoothly, but I do have one question: where can I put some "global" state?

asm.js returns the high 32-bits of i64 by making a call to an import of env.setTempRet0 before the actual return of the low bits

I need some safe place to store the data so I can retrieve it immediately after the call finishes.

So far I rewrite the export invocation to look like this:

const started = task.enterSync();
      let ret =   _withGlobalCurrentTaskMeta({
        taskID: task.id(),
        componentIdx: task.componentIdx(),
        fn: () => mergeInt64(exports0Add(...(splitInt64(toUint64(arg0))), ...(splitInt64(toUint64(arg1)))), /* <some way to get the tmp high bits> */),
      });

I added mergeInt64 and splitInt64 ConversionIntrinsics and inserted them when a core Wasm signature for a call takes or yields i64

Where would be the correct spot to handle this temporary global state? There's AsyncTask, AsyncSubtask, and ComponentAsyncState at least. And then I saw something about "trampolines", which may be relavent here? Any ideas?

view this post on Zulip Victor Adossi (Apr 17 2026 at 05:36):

hey @QuantumSegfault thanks for the hard work on this (diving into the js-component-bindgen codebase isn't easy, I think!).

If I'm understanding correctly, storing on the task itself seems like a good way to go, especially since this is tied to a particular call (and at this point due to the p3 changes underneath, every call should result in a somewhat-misnamed AsyncTask being created).

Where would be the correct spot to handle this temporary global state? There's AsyncTask, AsyncSubtask, and ComponentAsyncState at least. And then I saw something about "trampolines", which may be relavent here? Any ideas?

Looks like we need some docs in this area, so I've taken a note to try and add some. For now though:

Trampolines (e.g. Trampoline::CallWasm) are actually the pieces of code that get called during wasm execution when either a canonical built in (e.g. resource.new) is called, or when a FACT module special operation (e.g. Trampoline::StreamTransfer) which is injected by toolchains like wasmtime are called.

I think the right place to add this extra state is on the AsynctTask since this is call-related -- you can of course gate the functionality by whether we are transpiling to JS or not (please let me know if that option isn't available -- I just actually made a change to the codebase to enable transpile options to be accessed during Intrinsic::render)!

I added mergeInt64 and splitInt64 ConversionIntrinsics and inserted them when a core Wasm signature for a call takes or yields i64

As a separate note -- this sounds like you're doing it exactly the right way with respect to how the codebase is written right now.

That said, I would appreciate any feedback on things you found weird/annoying about the current organization of the codebase -- there is a lot of cleanup/simplification that needs to be done, and breaking out the intrinsics was a step I did a long time ago to attempt to add order into the chaos.

For example, on the horizon I want to break out all the Intrinsics to an external package and use them so that we can finally just write regular TS/JS code against some interface that lists out all the required functions.


Last updated: May 03 2026 at 22:13 UTC