I love the idea and execution. I did some reading of the code webcc and it's just brilliantly simple, and delivers to the promise.
From the product perspective, it occupies a different market than Emscripten, and I don't see it's good comparison. Your product is borderline optimized to run C++ code on Web (and Coi is a cherry on top of that). Where Emscripten is made to make native C++ application to run on Web - without significant changes to the original source itself.
Now, the `webcc::fush()` - what are your thoughts about scalability of the op-codes parsing? Right now it's switch/case based.
The flushing part can be tricky, as I see cases when main logic doesn't care about immediate response/sharing data - and it would be good to have a single flush on the end of the frame, and sometimes you'd like to pass data from C++ while it's in its life scope. On top of that, I'd be no surprised that control of what flushes is lost.
(I'm speaking from a game developer perspective, some issues I'm thinking aloud might be exaggerated)
Last, some suggestion what would make developers more happy is to provide a way to change wasm compilation flags - as a C++ developer I'd love to compile debug wasm code with DWARF, so I can debug with C++ sources.
To wrap up - I'm very impressed about the idea and execution. Phenomenal work!
You're right about the market positioning - WebCC isn't trying to be Emscripten. It's for when you want to build for the web, not just on the web. I'm actually using it myself to port my game engine, currently in the process of ripping out Emscripten entirely.
On the opcode parsing - the switch/case approach is intentionally simple and surprisingly fast. Modern compilers turn dense switch statements into jump tables, so it's essentially O(1) dispatch.
Your flush timing concern is understandable, but the architecture actually handles this cleanly. Buffered commands accumulate, and anything that returns a value auto-flushes first to guarantee correct ordering. For game loops, the natural pattern is batch everything during your frame logic, single flush at the end. You don't lose control, the auto-flush on sync calls ensures execution order is always maintained.
DWARF debug support is a great call