Skip to content

Commit 4dc3864

Browse files
committed
Add Symbol.dispose/Explicit Resource Management example (via Deno)
1 parent 5d2d399 commit 4dc3864

File tree

7 files changed

+117
-0
lines changed

7 files changed

+117
-0
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ members = [
7979
"examples/deno",
8080
"examples/dom",
8181
"examples/duck-typed-interfaces",
82+
"examples/explicit-resource-management",
8283
"examples/fetch",
8384
"examples/guide-supported-types-examples",
8485
"examples/hello_world",
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[package]
2+
authors = ["The wasm-bindgen Developers"]
3+
edition = "2021"
4+
name = "explicit-resource-management"
5+
publish = false
6+
version = "0.0.0"
7+
8+
[lib]
9+
crate-type = ["cdylib"]
10+
11+
[dependencies]
12+
wasm-bindgen = { path = "../../" }
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Using Explicit Resource Management (via Deno)
2+
3+
You can build the example with
4+
5+
```sh
6+
$ ./build.sh
7+
```
8+
9+
and test it with
10+
11+
```sh
12+
$ deno run --allow-read test.ts
13+
```
14+
15+
The `--allow-read` flag is needed because the Wasm file is read during runtime.
16+
This will be fixed when https://github.com/denoland/deno/issues/2552 is resolved.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/bin/sh
2+
3+
set -eux
4+
5+
cargo build --target wasm32-unknown-unknown --release
6+
WASM_BINDGEN_SYMBOL_DISPOSE=1 cargo run --package wasm-bindgen-cli --bin wasm-bindgen -- \
7+
--out-dir pkg --target deno ${CARGO_TARGET_DIR:-../../target}/wasm32-unknown-unknown/release/explicit_resource_management.wasm
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/explicit-resource-management.wasm
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
use std::alloc::{GlobalAlloc, Layout, System};
2+
use std::sync::atomic::{AtomicUsize, Ordering::Relaxed};
3+
use wasm_bindgen::prelude::*;
4+
5+
// simple counting allocator tracking
6+
struct Counter;
7+
8+
static ALLOCATED: AtomicUsize = AtomicUsize::new(0);
9+
10+
unsafe impl GlobalAlloc for Counter {
11+
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
12+
let ret = System.alloc(layout);
13+
if !ret.is_null() {
14+
ALLOCATED.fetch_add(layout.size(), Relaxed);
15+
}
16+
ret
17+
}
18+
19+
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
20+
System.dealloc(ptr, layout);
21+
ALLOCATED.fetch_sub(layout.size(), Relaxed);
22+
}
23+
}
24+
25+
#[global_allocator]
26+
static A: Counter = Counter;
27+
28+
#[wasm_bindgen]
29+
pub fn current_allocation() -> usize {
30+
ALLOCATED.load(Relaxed)
31+
}
32+
33+
// lifted from the `console_log` example
34+
#[wasm_bindgen]
35+
extern "C" {
36+
#[wasm_bindgen(js_namespace = console)]
37+
fn log(s: &str);
38+
}
39+
40+
#[wasm_bindgen]
41+
pub struct MyStruct {
42+
x: Vec<i64>,
43+
y: Vec<i64>,
44+
name: String,
45+
}
46+
47+
#[wasm_bindgen]
48+
impl MyStruct {
49+
#[wasm_bindgen(constructor)]
50+
pub fn new(name: String) -> MyStruct {
51+
Self {
52+
name,
53+
x: (0..50).collect(),
54+
y: (0..50).collect(),
55+
}
56+
}
57+
}
58+
59+
impl Drop for MyStruct {
60+
fn drop(&mut self) {
61+
log(&format!("Goodbye from {}!", self.name)); // should output "Goodbye from Rust!"
62+
}
63+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { current_allocation, MyStruct } from "./pkg/explicit_resource_management.js";
2+
3+
const initialAllocation = current_allocation();
4+
let referrent = {};
5+
console.log('Before scope: ', initialAllocation);
6+
7+
{
8+
using foo = new MyStruct("Rust");
9+
// force foo to be treated as live by implicit memory management (FinalizationRegistry/GC)
10+
// by retaining a reference that outlives the scope block (for the purposes of proving
11+
// Symbol.dispose is called on scope exit).
12+
referrent['foo'] = foo;
13+
console.log('After construction, but before scope exit: ', current_allocation());
14+
}
15+
const afterDisposeAllocation = current_allocation();
16+
console.log('After scope exit: ', afterDisposeAllocation);
17+
console.log(referrent);

0 commit comments

Comments
 (0)