@@ -65,9 +65,9 @@ pub struct Opts {
6565 )
6666 ) ]
6767 pub instantiation : bool ,
68- /// Inline core WebAssembly modules as base64 strings.
69- #[ cfg_attr( feature = "clap" , arg( long, conflicts_with = "instantiation" ) ) ]
70- pub base64 : bool ,
68+ /// Specify how generated WebAssembly core modules are loaded
69+ #[ cfg_attr( feature = "clap" , arg( long, conflicts_with = "instantiation" , value_enum , default_value_t = Load :: Fetch ) ) ]
70+ pub load : Load ,
7171 /// Comma-separated list of "from-specifier=./to-specifier.js" mappings of
7272 /// component import specifiers to JS import specifiers.
7373 #[ cfg_attr( feature = "clap" , arg( long) , clap( value_parser = maps_str_to_map) ) ]
@@ -91,6 +91,18 @@ pub struct Opts {
9191 pub valid_lifting_optimization : bool ,
9292}
9393
94+ #[ derive( Debug , Clone , Default ) ]
95+ #[ cfg_attr( feature = "clap" , derive( clap:: ValueEnum ) ) ]
96+ pub enum Load {
97+ /// Fetch core WebAssembly modules as separate files.
98+ #[ default]
99+ Fetch ,
100+ /// Inline core WebAssembly modules as base64 strings.
101+ Base64 ,
102+ /// Define custom scoped loadWasm & instantiateWasm functions.
103+ Custom ,
104+ }
105+
94106impl Opts {
95107 pub fn build ( self ) -> Result < Box < dyn ComponentGenerator > > {
96108 let mut gen = Js :: default ( ) ;
@@ -113,8 +125,9 @@ enum Intrinsic {
113125 GetErrorPayload ,
114126 HasOwnProperty ,
115127 I32ToF32 ,
116- IsLE ,
117128 I64ToF64 ,
129+ InstantiateWasm ,
130+ IsLE ,
118131 LoadWasm ,
119132 ThrowInvalidBool ,
120133 ThrowUninitialized ,
@@ -156,8 +169,9 @@ impl Intrinsic {
156169 Intrinsic :: GetErrorPayload => "getErrorPayload" ,
157170 Intrinsic :: HasOwnProperty => "hasOwnProperty" ,
158171 Intrinsic :: I32ToF32 => "i32ToF32" ,
159- Intrinsic :: IsLE => "isLE" ,
160172 Intrinsic :: I64ToF64 => "i64ToF64" ,
173+ Intrinsic :: InstantiateWasm => "instantiateWasm" ,
174+ Intrinsic :: IsLE => "isLE" ,
161175 Intrinsic :: LoadWasm => "loadWasm" ,
162176 Intrinsic :: ThrowInvalidBool => "throwInvalidBool" ,
163177 Intrinsic :: ThrowUninitialized => "throwUninitialized" ,
@@ -279,19 +293,31 @@ impl ComponentGenerator for Js {
279293 }
280294 }
281295
282- if self . opts . base64 && self . core_module_cnt > 0 {
296+ if !self . opts . instantiation
297+ && !matches ! ( self . opts. load, Load :: Custom )
298+ && self . core_module_cnt > 0
299+ {
283300 let mut first = true ;
284- output . push_str ( "const " ) ;
301+ uwrite ! ( output , "const " ) ;
285302 for i in 0 ..self . core_module_cnt {
286303 if first {
287304 first = false ;
288305 } else {
289- output. push_str ( ", " ) ;
306+ uwriteln ! ( output, "," ) ;
307+ }
308+ let name = self . core_file_name ( name, i as u32 ) ;
309+ match self . opts . load {
310+ Load :: Fetch => {
311+ uwrite ! ( output, "CORE{i} = new URL('./{name}', import.meta.url)" )
312+ }
313+ Load :: Base64 => {
314+ let data = files. remove ( & name) . unwrap ( ) ;
315+ uwrite ! ( output, "CORE{i} = '{}'" , base64:: encode( & data) ) ;
316+ }
317+ Load :: Custom => { }
290318 }
291- let data = files. remove ( & self . core_file_name ( name, i as u32 ) ) . unwrap ( ) ;
292- uwrite ! ( output, "BINARY{i} = '{}'" , base64:: encode( & data) ) ;
293319 }
294- output . push_str ( ";" ) ;
320+ uwriteln ! ( output , ";" ) ;
295321 }
296322
297323 let ( maybe_init_export, maybe_init) = if self . opts . tla_compat {
@@ -526,31 +552,39 @@ impl Js {
526552 const dataView = mem => dv.buffer === mem.buffer ? dv : dv = new DataView(mem.buffer);
527553 " ) ,
528554
529- Intrinsic :: LoadWasm => if self . opts . base64 {
530- if self . opts . nodejs_compat {
555+ Intrinsic :: LoadWasm => match self . opts . load {
556+ Load :: Fetch => if self . opts . nodejs_compat {
557+ self . src . js_intrinsics ( "
558+ const isNode = typeof process !== 'undefined' && process.versions && process.versions.node;
559+ let _fs;
560+ async function loadWasm (url) {
561+ if (isNode) {
562+ _fs = _fs || await import('fs/promises');
563+ return WebAssembly.compile(await _fs.readFile(url));
564+ }
565+ return fetch(url).then(WebAssembly.compileStreaming);
566+ }
567+ " )
568+ } else {
569+ self . src . js_intrinsics ( "
570+ const loadWasm = url => fetch(url).then(WebAssembly.compileStreaming);
571+ " )
572+ } ,
573+ Load :: Base64 => if self . opts . nodejs_compat {
531574 self . src . js_intrinsics ( "
532575 const loadWasm = str => WebAssembly.compile(typeof Buffer !== 'undefined' ? Buffer.from(str, 'base64') : Uint8Array.from(atob(str), b => b.charCodeAt(0)));
533576 " )
534577 } else {
535578 self . src . js_intrinsics ( "
536579 const loadWasm = str => WebAssembly.compile(Uint8Array.from(atob(str), b => b.charCodeAt(0)));
537580 " )
538- }
539- } else if self . opts . nodejs_compat {
540- self . src . js_intrinsics ( "
541- const isNode = typeof process !== 'undefined' && process.versions && process.versions.node;
542- let _fs;
543- async function loadWasm (url) {
544- if (isNode) {
545- _fs = _fs || await import('fs/promises');
546- return WebAssembly.compile(await _fs.readFile(url));
547- }
548- return fetch(url).then(WebAssembly.compileStreaming);
549- }
550- " )
551- } else {
581+ } ,
582+ Load :: Custom => { } ,
583+ } ,
584+
585+ Intrinsic :: InstantiateWasm => if !matches ! ( self . opts. load, Load :: Custom ) {
552586 self . src . js_intrinsics ( "
553- const loadWasm = url => fetch(url).then( WebAssembly.compileStreaming) ;
587+ const instantiateWasm = WebAssembly.instantiate ;
554588 " )
555589 } ,
556590
@@ -826,22 +860,16 @@ impl Instantiator<'_> {
826860 for init in self . component . initializers . iter ( ) {
827861 if let GlobalInitializer :: InstantiateModule ( InstantiateModule :: Static ( idx, _) ) = init {
828862 // Get the compiled WebAssembly.Module objects in parallel
829- let local_name = format ! ( "module{}" , idx. as_u32( ) ) ;
830- let name = self . gen . core_file_name ( & self . name , idx. as_u32 ( ) ) ;
863+ let idx_num = idx. as_u32 ( ) ;
864+ let local_name = format ! ( "module{}" , idx_num) ;
865+ let name = self . gen . core_file_name ( & self . name , idx_num) ;
831866 if self . gen . opts . instantiation {
832867 uwriteln ! ( self . src. js, "const {local_name} = compileCore('{name}');" ) ;
833- } else if self . gen . opts . base64 {
834- let load_wasm = self . gen . intrinsic ( Intrinsic :: LoadWasm ) ;
835- let idx_num = idx. as_u32 ( ) ;
836- uwriteln ! (
837- self . src. js_init,
838- "const {local_name} = {load_wasm}(BINARY{idx_num});"
839- ) ;
840868 } else {
841869 let load_wasm = self . gen . intrinsic ( Intrinsic :: LoadWasm ) ;
842870 uwriteln ! (
843871 self . src. js_init,
844- "const {local_name} = {load_wasm}(new URL('./{name}', import.meta.url) );"
872+ "const {local_name} = {load_wasm}(CORE{idx_num} );"
845873 ) ;
846874 }
847875 }
@@ -979,11 +1007,12 @@ impl Instantiator<'_> {
9791007
9801008 let i = self . instances . push ( idx) ;
9811009 let iu32 = i. as_u32 ( ) ;
1010+ let instantiate = self . gen . intrinsic ( Intrinsic :: InstantiateWasm ) ;
9821011 uwriteln ! ( self . src. js, "let exports{iu32};" ) ;
9831012 uwriteln ! (
9841013 self . src. js_init,
9851014 "
986- ({{ exports: exports{iu32} }} = await WebAssembly. instantiate(await module{}{imports}));\
1015+ ({{ exports: exports{iu32} }} = await { instantiate} (await module{}{imports}));\
9871016 ",
9881017 idx. as_u32( )
9891018 ) ;
0 commit comments