From 4035bba3f0a9d3ff01dbb6263f9c01b661a01461 Mon Sep 17 00:00:00 2001 From: Aevyrie Roessler Date: Wed, 5 Aug 2026 11:14:11 -0700 Subject: [PATCH] fix(webgpu): reading a mapped buffer throws on a detached ArrayBuffer Cloning a buffer duplicated its cached mapped ArrayBuffer rather than sharing it, so unmapping through one clone left every other clone holding an ArrayBuffer that Javascript had already detached. The next read built a Uint8Array view over that buffer and threw "Cannot perform Construct on a detached ArrayBuffer". The same applies to the mapped range recorded by map_async, which was invisible to any other clone. Upstream carries this same change from 29.0.1 onward; 27.0.4 is still affected. --- wgpu/src/backend/webgpu.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/wgpu/src/backend/webgpu.rs b/wgpu/src/backend/webgpu.rs index 920ad58ba17..a8b976a185d 100644 --- a/wgpu/src/backend/webgpu.rs +++ b/wgpu/src/backend/webgpu.rs @@ -1215,8 +1215,9 @@ struct WebBufferMapState { pub struct WebBuffer { /// The associated GPU buffer. inner: webgpu_sys::GpuBuffer, - /// The mapped array buffer and mapped range. - mapping: RefCell, + /// The mapped array buffer and mapped range. Shared across clones, because an unmap through + /// any one clone detaches the `ArrayBuffer` for all of them. + mapping: Rc>, /// Unique identifier for this Buffer. ident: crate::cmp::Identifier, } @@ -1226,10 +1227,10 @@ impl WebBuffer { fn new(inner: webgpu_sys::GpuBuffer, desc: &crate::BufferDescriptor<'_>) -> Self { Self { inner, - mapping: RefCell::new(WebBufferMapState { + mapping: Rc::new(RefCell::new(WebBufferMapState { mapped_buffer: None, range: 0..desc.size, - }), + })), ident: crate::cmp::Identifier::create(), } }