mirror of
https://github.com/compiler-explorer/compiler-explorer.git
synced 2026-09-10 15:47:42 -04:00
Fixes #9007. `LibsWidget` buckets `availableLibs` by compiler id, and it had two disagreeing ways of deciding that key. The constructor read `compiler.id`. `setNewLangId` took a plain id string. The compiler and executor panes pass a `CompilerInfo`, so they matched the constructor. The conformance view passes `compilerIds.join('|')`, because the libraries it offers are the intersection across every compiler in the pane, so it matched `setNewLangId` instead. The parameter was typed `any`, so nothing complained. Reading `.id` off a string gives `undefined`. So a conformance view restored from a link: 1. builds the widget with the joined id and keys itself on `undefined`, 2. loads the saved libs into `availableLibs[langId][undefined]`, 3. gets a real compiler-change event once the picker resolves, which calls `updateLibraries` and then `setNewLangId` with the same joined string, 4. is now keyed on `"g142|clang1500"`, where nothing was ever recorded. `listUsedLibs` reads the new bucket, finds nothing, and the libraries are gone. Re-adding one through the green button writes it into the new bucket, which is why that workaround sticks, exactly as the reporter describes. Both paths now go through one `toCompilerKey`, so the key cannot change shape mid-life. The parameter is typed instead of `any`, which is what let the two conventions coexist. One deliberate behavior change beyond the bug: a compiler whose `id` is the empty string now falls into `_default_` from the constructor too. `setNewLangId` already treated it that way through its falsy check, so this makes the two agree rather than inventing a third rule. The local `c_default_compiler_non_id` becomes the exported `DEFAULT_COMPILER_KEY`, and the two places that spelled the same value as a bare `'_default_'` literal now use it. Same value throughout, one name. ## What I ran `npm run check` passes: ts-check on both projects, biome over 826 files, frontend imports, license headers, and the test run. New test file `static/tests/widgets/libs-widget-tests.ts`, 5 cases over `toCompilerKey`, covering both call shapes, that they agree for the same compiler, every empty shape landing on the default, and that no shape can yield a non-string. All 5 fail before the change and pass after. The one failure in the suite, `test/build-systems-tests.ts > Maven build system > builds Kotlin ...`, also fails on a clean `main` on my machine. It is a symlink `realpath` comparison and I am on Windows. I did not reproduce the symptom in a browser: I cannot run the server locally, since it needs at least one compiler on POSIX paths. The chain above is read off the code and pinned by the unit test at the point where the two conventions met. If you would rather see a test that drives the whole widget through construct then `setNewLangId`, say so and I will add it.
Front-end unit tests
Tests here are super simple and use jsdom with a fake document to do quick checks on the front-end code.
For anything requiring a real browser, use the cypress tests in the cypress directory.