mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-14 20:40:17 -05:00
Avoid calling destroy on the PDF.js loading task (#21277)
GitOrigin-RevId: b315e78ff739d301583f2139109f3244abceade8
This commit is contained in:
parent
aa0fe5aeb3
commit
5ec52e2e5b
3 changed files with 48 additions and 78 deletions
|
@ -1,7 +1,6 @@
|
|||
import { FC, useCallback } from 'react'
|
||||
import useIsMounted from '@/shared/hooks/use-is-mounted'
|
||||
import { useFileTreePathContext } from '@/features/file-tree/contexts/file-tree-path'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
|
||||
const FileViewPdf: FC<{
|
||||
fileId: string
|
||||
|
@ -21,7 +20,6 @@ const FileViewPdf: FC<{
|
|||
|
||||
// bail out if loading PDF.js took too long
|
||||
if (!mountedRef.current) {
|
||||
onError()
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -37,7 +35,6 @@ const FileViewPdf: FC<{
|
|||
|
||||
// bail out if loading the PDF took too long
|
||||
if (!mountedRef.current) {
|
||||
onError()
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -47,6 +44,12 @@ const FileViewPdf: FC<{
|
|||
|
||||
for (let i = 1; i <= pdf.numPages; i++) {
|
||||
const page = await pdf.getPage(i)
|
||||
|
||||
// bail out if the component has been unmounted
|
||||
if (!mountedRef.current) {
|
||||
return
|
||||
}
|
||||
|
||||
const viewport = page.getViewport({ scale })
|
||||
|
||||
const canvas = document.createElement('canvas')
|
||||
|
@ -64,11 +67,6 @@ const FileViewPdf: FC<{
|
|||
}
|
||||
|
||||
onLoad()
|
||||
|
||||
return () => {
|
||||
pdf.cleanup().catch(debugConsole.error)
|
||||
pdf.destroy()
|
||||
}
|
||||
}
|
||||
},
|
||||
[mountedRef, pathInFolder, fileId, previewByPath, onLoad, onError]
|
||||
|
|
|
@ -64,24 +64,23 @@ function PdfJsViewer({ url, pdfFile }: PdfJsViewerProps) {
|
|||
const handleContainer = useCallback(
|
||||
parent => {
|
||||
if (parent) {
|
||||
let wrapper: PDFJSWrapper | undefined
|
||||
try {
|
||||
wrapper = new PDFJSWrapper(parent.firstChild)
|
||||
setPdfJsWrapper(wrapper)
|
||||
setPdfJsWrapper(new PDFJSWrapper(parent.firstChild))
|
||||
} catch (error: any) {
|
||||
setLoadingError(true)
|
||||
captureException(error)
|
||||
}
|
||||
|
||||
return () => {
|
||||
setPdfJsWrapper(null)
|
||||
wrapper?.destroy().catch(debugConsole.error)
|
||||
}
|
||||
}
|
||||
},
|
||||
[setLoadingError]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
setPdfJsWrapper(null)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const [startFetch, setStartFetch] = useState(0)
|
||||
|
||||
// listen for events and trigger rendering.
|
||||
|
@ -181,7 +180,9 @@ function PdfJsViewer({ url, pdfFile }: PdfJsViewerProps) {
|
|||
pdfJsWrapper
|
||||
.loadDocument({ url, pdfFile, abortController, handleFetchError })
|
||||
.then(doc => {
|
||||
setTotalPages(doc.numPages)
|
||||
if (doc) {
|
||||
setTotalPages(doc.numPages)
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
if (abortController.signal.aborted) return
|
||||
|
@ -190,7 +191,6 @@ function PdfJsViewer({ url, pdfFile }: PdfJsViewerProps) {
|
|||
})
|
||||
return () => {
|
||||
abortController.abort()
|
||||
pdfJsWrapper.abortDocumentLoading()
|
||||
}
|
||||
}
|
||||
}, [pdfJsWrapper, url, pdfFile, setError, setStartFetch])
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { captureException } from '@/infrastructure/error-reporter'
|
||||
import { generatePdfCachingTransportFactory } from './pdf-caching-transport'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
import { PDFJS, loadPdfDocumentFromUrl, imageResourcesPath } from './pdf-js'
|
||||
import {
|
||||
PDFViewer,
|
||||
|
@ -13,12 +12,11 @@ import 'pdfjs-dist/web/pdf_viewer.css'
|
|||
const DEFAULT_RANGE_CHUNK_SIZE = 128 * 1024 // 128K chunks
|
||||
|
||||
export default class PDFJSWrapper {
|
||||
private loadDocumentTask: PDFJS.PDFDocumentLoadingTask | undefined
|
||||
|
||||
public readonly viewer: PDFViewer
|
||||
public readonly eventBus: EventBus
|
||||
private readonly linkService: PDFLinkService
|
||||
private readonly pdfCachingTransportFactory: any
|
||||
private url?: string
|
||||
|
||||
// eslint-disable-next-line no-useless-constructor
|
||||
constructor(public container: HTMLDivElement) {
|
||||
|
@ -49,7 +47,7 @@ export default class PDFJSWrapper {
|
|||
}
|
||||
|
||||
// load a document from a URL
|
||||
loadDocument({
|
||||
async loadDocument({
|
||||
url,
|
||||
pdfFile,
|
||||
abortController,
|
||||
|
@ -60,61 +58,45 @@ export default class PDFJSWrapper {
|
|||
abortController: AbortController
|
||||
handleFetchError: (error: Error) => void
|
||||
}) {
|
||||
// cancel any previous loading task
|
||||
if (this.loadDocumentTask) {
|
||||
this.loadDocumentTask.destroy().catch(debugConsole.error)
|
||||
this.loadDocumentTask = undefined
|
||||
this.url = url
|
||||
|
||||
const rangeTransport = this.pdfCachingTransportFactory({
|
||||
url,
|
||||
pdfFile,
|
||||
abortController,
|
||||
handleFetchError,
|
||||
})
|
||||
let rangeChunkSize = DEFAULT_RANGE_CHUNK_SIZE
|
||||
if (rangeTransport && pdfFile.size < 2 * DEFAULT_RANGE_CHUNK_SIZE) {
|
||||
// pdf.js disables the "bulk" download optimization when providing a
|
||||
// custom range transport. Restore it by bumping the chunk size.
|
||||
rangeChunkSize = pdfFile.size
|
||||
}
|
||||
|
||||
return new Promise<PDFJS.PDFDocumentProxy>((resolve, reject) => {
|
||||
const rangeTransport = this.pdfCachingTransportFactory({
|
||||
url,
|
||||
pdfFile,
|
||||
abortController,
|
||||
handleFetchError,
|
||||
})
|
||||
let rangeChunkSize = DEFAULT_RANGE_CHUNK_SIZE
|
||||
if (rangeTransport && pdfFile.size < 2 * DEFAULT_RANGE_CHUNK_SIZE) {
|
||||
// pdf.js disables the "bulk" download optimization when providing a
|
||||
// custom range transport. Restore it by bumping the chunk size.
|
||||
rangeChunkSize = pdfFile.size
|
||||
}
|
||||
this.loadDocumentTask = loadPdfDocumentFromUrl(url, {
|
||||
try {
|
||||
const doc = await loadPdfDocumentFromUrl(url, {
|
||||
rangeChunkSize,
|
||||
range: rangeTransport,
|
||||
})
|
||||
}).promise
|
||||
|
||||
this.loadDocumentTask.promise
|
||||
.then(doc => {
|
||||
if (!this.loadDocumentTask || !this.viewer) {
|
||||
return // ignoring the response since loading task has been aborted
|
||||
}
|
||||
// check that this is still the current URL
|
||||
if (url !== this.url) {
|
||||
return
|
||||
}
|
||||
|
||||
const previousDoc = this.viewer.pdfDocument
|
||||
this.viewer.setDocument(doc)
|
||||
this.linkService.setDocument(doc)
|
||||
resolve(doc)
|
||||
this.viewer.setDocument(doc)
|
||||
this.linkService.setDocument(doc)
|
||||
|
||||
if (previousDoc) {
|
||||
previousDoc.cleanup().catch(debugConsole.error)
|
||||
previousDoc.destroy().catch(debugConsole.error)
|
||||
}
|
||||
return doc
|
||||
} catch (error: any) {
|
||||
if (!error || error.name !== 'MissingPDFException') {
|
||||
captureException(error, {
|
||||
tags: { handler: 'pdf-preview' },
|
||||
})
|
||||
.catch(error => {
|
||||
if (this.loadDocumentTask) {
|
||||
if (!error || error.name !== 'MissingPDFException') {
|
||||
captureException(error, {
|
||||
tags: { handler: 'pdf-preview' },
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
reject(error)
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.loadDocumentTask = undefined
|
||||
})
|
||||
})
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// update the current scale value if the container size changes
|
||||
|
@ -216,14 +198,4 @@ export default class PDFJSWrapper {
|
|||
isVisible() {
|
||||
return this.viewer.container.offsetParent !== null
|
||||
}
|
||||
|
||||
abortDocumentLoading() {
|
||||
this.loadDocumentTask = undefined
|
||||
}
|
||||
|
||||
async destroy() {
|
||||
await this.loadDocumentTask?.destroy().catch(debugConsole.error)
|
||||
this.loadDocumentTask = undefined
|
||||
await this.viewer.pdfDocument?.destroy().catch(debugConsole.error)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue