Skip to content

fix: init Spreadsheet api on connect to avoid undefined api in Dialog (#9333) (CP: 25.0)#9367

Merged
DiegoCardoso merged 3 commits into
25.0from
cherry-pick-9333-to-25.0-1779782882850
May 27, 2026
Merged

fix: init Spreadsheet api on connect to avoid undefined api in Dialog (#9333) (CP: 25.0)#9367
DiegoCardoso merged 3 commits into
25.0from
cherry-pick-9333-to-25.0-1779782882850

Conversation

@vaadin-bot

Copy link
Copy Markdown
Collaborator

This PR cherry-picks changes from the original PR #9333 to branch 25.0.

Original PR description

When a Spreadsheet is attached inside a closed Dialog and the Dialog later opens, Flow flushes its buffered property writes and callJsFunction calls in the same task. The connector created its api lazily inside Lit's microtask-scheduled updated(), so the RPC methods ran first — eleven of them threw Cannot read properties of undefined, and the initial selection was silently dropped.

Spreadsheet spreadsheet = new Spreadsheet();
spreadsheet.setSelectionRange(2, 7, 7, 10);
Dialog dialog = new Dialog();
dialog.add(spreadsheet);
dialog.open(); // console floods with errors, selection not applied

The api is now created eagerly in connectedCallback (Lit 3 sets up renderRoot in super.connectedCallback()), and each RPC method calls performUpdate() at the top so pending property writes have propagated to the api before it's used.

One symptom remains structurally async: GWT schedules the initial relayout() via setTimeout(1ms), so the sheet widget's layout state isn't yet populated when the first setSelectedCellAndRange arrives. That call would dereference definedRowHeights and throw inside \$scrollAreaIntoView. Flow reissues setSelectedCellAndRange after the spreadsheet has fully attached, so the connector skips the first call when the layout state isn't ready and lets the second one apply the selection.


🤖 Generated with Claude Code

…#9333)

When a Spreadsheet is attached inside a closed Dialog and the Dialog
later opens, Flow flushes its buffered property writes and
`callJsFunction` calls in the same task. The connector created its api
lazily inside Lit's microtask-scheduled `updated()`, so the RPC methods
ran first — eleven of them threw `Cannot read properties of undefined`,
and the initial selection was silently dropped.

```java
Spreadsheet spreadsheet = new Spreadsheet();
spreadsheet.setSelectionRange(2, 7, 7, 10);
Dialog dialog = new Dialog();
dialog.add(spreadsheet);
dialog.open(); // console floods with errors, selection not applied
```

The api is now created eagerly in `connectedCallback` (Lit 3 sets up
`renderRoot` in `super.connectedCallback()`), and each RPC method calls
`performUpdate()` at the top so pending property writes have propagated
to the api before it's used.

One symptom remains structurally async: GWT schedules the initial
`relayout()` via `setTimeout(1ms)`, so the sheet widget's layout state
isn't yet populated when the first `setSelectedCellAndRange` arrives.
That call would dereference `definedRowHeights` and throw inside
`\$scrollAreaIntoView`. Flow reissues `setSelectedCellAndRange` after
the spreadsheet has fully attached, so the connector skips the first
call when the layout state isn't ready and lets the second one apply the
selection.

---

🤖 Generated with Claude Code

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@DiegoCardoso
DiegoCardoso enabled auto-merge (squash) May 26, 2026 08:20
<!-- Why -->
Follow-up to #9333. The connector's `setSelectedCellAndRange` silently
dropped calls when the sheet widget's `definedRowHeights` wasn't yet
populated, on the assumption that Flow would reissue the call. That
assumption only holds for the reload cycle path (`initialSheetSelection`
set on the server, then `onSheetScroll` from the client triggering
`reloadCurrentSelection`). For any other path — most notably the
selection RPC sent when the user types a range into the address field —
there is no reissue, so a call that loses the race against GWT's
deferred initial relayout is lost permanently.

This caused the cherry-pick PRs (#9365, #9366, #9367) to consistently
fail 20 selection-related tests (`NavigationIT`, `NamedRangeIT`,
`ChartsIT`, `SheetTabSheetIT`, `PreserveOnRefreshIT`, and the new
`SpreadsheetDialogIT`). The original PR happened to pass on main's CI
agent timing, but the failure is deterministic on the cherry-pick
branches' GWT 2.9 / older-Flow-SNAPSHOT environment.

<!-- Changes -->
Queue the latest call as `_pendingSelection` and poll
`definedRowHeights` every 10 ms until it's set or the element is
disconnected. Rapid successive calls collapse to the final selection
(the array is overwritten, only one retry loop runs at a time).

Follow-up to #9333.

---

🤖 Generated with Claude Code

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
DiegoCardoso added a commit that referenced this pull request May 26, 2026
<!-- Why -->
Follow-up to #9333. The connector's `setSelectedCellAndRange` silently
dropped calls when the sheet widget's `definedRowHeights` wasn't yet
populated, on the assumption that Flow would reissue the call. That
assumption only holds for the reload cycle path (`initialSheetSelection`
set on the server, then `onSheetScroll` from the client triggering
`reloadCurrentSelection`). For any other path — most notably the
selection RPC sent when the user types a range into the address field —
there is no reissue, so a call that loses the race against GWT's
deferred initial relayout is lost permanently.

This caused the cherry-pick PRs (#9365, #9366, #9367) to consistently
fail 20 selection-related tests (`NavigationIT`, `NamedRangeIT`,
`ChartsIT`, `SheetTabSheetIT`, `PreserveOnRefreshIT`, and the new
`SpreadsheetDialogIT`). The original PR happened to pass on main's CI
agent timing, but the failure is deterministic on the cherry-pick
branches' GWT 2.9 / older-Flow-SNAPSHOT environment.

<!-- Changes -->
Queue the latest call as `_pendingSelection` and poll
`definedRowHeights` every 10 ms until it's set or the element is
disconnected. Rapid successive calls collapse to the final selection
(the array is overwritten, only one retry loop runs at a time).

Follow-up to #9333.

---

🤖 Generated with Claude Code

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
DiegoCardoso added a commit that referenced this pull request May 26, 2026
<!-- Why -->
Follow-up to #9333. The connector's `setSelectedCellAndRange` silently
dropped calls when the sheet widget's `definedRowHeights` wasn't yet
populated, on the assumption that Flow would reissue the call. That
assumption only holds for the reload cycle path (`initialSheetSelection`
set on the server, then `onSheetScroll` from the client triggering
`reloadCurrentSelection`). For any other path — most notably the
selection RPC sent when the user types a range into the address field —
there is no reissue, so a call that loses the race against GWT's
deferred initial relayout is lost permanently.

This caused the cherry-pick PRs (#9365, #9366, #9367) to consistently
fail 20 selection-related tests (`NavigationIT`, `NamedRangeIT`,
`ChartsIT`, `SheetTabSheetIT`, `PreserveOnRefreshIT`, and the new
`SpreadsheetDialogIT`). The original PR happened to pass on main's CI
agent timing, but the failure is deterministic on the cherry-pick
branches' GWT 2.9 / older-Flow-SNAPSHOT environment.

<!-- Changes -->
Queue the latest call as `_pendingSelection` and poll
`definedRowHeights` every 10 ms until it's set or the element is
disconnected. Rapid successive calls collapse to the final selection
(the array is overwritten, only one retry loop runs at a time).

Follow-up to #9333.

---

🤖 Generated with Claude Code

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… internals

#9333 guarded setSelectedCellAndRange by reading
`this.api.spreadsheetWidget.sheetWidget.definedRowHeights`. Those are private
GWT fields: their names survive only in `pretty` GWT output (local/dev), so the
check worked there. CI compiles the client with `-Dgwt.style=OBF`, which
obfuscates the field names, so `this.api.spreadsheetWidget` is undefined and the
guard threw `Cannot read properties of undefined (reading 'sheetWidget')`. That
single throw dropped the selection and tripped the `*_noErrors`/
`*_noConsoleErrors` console-log assertions, producing the ~20 spreadsheet IT
failures seen only on CI for the 24.10/25.0/25.1 cherry-picks (and untouched by
#9373, which threw on the same line).

Drop the private-field probe. The api's `setSelectedCellAndRange` is a public,
@JsType-exported method whose name is stable under obfuscation; call it and, if
the deferred initial relayout hasn't run yet (it throws inside
`$scrollAreaIntoView`), keep the latest selection and retry until it applies.

Reproduced locally by compiling the client with -Dgwt.style=OBF: the old probe
fails NavigationIT, this fix passes.

Follow-up to #9333, #9373.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
30.1% Duplication on New Code (required ≤ 10%)

See analysis details on SonarQube Cloud

@DiegoCardoso
DiegoCardoso merged commit f714eac into 25.0 May 27, 2026
8 of 9 checks passed
@DiegoCardoso
DiegoCardoso deleted the cherry-pick-9333-to-25.0-1779782882850 branch May 27, 2026 20:40
mletenay pushed a commit to mletenay/flow-components that referenced this pull request Jun 5, 2026
…n#9373)

<!-- Why -->
Follow-up to vaadin#9333. The connector's `setSelectedCellAndRange` silently
dropped calls when the sheet widget's `definedRowHeights` wasn't yet
populated, on the assumption that Flow would reissue the call. That
assumption only holds for the reload cycle path (`initialSheetSelection`
set on the server, then `onSheetScroll` from the client triggering
`reloadCurrentSelection`). For any other path — most notably the
selection RPC sent when the user types a range into the address field —
there is no reissue, so a call that loses the race against GWT's
deferred initial relayout is lost permanently.

This caused the cherry-pick PRs (vaadin#9365, vaadin#9366, vaadin#9367) to consistently
fail 20 selection-related tests (`NavigationIT`, `NamedRangeIT`,
`ChartsIT`, `SheetTabSheetIT`, `PreserveOnRefreshIT`, and the new
`SpreadsheetDialogIT`). The original PR happened to pass on main's CI
agent timing, but the failure is deterministic on the cherry-pick
branches' GWT 2.9 / older-Flow-SNAPSHOT environment.

<!-- Changes -->
Queue the latest call as `_pendingSelection` and poll
`definedRowHeights` every 10 ms until it's set or the element is
disconnected. Rapid successive calls collapse to the final selection
(the array is overwritten, only one retry loop runs at a time).

Follow-up to vaadin#9333.

---

🤖 Generated with Claude Code

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vaadin-bot

Copy link
Copy Markdown
Collaborator Author

This ticket/PR has been released with Vaadin 25.0.12.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants