-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add --target electron-renderer (for generating electron preloads) #1928
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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<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. | ||
|
@@ -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"); | ||
} | ||
|
@@ -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<String, Error> { | ||
let mut imports = String::new(); | ||
fn js_import_header(&self, imports: &mut String, preloads: &mut String) -> Result<(), Error> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of taking two out-parameters could this return a structure with named fields that document the meaning of each field? |
||
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 { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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)>, | ||
|
@@ -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 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The variable "web" here probably wants a different name |
||
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(()) | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's ok to not add this since there's no need to add an insta-deprecated option |
||
--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) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This return type is getting unfortunately pretty unwieldy, could this be updated to a named structure with documented fields?