C++ has had smart pointers for memory (and other resource) management for a long time now (see e.g. the Windows ATL classes for working with COM objects and resources).
There are a number of challenges that make browsers more challenging (even in memory safe languages like Swift and Rust).
1. Back references/pointers like `parentElement` to other objects in the graph that create dependency cycles (where traditional/simple reference counting will prevent the objects being deallocated).
2. Interacting with (and creating resources in) a garbage collector when running/evaluating JavaScript code.
3. Just-in-Time (JIT) compilation of JavaScript and other complicated interpretation-compilation pipelines that can allocate and transfer objects between the different stages.