@@ -4,6 +4,7 @@ use std::mem;
44use decode;
55use failure:: { Error , ResultExt } ;
66use parity_wasm:: elements:: * ;
7+ use parity_wasm:: elements:: Error as ParityError ;
78use shared;
89use 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
20182122impl < ' a , ' b > SubContext < ' a , ' b > {
0 commit comments