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.