This fixes https://github.com/cmcaine/tridactyl/issues/613.
This was a really fun bug. What happened was this:
- First, the content script set state.mode to "hint", which was then
synchronized
- The event listener in the background script noticed the update and set
state.mode to "hint" in the background script
- Then, the content script translated the hint selection into an excmd
that needed to be executed in the background script and sent said
command to the controller, which lives in the background script
- The content script then set state.mode to "normal"
- The background script executed the command and saved it in
state.last_ex_str, which was then synchronized
- The event listener in the content script noticed the update and set
last_ex_str to the last executed str and "state.mode" to "hint"
So basically, the problem was that the background script didn't notice
the state.mode update right after it happened. I fixed this by moving
last_ex_str out of "state" since it doesn't need to be synchronized with
the content script.
This means that the same kind of race condition can still happen. I'm
not sure how to fix this. We could just kill state completely and
instead have state be updated through message passing, but this probably
wouldn't be very ergonomic.
Another solution, the one envisioned for Tridactylv2, is to move to the
content script entirely. This is probably the best option.
Allows one to bind `composite tabprev | sleep 100 | tabclose #` and have
the command work; `composite tabclose | tabprev` also works but looks a
little janky. The sleep is required in the first command so that the
value of `#` has time to update.
Turns out writing to browser.storage is expensive because state.ts and
config.ts both listen for it in every tab. I'd vaguely assumed that
Firefox would run other tabs as low priority tasks and that this would
not be an issue, but it doesn't.
I also wrote the code in a rush, and while I mused that this potential
risk exists I didn't document it or explore it.
Retrospective: Content switches are expensive - think before you do
anything that may wake many processes and don't make wild assumptions
about how Firefox handles multiprocessing.
This is useful for suppressing spew, but still allowing easy debugging
when needed, without rebuilding.
To use, use excmd:
setlogginglevel <prefix> <level>
Where the level is one of:
- never: never log
- error
- warning
- info
- debug: most verbose
Output is directed to console methods "error", "warn", "log", "debug".
- Add `focusinput -n` and `focusinput -N`
- Press `gi` to focus input and enter inputmode
- When in inputmode, `Tab` to focus input after last focussed one, `Shift+Tab`
to focus input before last focussed one
exmode.parser now converts strings to the types given in excmd
signatures.
Messaging now works in both directions (but I haven't made excmds.ts use
the new system yet. Exercise for the reader (see keydown_* state() for a
simple example)).
keys are now being suppressed, but in a pretty stupid way.
I got fed up of not having proper itertools, or str conversions, so I
wrote some. Others have written them in JS, but they were fun to make.
Only the ones I'm using are tested.
Motivation:
- Most test frameworks expect modules
- I'm told they're the future
Changes:
- Every typescript source file is now an es6 module
- Build system is now webpack (tho rollup makes nicer outputs)
- Outputs of buildsystem are one js file per entry point (background,
content, commandline_frame)
- These bundled js files are generated by traversing the dependency
graph of each entry point