Single-line inputs strip pasted line breaks and never paint a second line#140
Merged
Conversation
- Sanitize derived edits for input/text_field/search_field/combobox at the keyboard choke point, BEFORE the stamp, so the retained editor, the app's on_input mirror, and replay all hear identical stripped bytes (HTML value-sanitization rule; covers shortcut and context-menu paste, typed/automation text_input, and IME composition). - Suppress inserts that strip to nothing so pasting bare newlines inserts nothing and a host-stuffed Enter payload never deletes a live selection; the app-side fallback derivation applies the same rule so both derivations agree. - Sanitize direct runtime editCanvasWidgetText writes through the same shared rule. Co-authored-by: IFTC-XLKJ <151902522+IFTC-XLKJ@users.noreply.github.com>
- Lay out, measure, and paint a single-line field's value with \n/\r presented as spaces (byte-for-byte, so caret/selection/hit-test offsets address the raw value) — one line on the GPU engine, the reference renderer, and packet hosts alike; copy, semantics, and automation still read the raw model value. - Force the content-rect clip whenever the raw value holds a line break, the independent guard that keeps even a presentation-scratch fallback inside the field's rounded border. - Persist presented bytes into a render-walk pool (the chart-label scratch precedent) so emitted commands survive until the runtime copies the display list. Co-authored-by: IFTC-XLKJ <151902522+IFTC-XLKJ@users.noreply.github.com>
…ries - Paste, automation set_text, IME composition, and the Tree fallback derivation all pin stripped inserts (textarea keeps its breaks); bare-newline pastes insert nothing and Enter stays not-an-insert even with a host-stuffed newline payload. - Model-set values holding a newline pin one presented line under a forced clip in both render walks and through the runtime display list, with semantics still reporting the raw value. - The session reference recording now copies a textarea's two lines and pastes them into the search field, pinning that a recorded multi-line paste replays to the identical sanitized value and fingerprint. Co-authored-by: IFTC-XLKJ <151902522+IFTC-XLKJ@users.noreply.github.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
- clampCanvasWidgetPasteText (shared by the cmd+V shortcut and the context-menu Paste) now strips single-line targets' line breaks BEFORE measuring against remaining capacity, so a near-limit paste never spends free bytes on breaks the seam strips anyway ("a\nbc" into 3 free bytes lands "abc", not "ab"), and a paste that sanitizes to nothing is not reported truncated.
- Boundary tests pin both paste paths at exactly three free bytes: retained editor and the app's stamped edit hear the identical whole sanitized suffix with no false truncation flag.
- The builder contract (pinned at Builder.allocPathElements) lets a display list accumulate across several emit calls or be held while another builder emits; presented single-line values and formatted chart labels lived in thread-local pools RESET at each emit entry, so a second emit overwrote text an earlier list still sliced. - Builder now owns the bytes beside its path-element store: allocChartLabelBytes keeps the chart label budget's loud ChartLabelBytesFull, and allocTextBytes holds presented values under a per-view-text-budget-sized store (lockstep-tested against max_canvas_text_bytes_per_view) with the raw-value fallback intact; both thread-local pools and the per-emit resets are gone. - Regression tests emit twice — into another builder and accumulated into one — and pin both lists' draw_text bytes intact for presented fields and tick labels; both fail against the pool-reset design.
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes the reported issue: pasting content containing line breaks into a single-line input displayed multiple lines — with the extra line painting outside the field's border.
Two independent layers:
\r/\nfrom inserted text per the WHATWG value-sanitization rule for single-line inputs (Chromium's paste behavior; documented with citations at the sanitize site). The rule sits in the v0.5.2 edit-derivation choke point with the order derive → sanitize → stamp → apply, so the retained editor, the core'son_inputmirror (both tiers), and replay all hear byte-identical bytes — covering clipboard paste, context-menu paste, typed/automationtext_input, IME composition (sanitized at preview so a commit can never land a break), and direct runtime writes, with the app-side fallback derivation applying the identical rule. An insert that strips to nothing is suppressed (pasting bare newlines never eats a live selection), and Enter-in-input is pinned as not-an-insert even against hosts that stuff a newline into the key event. Textareas are untouched.\n/\ras spaces byte-for-byte, so caret/selection/composition/hit-test offsets address the raw value unchanged while layout produces exactly one line on the GPU engine, the reference renderer, and packet hosts; the content-rect clip is additionally forced whenever the raw value holds a break. Copy, semantics, and automation still report the raw value.Replay needed no journal changes — sanitization is deterministic derivation over the recorded raw events, pinned by extending the reference recording with a textarea→search-field multi-line paste.
Tests across events/ui/clipboard/text/session suites, all sabotage-verified (disabling the rule fails 10+ tests; disabling presentation or the forced clip fails the containment pins). Full battery, validate, tooling, examples, ts-core e2e all green.