bun_ptr: RefPtr::new_cyclic; a BackRef<_, Root> can no longer be dangling

JA
2mo ago
+115-7

What

Follow-up to #40192 (raised in review of #40203): BackRef::dangling() was generic over the provenance marker, so a BackRef<T, Root> — which can hand out a ThisPtr — could be created dangling and "patched later" (CronJob::self_ref did exactly that: Cell::new(BackRef::dangling()) then set(BackRef::from(job.this_ptr())) after RefPtr::new).

  • RefPtr::new_cyclic(|this: SelfRoot<T>| -> T) (à la Arc::new_cyclic): allocates the slot, hands init an opaque SelfRoot<T> token to store, writes the value, adopts the ref. SelfRoot has no accessors of its own — this_ptr(&self, owner: &T) / backref(&self, owner: &T) need the constructed &T, so the pointer cannot be followed inside init.
  • BackRef::dangling() is now only available for Shared/Mut (sealed DanglingOk bound), so a Root back-reference is always minted from a real root (From<ThisPtr>, from_root, or new_cyclic).
  • CronJob::self_ref becomes a SelfRoot<CronJob> field initialised through new_cyclic (self.self_ref.this_ptr(self)); no Cell, no two-phase init.

Testing

test/js/bun/cron 162/162 on debug+ASAN; clippy clean on bun_ptr / bun_runtime / bun_bundler (the two bundler BackRef::dangling() placeholders are Shared and unchanged).