In box2d-wasm, you cannot safely assign custom properties directly to the JS objects returned by the API (e.g., b2Body). Because Emscripten reuses JS objects for recycled WASM memory, properties assigned to a destroyed object will persist and appear on the next object that occupies that same memory address, leading to data corruption and logic errors.
To manage metadata safely, you must store it externally to the Box2D JS objects using one of the following patterns:
1. Using Pointers as Keys (Recommended)
Use getPointer(object) to retrieve the memory address and use that as a key in a standard JavaScript object or Map. This is the most robust method.
2. Using the JS Object as a Key
Since Box2D object references are reused, you can use the object itself as a key in a metadata object. This is simpler but relies on the same object-reuse behavior.
3. Using Prototypical Inheritance (Hydration Pattern)
If you want the metadata to appear as if it lives on the Box2D object, you can create a wrapper using Object.setPrototypeOf. This allows you to access both your custom metadata and the original Box2D methods on the same reference.
Important: Regardless of the method chosen, you must manually delete the metadata when you call world.DestroyBody(object) to prevent memory leaks and stale data.
/**
* Recommended: Using pointers as keys
*/
const metadata = {}
const body = world.CreateBody(bd);
// Store metadata using the pointer
metadata[getPointer(body)] = {
favouriteDessert: 'pie'
};
// Cleanup
world.DestroyBody(body);
delete metadata[getPointer(body)];
/**
* Alternative: Prototypical inheritance (Hydration)
*/
const hydratedInstances = {}
// Create a 'hydrated' version where metadata is on the prototype
hydratedInstances[body] = Object.setPrototypeOf({
favouriteDessert: 'pie'
}, body);
// Access both metadata and Box2D methods
console.log(hydratedInstances[body].favouriteDessert);
console.log(hydratedInstances[body].GetMass());
// Cleanup
world.DestroyBody(body);
delete hydratedInstances[body];