Skip to content

Commit fbdbe76

Browse files
committed
Update patch
1 parent d2dc393 commit fbdbe76

File tree

2 files changed

+125
-10
lines changed

2 files changed

+125
-10
lines changed

src/Editor.tsx

Lines changed: 122 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -129,13 +129,66 @@ const Editor = ({
129129
cleanupProviders();
130130
}, []);
131131

132+
// Handle Monaco disposal errors gracefully - suppress instead of remounting
133+
useEffect(() => {
134+
const handleMonacoError = (event: ErrorEvent) => {
135+
const message = event.error?.message || "";
136+
if (
137+
message.includes("InstantiationService has been disposed") ||
138+
message.includes("domNode") ||
139+
message.includes("renderText") ||
140+
message.includes("AnimationFrameQueueItem")
141+
) {
142+
// Suppress Monaco cleanup errors - they're harmless during layout changes
143+
console.debug("Monaco cleanup error suppressed:", message);
144+
event.preventDefault();
145+
event.stopPropagation();
146+
return false;
147+
}
148+
return true;
149+
};
150+
151+
const handleUnhandledRejection = (event: PromiseRejectionEvent) => {
152+
const message = event.reason?.message || "";
153+
if (
154+
message.includes("InstantiationService has been disposed") ||
155+
message.includes("domNode") ||
156+
message.includes("renderText")
157+
) {
158+
// Suppress Monaco cleanup errors in promises
159+
console.debug("Monaco cleanup promise error suppressed:", message);
160+
event.preventDefault();
161+
return false;
162+
}
163+
return true;
164+
};
165+
166+
window.addEventListener("error", handleMonacoError, true);
167+
window.addEventListener("unhandledrejection", handleUnhandledRejection);
168+
169+
return () => {
170+
window.removeEventListener("error", handleMonacoError, true);
171+
window.removeEventListener("unhandledrejection", handleUnhandledRejection);
172+
};
173+
}, []);
174+
132175
// Cleanup on unmount
133176
useEffect(() => {
134177
return () => {
135178
cleanupMonaco();
136179
};
137180
}, [cleanupMonaco]);
138181

182+
// Track if component is mounted to prevent layout operations after unmount
183+
const isMountedRef = useRef(true);
184+
185+
useEffect(() => {
186+
isMountedRef.current = true;
187+
return () => {
188+
isMountedRef.current = false;
189+
};
190+
}, []);
191+
139192
const onMount = useCallback(
140193
(editor: any, mon: any, t: Tools) => {
141194
editorRef.current = editor;
@@ -159,6 +212,58 @@ const Editor = ({
159212
}
160213
};
161214

215+
// Safe layout wrapper - only layout if mounted
216+
const originalLayout = editor.layout.bind(editor);
217+
editor.layout = function (...args: any[]) {
218+
if (!isMountedRef.current) {
219+
console.debug("Skipped layout call on unmounted editor");
220+
return;
221+
}
222+
try {
223+
originalLayout(...args);
224+
} catch (error: any) {
225+
if (
226+
!error.message?.includes("InstantiationService has been disposed") &&
227+
!error.message?.includes("domNode")
228+
) {
229+
throw error;
230+
}
231+
console.debug("Suppressed layout error during cleanup");
232+
}
233+
};
234+
235+
// Patch the editor's internal rendering to prevent domNode errors
236+
// This is a deep patch to prevent errors from bubbling up
237+
try {
238+
const editorInternal = (editor as any)._view;
239+
if (editorInternal && editorInternal._renderingCoordinator) {
240+
const coordinator = editorInternal._renderingCoordinator;
241+
const originalOnRenderScheduled = coordinator._onRenderScheduled;
242+
if (originalOnRenderScheduled) {
243+
coordinator._onRenderScheduled = function (this: any) {
244+
if (!isMountedRef.current || !editorRef.current) {
245+
console.debug("Skipped render on unmounted editor");
246+
return;
247+
}
248+
try {
249+
originalOnRenderScheduled.call(this);
250+
} catch (error: any) {
251+
if (
252+
error.message?.includes("domNode") ||
253+
error.message?.includes("renderText")
254+
) {
255+
console.debug("Suppressed Monaco rendering error:", error.message);
256+
return;
257+
}
258+
throw error;
259+
}
260+
};
261+
}
262+
}
263+
} catch (e) {
264+
console.debug("Could not patch Monaco rendering coordinator (non-critical)");
265+
}
266+
162267
// Monaco Editor markers will automatically show error tooltips on hover
163268
// No need for custom hover provider as it causes duplicates
164269

@@ -261,7 +366,16 @@ const Editor = ({
261366
const editor = editorRef.current;
262367
if (!editor) return;
263368

264-
const monacoErrors: any[] = validate(t)(editor?.getValue() || str).map(error => {
369+
// Check if model exists before parsing
370+
const model = editor?.getModel();
371+
if (!model) {
372+
console.debug("parseContent: model not ready yet");
373+
return;
374+
}
375+
376+
// Use provided string or get value from editor
377+
const content = str !== undefined ? str : editor.getValue();
378+
const monacoErrors: any[] = validate(t)(content).map(error => {
265379
return {
266380
startLineNumber: error.startLine,
267381
startColumn: error.startCol,
@@ -273,15 +387,14 @@ const Editor = ({
273387
: monacoRef.current?.editor?.MarkerSeverity?.Error || 8
274388
};
275389
});
276-
const model = editor?.getModel();
277-
if (model) {
278-
if (!isTestEnvironment && monacoRef.current?.editor) {
279-
// Clear existing markers first
280-
monacoRef.current.editor.setModelMarkers(model, "owner", []);
281-
// Set new markers
282-
monacoRef.current.editor.setModelMarkers(model, "owner", monacoErrors);
283-
}
390+
391+
if (!isTestEnvironment && monacoRef.current?.editor) {
392+
// Clear existing markers first
393+
monacoRef.current.editor.setModelMarkers(model, "owner", []);
394+
// Set new markers
395+
monacoRef.current.editor.setModelMarkers(model, "owner", monacoErrors);
284396
}
397+
285398
if (onListErrors) {
286399
onListErrors(
287400
monacoErrors.map(error => {

src/monaco-patch.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ console.error = function (...args: any[]) {
1717
message.includes("domNode") ||
1818
message.includes("renderText") ||
1919
message.includes("AnimationFrameQueueItem") ||
20-
message.includes("Cannot read properties of undefined")
20+
message.includes("getFullModelRange") ||
21+
message.includes("Cannot read properties of undefined") ||
22+
message.includes("Cannot read properties of null")
2123
) {
2224
console.debug("[Monaco Patch] Suppressed console.error:", message);
2325
return;

0 commit comments

Comments
 (0)