fix(bindgen): use IndexMap for deterministic export iteration order#1373
Open
wondenge wants to merge 1 commit intobytecodealliance:mainfrom
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Running
jco transpileon the same unchanged component twice can produce different JS output. ThepostReturnandcallbackvariable assignments pick different representative export names across runs. This shows up when multiplecabi_post_*or[callback]exports alias the same core function, which wit-bindgen does pretty commonly for shared deallocation logic. The wasm is correct and runtime behaviour is fine. It is just the JS picking a different name each time, which breaks reproducible builds and makes diffing transpiled output unreliable.Translation::exports()returns aHashMap<String, EntityIndex>, and whencore_export_var_nameiterates it withfind_mapto resolve a function index back to an export name,HashMap's iteration order varies between runs (Rust randomizes the hash seed per process). This changed from&IndexMaptoHashMapin39e6972dduring the wasmtime deps update whenModule.exportsmoved toAtomkeyed maps, the conversion toStringkeys needed a new map, andHashMapwas picked instead ofIndexMap.This PR switches the return type back to
IndexMapso export iteration preserves wasm binary order.indexmap = "2"is added toCargo.tomlas it's already inCargo.lock(resolves to 2.13.0) as a transitive dependency, so no new crates to pull in. Verified across 5 transpile runs on the same component and the output is now identical every time. Also tested with an instrumented component (additional imports, trampolines, multi-memory) same result, fully deterministic.Before: Two runs of the same component produced different JS:
After: Five runs, identical output every time
diffis now empty: