diff --git a/src/SaveObject.tsx b/src/SaveObject.tsx index bd4e766d6..daa4a5b0e 100755 --- a/src/SaveObject.tsx +++ b/src/SaveObject.tsx @@ -480,12 +480,6 @@ function evaluateVersionCompatibility(ver: string | number): void { if (ver < 23) { anyPlayer.currentWork = null; } - if (ver < 24) { - // Assert the relevant type that was in effect at this version. - (Player.getHomeComputer().scripts as unknown as { filename: string }[]).forEach( - (s) => s.filename.endsWith(".ns") && (s.filename += ".js"), - ); - } if (ver < 25) { const removePlayerFields = [ "hacking_chance_mult", diff --git a/src/ScriptEditor/ui/themes.ts b/src/ScriptEditor/ui/themes.ts index b9cee6d8a..b8751c6d6 100644 --- a/src/ScriptEditor/ui/themes.ts +++ b/src/ScriptEditor/ui/themes.ts @@ -1,4 +1,6 @@ import type { editor } from "monaco-editor"; +import { getRecordKeys } from "../../Types/Record"; +import { Settings } from "../../Settings/Settings"; type DefineThemeFn = typeof editor.defineTheme; export interface IScriptEditorTheme { @@ -72,8 +74,13 @@ const colorRegExp = /^#?([0-9A-Fa-f]{6})([0-9A-Fa-f]{2})?$/; // Recursively sanitize the theme data to prevent errors // Invalid data will be replaced with FF0000 (bright red) export const sanitizeTheme = (theme: IScriptEditorTheme): void => { - for (const [k, v] of Object.entries(theme)) { - switch (k) { + if (typeof theme !== "object") { + Settings.EditorTheme = defaultMonacoTheme; + return; + } + for (const themeKey of getRecordKeys(theme)) { + if (typeof theme[themeKey] !== "object") delete theme[themeKey]; + switch (themeKey) { case "base": if (!["vs-dark", "vs"].includes(theme.base)) theme.base = "vs-dark"; continue; @@ -82,14 +89,17 @@ export const sanitizeTheme = (theme: IScriptEditorTheme): void => { continue; } - const repairBlock = (block: Record): void => { - for (const [k, v] of Object.entries(block)) { - if (typeof v === "object") { - repairBlock(v as Record); - } else if (!v.match(colorRegExp)) block[k] = "FF0000"; + const block = theme[themeKey]; + function repairBlock>(block: T) { + for (const [blockKey, blockValue] of Object.entries(block) as [keyof T, unknown][]) { + if (!blockValue || (typeof blockValue !== "string" && typeof blockValue !== "object")) + (block[blockKey] as string) = "FF0000"; + else if (typeof blockValue === "object") repairBlock(block); + else if (!blockValue.match(colorRegExp)) (block[blockKey] as string) = "FF0000"; } - }; - repairBlock(v); + } + // Type assertion is to something less specific. + repairBlock(block); } }; diff --git a/src/Server/BaseServer.ts b/src/Server/BaseServer.ts index d2d132d0e..b41e7c048 100644 --- a/src/Server/BaseServer.ts +++ b/src/Server/BaseServer.ts @@ -333,6 +333,8 @@ export abstract class BaseServer implements IServer { server.scripts = new JSONMap(); // In case somehow there are previously valid filenames that can't be sanitized, they will go in a new directory with a note. for (const script of oldScripts) { + // We're about to do type validation on the filename anyway. + if (script.filename.endsWith(".ns")) script.filename = (script.filename + ".js") as any; let newFilePath = resolveScriptFilePath(script.filename); if (!newFilePath) { newFilePath = `${newDirectory}script${++invalidScriptCount}.js` as ScriptFilePath;