diff --git a/third_party/blink/renderer/modules/xr/xr_frame.cc b/third_party/blink/renderer/modules/xr/xr_frame.cc index 0d391336694c8..c24af96cfff6f 100644 --- a/third_party/blink/renderer/modules/xr/xr_frame.cc +++ b/third_party/blink/renderer/modules/xr/xr_frame.cc @@ -570,7 +570,17 @@ bool XRFrame::fillPoses(const HeapVector>& spaces, auto transforms_data = transforms->AsSpan(); for (const auto& space : spaces) { auto current_transform = transforms_data.take_first(); - if (const XRPose* pose = space->getPose(base_space)) { + const XRPose* pose = space->getPose(base_space); + // getPose() can reach XRBoundedReferenceSpace::EnsureUpdated() which + // synchronously dispatches a 'reset' event to author script. That script + // may transfer/detach |transforms|, leaving |transforms_data| (and + // |current_transform|) dangling. Re-check before every write. + if (transforms->IsDetached()) { + exception_state.ThrowTypeError( + "The transforms array was detached during fillPoses()."); + return false; + } + if (pose) { current_transform.copy_from(pose->transform()->matrix()->AsSpan()); } else { std::ranges::fill(current_transform, NAN);