Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
[ci skip]
  • Loading branch information
darinmorrison committed Dec 23, 2019
1 parent 580daab commit ebec518
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 10 deletions.
60 changes: 52 additions & 8 deletions crates/cli-support/src/js/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ impl<'a> Context<'a> {
}
}
OutputMode::Bundler { .. }
| OutputMode::ElectronRenderer
| OutputMode::Node {
experimental_modules: true,
}
Expand Down Expand Up @@ -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<String>), 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.
Expand All @@ -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<String>), 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");
}
Expand All @@ -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
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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("process.once('loaded', () => {");
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<String, Error> {
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() {
Expand Down Expand Up @@ -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 {
Expand Down
25 changes: 24 additions & 1 deletion crates/cli-support/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ struct JsGenerated {
mode: OutputMode,
js: String,
ts: String,
preloads: Option<String>,
snippets: HashMap<String, Vec<String>>,
local_modules: HashMap<String, String>,
npm_dependencies: HashMap<String, (PathBuf, String)>,
Expand All @@ -67,6 +68,7 @@ struct JsGenerated {
#[derive(Clone)]
enum OutputMode {
Bundler { browser_only: bool },
ElectronRenderer,
Web,
NoModules { global: String },
Node { experimental_modules: bool },
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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(),
Expand All @@ -421,6 +430,7 @@ impl Bindgen {
npm_dependencies: cx.npm_dependencies.clone(),
js,
ts,
preloads,
})
};

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -674,6 +691,12 @@ impl Output {
.with_context(|| format!("failed to write `{}`", ts_path.display()))?;
}

if gen.mode.electron_renderer() {
let preloads_path = PathBuf::from("preloads.js");
fs::write(&preloads_path, &gen.preloads.as_ref().unwrap())
.with_context(|| format!("failed to write `{}`", preloads_path.display()))?;
}

Ok(())
}
}
Expand Down
5 changes: 4 additions & 1 deletion crates/cli/src/bin/wasm-bindgen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -46,6 +46,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,
Expand Down Expand Up @@ -96,12 +97,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)
Expand Down

0 comments on commit ebec518

Please sign in to comment.