Skip to content

Prevent stale translation responses from overwriting newer selection results #40

Description

@fly1d

Problem

Translation responses are committed unconditionally. A slower older request can therefore overwrite the result, error, or loading state that belongs to a newer selected-text translation.

The selection-only in-flight guard prevents two shortcut captures from overlapping, but it does not serialize an existing manual or document translation with a new global-selection request. Editing, importing, or clearing the source also does not invalidate an older request.

Reproduction

  1. Start translation A and keep its request pending.
  2. Trigger the registered global-selection callback with source B.
  3. Resolve B first and verify that its result appears.
  4. Resolve or reject A afterward.

Current behavior: A replaces B's result or error state while the source still shows B. If A completes first, it can also clear the shared loading state while B remains pending.

Acceptance criteria

  • Assign every translation a monotonic request generation; only the current generation may update result, error, or loading.
  • Replacing source text from global selection immediately invalidates every older translation before B becomes current.
  • Editing, importing, and clearing source text also invalidate in-flight translations, so old completions cannot repopulate the UI.
  • In both A-then-B and B-then-A completion orders, A cannot modify B's result, error, or loading state.
  • A rejection from an old request cannot replace the current request's state.
  • Apply the UI-level generation guard to both web fetch and Tauri invoke paths. Transport cancellation can be added as an optimization but is not a substitute for the commit guard.
  • Add automated deferred-promise coverage for both completion orders and an old-request rejection.

Relevant code

  • src/App.tsx: handleSelectedText, translateValue, handleTranslate, document import, textarea editing, and reset paths.
  • src/platform.ts: the capture guard only covers concurrent selection captures and does not cover existing translation requests.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingjavascriptPull requests that update javascript coderelease-blockerBlocks delivery of an installable public releaserisk:mediumShared behavior or integration risk

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions