@@ -34,12 +34,13 @@ use std::env;
34
34
use std:: fs;
35
35
use std:: iter:: FromIterator ;
36
36
37
- use backend:: ast;
38
37
use backend:: TryToTokens ;
39
- use backend:: defined :: { ImportedTypeDefinitions , RemoveUndefinedImports } ;
38
+ use backend:: ast ;
40
39
use backend:: defined:: ImportedTypeReferences ;
40
+ use backend:: defined:: { ImportedTypeDefinitions , RemoveUndefinedImports } ;
41
41
use backend:: util:: { ident_ty, rust_ident, raw_ident, wrap_import_function} ;
42
42
use proc_macro2:: { Ident , Span } ;
43
+ use quote:: ToTokens ;
43
44
use weedle:: attribute:: { ExtendedAttributeList } ;
44
45
use weedle:: dictionary:: DictionaryMember ;
45
46
use weedle:: interface:: InterfaceMember ;
@@ -51,9 +52,14 @@ use idl_type::ToIdlType;
51
52
52
53
pub use error:: { Error , ErrorKind , Result } ;
53
54
55
+ struct Program {
56
+ main : backend:: ast:: Program ,
57
+ submodules : Vec < ( String , backend:: ast:: Program ) > ,
58
+ }
59
+
54
60
/// Parse a string of WebIDL source text into a wasm-bindgen AST.
55
61
fn parse ( webidl_source : & str , allowed_types : Option < & [ & str ] > )
56
- -> Result < backend :: ast :: Program >
62
+ -> Result < Program >
57
63
{
58
64
let definitions = match weedle:: parse ( webidl_source) {
59
65
Ok ( def) => def,
@@ -80,6 +86,7 @@ fn parse(webidl_source: &str, allowed_types: Option<&[&str]>)
80
86
first_pass_record. builtin_idents = builtin_idents ( ) ;
81
87
definitions. first_pass ( & mut first_pass_record, ( ) ) ?;
82
88
let mut program = Default :: default ( ) ;
89
+ let mut submodules = Vec :: new ( ) ;
83
90
84
91
let allowed_types = allowed_types. map ( |list| {
85
92
list. iter ( ) . cloned ( ) . collect :: < HashSet < _ > > ( )
@@ -102,7 +109,8 @@ fn parse(webidl_source: &str, allowed_types: Option<&[&str]>)
102
109
}
103
110
}
104
111
for ( name, n) in first_pass_record. namespaces . iter ( ) {
105
- first_pass_record. append_ns ( & mut program, name, n) ;
112
+ let prog = first_pass_record. append_ns ( name, n) ;
113
+ submodules. push ( ( snake_case_ident ( name) . to_string ( ) , prog) ) ;
106
114
}
107
115
for ( name, d) in first_pass_record. interfaces . iter ( ) {
108
116
if filter ( name) {
@@ -127,7 +135,10 @@ fn parse(webidl_source: &str, allowed_types: Option<&[&str]>)
127
135
}
128
136
}
129
137
130
- Ok ( program)
138
+ Ok ( Program {
139
+ main : program,
140
+ submodules : submodules,
141
+ } )
131
142
}
132
143
133
144
/// Compile the given WebIDL source text into Rust source text containing
@@ -152,7 +163,7 @@ fn builtin_idents() -> BTreeSet<Ident> {
152
163
}
153
164
154
165
/// Run codegen on the AST to generate rust code.
155
- fn compile_ast ( mut ast : backend :: ast :: Program ) -> String {
166
+ fn compile_ast ( mut ast : Program ) -> String {
156
167
// Iteratively prune all entries from the AST which reference undefined
157
168
// fields. Each pass may remove definitions of types and so we need to
158
169
// reexecute this pass to see if we need to keep removing types until we
@@ -162,13 +173,24 @@ fn compile_ast(mut ast: backend::ast::Program) -> String {
162
173
let track = env:: var_os ( "__WASM_BINDGEN_DUMP_FEATURES" ) ;
163
174
loop {
164
175
let mut defined = builtin. clone ( ) ;
165
- ast. imported_type_definitions ( & mut |id| {
166
- defined. insert ( id. clone ( ) ) ;
167
- if track. is_some ( ) {
168
- all_definitions. insert ( id. clone ( ) ) ;
176
+ {
177
+ let mut cb = |id : & Ident | {
178
+ defined. insert ( id. clone ( ) ) ;
179
+ if track. is_some ( ) {
180
+ all_definitions. insert ( id. clone ( ) ) ;
181
+ }
182
+ } ;
183
+ ast. main . imported_type_definitions ( & mut cb) ;
184
+ for ( _, m) in ast. submodules . iter ( ) {
185
+ m. imported_type_references ( & mut cb) ;
169
186
}
170
- } ) ;
171
- if !ast. remove_undefined_imports ( & |id| defined. contains ( id) ) {
187
+ }
188
+ let changed =
189
+ ast. main . remove_undefined_imports ( & |id| defined. contains ( id) ) ||
190
+ ast. submodules . iter_mut ( ) . any ( |( _, m) | {
191
+ m. remove_undefined_imports ( & |id| defined. contains ( id) )
192
+ } ) ;
193
+ if !changed {
172
194
break
173
195
}
174
196
}
@@ -181,9 +203,21 @@ fn compile_ast(mut ast: backend::ast::Program) -> String {
181
203
}
182
204
183
205
let mut tokens = proc_macro2:: TokenStream :: new ( ) ;
184
- if let Err ( e) = ast. try_to_tokens ( & mut tokens) {
206
+ if let Err ( e) = ast. main . try_to_tokens ( & mut tokens) {
185
207
e. panic ( ) ;
186
208
}
209
+ for ( name, m) in ast. submodules . iter ( ) {
210
+ let mut m_tokens = proc_macro2:: TokenStream :: new ( ) ;
211
+ if let Err ( e) = m. try_to_tokens ( & mut m_tokens) {
212
+ e. panic ( ) ;
213
+ }
214
+
215
+ let name = Ident :: new ( name, Span :: call_site ( ) ) ;
216
+
217
+ ( quote ! {
218
+ pub mod #name { #m_tokens }
219
+ } ) . to_tokens ( & mut tokens) ;
220
+ }
187
221
tokens. to_string ( )
188
222
}
189
223
@@ -340,26 +374,21 @@ impl<'src> FirstPassRecord<'src> {
340
374
341
375
fn append_ns (
342
376
& ' src self ,
343
- program : & mut backend:: ast:: Program ,
344
377
name : & ' src str ,
345
378
ns : & ' src first_pass:: NamespaceData < ' src > ,
346
- ) {
347
- let mut module = backend:: ast:: Module {
348
- vis : public ( ) ,
349
- name : rust_ident ( snake_case_ident ( name) . as_str ( ) ) ,
350
- imports : Default :: default ( ) ,
351
- } ;
379
+ ) -> backend:: ast:: Program {
380
+ let mut ret = Default :: default ( ) ;
352
381
353
382
for ( id, data) in ns. operations . iter ( ) {
354
- self . append_ns_member ( & mut module , name, id, data) ;
383
+ self . append_ns_member ( & mut ret , name, id, data) ;
355
384
}
356
385
357
- program . modules . push ( module ) ;
386
+ return ret
358
387
}
359
388
360
389
fn append_ns_member (
361
390
& self ,
362
- module : & mut backend:: ast:: Module ,
391
+ module : & mut backend:: ast:: Program ,
363
392
self_name : & ' src str ,
364
393
id : & OperationId < ' src > ,
365
394
data : & OperationData < ' src > ,
0 commit comments