Skip to content

Commit 6f1e3c8

Browse files
committed
Add wasm-bindgen to the producers section
Recently proposed in WebAssembly/tool-conventions#65 each wasm file will now have an optional `producers` section listing the tooling that went into producing it. Let's add `wasm-bindgen` in when it processes a wasm file!
1 parent f741ccd commit 6f1e3c8

File tree

1 file changed

+104
-0
lines changed
  • crates/cli-support/src/js

1 file changed

+104
-0
lines changed

crates/cli-support/src/js/mod.rs

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::mem;
44
use decode;
55
use failure::{Error, ResultExt};
66
use parity_wasm::elements::*;
7+
use parity_wasm::elements::Error as ParityError;
78
use shared;
89
use gc;
910

@@ -475,6 +476,7 @@ impl<'a> Context<'a> {
475476
})?;
476477

477478
self.rewrite_imports(module_name);
479+
self.update_producers_section();
478480

479481
let mut js = if self.config.threads.is_some() {
480482
// TODO: It's not clear right now how to best use threads with
@@ -2013,6 +2015,108 @@ impl<'a> Context<'a> {
20132015
ImportTarget::Method(format!("{}_target", import.shim))
20142016
})
20152017
}
2018+
2019+
/// Update the wasm file's `producers` section to include information about
2020+
/// the wasm-bindgen tool.
2021+
///
2022+
/// Specified at:
2023+
/// https://github.com/WebAssembly/tool-conventions/blob/master/ProducersSection.md
2024+
fn update_producers_section(&mut self) {
2025+
for section in self.module.sections_mut() {
2026+
let section = match section {
2027+
Section::Custom(s) => s,
2028+
_ => continue,
2029+
};
2030+
if section.name() != "producers" {
2031+
return
2032+
}
2033+
drop(update(section));
2034+
return
2035+
}
2036+
2037+
// `CustomSection::new` added in paritytech/parity-wasm#244 which isn't
2038+
// merged just yet
2039+
let data = [
2040+
("producers".len() + 2) as u8,
2041+
"producers".len() as u8,
2042+
b'p', b'r', b'o', b'd', b'u', b'c', b'e', b'r', b's',
2043+
0,
2044+
];
2045+
let mut section = CustomSection::deserialize(&mut &data[..]).unwrap();
2046+
assert_eq!(section.name(), "producers");
2047+
assert_eq!(section.payload(), [0]);
2048+
drop(update(&mut section));
2049+
self.module.sections_mut().push(Section::Custom(section));
2050+
2051+
fn update(section: &mut CustomSection) -> Result<(), ParityError> {
2052+
struct Field {
2053+
name: String,
2054+
values: Vec<FieldValue>,
2055+
}
2056+
struct FieldValue {
2057+
name: String,
2058+
version: String,
2059+
}
2060+
2061+
let wasm_bindgen = || {
2062+
FieldValue {
2063+
name: "wasm-bindgen".to_string(),
2064+
version: shared::version(),
2065+
}
2066+
};
2067+
let mut fields = Vec::new();
2068+
2069+
// Deserialize the fields, appending the wasm-bidngen field/value
2070+
// where applicable
2071+
{
2072+
let mut data = section.payload();
2073+
let amt: u32 = VarUint32::deserialize(&mut data)?.into();
2074+
let mut found_processed_by = false;
2075+
for _ in 0..amt {
2076+
let name = String::deserialize(&mut data)?;
2077+
let cnt: u32 = VarUint32::deserialize(&mut data)?.into();
2078+
let mut values = Vec::with_capacity(cnt as usize);
2079+
for _ in 0..cnt {
2080+
let name = String::deserialize(&mut data)?;
2081+
let version = String::deserialize(&mut data)?;
2082+
values.push(FieldValue { name, version });
2083+
}
2084+
2085+
if name == "processed-by" {
2086+
found_processed_by = true;
2087+
values.push(wasm_bindgen());
2088+
}
2089+
2090+
fields.push(Field { name, values });
2091+
}
2092+
if data.len() != 0 {
2093+
return Err(ParityError::InconsistentCode)
2094+
}
2095+
2096+
if !found_processed_by {
2097+
fields.push(Field {
2098+
name: "processed-by".to_string(),
2099+
values: vec![wasm_bindgen()],
2100+
});
2101+
}
2102+
}
2103+
2104+
// re-serialize these fields back into the custom section
2105+
let dst = section.payload_mut();
2106+
dst.truncate(0);
2107+
VarUint32::from(fields.len() as u32).serialize(dst)?;
2108+
for field in fields.iter() {
2109+
field.name.clone().serialize(dst)?;
2110+
VarUint32::from(field.values.len() as u32).serialize(dst)?;
2111+
for value in field.values.iter() {
2112+
value.name.clone().serialize(dst)?;
2113+
value.version.clone().serialize(dst)?;
2114+
}
2115+
}
2116+
2117+
Ok(())
2118+
}
2119+
}
20162120
}
20172121

20182122
impl<'a, 'b> SubContext<'a, 'b> {

0 commit comments

Comments
 (0)