Skip to content

Conversation

@seefeldb
Copy link
Contributor

@seefeldb seefeldb commented Oct 24, 2025

This fixes a bug where synthetic identifiers created by ClosureTransformer were leaking into derive calls in outer scopes, causing ReferenceError at runtime.

The fix adds heuristic filtering in filterRelevantDataFlows() to detect when synthetic identifiers (those without symbol information) are being incorrectly included in outer-scope expressions. The heuristic:

  • Identifies synthetic vs non-synthetic dataflows by checking for symbol info
  • When mixing both: if non-synthetic flows all have outer-scope symbols (2+), we're at outer scope → filter synthetic ones
  • Otherwise we're inside a callback with captures → keep everything

This approach is robust as it relies on symbol presence rather than hardcoded identifier names, so it won't break if user code happens to use variables named "element", "index", etc.

Also adds test case for nested map within conditional to prevent regression and updates expected output for map-nested-conditional to correctly derive element properties.

🤖 Generated with Claude Code


Summary by cubic

Fixes a runtime ReferenceError caused by synthetic identifiers leaking into outer-scope derive calls in nested map scenarios. Adds a heuristic to filter these synthetic params when analyzing outer scope.

  • Bug Fixes
    • Filters synthetic identifiers (no symbol info) in filterRelevantDataFlows when mixed with outer-scope flows; keeps them when inside callbacks.
    • Prevents “element is not defined” in derive within map cases; addresses Linear CT-1003.
    • Adds a test for map nested in a conditional and updates expected output to derive element.name correctly.

This fixes a bug where synthetic identifiers created by ClosureTransformer
were leaking into derive calls in outer scopes, causing ReferenceError at
runtime.

The fix adds heuristic filtering in filterRelevantDataFlows() to detect when
synthetic identifiers (those without symbol information) are being incorrectly
included in outer-scope expressions. The heuristic:

- Identifies synthetic vs non-synthetic dataflows by checking for symbol info
- When mixing both: if non-synthetic flows all have outer-scope symbols (2+),
  we're at outer scope → filter synthetic ones
- Otherwise we're inside a callback with captures → keep everything

This approach is robust as it relies on symbol presence rather than hardcoded
identifier names, so it won't break if user code happens to use variables
named "element", "index", etc.

Also adds test case for nested map within conditional to prevent regression
and updates expected output for map-nested-conditional to correctly derive
element properties.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@seefeldb seefeldb requested a review from mathpirate October 24, 2025 00:34
@linear
Copy link

linear bot commented Oct 24, 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.

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/ts-transformers/src/transformers/opaque-ref/helpers.ts">

<violation number="1" location="packages/ts-transformers/src/transformers/opaque-ref/helpers.ts:152">
This heuristic treats callbacks that capture multiple outer variables as outer-scope expressions, so it drops the synthetic map parameter data flows; when a callback references two captured identifiers plus the synthetic parameter, the synthetic flow is removed and the derive call breaks.</violation>
</file>

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

seefeldb and others added 2 commits October 23, 2025 17:53
…e captures

The heuristic for filtering synthetic dataflows was too aggressive. It
treated callbacks that capture 2+ outer variables as outer-scope
expressions, which caused it to drop synthetic map parameter dataflows.
This broke derive calls when a callback referenced multiple captured
identifiers plus the synthetic parameter.

Example that was breaking:
```tsx
items.map((item, index) => (
  <div>
    {item.name} - {cell1.value} - {cell2.value} - {index}
  </div>
))
```

The heuristic saw 2 outer-scope symbols (cell1, cell2) and incorrectly
filtered out the synthetic parameters (item, index).

Fix:
- Check if dataflows belong to a map callback scope before applying
  the "2+ outer captures" heuristic
- If in a map callback scope, keep all dataflows (synthetic and captures)
- Only filter out ignored parameters
- This allows callbacks to legitimately capture multiple outer variables
  while still using synthetic map parameters

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@seefeldb seefeldb merged commit 321a5e3 into main Oct 24, 2025
8 checks passed
@seefeldb seefeldb deleted the berni/ct-1003-derive-in-map-in-derive-gets-element-not-defined branch October 24, 2025 01:33
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