Firefox is written in Rust, and I suspect that their DOM implementation has backpointers (from children back to parents), for performance reasons. It might be interesting to check how they did it.
This is a good question, even if the details are wrong (the question should be about Servo, not Firefox/Gecko). The answer is somewhat idiosyncratic: Servo uses the SpiderMonkey garbage collector to manage DOM objects, which, like all tracing GCs, can deal with cycles just fine.
This ends up simultaneously solving the ever-annoying problem of "how do you manage memory when both JS and Rust can hold strong references to objects?" (In Servo's case, the answer is simply "just punt all of the logic to the JS engine.")
Firefox is not written in rust. It has multiple small components which were rewritten in rust recently, but it's far from the whole system. Their DOM is still C++