This is a very Proof of Concept execution of this feature. Notable limitations:
only implemented for interpret and not jit
does no checking to make sure that feature name hashes do not collide
adds a new public function to the proc_macro2 to be the wasm-side feature check
this should probably be a distinct crate used by the wasm-side implementation
thus the watt runtime should gracefully (ish: probably a nice panic message) error if the required symbol to publish features aren't there
wasm-side implementation uses a static mut as opposed to a more principled shared global
But this implementation does work!
D:\repos\dtolnay\watt\demo\caller>cargo run --quiet --features=""
message=Hello from WASM! My name is S.
D:\repos\dtolnay\watt\demo\caller>cargo run --quiet --features="feat_a"
message=Hello from WASM! My name is S. feat_a is enabled.
D:\repos\dtolnay\watt\demo\caller>cargo run --quiet --features="feat_b"
message=Hello from WASM! My name is S. feat_b is enabled.
D:\repos\dtolnay\watt\demo\caller>cargo run --quiet --features="feat_a feat_b"
message=Hello from WASM! My name is S. feat_a is enabled. feat_b is enabled.
Simple overview of how the feature information flows into the wasm module:
WasmMacro is created with watt::wasm_macro_features!. This takes the wasm binary to wrap as well as a list of feature strings.
The wasm binary as well as a static array of the enabled features is passed to WasmMacro::new_with_features. This function, while necessarily public to be called by the macro, is hidden and not public API. This is so that the only named bits of information injected are the enabled (and opted-in) cargo features.
WasmMacro just holds the list of features that it has been told are enabled.
When the wasm module is instantiated, but before any other code is run, we call the __watt_publish_feature function of the wasm library with the FNV-1a hash of all enabled feature strings.
__watt_publish_feature takes a single 32 bit integer as input and stores it in a static mut sorted vector of enabled feature hashes.
this is (most likely) sound because the location is only ever used mutably at module creation time.
At macro time, the macro calls proc_macro2::features::check("feature_name")
The feature name is turned into its FNV-1a hash again, and the feature list is checked for that hash.
While the details of an impl may change, the rough shape will stay the same:
Collect a list of features to pass through
Compress each feature to a primitive wasm ffi understands
At module instantiation time, fire a message to the wasm for each feature
At macro runtime, query a global populated with the enabled features
The wasm interface types proposal could potentially allow passing an "abstract string" more simply, but for the time being, we have to compress the feature string into a 32 bit or 64 bit integer via some hash function.
Closes #35
This is a very Proof of Concept execution of this feature. Notable limitations:
proc_macro2
to be the wasm-side feature checkstatic mut
as opposed to a more principled shared globalBut this implementation does work!
Simple overview of how the feature information flows into the wasm module:
WasmMacro
is created withwatt::wasm_macro_features!
. This takes the wasm binary to wrap as well as a list of feature strings.WasmMacro::new_with_features
. This function, while necessarily public to be called by the macro, is hidden and not public API. This is so that the only named bits of information injected are the enabled (and opted-in) cargo features.WasmMacro
just holds the list of features that it has been told are enabled.__watt_publish_feature
function of the wasm library with the FNV-1a hash of all enabled feature strings.__watt_publish_feature
takes a single 32 bit integer as input and stores it in astatic mut
sorted vector of enabled feature hashes.proc_macro2::features::check("feature_name")
While the details of an impl may change, the rough shape will stay the same:
The wasm interface types proposal could potentially allow passing an "abstract string" more simply, but for the time being, we have to compress the feature string into a 32 bit or 64 bit integer via some hash function.