Make XRHand::joints_ a Member

XRHand::joints_ is currently just a HeapVector. However, in order to
create a GarbageCollected XRHandIterationSource it either needs to be
copied in or made a Member, as otherwise we end up with a
'GarbageCollected' type that isn't actually GarbageCollected, and this
can lead to some Heap corruption.

Bug: 357653515
Change-Id: I462f4583b6f16718b1e84ccc2b3f81a49704d1cd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5941589
Reviewed-by: Brandon Jones <bajones@chromium.org>
Commit-Queue: Brandon Jones <bajones@chromium.org>
Commit-Queue: Alexander Cooper <alcooper@chromium.org>
Auto-Submit: Alexander Cooper <alcooper@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1370801}
diff --git a/third_party/blink/renderer/modules/xr/xr_hand.cc b/third_party/blink/renderer/modules/xr/xr_hand.cc
index 1bacd86..e85de21 100644
--- a/third_party/blink/renderer/modules/xr/xr_hand.cc
+++ b/third_party/blink/renderer/modules/xr/xr_hand.cc
@@ -14,12 +14,14 @@
 
 namespace blink {
 
+using XRJointVector = HeapVector<Member<XRJointSpace>>;
+
 class XRHandIterationSource final
     : public PairSyncIterable<XRHand>::IterationSource {
  public:
-  explicit XRHandIterationSource(const HeapVector<Member<XRJointSpace>>& joints,
+  explicit XRHandIterationSource(const Member<XRJointVector>& joints,
                                  XRHand* xr_hand)
-      : joints_(&joints), xr_hand_(xr_hand) {}
+      : joints_(joints), xr_hand_(xr_hand) {}
 
   bool FetchNextItem(ScriptState*,
                      V8XRHandJoint& key,
@@ -42,20 +44,20 @@
 
  private:
   wtf_size_t index_ = 0;
-  const Member<const HeapVector<Member<XRJointSpace>>> joints_;
+  const Member<const XRJointVector> joints_;
   Member<XRHand> xr_hand_;  // Owner object of `joints_`
 };
 
 XRHand::XRHand(const device::mojom::blink::XRHandTrackingData* state,
-               XRInputSource* input_source)
-    : joints_(kNumJoints) {
+               XRInputSource* input_source) {
+  joints_ = MakeGarbageCollected<XRJointVector>(kNumJoints);
   DCHECK_EQ(kNumJoints, V8XRHandJoint::kEnumSize);
   for (unsigned i = 0; i < kNumJoints; ++i) {
     device::mojom::blink::XRHandJoint joint =
         static_cast<device::mojom::blink::XRHandJoint>(i);
     DCHECK_EQ(MojomHandJointToV8Enum(joint),
               static_cast<V8XRHandJoint::Enum>(i));
-    joints_[i] = MakeGarbageCollected<XRJointSpace>(
+    joints_->at(i) = MakeGarbageCollected<XRJointSpace>(
         this, input_source->session(), nullptr, joint, 0.0f,
         input_source->xr_handedness());
   }
@@ -65,7 +67,7 @@
 
 XRJointSpace* XRHand::get(const V8XRHandJoint& key) const {
   wtf_size_t index = static_cast<wtf_size_t>(key.AsEnum());
-  return joints_[index].Get();
+  return joints_->at(index).Get();
 }
 
 void XRHand::updateFromHandTrackingData(
@@ -86,8 +88,8 @@
       new_missing_poses = true;
     }
 
-    joints_[joint_index]->UpdateTracking(std::move(mojo_from_joint),
-                                         hand_joint->radius);
+    joints_->at(joint_index)
+        ->UpdateTracking(std::move(mojo_from_joint), hand_joint->radius);
   }
 
   if (new_missing_poses) {
@@ -96,7 +98,7 @@
   } else if (has_missing_poses_ && new_poses) {
     // Need to check if there are any missing poses
     has_missing_poses_ =
-        !base::ranges::all_of(joints_, &XRJointSpace::MojoFromNative);
+        !base::ranges::all_of(*joints_, &XRJointSpace::MojoFromNative);
   }
 }
 
diff --git a/third_party/blink/renderer/modules/xr/xr_hand.h b/third_party/blink/renderer/modules/xr/xr_hand.h
index 9a22fdd1a..ea7ffd2 100644
--- a/third_party/blink/renderer/modules/xr/xr_hand.h
+++ b/third_party/blink/renderer/modules/xr/xr_hand.h
@@ -20,7 +20,7 @@
 class XRHand : public ScriptWrappable, public PairSyncIterable<XRHand> {
   DEFINE_WRAPPERTYPEINFO();
 
-  static const unsigned kNumJoints =
+  static constexpr unsigned kNumJoints =
       static_cast<unsigned>(device::mojom::blink::XRHandJoint::kMaxValue) + 1u;
 
  public:
@@ -28,7 +28,7 @@
                   XRInputSource* input_source);
   ~XRHand() override = default;
 
-  size_t size() const { return joints_.size(); }
+  size_t size() const { return joints_->size(); }
 
   XRJointSpace* get(const V8XRHandJoint& key) const;
 
@@ -44,7 +44,7 @@
   IterationSource* CreateIterationSource(ScriptState*,
                                          ExceptionState&) override;
 
-  HeapVector<Member<XRJointSpace>> joints_;
+  Member<HeapVector<Member<XRJointSpace>>> joints_;
   bool has_missing_poses_ = true;
 };