@@ -222,6 +222,170 @@ impl<'a> Context<'a> {
222
222
}
223
223
224
224
pub fn finalize ( & mut self , module_name : & str ) -> Result < ( String , String ) , Error > {
225
+ // Wire up all default intrinsics, those which don't have any sort of
226
+ // dependency on the clsoure/anyref/etc passes. This is where almost all
227
+ // intrinsics are wired up.
228
+ self . wire_up_initial_intrinsics ( ) ?;
229
+
230
+ // Next up, perform our closure rewriting pass. This is where we'll
231
+ // update invocations of the closure intrinsics we have to instead call
232
+ // appropriate JS functions which actually create closures.
233
+ closures:: rewrite ( self ) . with_context ( |_| "failed to generate internal closure shims" ) ?;
234
+
235
+ // Finalize all bindings for JS classes. This is where we'll generate JS
236
+ // glue for all classes as well as finish up a few final imports like
237
+ // `__wrap` and such.
238
+ self . write_classes ( ) ?;
239
+
240
+ // And now that we're almost ready, run the final "anyref" pass. This is
241
+ // where we transform a wasm module which doesn't actually use `anyref`
242
+ // anywhere to using the type internally. The transformation here is
243
+ // based off all the previous data we've collected so far for each
244
+ // import/export listed.
245
+ self . anyref . run ( self . module ) ?;
246
+
247
+ // With our transforms finished, we can now wire up the final list of
248
+ // intrinsics which may depend on the passes run above.
249
+ self . wire_up_late_intrinsics ( ) ?;
250
+
251
+ // We're almost done here, so we can delete any internal exports (like
252
+ // `__wbindgen_malloc`) if none of our JS glue actually needed it.
253
+ self . unexport_unused_internal_exports ( ) ;
254
+
255
+ // Handle the `start` function, if one was specified. If we're in a
256
+ // --test mode (such as wasm-bindgen-test-runner) then we skip this
257
+ // entirely. Otherwise we want to first add a start function to the
258
+ // `start` section if one is specified.
259
+ //
260
+ // Note that once a start function is added, if any, we immediately
261
+ // un-start it. This is done because we require that the JS glue
262
+ // initializes first, so we execute wasm startup manually once the JS
263
+ // glue is all in place.
264
+ let mut needs_manual_start = false ;
265
+ if self . config . emit_start {
266
+ self . add_start_function ( ) ?;
267
+ needs_manual_start = self . unstart_start_function ( ) ;
268
+ }
269
+
270
+ // If our JS glue needs to access the function table, then do so here.
271
+ // JS closure shim generation may access the function table as an
272
+ // example, but if there's no closures in the module there's no need to
273
+ // export it!
274
+ self . export_table ( ) ?;
275
+
276
+ // After all we've done, especially
277
+ // `unexport_unused_internal_exports()`, we probably have a bunch of
278
+ // garbage in the module that's no longer necessary, so delete
279
+ // everything that we don't actually need.
280
+ walrus:: passes:: gc:: run ( self . module ) ;
281
+
282
+ // Almost there, but before we're done make sure to rewrite the `module`
283
+ // field of all imports in the wasm module. The field is currently
284
+ // always `__wbindgen_placeholder__` coming out of rustc, but we need to
285
+ // update that here to the shim file or an actual ES module.
286
+ self . rewrite_imports ( module_name) ;
287
+
288
+ // We likely made a ton of modifications, so add ourselves to the
289
+ // producers section!
290
+ self . update_producers_section ( ) ;
291
+
292
+ // Cause any future calls to `should_write_global` to panic, making sure
293
+ // we don't ask for items which we can no longer emit.
294
+ drop ( self . exposed_globals . take ( ) . unwrap ( ) ) ;
295
+
296
+ Ok ( self . finalize_js ( module_name, needs_manual_start) )
297
+ }
298
+
299
+ /// Performs the task of actually generating the final JS module, be it
300
+ /// `--no-modules`, `--browser`, or for bundlers. This is the very last step
301
+ /// performed in `finalize`.
302
+ fn finalize_js ( & mut self , module_name : & str , needs_manual_start : bool ) -> ( String , String ) {
303
+ let mut js = String :: new ( ) ;
304
+ if self . config . mode . no_modules ( ) {
305
+ js. push_str ( "(function() {\n " ) ;
306
+ }
307
+
308
+ // Depending on the output mode, generate necessary glue to actually
309
+ // import the wasm file in one way or another.
310
+ let mut init = String :: new ( ) ;
311
+ match & self . config . mode {
312
+ // In `--no-modules` mode we need to both expose a name on the
313
+ // global object as well as generate our own custom start function.
314
+ OutputMode :: NoModules { global } => {
315
+ js. push_str ( "const __exports = {};\n " ) ;
316
+ js. push_str ( "let wasm;\n " ) ;
317
+ init = self . gen_init ( & module_name, needs_manual_start) ;
318
+ self . footer . push_str ( & format ! (
319
+ "self.{} = Object.assign(init, __exports);\n " ,
320
+ global
321
+ ) ) ;
322
+ }
323
+
324
+ // With normal CommonJS node we need to defer requiring the wasm
325
+ // until the end so most of our own exports are hooked up
326
+ OutputMode :: Node {
327
+ experimental_modules : false ,
328
+ } => {
329
+ self . footer
330
+ . push_str ( & format ! ( "wasm = require('./{}_bg');\n " , module_name) ) ;
331
+ if needs_manual_start {
332
+ self . footer . push_str ( "wasm.__wbindgen_start();\n " ) ;
333
+ }
334
+ js. push_str ( "var wasm;\n " ) ;
335
+ }
336
+
337
+ // With Bundlers and modern ES6 support in Node we can simply import
338
+ // the wasm file as if it were an ES module and let the
339
+ // bundler/runtime take care of it.
340
+ OutputMode :: Bundler
341
+ | OutputMode :: Node {
342
+ experimental_modules : true ,
343
+ } => {
344
+ js. push_str ( & format ! ( "import * as wasm from './{}_bg';\n " , module_name) ) ;
345
+ if needs_manual_start {
346
+ self . footer . push_str ( "wasm.__wbindgen_start();\n " ) ;
347
+ }
348
+ }
349
+
350
+ // With a browser-native output we're generating an ES module, but
351
+ // browsers don't support natively importing wasm right now so we
352
+ // expose the same initialization function as `--no-modules` as the
353
+ // default export of the module.
354
+ OutputMode :: Browser => {
355
+ js. push_str ( "const __exports = {};\n " ) ;
356
+ self . imports_post . push_str ( "let wasm;\n " ) ;
357
+ init = self . gen_init ( & module_name, needs_manual_start) ;
358
+ self . footer . push_str ( "export default init;\n " ) ;
359
+ }
360
+ }
361
+
362
+ // Emit all the JS for importing all our functionality
363
+ js. push_str ( & self . imports ) ;
364
+ js. push_str ( "\n " ) ;
365
+ js. push_str ( & self . imports_post ) ;
366
+ js. push_str ( "\n " ) ;
367
+
368
+ // Emit all our exports from this module
369
+ js. push_str ( & self . globals ) ;
370
+ js. push_str ( "\n " ) ;
371
+
372
+ // Generate the initialization glue, if there was any
373
+ js. push_str ( & init) ;
374
+ js. push_str ( "\n " ) ;
375
+ js. push_str ( & self . footer ) ;
376
+ js. push_str ( "\n " ) ;
377
+ if self . config . mode . no_modules ( ) {
378
+ js. push_str ( "})();\n " ) ;
379
+ }
380
+
381
+ while js. contains ( "\n \n \n " ) {
382
+ js = js. replace ( "\n \n \n " , "\n \n " ) ;
383
+ }
384
+
385
+ ( js, self . typescript . clone ( ) )
386
+ }
387
+
388
+ fn wire_up_initial_intrinsics ( & mut self ) -> Result < ( ) , Error > {
225
389
self . bind ( "__wbindgen_string_new" , & |me| {
226
390
me. anyref . import_xform (
227
391
"__wbindgen_placeholder__" ,
@@ -604,10 +768,28 @@ impl<'a> Context<'a> {
604
768
) )
605
769
} ) ?;
606
770
607
- closures:: rewrite ( self ) . with_context ( |_| "failed to generate internal closure shims" ) ?;
608
- self . write_classes ( ) ?;
609
- self . anyref . run ( self . module ) ?;
771
+ self . bind ( "__wbindgen_throw" , & |me| {
772
+ me. expose_get_string_from_wasm ( ) ;
773
+ Ok ( String :: from (
774
+ "
775
+ function(ptr, len) {
776
+ throw new Error(getStringFromWasm(ptr, len));
777
+ }
778
+ " ,
779
+ ) )
780
+ } ) ?;
610
781
782
+ Ok ( ( ) )
783
+ }
784
+
785
+ /// Provide implementations of remaining intrinsics after initial passes
786
+ /// have been run on the wasm module.
787
+ ///
788
+ /// The intrinsics implemented here are added very late in the process or
789
+ /// otherwise may be overwritten by passes (such as the anyref pass). As a
790
+ /// result they don't go into the initial list of intrinsics but go just at
791
+ /// the end.
792
+ fn wire_up_late_intrinsics ( & mut self ) -> Result < ( ) , Error > {
611
793
// After the anyref pass has executed, if this intrinsic is needed then
612
794
// we expose a function which initializes it
613
795
self . bind ( "__wbindgen_init_anyref_table" , & |me| {
@@ -645,132 +827,7 @@ impl<'a> Context<'a> {
645
827
Ok ( String :: from ( "function(i) { dropObject(i); }" ) )
646
828
} ) ?;
647
829
648
- self . unexport_unused_internal_exports ( ) ;
649
-
650
- // Handle the `start` function, if one was specified. If we're in a
651
- // --test mode (such as wasm-bindgen-test-runner) then we skip this
652
- // entirely. Otherwise we want to first add a start function to the
653
- // `start` section if one is specified.
654
- //
655
- // Note that once a start function is added, if any, we immediately
656
- // un-start it. This is done because we require that the JS glue
657
- // initializes first, so we execute wasm startup manually once the JS
658
- // glue is all in place.
659
- let mut needs_manual_start = false ;
660
- if self . config . emit_start {
661
- self . add_start_function ( ) ?;
662
- needs_manual_start = self . unstart_start_function ( ) ;
663
- }
664
-
665
- self . export_table ( ) ?;
666
-
667
- walrus:: passes:: gc:: run ( self . module ) ;
668
-
669
- // Note that it's important `throw` comes last *after* we gc. The
670
- // `__wbindgen_malloc` function may call this but we only want to
671
- // generate code for this if it's actually live (and __wbindgen_malloc
672
- // isn't gc'd).
673
- self . bind ( "__wbindgen_throw" , & |me| {
674
- me. expose_get_string_from_wasm ( ) ;
675
- Ok ( String :: from (
676
- "
677
- function(ptr, len) {
678
- throw new Error(getStringFromWasm(ptr, len));
679
- }
680
- " ,
681
- ) )
682
- } ) ?;
683
-
684
- self . rewrite_imports ( module_name) ;
685
- self . update_producers_section ( ) ;
686
-
687
- // Cause any future calls to `should_write_global` to panic, making sure
688
- // we don't ask for items which we can no longer emit.
689
- drop ( self . exposed_globals . take ( ) . unwrap ( ) ) ;
690
-
691
- let mut js = String :: new ( ) ;
692
- if self . config . mode . no_modules ( ) {
693
- js. push_str ( "(function() {\n " ) ;
694
- }
695
-
696
- // Depending on the output mode, generate necessary glue to actually
697
- // import the wasm file in one way or another.
698
- let mut init = String :: new ( ) ;
699
- match & self . config . mode {
700
- // In `--no-modules` mode we need to both expose a name on the
701
- // global object as well as generate our own custom start function.
702
- OutputMode :: NoModules { global } => {
703
- js. push_str ( "const __exports = {};\n " ) ;
704
- js. push_str ( "let wasm;\n " ) ;
705
- init = self . gen_init ( & module_name, needs_manual_start) ;
706
- self . footer . push_str ( & format ! (
707
- "self.{} = Object.assign(init, __exports);\n " ,
708
- global
709
- ) ) ;
710
- }
711
-
712
- // With normal CommonJS node we need to defer requiring the wasm
713
- // until the end so most of our own exports are hooked up
714
- OutputMode :: Node {
715
- experimental_modules : false ,
716
- } => {
717
- self . footer
718
- . push_str ( & format ! ( "wasm = require('./{}_bg');\n " , module_name) ) ;
719
- if needs_manual_start {
720
- self . footer . push_str ( "wasm.__wbindgen_start();\n " ) ;
721
- }
722
- js. push_str ( "var wasm;\n " ) ;
723
- }
724
-
725
- // With Bundlers and modern ES6 support in Node we can simply import
726
- // the wasm file as if it were an ES module and let the
727
- // bundler/runtime take care of it.
728
- OutputMode :: Bundler
729
- | OutputMode :: Node {
730
- experimental_modules : true ,
731
- } => {
732
- js. push_str ( & format ! ( "import * as wasm from './{}_bg';\n " , module_name) ) ;
733
- if needs_manual_start {
734
- self . footer . push_str ( "wasm.__wbindgen_start();\n " ) ;
735
- }
736
- }
737
-
738
- // With a browser-native output we're generating an ES module, but
739
- // browsers don't support natively importing wasm right now so we
740
- // expose the same initialization function as `--no-modules` as the
741
- // default export of the module.
742
- OutputMode :: Browser => {
743
- js. push_str ( "const __exports = {};\n " ) ;
744
- self . imports_post . push_str ( "let wasm;\n " ) ;
745
- init = self . gen_init ( & module_name, needs_manual_start) ;
746
- self . footer . push_str ( "export default init;\n " ) ;
747
- }
748
- }
749
-
750
- // Emit all the JS for importing all our functionality
751
- js. push_str ( & self . imports ) ;
752
- js. push_str ( "\n " ) ;
753
- js. push_str ( & self . imports_post ) ;
754
- js. push_str ( "\n " ) ;
755
-
756
- // Emit all our exports from this module
757
- js. push_str ( & self . globals ) ;
758
- js. push_str ( "\n " ) ;
759
-
760
- // Generate the initialization glue, if there was any
761
- js. push_str ( & init) ;
762
- js. push_str ( "\n " ) ;
763
- js. push_str ( & self . footer ) ;
764
- js. push_str ( "\n " ) ;
765
- if self . config . mode . no_modules ( ) {
766
- js. push_str ( "})();\n " ) ;
767
- }
768
-
769
- while js. contains ( "\n \n \n " ) {
770
- js = js. replace ( "\n \n \n " , "\n \n " ) ;
771
- }
772
-
773
- Ok ( ( js, self . typescript . clone ( ) ) )
830
+ Ok ( ( ) )
774
831
}
775
832
776
833
fn gen_init ( & mut self , module_name : & str , needs_manual_start : bool ) -> String {
@@ -1250,8 +1307,7 @@ impl<'a> Context<'a> {
1250
1307
passStringToWasm = function(arg) {{ {} }};
1251
1308
}}
1252
1309
" ,
1253
- use_encode_into,
1254
- use_encode,
1310
+ use_encode_into, use_encode,
1255
1311
) ) ;
1256
1312
}
1257
1313
_ => {
0 commit comments