@@ -113,7 +113,7 @@ impl<'a> Context<'a> {
113
113
contents : & str ,
114
114
comments : Option < & str > ,
115
115
) -> Result < ( ) , Error > {
116
- let definition_name = generate_identifier ( export_name, & mut self . defined_identifiers ) ;
116
+ let definition_name = self . generate_identifier ( export_name) ;
117
117
if contents. starts_with ( "class" ) && definition_name != export_name {
118
118
bail ! ( "cannot shadow already defined class `{}`" , export_name) ;
119
119
}
@@ -1922,6 +1922,18 @@ impl<'a> Context<'a> {
1922
1922
require_class ( & mut self . exported_classes , name) . wrap_needed = true ;
1923
1923
}
1924
1924
1925
+ fn add_module_import ( & mut self , module : String , name : & str , actual : & str ) {
1926
+ let rename = if name == actual {
1927
+ None
1928
+ } else {
1929
+ Some ( actual. to_string ( ) )
1930
+ } ;
1931
+ self . js_imports
1932
+ . entry ( module)
1933
+ . or_insert ( Vec :: new ( ) )
1934
+ . push ( ( name. to_string ( ) , rename) ) ;
1935
+ }
1936
+
1925
1937
fn import_name ( & mut self , import : & JsImport ) -> Result < String , Error > {
1926
1938
if let Some ( name) = self . imported_names . get ( & import. name ) {
1927
1939
let mut name = name. clone ( ) ;
@@ -1932,30 +1944,17 @@ impl<'a> Context<'a> {
1932
1944
return Ok ( name. clone ( ) ) ;
1933
1945
}
1934
1946
1935
- let js_imports = & mut self . js_imports ;
1936
- let mut add_module_import = |module : String , name : & str , actual : & str | {
1937
- let rename = if name == actual {
1938
- None
1939
- } else {
1940
- Some ( actual. to_string ( ) )
1941
- } ;
1942
- js_imports
1943
- . entry ( module)
1944
- . or_insert ( Vec :: new ( ) )
1945
- . push ( ( name. to_string ( ) , rename) ) ;
1946
- } ;
1947
-
1948
1947
let mut name = match & import. name {
1949
1948
JsImportName :: Module { module, name } => {
1950
- let unique_name = generate_identifier ( name, & mut self . defined_identifiers ) ;
1951
- add_module_import ( module. clone ( ) , name, & unique_name) ;
1949
+ let unique_name = self . generate_identifier ( name) ;
1950
+ self . add_module_import ( module. clone ( ) , name, & unique_name) ;
1952
1951
unique_name
1953
1952
}
1954
1953
1955
1954
JsImportName :: LocalModule { module, name } => {
1956
- let unique_name = generate_identifier ( name, & mut self . defined_identifiers ) ;
1955
+ let unique_name = self . generate_identifier ( name) ;
1957
1956
let module = self . config . local_module_name ( module) ;
1958
- add_module_import ( module, name, & unique_name) ;
1957
+ self . add_module_import ( module, name, & unique_name) ;
1959
1958
unique_name
1960
1959
}
1961
1960
@@ -1967,8 +1966,8 @@ impl<'a> Context<'a> {
1967
1966
let module = self
1968
1967
. config
1969
1968
. inline_js_module_name ( unique_crate_identifier, * snippet_idx_in_crate) ;
1970
- let unique_name = generate_identifier ( name, & mut self . defined_identifiers ) ;
1971
- add_module_import ( module, name, & unique_name) ;
1969
+ let unique_name = self . generate_identifier ( name) ;
1970
+ self . add_module_import ( module, name, & unique_name) ;
1972
1971
unique_name
1973
1972
}
1974
1973
@@ -1998,7 +1997,7 @@ impl<'a> Context<'a> {
1998
1997
}
1999
1998
2000
1999
JsImportName :: Global { name } => {
2001
- let unique_name = generate_identifier ( name, & mut self . defined_identifiers ) ;
2000
+ let unique_name = self . generate_identifier ( name) ;
2002
2001
if unique_name != * name {
2003
2002
bail ! ( "cannot import `{}` from two locations" , name) ;
2004
2003
}
@@ -2055,6 +2054,7 @@ impl<'a> Context<'a> {
2055
2054
}
2056
2055
2057
2056
pub fn generate ( & mut self ) -> Result < ( ) , Error > {
2057
+ self . prestore_global_import_identifiers ( ) ?;
2058
2058
for ( id, adapter) in crate :: sorted_iter ( & self . wit . adapters ) {
2059
2059
let instrs = match & adapter. kind {
2060
2060
AdapterKind :: Import { .. } => continue ,
@@ -2084,6 +2084,29 @@ impl<'a> Context<'a> {
2084
2084
Ok ( ( ) )
2085
2085
}
2086
2086
2087
+ /// Registers import names for all `Global` imports first before we actually
2088
+ /// process any adapters.
2089
+ ///
2090
+ /// `Global` names must be imported as their exact name, so if the same name
2091
+ /// from a global is also imported from a module we have to be sure to
2092
+ /// import the global first to ensure we don't shadow the actual global
2093
+ /// value. Otherwise we have no way of accessing the global value!
2094
+ ///
2095
+ /// This function will iterate through the import map up-front and generate
2096
+ /// a cache entry for each import name which is a `Global`.
2097
+ fn prestore_global_import_identifiers ( & mut self ) -> Result < ( ) , Error > {
2098
+ for import in self . aux . import_map . values ( ) {
2099
+ let js = match import {
2100
+ AuxImport :: Value ( AuxValue :: Bare ( js) ) => js,
2101
+ _ => continue ,
2102
+ } ;
2103
+ if let JsImportName :: Global { .. } = js. name {
2104
+ self . import_name ( js) ?;
2105
+ }
2106
+ }
2107
+ Ok ( ( ) )
2108
+ }
2109
+
2087
2110
fn generate_adapter (
2088
2111
& mut self ,
2089
2112
id : AdapterId ,
@@ -3133,6 +3156,21 @@ impl<'a> Context<'a> {
3133
3156
fn adapter_name ( & self , id : AdapterId ) -> String {
3134
3157
format ! ( "__wbg_adapter_{}" , id. 0 )
3135
3158
}
3159
+
3160
+ fn generate_identifier ( & mut self , name : & str ) -> String {
3161
+ let cnt = self
3162
+ . defined_identifiers
3163
+ . entry ( name. to_string ( ) )
3164
+ . or_insert ( 0 ) ;
3165
+ * cnt += 1 ;
3166
+ // We want to mangle `default` at once, so we can support default exports and don't generate
3167
+ // invalid glue code like this: `import { default } from './module';`.
3168
+ if * cnt == 1 && name != "default" {
3169
+ name. to_string ( )
3170
+ } else {
3171
+ format ! ( "{}{}" , name, cnt)
3172
+ }
3173
+ }
3136
3174
}
3137
3175
3138
3176
fn check_duplicated_getter_and_setter_names (
@@ -3180,18 +3218,6 @@ fn check_duplicated_getter_and_setter_names(
3180
3218
Ok ( ( ) )
3181
3219
}
3182
3220
3183
- fn generate_identifier ( name : & str , used_names : & mut HashMap < String , usize > ) -> String {
3184
- let cnt = used_names. entry ( name. to_string ( ) ) . or_insert ( 0 ) ;
3185
- * cnt += 1 ;
3186
- // We want to mangle `default` at once, so we can support default exports and don't generate
3187
- // invalid glue code like this: `import { default } from './module';`.
3188
- if * cnt == 1 && name != "default" {
3189
- name. to_string ( )
3190
- } else {
3191
- format ! ( "{}{}" , name, cnt)
3192
- }
3193
- }
3194
-
3195
3221
fn format_doc_comments ( comments : & str , js_doc_comments : Option < String > ) -> String {
3196
3222
let body: String = comments. lines ( ) . map ( |c| format ! ( "*{}\n " , c) ) . collect ( ) ;
3197
3223
let doc = if let Some ( docs) = js_doc_comments {
@@ -3294,27 +3320,6 @@ impl ExportedClass {
3294
3320
}
3295
3321
}
3296
3322
3297
- #[ test]
3298
- fn test_generate_identifier ( ) {
3299
- let mut used_names: HashMap < String , usize > = HashMap :: new ( ) ;
3300
- assert_eq ! (
3301
- generate_identifier( "someVar" , & mut used_names) ,
3302
- "someVar" . to_string( )
3303
- ) ;
3304
- assert_eq ! (
3305
- generate_identifier( "someVar" , & mut used_names) ,
3306
- "someVar2" . to_string( )
3307
- ) ;
3308
- assert_eq ! (
3309
- generate_identifier( "default" , & mut used_names) ,
3310
- "default1" . to_string( )
3311
- ) ;
3312
- assert_eq ! (
3313
- generate_identifier( "default" , & mut used_names) ,
3314
- "default2" . to_string( )
3315
- ) ;
3316
- }
3317
-
3318
3323
struct MemView {
3319
3324
name : & ' static str ,
3320
3325
num : usize ,
0 commit comments