Skip to content

Commit f9f1eff

Browse files
committed
feat: add experimental inline node target
1 parent ddceac7 commit f9f1eff

File tree

3 files changed

+74
-5
lines changed

3 files changed

+74
-5
lines changed

crates/cli-support/src/js/mod.rs

+58-5
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ impl<'a> Context<'a> {
142142
self.globals.push_str(c);
143143
}
144144
let global = match self.config.mode {
145-
OutputMode::Node { module: false } => {
145+
OutputMode::InlineNodeJs | OutputMode::Node { module: false } => {
146146
if contents.starts_with("class") {
147147
format!("{}\nmodule.exports.{1} = {1};\n", contents, export_name)
148148
} else {
@@ -291,6 +291,31 @@ impl<'a> Context<'a> {
291291
reset_indentation(&shim)
292292
}
293293

294+
fn generate_isomorphic_wasm_loading(&mut self) -> String {
295+
let mut shim = String::new();
296+
297+
let buf = self.module.emit_wasm();
298+
299+
let mut serialized = "const bytes = Buffer.from([".to_string();
300+
let (last, bytes) = buf.split_last().unwrap();
301+
for byte in bytes {
302+
serialized.push_str(&format!("{},", byte));
303+
}
304+
serialized.push_str(&format!("{}", last));
305+
serialized.push_str("]);");
306+
shim.push_str(&serialized);
307+
shim.push_str(
308+
"
309+
const wasmModule = new WebAssembly.Module(bytes);
310+
const wasmInstance = new WebAssembly.Instance(wasmModule, imports);
311+
wasm = wasmInstance.exports;
312+
module.exports.__wasm = wasm;
313+
",
314+
);
315+
316+
reset_indentation(&shim)
317+
}
318+
294319
// generates something like
295320
// ```js
296321
// import * as import0 from './snippets/.../inline1.js';
@@ -500,6 +525,32 @@ impl<'a> Context<'a> {
500525
footer.push_str("export { initSync };\n");
501526
footer.push_str("export default __wbg_init;");
502527
}
528+
529+
OutputMode::InlineNodeJs => {
530+
js.push_str(&self.generate_node_imports());
531+
532+
js.push_str("let wasm;\n");
533+
534+
for (id, js) in crate::sorted_iter(&self.wasm_import_definitions) {
535+
let import = self.module.imports.get_mut(*id);
536+
footer.push_str("\nmodule.exports.");
537+
footer.push_str(&import.name);
538+
footer.push_str(" = ");
539+
footer.push_str(js.trim());
540+
footer.push_str(";\n");
541+
}
542+
543+
footer.push_str(
544+
&self.generate_node_wasm_loading(Path::new(&format!(
545+
"./{}_bg.wasm",
546+
module_name
547+
))),
548+
);
549+
550+
if needs_manual_start {
551+
footer.push_str("\nwasm.__wbindgen_start();\n");
552+
}
553+
}
503554
}
504555

505556
// Before putting the static init code declaration info, put all existing typescript into a `wasm_bindgen` namespace declaration.
@@ -568,7 +619,7 @@ impl<'a> Context<'a> {
568619
}
569620
}
570621

571-
OutputMode::Node { module: false } => {
622+
OutputMode::InlineNodeJs | OutputMode::Node { module: false } => {
572623
for (module, items) in crate::sorted_iter(&self.js_imports) {
573624
imports.push_str("const { ");
574625
for (i, (item, rename)) in items.iter().enumerate() {
@@ -1043,7 +1094,7 @@ impl<'a> Context<'a> {
10431094
*/\n toString(): string;\n",
10441095
);
10451096

1046-
if self.config.mode.nodejs() {
1097+
if self.config.mode.nodejs() || self.config.mode.inline_nodejs() {
10471098
// `util.inspect` must be imported in Node.js to define [inspect.custom]
10481099
let module_name = self.import_name(&JsImport {
10491100
name: JsImportName::Module {
@@ -1522,7 +1573,8 @@ impl<'a> Context<'a> {
15221573
init: Option<&str>,
15231574
) -> Result<(), Error> {
15241575
match &self.config.mode {
1525-
OutputMode::Node { .. } => {
1576+
1577+
OutputMode::InlineNodeJs | OutputMode::Node { .. } => {
15261578
let name = self.import_name(&JsImport {
15271579
name: JsImportName::Module {
15281580
module: "util".to_string(),
@@ -1555,6 +1607,7 @@ impl<'a> Context<'a> {
15551607
if let Some(init) = init {
15561608
match &self.config.mode {
15571609
OutputMode::Node { .. }
1610+
| OutputMode::InlineNodeJs
15581611
| OutputMode::Bundler {
15591612
browser_only: false,
15601613
} => self.global(init),
@@ -3244,7 +3297,7 @@ impl<'a> Context<'a> {
32443297
| OutputMode::Bundler { .. }
32453298
| OutputMode::Deno
32463299
| OutputMode::Node { module: true } => "import.meta.url",
3247-
OutputMode::Node { module: false } => {
3300+
OutputMode::InlineNodeJs | OutputMode::Node { module: false } => {
32483301
"require('url').pathToFileURL(__filename)"
32493302
}
32503303
OutputMode::NoModules { .. } => {

crates/cli-support/src/lib.rs

+15
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ enum OutputMode {
6868
NoModules { global: String },
6969
Node { module: bool },
7070
Deno,
71+
InlineNodeJs,
7172
}
7273

7374
enum Input {
@@ -169,6 +170,16 @@ impl Bindgen {
169170
Ok(self)
170171
}
171172

173+
pub fn inline_nodejs(&mut self, inline_nodejs: bool) -> Result<&mut Bindgen, Error> {
174+
if inline_nodejs {
175+
self.switch_mode(
176+
OutputMode::InlineNodeJs,
177+
"--target experimental-inline-nodejs",
178+
)?;
179+
}
180+
Ok(self)
181+
}
182+
172183
pub fn bundler(&mut self, bundler: bool) -> Result<&mut Bindgen, Error> {
173184
if bundler {
174185
self.switch_mode(
@@ -544,6 +555,10 @@ impl OutputMode {
544555
matches!(self, OutputMode::Node { .. })
545556
}
546557

558+
fn inline_nodejs(&self) -> bool {
559+
matches!(self, OutputMode::InlineNodeJs)
560+
}
561+
547562
fn no_modules(&self) -> bool {
548563
matches!(self, OutputMode::NoModules { .. })
549564
}

crates/cli/src/bin/wasm-bindgen.rs

+1
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ fn rmain(args: &Args) -> Result<(), Error> {
110110
"nodejs" => b.nodejs(true)?,
111111
"deno" => b.deno(true)?,
112112
"experimental-nodejs-module" => b.nodejs_module(true)?,
113+
"experimental-inline-nodejs" => b.inline_nodejs(true)?,
113114
s => bail!("invalid encode-into mode: `{}`", s),
114115
};
115116
}

0 commit comments

Comments
 (0)