React Aria Components collections crash: host and text nodes ignore the portal container's ownerDocument

未关闭
#163 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

还没有人认领这个 Issue。

评估

难度
4/5
预计耗时
3-5 天
新手友好度
49/100
Issue 类型
缺陷
描述清晰度
基本清楚
活跃度
活跃
技术栈
react, typescript
领域
frontend

调研方向

Start with src/dom/reconcile.ts: inspect node creation around lines 599 and 1004, then child reordering around line 477. Reproduce with the Vite configuration and Tabs example from the issue, comparing behavior with and without the Redact plugin. Done means the collection mounts without either reported crash; the issue notes that the second crash is not confirmed in the minimal reproduction.

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

描述

Versions

  • @tanstack/redact 0.3.1
  • react and react-dom 19.3.1
  • react-aria-components 1.22.1 (react-aria 3.53.1)
  • vite 8.3.5, production build, Chromium

What happens

Any React Aria Components collection (Tabs here) crashes on mount and leaves the root empty:

Uncaught TypeError: Cannot set property previousSibling of #<Node> which has only a getter
    at appendChild (react-aria collections Document)

The same app built without the redact() plugin renders both tabs with no console errors.

Reproduction

// vite.config.ts
import { redact } from "@tanstack/redact/vite"
import react from "@vitejs/plugin-react"
import { defineConfig } from "vite"

export default defineConfig({ plugins: [react(), redact()] })
// src/main.tsx
import { createRoot } from "react-dom/client"
import { Tab, TabList, TabPanel, Tabs } from "react-aria-components"

createRoot(document.getElementById("root")!).render(
  <Tabs>
    <TabList aria-label="Example">
      <Tab id="a">A</Tab>
      <Tab id="b">B</Tab>
    </TabList>
    <TabPanel id="a">Panel A</TabPanel>
    <TabPanel id="b">Panel B</TabPanel>
  </Tabs>,
)

Run vite build && vite preview and open the page.

Cause

React Aria builds its collections by calling createPortal(children, doc), where doc is its own fake Document (react-aria/dist/private/collections/Document.mjs). Its nodes have their own appendChild, insertBefore and ownerDocument.

This relies on the renderer creating nodes through the portal container's ownerDocument, as I understand React DOM does. Redact uses the global document:

  • src/dom/reconcile.ts:1004: createHostNode(type, isSvg), whose owner parameter defaults to document
  • src/dom/reconcile.ts:599: document.createTextNode(text)

A real DOM node then reaches the fake appendChild, which assigns child.previousSibling and throws, because that property is a getter on a real Node.

Possible fix, partly tested

Using the parent's owner document got past this crash when applied to dist/dom/reconcile.js in a larger app, using a build-time transform:

fiber.n = createHostNode(type, isSvg, domParent.ownerDocument || document)
fiber.n = (domParent.ownerDocument || document).createTextNode(text)

I only tried this as an experiment in that app, not against Redact's test suite.

Second crash after that fix

With the fix applied, the larger app's page using Tabs then threw this:

TypeError: r.compareDocumentPosition is not a function

The likely source is src/dom/reconcile.ts:477, which calls d.compareDocumentPosition(targetNext) while reordering children. I found no such method in a search of React Aria's Document.mjs. I haven't confirmed the call site or reproduced this crash in the minimal app.

Impact

We evaluated Redact for a TanStack Start dashboard built on React Aria Components. With Redact enabled:

  • 318 of 1231 unit and story tests failed; all pass on React.
  • No E2E test passed, because the sign-in flow failed for every role.

Not all of those story failures are confirmed to be this bug. The most common error was Cannot read properties of undefined (reading 'toLowerCase') (116 occurrences), which I haven't diagnosed, so it may be a separate issue.

主要语言
TypeScript
星标
537
派生
22
平均合并
10 小时 27 分钟
30 天内合并 PR
40

环境准备

这个项目没有提供开发容器、Dockerfile 或贡献指南,环境需要你自己搭建:先看它的 README,通用步骤见我们的新手贡献指南。

从这里开始

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

TanStack/redact 的其他 Issue

查看 TanStack/redact 的全部 Issue

相似的 Issue

更多 TypeScript Issue

把新 issue 发到你的邮箱

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