Skip to content

Commit

Permalink
Add Symbol.dispose/Explicit Resource Management example (via Deno)
Browse files Browse the repository at this point in the history
  • Loading branch information
H-Plus-Time committed Sep 20, 2024
1 parent 5d2d399 commit 4dc3864
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ members = [
"examples/deno",
"examples/dom",
"examples/duck-typed-interfaces",
"examples/explicit-resource-management",
"examples/fetch",
"examples/guide-supported-types-examples",
"examples/hello_world",
Expand Down
12 changes: 12 additions & 0 deletions examples/explicit-resource-management/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
authors = ["The wasm-bindgen Developers"]
edition = "2021"
name = "explicit-resource-management"
publish = false
version = "0.0.0"

[lib]
crate-type = ["cdylib"]

[dependencies]
wasm-bindgen = { path = "../../" }
16 changes: 16 additions & 0 deletions examples/explicit-resource-management/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Using Explicit Resource Management (via Deno)

You can build the example with

```sh
$ ./build.sh
```

and test it with

```sh
$ deno run --allow-read test.ts
```

The `--allow-read` flag is needed because the Wasm file is read during runtime.
This will be fixed when https://github.com/denoland/deno/issues/2552 is resolved.
7 changes: 7 additions & 0 deletions examples/explicit-resource-management/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/sh

set -eux

cargo build --target wasm32-unknown-unknown --release
WASM_BINDGEN_SYMBOL_DISPOSE=1 cargo run --package wasm-bindgen-cli --bin wasm-bindgen -- \
--out-dir pkg --target deno ${CARGO_TARGET_DIR:-../../target}/wasm32-unknown-unknown/release/explicit_resource_management.wasm
1 change: 1 addition & 0 deletions examples/explicit-resource-management/crate/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/explicit-resource-management.wasm
63 changes: 63 additions & 0 deletions examples/explicit-resource-management/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
use std::alloc::{GlobalAlloc, Layout, System};
use std::sync::atomic::{AtomicUsize, Ordering::Relaxed};
use wasm_bindgen::prelude::*;

// simple counting allocator tracking
struct Counter;

static ALLOCATED: AtomicUsize = AtomicUsize::new(0);

unsafe impl GlobalAlloc for Counter {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
let ret = System.alloc(layout);
if !ret.is_null() {
ALLOCATED.fetch_add(layout.size(), Relaxed);
}
ret
}

unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
System.dealloc(ptr, layout);
ALLOCATED.fetch_sub(layout.size(), Relaxed);
}
}

#[global_allocator]
static A: Counter = Counter;

#[wasm_bindgen]
pub fn current_allocation() -> usize {
ALLOCATED.load(Relaxed)
}

// lifted from the `console_log` example
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console)]
fn log(s: &str);
}

#[wasm_bindgen]
pub struct MyStruct {
x: Vec<i64>,
y: Vec<i64>,
name: String,
}

#[wasm_bindgen]
impl MyStruct {
#[wasm_bindgen(constructor)]
pub fn new(name: String) -> MyStruct {
Self {
name,
x: (0..50).collect(),
y: (0..50).collect(),
}
}
}

impl Drop for MyStruct {
fn drop(&mut self) {
log(&format!("Goodbye from {}!", self.name)); // should output "Goodbye from Rust!"
}
}
17 changes: 17 additions & 0 deletions examples/explicit-resource-management/test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { current_allocation, MyStruct } from "./pkg/explicit_resource_management.js";

const initialAllocation = current_allocation();
let referrent = {};
console.log('Before scope: ', initialAllocation);

{
using foo = new MyStruct("Rust");
// force foo to be treated as live by implicit memory management (FinalizationRegistry/GC)
// by retaining a reference that outlives the scope block (for the purposes of proving
// Symbol.dispose is called on scope exit).
referrent['foo'] = foo;
console.log('After construction, but before scope exit: ', current_allocation());
}
const afterDisposeAllocation = current_allocation();
console.log('After scope exit: ', afterDisposeAllocation);
console.log(referrent);

0 comments on commit 4dc3864

Please sign in to comment.