Skip to content

Conversation

@seefeldb
Copy link
Contributor

@seefeldb seefeldb commented Oct 15, 2025

This change ensures that when writing arrays to cells or pushing to array cells, all objects are given IDs so they can be stored as separate documents with links. This applies to both explicitly written arrays and default values from schemas.

Changes to cell.ts:

  1. Modified the set method to call addIDIfNeeded on each element when writing an array, ensuring all objects get IDs before being processed by diffAndUpdate.

  2. Enhanced the push method to:

    • Process default values from schemas using processDefaultValue to ensure they're properly materialized with IDs
    • Apply addIDIfNeeded to all elements (both existing defaults and newly pushed values) to ensure consistent ID assignment
  3. Improved the update method's schema validation to:

    • Use resolveSchema to properly handle schema references
    • Check for undefined schemas (which allow objects)
    • Consolidate the schema validation logic to determine if objects are allowed
  4. Added new addIDIfNeeded helper function that:

    • Checks if a value is an object without an ID
    • Generates a new ID from the frame's counter if needed
    • Preserves existing IDs when present

New tests in cell.test.ts:

  • "set operations with arrays" suite:

    • Tests that objects written as arrays each get their own document ID
    • Verifies that existing IDs are preserved during array writes
    • Uses asSchema with asCell: true to read back as cells and verify each element has a distinct document ID
  • "push operations with default values" suite:

    • Tests that default values from schemas are properly materialized with IDs
    • Verifies all objects (defaults + pushed) get unique IDs
    • Tests push operations both with and without schema defaults

These changes ensure that array operations consistently create separate documents for each object, maintaining proper referential structure in the storage layer.


Summary by cubic

Ensures array writes and pushes create separate docs for each object by auto-assigning IDs, including for schema defaults. Addresses Linear CT-982 by fixing default materialization and creating cells on array writes.

  • Bug Fixes
    • set: runs addIDIfNeeded on array elements before diffAndUpdate.
    • push: initializes empty arrays via resolveSchema + processDefaultValue, then assigns IDs to defaults and new items before appending.
    • update: uses resolveSchema and a unified “objects allowed” check; treats undefined schema as permitting objects.
    • Adds addIDIfNeeded helper and exports processDefaultValue to support consistent ID assignment.

@seefeldb seefeldb requested review from ellyxir and ubik2 October 15, 2025 23:57
@linear
Copy link

linear bot commented Oct 15, 2025

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 3 files

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 1 file

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 1 file

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 1 file

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 2 files

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

Reviewed changes from recent commits (found 1 issue).

1 issue found across 3 files

Prompt for AI agents (all 1 issues)

Understand the root cause of the following 1 issues and fix them.


<file name="packages/runner/src/query-result-proxy.ts">

<violation number="1" location="packages/runner/src/query-result-proxy.ts:126">
The new Symbol.iterator handler never reads the array length through the runtime transaction, so iterating an empty array records no dependency; reactive consumers will miss later additions. Please mirror the other array read paths by logging the length before iterating.</violation>
</file>

React with 👍 or 👎 to teach cubic. Mention @cubic-dev-ai to give feedback, ask questions, or re-run the review.

return () => createCell(runtime, link, tx, true);
} else if (prop === toOpaqueRef) {
return () => makeOpaqueRef(link);
} else if (prop === Symbol.iterator && Array.isArray(target)) {
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Oct 16, 2025

Choose a reason for hiding this comment

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

The new Symbol.iterator handler never reads the array length through the runtime transaction, so iterating an empty array records no dependency; reactive consumers will miss later additions. Please mirror the other array read paths by logging the length before iterating.

Prompt for AI agents
Address the following comment on packages/runner/src/query-result-proxy.ts at line 126:

<comment>The new Symbol.iterator handler never reads the array length through the runtime transaction, so iterating an empty array records no dependency; reactive consumers will miss later additions. Please mirror the other array read paths by logging the length before iterating.</comment>

<file context>
@@ -123,6 +123,26 @@ export function createQueryResultProxy&lt;T&gt;(
           return () =&gt; createCell(runtime, link, tx, true);
         } else if (prop === toOpaqueRef) {
           return () =&gt; makeOpaqueRef(link);
+        } else if (prop === Symbol.iterator &amp;&amp; Array.isArray(target)) {
+          return function () {
+            let index = 0;
</file context>

✅ Addressed in 842f1da

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 1 file

This change ensures that when writing arrays to cells or pushing to array
cells, all objects are given IDs so they can be stored as separate documents
with links. This applies to both explicitly written arrays and default values
from schemas.

Changes to cell.ts:

1. Modified the `set` method to call `addIDIfNeeded` on each element when
   writing an array, ensuring all objects get IDs before being processed by
   `diffAndUpdate`.

2. Enhanced the `push` method to:
   - Process default values from schemas using `processDefaultValue` to ensure
     they're properly materialized with IDs
   - Apply `addIDIfNeeded` to all elements (both existing defaults and newly
     pushed values) to ensure consistent ID assignment

3. Improved the `update` method's schema validation to:
   - Use `resolveSchema` to properly handle schema references
   - Check for undefined schemas (which allow objects)
   - Consolidate the schema validation logic to determine if objects are
     allowed

4. Added new `addIDIfNeeded` helper function that:
   - Checks if a value is an object without an ID
   - Generates a new ID from the frame's counter if needed
   - Preserves existing IDs when present

New tests in cell.test.ts:

- "set operations with arrays" suite:
  - Tests that objects written as arrays each get their own document ID
  - Verifies that existing IDs are preserved during array writes
  - Uses `asSchema` with `asCell: true` to read back as cells and verify
    each element has a distinct document ID

- "push operations with default values" suite:
  - Tests that default values from schemas are properly materialized with IDs
  - Verifies all objects (defaults + pushed) get unique IDs
  - Tests push operations both with and without schema defaults

These changes ensure that array operations consistently create separate
documents for each object, maintaining proper referential structure in the
storage layer.
Add custom Symbol.iterator implementation for array query result proxies
to support spreading and for...of iteration. When iterating over an array
proxy, each element is now wrapped in its own query result proxy,
maintaining reactivity and cell references throughout the iteration.

This enables patterns like:
- const spread = [...proxy.items]
- for (const item of proxy.items) { ... }

Each iterated element maintains its query result proxy wrapper, allowing
access to toCell() and preserving the link to the underlying cell data.
…xies

Add comprehensive tests verifying Symbol.iterator behavior for array
query result proxies:

- for...of iteration with object elements
- Spread operator with object elements
- Nested array spreading with proper proxy preservation
- Arrays containing cell references (links to other cells)

Tests confirm that iteration and spreading maintain query result proxy
wrappers for each element, allowing access to toCell() and preserving
reactivity throughout iteration. The cell references test specifically
validates that link resolution works correctly when iterating over arrays
of cell links.
otherwise Cell.set turns this back into cell references and this can create loops

(fwiw, we might want to turn this into a structure where each node is its own document with its own id, in which case we'd actually want this behavior)
@seefeldb seefeldb force-pushed the berni/ct-982-fix-defaults-and-create-cells-on-array-writes branch from 766ed5f to 42b9ec0 Compare October 16, 2025 23:54
@seefeldb seefeldb merged commit d060d41 into main Oct 17, 2025
8 checks passed
@seefeldb seefeldb deleted the berni/ct-982-fix-defaults-and-create-cells-on-array-writes branch October 17, 2025 00:14
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.

2 participants