Skip to content

Commit 487289c

Browse files
authored
Merge pull request #1725 from alexcrichton/real-webidl-section
Add support for emitting a Wasm Interface Types section
2 parents bd7c907 + c5dd572 commit 487289c

File tree

6 files changed

+630
-73
lines changed

6 files changed

+630
-73
lines changed

crates/cli-support/src/anyref.rs

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use walrus::Module;
66
use wasm_bindgen_anyref_xform::Context;
77
use wasm_webidl_bindings::ast;
88

9-
pub fn process(module: &mut Module) -> Result<(), Error> {
9+
pub fn process(module: &mut Module, wasm_interface_types: bool) -> Result<(), Error> {
1010
let mut cfg = Context::default();
1111
cfg.prepare(module)?;
1212
let bindings = module
@@ -45,18 +45,24 @@ pub fn process(module: &mut Module) -> Result<(), Error> {
4545

4646
cfg.run(module)?;
4747

48-
// Make sure to export the `anyref` table for the JS bindings since it
49-
// will need to be initialized. If it doesn't exist though then the
50-
// module must not use it, so we skip it.
51-
let table = module.tables.iter().find(|t| match t.kind {
52-
walrus::TableKind::Anyref(_) => true,
53-
_ => false,
54-
});
55-
let table = match table {
56-
Some(t) => t.id(),
57-
None => return Ok(()),
58-
};
59-
module.exports.add("__wbg_anyref_table", table);
48+
// If our output is using WebAssembly interface types then our bindings will
49+
// never use this table, so no need to export it. Otherwise it's highly
50+
// likely in web/JS embeddings this will be used, so make sure we export it
51+
// to avoid it getting gc'd accidentally.
52+
if !wasm_interface_types {
53+
// Make sure to export the `anyref` table for the JS bindings since it
54+
// will need to be initialized. If it doesn't exist though then the
55+
// module must not use it, so we skip it.
56+
let table = module.tables.iter().find(|t| match t.kind {
57+
walrus::TableKind::Anyref(_) => true,
58+
_ => false,
59+
});
60+
let table = match table {
61+
Some(t) => t.id(),
62+
None => return Ok(()),
63+
};
64+
module.exports.add("__wbg_anyref_table", table);
65+
}
6066

6167
// Clean up now-unused intrinsics and shims and such
6268
walrus::passes::gc::run(module);

crates/cli-support/src/intrinsic.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,15 @@ macro_rules! intrinsics {
5050
)*
5151
}
5252
}
53+
54+
/// Returns the symbol name of this intrinsic
55+
pub fn name(&self) -> &'static str {
56+
match self {
57+
$(
58+
Intrinsic::$name => $sym,
59+
)*
60+
}
61+
}
5362
}
5463
};
5564
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2081,11 +2081,13 @@ impl<'a> Context<'a> {
20812081
&binding.outgoing,
20822082
wasm_ty.params(),
20832083
&webidl.params,
2084+
self.config.wasm_interface_types,
20842085
)
20852086
&& webidl::incoming_do_not_require_glue(
20862087
&binding.incoming,
20872088
&webidl.result.into_iter().collect::<Vec<_>>(),
20882089
wasm_ty.results(),
2090+
self.config.wasm_interface_types,
20892091
)
20902092
}
20912093

crates/cli-support/src/lib.rs

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ pub struct Bindgen {
3636
// "ready to be instantiated on any thread"
3737
threads: wasm_bindgen_threads_xform::Config,
3838
anyref: bool,
39+
wasm_interface_types: bool,
3940
encode_into: EncodeInto,
4041
}
4142

@@ -49,6 +50,7 @@ pub struct Output {
4950
snippets: HashMap<String, Vec<String>>,
5051
local_modules: HashMap<String, String>,
5152
npm_dependencies: HashMap<String, (PathBuf, String)>,
53+
wasm_interface_types: bool,
5254
}
5355

5456
#[derive(Clone)]
@@ -73,6 +75,8 @@ pub enum EncodeInto {
7375

7476
impl Bindgen {
7577
pub fn new() -> Bindgen {
78+
let anyref = env::var("WASM_BINDGEN_ANYREF").is_ok();
79+
let wasm_interface_types = env::var("WASM_INTERFACE_TYPES").is_ok();
7680
Bindgen {
7781
input: Input::None,
7882
out_name: None,
@@ -88,7 +92,8 @@ impl Bindgen {
8892
emit_start: true,
8993
weak_refs: env::var("WASM_BINDGEN_WEAKREF").is_ok(),
9094
threads: threads_config(),
91-
anyref: env::var("WASM_BINDGEN_ANYREF").is_ok(),
95+
anyref: anyref || wasm_interface_types,
96+
wasm_interface_types,
9297
encode_into: EncodeInto::Test,
9398
}
9499
}
@@ -315,15 +320,15 @@ impl Bindgen {
315320
// the webidl bindings proposal) as well as an auxiliary section for all
316321
// sorts of miscellaneous information and features #[wasm_bindgen]
317322
// supports that aren't covered by WebIDL bindings.
318-
webidl::process(&mut module, self.anyref, self.emit_start)?;
323+
webidl::process(&mut module, self.anyref, self.wasm_interface_types, self.emit_start)?;
319324

320325
// Now that we've got type information from the webidl processing pass,
321326
// touch up the output of rustc to insert anyref shims where necessary.
322327
// This is only done if the anyref pass is enabled, which it's
323328
// currently off-by-default since `anyref` is still in development in
324329
// engines.
325330
if self.anyref {
326-
anyref::process(&mut module)?;
331+
anyref::process(&mut module, self.wasm_interface_types)?;
327332
}
328333

329334
let aux = module
@@ -344,6 +349,11 @@ impl Bindgen {
344349
(npm_dependencies, cx.finalize(stem)?)
345350
};
346351

352+
if self.wasm_interface_types {
353+
webidl::standard::add_section(&mut module, &aux, &bindings)
354+
.with_context(|_| "failed to generate a standard wasm bindings custom section")?;
355+
}
356+
347357
Ok(Output {
348358
module,
349359
stem: stem.to_string(),
@@ -354,6 +364,7 @@ impl Bindgen {
354364
ts,
355365
mode: self.mode.clone(),
356366
typescript: self.typescript,
367+
wasm_interface_types: self.wasm_interface_types,
357368
})
358369
}
359370

@@ -506,6 +517,7 @@ fn unexported_unused_lld_things(module: &mut Module) {
506517

507518
impl Output {
508519
pub fn js(&self) -> &str {
520+
assert!(!self.wasm_interface_types);
509521
&self.js
510522
}
511523

@@ -518,6 +530,23 @@ impl Output {
518530
}
519531

520532
fn _emit(&self, out_dir: &Path) -> Result<(), Error> {
533+
let wasm_name = if self.wasm_interface_types {
534+
self.stem.clone()
535+
} else {
536+
format!("{}_bg", self.stem)
537+
};
538+
let wasm_path = out_dir
539+
.join(wasm_name)
540+
.with_extension("wasm");
541+
fs::create_dir_all(out_dir)?;
542+
let wasm_bytes = self.module.emit_wasm()?;
543+
fs::write(&wasm_path, wasm_bytes)
544+
.with_context(|_| format!("failed to write `{}`", wasm_path.display()))?;
545+
546+
if self.wasm_interface_types {
547+
return Ok(())
548+
}
549+
521550
// Write out all local JS snippets to the final destination now that
522551
// we've collected them from all the programs.
523552
for (identifier, list) in self.snippets.iter() {
@@ -554,7 +583,6 @@ impl Output {
554583
} else {
555584
"js"
556585
};
557-
fs::create_dir_all(out_dir)?;
558586
let js_path = out_dir.join(&self.stem).with_extension(extension);
559587
fs::write(&js_path, reset_indentation(&self.js))
560588
.with_context(|_| format!("failed to write `{}`", js_path.display()))?;
@@ -565,10 +593,6 @@ impl Output {
565593
.with_context(|_| format!("failed to write `{}`", ts_path.display()))?;
566594
}
567595

568-
let wasm_path = out_dir
569-
.join(format!("{}_bg", self.stem))
570-
.with_extension("wasm");
571-
572596
if self.mode.nodejs() {
573597
let js_path = wasm_path.with_extension(extension);
574598
let shim = self.generate_node_wasm_import(&self.module, &wasm_path);
@@ -583,9 +607,6 @@ impl Output {
583607
.with_context(|_| format!("failed to write `{}`", ts_path.display()))?;
584608
}
585609

586-
let wasm_bytes = self.module.emit_wasm()?;
587-
fs::write(&wasm_path, wasm_bytes)
588-
.with_context(|_| format!("failed to write `{}`", wasm_path.display()))?;
589610
Ok(())
590611
}
591612

0 commit comments

Comments
 (0)