## Summary
This PR makes URL serialization logic available to Node.js contexts
(like Cypress tests) and replaces a hard-coded 4812-character base64 URL
in tests with programmatically generated state. This builds on the
shared utilities refactoring from #8246.
### Changes
#### 1. Extract URL Serialization to Shared Module
**Problem:** URL serialization code depended on GoldenLayout's
browser-only ConfigMinifier, preventing Cypress spec files from
importing it (they load in Node.js before running in browser).
**Solution:** Created `shared/url-serialization.ts` with a
Node-compatible ConfigMinifier reimplementation.
**Technical Details:**
- Reimplemented GoldenLayout's ConfigMinifier without browser
dependencies
- Moved serialization functions (`serialiseState`, `deserialiseState`,
`risonify`, `unrisonify`) to shared module
- Moved minification functions (`minifyConfig`, `unminifyConfig`) to
shared module
- Updated `static/url.ts` to use shared module instead of GoldenLayout
- Added comprehensive test coverage in `test/url-serialization.ts`
**Files:**
- **New:** `shared/url-serialization.ts` (~279 lines)
- **Modified:** `static/url.ts` (removed ~30 lines, eliminated
GoldenLayout dependency)
- **New:** `test/url-serialization.ts` (~96 lines)
#### 2. Replace Hard-coded Cypress URL with Programmatic State
**Before:** A hard-coded 4812-character base64 URL containing state for
all panes
```typescript
cy.visit('http://localhost:10240/#z:OYLghAFBqd5TB8IAsQGMD2ATApgUWwEsAXTAJwBoiQIAzIgG...');
```
**After:** Programmatically generated state using
`buildKnownGoodState()` function
```typescript
const state = buildKnownGoodState();
const hash = serialiseState(state);
cy.visit(`http://localhost:10240/#${hash}`, {...});
```
**Benefits:**
- Human-readable, maintainable test state
- Programmatic generation from `PANE_DATA_MAP` keys
- Layout optimized with 8 panes per row
- Produces identical compressed URL format
- Much easier to add/modify panes in the future
#### 3. PANE_DATA_MAP Consistency Improvements
Updated `PANE_DATA_MAP` to use component names exactly as registered
with GoldenLayout:
**Key renames:**
- `preprocessor` → `pp`
- `llvmir` → `ir`
- `pipeline` → `llvmOptPipelineView`
- `mir` → `rustmir`
- `hir` → `rusthir`
- `macro` → `rustmacroexp`
- `core` → `haskellCore`
- `stg` → `haskellStg`
- `cmm` → `haskellCmm`
- `dump` → `gccdump`
- `tree` → `gnatdebugtree`
- `debug` → `gnatdebug`
**Added panes:** `codeEditor`, `compiler`, `conformance`, `output` (were
missing from map)
**Re-enabled tests:**
- `yul` pane test (was commented out, now fixed)
- `clojuremacroexp` pane test (was commented out, now fixed)
- `cfg` pane test (had TODO, now removed)
**Why this matters:** The `buildKnownGoodState()` function uses
`Object.keys(PANE_DATA_MAP)` as the `componentName` property, so keys
must match the actual registered component names for GoldenLayout to
find them.
## Test Plan
- [x] All Cypress tests pass (confirmed by @mattgodbolt)
- [x] TypeScript compilation passes (`npm run ts-check`)
- [x] Linting passes (`npm run lint`)
- [x] URL serialization tests pass (3/3 tests)
- [x] Pre-commit hooks pass
- [x] Related vitest tests pass
## Dependencies
- Builds on #8246 (shared utilities refactoring - already merged)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
Moves `static/assert.ts` and `static/rison.ts` to `shared/` directory to
make them available to both frontend and backend code without browser
dependencies. Updates all import paths across the codebase (~47 files).
## Motivation
This refactoring eliminates browser dependencies in these utilities,
allowing them to be imported by Node.js contexts (like Cypress test
files) without causing module load failures. This is a prerequisite for
upcoming Cypress test improvements.
## Changes
- Move `static/assert.ts` → `shared/assert.ts`
- Move `static/rison.ts` → `shared/rison.ts`
- Update `biome.json` to allow `hasOwnProperty` in `shared/` directory
- Update all imports across `static/`, `lib/`, and `test/` directories
(47 files changed)
## Benefits
- No functional changes, purely a code reorganization
- Makes these utilities accessible to both frontend and backend without
circular dependencies
- Enables future Cypress improvements that require these utilities in
Node.js context
- All tests pass ✓ (699 tests)
## Test Plan
- [x] TypeScript compilation passes
- [x] Linting passes
- [x] All unit tests pass (699 tests)
- [x] Pre-commit hooks pass
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
Fixes the issue where the "Edit on Compiler Explorer" link in embedded
iframes doesn't update with the current code state, staying as "/"
instead of including the serialized state.
## Changes
- Refactored `Sharing` class into a base class `SharingBase` that
handles state tracking and embedded link updates
- `Sharing` class now extends `SharingBase` and adds the full sharing UI
features
- Created `initialiseSharing()` function that instantiates the
appropriate class based on embedded mode
- Updated `main.ts` to use the new initialization function
- Updated `history.ts` to use `SharingBase.filterComponentState()`
instead of `Sharing.filterComponentState()`
## Testing
- TypeScript compilation passes (`npm run ts-check`)
- Linting passes (`npm run lint`)
- Tests pass (`npm run test-min`)
- Manual browser testing confirms embedded links now update correctly
Closes#8097🤖 Generated with [Claude Code](https://claude.ai/code)
---------
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
This PR fixes Sentry issue COMPILER-EXPLORER-BFA which has generated
over 33,000 occurrences of non-actionable error reports.
## Problem
The issue occurs when jQuery `.get()` requests fail with `readyState: 0`
and `status: 0`, which typically indicates:
- Ad blockers blocking requests to static assets (icons.html,
sponsors.html)
- Network connectivity issues
- Browser security policies
- User navigating away during request
These network-level failures are not application bugs and create noise
in Sentry monitoring.
## Solution
- Filter out network failures (`readyState === 0 && status === 0`)
before sending to Sentry
- Only capture actual server errors (`status >= 400`) for debugging
- Log network failures to console for debugging instead
- For sponsors.html specifically, silently fail on network issues per
request
## Test Plan
- [x] TypeScript compilation passes
- [x] All tests pass
- [x] Pre-commit hooks complete successfully
- Verified logic handles both network failures and real server errors
appropriately
🤖 Generated with [Claude Code](https://claude.ai/code)
- latest biome, and fix its configuration
- fixes "static" content to be globally configured too (instead of
per-line)
- fixes issues:
- imports fixed up
- `Date.now()` vs `+new Date()`
- some unused things `_` prefixed
After discussion with the team, turned off the unused parameter warning.
This adds some unit tests for the front end.
- configures "frontend tests" as a unit tests in `static/tests`,
removing the old cypress-requiring "unit" tests
- hack enough of a DOM to get things working
- port motd and id tests
- *adds* a golden layout checks (see #7807)
- Updates READMEs etc
---------
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
This PR significantly improves type safety for GoldenLayout
configurations, continuing work from issue #4490 "The War of The Types".
This is an **incremental improvement** that establishes a solid
foundation for future work.
## ✅ What We've Accomplished
### Core Type Infrastructure
- **Created comprehensive type system** in
`static/components.interfaces.ts`
- **Added `ComponentConfig<K>`** with proper generic constraints for
type-safe component configurations
- **Added `GoldenLayoutConfig`** to replace unsafe `any[]` content with
strongly-typed `ItemConfig[]`
- **Created `ComponentStateMap`** mapping component names to their
expected state types
- **Added proper TypeScript component name constants** with `as const`
for literal type inference
### Component Configuration Type Safety
- **All component factory functions** now return strongly-typed
configurations
- **Clean type syntax**: `ComponentConfig<'compiler'>` using the
exported constants
- **Eliminated unsafe casts** in component creation and drag source
setup
- **Fixed hub method signatures** that incorrectly expected
`ContentItem` instead of `ItemConfig`
### Bug Fixes and Code Quality
- **Fixed Jeremy's TODO**: Improved `fixBugsInConfig` function typing
- **Discovered and fixed hub type bug**:
`addAtRoot`/`addInEditorStackIfPossible` now accept correct types
- **Removed legacy conversion functions** that were no longer needed
- **Replaced verbose TODO comments** with GitHub issue references for
better organization
### Documentation and Planning
- **Created GitHub issues**
[#7807](https://github.com/compiler-explorer/compiler-explorer/issues/7807)
and
[#7808](https://github.com/compiler-explorer/compiler-explorer/issues/7808)
for remaining work
- **Documented type safety approach** with clear explanations of design
decisions
- **Added comprehensive implementation notes** for future contributors
## 🚧 What's Next (GitHub Issues)
- **Issue #7807**: [Type-safe
serialization/deserialization](https://github.com/compiler-explorer/compiler-explorer/issues/7807)
- localStorage persistence and URL sharing
- SerializedLayoutState implementation
- Version migration support
- **Issue #7808**: [Configuration validation and remaining type
gaps](https://github.com/compiler-explorer/compiler-explorer/issues/7808)
- Enable `fromGoldenLayoutConfig` validation
- Fix upstream GoldenLayout TypeScript definitions
- State type normalization (addresses #4490)
## 📊 Impact
### Type Safety Improvements
- **No more `any` casts** in component configuration creation
- **Compile-time validation** of component names and state types
- **Better IDE support** with autocomplete and type checking
- **Runtime safety** through proper TypeScript interfaces
### Code Quality
- **~100 lines of verbose TODO comments** replaced with concise GitHub
issue references
- **Technical debt reduction** through elimination of unsafe casting
patterns
- **Improved maintainability** with centralized type definitions
- **Better error messages** when component configurations are incorrect
### Files Modified
- `static/components.interfaces.ts` - Core type definitions
- `static/components.ts` - Component factory functions and utilities
- `static/main.ts` - Layout initialization and configuration handling
- `static/hub.ts` - Fixed method signatures
- `static/panes/*.ts` - Updated component creation patterns
## ✅ Testing & Validation
- **All existing tests pass** - no runtime regressions
- **TypeScript compilation succeeds** with strict type checking
- **Linting passes** with no new warnings
- **Pre-commit hooks validated** all changes
- **Manual testing confirmed** layout functionality works correctly
## 🎯 Ready to Merge
This PR represents a **significant incremental improvement** that:
- ✅ **Provides immediate value** through better type safety
- ✅ **Maintains full backward compatibility**
- ✅ **Establishes solid foundation** for future improvements
- ✅ **Centralizes remaining work** in well-documented GitHub issues
- ✅ **Ready for production use** with no runtime changes
The remaining work is clearly tracked in the linked GitHub issues and
can be tackled incrementally in future PRs.
🤖 Generated with [Claude Code](https://claude.ai/code)
---------
Co-authored-by: Claude <noreply@anthropic.com>
- Removes `rootDirs` so all imports will be relative in the frontend
- Updates (and unifies) imports to be `../types/...` etc instead of
relying on "types" being in the rootDir for the frontend.
- Fixes one type that was being picked up from `lib` in the frontend.
- Adds a precommit hook to check in future
Paves the way to writing _unit_ tests for the frontend for the subset of
the frontend code we can import from `node` (which might be a lot of
it!)
## Summary
Fixes `TypeError: Cannot read properties of undefined (reading
'content')` in `findConfig()` when URL parsing fails and no saved state
is available.
## Root Cause
This error occurs when:
1. `url.deserialiseState()` throws an exception due to
malformed/corrupted URLs
2. No saved state exists in localStorage
(`sessionThenLocalStorage.get('gl', null)` returns `null`)
3. Code attempts to access `config.content` when `config` is still
`undefined`
The error happens legitimately from truncated URLs, corrupted bookmarks,
or URL shortener issues.
## Changes
- Changed `if (!config.content || config.content.length === 0)` to use
optional chaining: `if (!config?.content || config.content?.length ===
0)`
- This gracefully handles the null/undefined case and falls back to
default config as intended
## Impact
- Maintains existing user experience (fallback to default config when
URL parsing fails)
- Prevents crash with 1430+ reported occurrences
- No behavioral changes for valid URLs
Fixes COMPILER-EXPLORER-DE3
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-authored-by: Claude <noreply@anthropic.com>
Fixes issues with missing components (e.g. from beta, 'explain')
The issue was that the exceptions are thrown in `initLayout`, not in the
constructor.
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This PR completes the migration from Bootstrap 4 to Bootstrap 5.3.5
following the plan outlined in
[docs/Bootstrap5Migration.md](https://github.com/compiler-explorer/compiler-explorer/blob/mg/bootstrap5/docs/Bootstrap5Migration.md).
## Migration Process
We followed a phased approach as documented in the migration plan:
1. **Phase 1: Dependency Updates and Basic Setup**
- Updated Bootstrap from 4.6.2 to 5.3.5
- Added @popperjs/core dependency (replacing Popper.js)
- Updated Tom Select theme from bootstrap4 to bootstrap5
2. **Phase 2: Global CSS Class Migration**
- Updated directional utility classes (ml/mr → ms/me)
- Updated floating utility classes (float-left/right → float-start/end)
- Updated text alignment classes (text-left/right → text-start/end)
3. **Phase 3: HTML Attribute Updates**
- Updated data attributes to use Bootstrap 5 prefixes (data-bs-toggle,
data-bs-target, etc.)
- Fixed tab navigation issues
4. **Phase 4: JavaScript API Compatibility Layer**
- Created bootstrap-utils.ts compatibility layer
- Updated component initialization for modals, dropdowns, popovers, etc.
5. **Phase 5: Component Migration**
- Updated and tested specific components (modals, dropdowns, toasts,
etc.)
- Fixed styling issues in cards and button groups
6. **Phase 6: Form System Updates**
- Updated form control classes to Bootstrap 5 standards
- Updated checkbox/radio markup patterns
- Simplified input groups
7. **Phase 7: Navbar Structure Updates**
- Updated navbar structure with container-fluid
- Fixed responsive behavior
8. **Phase 8: SCSS Variables and Theming**
- Added custom CSS fixes for navbar alignment
- Verified theme compatibility
9. **Phase 9: Accessibility Improvements**
- Updated sr-only to visually-hidden
- Added proper ARIA attributes
- Enhanced screen reader support
## Key Changes
- No more jQuery dependency in Bootstrap 5
- New prefix for data attributes (data-bs-*)
- Improved accessibility with ARIA attributes
- Updated positioning classes (start/end instead of left/right)
- Simplified input group structure
## Test Plan
1. **Navigation Testing**
- Verify all dropdown menus open and close properly
- Test mobile menu responsiveness
- Check tab navigation in settings dialog
2. **Component Testing**
- Verify all modals open and close correctly (settings, share,
load/save)
- Test tooltips and popovers
- Check form controls in different dialogs
3. **Layout Testing**
- Test responsiveness on different screen sizes
- Verify proper alignment of elements
- Check dark mode compatibility
4. **Specific Features to Test**
- Compiler selection and options
- Share dialog functionality
- Settings dialog
- Tree view (IDE mode)
- Font selection dropdown
5. **Browser Testing**
- Test in Chrome, Firefox, Safari
- Test in mobile browsers
## Note on Further Improvements
After this migration is stable, we could consider Phase 12: removing
jQuery dependency entirely, as Bootstrap 5 no longer requires it. This
would be a separate effort.
---------
Co-authored-by: Claude <noreply@anthropic.com>
When settings are set to emit-short-link upon ctrl+S, managing the logic
in `Editor` is problematic since the editor may lose focus and not
receive the event.
Also logically this is a cross-site event, and doesn't belong in any
particular editor (there can be multiple).
<!-- THIS COMMENT IS INVISIBLE IN THE FINAL PR, BUT FEEL FREE TO REMOVE
IT
Thanks for taking the time to improve CE. We really appreciate it.
Before opening the PR, please make sure that the tests & linter pass
their checks,
by running `make check`.
In the best case scenario, you are also adding tests to back up your
changes,
but don't sweat it if you don't. We can discuss them at a later date.
Feel free to append your name to the CONTRIBUTORS.md file
Thanks again, we really appreciate this!
-->
Fix#6464, following the discord discussion.
2 protections are added here:
(1) Make the first code editor non-closable, to avoid an empty layout,
(2) If a loaded config has empty layout - fallback to the default
config.
In conversation with @mknejp he pointed out that it can be frustating
when having a browser loaded up with many tabs of CE links, then
reloading the browser (e.g. a reboot, or open/closing the tabs), that
upon reload all the tabs will have the same, shared state (corresponding
to whichever saved to local storage last).
This change:
- stores state in _both_ session and local storage
- removes from both on UI reset
- loads first from session storage and then falls back to local storage
The net result is:
- tabs reopened with "ctrl-shift T" will regain their prior state, as do
any other tabs for which the browser thinks are part of the same session
(like on a "reopen tabs" plugins etc)
- newly-opened tabs still have the prior behaviour of using whatever the
most recently opened tab had as its starting state
Some more info on session vs local storage
[here](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage)
This PR refactors some common utilities out of lib/ and into shared/ and
eliminates some use of underscore.js, as well as general type
improvements done along the way.
Makes the Compiler Explorer app, and all the tooling ESM compatible.
Things that have been done:
1. The package.json has `type: module` now
2. All relative imports have a .js ending
3. All directory imports are now directory/index.js to comply with ESM
standards
4. Dependency node-graceful is now imported into tree, because the
package is broken under esm
5. Dependency p-queue has been bumped to 7.x with ESM support
6. Dependency profanities has been bumped to 3.x with ESM support
7. Webpack config is now both ESM and CommonJS compatible
8. Non-ESM compatible imports have been rewritten
9. ESLint configuration has been tweaked to not fail on .js imports
10. Mocha is now hacked together and ran with ts-node-esm
11. Webpack is now hacked together and ran with ts-node-esm
12. Webpack config is now ESM compatible, so that it can be used in the
dev server
13. Cypress code still runs commonjs, and has been excluded from the
tsconfig
14. All sinon mock tests have been commented out, because sinon module
mocks do not work with ESModules (because ESModules are immutable)
A lot of tests are now giving warnings/errors to stdout, yet still pass.
Docenizer codegenerator scripts have been updated, but I did not re-run
them, and instead just changed their code.
---------
Co-authored-by: Matt Godbolt <matt@godbolt.org>