Skip to content

fix(input-emulation): prevent char duping race condition (@HenryHYeary) - #8387

Open
HenryHYeary wants to merge 1 commit into
monkeytypegame:masterfrom
HenryHYeary:fix/keydown-preventdefault-race
Open

fix(input-emulation): prevent char duping race condition (@HenryHYeary)#8387
HenryHYeary wants to merge 1 commit into
monkeytypegame:masterfrom
HenryHYeary:fix/keydown-preventdefault-race

Conversation

@HenryHYeary

@HenryHYeary HenryHYeary commented Sep 3, 2026

Copy link
Copy Markdown

Description

Changes

I moved event.preventDefault() in the keydown handler to before the asynchronous call to getCharFromEvent where the previous placement of the preventDefault call (after the asynchronous call) was causing a race condition which meant it could lose the race against the browser's native default action. If the browser inserted the native character before preventDefault() ran, both the native character and the emulated character would get inserted, producing a duplicate.

I was able to reproduce the bug after adding a 50ms setTimeout delay
right after layout = await __nonReactive.getInputLayout();. I used await new Promise(r => setTimeout(r, 50));.

I also refactored the keyEventCodes reassignments in layout-emulator.ts to ANSI_KEYCODES, ISO_KEYCODES, and MATRIX_KEYCODES. I then used these constants in a set to specify all of the emulated key codes, so that a new mayEmulateChar check function in layout-emulator could do quick lookups on which keys it would be necessary to emulate. Without this check, preventDefault() would need to run unconditionally for every key while a custom layout is active, which breaks Backspace, Tab, Enter, and other keys the emulator doesn't handle.

Notably a key in mayEmulateChar's set could still resolve to null if a layout's keyVariants data is incomplete, but I believe it's the responsibility of the layout creator to ensure the keyVariants data is complete rather than relying on fallbacks.

Checks

  • Adding quotes?
    • Make sure to follow the quotes documentation
    • Make sure to include translations for the quotes in the description (or another comment) so we can verify their content.
  • Adding a language?
    • Make sure to follow the languages documentation
    • Add language to packages/schemas/src/languages.ts
    • Add language to exactly one group in frontend/src/ts/constants/languages.ts
    • Add language json file to frontend/static/languages
  • Adding a theme?
    • Make sure to follow the themes documentation
    • Add theme to packages/schemas/src/themes.ts
    • Add theme to frontend/src/ts/constants/themes.ts
    • (optional) Add theme css file to frontend/static/themes
    • Add some screenshots of the theme, especially with different test settings (colorful, flip colors) to your pull request
  • Adding a layout?
    • Make sure to follow the layouts documentation
    • Add layout to packages/schemas/src/layouts.ts
    • Add layout json file to frontend/static/layouts
  • Adding a font?
    • Make sure to follow the fonts documentation
    • Add font file to frontend/static/webfonts
    • Add font to packages/schemas/src/fonts.ts
    • Add font to frontend/src/ts/constants/fonts.ts
  • Check if any open issues are related to this PR; if so, be sure to tag them below.
  • Make sure the PR title follows the Conventional Commits standard. (https://www.conventionalcommits.org for more info)
  • Make sure to include your GitHub username prefixed with @ inside parentheses at the end of the PR title.

Closes #8383

@monkeytypegeorge monkeytypegeorge added the frontend User interface or web stuff label Sep 3, 2026
@HenryHYeary HenryHYeary changed the title fix(input-emulation): prevent race condition causing duplicated chara… fix(input-emulation): prevent char duping race condition (@HenryHYeary) Sep 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

frontend User interface or web stuff

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Deduplicating key presses when emulating

2 participants