mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-03-16 18:20:51 +00:00
Merge pull request #713 from alexcrichton/weakref
Add experimental support for `WeakRef`
This commit is contained in:
commit
285a7bf7da
@ -490,6 +490,39 @@ impl<'a> Context<'a> {
|
||||
let mut dst = format!("class {} {{\n", name);
|
||||
let mut ts_dst = format!("export {}", dst);
|
||||
|
||||
let (mkweakref, freeref) = if self.config.weak_refs {
|
||||
// When weak refs are enabled we use them to automatically free the
|
||||
// contents of an exported rust class when it's gc'd. Note that a
|
||||
// manual `free` function still exists for deterministic
|
||||
// destruction.
|
||||
//
|
||||
// This is implemented by using a `WeakRefGroup` to run finalizers
|
||||
// for all `WeakRef` objects that it creates. Upon construction of
|
||||
// a new wasm object we use `makeRef` with "holdings" of a thunk to
|
||||
// free the wasm instance. Once the `this` (the instance we're
|
||||
// creating) is gc'd then the finalizer will run with the
|
||||
// `WeakRef`, and we'll pull out the `holdings`, our pointer.
|
||||
//
|
||||
// Note, though, that if manual finalization happens we want to
|
||||
// cancel the `WeakRef`-generated finalization, so we retain the
|
||||
// `WeakRef` in a global map. This global map is then used to
|
||||
// `drop()` the `WeakRef` (cancel finalization) whenever it is
|
||||
// finalized.
|
||||
self.expose_cleanup_groups();
|
||||
let mk = format!("
|
||||
const cleanup_ptr = this.ptr;
|
||||
const ref = CLEANUPS.makeRef(this, () => free{}(cleanup_ptr));
|
||||
CLEANUPS_MAP.set(this.ptr, ref);
|
||||
", name);
|
||||
let free = "
|
||||
CLEANUPS_MAP.get(ptr).drop();
|
||||
CLEANUPS_MAP.delete(ptr);
|
||||
";
|
||||
(mk, free)
|
||||
} else {
|
||||
(String::new(), "")
|
||||
};
|
||||
|
||||
if self.config.debug || class.constructor.is_some() {
|
||||
self.expose_constructor_token();
|
||||
|
||||
@ -516,9 +549,11 @@ impl<'a> Context<'a> {
|
||||
// This invocation of new will call this constructor with a ConstructorToken
|
||||
let instance = {class}.{constructor}(...args);
|
||||
this.ptr = instance.ptr;
|
||||
{mkweakref}
|
||||
",
|
||||
class = name,
|
||||
constructor = constructor
|
||||
constructor = constructor,
|
||||
mkweakref = mkweakref,
|
||||
));
|
||||
} else {
|
||||
dst.push_str(
|
||||
@ -537,9 +572,11 @@ impl<'a> Context<'a> {
|
||||
|
||||
constructor(ptr) {{
|
||||
this.ptr = ptr;
|
||||
{}
|
||||
}}
|
||||
",
|
||||
name
|
||||
name,
|
||||
mkweakref,
|
||||
));
|
||||
}
|
||||
|
||||
@ -599,16 +636,29 @@ impl<'a> Context<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
dst.push_str(&format!(
|
||||
self.global(&format!(
|
||||
"
|
||||
free() {{
|
||||
const ptr = this.ptr;
|
||||
this.ptr = 0;
|
||||
function free{}(ptr) {{
|
||||
{}
|
||||
wasm.{}(ptr);
|
||||
}}
|
||||
",
|
||||
name,
|
||||
freeref,
|
||||
shared::free_function(&name)
|
||||
));
|
||||
dst.push_str(&format!(
|
||||
"
|
||||
free() {{
|
||||
if (this.ptr === 0)
|
||||
return;
|
||||
const ptr = this.ptr;
|
||||
this.ptr = 0;
|
||||
free{}(this.ptr);
|
||||
}}
|
||||
",
|
||||
name,
|
||||
));
|
||||
ts_dst.push_str("free(): void;\n");
|
||||
dst.push_str(&class.contents);
|
||||
ts_dst.push_str(&class.typescript);
|
||||
@ -1594,6 +1644,18 @@ impl<'a> Context<'a> {
|
||||
");
|
||||
}
|
||||
|
||||
fn expose_cleanup_groups(&mut self) {
|
||||
if !self.exposed_globals.insert("cleanup_groups") {
|
||||
return
|
||||
}
|
||||
self.global(
|
||||
"
|
||||
const CLEANUPS = new WeakRefGroup(x => x.holdings());
|
||||
const CLEANUPS_MAP = new Map();
|
||||
"
|
||||
);
|
||||
}
|
||||
|
||||
fn gc(&mut self) -> Result<(), Error> {
|
||||
let module = mem::replace(self.module, Module::default());
|
||||
let module = module.parse_names().unwrap_or_else(|p| p.1);
|
||||
|
@ -10,6 +10,7 @@ extern crate failure;
|
||||
|
||||
use std::any::Any;
|
||||
use std::collections::BTreeSet;
|
||||
use std::env;
|
||||
use std::fmt;
|
||||
use std::fs;
|
||||
use std::mem;
|
||||
@ -33,6 +34,9 @@ pub struct Bindgen {
|
||||
typescript: bool,
|
||||
demangle: bool,
|
||||
keep_debug: bool,
|
||||
// Experimental support for `WeakRefGroup`, an upcoming ECMAScript feature.
|
||||
// Currently only enable-able through an env var.
|
||||
weak_refs: bool,
|
||||
}
|
||||
|
||||
enum Input {
|
||||
@ -55,6 +59,7 @@ impl Bindgen {
|
||||
typescript: false,
|
||||
demangle: true,
|
||||
keep_debug: false,
|
||||
weak_refs: env::var("WASM_BINDGEN_WEAKREF").is_ok(),
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user