Skip to content

Commit 92d5ca1

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 992fad8 commit 92d5ca1

File tree

1 file changed

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

1 file changed

+103
-0
lines changed

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

Lines changed: 103 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,107 @@ 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() + 1) as u8,
2041+
b'p', b'r', b'o', b'd', b'u', b'c', b'e', b'r', b's',
2042+
0,
2043+
];
2044+
let mut section = CustomSection::deserialize(&mut &data[..]).unwrap();
2045+
assert_eq!(section.name(), "producers");
2046+
assert_eq!(section.payload(), [0]);
2047+
drop(update(&mut section));
2048+
self.module.sections_mut().push(Section::Custom(section));
2049+
2050+
fn update(section: &mut CustomSection) -> Result<(), ParityError> {
2051+
struct Field {
2052+
name: String,
2053+
values: Vec<FieldValue>,
2054+
}
2055+
struct FieldValue {
2056+
name: String,
2057+
version: String,
2058+
}
2059+
2060+
let wasm_bindgen = || {
2061+
FieldValue {
2062+
name: "wasm-bindgen".to_string(),
2063+
version: shared::version(),
2064+
}
2065+
};
2066+
let mut fields = Vec::new();
2067+
2068+
// Deserialize the fields, appending the wasm-bidngen field/value
2069+
// where applicable
2070+
{
2071+
let mut data = section.payload();
2072+
let amt: u32 = VarUint32::deserialize(&mut data)?.into();
2073+
let mut found_processed_by = false;
2074+
for _ in 0..amt {
2075+
let name = String::deserialize(&mut data)?;
2076+
let cnt: u32 = VarUint32::deserialize(&mut data)?.into();
2077+
let mut values = Vec::with_capacity(cnt as usize);
2078+
for _ in 0..cnt {
2079+
let name = String::deserialize(&mut data)?;
2080+
let version = String::deserialize(&mut data)?;
2081+
values.push(FieldValue { name, version });
2082+
}
2083+
2084+
if name == "processed-by" {
2085+
found_processed_by = true;
2086+
values.push(wasm_bindgen());
2087+
}
2088+
2089+
fields.push(Field { name, values });
2090+
}
2091+
if data.len() != 0 {
2092+
return Err(ParityError::InconsistentCode)
2093+
}
2094+
2095+
if !found_processed_by {
2096+
fields.push(Field {
2097+
name: "processed-by".to_string(),
2098+
values: vec![wasm_bindgen()],
2099+
});
2100+
}
2101+
}
2102+
2103+
// re-serialize these fields back into the custom section
2104+
let dst = section.payload_mut();
2105+
dst.truncate(0);
2106+
VarUint32::from(fields.len() as u32).serialize(dst)?;
2107+
for field in fields.iter() {
2108+
field.name.clone().serialize(dst)?;
2109+
VarUint32::from(field.values.len() as u32).serialize(dst)?;
2110+
for value in field.values.iter() {
2111+
value.name.clone().serialize(dst)?;
2112+
value.version.clone().serialize(dst)?;
2113+
}
2114+
}
2115+
2116+
Ok(())
2117+
}
2118+
}
20162119
}
20172120

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

0 commit comments

Comments
 (0)