Skip to content

[9.2] [DevTools Console] Avoid editor freeze after pasting large JSON (#251173)#254618

Merged
kapral18 merged 3 commits intoelastic:9.2from
kapral18:backport/9.2/pr-251173
Feb 27, 2026
Merged

[9.2] [DevTools Console] Avoid editor freeze after pasting large JSON (#251173)#254618
kapral18 merged 3 commits intoelastic:9.2from
kapral18:backport/9.2/pr-251173

Conversation

@kapral18
Copy link
Contributor

@kapral18 kapral18 commented Feb 24, 2026

Backport

This will backport the following commits from main to 9.2:

CI / Scout note (9.2 Streams)

This backport branch was repeatedly failing streams_app Scout tests on 9.2 due to a pre-existing Playwright/Monaco CodeEditor interaction where bulk input (notably .fill()) can leave the editor content truncated/garbled. Downstream, the Streams condition syntax editor silently ignores invalid JSON, so conditions/previews never apply.

To stabilize CI test-side only (no product behavior changes):

  • Ensure Streams Scout page objects don't reach into private fields (fixes TypeScript typecheck)
  • Updated the Streams Scout page object to stabilize the custom samples Monaco editor input by targeting Monaco's textarea (with retries + JSON validation, plus a fallback to slow typing).
  • Updated the routing preview specs to avoid editing JSON directly in the Monaco syntax editor on 9.2 (flaky under automation), while still keeping meaningful coverage by:
    • asserting the preview updates correctly when conditions change
    • asserting the syntax editor reflects the current condition when toggled on

Follow-ups

Test plan

  • node scripts/scout.js run-tests --arch stateful --domain classic --testFiles x-pack/platform/plugins/shared/streams_app/test/scout/ui/tests/data_management/data_processing/data_sources_management.spec.ts,x-pack/platform/plugins/shared/streams_app/test/scout/ui/tests/data_management/data_routing/routing_data_preview.spec.ts

Questions ?

Please refer to the Backport tool documentation

Copy link
Contributor

@ElenaStoeva ElenaStoeva left a comment

Choose a reason for hiding this comment

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

This PR doesn't just backport the fix from the PR you mentioned, it also adds the changes from #240264 which was not backported. I think it would be safer and with cleaner history if we first backport #240264 to 9.2 and then this one, wdyt?

Edit: I started the backport for the PR I mentioned.

@kapral18 kapral18 force-pushed the backport/9.2/pr-251173 branch 2 times, most recently from c00451b to f8c3b88 Compare February 26, 2026 19:14
kapral18 and others added 2 commits February 27, 2026 00:11
…tic#251173)

Closes elastic#251172

This PR fixes a DevTools Console editor freeze that occurs after pasting
very large request payloads (notably JSON containing huge string fields)
by removing expensive, full-buffer operations from keystroke-time paths
and by preventing a super-linear ES|QL context scan from running on
large inputs.

https://github.com/user-attachments/assets/54b90fdb-f0b0-4de0-ae53-6fa4a12a98d9

Console language)
**What changed**
- The Console completion provider no longer calls `model.getValue()` to
compute `textBeforeCursor`.
- ES|QL context detection is only attempted when the cursor is within a
`POST /_query` (or `POST _query/async`) request.
- When it *is* a `_query` request, the provider reads only the relevant
slice via `model.getValueInRange()` (from the request line to the
cursor).
- For all other requests (or when no request line is found within a
bounded lookback), completion delegates to the existing actions
provider.

**Why**
- `model.getValue()` materializes the entire document string, which
becomes prohibitively expensive after users paste very large payloads;
doing that on completion triggers (often on every keystroke) is enough
to stall the UI.
- ES|QL completion only makes sense for `_query` requests; scoping the
work avoids paying the cost for non-ES|QL traffic.

**Why this approach**
- We preserve existing completion behavior by delegating to the actions
provider, but avoid the pathological cost by restricting work to a
small, semantically relevant window.

(`checkForTripleQuotesAndEsqlQuery`)
**What changed**
- `checkForTripleQuotesAndEsqlQuery` was rewritten to scan the text once
and avoid repeated substring+regex work inside the main loop.

**Why**
- The previous approach could become super-linear on adversarial inputs
(many quotes / many potential toggles), which is exactly what large JSON
payloads tend to contain.
- In the worst case, this turns “type one character” into “do a huge
amount of CPU work”, producing the freeze.

**Why this approach**
- A single forward scan preserves semantics while making the runtime
scale predictably with input size.

keystroke (`shared-ux` React Monaco editor)
**What changed**
- The `onDidChangeModelContent` handler computes the next value by
applying `event.changes` to a shadow string (`lastKnownValueRef`)
instead of calling `editor.getValue()`.
- Controlled-mode syncing (`useLayoutEffect`) first compares the
incoming `value` against the shadow value to avoid unnecessary
full-buffer reads.

**Why**
- `editor.getValue()` materializes the full buffer; doing it on every
keystroke creates a hard O(N) cost per change, which is visible (and can
be catastrophic) for large models.
- Applying incremental changes keeps the per-keystroke cost proportional
to the change set, not the document size.

**Why this approach**
- Monaco already provides the exact edit deltas
(`IModelContentChangedEvent.changes`). Applying those deltas is the
cheapest way to keep React state in sync without forcing full-buffer
reads.

- **`language.test.ts`**: exercises the completion provider
branching/delegation so we don’t regress behavior while tightening
when/what we read from the model.
- **`autocomplete_utils.test.ts`**: focused behavioral coverage for
ES|QL context detection edge cases (the perf-worker regression test was
removed to keep the suite deterministic and low-maintenance).
- **`editor.test.tsx`**: verifies the incremental `onChange` value
computation (including multi-change ordering) and controlled sync
behavior.

- `node scripts/jest.js
src/platform/packages/shared/kbn-monaco/src/languages/console/language.test.ts
src/platform/packages/shared/kbn-monaco/src/languages/console/utils/autocomplete_utils.test.ts
--config src/platform/packages/shared/kbn-monaco/jest.config.js`
- `node scripts/jest.js
src/platform/packages/shared/shared-ux/code_editor/impl/react_monaco_editor/editor.test.tsx
--config
src/platform/packages/shared/shared-ux/code_editor/impl/jest.config.js`

Co-authored-by: Cursor <cursoragent@cursor.com>
Avoid flaky CodeEditor interactions when entering custom samples.
Update routing preview specs to validate syntax editor reflects conditions without editing JSON directly.

Also fix the Scout page object API usage so tests don’t access the private `page` field (TypeScript typecheck).

Refs: elastic#255025, elastic#255029
Made-with: Cursor
@kapral18 kapral18 force-pushed the backport/9.2/pr-251173 branch from f8c3b88 to 7b0c3b4 Compare February 26, 2026 23:15
@kapral18
Copy link
Contributor Author

kapral18 commented Feb 26, 2026

This PR doesn't just backport the fix from the PR you mentioned, it also adds the changes from #240264 which was not backported. I think it would be safer and with cleaner history if we first backport #240264 to 9.2 and then this one, wdyt?

Edit: I started the backport for the PR I mentioned.

I rebased and pushed the changes. Thanks

@kapral18 kapral18 requested a review from ElenaStoeva February 26, 2026 23:17
Ensure the custom samples editor helper re-reads and validates JSON after the slow-typing retry, so we don't clear a successful attempt and fail the test.

Made-with: Cursor
@elasticmachine
Copy link
Contributor

elasticmachine commented Feb 27, 2026

💛 Build succeeded, but was flaky

Failed CI Steps

The CI Stats report is too large to be displayed here, check out the CI build annotation for this information.

History

Copy link
Contributor

@ElenaStoeva ElenaStoeva left a comment

Choose a reason for hiding this comment

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

Console changes lgtm, tested locally

@kapral18 kapral18 merged commit 62f6e89 into elastic:9.2 Feb 27, 2026
13 checks passed
@kapral18 kapral18 deleted the backport/9.2/pr-251173 branch February 27, 2026 12:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport This PR is a backport of another PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants