Skip to content

fix: defer Spreadsheet.selectCellRange until sheet widget layout is ready (#9381) (CP: 25.1)#9486

Merged
DiegoCardoso merged 1 commit into
25.1from
fix/spreadsheet-selection-obf-safe-25.1
Jun 11, 2026
Merged

fix: defer Spreadsheet.selectCellRange until sheet widget layout is ready (#9381) (CP: 25.1)#9486
DiegoCardoso merged 1 commit into
25.1from
fix/spreadsheet-selection-obf-safe-25.1

Conversation

@DiegoCardoso

Copy link
Copy Markdown
Contributor

This PR cherry-picks changes from the original PR #9381 to branch 25.1.


Follow-up to #9333. When a Spreadsheet inside a closed Dialog is opened, Flow
flushes the property writes and the setSelectedCellAndRange RPC in the same
task. The api receives the call before the deferred init scheduled in
SheetWidget.resetFromModel has run — so SheetWidget.getRowHeight reads an
uninitialized definedRowHeights and throws

Uncaught TypeError: Cannot read properties of undefined (reading 'length')

That throw drops the selection and trips the *_noErrors/*_noConsoleErrors
console-log assertions.

#9333's connector-side guard masked this by probing definedRowHeights
through the api's private GWT fields — names that only survive
-Dgwt.style=pretty (local/dev). CI compiles the GWT client with
-Dgwt.style=OBF, where those private names are renamed and api.spreadsheetWidget
is undefined. The guard itself then threw, producing the same SEVERE log and
the same ~20 spreadsheet IT failures on the cherry-pick PRs.

Move the layout-readiness handling into the widget that owns the operation:

  • SheetWidget.isLoaded() (package-private) — exposes the already-existing
    loaded flag that flips at the end of resetFromModel's deferred command.
  • SpreadsheetWidget.selectCellRange — if !sheetWidget.isLoaded(), store the
    latest args and Scheduler.scheduleDeferred(this::applyPendingSelectCellRange).
    The deferred re-checks, applies, or re-schedules. Latest-wins (rapid successive
    calls collapse to the final selection). Bounded at 100 hops as a safety net;
    in the typical case the layout init has already been scheduled before us, so
    GWT's FIFO scheduler resolves us in 0–1 hops.
  • vaadin-spreadsheet.jssetSelectedCellAndRange goes back to a one-liner
    (this._flush(); this.api.setSelectedCellAndRange(...args)). No try/catch,
    no pending state, no constants.

Only selectCellRange is deferred — it's the only RPC that touches row/column
metrics. Other RPCs (cellsUpdated, popup ops, etc.) don't need this and
didn't fail in the original CI runs.

Reproduce locally by compiling the client with -Dgwt.style=OBF (matching CI)
and running the merged ITs in production mode:

mvn clean install -DskipTests -Dgwt.style=OBF \
  -pl vaadin-spreadsheet-flow-parent/vaadin-spreadsheet-flow-client,vaadin-spreadsheet-flow-parent/vaadin-spreadsheet-flow
node scripts/mergeITs.js spreadsheet
mvn verify -Drun-it -pl integration-tests -Dvaadin.productionMode=true \
  -Dit.test='NavigationIT,SpreadsheetDialogIT' -DskipUnitTests
  • With this PR → NavigationIT 26/0, SpreadsheetDialogIT 1/0.
  • Reverting only the GWT-side change → SpreadsheetDialogIT fails with the
    underlying Cannot read properties of undefined (reading 'length') in
    FlowClient-…js — the actual definedRowHeights NPE.

Follow-up to #9333.


🤖 Generated with Claude Code

…eady (#9381) (CP: 25.1)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@DiegoCardoso DiegoCardoso requested a review from vursen June 10, 2026 13:38
@DiegoCardoso DiegoCardoso enabled auto-merge (squash) June 10, 2026 13:42
@sonarqubecloud

Copy link
Copy Markdown

@DiegoCardoso DiegoCardoso merged commit e07d3e3 into 25.1 Jun 11, 2026
9 checks passed
@DiegoCardoso DiegoCardoso deleted the fix/spreadsheet-selection-obf-safe-25.1 branch June 11, 2026 06:03
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