Summary
MeshPortalMaterial throws on construction under @react-three/drei/webgpu,
taking the whole canvas subtree down with it. It is unusable on the WebGPU entry.
TypeError: Cannot read properties of undefined (reading 'value')
at get map (@react-three/drei/webgpu/index.mjs)
at PortalMaterialImpl.setDefaultValues (three/build/three.webgpu.js)
at new MeshBasicNodeMaterial (three/build/three.webgpu.js)
at new PortalMaterialImpl (@react-three/drei/webgpu/index.mjs)
at handleContainerEffects (@react-three/fiber/dist/webgpu/index.mjs)
followed by a second, cascading error as React unwinds the failed subtree:
TypeError: Cannot read properties of undefined (reading 'map')
at resolve (@react-three/fiber/dist/webgpu/index.mjs)
at detach (@react-three/fiber/dist/webgpu/index.mjs)
at removeChild ...
Cause: class fields initialise after super() returns
class PortalMaterialImpl extends MeshBasicNodeMaterial {
_blur;
_map; // <- undefined until after super() completes
...
constructor() {
super(); // <- reads this.map before the line below has run
this._blur = uniform(0);
this._map = uniformTexture(new THREE.Texture());
...
}
get map() { return this._map.value; } // boom
set map(v) { this._map.value = v ?? new THREE.Texture(); }
}
Material.setDefaultValues probes every property of the reference material:
// three/src/materials/nodes/NodeMaterial.js
setDefaultValues( material ) {
for ( const property in material ) {
const value = material[ property ];
if ( this[ property ] === undefined ) { // <- fires the `map` getter
this[ property ] = value;
MeshBasicNodeMaterial's constructor calls that, so get map() runs from
inside super() β before _map exists. Per the JS class-fields spec, subclass
field initialisers do not run until super() returns, so this is not a
three-version quirk; it is unconditional.
map is the only accessor that collides today, because it is the only one of
these six names that is also a real MeshBasicMaterial property. The rest
(blur, sdf, blend, size, resolution) are latent β they break the moment
three adds a matching property name.
The same shape appears in BlendMaterial (_textureA, _textureB, _blend)
and UVRenderMaterial (_tex, _inside), and in a long tail of other
uniform-backed materials in that entry, so it may be worth a sweep rather than a
point fix.
Suggested fix
Make the accessors tolerate being called before the uniforms exist:
- get map() { return this._map.value; }
- set map(v) { this._map.value = v ?? new THREE.Texture(); }
+ get map() { return this._map?.value; }
+ set map(v) { if (this._map) this._map.value = v ?? new THREE.Texture(); }
Dropping the write during super() is safe here: the constructor assigns
_map = uniformTexture(new THREE.Texture()) immediately afterwards, which is the
value the class wants anyway, and RenderTexture attaches the real texture later
via attach="map".
Workaround
pnpm patch @react-three/drei@11.0.0-alpha.5, guarding all six accessor pairs on
PortalMaterialImpl. Confirmed working: portals render correctly on the WebGPU
entry afterwards, no console errors.
Environment
|
|
@react-three/drei |
11.0.0-alpha.5 (entry: @react-three/drei/webgpu) |
@react-three/fiber |
10.0.0-alpha.3 (entry: @react-three/fiber/webgpu) |
three |
0.185.1 |
| React |
19.2.8 |
| Bundler |
Next.js 16.3.0, Turbopack |
Separate from #2764, which is an import-name mismatch in the same entry β both
have to be patched before MeshPortalMaterial can be used at all under WebGPU.
Summary
MeshPortalMaterialthrows on construction under@react-three/drei/webgpu,taking the whole canvas subtree down with it. It is unusable on the WebGPU entry.
followed by a second, cascading error as React unwinds the failed subtree:
Cause: class fields initialise after
super()returnsMaterial.setDefaultValuesprobes every property of the reference material:MeshBasicNodeMaterial's constructor calls that, soget map()runs frominside
super()β before_mapexists. Per the JS class-fields spec, subclassfield initialisers do not run until
super()returns, so this is not athree-version quirk; it is unconditional.
mapis the only accessor that collides today, because it is the only one ofthese six names that is also a real
MeshBasicMaterialproperty. The rest(
blur,sdf,blend,size,resolution) are latent β they break the momentthree adds a matching property name.
The same shape appears in
BlendMaterial(_textureA,_textureB,_blend)and
UVRenderMaterial(_tex,_inside), and in a long tail of otheruniform-backed materials in that entry, so it may be worth a sweep rather than a
point fix.
Suggested fix
Make the accessors tolerate being called before the uniforms exist:
Dropping the write during
super()is safe here: the constructor assigns_map = uniformTexture(new THREE.Texture())immediately afterwards, which is thevalue the class wants anyway, and
RenderTextureattaches the real texture latervia
attach="map".Workaround
pnpm patch @react-three/drei@11.0.0-alpha.5, guarding all six accessor pairs onPortalMaterialImpl. Confirmed working: portals render correctly on the WebGPUentry afterwards, no console errors.
Environment
@react-three/drei11.0.0-alpha.5(entry:@react-three/drei/webgpu)@react-three/fiber10.0.0-alpha.3(entry:@react-three/fiber/webgpu)three0.185.119.2.816.3.0, TurbopackSeparate from #2764, which is an import-name mismatch in the same entry β both
have to be patched before
MeshPortalMaterialcan be used at all under WebGPU.