fix(extensions): prune malformed browser overrides (#5094)

This commit is contained in:
Rod Boev 2026-06-28 18:31:43 -04:00
parent aef8e524fd
commit 7153e8d78f
2 changed files with 21 additions and 7 deletions

View file

@ -143,17 +143,23 @@
} }
} }
function safeRead(key){ function safeReadState(key){
try{ try{
const raw=window.localStorage.getItem(key); const raw=window.localStorage.getItem(key);
if(!raw) return {}; if(!raw) return {value:{},malformed:false};
const parsed=JSON.parse(raw); const parsed=JSON.parse(raw);
return parsed&&typeof parsed==='object'&&!Array.isArray(parsed)?parsed:{}; return parsed&&typeof parsed==='object'&&!Array.isArray(parsed)
?{value:parsed,malformed:false}
:{value:{},malformed:true};
}catch(_e){ }catch(_e){
return {}; return {value:{},malformed:true};
} }
} }
function safeRead(key){
return safeReadState(key).value;
}
function safeWrite(key,value){ function safeWrite(key,value){
const keys=Object.keys(value||{}); const keys=Object.keys(value||{});
try{ try{
@ -211,10 +217,10 @@
} }
function readSettingsState(schema,key){ function readSettingsState(schema,key){
const stored=safeRead(key); const stored=safeReadState(key);
const checked=validate(schema,stored); const checked=validate(schema,stored.value);
const overrides=overridesFromValues(schema,checked.values); const overrides=overridesFromValues(schema,checked.values);
if(JSON.stringify(stored)!==JSON.stringify(overrides)) safeWrite(key,overrides); if(stored.malformed||JSON.stringify(stored.value)!==JSON.stringify(overrides)) safeWrite(key,overrides);
return {values:checked.values,overrides}; return {values:checked.values,overrides};
} }

View file

@ -72,6 +72,14 @@ def test_extension_settings_runtime_normalizes_persists_resets_and_clears():
assert.deepStrictEqual(settings.values, {{flag: false, mode: 'compact', count: 2}}); assert.deepStrictEqual(settings.values, {{flag: false, mode: 'compact', count: 2}});
assert.deepStrictEqual(settings.overrides, {{}}); assert.deepStrictEqual(settings.overrides, {{}});
assert.strictEqual(store.has('hermes.ext.settings.demo.ext'), false); assert.strictEqual(store.has('hermes.ext.settings.demo.ext'), false);
store.set('hermes.ext.settings.demo.ext', 'not-json');
assert.deepStrictEqual(settings.values, {{flag: false, mode: 'compact', count: 2}});
assert.deepStrictEqual(settings.overrides, {{}});
assert.strictEqual(store.has('hermes.ext.settings.demo.ext'), false);
store.set('hermes.ext.settings.demo.ext', JSON.stringify(['bad']));
assert.deepStrictEqual(settings.values, {{flag: false, mode: 'compact', count: 2}});
assert.deepStrictEqual(settings.overrides, {{}});
assert.strictEqual(store.has('hermes.ext.settings.demo.ext'), false);
assert.strictEqual(settings.set('mode', 'invalid').ok, false); assert.strictEqual(settings.set('mode', 'invalid').ok, false);
assert.deepStrictEqual(settings.reset(), {{flag: false, mode: 'compact', count: 2}}); assert.deepStrictEqual(settings.reset(), {{flag: false, mode: 'compact', count: 2}});
assert.strictEqual(store.has('hermes.ext.settings.demo.ext'), false); assert.strictEqual(store.has('hermes.ext.settings.demo.ext'), false);