mirror of
https://github.com/vale981/tridactyl
synced 2025-03-05 17:41:40 -05:00
Merge pull request #2200 from tridactyl/fix_repeat
Fix #1538: synchronise repeat between tabs and bg
This commit is contained in:
commit
09f6831b0e
7 changed files with 45 additions and 16 deletions
|
@ -33,6 +33,7 @@ import * as locks from "@src/lib/locks"
|
|||
excmds: excmds_background,
|
||||
convert,
|
||||
config,
|
||||
controller,
|
||||
dom,
|
||||
download_background,
|
||||
itertools,
|
||||
|
|
|
@ -149,6 +149,7 @@ import * as locks from "@src/lib/locks"
|
|||
commandline_content,
|
||||
convert,
|
||||
config,
|
||||
controller,
|
||||
dom,
|
||||
editor,
|
||||
excmds,
|
||||
|
|
|
@ -2749,7 +2749,7 @@ async function getnexttabs(tabid: number, n?: number) {
|
|||
*/
|
||||
//#both
|
||||
export async function repeat(n = 1, ...exstr: string[]) {
|
||||
let cmd = controller.last_ex_str
|
||||
let cmd = state.last_ex_str
|
||||
if (exstr.length > 0) cmd = exstr.join(" ")
|
||||
logger.debug("repeating " + cmd + " " + n + " times")
|
||||
for (let i = 0; i < n; i++) {
|
||||
|
|
|
@ -785,6 +785,7 @@ export class default_config {
|
|||
performance: "warning",
|
||||
state: "warning",
|
||||
styling: "warning",
|
||||
locks: "warning",
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import Logger from "@src/lib/logging"
|
||||
import { parser as exmode_parser } from "@src/parsers/exmode"
|
||||
import state from "@src/state"
|
||||
|
||||
const logger = new Logger("controller")
|
||||
|
||||
|
@ -8,15 +9,13 @@ export function setExCmds(excmds: any) {
|
|||
stored_excmds = excmds
|
||||
}
|
||||
|
||||
export let last_ex_str = ""
|
||||
|
||||
/** Parse and execute ExCmds */
|
||||
export async function acceptExCmd(exstr: string): Promise<any> {
|
||||
// TODO: Errors should go to CommandLine.
|
||||
try {
|
||||
const [func, args] = exmode_parser(exstr, stored_excmds)
|
||||
// Stop the repeat excmd from recursing.
|
||||
if (func !== stored_excmds[""].repeat) last_ex_str = exstr
|
||||
if (func !== stored_excmds[""].repeat) state.last_ex_str = exstr
|
||||
try {
|
||||
return await func(...args)
|
||||
} catch (e) {
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
import {messageAllTabs} from "@src/lib/messaging"
|
||||
|
||||
import {v1 as uuid} from "uuid"
|
||||
import * as Logging from "@src/lib/logging"
|
||||
|
||||
const logger = new Logging.Logger("locks")
|
||||
|
||||
export const OWNED_LOCKS = new Set()
|
||||
|
||||
|
@ -11,21 +14,49 @@ export const ID = uuid()
|
|||
|
||||
const now = () => (new Date()).getTime() + Math.random() // getTime is accurate only to ms, so fake microseconds with random
|
||||
|
||||
export async function acquire(lockname: string) {
|
||||
export async function acquire(lockname: string, timeout = 2000) {
|
||||
if (OWNED_LOCKS.has(lockname) || DESIRED_LOCKS.hasOwnProperty(lockname)) return;
|
||||
const time = now()
|
||||
|
||||
DESIRED_LOCKS[lockname] = time
|
||||
|
||||
await Promise.all([
|
||||
browser.runtime.sendMessage({type: "lock", command: "acquire", args: [lockname, time, ID]}),
|
||||
messageAllTabs("lock", "acquire", [lockname, time, ID])]
|
||||
)
|
||||
const a = await Promise.race([
|
||||
Promise.all([
|
||||
browser.runtime.sendMessage({type: "lock", command: "acquire", args: [lockname, time, ID]}),
|
||||
messageAllTabs("lock", "acquire", [lockname, time, ID]),
|
||||
]),
|
||||
new Promise(resolve => setTimeout(
|
||||
() => {
|
||||
resolve("ERROR: LOST THE RACE")
|
||||
},
|
||||
timeout)), // Take the lock anyway after timeout
|
||||
])
|
||||
if (a === "ERROR: LOST THE RACE") {logger.warning("lock " + lockname + " was taken without confirmation")}
|
||||
|
||||
delete DESIRED_LOCKS[lockname]
|
||||
OWNED_LOCKS.add(lockname)
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute func after acquiring a named lock. If func takes longer than timeout, release the lock early.
|
||||
* Returns the value of func.
|
||||
*/
|
||||
export async function withlock(lockname: string, func, timeout = 500) {
|
||||
await acquire(lockname)
|
||||
const p = (async () => func())() // Ensure function is promisified
|
||||
const a = await Promise.race([
|
||||
p,
|
||||
new Promise(resolve => setTimeout(
|
||||
() => {
|
||||
resolve("ERROR: LOST THE RACE")
|
||||
},
|
||||
timeout)), // Release the lock anyway after timeout
|
||||
])
|
||||
if (a === "ERROR: LOST THE RACE") {logger.warning("lock " + lockname + " was released early")}
|
||||
release(lockname)
|
||||
return p
|
||||
}
|
||||
|
||||
export async function release(lockname: string) {
|
||||
OWNED_LOCKS.delete(lockname)
|
||||
}
|
||||
|
|
10
src/state.ts
10
src/state.ts
|
@ -29,6 +29,7 @@ class State {
|
|||
jumppos: undefined,
|
||||
},
|
||||
]
|
||||
last_ex_str: string = "echo"
|
||||
}
|
||||
|
||||
// Don't change these from const or you risk breaking the Proxy below.
|
||||
|
@ -57,9 +58,7 @@ const state = (new Proxy(overlay, {
|
|||
|
||||
/** Persist sets to storage "immediately" */
|
||||
set(target, property, value) {
|
||||
(async () => {
|
||||
await locks.acquire("state")
|
||||
|
||||
locks.withlock("state", async () => {
|
||||
logger.debug("State changed!", property, value)
|
||||
target[property] = value
|
||||
browser.storage.local.set({ state: target } as any)
|
||||
|
@ -73,10 +72,7 @@ const state = (new Proxy(overlay, {
|
|||
// I haven't had time to get my head around them
|
||||
browser.runtime.sendMessage({type: "state", command: "stateUpdate", args: [{state: target}]}),
|
||||
])
|
||||
|
||||
// Release named lock
|
||||
locks.release("state")
|
||||
})()
|
||||
})
|
||||
|
||||
return true
|
||||
},
|
||||
|
|
Loading…
Add table
Reference in a new issue