Browse Source

Merge pull request #25080 from overleaf/revert-25073-td-upgrade-react-error-boundary

Revert "Upgrade react-error-boundary to version 5"

GitOrigin-RevId: 3301adb508eed26e4429c6aa912abf9e81c1d9f8
Tim Down 1 year ago
parent
commit
cf36767f03

+ 9 - 6
package-lock.json

@@ -35064,13 +35064,16 @@
       }
       }
     },
     },
     "node_modules/react-error-boundary": {
     "node_modules/react-error-boundary": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-5.0.0.tgz",
-      "integrity": "sha512-tnjAxG+IkpLephNcePNA7v6F/QpWLH8He65+DmedchDwg162JZqx4NmbXj0mlAYVVEd81OW7aFhmbsScYfiAFQ==",
+      "version": "2.3.2",
+      "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-2.3.2.tgz",
+      "integrity": "sha512-ZMzi7s4pj/6A/6i9RS4tG7g1PdF2Rgr4/7FTQ8sbKHex19uNji0j+xq0OS//c6TUgQRKoL6P51BNNNFmYpRMhw==",
       "dev": true,
       "dev": true,
-      "license": "MIT",
       "dependencies": {
       "dependencies": {
-        "@babel/runtime": "^7.12.5"
+        "@babel/runtime": "^7.11.2"
+      },
+      "engines": {
+        "node": ">=10",
+        "npm": ">=6"
       },
       },
       "peerDependencies": {
       "peerDependencies": {
         "react": ">=16.13.1"
         "react": ">=16.13.1"
@@ -45419,7 +45422,7 @@
         "react-dnd": "^16.0.1",
         "react-dnd": "^16.0.1",
         "react-dnd-html5-backend": "^16.0.1",
         "react-dnd-html5-backend": "^16.0.1",
         "react-dom": "^17.0.2",
         "react-dom": "^17.0.2",
-        "react-error-boundary": "^5.0.0",
+        "react-error-boundary": "^2.3.1",
         "react-google-recaptcha": "^3.1.0",
         "react-google-recaptcha": "^3.1.0",
         "react-i18next": "^13.3.1",
         "react-i18next": "^13.3.1",
         "react-linkify": "^1.0.0-alpha",
         "react-linkify": "^1.0.0-alpha",

+ 15 - 4
services/web/frontend/js/features/history/components/diff-view/diff-view.tsx

@@ -5,6 +5,7 @@ import { Diff, DocDiffResponse } from '../../services/types/doc'
 import { useHistoryContext } from '../../context/history-context'
 import { useHistoryContext } from '../../context/history-context'
 import { diffDoc } from '../../services/api'
 import { diffDoc } from '../../services/api'
 import { highlightsFromDiffResponse } from '../../utils/highlights-from-diff-response'
 import { highlightsFromDiffResponse } from '../../utils/highlights-from-diff-response'
+import { useErrorHandler } from 'react-error-boundary'
 import useAsync from '../../../../shared/hooks/use-async'
 import useAsync from '../../../../shared/hooks/use-async'
 import { useTranslation } from 'react-i18next'
 import { useTranslation } from 'react-i18next'
 
 
@@ -13,6 +14,7 @@ function DiffView() {
   const { isLoading, data, runAsync } = useAsync<DocDiffResponse>()
   const { isLoading, data, runAsync } = useAsync<DocDiffResponse>()
   const { t } = useTranslation()
   const { t } = useTranslation()
   const { updateRange, selectedFile } = selection
   const { updateRange, selectedFile } = selection
+  const handleError = useErrorHandler()
 
 
   useEffect(() => {
   useEffect(() => {
     if (!updateRange || !selectedFile?.pathname || loadingFileDiffs) {
     if (!updateRange || !selectedFile?.pathname || loadingFileDiffs) {
@@ -30,9 +32,11 @@ function DiffView() {
         selectedFile.pathname,
         selectedFile.pathname,
         abortController.signal
         abortController.signal
       )
       )
-    ).finally(() => {
-      abortController = null
-    })
+    )
+      .catch(handleError)
+      .finally(() => {
+        abortController = null
+      })
 
 
     // Abort an existing request before starting a new one or on unmount
     // Abort an existing request before starting a new one or on unmount
     return () => {
     return () => {
@@ -40,7 +44,14 @@ function DiffView() {
         abortController.abort()
         abortController.abort()
       }
       }
     }
     }
-  }, [projectId, runAsync, updateRange, selectedFile, loadingFileDiffs])
+  }, [
+    projectId,
+    runAsync,
+    updateRange,
+    selectedFile,
+    loadingFileDiffs,
+    handleError,
+  ])
 
 
   const diff = useMemo(() => {
   const diff = useMemo(() => {
     let diff: Diff | null
     let diff: Diff | null

+ 6 - 2
services/web/frontend/js/features/history/context/history-context.tsx

@@ -25,6 +25,7 @@ import {
   Update,
   Update,
 } from '../services/types/update'
 } from '../services/types/update'
 import { Selection } from '../services/types/selection'
 import { Selection } from '../services/types/selection'
+import { useErrorHandler } from 'react-error-boundary'
 import { getUpdateForVersion } from '../utils/history-details'
 import { getUpdateForVersion } from '../utils/history-details'
 import { getHueForUserId } from '@/shared/utils/colors'
 import { getHueForUserId } from '@/shared/utils/colors'
 
 
@@ -98,6 +99,7 @@ function useHistory() {
   )
   )
 
 
   const updatesAbortControllerRef = useRef<AbortController | null>(null)
   const updatesAbortControllerRef = useRef<AbortController | null>(null)
+  const handleError = useErrorHandler()
 
 
   const fetchNextBatchOfUpdates = useCallback(() => {
   const fetchNextBatchOfUpdates = useCallback(() => {
     // If there is an in-flight request for updates, just let it complete, by
     // If there is an in-flight request for updates, just let it complete, by
@@ -197,10 +199,11 @@ function useHistory() {
           loadingState: 'ready',
           loadingState: 'ready',
         })
         })
       })
       })
+      .catch(handleError)
       .finally(() => {
       .finally(() => {
         updatesAbortControllerRef.current = null
         updatesAbortControllerRef.current = null
       })
       })
-  }, [updatesInfo, projectId, labels, userHasFullFeature])
+  }, [updatesInfo, projectId, labels, handleError, userHasFullFeature])
 
 
   // Abort in-flight updates request on unmount
   // Abort in-flight updates request on unmount
   useEffect(() => {
   useEffect(() => {
@@ -281,6 +284,7 @@ function useHistory() {
           }
           }
         })
         })
       })
       })
+      .catch(handleError)
       .finally(() => {
       .finally(() => {
         setLoadingFileDiffs(false)
         setLoadingFileDiffs(false)
         abortController = null
         abortController = null
@@ -291,7 +295,7 @@ function useHistory() {
         abortController.abort()
         abortController.abort()
       }
       }
     }
     }
-  }, [projectId, fromV, toV, updateForToV])
+  }, [projectId, fromV, toV, updateForToV, handleError])
 
 
   useEffect(() => {
   useEffect(() => {
     // Set update range if there isn't one and updates have loaded
     // Set update range if there isn't one and updates have loaded

+ 6 - 4
services/web/frontend/js/features/history/context/hooks/use-restore-deleted-file.ts

@@ -4,6 +4,7 @@ import { restoreFile } from '../../services/api'
 import { isFileRemoved } from '../../utils/file-diff'
 import { isFileRemoved } from '../../utils/file-diff'
 import { useHistoryContext } from '../history-context'
 import { useHistoryContext } from '../history-context'
 import type { HistoryContextValue } from '../types/history-context-value'
 import type { HistoryContextValue } from '../types/history-context-value'
+import { useErrorHandler } from 'react-error-boundary'
 import { useFileTreeData } from '@/shared/context/file-tree-data-context'
 import { useFileTreeData } from '@/shared/context/file-tree-data-context'
 import { findInTree } from '@/features/file-tree/util/find-in-tree'
 import { findInTree } from '@/features/file-tree/util/find-in-tree'
 import { useCallback, useEffect, useState } from 'react'
 import { useCallback, useEffect, useState } from 'react'
@@ -22,6 +23,7 @@ export function useRestoreDeletedFile() {
   const { projectId } = useHistoryContext()
   const { projectId } = useHistoryContext()
   const { setView } = useLayoutContext()
   const { setView } = useLayoutContext()
   const { openDocWithId, openFileWithId } = useEditorManagerContext()
   const { openDocWithId, openFileWithId } = useEditorManagerContext()
+  const handleError = useErrorHandler()
   const { fileTreeData } = useFileTreeData()
   const { fileTreeData } = useFileTreeData()
   const [state, setState] = useState<RestorationState>('idle')
   const [state, setState] = useState<RestorationState>('idle')
   const [restoredFileMetadata, setRestoredFileMetadata] =
   const [restoredFileMetadata, setRestoredFileMetadata] =
@@ -57,14 +59,14 @@ export function useRestoreDeletedFile() {
     if (state === 'waitingForFileTree') {
     if (state === 'waitingForFileTree') {
       const timer = window.setTimeout(() => {
       const timer = window.setTimeout(() => {
         setState('timedOut')
         setState('timedOut')
-        throw new Error('timed out')
+        handleError(new Error('timed out'))
       }, 3000)
       }, 3000)
 
 
       return () => {
       return () => {
         window.clearTimeout(timer)
         window.clearTimeout(timer)
       }
       }
     }
     }
-  }, [state])
+  }, [handleError, state])
 
 
   const restoreDeletedFile = useCallback(
   const restoreDeletedFile = useCallback(
     (selection: HistoryContextValue['selection']) => {
     (selection: HistoryContextValue['selection']) => {
@@ -91,13 +93,13 @@ export function useRestoreDeletedFile() {
             },
             },
             error => {
             error => {
               setState('error')
               setState('error')
-              throw error
+              handleError(error)
             }
             }
           )
           )
         }
         }
       }
       }
     },
     },
-    [projectId]
+    [handleError, projectId]
   )
   )
 
 
   return { restoreDeletedFile, isLoading }
   return { restoreDeletedFile, isLoading }

+ 4 - 2
services/web/frontend/js/features/history/context/hooks/use-restore-project.ts

@@ -1,10 +1,12 @@
 import { useCallback, useState } from 'react'
 import { useCallback, useState } from 'react'
+import { useErrorHandler } from 'react-error-boundary'
 import { restoreProjectToVersion } from '../../services/api'
 import { restoreProjectToVersion } from '../../services/api'
 import { useLayoutContext } from '@/shared/context/layout-context'
 import { useLayoutContext } from '@/shared/context/layout-context'
 
 
 type RestorationState = 'initial' | 'restoring' | 'restored' | 'error'
 type RestorationState = 'initial' | 'restoring' | 'restored' | 'error'
 
 
 export const useRestoreProject = () => {
 export const useRestoreProject = () => {
+  const handleError = useErrorHandler()
   const { setView } = useLayoutContext()
   const { setView } = useLayoutContext()
 
 
   const [restorationState, setRestorationState] =
   const [restorationState, setRestorationState] =
@@ -20,10 +22,10 @@ export const useRestoreProject = () => {
         })
         })
         .catch(err => {
         .catch(err => {
           setRestorationState('error')
           setRestorationState('error')
-          throw err
+          handleError(err)
         })
         })
     },
     },
-    [setView]
+    [handleError, setView]
   )
   )
 
 
   return {
   return {

+ 6 - 4
services/web/frontend/js/features/history/context/hooks/use-restore-selected-file.ts

@@ -3,6 +3,7 @@ import { restoreFileToVersion } from '../../services/api'
 import { isFileRemoved } from '../../utils/file-diff'
 import { isFileRemoved } from '../../utils/file-diff'
 import { useHistoryContext } from '../history-context'
 import { useHistoryContext } from '../history-context'
 import type { HistoryContextValue } from '../types/history-context-value'
 import type { HistoryContextValue } from '../types/history-context-value'
+import { useErrorHandler } from 'react-error-boundary'
 import { useFileTreeData } from '@/shared/context/file-tree-data-context'
 import { useFileTreeData } from '@/shared/context/file-tree-data-context'
 import { findInTree } from '@/features/file-tree/util/find-in-tree'
 import { findInTree } from '@/features/file-tree/util/find-in-tree'
 import { useCallback, useEffect, useState } from 'react'
 import { useCallback, useEffect, useState } from 'react'
@@ -23,6 +24,7 @@ export function useRestoreSelectedFile() {
   const { projectId } = useHistoryContext()
   const { projectId } = useHistoryContext()
   const { setView } = useLayoutContext()
   const { setView } = useLayoutContext()
   const { openDocWithId, openFileWithId } = useEditorManagerContext()
   const { openDocWithId, openFileWithId } = useEditorManagerContext()
+  const handleError = useErrorHandler()
   const { fileTreeData } = useFileTreeData()
   const { fileTreeData } = useFileTreeData()
   const [state, setState] = useState<RestoreState>('idle')
   const [state, setState] = useState<RestoreState>('idle')
   const [restoredFileMetadata, setRestoredFileMetadata] =
   const [restoredFileMetadata, setRestoredFileMetadata] =
@@ -58,14 +60,14 @@ export function useRestoreSelectedFile() {
     if (state === 'waitingForFileTree') {
     if (state === 'waitingForFileTree') {
       const timer = window.setTimeout(() => {
       const timer = window.setTimeout(() => {
         setState('timedOut')
         setState('timedOut')
-        throw new Error('timed out')
+        handleError(new Error('timed out'))
       }, RESTORE_FILE_TIMEOUT)
       }, RESTORE_FILE_TIMEOUT)
 
 
       return () => {
       return () => {
         window.clearTimeout(timer)
         window.clearTimeout(timer)
       }
       }
     }
     }
-  }, [state])
+  }, [handleError, state])
 
 
   const restoreSelectedFile = useCallback(
   const restoreSelectedFile = useCallback(
     (selection: HistoryContextValue['selection']) => {
     (selection: HistoryContextValue['selection']) => {
@@ -89,13 +91,13 @@ export function useRestoreSelectedFile() {
             },
             },
             error => {
             error => {
               setState('error')
               setState('error')
-              throw error
+              handleError(error)
             }
             }
           )
           )
         }
         }
       }
       }
     },
     },
-    [projectId]
+    [handleError, projectId]
   )
   )
 
 
   return { restoreSelectedFile, isLoading }
   return { restoreSelectedFile, isLoading }

+ 5 - 1
services/web/frontend/js/features/source-editor/hooks/use-codemirror-scope.ts

@@ -33,6 +33,7 @@ import { setSpellCheckLanguage } from '../extensions/spelling'
 import { setKeybindings } from '../extensions/keybindings'
 import { setKeybindings } from '../extensions/keybindings'
 import { Highlight } from '../../../../../types/highlight'
 import { Highlight } from '../../../../../types/highlight'
 import { EditorView } from '@codemirror/view'
 import { EditorView } from '@codemirror/view'
+import { useErrorHandler } from 'react-error-boundary'
 import { setVisual } from '../extensions/visual/visual'
 import { setVisual } from '../extensions/visual/visual'
 import { useFileTreePathContext } from '@/features/file-tree/contexts/file-tree-path'
 import { useFileTreePathContext } from '@/features/file-tree/contexts/file-tree-path'
 import { useUserSettingsContext } from '@/shared/context/user-settings-context'
 import { useUserSettingsContext } from '@/shared/context/user-settings-context'
@@ -264,6 +265,8 @@ function useCodeMirrorScope(view: EditorView) {
     visual: showVisual,
     visual: showVisual,
   })
   })
 
 
+  const handleError = useErrorHandler()
+
   const handleException = useCallback((exception: any) => {
   const handleException = useCallback((exception: any) => {
     captureException(exception, {
     captureException(exception, {
       tags: {
       tags: {
@@ -301,6 +304,7 @@ function useCodeMirrorScope(view: EditorView) {
           spelling: spellingRef.current,
           spelling: spellingRef.current,
           visual: visualRef.current,
           visual: visualRef.current,
           projectFeatures: projectFeaturesRef.current,
           projectFeatures: projectFeaturesRef.current,
+          handleError,
           handleException,
           handleException,
         }),
         }),
       })
       })
@@ -331,7 +335,7 @@ function useCodeMirrorScope(view: EditorView) {
     }
     }
     // IMPORTANT: This effect must not depend on anything variable apart from currentDocument,
     // IMPORTANT: This effect must not depend on anything variable apart from currentDocument,
     // as the editor state is recreated when the effect runs.
     // as the editor state is recreated when the effect runs.
-  }, [view, currentDocument, handleException])
+  }, [view, currentDocument, handleError, handleException])
 
 
   useEffect(() => {
   useEffect(() => {
     if (openDocName) {
     if (openDocName) {

+ 1 - 1
services/web/package.json

@@ -333,7 +333,7 @@
     "react-dnd": "^16.0.1",
     "react-dnd": "^16.0.1",
     "react-dnd-html5-backend": "^16.0.1",
     "react-dnd-html5-backend": "^16.0.1",
     "react-dom": "^17.0.2",
     "react-dom": "^17.0.2",
-    "react-error-boundary": "^5.0.0",
+    "react-error-boundary": "^2.3.1",
     "react-google-recaptcha": "^3.1.0",
     "react-google-recaptcha": "^3.1.0",
     "react-i18next": "^13.3.1",
     "react-i18next": "^13.3.1",
     "react-linkify": "^1.0.0-alpha",
     "react-linkify": "^1.0.0-alpha",