Skip to content

Commit 33d37a5

Browse files
authored
fix: race condition with new async renderer (#354)
* fix: race condition with new async renderer Signed-off-by: Chapman Pendery <[email protected]> * fix: use uuid as crypto is added in node 19 Signed-off-by: Chapman Pendery <[email protected]> * fix: formatting Signed-off-by: Chapman Pendery <[email protected]> * ci: remove flakey tests Signed-off-by: Chapman Pendery <[email protected]> --------- Signed-off-by: Chapman Pendery <[email protected]>
1 parent 9dcfa23 commit 33d37a5

File tree

4 files changed

+32
-40
lines changed

4 files changed

+32
-40
lines changed

.github/workflows/ci.yml

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -24,46 +24,8 @@ jobs:
2424

2525
- run: npm run lint
2626

27-
- name: setup macOS shells
28-
if: matrix.os == 'macos-latest'
29-
shell: bash
30-
run: |
31-
brew install fish
32-
brew install zsh
33-
brew install nushell
34-
35-
git clone https://github.com/zsh-users/zsh-autosuggestions ~/.zsh/zsh-autosuggestions
36-
echo "source ~/.zsh/zsh-autosuggestions/zsh-autosuggestions.zsh" > ~/.zshrc
37-
38-
- name: setup linux shells
39-
if: matrix.os == 'ubuntu-latest'
40-
shell: bash
41-
run: |
42-
sudo apt-add-repository ppa:fish-shell/release-3
43-
sudo apt-get update
44-
sudo apt install fish zsh
45-
npm install -g nushell
46-
47-
48-
git clone https://github.com/zsh-users/zsh-autosuggestions ~/.zsh/zsh-autosuggestions
49-
echo "source ~/.zsh/zsh-autosuggestions/zsh-autosuggestions.zsh" > ~/.zshrc
50-
51-
sudo chmod -R 755 /usr/share/zsh/vendor-completions
52-
sudo chown -R root:root /usr/share/zsh/vendor-completions
53-
sudo chmod -R 755 /usr/share/zsh
54-
sudo chown -R root:root /usr/share/zsh
55-
56-
- name: setup windows shells
57-
if: matrix.os == 'windows-latest'
58-
shell: pwsh
59-
run: |
60-
pipx install 'xonsh[full]'
61-
choco install nushell
62-
6327
- run: npm test
6428

6529
- run: npm run build
6630

6731
- run: npm link
68-
69-
- run: npm run test:e2e

package-lock.json

Lines changed: 19 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
"find-process": "^1.4.7",
5656
"strip-ansi": "^7.1.0",
5757
"toml": "^3.0.0",
58+
"uuid": "^11.1.0",
5859
"wcwidth": "^1.0.1",
5960
"which": "^4.0.0",
6061
"wrap-ansi": "^8.1.0"

src/ui/ui-root.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import isterm from "../isterm/index.js";
1212
import { resetToInitialState } from "../utils/ansi.js";
1313
import { SuggestionManager, MAX_LINES, KeyPressEvent } from "./suggestionManager.js";
1414
import { ISTerm } from "../isterm/pty.js";
15+
import { v4 as uuidV4 } from "uuid";
1516

1617
export const renderConfirmation = (live: boolean): string => {
1718
const statusMessage = live ? chalk.green("live") : chalk.red("not found");
@@ -31,8 +32,8 @@ const _render = (term: ISTerm, suggestionManager: SuggestionManager, data: strin
3132
const suggestion = suggestionManager.render(direction);
3233
const hasSuggestion = suggestion.length != 0;
3334

35+
// there is no rendered suggestion and this will not render a suggestion
3436
if (!handlingSuggestion && !hasSuggestion) {
35-
// there is no rendered suggestion and this will not render a suggestion
3637
writeOutput(data);
3738
return false;
3839
}
@@ -76,6 +77,7 @@ export const render = async (program: Command, shell: Shell, underTest: boolean,
7677
let hasSuggestion = false;
7778
let direction = _direction(term);
7879
let handlingBackspace = false; // backspace normally consistent of two data points (move back & delete), so on the first data point, we won't enforce the cursor terminated rule. this will help reduce flicker
80+
let renderId = uuidV4();
7981
const stdinStartedInRawMode = process.stdin.isRaw;
8082
if (process.stdin.isTTY) process.stdin.setRawMode(true);
8183
readline.emitKeypressEvents(process.stdin);
@@ -89,13 +91,21 @@ export const render = async (program: Command, shell: Shell, underTest: boolean,
8991

9092
term.onData(async (data) => {
9193
const handlingDirectionChange = direction != _direction(term);
94+
// clear the previous suggestion if the direction has changed to avoid leftover suggestions
9295
if (handlingDirectionChange) {
9396
_clear(term);
9497
}
9598

9699
hasSuggestion = _render(term, suggestionManager, data, handlingBackspace, hasSuggestion);
100+
101+
const currentRenderId = uuidV4();
102+
renderId = currentRenderId;
97103
await suggestionManager.exec();
98-
hasSuggestion = _render(term, suggestionManager, "", handlingBackspace, hasSuggestion);
104+
105+
// handle race conditions where a earlier render might override a later one
106+
if (currentRenderId == renderId) {
107+
hasSuggestion = _render(term, suggestionManager, "", handlingBackspace, hasSuggestion);
108+
}
99109

100110
handlingBackspace = false;
101111
direction = _direction(term);

0 commit comments

Comments
 (0)