@@ -6,7 +6,7 @@ use crate::webidl::{AuxValue, Binding};
6
6
use crate :: webidl:: { JsImport , JsImportName , NonstandardWebidlSection , WasmBindgenAux } ;
7
7
use crate :: { Bindgen , EncodeInto , OutputMode } ;
8
8
use failure:: { bail, Error , ResultExt } ;
9
- use std:: collections:: { BTreeMap , HashMap , HashSet } ;
9
+ use std:: collections:: { BTreeMap , BTreeSet , HashMap , HashSet } ;
10
10
use std:: fs;
11
11
use std:: path:: { Path , PathBuf } ;
12
12
use walrus:: { ExportId , ImportId , MemoryId , Module } ;
@@ -248,7 +248,7 @@ impl<'a> Context<'a> {
248
248
OutputMode :: NoModules { global } => {
249
249
js. push_str ( "const __exports = {};\n " ) ;
250
250
js. push_str ( "let wasm;\n " ) ;
251
- init = self . gen_init ( needs_manual_start) ;
251
+ init = self . gen_init ( needs_manual_start, None ) ? ;
252
252
footer. push_str ( & format ! (
253
253
"self.{} = Object.assign(init, __exports);\n " ,
254
254
global
@@ -309,7 +309,7 @@ impl<'a> Context<'a> {
309
309
// as the default export of the module.
310
310
OutputMode :: Web => {
311
311
self . imports_post . push_str ( "let wasm;\n " ) ;
312
- init = self . gen_init ( needs_manual_start) ;
312
+ init = self . gen_init ( needs_manual_start, Some ( & mut imports ) ) ? ;
313
313
footer. push_str ( "export default init;\n " ) ;
314
314
}
315
315
}
@@ -435,7 +435,11 @@ impl<'a> Context<'a> {
435
435
)
436
436
}
437
437
438
- fn gen_init ( & mut self , needs_manual_start : bool ) -> ( String , String ) {
438
+ fn gen_init (
439
+ & mut self ,
440
+ needs_manual_start : bool ,
441
+ mut imports : Option < & mut String > ,
442
+ ) -> Result < ( String , String ) , Error > {
439
443
let module_name = "wbg" ;
440
444
let mem = self . module . memories . get ( self . memory ) ;
441
445
let ( init_memory1, init_memory2) = if let Some ( id) = mem. import {
@@ -495,6 +499,30 @@ impl<'a> Context<'a> {
495
499
imports_init. push_str ( ";\n " ) ;
496
500
}
497
501
502
+ let extra_modules = self
503
+ . module
504
+ . imports
505
+ . iter ( )
506
+ . filter ( |i| !self . wasm_import_definitions . contains_key ( & i. id ( ) ) )
507
+ . filter ( |i| {
508
+ // Importing memory is handled specially in this area, so don't
509
+ // consider this a candidate for importing from extra modules.
510
+ match i. kind {
511
+ walrus:: ImportKind :: Memory ( _) => false ,
512
+ _ => true ,
513
+ }
514
+ } )
515
+ . map ( |i| & i. module )
516
+ . collect :: < BTreeSet < _ > > ( ) ;
517
+ for ( i, extra) in extra_modules. iter ( ) . enumerate ( ) {
518
+ let imports = match & mut imports {
519
+ Some ( list) => list,
520
+ None => bail ! ( "cannot import from modules (`{}`) with `--no-modules`" , extra) ,
521
+ } ;
522
+ imports. push_str ( & format ! ( "import * as __wbg_star{} from '{}';\n " , i, extra) ) ;
523
+ imports_init. push_str ( & format ! ( "imports['{}'] = __wbg_star{};\n " , extra, i) ) ;
524
+ }
525
+
498
526
let js = format ! (
499
527
"\
500
528
function init(module{init_memory_arg}) {{
@@ -553,7 +581,7 @@ impl<'a> Context<'a> {
553
581
imports_init = imports_init,
554
582
) ;
555
583
556
- ( js, ts)
584
+ Ok ( ( js, ts) )
557
585
}
558
586
559
587
fn write_classes ( & mut self ) -> Result < ( ) , Error > {
@@ -1104,15 +1132,17 @@ impl<'a> Context<'a> {
1104
1132
//
1105
1133
// If `ptr` and `len` are both `0` then that means it's `None`, in that case we rely upon
1106
1134
// the fact that `getObject(0)` is guaranteed to be `undefined`.
1107
- self . global ( "
1135
+ self . global (
1136
+ "
1108
1137
function getCachedStringFromWasm(ptr, len) {
1109
1138
if (ptr === 0) {
1110
1139
return getObject(len);
1111
1140
} else {
1112
1141
return getStringFromWasm(ptr, len);
1113
1142
}
1114
1143
}
1115
- " ) ;
1144
+ " ,
1145
+ ) ;
1116
1146
Ok ( ( ) )
1117
1147
}
1118
1148
@@ -1730,7 +1760,8 @@ impl<'a> Context<'a> {
1730
1760
1731
1761
JsImportName :: LocalModule { module, name } => {
1732
1762
let unique_name = generate_identifier ( name, & mut self . defined_identifiers ) ;
1733
- add_module_import ( format ! ( "./snippets/{}" , module) , name, & unique_name) ;
1763
+ let module = self . config . local_module_name ( module) ;
1764
+ add_module_import ( module, name, & unique_name) ;
1734
1765
unique_name
1735
1766
}
1736
1767
@@ -1739,11 +1770,10 @@ impl<'a> Context<'a> {
1739
1770
snippet_idx_in_crate,
1740
1771
name,
1741
1772
} => {
1773
+ let module = self
1774
+ . config
1775
+ . inline_js_module_name ( unique_crate_identifier, * snippet_idx_in_crate) ;
1742
1776
let unique_name = generate_identifier ( name, & mut self . defined_identifiers ) ;
1743
- let module = format ! (
1744
- "./snippets/{}/inline{}.js" ,
1745
- unique_crate_identifier, snippet_idx_in_crate,
1746
- ) ;
1747
1777
add_module_import ( module, name, & unique_name) ;
1748
1778
unique_name
1749
1779
}
@@ -2014,16 +2044,11 @@ impl<'a> Context<'a> {
2014
2044
. types
2015
2045
. get :: < ast:: WebidlFunction > ( binding. webidl_ty )
2016
2046
. unwrap ( ) ;
2017
- let js = match import {
2047
+ match import {
2018
2048
AuxImport :: Value ( AuxValue :: Bare ( js) )
2019
2049
if !variadic && !catch && self . import_does_not_require_glue ( binding, webidl) =>
2020
2050
{
2021
- self . expose_not_defined ( ) ;
2022
- let name = self . import_name ( js) ?;
2023
- format ! (
2024
- "typeof {name} == 'function' ? {name} : notDefined('{name}')" ,
2025
- name = name,
2026
- )
2051
+ self . direct_import ( id, js)
2027
2052
}
2028
2053
_ => {
2029
2054
if assert_no_shim {
@@ -2048,11 +2073,11 @@ impl<'a> Context<'a> {
2048
2073
cx. invoke_import ( & binding, import, bindings, args, variadic, prelude)
2049
2074
} ,
2050
2075
) ?;
2051
- format ! ( "function{}" , js)
2076
+ self . wasm_import_definitions
2077
+ . insert ( id, format ! ( "function{}" , js) ) ;
2078
+ Ok ( ( ) )
2052
2079
}
2053
- } ;
2054
- self . wasm_import_definitions . insert ( id, js) ;
2055
- Ok ( ( ) )
2080
+ }
2056
2081
}
2057
2082
2058
2083
fn import_does_not_require_glue (
@@ -2078,6 +2103,69 @@ impl<'a> Context<'a> {
2078
2103
)
2079
2104
}
2080
2105
2106
+ /// Emit a direct import directive that hooks up the `js` value specified to
2107
+ /// the wasm import `id`.
2108
+ fn direct_import ( & mut self , id : ImportId , js : & JsImport ) -> Result < ( ) , Error > {
2109
+ // If there's no field projection happening here and this is a direct
2110
+ // import from an ES-looking module, then we can actually just hook this
2111
+ // up directly in the wasm file itself. Note that this is covered in the
2112
+ // various output formats as well:
2113
+ //
2114
+ // * `bundler` - they think wasm is an ES module anyway
2115
+ // * `web` - we're sure to emit more `import` directives during
2116
+ // `gen_init` and we update the import object accordingly.
2117
+ // * `nodejs` - the polyfill we have for requiring a wasm file as a node
2118
+ // module will naturally emit `require` directives for the module
2119
+ // listed on each wasm import.
2120
+ // * `no-modules` - imports aren't allowed here anyway from other
2121
+ // modules and an error is generated.
2122
+ if js. fields . len ( ) == 0 {
2123
+ match & js. name {
2124
+ JsImportName :: Module { module, name } => {
2125
+ let import = self . module . imports . get_mut ( id) ;
2126
+ import. module = module. clone ( ) ;
2127
+ import. name = name. clone ( ) ;
2128
+ return Ok ( ( ) ) ;
2129
+ }
2130
+ JsImportName :: LocalModule { module, name } => {
2131
+ let module = self . config . local_module_name ( module) ;
2132
+ let import = self . module . imports . get_mut ( id) ;
2133
+ import. module = module;
2134
+ import. name = name. clone ( ) ;
2135
+ return Ok ( ( ) ) ;
2136
+ }
2137
+ JsImportName :: InlineJs {
2138
+ unique_crate_identifier,
2139
+ snippet_idx_in_crate,
2140
+ name,
2141
+ } => {
2142
+ let module = self
2143
+ . config
2144
+ . inline_js_module_name ( unique_crate_identifier, * snippet_idx_in_crate) ;
2145
+ let import = self . module . imports . get_mut ( id) ;
2146
+ import. module = module;
2147
+ import. name = name. clone ( ) ;
2148
+ return Ok ( ( ) ) ;
2149
+ }
2150
+
2151
+ // Fall through below to requiring a JS shim to create an item
2152
+ // that we can import. These are plucked from the global
2153
+ // environment so there's no way right now to describe these
2154
+ // imports in an ES module-like fashion.
2155
+ JsImportName :: Global { .. } | JsImportName :: VendorPrefixed { .. } => { }
2156
+ }
2157
+ }
2158
+
2159
+ self . expose_not_defined ( ) ;
2160
+ let name = self . import_name ( js) ?;
2161
+ let js = format ! (
2162
+ "typeof {name} == 'function' ? {name} : notDefined('{name}')" ,
2163
+ name = name,
2164
+ ) ;
2165
+ self . wasm_import_definitions . insert ( id, js) ;
2166
+ Ok ( ( ) )
2167
+ }
2168
+
2081
2169
/// Generates a JS snippet appropriate for invoking `import`.
2082
2170
///
2083
2171
/// This is generating code for `binding` where `bindings` has more type
0 commit comments