Skip to content

fix(svelte-query): preserve array length updates in createRawRef#10836

Open
raashish1601 wants to merge 5 commits into
TanStack:mainfrom
raashish1601:fix/svelte-createqueries-empty-activates
Open

fix(svelte-query): preserve array length updates in createRawRef#10836
raashish1601 wants to merge 5 commits into
TanStack:mainfrom
raashish1601:fix/svelte-createqueries-empty-activates

Conversation

@raashish1601
Copy link
Copy Markdown
Contributor

@raashish1601 raashish1601 commented May 30, 2026

Summary: keep array length in sync when createRawRef adds numeric indices during update; this fixes createQueries activating from an empty array. Validation: pnpm --filter @tanstack/svelte-query test:lib -- --run tests/containers.svelte.test.ts tests/createQueries/createQueries.svelte.test.ts

Summary by CodeRabbit

  • Bug Fixes

    • Broadcast handling improved so newly added queries include state and receivers ignore malformed/empty add messages.
    • Array-backed reactive references fixed so numeric indexes correctly extend/shrink length; non-canonical index-like keys don’t affect length.
  • Behavior Change

    • Solid query resources now start when status fields are read, ensuring curried query options fetch on mount.
  • Tests

    • Added/expanded tests for broadcast sync, array-ref behaviors, reactive query activation, and resource-triggered fetching.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 30, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: dbc23db1-74b1-4d89-9b67-1fab2de3ecf4

📥 Commits

Reviewing files that changed from the base of the PR and between cc9c94d and 09577e1.

📒 Files selected for processing (3)
  • .changeset/solid-query-status-resource.md
  • packages/solid-query/src/__tests__/useQuery.test.tsx
  • packages/solid-query/src/useBaseQuery.ts
✅ Files skipped from review due to trivial changes (1)
  • .changeset/solid-query-status-resource.md

📝 Walkthrough

Walkthrough

Broadcast 'added' messages now include the query state; receivers ignore 'added' messages without state. Tests centralize a broadcastChannel and add a sender→receiver cache-seed sync test. Svelte ref proxy refines array-index handling and length syncing. Solid proxy triggers resource evaluation on status/resource property reads.

Changes

Query Broadcast Protocol

Layer / File(s) Summary
Broadcast 'added' message protocol
packages/query-broadcast-client-experimental/src/index.ts
Sender posts state in 'added' messages; receiver returns early if state is missing/falsy.
Test suite and integration coverage
packages/query-broadcast-client-experimental/src/__tests__/index.test.ts
Adds QueryClient/vi imports, introduces shared broadcastChannel constant, updates listener tests, and adds an integration test that seeds a sender cache and asserts the receiver eventually matches that state.

Svelte Query Array Ref Handling

Layer / File(s) Summary
Array index detection and proxy refinement
packages/svelte-query/src/containers.svelte.ts
Adds isArrayIndex and syncLengthFromVisibleIndexes; set extends target.length for valid numeric indices; deleteProperty recomputes length only when a recognized array index is removed.
Array behavior and reactive query tests
packages/svelte-query/tests/containers.svelte.test.ts, packages/svelte-query/tests/createQueries/createQueries.svelte.test.ts
Adds tests for length growth, destructuring, shrinking, non-canonical numeric-like keys, and a reactive createQueries activation test when queries becomes populated.

Solid Query resource-start tracking

Layer / File(s) Summary
Resource-tracking props and proxy get
packages/solid-query/src/useBaseQuery.ts
Introduces resourceTrackingProps and calls queryResource() from the proxy get when status/resource properties are accessed.
Tests and changeset documenting behavior
packages/solid-query/src/__tests__/useQuery.test.tsx, .changeset/solid-query-status-resource.md
Adds tests verifying curried queryOptions trigger fetches when only status or resource fields are read and adds a changeset entry documenting the behavior.

Sequence Diagram

sequenceDiagram
  participant QueryClientSender
  participant BroadcastChannel
  participant QueryClientReceiver
  QueryClientSender->>BroadcastChannel: post { type: "added", queryKey, state }
  BroadcastChannel->>QueryClientReceiver: deliver message
  QueryClientReceiver->>QueryClientReceiver: if state present -> build/update cache
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • TkDodo

Poem

🐰 I hop where states are sent and found,

I seed a cache then bound and round.
Indices count, lengths stretch and shrink,
Status reads wake queries in a blink.
Hooray — the broadcast made caches link!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description is minimal and does not follow the provided template structure with 'Changes' and 'Release Impact' sections, making it difficult to assess completeness. Expand the description to follow the template format: add a 'Changes' section with detailed motivation and a 'Release Impact' section confirming whether a changeset was generated.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main fix: preserving array length updates in createRawRef, which directly addresses the primary change in the svelte-query package.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/svelte-query/src/containers.svelte.ts (1)

83-96: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Fix deleteProperty array truncation when deleting multiple indices

In packages/svelte-query/src/containers.svelte.ts, deleteProperty() decrements target.length-- for every numeric index delete. update() then removes stale indices by doing delete out[key] for each key in keysToRemove; for arrays these keys are processed in ascending index order, so deleting multiple indices truncates the current tail each time. The provided repro ([1,2,3,4] -> [1]) results in length: 2 (with remaining keys [ '0' ]) instead of length: 1, proving the proxy ends with the wrong array length.

Existing tests for createRawRef only cover shrinking arrays step-by-step by a single trailing decrement, so the multi-element shrink case is uncovered.

The repro in the comment already demonstrates the bug in code matching this implementation; any createQueries update where the queries array length drops by more than one element will go through the same createRawRef.update() deletion path.

Want me to draft a deleteProperty fix that recomputes length from the remaining visible indices instead of blindly decrementing?

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/svelte-query/src/containers.svelte.ts` around lines 83 - 96, The
deleteProperty trap in createRawRef currently decrements target.length for every
numeric index delete, causing incorrect lengths when multiple indices are
removed; change deleteProperty (and any related logic in createRawRef.update) so
that when deleting an array index (isArrayIndex(prop)) you do NOT blindly do
target.length-- but instead recompute the correct length from the remaining
visible numeric indices: consider target's own keys minus hiddenKeys, find the
maximum numeric index (or -1 if none) and set target.length = maxIndex + 1 (or
0), ensuring hiddenKeys are excluded from the computation; keep the existing
behavior of setting target[prop] = undefined and adding hiddenKeys.add(prop) but
replace the decrement with the recompute step so multi-index removals produce
the correct final length.
🧹 Nitpick comments (1)
packages/svelte-query/src/containers.svelte.ts (1)

34-38: ⚡ Quick win

Harden isArrayIndex against non-canonical numeric strings

Number.isInteger(Number(value)) currently returns true for non-canonical inputs like '1e3', '0x10', and ''/' ' (coerced to 1000, 16, and 0), so the current check can treat them as valid array indices. Use a round-trip String(n) === value check.

♻️ Canonical index detection
-  const isArrayIndex = (value: PropertyKey): value is `${number}` =>
-    typeof value === 'string' &&
-    value !== 'length' &&
-    Number.isInteger(Number(value)) &&
-    Number(value) >= 0
+  const isArrayIndex = (value: PropertyKey): value is `${number}` => {
+    if (typeof value !== 'string') return false
+    const n = Number(value)
+    return Number.isInteger(n) && n >= 0 && String(n) === value
+  }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/svelte-query/src/containers.svelte.ts` around lines 34 - 38, The
isArrayIndex predicate currently treats non-canonical numeric strings as valid
(e.g. "1e3", "0x10", ""), so change its logic to parse Number(value) into a
variable (e.g., const n = Number(value)) and then require Number.isInteger(n) &&
n >= 0 && String(n) === value (and retain the typeof value === 'string' && value
!== 'length' checks); update the isArrayIndex implementation to use that
round-trip String(n) === value equality to ensure only canonical decimal integer
strings are accepted.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@packages/svelte-query/src/containers.svelte.ts`:
- Around line 83-96: The deleteProperty trap in createRawRef currently
decrements target.length for every numeric index delete, causing incorrect
lengths when multiple indices are removed; change deleteProperty (and any
related logic in createRawRef.update) so that when deleting an array index
(isArrayIndex(prop)) you do NOT blindly do target.length-- but instead recompute
the correct length from the remaining visible numeric indices: consider target's
own keys minus hiddenKeys, find the maximum numeric index (or -1 if none) and
set target.length = maxIndex + 1 (or 0), ensuring hiddenKeys are excluded from
the computation; keep the existing behavior of setting target[prop] = undefined
and adding hiddenKeys.add(prop) but replace the decrement with the recompute
step so multi-index removals produce the correct final length.

---

Nitpick comments:
In `@packages/svelte-query/src/containers.svelte.ts`:
- Around line 34-38: The isArrayIndex predicate currently treats non-canonical
numeric strings as valid (e.g. "1e3", "0x10", ""), so change its logic to parse
Number(value) into a variable (e.g., const n = Number(value)) and then require
Number.isInteger(n) && n >= 0 && String(n) === value (and retain the typeof
value === 'string' && value !== 'length' checks); update the isArrayIndex
implementation to use that round-trip String(n) === value equality to ensure
only canonical decimal integer strings are accepted.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c8b0cd51-7cbb-4e46-8beb-9dfebd1e63fb

📥 Commits

Reviewing files that changed from the base of the PR and between 7fa2781 and b896d79.

📒 Files selected for processing (5)
  • packages/query-broadcast-client-experimental/src/__tests__/index.test.ts
  • packages/query-broadcast-client-experimental/src/index.ts
  • packages/svelte-query/src/containers.svelte.ts
  • packages/svelte-query/tests/containers.svelte.test.ts
  • packages/svelte-query/tests/createQueries/createQueries.svelte.test.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant