Repository: compiler-explorer/compiler-explorer
Pull request #6841 (2024-09-07 20:39:57)

tsification + small package upgrade (semver)


Patch:
diff --git a/etc/config/c++.amazon.properties b/etc/config/c++.amazon.properties
index 1d8e90aef..247b8d85b 100644
--- a/etc/config/c++.amazon.properties
+++ b/etc/config/c++.amazon.properties
@@ -1113,10 +1113,10 @@ group.loongarch-clang.licenseLink=https://github.com/llvm/llvm-project/blob/main
 group.loongarch-clang.licensePreamble=The LLVM Project is under the Apache License v2.0 with LLVM Exceptions
 
 group.loongarch64clang.compilers=loongarch64-clangtrunk:loongarch64-clang1701:loongarch64-clang1810
-group.loongarch64clang.options=-target loongarch64-unknown-elf --gcc-toolchain=/opt/compiler-explorer/loongarch64/gcc-13.2.0/loongarch64-unknown-linux-gnu --sysroot=/opt/compiler-explorer/loongarch64/gcc-13.2.0/loongarch64-unknown-linux-gnu/loongarch64-unknown-linux-gnu/sysroot
-group.loongarch64clang.objdumper=/opt/compiler-explorer/loongarch64/gcc-13.2.0/loongarch64-unknown-linux-gnu/bin/loongarch64-unknown-linux-gnu-objdump
-group.loongarch64clang.baseName=Loongarch64 clang
-group.loongarch64clang.groupName=Loongarch64 Clang
+group.loongarch64clang.options=-target loongarch64-unknown-linux-gnu --gcc-toolchain=/opt/compiler-explorer/loongarch64/gcc-13.3.0/loongarch64-unknown-linux-gnu --sysroot=/opt/compiler-explorer/loongarch64/gcc-13.3.0/loongarch64-unknown-linux-gnu/loongarch64-unknown-linux-gnu/sysroot
+group.loongarch64clang.objdumper=/opt/compiler-explorer/loongarch64/gcc-13.3.0/loongarch64-unknown-linux-gnu/bin/loongarch64-unknown-linux-gnu-objdump
+group.loongarch64clang.baseName=LoongArch64 clang
+group.loongarch64clang.groupName=LoongArch64 Clang
 group.loongarch64clang.compilerCategories=clang
 group.loongarch64clang.demangler=/opt/compiler-explorer/clang-trunk/bin/llvm-cxxfilt
 
diff --git a/lib/base-compiler.ts b/lib/base-compiler.ts
index 924d87339..e3a0f598b 100644
--- a/lib/base-compiler.ts
+++ b/lib/base-compiler.ts
@@ -69,7 +69,7 @@ import {
 import type {CompilerOutputOptions, ParseFiltersAndOutputOptions} from '../types/features/filters.interfaces.js';
 import {InstructionSet} from '../types/instructionsets.js';
 import type {Language} from '../types/languages.interfaces.js';
-import type {Library, LibraryVersion, SelectedLibraryVersion} from '../types/libraries/libraries.interfaces.js';
+import type {SelectedLibraryVersion} from '../types/libraries/libraries.interfaces.js';
 import type {ResultLine} from '../types/resultline/resultline.interfaces.js';
 import {type ToolResult, type ToolTypeKey} from '../types/tool.interfaces.js';
 
@@ -185,7 +185,7 @@ export class BaseCompiler implements ICompiler {
     protected cmakeBaseEnv: Record<string, string>;
     protected buildenvsetup: null | any;
     protected externalparser: null | ExternalParserBase;
-    protected supportedLibraries?: Record<string, Library>;
+    protected supportedLibraries?: Record<string, OptionsHandlerLibrary>;
     protected packager: Packager;
     protected executionType: string;
     protected sandboxType: string;
@@ -758,15 +758,15 @@ export class BaseCompiler implements ICompiler {
         return options;
     }
 
-    findLibVersion(selectedLib: SelectedLibraryVersion): false | LibraryVersion {
+    findLibVersion(selectedLib: SelectedLibraryVersion): false | VersionInfo {
         if (!this.supportedLibraries) return false;
 
         const foundLib = _.find(this.supportedLibraries, (o, libId) => libId === selectedLib.id);
         if (!foundLib) return false;
 
-        const result: LibraryVersion | undefined = _.find(
+        const result: VersionInfo | undefined = _.find(
             foundLib.versions,
-            (o: LibraryVersion, versionId: string): boolean => {
+            (o: VersionInfo, versionId: string): boolean => {
                 if (versionId === selectedLib.version) return true;
                 return !!(o.alias && o.alias.includes(selectedLib.version));
             },
@@ -783,7 +783,7 @@ export class BaseCompiler implements ICompiler {
     }
 
     findAutodetectStaticLibLink(linkname: string): SelectedLibraryVersion | false {
-        const foundLib = _.findKey(this.supportedLibraries as Record<string, Library>, lib => {
+        const foundLib = _.findKey(this.supportedLibraries!, lib => {
             return (
                 lib.versions.autodetect &&
                 lib.versions.autodetect.staticliblink &&
@@ -799,7 +799,7 @@ export class BaseCompiler implements ICompiler {
     }
 
     getSortedStaticLibraries(libraries: CompileChildLibraries[]) {
-        const dictionary = {};
+        const dictionary: Record<string, VersionInfo> = {};
         const links = unique(
             libraries
                 .map(selectedLib => {
@@ -826,7 +826,7 @@ export class BaseCompiler implements ICompiler {
 
                 let idxToInsert = sortedlinks.length;
                 for (const [idx, libCompareName] of sortedlinks.entries()) {
-                    const libCompareObj: LibraryVersion = dictionary[libCompareName];
+                    const libCompareObj: VersionInfo = dictionary[libCompareName];
 
                     if (
                         libToInsertObj &&
@@ -1719,8 +1719,8 @@ export class BaseCompiler implements ICompiler {
         return maskedArgs;
     }
 
-    async getRequiredLibraryVersions(libraries): Promise<Record<string, LibraryVersion>> {
-        const libraryDetails = {};
+    async getRequiredLibraryVersions(libraries): Promise<Record<string, VersionInfo>> {
+        const libraryDetails: Record<string, VersionInfo> = {};
         _.each(libraries, selectedLib => {
             const foundVersion = this.findLibVersion(selectedLib);
             if (foundVersion) libraryDetails[selectedLib.id] = foundVersion;
@@ -1728,7 +1728,7 @@ export class BaseCompiler implements ICompiler {
         return libraryDetails;
     }
 
-    async setupBuildEnvironment(key: any, dirPath: string, binary: boolean): Promise<BuildEnvDownloadInfo[]> {
+    async setupBuildEnvironment(key: CacheKey, dirPath: string, binary: boolean): Promise<BuildEnvDownloadInfo[]> {
         if (this.buildenvsetup) {
             const libraryDetails = await this.getRequiredLibraryVersions(key.libraries);
             return this.buildenvsetup.setup(key, dirPath, libraryDetails, binary);
@@ -1785,7 +1785,7 @@ export class BaseCompiler implements ICompiler {
         };
     }
 
-    async buildExecutableInFolder(key, dirPath: string): Promise<BuildResult> {
+    async buildExecutableInFolder(key: CacheKey, dirPath: string): Promise<BuildResult> {
         const writeSummary = await this.writeAllFiles(dirPath, key.source, key.files, key.filters);
         const downloads = await this.setupBuildEnvironment(key, dirPath, true);
 
@@ -1827,11 +1827,11 @@ export class BaseCompiler implements ICompiler {
         });
     }
 
-    async afterBuild(key, dirPath: string, buildResult: BuildResult): Promise<BuildResult> {
+    async afterBuild(key: CacheKey, dirPath: string, buildResult: BuildResult): Promise<BuildResult> {
         return buildResult;
     }
 
-    async getOrBuildExecutable(key, bypassCache: BypassCache) {
+    async getOrBuildExecutable(key: CacheKey, bypassCache: BypassCache) {
         const dirPath = await this.newTempDir();
 
         if (!bypassCompilationCache(bypassCache)) {
@@ -1864,7 +1864,7 @@ export class BaseCompiler implements ICompiler {
         return compilationResult;
     }
 
-    async loadPackageWithExecutable(key, dirPath) {
+    async loadPackageWithExecutable(key: CacheKey, dirPath: string) {
         const compilationResultFilename = 'compilation-result.json';
         try {
             const startTime = process.hrtime.bigint();
@@ -1939,7 +1939,7 @@ export class BaseCompiler implements ICompiler {
         executeParameters.args.unshift(outputFilename);
     }
 
-    async handleInterpreting(key, executeParameters: ExecutableExecutionOptions): Promise<CompilationResult> {
+    async handleInterpreting(key: CacheKey, executeParameters: ExecutableExecutionOptions): Promise<CompilationResult> {
         const source = key.source;
         const dirPath = await this.newTempDir();
         const outputFilename = this.getExecutableFilename(dirPath, this.outputFilebase);
@@ -1971,7 +1971,7 @@ export class BaseCompiler implements ICompiler {
     }
 
     async doExecution(
-        key,
+        key: CacheKey,
         executeParameters: ExecutableExecutionOptions,
         bypassCache: BypassCache,
     ): Promise<CompilationResult> {
@@ -3229,12 +3229,10 @@ but nothing was dumped. Possible causes are:
     }
 
     initialiseLibraries(clientOptions: ClientOptionsType) {
-        // TODO: Awful cast here because of OptionsHandlerLibrary vs Library. These might really be the same types and
-        // OptionsHandlerLibrary should maybe be yeeted.
         this.supportedLibraries = this.getSupportedLibraries(
             this.compiler.libsArr,
             clientOptions.libs[this.lang.id] || [],
-        ) as any as Record<string, Library>;
+        );
     }
 
     async getTargetsAsOverrideValues(): Promise<CompilerOverrideOption[]> {
diff --git a/lib/buildenvsetup/base.ts b/lib/buildenvsetup/base.ts
index cca339a26..8b5229206 100644
--- a/lib/buildenvsetup/base.ts
+++ b/lib/buildenvsetup/base.ts
@@ -26,8 +26,11 @@ import path from 'path';
 
 import _ from 'underscore';
 
-import {LibraryVersion} from '../../types/libraries/libraries.interfaces.js';
+import {CacheKey} from '../../types/compilation/compilation.interfaces.js';
+import {CompilerInfo} from '../../types/compiler.interfaces.js';
+import {CompilationEnvironment} from '../compilation-env.js';
 import {logger} from '../logger.js';
+import {VersionInfo} from '../options-handler.js';
 import * as utils from '../utils.js';
 
 import type {BuildEnvDownloadInfo} from './buildenv.interfaces.js';
@@ -41,7 +44,7 @@ export class BuildEnvSetupBase {
     public compilerSupportsX86: boolean;
     public defaultLibCxx: string;
 
-    constructor(compilerInfo, env) {
+    constructor(compilerInfo: CompilerInfo, env: CompilationEnvironment) {
         this.compiler = compilerInfo;
         this.env = env;
 
@@ -99,9 +102,9 @@ export class BuildEnvSetupBase {
     }
 
     async setup(
-        key,
+        key: CacheKey,
         dirPath: string,
-        selectedLibraries: Record<string, LibraryVersion>,
+        selectedLibraries: Record<string, VersionInfo>,
         binary: boolean,
     ): Promise<BuildEnvDownloadInfo[]> {
         return [];
@@ -143,7 +146,7 @@ export class BuildEnvSetupBase {
         return false;
     }
 
-    getLibcxx(key) {
+    getLibcxx(key: CacheKey): string {
         const match = this.compiler.options.match(/-stdlib=(\S*)/i);
         if (match) {
             return match[1];
@@ -160,7 +163,7 @@ export class BuildEnvSetupBase {
         }
     }
 
-    getTarget(key): string {
+    getTarget(key: CacheKey): string {
         if (!this.compilerSupportsX86) return '';
         if (this.compilerArch) return this.compilerArch;
 
@@ -179,7 +182,7 @@ export class BuildEnvSetupBase {
         return 'x86_64';
     }
 
-    hasBinariesToLink(details: LibraryVersion) {
+    hasBinariesToLink(details: VersionInfo) {
         return (
             details.libpath.length === 0 &&
             (details.staticliblink.length > 0 || details.liblink.length > 0) &&
@@ -187,11 +190,11 @@ export class BuildEnvSetupBase {
         );
     }
 
-    hasPackagedHeaders(details: LibraryVersion) {
+    hasPackagedHeaders(details: VersionInfo) {
         return !!details.packagedheaders;
     }
 
-    shouldDownloadPackage(details: LibraryVersion) {
+    shouldDownloadPackage(details: VersionInfo) {
         return this.hasPackagedHeaders(details) || this.hasBinariesToLink(details);
     }
 }
diff --git a/lib/buildenvsetup/ceconan-fortran.ts b/lib/buildenvsetup/ceconan-fortran.ts
index be4b8f776..dab60509f 100644
--- a/lib/buildenvsetup/ceconan-fortran.ts
+++ b/lib/buildenvsetup/ceconan-fortran.ts
@@ -29,7 +29,7 @@ export class BuildEnvSetupCeConanFortranDirect extends BuildEnvSetupCeConanDirec
         return 'ceconan-fortran';
     }
 
-    override async getConanBuildProperties(key): Promise<ConanBuildProperties> {
+    override async getConanBuildProperties(/*key*/): Promise<ConanBuildProperties> {
         const arch = this.getCompilerArch() || 'x86_64';
         const libcxx = 'std';
         const stdver = '';
diff --git a/lib/buildenvsetup/ceconan.ts b/lib/buildenvsetup/ceconan.ts
index 5b2a48048..41f24fff7 100644
--- a/lib/buildenvsetup/ceconan.ts
+++ b/lib/buildenvsetup/ceconan.ts
@@ -30,11 +30,14 @@ import request from 'request';
 import tar from 'tar-stream';
 import _ from 'underscore';
 
-import {LibraryVersion} from '../../types/libraries/libraries.interfaces.js';
+import {CacheKey} from '../../types/compilation/compilation.interfaces.js';
+import {CompilerInfo} from '../../types/compiler.interfaces.js';
 import {logger} from '../logger.js';
+import {VersionInfo} from '../options-handler.js';
 
 import {BuildEnvSetupBase} from './base.js';
 import type {BuildEnvDownloadInfo} from './buildenv.interfaces.js';
+// import { CompilationEnvironment } from '../compilation-env.js';
 
 export type ConanBuildProperties = {
     os: string;
@@ -56,11 +59,11 @@ export class BuildEnvSetupCeConanDirect extends BuildEnvSetupBase {
         return 'ceconan';
     }
 
-    constructor(compilerInfo, env) {
+    constructor(compilerInfo: CompilerInfo, env) {
         super(compilerInfo, env);
 
-        this.host = compilerInfo.buildenvsetup.props('host', false);
-        this.onlyonstaticliblink = compilerInfo.buildenvsetup.props('onlyonstaticliblink', false);
+        this.host = compilerInfo.buildenvsetup!.props('host', '');
+        this.onlyonstaticliblink = compilerInfo.buildenvsetup!.props('onlyonstaticliblink', '');
         this.extractAllToRoot = false;
 
         if (env.debug) request.debug = true;
@@ -121,7 +124,12 @@ export class BuildEnvSetupCeConanDirect extends BuildEnvSetupBase {
         }
     }
 
-    async downloadAndExtractPackage(libId, version, downloadPath, packageUrl): Promise<BuildEnvDownloadInfo> {
+    async downloadAndExtractPackage(
+        libId,
+        version,
+        downloadPath: string,
+        packageUrl: string,
+    ): Promise<BuildEnvDownloadInfo> {
         return new Promise((resolve, reject) => {
             const startTime = process.hrtime.bigint();
             const extract = tar.extract();
@@ -207,7 +215,7 @@ export class BuildEnvSetupCeConanDirect extends BuildEnvSetupBase {
         });
     }
 
-    async getConanBuildProperties(key): Promise<ConanBuildProperties> {
+    async getConanBuildProperties(key: CacheKey): Promise<ConanBuildProperties> {
         const arch = this.getTarget(key);
         const libcxx = this.getLibcxx(key);
         const stdver = '';
@@ -239,7 +247,11 @@ export class BuildEnvSetupCeConanDirect extends BuildEnvSetupBase {
         });
     }
 
-    async download(key, dirPath, libraryDetails): Promise<BuildEnvDownloadInfo[]> {
+    async download(
+        key: CacheKey,
+        dirPath: string,
+        libraryDetails: Record<string, VersionInfo>,
+    ): Promise<BuildEnvDownloadInfo[]> {
         const allDownloads: Promise<BuildEnvDownloadInfo>[] = [];
         const allLibraryBuilds: any = [];
 
@@ -285,10 +297,10 @@ export class BuildEnvSetupCeConanDirect extends BuildEnvSetupBase {
     }
 
     override async setup(
-        key,
-        dirPath,
-        libraryDetails: Record<string, LibraryVersion>,
-        binary,
+        key: CacheKey,
+        dirPath: string,
+        libraryDetails: Record<string, VersionInfo>,
+        binary: boolean,
     ): Promise<BuildEnvDownloadInfo[]> {
         if (!this.host) return [];
 
@@ -296,7 +308,7 @@ export class BuildEnvSetupCeConanDirect extends BuildEnvSetupBase {
 
         const librariesToDownload = _.pick(libraryDetails, details => {
             return this.shouldDownloadPackage(details);
-        }) as Record<string, LibraryVersion>;
+        }) as Record<string, VersionInfo>;
 
         return this.download(key, dirPath, librariesToDownload);
     }
diff --git a/lib/cache/multi.ts b/lib/cache/multi.ts
index e909d1d7e..c49508b22 100644
--- a/lib/cache/multi.ts
+++ b/lib/cache/multi.ts
@@ -33,7 +33,7 @@ import {BaseCache} from './base.js';
 export class MultiCache extends BaseCache {
     private readonly upstream: BaseCache[];
 
-    constructor(cacheName, ...upstream) {
+    constructor(cacheName: string, ...upstream: any[]) {
         super(cacheName, 'Multi', 'multi');
         this.countersEnabled = false;
         this.upstream = upstream;
diff --git a/lib/cache/null.ts b/lib/cache/null.ts
index f3786a331..11a644ca8 100644
--- a/lib/cache/null.ts
+++ b/lib/cache/null.ts
@@ -27,7 +27,7 @@ import type {GetResult} from '../../types/cache.interfaces.js';
 import {BaseCache} from './base.js';
 
 export class NullCache extends BaseCache {
-    constructor(cacheName) {
+    constructor(cacheName: string) {
         super(cacheName, 'Null', 'null');
     }
 
diff --git a/lib/cache/on-disk.ts b/lib/cache/on-disk.ts
index aaeb8b66e..ac15c24b9 100644
--- a/lib/cache/on-disk.ts
+++ b/lib/cache/on-disk.ts
@@ -34,9 +34,11 @@ import {logger} from '../logger.js';
 import {BaseCache} from './base.js';
 
 // With thanks to https://gist.github.com/kethinov/6658166
-function getAllFiles(root: string, dir?: string) {
+type relFile = {name: string; fullPath: string};
+
+function getAllFiles(root: string, dir?: string): Array<relFile> {
     const actualDir = dir || root;
-    return fs.readdirSync(actualDir).reduce((files: Array<string>, file: string) => {
+    return fs.readdirSync(actualDir).reduce((files: Array<relFile>, file: string) => {
         const fullPath = path.join(actualDir, file);
         const name = path.relative(root, fullPath);
         const isDirectory = fs.statSync(fullPath).isDirectory();
@@ -80,9 +82,14 @@ export class OnDiskCache extends BaseCache {
                 };
             })
             .filter(Boolean);
+
         // Sort oldest first
+        // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+        // @ts-ignore filter(Boolean) should have sufficed but doesn't
         info.sort((x, y) => x.sort - y.sort);
         for (const i of info) {
+            // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+            // @ts-ignore
             this.cache.set(i.key, i.data);
         }
     }
diff --git a/lib/cfg/cfg-parsers/base.ts b/lib/cfg/cfg-parsers/base.ts
index 4174378d5..0b1f8c56f 100644
--- a/lib/cfg/cfg-parsers/base.ts
+++ b/lib/cfg/cfg-parsers/base.ts
@@ -142,7 +142,7 @@ export class BaseCFGParser {
         return null;
     }
 
-    protected filterTextSection(data: AssemblyLine[]) {
+    protected filterTextSection(data: AssemblyLine[]): AssemblyLine[] {
         let useCurrentSection = true;
         const result: AssemblyLine[] = [];
         for (const i in data) {
diff --git a/lib/cfg/cfg-parsers/clang.ts b/lib/cfg/cfg-parsers/clang.ts
index 22141a7e6..b9da99ad3 100644
--- a/lib/cfg/cfg-parsers/clang.ts
+++ b/lib/cfg/cfg-parsers/clang.ts
@@ -36,7 +36,8 @@ export class ClangCFGParser extends BaseCFGParser {
 
     override filterData(assembly: ResultLine[]) {
         const jmpLabelRegex = /\.LBB\d+_\d+:/;
-        const isCode = x => x && x.text && (x.source !== null || jmpLabelRegex.test(x.text) || this.isFunctionName(x));
+        const isCode = (x: ResultLine) =>
+            x && x.text && (x.source !== null || jmpLabelRegex.test(x.text) || this.isFunctionName(x));
 
         const removeComments = (x: ResultLine) => {
             const pos_x86 = x.text.indexOf('# ');
diff --git a/lib/cfg/cfg-parsers/gcc.ts b/lib/cfg/cfg-parsers/gcc.ts
index 379c8f0cf..089736b1c 100644
--- a/lib/cfg/cfg-parsers/gcc.ts
+++ b/lib/cfg/cfg-parsers/gcc.ts
@@ -26,7 +26,7 @@ import _ from 'underscore';
 
 import type {ResultLine} from '../../../types/resultline/resultline.interfaces.js';
 
-import {BaseCFGParser} from './base.js';
+import {AssemblyLine, BaseCFGParser} from './base.js';
 
 export class GccCFGParser extends BaseCFGParser {
     static override get key() {
@@ -35,7 +35,8 @@ export class GccCFGParser extends BaseCFGParser {
 
     override filterData(assembly: ResultLine[]) {
         const jmpLabelRegex = /\.L\d+:/;
-        const isCode = x => x && x.text && (x.source !== null || jmpLabelRegex.test(x.text) || this.isFunctionName(x));
+        const isCode = (x: AssemblyLine) =>
+            x && x.text && (x.source !== null || jmpLabelRegex.test(x.text) || this.isFunctionName(x));
         return this.filterTextSection(assembly).map(_.clone).filter(isCode);
     }
 
diff --git a/lib/clientstate-normalizer.ts b/lib/clientstate-normalizer.ts
index 23cbbac64..2141b95ec 100644
--- a/lib/clientstate-normalizer.ts
+++ b/lib/clientstate-normalizer.ts
@@ -22,8 +22,34 @@
 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 // POSSIBILITY OF SUCH DAMAGE.
 
+import {assert} from './assert.js';
 import {ClientState, ClientStateCompiler, ClientStateConformanceView, ClientStateExecutor} from './clientstate.js';
 
+type BasicGoldenLayoutStruct = {
+    type: string;
+    width?: number;
+    height?: number;
+    isClosable?: boolean;
+    reorderEnabled?: boolean;
+    content: Array<BasicGoldenLayoutStruct | GoldenLayoutComponentStruct>;
+};
+
+type GoldenLayoutComponentStruct = {
+    type: string;
+    title?: string;
+    componentName: string;
+    componentState: any;
+    isClosable: boolean;
+    reorderEnabled: boolean;
+};
+
+type GoldenLayoutRootStruct = {
+    settings?: any;
+    dimensions?: Record<string, number>;
+    labels?: Record<string, string>;
+    content?: Array<BasicGoldenLayoutStruct>;
+};
+
 export class ClientStateNormalizer {
     normalized = new ClientState();
     rootContent = null;
@@ -144,6 +170,7 @@ export class ClientStateNormalizer {
                     return;
                 }
             } else {
+                // throw new Error("No component.componentState.id " + JSON.stringify(component));
                 compiler = new ClientStateCompiler();
 
                 if (component.componentState.source) {
@@ -253,7 +280,7 @@ export class ClientStateNormalizer {
 }
 
 class GoldenLayoutComponents {
-    createSourceComponent(session, customSessionId?) {
+    createSourceComponent(session, customSessionId?): GoldenLayoutComponentStruct {
         const editor = {
             type: 'component',
             componentName: 'codeEditor',
@@ -280,7 +307,7 @@ class GoldenLayoutComponents {
         }
     }
 
-    createTreeComponent(tree, customTreeId?) {
+    createTreeComponent(tree, customTreeId?): GoldenLayoutComponentStruct {
         const treeComponent = {
             type: 'component',
             componentName: 'tree',
@@ -304,7 +331,7 @@ class GoldenLayoutComponents {
         return treeComponent;
     }
 
-    createAstComponent(session, compilerIndex, customSessionId?) {
+    createAstComponent(session, compilerIndex, customSessionId?): GoldenLayoutComponentStruct {
         return {
             type: 'component',
             componentName: 'ast',
@@ -317,7 +344,7 @@ class GoldenLayoutComponents {
         };
     }
 
-    createOptComponent(session, compilerIndex, customSessionId?) {
+    createOptComponent(session, compilerIndex, customSessionId?): GoldenLayoutComponentStruct {
         return {
             type: 'component',
             componentName: 'opt',
@@ -329,7 +356,7 @@ class GoldenLayoutComponents {
             reorderEnabled: true,
         };
     }
-    createStackUsageComponent(session, compilerIndex, customSessionId?) {
+    createStackUsageComponent(session, compilerIndex, customSessionId?): GoldenLayoutComponentStruct {
         return {
             type: 'component',
             componentName: 'stackusage',
@@ -342,7 +369,7 @@ class GoldenLayoutComponents {
         };
     }
 
-    createCfgComponent(session, compilerIndex, customSessionId?) {
+    createCfgComponent(session, compilerIndex, customSessionId?): GoldenLayoutComponentStruct {
         return {
             type: 'component',
             componentName: 'opt',
@@ -359,7 +386,7 @@ class GoldenLayoutComponents {
         };
     }
 
-    createGccDumpComponent(session, compilerIndex, customSessionId?) {
+    createGccDumpComponent(session, compilerIndex, customSessionId?): GoldenLayoutComponentStruct {
         return {
             type: 'component',
             componentName: 'gccdump',
@@ -372,7 +399,7 @@ class GoldenLayoutComponents {
         };
     }
 
-    createCompilerOutComponent(session, compilerIndex, customSessionId?) {
+    createCompilerOutComponent(session, compilerIndex, customSessionId?): GoldenLayoutComponentStruct {
         return {
             type: 'component',
             componentName: 'output',
@@ -387,7 +414,7 @@ class GoldenLayoutComponents {
         };
     }
 
-    createToolComponent(session, compilerIndex, toolId, args, stdin, customSessionId?) {
+    createToolComponent(session, compilerIndex, toolId, args, stdin, customSessionId?): GoldenLayoutComponentStruct {
         return {
             type: 'component',
             componentName: 'tool',
@@ -403,7 +430,7 @@ class GoldenLayoutComponents {
         };
     }
 
-    createConformanceViewComponent(session, conformanceview, customSessionId?) {
+    createConformanceViewComponent(session, conformanceview, customSessionId?): GoldenLayoutComponentStruct {
         return {
             type: 'component',
             componentName: 'conformance',
@@ -422,7 +449,7 @@ class GoldenLayoutComponents {
         return {...filters};
     }
 
-    createCompilerComponent(session, compiler, customSessionId?, idxCompiler?) {
+    createSourceCompilerComponent(session, compiler, customSessionId?, idxCompiler?) {
         return {
             type: 'component',
             componentName: 'compiler',
@@ -520,7 +547,7 @@ class GoldenLayoutComponents {
         };
     }
 
-    createSpecialOutputComponent(viewtype, session, idxCompiler, customSessionId?) {
+    createSpecialOutputComponent(viewtype, session, idxCompiler, customSessionId?): GoldenLayoutComponentStruct {
         if (viewtype === 'ast') {
             return this.createAstComponent(session, idxCompiler + 1, customSessionId);
         } else if (viewtype === 'opt') {
@@ -533,10 +560,12 @@ class GoldenLayoutComponents {
             return this.createGccDumpComponent(session, idxCompiler + 1, customSessionId);
         } else if (viewtype === 'compilerOutput') {
             return this.createCompilerOutComponent(session, idxCompiler + 1, customSessionId);
+        } else {
+            throw new Error(`Unknown viewtype for compiler(${idxCompiler + 1}) ${viewtype}`);
         }
     }
 
-    createSpecialOutputComponentForTreeCompiler(viewtype, idxCompiler) {
+    createSpecialOutputComponentForTreeCompiler(viewtype, idxCompiler): GoldenLayoutComponentStruct {
         if (viewtype === 'ast') {
             return this.createAstComponent(null, idxCompiler + 1, false);
         } else if (viewtype === 'opt') {
@@ -549,10 +578,19 @@ class GoldenLayoutComponents {
             return this.createGccDumpComponent(null, idxCompiler + 1, false);
         } else if (viewtype === 'compilerOutput') {
             return this.createCompilerOutComponent(null, idxCompiler + 1, false);
+        } else {
+            throw new Error(`Unknown viewtype (for tree compiler ${idxCompiler + 1}) ${viewtype}`);
         }
     }
 
-    createToolComponentForTreeCompiler(tree, compilerIndex, toolId, args, stdin, customTreeId?) {
+    createToolComponentForTreeCompiler(
+        tree,
+        compilerIndex,
+        toolId,
+        args,
+        stdin,
+        customTreeId?,
+    ): GoldenLayoutComponentStruct {
         return {
             type: 'component',
             componentName: 'tool',
@@ -570,17 +608,32 @@ class GoldenLayoutComponents {
 }
 
 export class ClientStateGoldenifier extends GoldenLayoutComponents {
-    golden: any = {};
+    golden: GoldenLayoutRootStruct = {};
 
-    newEmptyStack(width) {
+    newEmptyStack(width: number): BasicGoldenLayoutStruct {
         return {
             type: 'stack',
             width: width,
-            content: [] as any[],
+            content: [],
         };
     }
 
-    newStackWithOneComponent(width, component) {
+    newEmptyRow(height: number): BasicGoldenLayoutStruct {
+        return {
+            type: 'row',
+            height: height,
+            content: [],
+        };
+    }
+
+    newEmptyColumn(): BasicGoldenLayoutStruct {
+        return {
+            type: 'column',
+            content: [],
+        };
+    }
+
+    newStackWithOneComponent(width: number, component: GoldenLayoutComponentStruct): BasicGoldenLayoutStruct {
         return {
             type: 'stack',
             width: width,
@@ -588,46 +641,43 @@ export class ClientStateGoldenifier extends GoldenLayoutComponents {
         };
     }
 
-    newTreeFromTree(tree, width) {
+    newTreeFromTree(tree, width: number): BasicGoldenLayoutStruct {
         return this.newStackWithOneComponent(width, this.createTreeComponent(tree));
     }
 
-    newSourceStackFromSession(session, width) {
+    newSourceStackFromSession(session, width: number): BasicGoldenLayoutStruct {
         return this.newStackWithOneComponent(width, this.createSourceComponent(session));
     }
 
-    newAstStackFromCompiler(session, compilerIndex, width) {
+    newAstStackFromCompiler(session, compilerIndex: number, width: number): BasicGoldenLayoutStruct {
         return this.newStackWithOneComponent(width, this.createAstComponent(session, compilerIndex));
     }
 
-    newOptStackFromCompiler(session, compilerIndex, width) {
+    newOptStackFromCompiler(session, compilerIndex: number, width: number): BasicGoldenLayoutStruct {
         return this.newStackWithOneComponent(width, this.createOptComponent(session, compilerIndex));
     }
 
-    newCfgStackFromCompiler(session, compilerIndex, width) {
+    newCfgStackFromCompiler(session, compilerIndex: number, width: number): BasicGoldenLayoutStruct {
         return this.newStackWithOneComponent(width, this.createCfgComponent(session, compilerIndex));
     }
 
-    newGccDumpStackFromCompiler(session, compilerIndex, width) {
+    newGccDumpStackFromCompiler(session, compilerIndex, width: number): BasicGoldenLayoutStruct {
         return this.newStackWithOneComponent(width, this.createGccDumpComponent(session, compilerIndex));
     }
 
-    newCompilerOutStackFromCompiler(session, compilerIndex, width) {
+    newCompilerOutStackFromCompiler(session, compilerIndex, width: number): BasicGoldenLayoutStruct {
         return this.newStackWithOneComponent(width, this.createCompilerOutComponent(session, compilerIndex));
     }
 
-    newToolStackFromCompiler(session, compilerIndex, toolId, args, stdin, width) {
+    newToolStackFromCompiler(session, compilerIndex, toolId, args, stdin, width: number): BasicGoldenLayoutStruct {
         return this.newStackWithOneComponent(
             width,
             this.createToolComponent(session, compilerIndex, toolId, args, stdin),
         );
     }
 
-    newConformanceViewStack(session, width, conformanceview) {
-        const stack = this.newStackWithOneComponent(
-            width,
-            this.createConformanceViewComponent(session, conformanceview),
-        );
+    newConformanceViewStack(session, width: number, conformanceview): BasicGoldenLayoutStruct {
+        const component = this.createConformanceViewComponent(session, conformanceview);
 
         for (const compiler of conformanceview.compilers) {
             const compjson = {
@@ -635,24 +685,24 @@ export class ClientStateGoldenifier extends GoldenLayoutComponents {
                 options: compiler.options,
             };
 
-            stack.content[0].componentState.compilers.push(compjson);
+            component.componentState.compilers.push(compjson);
         }
 
-        return stack;
+        return this.newStackWithOneComponent(width, component);
     }
 
-    newCompilerStackFromSession(session, compiler, width) {
+    newCompilerStackFromSession(session, compiler, width: number): BasicGoldenLayoutStruct {
         return this.newStackWithOneComponent(
             width,
-            this.createCompilerComponent(session, compiler, false, compiler._internalId),
+            this.createSourceCompilerComponent(session, compiler, false, compiler._internalId),
         );
     }
 
-    newExecutorStackFromSession(session, executor, width) {
+    newExecutorStackFromSession(session, executor, width: number): BasicGoldenLayoutStruct {
         return this.newStackWithOneComponent(width, this.createExecutorComponent(session, executor));
     }
 
-    createSourceContentArray(state, left, right) {
+    createSourceContentArray(state, left, right): BasicGoldenLayoutStruct[] {
         if (left.session === right.session) {
             return [this.createPresentationModeComponents(state.sessions[left.session], 1, 100)];
         } else {
@@ -817,7 +867,7 @@ export class ClientStateGoldenifier extends GoldenLayoutComponents {
 
         for (let idxCompiler = 0; idxCompiler < session.compilers.length; idxCompiler++) {
             const compiler = session.compilers[idxCompiler];
-            stack.content.push(this.createCompilerComponent(session, compiler, customSessionId));
+            stack.content.push(this.createSourceCompilerComponent(session, compiler, customSessionId));
 
             for (const viewtype of compiler.specialoutputs) {
                 stack.content.push(this.createSpecialOutputComponent(viewtype, session, idxCompiler, customSessionId));
@@ -862,7 +912,7 @@ export class ClientStateGoldenifier extends GoldenLayoutComponents {
         return slides;
     }
 
-    treeLayoutFromClientstate(state) {
+    treeLayoutFromClientstate(state, leaveSomeSpace: boolean): BasicGoldenLayoutStruct | undefined {
         const firstTree = state.trees[0];
         const leftSide = this.newTreeFromTree(firstTree, 25);
         const middle = this.newEmptyStack(40);
@@ -870,19 +920,49 @@ export class ClientStateGoldenifier extends GoldenLayoutComponents {
             middle.content.push(this.createSourceComponent(session));
         }
 
-        const rightSide = this.newEmptyStack(40);
+        let rightSide;
+        let contentRow;
+        let extraRow;
+
+        if (leaveSomeSpace) {
+            contentRow = this.newEmptyRow(50);
+            extraRow = this.newEmptyRow(50);
+            rightSide = this.newEmptyColumn();
+            rightSide.content.push(contentRow, extraRow);
+        } else {
+            rightSide = this.newEmptyStack(40);
+            contentRow = this.newEmptyRow(100);
+        }
+
         let idxCompiler = 0;
         for (const compiler of firstTree.compilers) {
-            rightSide.content.push(this.createCompilerComponentForTree(firstTree, compiler));
+            contentRow.content.push(this.createCompilerComponentForTree(firstTree, compiler, false, idxCompiler + 1));
 
             for (const specialOutput of compiler.specialoutputs) {
-                rightSide.content.push(this.createSpecialOutputComponentForTreeCompiler(specialOutput, idxCompiler));
+                contentRow.content.push(
+                    this.createSpecialOutputComponentForTreeCompiler(specialOutput, idxCompiler + 1),
+                );
             }
 
             idxCompiler++;
         }
 
+        rightSide.content.push(contentRow);
+
+        assert(this.golden.content);
         this.golden.content[0].content.push(leftSide, middle, rightSide);
+
+        return extraRow;
+    }
+
+    hasEditorCompilersOrExecutors(state) {
+        for (const session of state.sessions) {
+            if (session.compilers.length > 0 || session.executors.length > 0) {
+                return true;
+            }
+        }
+
+        return false;
     }
 
     fromClientState(state) {
@@ -929,35 +1009,98 @@ export class ClientStateGoldenifier extends GoldenLayoutComponents {
         };
 
         if (state.trees.length > 0) {
-            this.treeLayoutFromClientstate(state);
+            const hasOtherPanes = this.hasEditorCompilersOrExecutors(state);
+            const extraRow = this.treeLayoutFromClientstate(state, hasOtherPanes);
+
+            if (!hasOtherPanes || !extraRow) return;
+
+            const treeCompilerCount = state.trees[0].compilers.length;
+            const treeExecutorCount = state.trees[0].executors.length;
+
+            for (let idxSession = 0; idxSession < state.sessions.length; idxSession++) {
+                const session = state.sessions[idxSession];
+
+                if (session.compilers.length > 0 || session.executors.length > 0) {
+                    const rightCol: BasicGoldenLayoutStruct = {
+                        type: 'column',
+                        content: [],
+                    };
+                    const rightStack = this.newEmptyStack(100);
+
+                    for (let idxCompiler = 0; idxCompiler < session.compilers.length; idxCompiler++) {
+                        const compiler = session.compilers[idxCompiler];
+                        const compilerComponent = this.createSourceCompilerComponent(
+                            session,
+                            compiler,
+                            false,
+                            treeCompilerCount + idxCompiler + 1,
+                        );
+                        rightStack.content.push(compilerComponent);
+
+                        for (const viewtype of compiler.specialoutputs) {
+                            rightStack.content.push(
+                                this.createSpecialOutputComponent(
+                                    viewtype,
+                                    session,
+                                    treeCompilerCount + idxCompiler + 1,
+                                ),
+                            );
+                        }
+
+                        for (const tool of compiler.tools) {
+                            rightStack.content.push(
+                                this.createToolComponent(
+                                    session,
+                                    treeCompilerCount + idxCompiler + 1,
+                                    tool.id,
+                                    tool.args,
+                                    tool.stdin,
+                                ),
+                            );
+                        }
+                    }
+
+                    for (let idxExecutor = 0; idxExecutor < session.executors.length; idxExecutor++) {
+                        const executor = session.compilers[idxExecutor];
+                        const executorComponent = this.createExecutorComponent(
+                            session,
+                            executor,
+                            treeExecutorCount + idxExecutor + 1,
+                        );
+                        rightStack.content.push(executorComponent);
+                    }
+
+                    rightCol.content.push(rightStack);
+
+                    extraRow.content.push({
+                        type: 'row',
+                        content: [rightCol],
+                    });
+                }
+            }
+
             return;
         }
 
+        assert(this.golden.content);
+
         if (state.sessions.length > 1) {
             const sessionWidth = 100 / state.sessions.length;
 
             for (let idxSession = 0; idxSession < state.sessions.length; idxSession++) {
                 const session = state.sessions[idxSession];
 
-                this.golden.content[0].content[idxSession] = {
-                    type: 'column',
-                    isClosable: true,
-                    reorderEnabled: true,
-                    width: sessionWidth,
-                    content: [
-                        {
-                            type: 'row',
-                            content: [],
-                        },
-                        {
-                            type: 'row',
-                            content: [],
-                        },
-                    ],
+                const topRow: BasicGoldenLayoutStruct = {
+                    type: 'row',
+                    content: [],
+                };
+                const bottomRow: BasicGoldenLayoutStruct = {
+                    type: 'row',
+                    content: [],
                 };
 
                 const stack = this.newSourceStackFromSession(session, 100);
-                this.golden.content[0].content[idxSession].content[0].content.push(stack);
+                topRow.content.push(stack);
 
                 const compilerWidth =
                     100 /
@@ -968,13 +1111,13 @@ export class ClientStateGoldenifier extends GoldenLayoutComponents {
 
                 if (session.conformanceview) {
                     const stack = this.newConformanceViewStack(session, compilerWidth, session.conformanceview);
-                    this.golden.content[0].content[idxSession].content[1].content.push(stack);
+                    bottomRow.content.push(stack);
                 }
 
                 for (let idxCompiler = 0; idxCompiler < session.compilers.length; idxCompiler++) {
                     const compiler = session.compilers[idxCompiler];
                     const stack = this.newCompilerStackFromSession(session, compiler, compilerWidth);
-                    this.golden.content[0].content[idxSession].content[1].content.push(stack);
+                    bottomRow.content.push(stack);
 
                     for (const viewtype of compiler.specialoutputs) {
                         const stack = this.newStackWithOneComponent(
@@ -983,7 +1126,7 @@ export class ClientStateGoldenifier extends GoldenLayoutComponents {
                         );
 
                         if (stack) {
-                            this.golden.content[0].content[idxSession].content[1].content.push(stack);
+                            bottomRow.content.push(stack);
                         }
                     }
 
@@ -996,15 +1139,25 @@ export class ClientStateGoldenifier extends GoldenLayoutComponents {
                             tool.stdin,
                             compilerWidth,
                         );
-                        this.golden.content[0].content[idxSession].content[1].content.push(stack);
+                        bottomRow.content.push(stack);
                     }
                 }
 
                 for (let idxExecutor = 0; idxExecutor < session.executors.length; idxExecutor++) {
                     const executor = session.executors[idxExecutor];
                     const stack = this.newExecutorStackFromSession(session, executor, compilerWidth);
-                    this.golden.content[0].content[idxSession].content[1].content.push(stack);
+                    bottomRow.content.push(stack);
                 }
+
+                const sessionColumn: BasicGoldenLayoutStruct = {
+                    type: 'column',
+                    isClosable: true,
+                    reorderEnabled: true,
+                    width: sessionWidth,
+                    content: [topRow, bottomRow],
+                };
+
+                this.golden.content[0].content[idxSession] = sessionColumn;
             }
         } else if (state.sessions.length === 1) {
             const session = state.sessions[0];
diff --git a/lib/compilation-env.ts b/lib/compilation-env.ts
index 9b16ab0b2..7999dcd61 100644
--- a/lib/compilation-env.ts
+++ b/lib/compilation-env.ts
@@ -41,12 +41,12 @@ import type {PropertyGetter} from './properties.interfaces.js';
 import {CompilerProps} from './properties.js';
 import {createStatsNoter, IStatsNoter} from './stats.js';
 
-type PropFunc = (string, any?) => any;
+type PropFunc = (s: string, a?: any) => any;
 
 export class CompilationEnvironment {
     ceProps: PropertyGetter;
-    compilationQueue: CompilationQueue;
-    compilerProps: CompilerProps;
+    compilationQueue: CompilationQueue | undefined;
+    compilerProps: PropFunc;
     okOptions: RegExp;
     badOptions: RegExp;
     cache: Cache;
@@ -60,7 +60,7 @@ export class CompilationEnvironment {
     statsNoter: IStatsNoter;
     private logCompilerCacheAccesses: boolean;
 
-    constructor(compilerProps, compilationQueue, doCache) {
+    constructor(compilerProps: CompilerProps, compilationQueue: CompilationQueue | undefined, doCache?: boolean) {
         this.ceProps = compilerProps.ceProps;
         this.compilationQueue = compilationQueue;
         this.compilerProps = compilerProps.get.bind(compilerProps);
@@ -174,7 +174,7 @@ export class CompilationEnvironment {
     }
 
     enqueue<T>(job: Job<T>, options?: EnqueueOptions) {
-        return this.compilationQueue.enqueue(job, options);
+        if (this.compilationQueue) return this.compilationQueue.enqueue(job, options);
     }
 
     findBadOptions(options: string[]) {
diff --git a/lib/compilation-queue.ts b/lib/compilation-queue.ts
index 4ad4c84c5..b3b6ee4d4 100644
--- a/lib/compilation-queue.ts
+++ b/lib/compilation-queue.ts
@@ -28,6 +28,8 @@ import {executionAsyncId} from 'async_hooks';
 import {default as Queue} from 'p-queue';
 import PromClient from 'prom-client';
 
+import {PropertyGetter} from './properties.interfaces.js';
+
 // globals as essentially the compilation queue is a singleton, and if we make them members of the queue, tests fail as
 // when we create a second queue, the previous counters are still registered.
 const queueEnqueued = new PromClient.Counter({
@@ -68,10 +70,10 @@ export class CompilationQueue {
         this._staleAfterMs = staleAfterMs;
     }
 
-    static fromProps(ceProps) {
+    static fromProps(ceProps: PropertyGetter) {
         return new CompilationQueue(
             ceProps('maxConcurrentCompiles', 1),
-            ceProps('compilationEnvTimeoutMs'),
+            ceProps('compilationEnvTimeoutMs', 300_000),
             ceProps('compilationStaleAfterMs', 60_000),
         );
     }
diff --git a/lib/compilers/ada.ts b/lib/compilers/ada.ts
index 1a84ae491..98e6b42e6 100644
--- a/lib/compilers/ada.ts
+++ b/lib/compilers/ada.ts
@@ -56,7 +56,7 @@ export class AdaCompiler extends BaseCompiler {
         this.compiler.supportsGnatDebugViews = true;
     }
 
-    override getExecutableFilename(dirPath: string, outputFilebase: string, key?) {
+    override getExecutableFilename(dirPath: string, outputFilebase: string) {
         // The name here must match the value used in the pragma Source_File
         // in the user provided source.
         return path.join(dirPath, 'example');
diff --git a/lib/compilers/cerberus.ts b/lib/compilers/cerberus.ts
index 6dac7f15b..b73641e5d 100644
--- a/lib/compilers/cerberus.ts
+++ b/lib/compilers/cerberus.ts
@@ -24,7 +24,7 @@
 
 import path from 'path';
 
-import {BypassCache, ExecutionOptions} from '../../types/compilation/compilation.interfaces.js';
+import {BypassCache, CacheKey, ExecutionOptions} from '../../types/compilation/compilation.interfaces.js';
 import type {PreliminaryCompilerInfo} from '../../types/compiler.interfaces.js';
 import {ExecutableExecutionOptions} from '../../types/execution/execution.interfaces.js';
 import type {ParseFiltersAndOutputOptions} from '../../types/features/filters.interfaces.js';
@@ -87,7 +87,7 @@ export class CerberusCompiler extends BaseCompiler {
         return result;
     }
 
-    override async handleInterpreting(key, executeParameters: ExecutableExecutionOptions) {
+    override async handleInterpreting(key: CacheKey, executeParameters: ExecutableExecutionOptions) {
         const compileResult = await this.getOrBuildExecutable(key, BypassCache.None);
         if (compileResult.code === 0) {
             executeParameters.args = [
diff --git a/lib/compilers/d8.ts b/lib/compilers/d8.ts
index c7c1ab306..cd0b3c8c4 100644
--- a/lib/compilers/d8.ts
+++ b/lib/compilers/d8.ts
@@ -36,6 +36,7 @@ import {unwrap} from '../assert.js';
 import {BaseCompiler, SimpleOutputFilenameCompiler} from '../base-compiler.js';
 import {CompilationEnvironment} from '../compilation-env.js';
 import {logger} from '../logger.js';
+import '../global.js';
 
 import {JavaCompiler} from './java.js';
 import {KotlinCompiler} from './kotlin.js';
@@ -82,7 +83,7 @@ export class D8Compiler extends BaseCompiler implements SimpleOutputFilenameComp
     ): Promise<CompilationResult> {
         const preliminaryCompilePath = path.dirname(inputFilename);
         let outputFilename = '';
-        let initialResult;
+        let initialResult: CompilationResult | null = null;
 
         const javaCompiler = unwrap(
             global.handler_config.compileHandler.findCompiler('java', this.javaId),
@@ -136,7 +137,7 @@ export class D8Compiler extends BaseCompiler implements SimpleOutputFilenameComp
 
         // D8 should not run if initial compile stage failed, the JavaCompiler
         // result can be returned instead.
-        if (initialResult.code !== 0) {
+        if (initialResult && initialResult.code !== 0) {
             return initialResult;
         }
 
diff --git a/lib/compilers/dex2oat.ts b/lib/compilers/dex2oat.ts
index a32f616c4..fb2fcfe20 100644
--- a/lib/compilers/dex2oat.ts
+++ b/lib/compilers/dex2oat.ts
@@ -423,7 +423,7 @@ export class Dex2OatCompiler extends BaseCompiler {
         return {asm: segments};
     }
 
-    parseAsm(oatdumpOut) {
+    parseAsm(oatdumpOut: string) {
         const compileData: {
             insnSet?: string;
             insnSetFeatures?: string;
diff --git a/lib/compilers/hook.ts b/lib/compilers/hook.ts
index 14eb27b8d..50aa420a3 100644
--- a/lib/compilers/hook.ts
+++ b/lib/compilers/hook.ts
@@ -24,7 +24,7 @@
 
 import path from 'path';
 
-import type {CompilationResult, ExecutionOptions} from '../../types/compilation/compilation.interfaces.js';
+import type {CacheKey, CompilationResult, ExecutionOptions} from '../../types/compilation/compilation.interfaces.js';
 import type {PreliminaryCompilerInfo} from '../../types/compiler.interfaces.js';
 import type {ExecutableExecutionOptions} from '../../types/execution/execution.interfaces.js';
 import type {ParseFiltersAndOutputOptions} from '../../types/features/filters.interfaces.js';
@@ -55,7 +55,10 @@ export class HookCompiler extends BaseCompiler {
         return {HOOK_HOME: this.hook_home, ...env};
     }
 
-    override async handleInterpreting(key, executeParameters: ExecutableExecutionOptions): Promise<CompilationResult> {
+    override async handleInterpreting(
+        key: CacheKey,
+        executeParameters: ExecutableExecutionOptions,
+    ): Promise<CompilationResult> {
         executeParameters.env = this.addHookHome(executeParameters.env);
         return super.handleInterpreting(key, executeParameters);
     }
diff --git a/lib/compilers/java.ts b/lib/compilers/java.ts
index 63d1cc99a..465b7f789 100644
--- a/lib/compilers/java.ts
+++ b/lib/compilers/java.ts
@@ -28,7 +28,7 @@ import fs from 'fs-extra';
 import Semver from 'semver';
 
 import type {ParsedAsmResult, ParsedAsmResultLine} from '../../types/asmresult/asmresult.interfaces.js';
-import {BypassCache, CompilationResult} from '../../types/compilation/compilation.interfaces.js';
+import {BypassCache, CacheKey, CompilationResult} from '../../types/compilation/compilation.interfaces.js';
 import type {PreliminaryCompilerInfo} from '../../types/compiler.interfaces.js';
 import {ExecutableExecutionOptions} from '../../types/execution/execution.interfaces.js';
 import type {ParseFiltersAndOutputOptions} from '../../types/features/filters.interfaces.js';
@@ -131,7 +131,10 @@ export class JavaCompiler extends BaseCompiler implements SimpleOutputFilenameCo
         return ['-Xlint:all', '-encoding', 'utf8'];
     }
 
-    override async handleInterpreting(key, executeParameters: ExecutableExecutionOptions): Promise<CompilationResult> {
+    override async handleInterpreting(
+        key: CacheKey,
+        executeParameters: ExecutableExecutionOptions,
+    ): Promise<CompilationResult> {
         const compileResult = await this.getOrBuildExecutable(key, BypassCache.None);
         if (compileResult.code === 0) {
             const extraXXFlags: string[] = [];
diff --git a/lib/compilers/kotlin.ts b/lib/compilers/kotlin.ts
index c566dd43d..5afcfe193 100644
--- a/lib/compilers/kotlin.ts
+++ b/lib/compilers/kotlin.ts
@@ -22,7 +22,7 @@
 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 // POSSIBILITY OF SUCH DAMAGE.
 
-import {BypassCache, CompilationResult} from '../../types/compilation/compilation.interfaces.js';
+import {BypassCache, CacheKey, CompilationResult} from '../../types/compilation/compilation.interfaces.js';
 import type {PreliminaryCompilerInfo} from '../../types/compiler.interfaces.js';
 import {ExecutableExecutionOptions} from '../../types/execution/execution.interfaces.js';
 import type {ParseFiltersAndOutputOptions} from '../../types/features/filters.interfaces.js';
@@ -97,7 +97,10 @@ export class KotlinCompiler extends JavaCompiler implements SimpleOutputFilename
      *
      * TODO(supergrecko): Find a better fix than this bandaid for execution
      */
-    override async handleInterpreting(key, executeParameters: ExecutableExecutionOptions): Promise<CompilationResult> {
+    override async handleInterpreting(
+        key: CacheKey,
+        executeParameters: ExecutableExecutionOptions,
+    ): Promise<CompilationResult> {
         const alteredKey = {
             ...key,
             options: ['-include-runtime', '-d', 'example.jar'],
diff --git a/lib/compilers/r8.ts b/lib/compilers/r8.ts
index aaef45153..6b884d444 100644
--- a/lib/compilers/r8.ts
+++ b/lib/compilers/r8.ts
@@ -35,6 +35,7 @@ import {SimpleOutputFilenameCompiler} from '../base-compiler.js';
 import {CompilationEnvironment} from '../compilation-env.js';
 import {logger} from '../logger.js';
 
+import '../global.js';
 import {D8Compiler} from './d8.js';
 import {JavaCompiler} from './java.js';
 import {KotlinCompiler} from './kotlin.js';
@@ -60,7 +61,7 @@ export class R8Compiler extends D8Compiler implements SimpleOutputFilenameCompil
     ): Promise<CompilationResult> {
         const preliminaryCompilePath = path.dirname(inputFilename);
         let outputFilename = '';
-        let initialResult;
+        let initialResult: CompilationResult | null = null;
 
         const javaCompiler = unwrap(
             global.handler_config.compileHandler.findCompiler('java', this.javaId),
@@ -114,7 +115,7 @@ export class R8Compiler extends D8Compiler implements SimpleOutputFilenameCompil
 
         // R8 should not run if initial compile stage failed, the JavaCompiler
         // result can be returned instead.
-        if (initialResult.code !== 0) {
+        if (initialResult && initialResult.code !== 0) {
             return initialResult;
         }
 
diff --git a/lib/compilers/rga.ts b/lib/compilers/rga.ts
index 645dfc4bb..081de1a24 100644
--- a/lib/compilers/rga.ts
+++ b/lib/compilers/rga.ts
@@ -147,7 +147,7 @@ Please supply an ASIC from the following options:`,
             return {
                 code: -1,
                 okToCache: true,
-                filenameTransform: x => x,
+                filenameTransform: (x: string) => x,
                 stdout: asicSelection.error,
                 execTime: this.execTime(startTime, endTime),
             };
@@ -168,7 +168,7 @@ Please supply an ASIC from the following options:`,
             return {
                 code: -1,
                 okToCache: true,
-                filenameTransform: x => x,
+                filenameTransform: (x: string) => x,
                 stdout: 'Failed to emit intermediate SPIR-V result.',
                 execTime: this.execTime(startTime, endTime),
             };
diff --git a/lib/compilers/typescript-native.ts b/lib/compilers/typescript-native.ts
index 4c145cf18..1990ab3b6 100644
--- a/lib/compilers/typescript-native.ts
+++ b/lib/compilers/typescript-native.ts
@@ -26,6 +26,7 @@ import path from 'path';
 
 import Semver from 'semver';
 
+import {CacheKey} from '../../types/compilation/compilation.interfaces.js';
 import {LLVMIrBackendOptions} from '../../types/compilation/ir.interfaces.js';
 import type {PreliminaryCompilerInfo} from '../../types/compiler.interfaces.js';
 import {ExecutableExecutionOptions} from '../../types/execution/execution.interfaces.js';
@@ -119,7 +120,7 @@ export class TypeScriptNativeCompiler extends BaseCompiler {
         return this.llvmIr.process(output.stderr.map(l => l.text).join('\n'), irOptions);
     }
 
-    override async handleInterpreting(key, executeParameters: ExecutableExecutionOptions) {
+    override async handleInterpreting(key: CacheKey, executeParameters: ExecutableExecutionOptions) {
         executeParameters.args = [
             '--emit=jit',
             this.tscSharedLib ? '--shared-libs=' + this.tscSharedLib : '-nogc',
diff --git a/lib/compilers/wine-vc.ts b/lib/compilers/wine-vc.ts
index 570600509..95c05c84b 100644
--- a/lib/compilers/wine-vc.ts
+++ b/lib/compilers/wine-vc.ts
@@ -89,7 +89,7 @@ export class WineVcCompiler extends BaseCompiler {
             const mapFilename = outputFilename + '.map';
             const mapFileReader = new MapFileReaderVS(mapFilename);
 
-            (filters as any).preProcessBinaryAsmLines = asmLines => {
+            filters.preProcessBinaryAsmLines = (asmLines: string[]) => {
                 const reconstructor = new PELabelReconstructor(asmLines, false, mapFileReader);
                 reconstructor.run('output.s.obj');
 
diff --git a/lib/handlers/compile.ts b/lib/handlers/compile.ts
index 445d24203..83406a2f7 100644
--- a/lib/handlers/compile.ts
+++ b/lib/handlers/compile.ts
@@ -73,7 +73,7 @@ function initialise(compilerEnv: CompilationEnvironment) {
 
     let cyclesBusy = 0;
     setInterval(() => {
-        const status = compilerEnv.compilationQueue.status();
+        const status = compilerEnv.compilationQueue!.status();
         if (status.busy) {
             cyclesBusy++;
             logger.warn(
@@ -524,17 +524,17 @@ export class CompileHandler implements ICompileHandler {
             if (req.body.files === undefined) throw new Error('Missing files property');
 
             this.cmakeCounter.inc({language: compiler.lang.id});
-            const options = this.parseRequest(req, compiler);
+            const parsedRequest = this.parseRequest(req, compiler);
             this.compilerEnv.statsNoter.noteCompilation(
                 compiler.getInfo().id,
-                options,
+                parsedRequest,
                 req.body.files as FiledataPair[],
                 KnownBuildMethod.CMake,
             );
             compiler
                 // Backwards compatibility: bypassCache used to be a boolean.
                 // Convert a boolean input to an enum's underlying numeric value
-                .cmake(req.body.files, options, req.body.bypassCache * 1)
+                .cmake(req.body.files, parsedRequest, req.body.bypassCache * 1)
                 .then(result => {
                     if (result.didExecute || (result.execResult && result.execResult.didExecute))
                         this.cmakeExecuteCounter.inc({language: compiler.lang.id});
diff --git a/lib/llvm-ir.ts b/lib/llvm-ir.ts
index 7f81c66e8..ab0c2e99e 100644
--- a/lib/llvm-ir.ts
+++ b/lib/llvm-ir.ts
@@ -28,6 +28,7 @@ import {LLVMIrBackendOptions} from '../types/compilation/ir.interfaces.js';
 import {ParseFiltersAndOutputOptions} from '../types/features/filters.interfaces.js';
 
 import {LLVMIRDemangler} from './demangler/llvm.js';
+import {PropertyGetter} from './properties.interfaces.js';
 import * as utils from './utils.js';
 
 type MetaNode = {
@@ -54,7 +55,7 @@ export class LlvmIrParser {
     private commentAtEOL: RegExp;
 
     constructor(
-        compilerProps,
+        compilerProps: PropertyGetter,
         private readonly irDemangler: LLVMIRDemangler,
     ) {
         this.maxIrLines = 5000;
diff --git a/lib/options-handler.ts b/lib/options-handler.ts
index 3e3384011..14c690a5b 100755
--- a/lib/options-handler.ts
+++ b/lib/options-handler.ts
@@ -43,6 +43,7 @@ import {asSafeVer, getHash, splitArguments, splitIntoArray} from './utils.js';
 
 // TODO: Figure out if same as libraries.interfaces.ts?
 export type VersionInfo = {
+    name?: string;
     version: string;
     staticliblink: string[];
     alias: string[];
diff --git a/lib/pe32-support.ts b/lib/pe32-support.ts
index 41455a851..127b7427c 100644
--- a/lib/pe32-support.ts
+++ b/lib/pe32-support.ts
@@ -142,14 +142,14 @@ export class PELabelReconstructor {
         let idx, info;
         for (idx = 0; idx < this.mapFileReader.segments.length; idx++) {
             info = this.mapFileReader.segments[idx];
-            if (systemUnits.has(info.unitName)) {
+            if (info.unitName && systemUnits.has(info.unitName)) {
                 this.deleteLinesBetweenAddresses(info.addressInt, info.addressInt + info.segmentLength);
             }
         }
 
         for (idx = 0; idx < this.mapFileReader.isegments.length; idx++) {
             info = this.mapFileReader.isegments[idx];
-            if (systemUnits.has(info.unitName)) {
+            if (info.unitName && systemUnits.has(info.unitName)) {
                 this.deleteLinesBetweenAddresses(info.addressInt, info.addressInt + info.segmentLength);
             }
         }
diff --git a/lib/stats.ts b/lib/stats.ts
index 4429b2763..67717352d 100644
--- a/lib/stats.ts
+++ b/lib/stats.ts
@@ -25,7 +25,8 @@
 import {StorageClass} from '@aws-sdk/client-s3';
 import ems from 'enhanced-ms';
 
-import {FiledataPair} from '../types/compilation/compilation.interfaces.js';
+import {CompileChildLibraries, FiledataPair} from '../types/compilation/compilation.interfaces.js';
+import {ConfiguredRuntimeTool} from '../types/execution/execution.interfaces.js';
 
 import {ParsedRequest} from './handlers/compile.js';
 import {logger} from './logger.js';
@@ -39,11 +40,11 @@ export enum KnownBuildMethod {
 }
 
 export interface IStatsNoter {
-    noteCompilation(compilerId: string, request: ParsedRequest, files: FiledataPair[], buildMethod: string);
+    noteCompilation(compilerId: string, request: ParsedRequest, files: FiledataPair[], buildMethod: string): void;
 }
 
 class NullStatsNoter implements IStatsNoter {
-    noteCompilation(compilerId: string, request: ParsedRequest, files: FiledataPair[], buildMethod: string) {}
+    noteCompilation(compilerId: string, request: ParsedRequest, files: FiledataPair[], buildMethod: string): void {}
 }
 
 // A type for storing only compilation information deemed non-identifying; that is, no source or execution options.
@@ -75,7 +76,7 @@ export function filterCompilerOptions(args: string[]): string[] {
 export function makeSafe(
     time: Date,
     compilerId: string,
-    request: ParsedRequest | any,
+    request: ParsedRequest,
     files: FiledataPair[],
     buildMethod: string,
 ): CompilationRecord {
@@ -99,14 +100,14 @@ export function makeSafe(
             ),
         ).map(item => `${item[0]}=${item[1] ? '1' : '0'}`),
         bypassCache: !!request.bypassCache,
-        libraries: (request.libraries || []).map(lib => lib.id + '/' + lib.version),
+        libraries: (request.libraries || []).map((lib: CompileChildLibraries) => lib.id + '/' + lib.version),
         tools: (request.tools || []).map(tool => tool.id),
         overrides: (request.backendOptions.overrides || [])
             .filter(item => item.name !== 'env' && item.value)
             .map(item => `${item.name}=${item.value}`),
         runtimeTools: (request.executeParameters.runtimeTools || [])
-            .filter(item => item.name !== 'env')
-            .map(item => item.name),
+            .filter((item: ConfiguredRuntimeTool) => item.name !== 'env')
+            .map((item: ConfiguredRuntimeTool) => item.name),
         buildMethod: buildMethod,
     };
 }
@@ -152,7 +153,7 @@ class StatsNoter implements IStatsNoter {
         }
     }
 
-    noteCompilation(compilerId: string, request: ParsedRequest, files: FiledataPair[], buildMethod: string) {
+    noteCompilation(compilerId: string, request: ParsedRequest, files: FiledataPair[], buildMethod: string): void {
         this._statsQueue.push(makeSafe(new Date(), compilerId, request, files, buildMethod));
         if (!this._flushJob) this._flushJob = setTimeout(() => this.flush(), this._flushAfterMs);
     }
diff --git a/lib/symbol-store.ts b/lib/symbol-store.ts
index 54ac6c5fa..da6645486 100644
--- a/lib/symbol-store.ts
+++ b/lib/symbol-store.ts
@@ -63,7 +63,7 @@ export class SymbolStore {
     softExclude(otherStore: SymbolStore) {
         for (const symbol in otherStore.uniqueSymbols) {
             let shouldExclude = false;
-            let checksymbol;
+            let checksymbol: string = '';
             for (checksymbol in this.uniqueSymbols) {
                 if (checksymbol.endsWith(symbol)) {
                     shouldExclude = true;
diff --git a/lib/tooling/base-tool.interface.ts b/lib/tooling/base-tool.interface.ts
index 03c1e3c69..98a3a645a 100755
--- a/lib/tooling/base-tool.interface.ts
+++ b/lib/tooling/base-tool.interface.ts
@@ -22,8 +22,8 @@
 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 // POSSIBILITY OF SUCH DAMAGE.
 
-import {Library} from '../../types/libraries/libraries.interfaces.js';
 import {Tool, ToolResult} from '../../types/tool.interfaces.js';
+import {OptionsHandlerLibrary} from '../options-handler.js';
 import {PropertyGetter} from '../properties.interfaces.js';
 
 export type ToolEnv = {
@@ -37,6 +37,6 @@ export interface ITool extends Tool {
         inputFilepath?: string,
         args?: string[],
         stdin?: string,
-        supportedLibraries?: Record<string, Library>,
+        supportedLibraries?: Record<string, OptionsHandlerLibrary>,
     ): Promise<ToolResult>;
 }
diff --git a/lib/tooling/base-tool.ts b/lib/tooling/base-tool.ts
index 8e4afed40..052c42163 100755
--- a/lib/tooling/base-tool.ts
+++ b/lib/tooling/base-tool.ts
@@ -29,11 +29,12 @@ import _ from 'underscore';
 
 import {ExecutionOptions} from '../../types/compilation/compilation.interfaces.js';
 import {UnprocessedExecResult} from '../../types/execution/execution.interfaces.js';
-import {Library, SelectedLibraryVersion} from '../../types/libraries/libraries.interfaces.js';
+import {SelectedLibraryVersion} from '../../types/libraries/libraries.interfaces.js';
 import {ResultLine} from '../../types/resultline/resultline.interfaces.js';
 import {ToolInfo, ToolResult} from '../../types/tool.interfaces.js';
 import * as exec from '../exec.js';
 import {logger} from '../logger.js';
+import {OptionsHandlerLibrary} from '../options-handler.js';
 import {parseOutput} from '../utils.js';
 
 import {ITool, ToolEnv} from './base-tool.interface.js';
@@ -110,7 +111,7 @@ export class BaseTool implements ITool {
     }
 
     // mostly copy&paste from base-compiler.js
-    findLibVersion(selectedLib: SelectedLibraryVersion, supportedLibraries: Record<string, Library>) {
+    findLibVersion(selectedLib: SelectedLibraryVersion, supportedLibraries: Record<string, OptionsHandlerLibrary>) {
         const foundLib = _.find(supportedLibraries, (o, libId) => libId === selectedLib.id);
         if (!foundLib) return false;
 
@@ -118,7 +119,10 @@ export class BaseTool implements ITool {
     }
 
     // mostly copy&paste from base-compiler.js
-    getIncludeArguments(libraries: SelectedLibraryVersion[], supportedLibraries: Record<string, Library>): string[] {
+    getIncludeArguments(
+        libraries: SelectedLibraryVersion[],
+        supportedLibraries: Record<string, OptionsHandlerLibrary>,
+    ): string[] {
         const includeFlag = '-I';
 
         return libraries.flatMap(selectedLib => {
@@ -129,7 +133,10 @@ export class BaseTool implements ITool {
         });
     }
 
-    getLibraryOptions(libraries: SelectedLibraryVersion[], supportedLibraries: Record<string, Library>): string[] {
+    getLibraryOptions(
+        libraries: SelectedLibraryVersion[],
+        supportedLibraries: Record<string, OptionsHandlerLibrary>,
+    ): string[] {
         return libraries.flatMap(selectedLib => {
             const foundVersion = this.findLibVersion(selectedLib, supportedLibraries);
             if (!foundVersion) return [];
@@ -143,7 +150,7 @@ export class BaseTool implements ITool {
         inputFilepath?: string,
         args?: string[],
         stdin?: string,
-        supportedLibraries?: Record<string, Library>,
+        supportedLibraries?: Record<string, OptionsHandlerLibrary>,
     ) {
         if (this.tool.name) {
             toolCounter.inc({
diff --git a/lib/tooling/clang-tidy-tool.ts b/lib/tooling/clang-tidy-tool.ts
index 15161fc76..d4ce3a5bc 100644
--- a/lib/tooling/clang-tidy-tool.ts
+++ b/lib/tooling/clang-tidy-tool.ts
@@ -26,7 +26,7 @@ import path from 'path';
 
 import fs from 'fs-extra';
 
-import {Library} from '../../types/libraries/libraries.interfaces.js';
+import {OptionsHandlerLibrary} from '../options-handler.js';
 import * as utils from '../utils.js';
 
 import {BaseTool} from './base-tool.js';
@@ -47,7 +47,7 @@ export class ClangTidyTool extends BaseTool {
         inputFilepath: string,
         args?: string[],
         stdin?: string,
-        supportedLibraries?: Record<string, Library>,
+        supportedLibraries?: Record<string, OptionsHandlerLibrary>,
     ) {
         const sourcefile = inputFilepath;
         const options = compilationInfo.options;
diff --git a/lib/tooling/compiler-dropin-tool.ts b/lib/tooling/compiler-dropin-tool.ts
index 2f2b31d51..79a443a24 100644
--- a/lib/tooling/compiler-dropin-tool.ts
+++ b/lib/tooling/compiler-dropin-tool.ts
@@ -22,8 +22,8 @@
 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 // POSSIBILITY OF SUCH DAMAGE.
 
-import {Library} from '../../types/libraries/libraries.interfaces.js';
 import {ToolResult} from '../../types/tool.interfaces.js';
+import {OptionsHandlerLibrary} from '../options-handler.js';
 import {getToolchainPath} from '../toolchain-utils.js';
 import * as utils from '../utils.js';
 
@@ -102,7 +102,7 @@ export class CompilerDropinTool extends BaseTool {
         inputFilepath?: string,
         args?: string[],
         stdin?: string,
-        supportedLibraries?: Record<string, Library>,
+        supportedLibraries?: Record<string, OptionsHandlerLibrary>,
     ): Promise<ToolResult> {
         const sourcefile = inputFilepath;
 
diff --git a/lib/tooling/microsoft-analysis-tool.ts b/lib/tooling/microsoft-analysis-tool.ts
index 6a49fe119..af6549e5e 100644
--- a/lib/tooling/microsoft-analysis-tool.ts
+++ b/lib/tooling/microsoft-analysis-tool.ts
@@ -24,10 +24,10 @@
 
 import path from 'path';
 
-import {Library} from '../../types/libraries/libraries.interfaces.js';
 import {ToolInfo} from '../../types/tool.interfaces.js';
 import {unwrap} from '../assert.js';
 import {logger} from '../logger.js';
+import {OptionsHandlerLibrary} from '../options-handler.js';
 import * as utils from '../utils.js';
 
 import {ToolEnv} from './base-tool.interface.js';
@@ -81,7 +81,7 @@ export class MicrosoftAnalysisTool extends BaseTool {
         inputFilepath?: string,
         args?: string[],
         stdin?: string,
-        supportedLibraries?: Record<string, Library>,
+        supportedLibraries?: Record<string, OptionsHandlerLibrary>,
     ) {
         const sourcefile = inputFilepath;
         const options = compilationInfo.options;
diff --git a/lib/tooling/sonar-tool.ts b/lib/tooling/sonar-tool.ts
index 695f5ffda..54ec21e86 100644
--- a/lib/tooling/sonar-tool.ts
+++ b/lib/tooling/sonar-tool.ts
@@ -25,7 +25,6 @@
 import path from 'path';
 
 import {ExecutionOptions} from '../../types/compilation/compilation.interfaces.js';
-import {Library} from '../../types/libraries/libraries.interfaces.js';
 import type {
     Fix,
     Link,
@@ -34,6 +33,7 @@ import type {
     ResultLineTag,
 } from '../../types/resultline/resultline.interfaces.js';
 import type {Artifact, ToolInfo, ToolResult} from '../../types/tool.interfaces.js';
+import {OptionsHandlerLibrary} from '../options-handler.js';
 import * as utils from '../utils.js';
 
 import {ToolEnv} from './base-tool.interface.js';
@@ -180,7 +180,7 @@ export class SonarTool extends BaseTool {
     buildCompilationCMD(
         compilationInfo: Record<any, any>,
         inputFilePath: string,
-        supportedLibraries?: Record<string, Library>,
+        supportedLibraries?: Record<string, OptionsHandlerLibrary>,
     ) {
         const cmd: any[] = [];
         cmd.push(compilationInfo.compiler.exe);
@@ -211,7 +211,7 @@ export class SonarTool extends BaseTool {
         inputFilePath?: string,
         args?: string[],
         stdin?: string,
-        supportedLibraries?: Record<string, Library>,
+        supportedLibraries?: Record<string, OptionsHandlerLibrary>,
     ): Promise<ToolResult> {
         if (inputFilePath == null) {
             return new Promise(resolve => {
diff --git a/package-lock.json b/package-lock.json
index ce261bef6..5f6384df3 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -20,6 +20,7 @@
         "@sentry/browser": "^7.114.0",
         "@sentry/node": "^7.114.0",
         "@types/morgan": "^1.9.9",
+        "@types/semver": "^7.5.8",
         "big-integer": "^1.6.52",
         "body-parser": "^1.20.2",
         "bootstrap": "^4.6.2",
@@ -61,7 +62,7 @@
         "response-time": "^2.3.2",
         "sanitize-filename": "^1.6.3",
         "scroll-into-view-if-needed": "^3.1.0",
-        "semver": "^7.6.2",
+        "semver": "^7.6.3",
         "serve-favicon": "^2.5.0",
         "shell-quote": "^1.8.1",
         "systemd-socket": "0.0.0",
@@ -4074,6 +4075,7 @@
       "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.4.tgz",
       "integrity": "sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==",
       "dev": true,
+      "license": "MIT",
       "dependencies": {
         "@types/jsonfile": "*",
         "@types/node": "*"
@@ -4220,6 +4222,12 @@
         "form-data": "^2.5.0"
       }
     },
+    "node_modules/@types/semver": {
+      "version": "7.5.8",
+      "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz",
+      "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==",
+      "license": "MIT"
+    },
     "node_modules/@types/send": {
       "version": "0.17.4",
       "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz",
@@ -4311,7 +4319,8 @@
       "version": "1.11.15",
       "resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.11.15.tgz",
       "integrity": "sha512-HP38xE+GuWGlbSRq9WrZkousaQ7dragtZCruBVMi0oX1migFZavZ3OROKHSkNp/9ouq82zrWtZpg18jFnVN96g==",
-      "dev": true
+      "dev": true,
+      "license": "MIT"
     },
     "node_modules/@types/webpack-env": {
       "version": "1.18.5",
@@ -13900,9 +13909,10 @@
       "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA=="
     },
     "node_modules/semver": {
-      "version": "7.6.2",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz",
-      "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==",
+      "version": "7.6.3",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+      "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+      "license": "ISC",
       "bin": {
         "semver": "bin/semver.js"
       },
diff --git a/package.json b/package.json
index e1ac4118d..6b3362b1f 100644
--- a/package.json
+++ b/package.json
@@ -29,6 +29,7 @@
     "@sentry/browser": "^7.114.0",
     "@sentry/node": "^7.114.0",
     "@types/morgan": "^1.9.9",
+    "@types/semver": "^7.5.8",
     "big-integer": "^1.6.52",
     "body-parser": "^1.20.2",
     "bootstrap": "^4.6.2",
@@ -70,7 +71,7 @@
     "response-time": "^2.3.2",
     "sanitize-filename": "^1.6.3",
     "scroll-into-view-if-needed": "^3.1.0",
-    "semver": "^7.6.2",
+    "semver": "^7.6.3",
     "serve-favicon": "^2.5.0",
     "shell-quote": "^1.8.1",
     "systemd-socket": "0.0.0",


Test patch:
diff --git a/test/state/bug-6380.json b/test/state/bug-6380.json
new file mode 100644
index 000000000..7323b883a
--- /dev/null
+++ b/test/state/bug-6380.json
@@ -0,0 +1,81 @@
+{
+    "sessions": [
+        {
+            "id": 1,
+            "language": "c++",
+            "source": "// Type your code here, or load an example.\nint square(int num) {\n    return num * num;\n}",
+            "conformanceview": false,
+            "compilers": [
+                {
+                    "_internalid": 2,
+                    "id": "g132",
+                    "options": "",
+                    "filters": {
+                        "binary": false,
+                        "binaryObject": false,
+                        "commentOnly": true,
+                        "demangle": true,
+                        "directives": true,
+                        "execute": false,
+                        "intel": true,
+                        "labels": true,
+                        "libraryCode": true,
+                        "trim": false,
+                        "debugCalls": false
+                    },
+                    "libs": [],
+                    "specialoutputs": [],
+                    "tools": []
+                }
+            ],
+            "executors": [],
+            "filename": "example.cpp"
+        }
+    ],
+    "trees": [
+        {
+            "id": 1,
+            "cmakeArgs": "-DCMAKE_BUILD_TYPE=Debug",
+            "customOutputFilename": "",
+            "isCMakeProject": false,
+            "compilerLanguageId": "c++",
+            "files": [
+                {
+                    "fileId": 1,
+                    "isIncluded": true,
+                    "isOpen": true,
+                    "isMainSource": true,
+                    "filename": "example.cpp",
+                    "content": "// Type your code here, or load an example.\nint square(int num) {\n    return num * num;\n}",
+                    "editorId": 1,
+                    "langId": ""
+                }
+            ],
+            "newFileId": 2,
+            "compilers": [
+                {
+                    "_internalid": 1,
+                    "id": "g132",
+                    "options": "",
+                    "filters": {
+                        "binary": false,
+                        "binaryObject": false,
+                        "commentOnly": true,
+                        "demangle": true,
+                        "directives": true,
+                        "execute": false,
+                        "intel": true,
+                        "labels": true,
+                        "libraryCode": true,
+                        "trim": false,
+                        "debugCalls": false
+                    },
+                    "libs": [],
+                    "specialoutputs": [],
+                    "tools": []
+                }
+            ],
+            "executors": []
+        }
+    ]
+}
\ No newline at end of file
diff --git a/test/state/tree.goldenified.json b/test/state/tree.goldenified.json
index bdbb4fc53..f4a8c6929 100644
--- a/test/state/tree.goldenified.json
+++ b/test/state/tree.goldenified.json
@@ -48,7 +48,6 @@
                 "cmakeArgs": "",
                 "customOutputFilename": "",
                 "isCMakeProject": true,
-                "newFileId": 7,
                 "compilerLanguageId": "c++",
                 "files": [
                   {
@@ -91,7 +90,8 @@
                     "editorId": 4,
                     "langId": ""
                   }
-                ]
+                ],
+                "newFileId": 7
               },
               "isClosable": true,
               "reorderEnabled": true
@@ -161,45 +161,52 @@
           "width": 40,
           "content": [
             {
-              "componentName": "compiler",
-              "componentState": {
-                "compiler": "g103",
-                "filters": {
-                  "binary": true,
-                  "binaryObject": false,
-                  "commentOnly": true,
-                  "demangle": true,
-                  "directives": true,
-                  "execute": false,
-                  "intel": true,
-                  "labels": true,
-                  "libraryCode": false,
-                  "debugCalls": false,
-                  "trim": false
+              "type": "row",
+              "height": 100,
+              "content": [
+                {
+                  "type": "component",
+                  "componentName": "compiler",
+                  "componentState": {
+                    "id": 1,
+                    "compiler": "g103",
+                    "tree": 1,
+                    "options": "-g -O3 -flto",
+                    "filters": {
+                      "binary": true,
+                      "binaryObject": false,
+                      "commentOnly": true,
+                      "demangle": true,
+                      "directives": true,
+                      "execute": false,
+                      "intel": true,
+                      "labels": true,
+                      "libraryCode": false,
+                      "trim": false,
+                      "debugCalls": false
+                    },
+                    "libs": [],
+                    "lang": "c++"
+                  },
+                  "isClosable": true,
+                  "reorderEnabled": true
                 },
-                "lang": "c++",
-                "libs": [],
-                "options": "-g -O3 -flto",
-                "tree": 1
-              },
-              "isClosable": true,
-              "reorderEnabled": true,
-              "type": "component"
-            },
-            {
-              "componentName": "output",
-              "componentState": {
-                "compiler": 1,
-                "fontScale": 14,
-                "wrap": false
-              },
-              "isClosable": true,
-              "reorderEnabled": true,
-              "type": "component"
+                {
+                  "type": "component",
+                  "componentName": "output",
+                  "componentState": {
+                    "compiler": 2,
+                    "wrap": false,
+                    "fontScale": 14
+                  },
+                  "isClosable": true,
+                  "reorderEnabled": true
+                }
+              ]
             }
           ]
         }
       ]
     }
   ]
-}
+}
\ No newline at end of file
diff --git a/test/statenormalisation-tests.ts b/test/statenormalisation-tests.ts
index 12498f457..fddd0fd53 100644
--- a/test/statenormalisation-tests.ts
+++ b/test/statenormalisation-tests.ts
@@ -219,3 +219,20 @@ describe('Trees', () => {
         expect(golden).toEqual(resultdata);
     });
 });
+
+describe('bug-6380', () => {
+    it('Should goldenify properly', () => {
+        const jsonStr = fs.readFileSync('test/state/bug-6380.json', {encoding: 'utf8'});
+        const state = new ClientState(JSON.parse(jsonStr));
+
+        const gl = new ClientStateGoldenifier();
+        gl.fromClientState(state);
+
+        const golden = JSON.parse(JSON.stringify(gl.golden));
+
+        const normalizer = new ClientStateNormalizer();
+        normalizer.fromGoldenLayout(golden);
+
+        expect(normalizer.normalized).toEqual(state);
+    });
+});
diff --git a/test/stats-test.ts b/test/stats-test.ts
index 6210f2204..70bbb434f 100644
--- a/test/stats-test.ts
+++ b/test/stats-test.ts
@@ -24,9 +24,9 @@
 
 import {describe, expect, it} from 'vitest';
 
-import {ParsedRequest} from '../lib/handlers/compile.js';
 import {filterCompilerOptions, KnownBuildMethod, makeSafe} from '../lib/stats.js';
 import {getHash} from '../lib/utils.js';
+import {ParseFiltersAndOutputOptions} from '../types/features/filters.interfaces.js';
 
 describe('Stats', () => {
     const someDate = new Date(Date.UTC(2023, 6, 12, 2, 4, 6));
@@ -136,7 +136,7 @@ describe('Stats', () => {
                         optOutput: true,
                         preProcessLines: lines => lines,
                         preProcessBinaryAsmLines: lines => lines,
-                    } as unknown as ParsedRequest,
+                    } as ParseFiltersAndOutputOptions,
                     bypassCache: 0,
                     tools: undefined,
                     executeParameters: executionParameters,