Partial config updates to avoid race clobbering

Updates to the global configuration object happen via storage onChanged
event, however this is not guaranteed to fire before a set() promise
resolves: https://bugzilla.mozilla.org/show_bug.cgi?id=1554088

This can lead to situations where setting multiple values in sequence
can result in a previously scheduled callback clobbering newer settings.
Slightly mitigate races by not replacing the entire object; however this
only helps with flat values and won't catch nested object updates such
as the keymap settings.
This commit is contained in:
arcnmx 2019-07-29 14:24:30 -07:00
parent 798d03890b
commit 1cbf1d3f3f

View file

@ -1539,7 +1539,7 @@ const parseConfigHelper = (pconf, parseobj) => {
// Listen for changes to the storage and update the USERCONFIG if appropriate.
// TODO: BUG! Sync and local storage are merged at startup, but not by this thing.
browser.storage.onChanged.addListener(async (changes, areaname) => {
browser.storage.onChanged.addListener((changes, areaname) => {
if (CONFIGNAME in changes) {
const { newValue } = changes[CONFIGNAME]
const old = USERCONFIG
@ -1573,13 +1573,14 @@ browser.storage.onChanged.addListener(async (changes, areaname) => {
) !== JSON.stringify(newValue[k]),
)
USERCONFIG = newValue
// TODO: this should be a deep comparison but this is better than nothing
changedKeys.concat(unsetKeys).forEach(key => USERCONFIG[key] = newValue[key])
// Trigger listeners
unsetKeys.forEach(key => triggerChangeListeners(key, DEFAULTS[key]))
changedKeys.forEach(key => triggerChangeListeners(key))
} else if (areaname === (await get("storageloc"))) {
} else if (areaname === get("storageloc")) {
// If newValue is undefined and AREANAME is the same value as STORAGELOC, the user wants to clean their config
USERCONFIG = o({})