Skip to content

Commit bc982aa

Browse files
authored
fix: prevent memory leak on default theme recreation (#769)
1 parent e275fb6 commit bc982aa

2 files changed

Lines changed: 50 additions & 14 deletions

File tree

core/src/theme/dimensionTheme.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { EditorView } from '@codemirror/view';
2+
import type { Extension } from '@codemirror/state';
3+
4+
export const scrollerTheme = EditorView.theme({
5+
'& .cm-scroller': {
6+
height: '100% !important',
7+
},
8+
});
9+
10+
let lastDimensionKey: string | null = null;
11+
let lastDimensionTheme: Extension | null = null;
12+
13+
export function getDimensionTheme(
14+
height: string | null,
15+
minHeight: string | null,
16+
maxHeight: string | null,
17+
width: string | null,
18+
minWidth: string | null,
19+
maxWidth: string | null,
20+
): Extension | null {
21+
if (!height && !minHeight && !maxHeight && !width && !minWidth && !maxWidth) {
22+
return null;
23+
}
24+
25+
const cacheKey = JSON.stringify({ height, minHeight, maxHeight, width, minWidth, maxWidth });
26+
if (cacheKey === lastDimensionKey) {
27+
return lastDimensionTheme;
28+
}
29+
30+
lastDimensionKey = cacheKey;
31+
lastDimensionTheme = EditorView.theme({
32+
'&': {
33+
height,
34+
minHeight,
35+
maxHeight,
36+
width,
37+
minWidth,
38+
maxWidth,
39+
},
40+
});
41+
return lastDimensionTheme;
42+
}

core/src/useCodeMirror.ts

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { getDefaultExtensions } from './getDefaultExtensions';
55
import { getStatistics } from './utils';
66
import { type ReactCodeMirrorProps } from '.';
77
import { TimeoutLatch, getScheduler } from './timeoutLatch';
8+
import { scrollerTheme, getDimensionTheme } from './theme/dimensionTheme';
89

910
export const ExternalChange = Annotation.define<boolean>();
1011
const TYPING_TIMOUT = 200; // ms
@@ -45,19 +46,7 @@ export function useCodeMirror(props: UseCodeMirror) {
4546
const [state, setState] = useState<EditorState>();
4647
const typingLatch = useState<{ current: TimeoutLatch | null }>(() => ({ current: null }))[0];
4748
const pendingUpdate = useState<{ current: (() => void) | null }>(() => ({ current: null }))[0];
48-
const defaultThemeOption = EditorView.theme({
49-
'&': {
50-
height,
51-
minHeight,
52-
maxHeight,
53-
width,
54-
minWidth,
55-
maxWidth,
56-
},
57-
'& .cm-scroller': {
58-
height: '100% !important',
59-
},
60-
});
49+
const defaultThemeOption = getDimensionTheme(height, minHeight, maxHeight, width, minWidth, maxWidth);
6150
const updateListener = EditorView.updateListener.of((vu: ViewUpdate) => {
6251
if (
6352
vu.docChanged &&
@@ -96,7 +85,12 @@ export function useCodeMirror(props: UseCodeMirror) {
9685
basicSetup: defaultBasicSetup,
9786
});
9887

99-
let getExtensions = [updateListener, defaultThemeOption, ...defaultExtensions];
88+
let getExtensions = [
89+
updateListener,
90+
...(defaultThemeOption ? [defaultThemeOption] : []),
91+
scrollerTheme,
92+
...defaultExtensions,
93+
];
10094

10195
if (onUpdate && typeof onUpdate === 'function') {
10296
getExtensions.push(EditorView.updateListener.of(onUpdate));

0 commit comments

Comments
 (0)