mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-03-15 09:40:52 +00:00
Merge pull request #1557 from devsnek/new-weakref
Rewrite weakrefs to use current proposal
This commit is contained in:
commit
dfcaabc738
@ -488,8 +488,8 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
|
|||||||
if self.cx.config.weak_refs {
|
if self.cx.config.weak_refs {
|
||||||
self.ret_expr.push_str(&format!(
|
self.ret_expr.push_str(&format!(
|
||||||
"\
|
"\
|
||||||
addCleanup(this, this.ptr, free{});
|
{}FinalizationGroup.register(this, this.ptr, this.ptr);
|
||||||
",
|
",
|
||||||
name
|
name
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -1103,35 +1103,6 @@ impl<'a> Context<'a> {
|
|||||||
let mut dst = format!("class {} {{\n", name);
|
let mut dst = format!("class {} {{\n", name);
|
||||||
let mut ts_dst = format!("export {}", dst);
|
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!("addCleanup(this, this.ptr, free{});", name);
|
|
||||||
let free = "
|
|
||||||
CLEANUPS_MAP.get(ptr).drop();
|
|
||||||
CLEANUPS_MAP.delete(ptr);
|
|
||||||
";
|
|
||||||
(mk, free)
|
|
||||||
} else {
|
|
||||||
(String::new(), "")
|
|
||||||
};
|
|
||||||
|
|
||||||
if self.config.debug && !class.has_constructor {
|
if self.config.debug && !class.has_constructor {
|
||||||
dst.push_str(
|
dst.push_str(
|
||||||
"
|
"
|
||||||
@ -1165,29 +1136,52 @@ impl<'a> Context<'a> {
|
|||||||
}}
|
}}
|
||||||
",
|
",
|
||||||
name,
|
name,
|
||||||
mkweakref.replace("this", "obj"),
|
if self.config.weak_refs {
|
||||||
|
format!("{}FinalizationGroup.register(obj, obj.ptr, obj.ptr);", name)
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
},
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.global(&format!(
|
self.global(&format!(
|
||||||
"
|
"
|
||||||
function free{}(ptr) {{
|
function free{}(ptr) {{
|
||||||
{}
|
|
||||||
wasm.{}(ptr);
|
wasm.{}(ptr);
|
||||||
}}
|
}}
|
||||||
",
|
",
|
||||||
name,
|
name,
|
||||||
freeref,
|
|
||||||
wasm_bindgen_shared::free_function(&name)
|
wasm_bindgen_shared::free_function(&name)
|
||||||
));
|
));
|
||||||
|
|
||||||
|
if self.config.weak_refs {
|
||||||
|
self.global(&format!(
|
||||||
|
"
|
||||||
|
const {}FinalizationGroup = new FinalizationGroup((items) => {{
|
||||||
|
for (const ptr of items) {{
|
||||||
|
free{}(ptr);
|
||||||
|
}}
|
||||||
|
}});
|
||||||
|
",
|
||||||
|
name,
|
||||||
|
name,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
dst.push_str(&format!(
|
dst.push_str(&format!(
|
||||||
"
|
"
|
||||||
free() {{
|
free() {{
|
||||||
const ptr = this.ptr;
|
const ptr = this.ptr;
|
||||||
this.ptr = 0;
|
this.ptr = 0;
|
||||||
|
{}
|
||||||
free{}(ptr);
|
free{}(ptr);
|
||||||
}}
|
}}
|
||||||
",
|
",
|
||||||
|
if self.config.weak_refs {
|
||||||
|
format!("{}FinalizationGroup.unregister(ptr);", name)
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
},
|
||||||
name,
|
name,
|
||||||
));
|
));
|
||||||
ts_dst.push_str(" free(): void;");
|
ts_dst.push_str(" free(): void;");
|
||||||
@ -2279,23 +2273,6 @@ impl<'a> Context<'a> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expose_cleanup_groups(&mut self) {
|
|
||||||
if !self.should_write_global("cleanup_groups") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self.global(
|
|
||||||
"
|
|
||||||
const CLEANUPS = new WeakRefGroup(x => x.holdings());
|
|
||||||
const CLEANUPS_MAP = new Map();
|
|
||||||
|
|
||||||
function addCleanup(obj, ptr, free) {
|
|
||||||
const ref = CLEANUPS.makeRef(obj, () => free(ptr));
|
|
||||||
CLEANUPS_MAP.set(ptr, ref);
|
|
||||||
}
|
|
||||||
",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn describe(&mut self, name: &str) -> Option<Descriptor> {
|
fn describe(&mut self, name: &str) -> Option<Descriptor> {
|
||||||
let name = format!("__wbindgen_describe_{}", name);
|
let name = format!("__wbindgen_describe_{}", name);
|
||||||
let descriptor = self.interpreter.interpret_descriptor(&name, self.module)?;
|
let descriptor = self.interpreter.interpret_descriptor(&name, self.module)?;
|
||||||
|
@ -25,7 +25,7 @@ pub struct Bindgen {
|
|||||||
remove_name_section: bool,
|
remove_name_section: bool,
|
||||||
remove_producers_section: bool,
|
remove_producers_section: bool,
|
||||||
emit_start: bool,
|
emit_start: bool,
|
||||||
// Experimental support for `WeakRefGroup`, an upcoming ECMAScript feature.
|
// Experimental support for weakrefs, an upcoming ECMAScript feature.
|
||||||
// Currently only enable-able through an env var.
|
// Currently only enable-able through an env var.
|
||||||
weak_refs: bool,
|
weak_refs: bool,
|
||||||
// Experimental support for the wasm threads proposal, transforms the wasm
|
// Experimental support for the wasm threads proposal, transforms the wasm
|
||||||
|
Loading…
x
Reference in New Issue
Block a user