@@ -174,6 +174,14 @@ export default class SettingsStore {
174174 const watcherId = `${ new Date ( ) . getTime ( ) } _${ SettingsStore . watcherCount ++ } _${ settingName } _${ roomId } ` ;
175175
176176 const localizedCallback = ( changedInRoomId : string | null , atLevel : SettingLevel , newValAtLevel : any ) => {
177+ if ( ! SettingsStore . doesSettingSupportLevel ( originalSettingName , atLevel ) ) {
178+ logger . warn (
179+ `Setting handler notified for an update of an invalid setting level: ` +
180+ `${ originalSettingName } @${ atLevel } - this likely means a weird setting value ` +
181+ `made it into the level's storage. The notification will be ignored.` ,
182+ ) ;
183+ return ;
184+ }
177185 const newValue = SettingsStore . getValue ( originalSettingName ) ;
178186 const newValueAtLevel = SettingsStore . getValueAt ( atLevel , originalSettingName ) ?? newValAtLevel ;
179187 callbackFn ( originalSettingName , changedInRoomId , atLevel , newValueAtLevel , newValue ) ;
@@ -516,6 +524,23 @@ export default class SettingsStore {
516524 return LEVEL_HANDLERS [ level ] . isSupported ( ) ;
517525 }
518526
527+ /**
528+ * Determines if a setting supports a particular level.
529+ * @param settingName The setting name.
530+ * @param level The level.
531+ * @returns True if supported, false otherwise. Note that this will not check to see if
532+ * the level itself can be supported by the runtime (ie: you will need to call #isLevelSupported()
533+ * on your own).
534+ */
535+ public static doesSettingSupportLevel ( settingName : string , level : SettingLevel ) : boolean {
536+ const setting = SETTINGS [ settingName ] ;
537+ if ( ! setting ) {
538+ throw new Error ( "Setting '" + settingName + "' does not appear to be a setting." ) ;
539+ }
540+
541+ return level === SettingLevel . DEFAULT || ( setting . supportedLevels . includes ( level ) ) ;
542+ }
543+
519544 /**
520545 * Determines the first supported level out of all the levels that can be used for a
521546 * specific setting.
0 commit comments