From f7d0a104370cf8806fb56ca37d71e7f8f3f7de77 Mon Sep 17 00:00:00 2001 From: Darin Morrison Date: Fri, 27 Dec 2019 11:05:29 -0700 Subject: [PATCH] Add electron-renderer target --- crates/cli-support/src/js/mod.rs | 60 ++++++++++++++++++++++++++---- crates/cli-support/src/lib.rs | 25 ++++++++++++- crates/cli/src/bin/wasm-bindgen.rs | 6 ++- 3 files changed, 81 insertions(+), 10 deletions(-) diff --git a/crates/cli-support/src/js/mod.rs b/crates/cli-support/src/js/mod.rs index 4a78dadc4ef..4ebf6647c40 100644 --- a/crates/cli-support/src/js/mod.rs +++ b/crates/cli-support/src/js/mod.rs @@ -140,6 +140,7 @@ impl<'a> Context<'a> { } } OutputMode::Bundler { .. } + | OutputMode::ElectronRenderer | OutputMode::Node { experimental_modules: true, } @@ -167,7 +168,10 @@ impl<'a> Context<'a> { Ok(()) } - pub fn finalize(&mut self, module_name: &str) -> Result<(String, String), Error> { + pub fn finalize( + &mut self, + module_name: &str, + ) -> Result<(String, String, Option), Error> { // Finalize all bindings for JS classes. This is where we'll generate JS // glue for all classes as well as finish up a few final imports like // `__wrap` and such. @@ -194,9 +198,10 @@ impl<'a> Context<'a> { &mut self, module_name: &str, needs_manual_start: bool, - ) -> Result<(String, String), Error> { + ) -> Result<(String, String, Option), Error> { let mut ts = self.typescript.clone(); let mut js = String::new(); + let mut preloads = String::new(); if self.config.mode.no_modules() { js.push_str("(function() {\n"); } @@ -205,7 +210,8 @@ impl<'a> Context<'a> { // import the wasm file in one way or another. let mut init = (String::new(), String::new()); let mut footer = String::new(); - let mut imports = self.js_import_header()?; + let mut imports = String::new(); + self.js_import_header(&mut imports, &mut preloads)?; match &self.config.mode { // In `--target no-modules` mode we need to both expose a name on // the global object as well as generate our own custom start @@ -272,7 +278,7 @@ impl<'a> Context<'a> { // browsers don't support natively importing wasm right now so we // expose the same initialization function as `--target no-modules` // as the default export of the module. - OutputMode::Web => { + OutputMode::ElectronRenderer | OutputMode::Web => { self.imports_post.push_str("let wasm;\n"); init = self.gen_init(needs_manual_start, Some(&mut imports))?; footer.push_str("export default init;\n"); @@ -310,11 +316,31 @@ impl<'a> Context<'a> { js = js.replace("\n\n\n", "\n\n"); } - Ok((js, ts)) + let preloads = if self.config.mode.electron_renderer() { + preloads.push_str("\nprocess.once('loaded', () => {\n"); + for (_module, items) in crate::sorted_iter(&self.js_imports) { + for (_i, (item, rename)) in items.iter().enumerate() { + let mut name: &str = item; + if let Some(other) = rename { + name = other; + } + preloads.push_str(" global."); + preloads.push_str(name); + preloads.push_str(" = "); + preloads.push_str(name); + preloads.push_str(";\n"); + } + } + preloads.push_str("});"); + Some(preloads) + } else { + None + }; + + Ok((js, ts, preloads)) } - fn js_import_header(&self) -> Result { - let mut imports = String::new(); + fn js_import_header(&self, imports: &mut String, preloads: &mut String) -> Result<(), Error> { match &self.config.mode { OutputMode::NoModules { .. } => { for (module, _items) in self.js_imports.iter() { @@ -368,8 +394,26 @@ impl<'a> Context<'a> { imports.push_str("';\n"); } } + OutputMode::ElectronRenderer => { + for (module, items) in crate::sorted_iter(&self.js_imports) { + preloads.push_str("const { "); + for (i, (item, rename)) in items.iter().enumerate() { + if i > 0 { + preloads.push_str(", "); + } + preloads.push_str(item); + if let Some(other) = rename { + preloads.push_str(": "); + preloads.push_str(other) + } + } + preloads.push_str(" } = require(String.raw`"); + preloads.push_str(module); + preloads.push_str("`);\n"); + } + } } - Ok(imports) + Ok(()) } fn ts_for_init_fn(has_memory: bool, has_module_or_path_optional: bool) -> String { diff --git a/crates/cli-support/src/lib.rs b/crates/cli-support/src/lib.rs index 1a25f5c6e57..e5ddd319ce3 100755 --- a/crates/cli-support/src/lib.rs +++ b/crates/cli-support/src/lib.rs @@ -58,6 +58,7 @@ struct JsGenerated { mode: OutputMode, js: String, ts: String, + preloads: Option, snippets: HashMap>, local_modules: HashMap, npm_dependencies: HashMap, @@ -67,6 +68,7 @@ struct JsGenerated { #[derive(Clone)] enum OutputMode { Bundler { browser_only: bool }, + ElectronRenderer, Web, NoModules { global: String }, Node { experimental_modules: bool }, @@ -182,6 +184,13 @@ impl Bindgen { Ok(self) } + pub fn electron_renderer(&mut self, web: bool) -> Result<&mut Bindgen, Error> { + if web { + self.switch_mode(OutputMode::ElectronRenderer, "--target electron-renderer")?; + } + Ok(self) + } + pub fn no_modules(&mut self, no_modules: bool) -> Result<&mut Bindgen, Error> { if no_modules { self.switch_mode( @@ -412,7 +421,7 @@ impl Bindgen { .unwrap(); let mut cx = js::Context::new(&mut module, self, &adapters, &aux)?; cx.generate()?; - let (js, ts) = cx.finalize(stem)?; + let (js, ts, preloads) = cx.finalize(stem)?; Generated::Js(JsGenerated { snippets: aux.snippets.clone(), local_modules: aux.local_modules.clone(), @@ -421,6 +430,7 @@ impl Bindgen { npm_dependencies: cx.npm_dependencies.clone(), js, ts, + preloads, }) }; @@ -558,6 +568,13 @@ impl OutputMode { _ => false, } } + + fn electron_renderer(&self) -> bool { + match self { + OutputMode::ElectronRenderer => true, + _ => false, + } + } } /// Remove a number of internal exports that are synthesized by Rust's linker, @@ -674,6 +691,12 @@ impl Output { .with_context(|| format!("failed to write `{}`", ts_path.display()))?; } + if gen.mode.electron_renderer() { + let preloads_path = out_dir.join("preloads").with_extension(extension); + fs::write(&preloads_path, &gen.preloads.as_ref().unwrap()) + .with_context(|| format!("failed to write `{}`", preloads_path.display()))?; + } + Ok(()) } } diff --git a/crates/cli/src/bin/wasm-bindgen.rs b/crates/cli/src/bin/wasm-bindgen.rs index 57d8b4c2812..1b65bbfbd3f 100644 --- a/crates/cli/src/bin/wasm-bindgen.rs +++ b/crates/cli/src/bin/wasm-bindgen.rs @@ -22,7 +22,7 @@ Options: --out-dir DIR Output directory --out-name VAR Set a custom output filename (Without extension. Defaults to crate name) --target TARGET What type of output to generate, valid - values are [web, bundler, nodejs, no-modules], + values are [web, bundler, nodejs, no-modules, electron-renderer], and the default is [bundler] --no-modules-global VAR Name of the global variable to initialize --browser Hint that JS should only be compatible with a browser @@ -35,6 +35,7 @@ Options: --remove-producers-section Remove the telemetry `producers` section --encode-into MODE Whether or not to use TextEncoder#encodeInto, valid values are [test, always, never] + --electron-renderer Deprecated, use `--target electron-renderer` --nodejs Deprecated, use `--target nodejs` --web Deprecated, use `--target web` --no-modules Deprecated, use `--target no-modules` @@ -46,6 +47,7 @@ struct Args { flag_nodejs: bool, flag_browser: bool, flag_web: bool, + flag_electron_renderer: bool, flag_no_modules: bool, flag_typescript: bool, flag_no_typescript: bool, @@ -96,12 +98,14 @@ fn rmain(args: &Args) -> Result<(), Error> { "web" => b.web(true)?, "no-modules" => b.no_modules(true)?, "nodejs" => b.nodejs(true)?, + "electron-renderer" => b.electron_renderer(true)?, s => bail!("invalid encode-into mode: `{}`", s), }; } b.input_path(input) .nodejs(args.flag_nodejs)? .web(args.flag_web)? + .electron_renderer(args.flag_electron_renderer)? .browser(args.flag_browser)? .no_modules(args.flag_no_modules)? .debug(args.flag_debug)