PageSourceSearch

https://pressthink.org/j/rosen-archive/frontend/utils/submitGate.js?v=3.8.36

js pressthink.org collected 2026-10-02 04:27:22 UTC 2,196 bytes, 50 lines download raw bytes

1// Submit lifecycle gate for the branded report modal (#509).
2//
3// The modal has two concurrency rules that fought each other as ad-hoc refs:
4//   1. Block a second submit fired synchronously (a double-click or Enter-repeat)
5//      before React re-renders the disabled button, so one action never files
6//      two issues.
7//   2. Still allow a fresh submit after the modal is closed and reopened while an
8//      earlier request is in flight, and drop that earlier request's result so it
9//      cannot write into the reopened session.
10// Rule 1 alone blocks rule 2; naively clearing the guard on reopen lets an older
11// overlapping request's completion clear a newer submit's guard, which resurrects
12// the duplicate-file bug. Encoding the rules as a tiny pure state object with an
13// ownership check makes both correct by construction and unit-testable with no DOM.
14//
15// One gate per mounted modal (held in a ref). Seqs are opaque positive integers.
16export const createSubmitGate = () => {
17  let inFlightSeq = 0; // 0 = idle; otherwise the seq of the submit in flight
18  let lastSeq = 0;     // monotonic id of the newest submit-or-reset
19
20  return {
21    // Call on modal open. Disowns any still-pending submit (its result will be
22    // dropped and its cleanup will not touch the guard) so a fresh submit is
23    // allowed even while the old request is still settling.
24    reset() {
25      inFlightSeq = 0;
26      lastSeq += 1;
27    },
28
29    // Try to start a submit. Returns a positive seq if allowed, or 0 if a submit
30    // is already in flight (the synchronous double-submit block).
31    begin() {
32      if (inFlightSeq !== 0) return 0;
33      lastSeq += 1;
34      inFlightSeq = lastSeq;
35      return inFlightSeq;
36    },
37
38    // Whether `seq` is still the newest submit. False once the modal has been
39    // reopened or a newer submit began, so a slow completion drops its result.
40    isCurrent(seq) {
41      return seq !== 0 && seq === lastSeq;
42    },
43
44    // Call in the submit's finally. Clears the in-flight guard only if `seq` still
45    // owns it, so an older overlapping request cannot release a newer submit.
46    end(seq) {
47      if (inFlightSeq === seq) inFlightSeq = 0;
48    },
49  };
50};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.