Skip to content

Commit 7346058

Browse files
authored
Enable transformations when detecting target features (#4133)
1 parent 532f30a commit 7346058

File tree

3 files changed

+60
-0
lines changed

3 files changed

+60
-0
lines changed

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@
2020
* Added bindings for the draft [WebRTC Encoded Transform](https://www.w3.org/TR/webrtc-encoded-transform) spec.
2121
[#4125](https://github.com/rustwasm/wasm-bindgen/pull/4125)
2222

23+
### Changed
24+
25+
* Implicitly enable reference type and multivalue transformations if the module already makes use of the corresponding target features.
26+
[#4133](https://github.com/rustwasm/wasm-bindgen/pull/4133)
27+
2328
### Fixed
2429

2530
* Fixed linked modules emitting snippet files when not using `--split-linked-modules`.

crates/cli-support/src/lib.rs

+11
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,17 @@ impl Bindgen {
323323
.context("failed getting Wasm module")?,
324324
};
325325

326+
// Enable reference type transformations if the module is already using it.
327+
if let Ok(true) = wasm_bindgen_wasm_conventions::target_feature(&module, "reference-types")
328+
{
329+
self.externref = true;
330+
}
331+
332+
// Enable multivalue transformations if the module is already using it.
333+
if let Ok(true) = wasm_bindgen_wasm_conventions::target_feature(&module, "multivalue") {
334+
self.multi_value = true;
335+
}
336+
326337
// Check that no exported symbol is called "default" if we target web.
327338
if matches!(self.mode, OutputMode::Web)
328339
&& module.exports.iter().any(|export| export.name == "default")

crates/wasm-conventions/src/lib.rs

+44
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,50 @@ pub fn get_or_insert_start_builder(module: &mut Module) -> &mut FunctionBuilder
177177
.builder_mut()
178178
}
179179

180+
pub fn target_feature(module: &Module, feature: &str) -> Result<bool> {
181+
// Taken from <https://github.com/bytecodealliance/wasm-tools/blob/f1898f46bb9d96f0f09682415cb6ccfd6a4dca79/crates/wasmparser/src/limits.rs#L27>.
182+
anyhow::ensure!(feature.len() <= 100_000, "feature name too long");
183+
184+
// Try to find an existing section.
185+
let section = module
186+
.customs
187+
.iter()
188+
.find(|(_, custom)| custom.name() == "target_features");
189+
190+
if let Some((_, section)) = section {
191+
let section: &RawCustomSection = section
192+
.as_any()
193+
.downcast_ref()
194+
.context("failed to read section")?;
195+
let mut reader = BinaryReader::new(&section.data, 0, WasmFeatures::default());
196+
// The first integer contains the target feature count.
197+
let count = reader.read_var_u32()?;
198+
199+
// Try to find if the target feature is already present.
200+
for _ in 0..count {
201+
// First byte is the prefix.
202+
let prefix = reader.read_u8()?;
203+
// Read the feature.
204+
let length = reader.read_var_u32()?;
205+
let this_feature = reader.read_bytes(length as usize)?;
206+
207+
// If we found the target feature, we are done here.
208+
if this_feature == feature.as_bytes() {
209+
// Make sure we set any existing prefix to "enabled".
210+
if prefix == b'-' {
211+
return Ok(false);
212+
}
213+
214+
return Ok(true);
215+
}
216+
}
217+
218+
Ok(false)
219+
} else {
220+
Ok(false)
221+
}
222+
}
223+
180224
pub fn insert_target_feature(module: &mut Module, new_feature: &str) -> Result<()> {
181225
// Taken from <https://github.com/bytecodealliance/wasm-tools/blob/f1898f46bb9d96f0f09682415cb6ccfd6a4dca79/crates/wasmparser/src/limits.rs#L27>.
182226
anyhow::ensure!(new_feature.len() <= 100_000, "feature name too long");

0 commit comments

Comments
 (0)