react / react/react-native

@react-native/babel-preset applies transform-destructuring unconditionally under Hermes — semantic divergence breaks three.js TSL (crashes every InstancedMesh on WebGPU)

未关闭
#57,934 2 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

Needs: Author Feedback Needs: Repro
主要语言
C++
星标
127k
派生
25.3k
平均合并
1 天 23 小时
30 天内合并 PR
4

描述

Description

@react-native/babel-preset pushes @babel/plugin-transform-destructuring unconditionally — including for Hermes targets (packages/react-native-babel-preset/src/configs/main.js, the always-on plugin list; verified in 0.81.4 at src/configs/main.js:122). Hermes supports array/object destructuring natively, so for Hermes builds the transform is (a) redundant bytecode and (b) a semantic hazard, because downleveled destructuring is not perfectly equivalent to native destructuring.

The concrete divergence: native array destructuring always goes through the iterator protocol, while Babel's _slicedToArray helper short-circuits via _arrayWithHolesif (Array.isArray(r)) return r; — and then indexes positionally. For a Proxy over an array (Array.isArray pierces to the target) whose get trap serves a custom Symbol.iterator but does not answer positional reads, the two compile outputs produce different values: iterator yields the real elements, indexing yields undefined.

That exotic-sounding object is shipping in one of the most popular 3D libraries: three.js's TSL shader system passes Fn arguments through exactly such a Proxy, and three's own sources destructure it (src/nodes/accessors/Instance.js: Fn( ( [ instancedMesh ] ) => { const { instanceMatrix, instanceColor } = instancedMesh; ... } )). Metro rewrites three's code with this transform, so on device the body receives undefined and every React Native app using three.js WebGPU (react-native-webgpu, Dawn/Vulkan) with an InstancedMesh crashes on the first rendered frame:

TypeError: Cannot read property 'instanceMatrix' of undefined
  at ... setupOutput / getOutputNode / build / flowNodeFromShaderStage / ... / render

The same pattern arms skinning(), batch() and morphReference() — i.e. skinned meshes, batched meshes and morph targets are equally affected. Nothing surfaces in Node/browser tests because those run untransformed code; the failure exists only in the Metro-bundled app.

Ask

Consider making transform-destructuring conditional on the engine target (skipped for Hermes, as several other transforms already are engine-aware), or documenting why it must stay unconditional. Cross-filed with the two neighboring projects, since each owns a slice of the collision:

Steps to reproduce
  1. Bare RN 0.81.4 app (Hermes, new arch) + react-native-webgpu 0.8.2 + three 0.185.1
  2. Render any scene containing a THREE.InstancedMesh with WebGPURenderer
  3. First frame throws TypeError: Cannot read property 'instanceMatrix' of undefined

A toolchain-only demonstration (no device needed): run @react-native/babel-preset over const fn = ([a]) => a; and observe the _slicedToArray output; feed it an array-backed Proxy with a custom Symbol.iterator in its get trap and no index handling — native semantics return the element, transformed semantics return undefined.

React Native Version

0.81.4

Affected Platforms

Runtime: Android (verified on device: Android 15, Hermes release bundle, Dawn/Vulkan). iOS untested but the transform is platform-independent.

Output of npx @react-native-community/cli info

Not attached — the report is toolchain-level (@react-native/babel-preset 0.81.4, @babel/plugin-transform-destructuring 7.29.7, @babel/runtime 7.29.7); happy to add on request.

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

从 packages/react-native-babel-preset/src/configs/main.js 开始,重点查看第 122 行附近始终启用的插件列表,并使用 issue 中的数组支持的 Proxy 示例复现该转换。比较现有的 Hermes 和非 Hermes 配置模式;完成的标准是 preset 要么避免 Hermes 的语义差异,要么记录保留该转换的已确认原因,并通过适当的测试覆盖 toolchain 的行为。

由索引模型根据 Issue 内容生成。

评估

技术栈
javascript, react-native, three.js
领域
build-system, mobile, tooling
Issue 类型
缺陷
难度
4/5
预计耗时
3-5 天
活跃度
活跃
描述清晰度
基本清楚
新手友好度
55/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。