TanStack / TanStack/devtools

devtools-vite: source injection silently yields zero data-tsd-source attributes (AST child-key cache poisoned by regex literals)

Đang mở
#523 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

Ngôn ngữ chính
TypeScript
Star
499
Fork
100
Merge trung bình
1 ngày 17 giờ
Pull request đã merge (30 ngày)
4

Mô tả

TanStack Devtools version
  • @tanstack/devtools-vite@0.8.5
  • transitive @tanstack/devtools-bundler-core@0.1.3
  • @tanstack/react-devtools@0.10.12 (transitive @tanstack/devtools@0.14.2)
  • Vite 8.2.2, Astro 7.2.9 (Astro drives Vite here; I could not reproduce with plain Vite)
  • Node 26.7.0, Linux
Describe the bug and the steps to reproduce it

The "Go to Source" / source inspector feature injects zero data-tsd-source
attributes. There is no browser console warning and nothing in the Vite dev
server log, so the feature just silently does nothing.

Root cause, from reading @tanstack/devtools-bundler-core/dist/esm/ast-utils.js.
getChildKeys(node) memoises the child-bearing keys of each AST node type in a
module-level childKeysCache Map, seeded from the first instance of that
type it ever sees:

for (const key in node) {
  if (key === "type" || key === "start" || key === "end") continue;
  if (typeof node[key] === "object") keys.push(key);
}

A regex literal (/abc/g) is an oxc Literal whose value is an object, so
value is cached as a child key for the type Literal. Every subsequent
string Literal then reaches:

} else if ("type" in value) callback(value);

with value being a string, and throws:

TypeError: Cannot use 'in' operator to search for 'type' in use client
    at forEachChild (.../@tanstack/devtools-bundler-core/dist/esm/ast-utils.js:31:21)

"use client" is simply the first string literal in that particular file; the
throw happens for any string literal. addSourceToJsx() wraps its whole body in
try { ... } catch (e) { return; }, so the TypeError is swallowed and the
function returns undefined — no attributes, no log, no warning.

Because the cache is module-level and shared across every file and every call,
a single regex literal anywhere in the module graph disables source injection
for every string literal parsed afterwards. That is why this reproduces in a
real dev server but not in an isolated unit test.

Minimal reproduction

Two separate node processes, same target file (any .tsx file with JSX):

import { addSourceToJsx } from '@tanstack/devtools-bundler-core'

// Case A — fresh cache: works
addSourceToJsx(heroCode, heroPath, {})   // -> transformed, N attributes injected

// Case B — parse a regex literal first, then the same file: returns undefined
addSourceToJsx('const r = /abc/g;\nexport default r;\n', regexPath, {})
addSourceToJsx(heroCode, heroPath, {})   // -> undefined

Run the two cases in separate processes. Case A injects the attributes,
Case B returns undefined.

Observed in a real app: a component that reported 36 injected attributes in
isolation injected 0 once the dev server had processed the rest of the graph.

Expected behavior

Source injection should not depend on which files were parsed earlier. And a
failure inside addSourceToJsx should at least be logged rather than swallowed,
so the feature cannot fail completely silently.

Suggested fix

Guard the non-array branch the same way the array branch already is:

- } else if ("type" in value) callback(value);
+ } else if (typeof value === "object" && "type" in value) callback(value);

With that guard, Case B injects the attributes again. A more thorough fix would
make getChildKeys key the cache on the shape of the node (or only record
keys whose value is a node or an array of nodes) and drop the bare catch.

I am carrying this as a local patch-package patch for now.

Do you intend to try to help solve this bug with your own PR?

Maybe, I'll investigate and start debugging

Terms & Code of Conduct
  • I agree to follow this project's Code of Conduct
  • I understand that if my bug cannot be reliably reproduced in a debuggable environment, it will probably not get fixed and this issue may even be closed.

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Hướng nghiên cứu

Bắt đầu với việc duyệt AST trong ast-utils.js của @tanstack/devtools-bundler-core và entry point addSourceToJsx. Chạy bản tái hiện tối thiểu gồm hai process, trước tiên xác nhận rằng một regex literal làm hỏng các string literal phía sau. Được xem là hoàn tất khi việc chèn source vẫn thêm các thuộc tính data-tsd-source sau khi các file regex được xử lý và các lỗi không còn âm thầm vô hình nữa.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Công nghệ
devtools, typescript, vite
Lĩnh vực
build-system, tooling
Loại issue
Lỗi
Độ khó
3/5
Thời gian dự kiến
1-2 ngày
Mức độ hoạt động
Sôi nổi
Độ rõ ràng
Đặc tả rõ ràng
Mức phù hợp với người mới
74/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.